diff --git a/docs/anime.md b/docs/anime.md
index 8a5489c6a..751f7ea2e 100644
--- a/docs/anime.md
+++ b/docs/anime.md
@@ -252,6 +252,16 @@ pageClass: routes
+## CnGal
+
+### 每周速报
+
+
+
+### 制作者 / 游戏新闻
+
+
+
## DLsite
### 当前日期发售的新产品
diff --git a/lib/v2/cngal/entry.js b/lib/v2/cngal/entry.js
new file mode 100644
index 000000000..f852dfe2e
--- /dev/null
+++ b/lib/v2/cngal/entry.js
@@ -0,0 +1,25 @@
+const got = require('@/utils/got');
+const { art } = require('@/utils/render');
+const path = require('path');
+const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
+
+module.exports = async (ctx) => {
+ const entryId = ctx.params.id;
+
+ const response = await got(`https://www.cngal.org/api/entries/GetEntryView/${entryId}`);
+
+ const data = response.data;
+
+ ctx.state.data = {
+ title: `CnGal - ${data.name} 的动态`,
+ link: `https://www.cngal.org/entries/index/${entryId}`,
+ item: data.newsOfEntry.map((item) => ({
+ title: item.title,
+ description: art(path.join(__dirname, 'templates/entry-description.art'), item),
+ pubDate: timezone(parseDate(item.happenedTime), +8),
+ link: item.link,
+ })),
+ };
+ ctx.state.json = response.data;
+};
diff --git a/lib/v2/cngal/maintainer.js b/lib/v2/cngal/maintainer.js
new file mode 100644
index 000000000..a39d7281c
--- /dev/null
+++ b/lib/v2/cngal/maintainer.js
@@ -0,0 +1,4 @@
+module.exports = {
+ '/entry/:id': ['chengyuhui'],
+ '/weekly': ['chengyuhui'],
+};
diff --git a/lib/v2/cngal/radar.js b/lib/v2/cngal/radar.js
new file mode 100644
index 000000000..0edc6a357
--- /dev/null
+++ b/lib/v2/cngal/radar.js
@@ -0,0 +1,19 @@
+module.exports = {
+ 'cngal.org': {
+ _name: 'CnGal',
+ www: [
+ {
+ title: '每周速报',
+ docs: 'https://docs.rsshub.app/anime.html#cngal-mei-zhou-su-bao',
+ source: ['/', '/weeklynews'],
+ target: '/cngal/weekly',
+ },
+ {
+ title: '制作者/游戏新闻',
+ docs: 'https://docs.rsshub.app/anime.html#cngal-zhi-zuo-zhe-you-xi-xin-wen',
+ source: ['/entries/index/:id'],
+ target: '/cngal/entry/:id',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/cngal/router.js b/lib/v2/cngal/router.js
new file mode 100644
index 000000000..ca34fd616
--- /dev/null
+++ b/lib/v2/cngal/router.js
@@ -0,0 +1,4 @@
+module.exports = function (router) {
+ router.get('/entry/:id', require('./entry'));
+ router.get('/weekly', require('./weekly'));
+};
diff --git a/lib/v2/cngal/templates/entry-description.art b/lib/v2/cngal/templates/entry-description.art
new file mode 100644
index 000000000..4d12268e3
--- /dev/null
+++ b/lib/v2/cngal/templates/entry-description.art
@@ -0,0 +1,4 @@
+
{{ briefIntroduction }}
+{{ if image }}
+
+{{ /if }}
diff --git a/lib/v2/cngal/templates/weekly-description.art b/lib/v2/cngal/templates/weekly-description.art
new file mode 100644
index 000000000..9d4df4b9f
--- /dev/null
+++ b/lib/v2/cngal/templates/weekly-description.art
@@ -0,0 +1,4 @@
+{{ briefIntroduction }}
+{{ if mainImage }}
+
+{{ /if }}
diff --git a/lib/v2/cngal/weekly.js b/lib/v2/cngal/weekly.js
new file mode 100644
index 000000000..b4c28c2a9
--- /dev/null
+++ b/lib/v2/cngal/weekly.js
@@ -0,0 +1,20 @@
+const got = require('@/utils/got');
+const { art } = require('@/utils/render');
+const path = require('path');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const response = await got('https://www.cngal.org/api/news/GetWeeklyNewsOverview');
+
+ ctx.state.data = {
+ title: 'CnGal - 每周速报',
+ link: 'https://www.cngal.org/weeklynews',
+ item: response.data.map((item) => ({
+ title: item.name,
+ description: art(path.join(__dirname, 'templates/weekly-description.art'), item),
+ pubDate: parseDate(item.lastEditTime),
+ link: `https://www.cngal.org/articles/index/${item.id}`,
+ })),
+ };
+ ctx.state.json = response.data;
+};