diff --git a/docs/en/install/README.md b/docs/en/install/README.md
index 460be758e..b61260062 100644
--- a/docs/en/install/README.md
+++ b/docs/en/install/README.md
@@ -104,6 +104,35 @@ $ docker run -d --name rsshub -p 1200:1200 -e CACHE_EXPIRE=3600 -e GITHUB_ACCESS
To configure more options please refer to [Configuration](#configuration).
+# Ansible Deployment
+
+This Ansible playbook includes RSSHub, Redis, browserless (uses Docker) and Caddy 2
+
+Currently only support Ubuntu 20.04
+
+Requires sudo privilege and virtualization capability (Docker will be automatically installed)
+
+### Install
+
+```bash
+sudo apt update
+sudo apt install ansible
+git clone https://github.com/DIYgod/RSSHub.git ~/RSSHub
+cd ~/RSSHub/scripts/ansible
+sudo ansible-playbook rsshub.yaml
+# When prompt to enter a domain name, enter the domain name that this machine/VM will use
+# For example, if your users use https://rsshub.exmaple.com to access your RSSHub instance, enter rsshub.exmaple.com (remove the https://)
+```
+
+### Update
+
+```bash
+cd ~/RSSHub/scripts/ansible
+sudo ansible-playbook rsshub.yaml
+# When prompt to enter a domain name, enter the domain name that this machine/VM will use
+# For example, if your users use https://rsshub.exmaple.com to access your RSSHub instance, enter rsshub.exmaple.com (remove the https://)
+```
+
## Manual Deployment
The most direct way to deploy `RSSHub`, you can follow the steps below to deploy`RSSHub` on your computer, server or anywhere.
diff --git a/docs/en/new-media.md b/docs/en/new-media.md
index 070815cbe..d0b372cc8 100644
--- a/docs/en/new-media.md
+++ b/docs/en/new-media.md
@@ -67,6 +67,10 @@ Compared to the official one, the RSS feed generated by RSSHub not only has more
## CGTN
+### Opinions
+
+
+
### Most Read & Most Share
diff --git a/docs/en/program-update.md b/docs/en/program-update.md
index 9325fd5e2..13b702821 100644
--- a/docs/en/program-update.md
+++ b/docs/en/program-update.md
@@ -164,6 +164,12 @@ The owner of the official image fills in the library, for example: https://rsshu
+## Microsoft Store
+
+### Updates
+
+
+
## Minecraft
Refer to [#minecraft](/en/game.html#minecraft)
diff --git a/docs/en/traditional-media.md b/docs/en/traditional-media.md
index 983211fe8..4f942f500 100644
--- a/docs/en/traditional-media.md
+++ b/docs/en/traditional-media.md
@@ -149,6 +149,18 @@ Generates full-text feeds that the official feed doesn't provide.
+## Radio Free Asia (RFA)
+
+
+
+Delivers a better experience by supporting parameter specification.
+
+Parameters can be obtained from the official website, for instance:
+
+`https://www.rfa.org/cantonese/news` corresponds to `/rfa/cantonese/news`
+
+`https://www.rfa.org/cantonese/news/htm` corresponds to `/rfa/cantonese/news/htm`
+
## Reuters
### Channel
diff --git a/docs/install/README.md b/docs/install/README.md
index a98da79d6..a8c59fa91 100644
--- a/docs/install/README.md
+++ b/docs/install/README.md
@@ -106,6 +106,35 @@ $ docker run -d --name rsshub -p 1200:1200 -e CACHE_EXPIRE=3600 -e GITHUB_ACCESS
更多配置项请看 [#配置](#pei-zhi)
+## Ansible 部署
+
+这个 Ansible playbook 包括了 RSSHub, Redis, browserless (依赖 Docker) 以及 Caddy 2
+
+目前只支持 Ubuntu 20.04
+
+需要 sudo 权限和虚拟化能力(Docker 将会被自动安装)
+
+### 安装
+
+```bash
+sudo apt update
+sudo apt install ansible
+git clone https://github.com/DIYgod/RSSHub.git ~/RSSHub
+cd ~/RSSHub/scripts/ansible
+sudo ansible-playbook rsshub.yaml
+# 当提示输入 domain name 的时候,输入该主机所使用的域名
+# 举例:如果您的 RSSHub 用户使用 https://rsshub.exmaple.com 访问您的 RSSHub 实例,输入 rsshub.exmaple.com(去掉 https://)
+```
+
+### 更新
+
+```bash
+cd ~/RSSHub/scripts/ansible
+sudo ansible-playbook rsshub.yaml
+# 当提示输入 domain name 的时候,输入该主机所使用的域名
+# 举例:如果您的 RSSHub 用户使用 https://rsshub.exmaple.com 访问您的 RSSHub 实例,输入 rsshub.exmaple.com(去掉 https://)
+```
+
## 手动部署
部署 `RSSHub` 最直接的方式,您可以按照以下步骤将 `RSSHub` 部署在您的电脑、服务器或者其他任何地方
@@ -619,3 +648,8 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- `DIDA365_USERNAME`: 滴答清单用户名
- `DIDA365_PASSWORD`: 滴答清单密码
+
+- 知乎用户关注时间线
+
+ - `ZHIHU_COOKIES`: 知乎登录后的 cookie 值.
+ 1. 可以在知乎网页版的一些请求的请求头中找到,如 `GET /moments` 请求头中的 `cookie` 值.
diff --git a/docs/new-media.md b/docs/new-media.md
index dea896d57..ebc5e352c 100644
--- a/docs/new-media.md
+++ b/docs/new-media.md
@@ -122,6 +122,10 @@ pageClass: routes
## CGTN
+### Opinions
+
+
+
### Most Read & Most Share
diff --git a/docs/program-update.md b/docs/program-update.md
index b12003588..5eb9cf3bd 100644
--- a/docs/program-update.md
+++ b/docs/program-update.md
@@ -212,6 +212,12 @@ pageClass: routes
+## Microsoft Store
+
+### Updates
+
+
+
## Minecraft
见 [#minecraft](/game.html#minecraft)
diff --git a/docs/social-media.md b/docs/social-media.md
index e18c2d30d..d4ff76d2d 100644
--- a/docs/social-media.md
+++ b/docs/social-media.md
@@ -1141,3 +1141,12 @@ rule
### 知乎书店 - 知乎周刊
+
+### 用户关注时间线
+
+
+::: warning 注意
+
+用户关注动态需要登录后的 Cookie 值,所以只能自建,详情见部署页面的配置模块。
+
+:::
diff --git a/docs/traditional-media.md b/docs/traditional-media.md
index 94db156ae..6281d1bee 100644
--- a/docs/traditional-media.md
+++ b/docs/traditional-media.md
@@ -965,3 +965,15 @@ category 对应的关键词有
### 九江新闻
+
+## 自由亚洲电台
+
+
+
+通过指定频道参数,提供比官方源更佳的阅读体验。
+
+参数均可在官网获取,如:
+
+`https://www.rfa.org/cantonese/news` 对应 `/rfa/cantonese/news`
+
+`https://www.rfa.org/cantonese/news/htm` 对应 `/rfa/cantonese/news/htm`
diff --git a/lib/config.js b/lib/config.js
index 83112c8e7..5e81e3e9e 100644
--- a/lib/config.js
+++ b/lib/config.js
@@ -89,6 +89,9 @@ const calculateValue = () => {
yuque: {
token: envs.YUQUE_TOKEN,
},
+ zhihu: {
+ cookies: envs.ZHIHU_COOKIES,
+ },
puppeteerWSEndpoint: envs.PUPPETEER_WS_ENDPOINT,
loggerLevel: envs.LOGGER_LEVEL || 'info',
proxyUri: envs.PROXY_URI,
diff --git a/lib/router.js b/lib/router.js
index caf0600ea..0ead4eb01 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -158,6 +158,7 @@ router.get('/zhihu/people/pins/:id', require('./routes/zhihu/pin/people'));
router.get('/zhihu/bookstore/newest', require('./routes/zhihu/bookstore/newest'));
router.get('/zhihu/pin/daily', require('./routes/zhihu/pin/daily'));
router.get('/zhihu/weekly', require('./routes/zhihu/weekly'));
+router.get('/zhihu/timeline', require('./routes/zhihu/timeline'));
// 妹子图
router.get('/mzitu/home/:type?', require('./routes/mzitu/home'));
@@ -2852,6 +2853,9 @@ router.get('/xposed/module/:mod', require('./routes/xposed/module'));
// Microsoft Edge
router.get('/edge/addon/:crxid', require('./routes/edge/addon'));
+// Microsoft Store
+router.get('/microsoft-store/updates/:productid/:market?', require('./routes/microsoft-store/updates'));
+
// 上海立信会计金融学院
router.get('/slu/tzgg/:id', require('./routes/universities/slu/tzgg'));
router.get('/slu/jwc/:id', require('./routes/universities/slu/jwc'));
@@ -3338,6 +3342,7 @@ router.get('/fulinian/:caty?', require('./routes/fulinian/index'));
// CGTN
router.get('/cgtn/most/:type?/:time?', require('./routes/cgtn/most'));
+router.get('/cgtn/opinions', require('./routes/cgtn/opinions'));
// AppSales
router.get('/appsales/:caty?/:time?', require('./routes/appsales/index'));
@@ -3782,8 +3787,10 @@ router.get('/caixin/latest', require('./routes/caixin/latest'));
// SimpRead-消息通知
router.get('/simpread/notice', require('./routes/simpread/notice'));
-
// SimpRead-更新日志
router.get('/simpread/changelog', require('./routes/simpread/changelog'));
+// Radio Free Asia
+router.get('/rfa/:language?/:channel?/:subChannel?', require('./routes/rfa/index'));
+
module.exports = router;
diff --git a/lib/routes/caixin/article.js b/lib/routes/caixin/article.js
index 29fd6d70a..6874fe8aa 100644
--- a/lib/routes/caixin/article.js
+++ b/lib/routes/caixin/article.js
@@ -1,4 +1,5 @@
const got = require('@/utils/got');
+const cheerio = require('cheerio');
module.exports = async (ctx) => {
const response = await got({
@@ -12,15 +13,33 @@ module.exports = async (ctx) => {
const data = response.data.data.list;
+ const items = await Promise.all(
+ data.map(async (item) => {
+ const link = item.web_url;
+ const summary = `
${item.summary}
`;
+
+ const fullText = await ctx.cache.tryGet(link, async () => {
+ const result = await got.get(link);
+
+ const $ = cheerio.load(result.data);
+
+ return $('#Main_Content_Val').html();
+ });
+
+ return {
+ title: item.title,
+ description: fullText ? summary + fullText : summary,
+ link: link,
+ pubDate: new Date(item.time * 1000),
+ author: item.author_name,
+ };
+ })
+ );
+
ctx.state.data = {
title: `财新网 - 首页`,
link: `http://www.caixin.com/`,
description: '财新网 - 首页',
- item: data.map((item) => ({
- title: item.title,
- description: `${item.summary}
`,
- link: item.web_url,
- pubDate: new Date(item.time * 1000),
- })),
+ item: items,
};
};
diff --git a/lib/routes/cgtn/opinions.js b/lib/routes/cgtn/opinions.js
new file mode 100644
index 000000000..c10c3216c
--- /dev/null
+++ b/lib/routes/cgtn/opinions.js
@@ -0,0 +1,51 @@
+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(parseInt(a.attr('data-time'))).toUTCString(),
+ };
+ })
+ .get();
+
+ const items = await Promise.all(
+ list.map(
+ async (item) =>
+ await 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,
+ };
+};
diff --git a/lib/routes/douban/later.js b/lib/routes/douban/later.js
index bf6a69ee0..8d9b784dd 100644
--- a/lib/routes/douban/later.js
+++ b/lib/routes/douban/later.js
@@ -1,19 +1,32 @@
const got = require('@/utils/got');
+const cheerio = require('cheerio');
module.exports = async (ctx) => {
const response = await got({
method: 'get',
- url: 'https://api.douban.com/v2/movie/coming_soon?apikey=0df993c66c0c636e29ecbb5344252a4a',
+ url: 'https://movie.douban.com/cinema/later/beijing/',
});
- const movieList = response.data.subjects;
+ const $ = cheerio.load(response.data);
+
+ const item = $('#showing-soon .item')
+ .map((index, ele) => {
+ const description = $(ele).html();
+ const name = $('h3', ele).text().trim();
+ const date = $('ul li', ele).eq(0).text().trim();
+ const type = $('ul li', ele).eq(1).text().trim();
+ const link = $('a.thumb', ele).attr('href');
+
+ return {
+ title: `${date} - 《${name}》 - ${type}`,
+ link,
+ description,
+ };
+ })
+ .get();
ctx.state.data = {
title: '即将上映的电影',
link: 'https://movie.douban.com/cinema/later/',
- item: movieList.map((item) => ({
- title: item.title,
- description: `标题:${item.title}
影片类型:${item.genres.join(' | ')}
评分:${item.rating.stars === '00' ? '无' : item.rating.average}
`,
- link: item.alt,
- })),
+ item,
};
};
diff --git a/lib/routes/microsoft-store/updates.js b/lib/routes/microsoft-store/updates.js
new file mode 100644
index 000000000..4c5f63f62
--- /dev/null
+++ b/lib/routes/microsoft-store/updates.js
@@ -0,0 +1,32 @@
+const got = require('@/utils/got');
+
+module.exports = async (ctx) => {
+ const { market = 'CN', productid } = ctx.params;
+
+ const { data } = await got({
+ method: 'get',
+ url: `https://displaycatalog.mp.microsoft.com/v7.0/products/${productid}/?fieldsTemplate=&market=${market}&languages=en`,
+ headers: {
+ 'Content-Type': 'application/json',
+ 'MS-CV': `${Array(16)
+ .join()
+ .split(',')
+ .map(function () {
+ return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.charAt(Math.floor(Math.random() * 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.length));
+ })
+ .join('')}.1`,
+ },
+ });
+
+ ctx.state.data = {
+ title: `${data.Product.LocalizedProperties[0].ProductTitle} - Microsoft Store Updates`,
+ link: `https://www.microsoft.com/store/productId/${productid}`,
+ item: [
+ {
+ title: data.Product.DisplaySkuAvailabilities[0].Sku.Properties.Packages[0].PackageFullName,
+ pubDate: new Date(data.Product.DisplaySkuAvailabilities[0].Sku.LastModifiedDate),
+ link: `https://www.microsoft.com/store/productId/${productid}`,
+ },
+ ],
+ };
+};
diff --git a/lib/routes/rfa/index.js b/lib/routes/rfa/index.js
new file mode 100644
index 000000000..90791eb2f
--- /dev/null
+++ b/lib/routes/rfa/index.js
@@ -0,0 +1,47 @@
+const cheerio = require('cheerio');
+const got = require('@/utils/got');
+
+module.exports = async (ctx) => {
+ let url = 'https://www.rfa.org/' + (ctx.params.language || 'english');
+
+ if (ctx.params.channel) {
+ url += '/' + ctx.params.channel;
+ }
+ if (ctx.params.subChannel) {
+ url += '/' + ctx.params.subChannel;
+ }
+
+ const response = await got.get(url);
+ const $ = cheerio.load(response.data);
+
+ const selectors = ['div[id=topstorywidefulltease]', 'div.two_featured', 'div.three_featured', 'div.single_column_teaser', 'div.sectionteaser', 'div.specialwrap'];
+ const list = [];
+ selectors.forEach(function (selector) {
+ $(selector).each(function (_, e) {
+ const item = {};
+ item.title = $(e).find('h2 a span').first().text();
+ item.link = $(e).find('h2 a').first().attr('href');
+ list.push(item);
+ });
+ });
+
+ const result = await Promise.all(
+ list.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const content = await got.get(item.link);
+
+ const description = cheerio.load(content.data);
+ item.description = description('div[id=storytext]').html();
+ item.pubDate = new Date(description('span[id=story_date]').text()).toUTCString();
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: 'RFA',
+ link: 'https://www.rfa.org/',
+ item: result,
+ };
+};
diff --git a/lib/routes/zhihu/timeline.js b/lib/routes/zhihu/timeline.js
new file mode 100644
index 000000000..568c30a0e
--- /dev/null
+++ b/lib/routes/zhihu/timeline.js
@@ -0,0 +1,33 @@
+const got = require('@/utils/got');
+const config = require('@/config').value;
+
+module.exports = async (ctx) => {
+ const cookie = config.zhihu.cookies;
+ if (cookie === undefined) {
+ throw Error('缺少知乎用户登录后的 Cookie 值');
+ }
+
+ const response = await got({
+ method: 'get',
+ url: `https://www.zhihu.com/api/v3/moments?limit=10`,
+ headers: {
+ Cookie: cookie,
+ },
+ });
+ const feeds = response.data.data;
+
+ const out = feeds.map((e) => ({
+ title: `${e.action_text}: ${e.target.title ? e.target.title : e.target.question.title}`,
+ description: `${e.target.excerpt}`,
+ pubDate: new Date(e.updated_time * 1000),
+ link: e.target.url.replace('api.zhihu.com', 'zhihu.com'),
+ author: e.target.author.name,
+ guid: e.id,
+ }));
+
+ ctx.state.data = {
+ title: `知乎关注动态`,
+ link: `https://www.zhihu.com/follow`,
+ item: out,
+ };
+};
diff --git a/package.json b/package.json
index 0ac56cc3e..e762c5ede 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,7 @@
"jest": "26.6.3",
"mockdate": "3.0.2",
"nock": "13.0.5",
- "nodemon": "2.0.6",
+ "nodemon": "2.0.7",
"pinyin": "2.9.1",
"prettier": "2.2.1",
"prettier-check": "2.0.0",
@@ -75,14 +75,14 @@
"co-redis": "2.1.1",
"crypto-js": "4.0.0",
"currency-symbol-map": "4.0.4",
- "dayjs": "1.10.2",
+ "dayjs": "1.10.3",
"dotenv": "8.2.0",
"emailjs-imap-client": "3.1.0",
"entities": "2.1.0",
"etag": "1.8.1",
"fanfou-sdk": "4.2.0",
"git-rev-sync": "3.0.1",
- "googleapis": "66.0.0",
+ "googleapis": "67.0.0",
"got": "11.8.1",
"https-proxy-agent": "5.0.0",
"iconv-lite": "0.6.2",
diff --git a/scripts/ansible/.gitignore b/scripts/ansible/.gitignore
new file mode 100644
index 000000000..6117c5218
--- /dev/null
+++ b/scripts/ansible/.gitignore
@@ -0,0 +1,90 @@
+# Created by https://www.toptal.com/developers/gitignore/api/windows,linux,macos,ansible,vagrant
+# Edit at https://www.toptal.com/developers/gitignore?templates=windows,linux,macos,ansible,vagrant
+
+### Ansible ###
+*.retry
+
+### Linux ###
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+### macOS ###
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### Vagrant ###
+# General
+.vagrant/
+
+# Log files (if you are creating logs in debug mode, uncomment this)
+# *.log
+
+### Vagrant Patch ###
+*.box
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# End of https://www.toptal.com/developers/gitignore/api/windows,linux,macos,ansible,vagrant
+
+# vagrant logs
+*.log
\ No newline at end of file
diff --git a/scripts/ansible/README.md b/scripts/ansible/README.md
new file mode 100644
index 000000000..50cae9b71
--- /dev/null
+++ b/scripts/ansible/README.md
@@ -0,0 +1,20 @@
+# Readme
+
+Ansible playbook to deploy [RSSHub](https://github.com/DIYgod/RSSHub) on bare-metal with Redis, browserless and Caddy 2
+
+Requires sudo permission
+
+## Usage
+On `Ubuntu 20.04`, [install ansible](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-ansible-on-ubuntu-20-04), then
+
+```bash
+sudo ansible-playbook rsshub.yaml
+```
+
+## Development
+Install `vagrant`, then
+
+```bash
+./try.sh
+ansible-playbook rsshub.yaml
+```
diff --git a/scripts/ansible/Vagrantfile b/scripts/ansible/Vagrantfile
new file mode 100644
index 000000000..604af7f5a
--- /dev/null
+++ b/scripts/ansible/Vagrantfile
@@ -0,0 +1,5 @@
+Vagrant.configure("2") do |config|
+ config.vm.box = "generic/ubuntu2004"
+ config.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: ".git/"
+ config.ssh.extra_args = ["-t", "cd /vagrant; bash --login"]
+end
diff --git a/scripts/ansible/rsshub.Caddyfile b/scripts/ansible/rsshub.Caddyfile
new file mode 100644
index 000000000..7781eb24f
--- /dev/null
+++ b/scripts/ansible/rsshub.Caddyfile
@@ -0,0 +1,3 @@
+{{ domain_name }}
+
+reverse_proxy localhost:1200
diff --git a/scripts/ansible/rsshub.env b/scripts/ansible/rsshub.env
new file mode 100644
index 000000000..d4a283725
--- /dev/null
+++ b/scripts/ansible/rsshub.env
@@ -0,0 +1,3 @@
+NODE_ENV=production
+CACHE_TYPE=redis
+PUPPETEER_WS_ENDPOINT=ws://localhost:3000
diff --git a/scripts/ansible/rsshub.service b/scripts/ansible/rsshub.service
new file mode 100644
index 000000000..0c8352a44
--- /dev/null
+++ b/scripts/ansible/rsshub.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=RSSHub is an open source, easy to use, and extensible RSS feed aggregator
+
+[Service]
+User=rsshub
+WorkingDirectory=/home/rsshub/app
+ExecStart=yarn start
+EnvironmentFile=/home/rsshub/app/.env
+
+[Install]
+WantedBy=multi-user.target
diff --git a/scripts/ansible/rsshub.yaml b/scripts/ansible/rsshub.yaml
new file mode 100644
index 000000000..33671a51c
--- /dev/null
+++ b/scripts/ansible/rsshub.yaml
@@ -0,0 +1,130 @@
+-
+ name: Install RSSHub
+ hosts: localhost
+ become: true
+ vars_prompt:
+ -
+ name: domain_name
+ prompt: What is the domain name (without www, e.g. rsshub.example.com)? Use "http://localhost" for development in Vagrant VM.
+ private: no
+ tasks:
+ -
+ name: Check OS
+ fail:
+ msg: This playbook can only be run on Ubuntu 20.04 at this moment
+ when: ansible_distribution != 'Ubuntu' or ansible_distribution_version !='20.04'
+ -
+ name: Install GPG keys for repos
+ apt_key:
+ url: '{{ item }}'
+ state: present
+ with_items:
+ - https://deb.nodesource.com/gpgkey/nodesource.gpg.key
+ - https://dl.yarnpkg.com/debian/pubkey.gpg
+ - https://download.docker.com/linux/ubuntu/gpg
+ - https://dl.cloudsmith.io/public/caddy/stable/cfg/gpg/gpg.155B6D79CA56EA34.key
+ -
+ name: Install repos
+ apt_repository:
+ repo: '{{ item }}'
+ state: present
+ update_cache: yes
+ with_items:
+ - deb https://deb.nodesource.com/node_12.x focal main
+ - deb https://dl.yarnpkg.com/debian/ stable main
+ - deb https://download.docker.com/linux/ubuntu focal stable
+ - deb https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main
+ -
+ name: Install prerequisites
+ apt:
+ name:
+ - nodejs
+ - yarn
+ - build-essential
+ - python-is-python2
+ - redis-server
+ - docker-ce
+ - python3-pip
+ - virtualenv
+ - python3-setuptools
+ - caddy
+ state: present
+ update_cache: yes
+ -
+ name: Install python module for docker
+ pip:
+ name: docker
+ -
+ name: Pull docker image for browserless
+ docker_image:
+ name: browserless/chrome
+ source: pull
+ -
+ name: Start redis
+ systemd:
+ state: restarted
+ enabled: yes
+ name: redis
+ daemon_reload: yes
+ -
+ name: Copy caddy configuration
+ template:
+ src: rsshub.Caddyfile
+ dest: /etc/caddy/Caddyfile
+ -
+ name: Start caddy
+ systemd:
+ state: restarted
+ enabled: yes
+ name: caddy
+ daemon_reload: yes
+ -
+ name: Create and start browserless container
+ docker_container:
+ name: browserless
+ image: browserless/chrome
+ state: started
+ restart_policy: always
+ published_ports:
+ - "3000:3000"
+ -
+ name: Create the user
+ user:
+ name: rsshub
+ create_home: true
+ shell: /bin/bash
+ -
+ name: Clone the repo
+ git:
+ repo: https://github.com/DIYgod/RSSHub.git
+ dest: /home/rsshub/app
+ update: yes
+ -
+ name: Install repo dependencies
+ command: yarn install --production
+ args:
+ chdir: /home/rsshub/app
+ -
+ name: Copy configuration
+ copy:
+ src: rsshub.env
+ dest: /home/rsshub/app/.env
+ -
+ name: Own repo to the user
+ file:
+ path: /home/rsshub/app
+ owner: rsshub
+ group: rsshub
+ recurse: yes
+ -
+ name: Install the systemd unit
+ copy:
+ src: rsshub.service
+ dest: /etc/systemd/system/rsshub.service
+ -
+ name: Start the systemd service
+ systemd:
+ state: restarted
+ enabled: yes
+ name: rsshub
+ daemon_reload: yes
diff --git a/scripts/ansible/try.sh b/scripts/ansible/try.sh
new file mode 100755
index 000000000..cd8f1df76
--- /dev/null
+++ b/scripts/ansible/try.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -e
+
+vagrant rsync
+vagrant ssh
diff --git a/yarn.lock b/yarn.lock
index 512f41889..b6ed190df 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4304,10 +4304,10 @@ date-now@^0.1.4:
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=
-dayjs@1.10.2, dayjs@^1.8.29:
- version "1.10.2"
- resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.2.tgz#8f3a424ceb944a8193506804b0045a773d2d0672"
- integrity sha512-h/YtykNNTR8Qgtd1Fxl5J1/SFP1b7SOk/M1P+Re+bCdFMV0IMkuKNgHPN7rlvvuhfw24w0LX78iYKt4YmePJNQ==
+dayjs@1.10.3, dayjs@^1.8.29:
+ version "1.10.3"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.3.tgz#cf3357c8e7f508432826371672ebf376cb7d619b"
+ integrity sha512-/2fdLN987N8Ki7Id8BUN2nhuiRyxTLumQnSQf9CNncFCyqFsSKb9TNhzRYcC8K8eJSJOKvbvkImo/MKKhNi4iw==
de-indent@^1.0.2:
version "1.0.2"
@@ -6077,10 +6077,10 @@ googleapis-common@^4.4.1:
url-template "^2.0.8"
uuid "^8.0.0"
-googleapis@66.0.0:
- version "66.0.0"
- resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-66.0.0.tgz#008062d06b13954bd3a0425c17e8f8396e884957"
- integrity sha512-jdEleRoyo/AeJZjKGC7Z2mHgochn2vR2JKqey6kydRkIBmCZxoQKLisRR4H8CRYZeEd6+c8Ns/LzS1S7qUjoFw==
+googleapis@67.0.0:
+ version "67.0.0"
+ resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-67.0.0.tgz#ce0b92dcf5e4bc0fd1b82666a1625eb37fd3dc36"
+ integrity sha512-luhulHrk42DruR+c12W2sY2rrEVoKVdjaZDuHWSxcp1qz+VxvWQpuiK2QDLCXmo36/VFPMaa+Y7rRUR+Qqzd7w==
dependencies:
google-auth-library "^6.0.0"
googleapis-common "^4.4.1"
@@ -9197,10 +9197,10 @@ nodemailer@6.4.16:
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.4.16.tgz#5cb6391b1d79ab7eff32d6f9f48366b5a7117293"
integrity sha512-68K0LgZ6hmZ7PVmwL78gzNdjpj5viqBdFqKrTtr9bZbJYj6BRj5W6WGkxXrEnUl3Co3CBXi3CZBUlpV/foGnOQ==
-nodemon@2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.6.tgz#1abe1937b463aaf62f0d52e2b7eaadf28cc2240d"
- integrity sha512-4I3YDSKXg6ltYpcnZeHompqac4E6JeAMpGm8tJnB9Y3T0ehasLa4139dJOcCrB93HHrUMsCrKtoAlXTqT5n4AQ==
+nodemon@2.0.7:
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.7.tgz#6f030a0a0ebe3ea1ba2a38f71bf9bab4841ced32"
+ integrity sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA==
dependencies:
chokidar "^3.2.2"
debug "^3.2.6"
@@ -11977,9 +11977,9 @@ string-length@^4.0.1:
strip-ansi "^6.0.0"
string-similarity@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.3.tgz#ef52d6fc59c8a0fc93b6307fbbc08cc6e18cde21"
- integrity sha512-QEwJzNFCqq+5AGImk5z4vbsEPTN/+gtyKfXBVLBcbPBRPNganZGfQnIuf9yJ+GiwSnD65sT8xrw/uwU1Q1WmfQ==
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b"
+ integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==
string-width@4.2.0, string-width@^4.0.0, string-width@^4.2.0:
version "4.2.0"