diff --git a/assets/radar-rules.js b/assets/radar-rules.js
index e3fe1f192c..4f2695f0b7 100644
--- a/assets/radar-rules.js
+++ b/assets/radar-rules.js
@@ -1124,6 +1124,14 @@
script: "({id: document.querySelector('html').innerHTML.match(/photos.app.goo.gl\\/(.*?)\"/)[1]})",
},
],
+ sites: [
+ {
+ title: 'Sites',
+ docs: 'https://docs.rsshub.app/blog.html#google-sites',
+ source: ['/site/:id/*', '/site/:id'],
+ target: '/google/sites/:id',
+ },
+ ],
},
'javlibrary.com': {
_name: 'javlibrary',
diff --git a/docs/blog.md b/docs/blog.md
index 69b916072c..4b8e692169 100644
--- a/docs/blog.md
+++ b/docs/blog.md
@@ -10,6 +10,12 @@ pageClass: routes
+## Google Sites
+
+### 文章更新
+
+
+
## Hexo
### Next 主题博客
diff --git a/docs/en/blog.md b/docs/en/blog.md
index 3315372171..a7d4ab0446 100644
--- a/docs/en/blog.md
+++ b/docs/en/blog.md
@@ -10,6 +10,12 @@ pageClass: routes
+## Google Sites
+
+### Articles
+
+
+
## Hexo Blog
### Blog using Next theme
diff --git a/lib/router.js b/lib/router.js
index 9bf80ec23e..4ae1ffbd58 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -476,6 +476,7 @@ router.get('/google/citations/:id', require('./routes/google/citations'));
router.get('/google/scholar/:query', require('./routes/google/scholar'));
router.get('/google/doodles/:language?', require('./routes/google/doodles'));
router.get('/google/album/:id', require('./routes/google/album'));
+router.get('/google/sites/:id', require('./routes/google/sites'));
// Awesome Pigtals
router.get('/pigtails', require('./routes/pigtails'));
diff --git a/lib/routes/google/sites.js b/lib/routes/google/sites.js
new file mode 100644
index 0000000000..252d8d764e
--- /dev/null
+++ b/lib/routes/google/sites.js
@@ -0,0 +1,75 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+const base = 'https://sites.google.com/';
+
+module.exports = async (ctx) => {
+ const id = ctx.params.id;
+
+ const init_url = `https://sites.google.com/site/${id}/system/app/pages/sitemap/list?offset=0`;
+ const init_response = await got.get(init_url);
+
+ const test_pages_count = init_response.data.match(/'sites-pagination-next-link-top', (\d+),/);
+ if (!test_pages_count) {
+ throw 'Site Not Found';
+ }
+ const pages_count = parseInt(test_pages_count[1]);
+
+ const url = pages_count > 20 ? `https://sites.google.com/site/${id}/system/app/pages/sitemap/list?offset=${pages_count - 20}` : init_url;
+ const response = url === init_url ? init_response : await got.get(url);
+
+ const $ = cheerio.load(response.data);
+
+ const site_name = $('a#sites-chrome-userheader-title').text();
+ const list = $('.sites-table > tbody > tr').get();
+
+ const parseContent = async (htmlString) => {
+ const $ = cheerio.load(htmlString);
+
+ const content = $('#sites-canvas-main-content');
+
+ return {
+ description: content.html(),
+ };
+ };
+
+ const out = await Promise.all(
+ list.map(async (item, index) => {
+ const $ = cheerio.load(item);
+
+ const title = $('a');
+ const path = title.attr('href');
+ const link = base + path;
+ const time = new Date();
+ time.setMinutes(time.getMinutes() - pages_count + index);
+
+ const cache = await ctx.cache.get(link);
+ if (cache) {
+ return Promise.resolve(JSON.parse(cache));
+ }
+
+ const rssitem = {
+ title: title.text().trim(),
+ link: link,
+ pubDate: time,
+ author: site_name,
+ };
+
+ try {
+ const response = await got.get(link);
+ const result = await parseContent(response.data);
+ rssitem.description = result.description;
+ } catch (err) {
+ return Promise.resolve('');
+ }
+ ctx.cache.set(link, JSON.stringify(rssitem));
+ return Promise.resolve(rssitem);
+ })
+ );
+
+ ctx.state.data = {
+ title: `${site_name} - Google Sites`,
+ link: url,
+ item: out.filter((item) => item !== ''),
+ };
+};