diff --git a/docs/README.md b/docs/README.md
index d72d1eede..cc295251d 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -745,6 +745,14 @@ GitHub 官方也提供了一些 RSS:
> GitChat 需要付费订阅, RSS 仅做更新提醒, 不含付费内容.
+### Gitea
+
+
+
+> gitea 博客一般发布最新的 release 信息,路由选择用 blog 名称主要因为其地址名为 blog,而非 changlog,慎重起见还是用 blog 命名。
+
+
+
## 直播
### 哔哩哔哩直播
diff --git a/router.js b/router.js
index c594e10fe..13510474d 100644
--- a/router.js
+++ b/router.js
@@ -808,6 +808,9 @@ router.get('/tssstatus/:board/:build', require('./routes/tssstatus'));
router.get('/anime1/anime/:time/:name', require('./routes/anime1/anime'));
router.get('/anime1/search/:keyword', require('./routes/anime1/search'));
+// gitea
+router.get('/gitea/blog', require('./routes/gitea/blog'));
+
// iDownloadBlog
router.get('/idownloadblog', require('./routes/idownloadblog/index'));
diff --git a/routes/gitea/blog.js b/routes/gitea/blog.js
new file mode 100644
index 000000000..a99cbfa32
--- /dev/null
+++ b/routes/gitea/blog.js
@@ -0,0 +1,76 @@
+const axios = require('../../utils/axios');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ const host = 'https://blog.gitea.io/';
+
+ const response = await axios({
+ method: 'get',
+ url: host,
+ headers: {
+ Referer: host,
+ },
+ });
+
+ const $ = cheerio.load(response.data);
+
+ const loadContent = async (link) => {
+ // Check cache
+ const cache = await ctx.cache.get(link);
+ if (cache) {
+ return Promise.resolve(cache);
+ }
+
+ const response = await axios({
+ method: 'get',
+ url: link,
+ headers: {
+ Referer: host,
+ },
+ });
+
+ const $ = cheerio.load(response.data);
+ $('section .content script').remove();
+ $('section .content #discourse-comments').remove();
+ const html = $('section .content').html();
+ ctx.cache.set(link, html, 3 * 60 * 60);
+
+ return html;
+ };
+
+ const items = await Promise.all(
+ $('.card .card-content')
+ .get()
+ .map(async (item) => {
+ const title = $('.media .media-content .title', item).text();
+ const subtitle = $('.media .media-content .subtitle', item)
+ .text()
+ .replace(/\t/g, '')
+ .replace(/\n/g, ' ')
+ .trim();
+ const matchs = /(.*) by (.*)/.exec(subtitle);
+ const pubDate = matchs && matchs.length === 3 ? new Date(matchs[1]) : new Date();
+ const author = matchs && matchs.length === 3 ? matchs[2] : '';
+ const link = $(item)
+ .children('a')
+ .attr('href');
+ const desc = await loadContent(link);
+
+ const single = {
+ title: title,
+ link: link,
+ guid: link,
+ pubDate: pubDate,
+ description: `
${author}
${desc}`,
+ };
+ return Promise.resolve(single);
+ })
+ );
+
+ ctx.state.data = {
+ title: 'Gitea Blog',
+ link: host,
+ description: 'Gitea Blog',
+ item: items,
+ };
+};