diff --git a/docs/social-media.md b/docs/social-media.md
index 5fd4d21c03..f5d4f9a8b0 100644
--- a/docs/social-media.md
+++ b/docs/social-media.md
@@ -1146,6 +1146,16 @@ YouTube 官方亦有提供频道 RSS,形如
+## 全民 K 歌
+
+### 用户作品列表
+
+
+
+### 用户作品评论动态
+
+
+
## 数字尾巴
### 首页
diff --git a/lib/v2/qq/kg/cache.js b/lib/v2/qq/kg/cache.js
new file mode 100644
index 0000000000..30d83a6795
--- /dev/null
+++ b/lib/v2/qq/kg/cache.js
@@ -0,0 +1,28 @@
+const got = require('@/utils/got');
+const { JSDOM } = require('jsdom');
+
+module.exports = {
+ getPlayInfo: async (ctx, shareId, ksong_mid = '') => {
+ const link = `https://node.kg.qq.com/play?s=${shareId}`;
+ const cache_key = ksong_mid ? `ksong:${ksong_mid}` : link;
+ const data = await ctx.cache.tryGet(cache_key, async () => {
+ const response = await got(link);
+ const { window } = new JSDOM(response.data, {
+ runScripts: 'dangerously',
+ });
+ const data = window.__DATA__;
+ const name = data.detail.song_name;
+ const description = data.detail.content;
+ const author = data.detail.nick;
+ const itunes_item_image = data.detail.cover;
+
+ const enclosure_url = data.detail.playurl;
+ ksong_mid = ksong_mid ? ksong_mid : data.detail.ksong_mid;
+ const ctime = data.detail.ctime;
+ const comments = data.detail.comments;
+
+ return { name, link, description, author, enclosure_url, ksong_mid, ctime, itunes_item_image, comments };
+ });
+ return data;
+ },
+};
diff --git a/lib/v2/qq/kg/reply.js b/lib/v2/qq/kg/reply.js
new file mode 100644
index 0000000000..35bffe0068
--- /dev/null
+++ b/lib/v2/qq/kg/reply.js
@@ -0,0 +1,21 @@
+const cache = require('./cache');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const playId = ctx.params.playId;
+ const url = `https://node.kg.qq.com/play?s=${playId}`;
+ const play_item = await cache.getPlayInfo(ctx, playId, '');
+
+ ctx.state.data = {
+ title: `${play_item.name} - ${play_item.author} 的评论`,
+ link: url,
+ image: play_item.itunes_item_image,
+ allowEmpty: true,
+ item: play_item.comments.map((item) => ({
+ title: `${item.nick}:${item.content}`,
+ pubDate: parseDate(item.ctime * 1000),
+ link: url,
+ guid: `ksong:${play_item.ksong_mid}:${item.comment_id}`,
+ })),
+ };
+};
diff --git a/lib/v2/qq/kg/user.js b/lib/v2/qq/kg/user.js
new file mode 100644
index 0000000000..8194507571
--- /dev/null
+++ b/lib/v2/qq/kg/user.js
@@ -0,0 +1,50 @@
+const got = require('@/utils/got');
+const { JSDOM } = require('jsdom');
+const cache = require('./cache');
+const { parseDate } = require('@/utils/parse-date');
+
+module.exports = async (ctx) => {
+ const userId = ctx.params.userId;
+ const url = `https://node.kg.qq.com/personal?uid=${userId}`;
+ const response = await got(url);
+
+ const { window } = new JSDOM(response.data, {
+ runScripts: 'dangerously',
+ });
+ const data = window.__DATA__;
+ const author = data.data.nickname;
+ const authorimg = data.data.head_img_url;
+ const ugcList = data.data.ugclist;
+
+ const items = await Promise.all(
+ ugcList.map(async (item) => {
+ const link = `https://node.kg.qq.com/play?s=${item.shareid}`;
+ const item_info = await cache.getPlayInfo(ctx, item.shareid, item.ksong_mid);
+
+ const single = {
+ title: item.title || '',
+ description: item_info.description,
+ link,
+ guid: `ksong:${item.ksong_mid}`,
+ author,
+ pubDate: parseDate(item_info.ctime * 1000) || parseDate(item.ctime, 'X'),
+ itunes_item_image: item_info.itunes_item_image || item.avatar,
+ enclosure_url: item_info.enclosure_url,
+ enclosure_type: 'audio/x-m4a',
+ };
+
+ return single;
+ })
+ );
+
+ ctx.state.data = {
+ title: `${author} - 全民K歌`,
+ link: url,
+ description: data.share.content,
+ allowEmpty: true,
+ item: items,
+ image: authorimg,
+ itunes_author: author,
+ itunes_category: '全民K歌',
+ };
+};
diff --git a/lib/v2/qq/maintainer.js b/lib/v2/qq/maintainer.js
index 2161661481..5c76fc5d2b 100644
--- a/lib/v2/qq/maintainer.js
+++ b/lib/v2/qq/maintainer.js
@@ -1,5 +1,7 @@
module.exports = {
'/ac/comic/:id': ['nczitzk'],
'/ac/rank/:type?/:time?': ['nczitzk'],
+ '/kg/:userId': ['zhangxiang012'],
+ '/kg/reply/:playId': ['zhangxiang012'],
'/live/:id': ['nczitzk'],
};
diff --git a/lib/v2/qq/radar.js b/lib/v2/qq/radar.js
index 818cb96395..14f4d289b2 100644
--- a/lib/v2/qq/radar.js
+++ b/lib/v2/qq/radar.js
@@ -23,5 +23,19 @@ module.exports = {
target: '/qq/live/:id',
},
],
+ 'node.kg': [
+ {
+ title: '用户作品列表 - 全民 K 歌',
+ docs: 'https://docs.rsshub.app/live.html#qi-e-zhi-bo-zhi-bo-jian-ti-xing',
+ source: ['/personal'],
+ target: (_params, url) => `/qq/kg/${new URL(url).searchParams.get('uid')}`,
+ },
+ {
+ title: '用户作品评论动态 - 全民 K 歌',
+ docs: 'https://docs.rsshub.app/live.html#qi-e-zhi-bo-zhi-bo-jian-ti-xing',
+ source: ['/play'],
+ target: (_params, url) => `/qq/kg/${new URL(url).searchParams.get('s')}`,
+ },
+ ],
},
};
diff --git a/lib/v2/qq/router.js b/lib/v2/qq/router.js
index 1ed1c24a80..cdcf119fad 100644
--- a/lib/v2/qq/router.js
+++ b/lib/v2/qq/router.js
@@ -1,5 +1,7 @@
module.exports = function (router) {
router.get('/ac/comic/:id?', require('./ac/comic'));
router.get('/ac/rank/:type?/:time?', require('./ac/rank'));
+ router.get('/kg/:userId', require('./kg/user'));
+ router.get('/kg/reply/:playId', require('./kg/reply'));
router.get('/live/:id', require('./live'));
};