CVE-2021-21278: Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection') (CWE-74)
value: RSSHub is an open source, easy to use, and extensible RSS feed generator. In RSSHub before version 7f1c430 (non-semantic versioning) there is a risk of code injection. Some routes use `eval` or `Function constructor`, which may be injected by the target site with unsafe code, causing server-side security issues The fix in version 7f1c430 is to temporarily remove the problematic route and added a `no-new-func` rule to eslint.
CWE description: The product constructs all or part of a command, data structure, or record using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify how it is parsed or interpreted when it is sent to a downstream component.
CVSS v3 base score: 9.8
Published: 2021-01-26T21:15Z
Repository: https://github.com/DIYgod/RSSHub
Language: Markdown
Files changed: .eslintrc, docs/game.md, docs/live.md, docs/new-media.md, docs/program-update.md, docs/programming.md, lib/router.js, lib/routes/huxiu/utils.js
Commit date: 2021-01-25 18:43:47 +0800
Commit message: feat: remove some routes for security reasons, !!! no-eval no-new-func !!!

Diff: diff --git a/.eslintrc b/.eslintrc
index b1dac234..3b874a71 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -51,8 +51,9 @@
         "no-trailing-spaces": 2,
         "no-control-regex": 0,
         "prettier/prettier": 0,
         "no-await-in-loop": 2,
         "require-atomic-updates": 0,
-        "no-prototype-builtins": 0
+        "no-prototype-builtins": 0,
+        "no-new-func": 2
     }
 }
diff --git a/docs/game.md b/docs/game.md
index 001a2ea3..d113ee6f 100644
--- a/docs/game.md
+++ b/docs/game.md
@@ -430,26 +430,10 @@ Example: `https://store.steampowered.com/search/?specials=1&term=atelier` 中的
 
 ### 国服公告
 
 <Route author="KotoriK" example="/pcr/news-cn" path="/pcr/news-cn"/>
 
-## 篝火营地
-
-### 游戏资讯
-
-<Route author="sintak" example="/gouhuo/news/switch" path="/gouhuo/news/:category" :paramsDesc="['资讯类型']">
-
-| 精选       | 海外     | 原创    | PS4 | Xboxone | PC | Switch | 掌机     | 手游       | 新闻 | 评测   | 文化    | 视频  | 音频  | 折扣     |
-| ---------- | -------- | ------- | --- | ------- | -- | ------ | -------- | ---------- | ---- | ------ | ------- | ----- | ----- | -------- |
-| choiceness | overseas | orignal | ps4 | xboxone | pc | switch | handheld | mobilegame | news | review | culture | video | audio | discount |
-
-</Route>
-
-### 游戏攻略
-
-<Route author="sintak" example="/gouhuo/strategy" path="/gouhuo/strategy"/>
-
 ## 怪物猎人世界
 
 ### 更新情报
 
 <Route author="DIYgod" example="/mhw/update" path="/mhw/update" radar="1" rssbud="1"/>
diff --git a/docs/live.md b/docs/live.md
index 84f153c5..e92c8c05 100644
--- a/docs/live.md
+++ b/docs/live.md
@@ -36,16 +36,10 @@ pageClass: routes
 
 ### 直播间开播
 
 <Route author="DIYgod" example="/douyu/room/24422" path="/douyu/room/:id" :paramsDesc="['直播间 id, 可在主播直播间页 URL 中找到']"/>
 
-## 黑白直播
-
-### 直播间开播
-
-<Route author="laampui" example="/heibaizhibo/room/195976" path="/heibaizhibo/room/:id" :paramsDesc="['直播间 id, 可在主播直播间页 URL 中找到']"/>
-
 ## 虎牙直播
 
 ### 直播间开播
 
 <Route author="SettingDust xyqfer" example="/huya/live/edmunddzhang" path="/huya/live/:id" :paramsDesc="['直播间id或主播名(有一些id是名字，如上)']" radar="1" rssbud="1"/>
diff --git a/docs/new-media.md b/docs/new-media.md
index 23d50eb1..708e7f65 100644
--- a/docs/new-media.md
+++ b/docs/new-media.md
@@ -1934,14 +1934,10 @@ column 为 third 时可选的 category:
 | -------- | ---- | ---- | -------- | -------- | ---- | ---- | ------ | ------ | ---- | -------- | ------ | -------- | ---- | ---- |
 | 1        | 2    | 3    | 4        | 5        | 6    | 7    | 8      | 9      | 10   | 11       | 12     | 13       | 14   | 15   |
 
 </Route>
 
-### 数读
-
-<Route author="laampui" example="/netease/news/data" path="/netease/news/data"/>
-
 ## 维基百科
 
 ### 中国大陆新闻动态
 
 <Route author="HenryQW" example="/wikipedia/mainland" path="/wikipedia/mainland"/>
diff --git a/docs/program-update.md b/docs/program-update.md
index 649ab76f..37eb4863 100644
--- a/docs/program-update.md
+++ b/docs/program-update.md
@@ -416,16 +416,10 @@ pageClass: routes
 
 ### 版本详细信息
 
 <Route author="mrbruce516" example="/tesla" path="/tesla/update"/>
 
-## 腾讯柠檬 Lab
-
-### 柠檬精选 Mac Apps
-
-<Route author="HenryQW" example="/tencent/lemon" path="/tencent/lemon"/>
-
 ## 腾讯云移动直播 SDK
 
 ### 更新日志
 
 <Route author="cielpy" example="/qcloud/mlvb/changelog" path="/qcloud/mlvb/changelog"/>
diff --git a/docs/programming.md b/docs/programming.md
index 855b9925..493aa2bf 100644
--- a/docs/programming.md
+++ b/docs/programming.md
@@ -676,15 +676,10 @@ GitHub 官方也提供了一些 RSS:
 ### posts
 
 <Route author="hellodword" example="/galaxylab" path="/galaxylab">
 </Route>
 
-## 前端技术文章
-
-<Route author="laampui" example="/front-end-rss" path="/front-end-rss" :paramsDesc="['分类']">
-</Route>
-
 ## 前端艺术家 && 飞冰早报
 
 ### 列表
 
 <Route author="kouchao" example="/jskou/0" path="/jskou/:type?" :paramsDesc="['分类']">
diff --git a/lib/router.js b/lib/router.js
index 41506a7c..d9ee2918 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -2070,14 +2070,10 @@ router.get('/pingwest/tag/:tag/:type', require('./routes/pingwest/tag'));
 router.get('/pingwest/user/:uid/:type?', require('./routes/pingwest/user'));
 
 // Hanime
 router.get('/hanime/video', require('./routes/hanime/video'));
 
-// 篝火营地
-router.get('/gouhuo/news/:category', require('./routes/gouhuo'));
-router.get('/gouhuo/strategy', require('./routes/gouhuo/strategy'));
-
 // Soul
 router.get('/soul/:id', require('./routes/soul'));
 router.get('/soul/posts/hot', require('./routes/soul/hot'));
 
 // 单向空间
@@ -2139,13 +2135,10 @@ router.get('/szse/inquire/:type', require('./routes/szse/inquire'));
 router.get('/szse/rule', require('./routes/szse/rule'));
 
 // 前端艺术家每日整理&&飞冰早报
 router.get('/jskou/:type?', require('./routes/jskou/index'));
 
-// 前端
-router.get('/front-end-rss', require('./routes/frontend/index'));
-
 // 国家应急广播
 router.get('/cneb/yjxx', require('./routes/cneb/yjxx'));
 router.get('/cneb/guoneinews', require('./routes/cneb/guoneinews'));
 
 // 邮箱
@@ -2176,13 +2169,10 @@ router.get('/cfan/news', require('./routes/cfan/news'));
 router.get('/sohu/mp/:id', require('./routes/sohu/mp'));
 
 // 腾讯企鹅号
 router.get('/tencent/news/author/:mid', require('./routes/tencent/news/author'));
 
-// 腾讯柠檬精选
-router.get('/tencent/lemon', require('./routes/tencent/lemon/index'));
-
 // 奈菲影视
 router.get('/nfmovies/:id?', require('./routes/nfmovies/index'));
 
 // 书友社区
 router.get('/andyt/:view?', require('./routes/andyt/index'));
@@ -3054,11 +3044,10 @@ router.get('/jike/topic/text/:id', require('./routes/jike/topicText'));
 router.get('/jike/user/:id', require('./routes/jike/user'));
 
 // 网易新闻
 router.get('/netease/news/rank/:category?/:type?/:time?', require('./routes/netease/news/rank'));
 router.get('/netease/news/special/:type?', require('./routes/netease/news/special'));
-router.get('/netease/news/data', require('./routes/netease/news/data'));
 
 // 网易 - 网易号
 router.get('/netease/dy/:id', require('./routes/netease/dy'));
 router.get('/netease/dy2/:id', require('./routes/netease/dy2'));
 
@@ -3167,13 +3156,10 @@ router.get('/socialbeta/hunt', require('./routes/socialbeta/hunt'));
 router.get('/touhougarakuta/:language/:type', require('./routes/touhougarakuta'));
 
 // 猎趣TV
 router.get('/liequtv/room/:id', require('./routes/liequtv/room'));
 
-// 黑白直播
-router.get('/heibaizhibo/room/:id', require('./routes/heibaizhibo/room'));
-
 // Behance
 router.get('/behance/:user/:type?', require('./routes/behance/index'));
 
 // furstar.jp
 router.get('/furstar/characters/:lang?', require('./routes/furstar/index'));
diff --git a/lib/routes/frontend/index.js b/lib/routes/frontend/index.js
deleted file mode 100644
index 02e1dac2..00000000
--- a/lib/routes/frontend/index.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-
-module.exports = async (ctx) => {
-    const response = await got.get(`https://front-end-rss.now.sh/`);
-    const $ = cheerio.load(response.data);
-    const fn = Function($($('script')[1]).html() + 'return Array.isArray(LINKS_DATA) ? LINKS_DATA : []');
-    const items = fn().reduce(
-        (acc, category) => [
-            ...acc,
-            ...category.items.map((item) => ({
-                link: item.link,
-                pubDate: item.date,
-                title: item.title,
-                author: category.title,
-                description: category.title,
-            })),
-        ],
-        []
-    );
-
-    ctx.state.data = {
-        title: '前端技术文章',
-        link: 'https://front-end-rss.now.sh/',
-        item: items,
-    };
-};
diff --git a/lib/routes/gouhuo/cache.js b/lib/routes/gouhuo/cache.js
deleted file mode 100644
index 7f765aa4..00000000
--- a/lib/routes/gouhuo/cache.js
+++ /dev/null
@@ -1,44 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-
-const self = {
-    _getProfile: async (ctx) => {
-        const key = 'gouhuo-profile';
-        let profile = await ctx.cache.get(key);
-        if (!profile) {
-            const response = await got({
-                method: 'get',
-                url: `https://gouhuo.qq.com/`,
-                headers: {
-                    Referer: `https://gouhuo.qq.com/`,
-                },
-            });
-            const body = response.data;
-            const $ = cheerio.load(body);
-
-            // eslint-disable-next-line no-eval
-            const obj = eval(body.match(/(?<=<script>\s*window\.__NUXT__=)[\s\S]*?(?=<\/script>)/g)[0]);
-            const tabNameMapping = {};
-            for (const item of obj.data[0].tabList) {
-                tabNameMapping[item.tab_id] = item.tab_name;
-            }
-            const title = $('title').text().split('-')[0].trim();
-            const description = $('title').text().split('-')[1].trim();
-
-            profile = JSON.stringify({
-                title: title,
-                description: description,
-                tabNameMapping: tabNameMapping,
-            });
-
-            ctx.cache.set(key, profile);
-        }
-        return JSON.parse(profile);
-    },
-    getStaffs: async (ctx, tabId) => {
-        const profile = await self._getProfile(ctx);
-        return [profile.title, profile.description, profile.tabNameMapping[tabId]];
-    },
-};
-
-module.exports = self;
diff --git a/lib/routes/gouhuo/index.js b/lib/routes/gouhuo/index.js
deleted file mode 100644
index 2931ed7f..00000000
--- a/lib/routes/gouhuo/index.js
+++ /dev/null
@@ -1,62 +0,0 @@
-const got = require('@/utils/got');
-const cache = require('./cache');
-
-module.exports = async (ctx) => {
-    const category = ctx.params.category;
-
-    const tabIdMapping = {
-        choiceness: '1_110',
-        overseas: '1_108',
-        orignal: '1_109',
-        ps4: '2_5',
-        xboxone: '2_13',
-        pc: '2_1',
-        switch: '2_30',
-        handheld: '3_1',
-        mobilegame: '3_2',
-        news: '1_101',
-        review: '1_104',
-        culture: '1_103',
-        video: '1_102',
-        audio: '1_107',
-        discount: '1_120',
-    };
-    const tabId = (() => {
-        if (tabIdMapping[category]) {
-            return tabIdMapping[category];
-        } else {
-            throw Error('Unknow route.');
-        }
-    })();
-
-    const response = await got({
-        method: 'get',
-        url: `https://gouhuo.qq.com/content/getContentByTab?tabId=${tabId}`,
-        headers: {
-            Referer: `https://gouhuo.qq.com/`,
-        },
-    });
-    const list = response.data.data.list;
-
-    const staffs = await cache.getStaffs(ctx, tabId);
-    const title = staffs[0];
-    const description = staffs[1];
-    const tabName = staffs[2];
-
-    ctx.state.data = {
-        title: `${title} ${tabName}`,
-        link: `https://gouhuo.qq.com/`,
-        description: description,
-        item:
-            list &&
-            list.map((item) => {
-                const single = {
-                    title: item.title,
-                    description: `${item.title}<br><img src="${item.img_url}">`, // Get fulltext manually if needs be. Snippet like: $('.widget-article').first().html();
-                    pubDate: new Date(item.publish_ts * 1000).toUTCString(),
-                    link: item.link,
-                };
-                return single;
-            }),
-    };
-};
diff --git a/lib/routes/gouhuo/strategy.js b/lib/routes/gouhuo/strategy.js
deleted file mode 100644
index f5897ebf..00000000
--- a/lib/routes/gouhuo/strategy.js
+++ /dev/null
@@ -1,35 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-
-module.exports = async (ctx) => {
-    const baseUrl = 'https://gouhuo.qq.com';
-    const url = `${baseUrl}/guide`;
-    const response = await got({
-        method: 'get',
-        url: url,
-        headers: {
-            Referer: `https://gouhuo.qq.com/`,
-        },
-    });
-    const body = response.data;
-    const $ = cheerio.load(body);
-
-    // eslint-disable-next-line no-eval
-    const obj = eval(body.match(/(?<=<script>\s*window\.__NUXT__=)[\s\S]*?(?=<\/script>)/g)[0]);
-    const items = obj.data[0].newGuides.map((item) => {
-        const img_url = item.img_url;
-        const single = {
-            title: item.title,
-            description: `${item.title}<br><img src="${img_url}">`,
-            pubDate: new Date(item.publish_ts * 1000).toUTCString(),
-            link: `${baseUrl}${item.link}`,
-        };
-        return single;
-    });
-
-    ctx.state.data = {
-        title: $('title').text().split('_')[0],
-        link: url,
-        item: items,
-    };
-};
diff --git a/lib/routes/heibaizhibo/room.js b/lib/routes/heibaizhibo/room.js
deleted file mode 100644
index 970374fd..00000000
--- a/lib/routes/heibaizhibo/room.js
+++ /dev/null
@@ -1,31 +0,0 @@
-const got = require('@/utils/got');
-
-module.exports = async (ctx) => {
-    const id = ctx.params.id;
-    const response = await got.get(`https://www.heibaizhibo.com/anchorLive/${id}`);
-
-    const liveInfo = Function('const window={};' + response.data.match(/window\.__NUXT__=.*;/gm)[0] + 'return window.__NUXT__')();
-    const gtvId = liveInfo.data[0].gtvId;
-    const res = await got.get(`https://sig.heibaizhibo.com/signal-front/live/matchLiveInfo?gtvId=${gtvId}&source=2&liveType=3&defi=hd`);
-    const offline = res.data.data[0].score === -1;
-
-    const item = offline
-        ? []
-        : [
-              {
-                  title: liveInfo.data[0].text,
-                  author: liveInfo.data[0].anchorInfo.nickname,
-                  link: response.url,
-                  guid: response.url + liveInfo.data[0].live_info.startDate,
-              },
-          ];
-
-    ctx.state.data = {
-        title: `${liveInfo.data[0].anchorInfo.nickname} - 黑白直播`,
-        image: liveInfo.data[0].anchorInfo.portrait,
-        description: liveInfo.data[0].anchorInfo.notice,
-        link: response.url,
-        item,
-        allowEmpty: true,
-    };
-};
diff --git a/lib/routes/huxiu/utils.js b/lib/routes/huxiu/utils.js
index 42ba16f7..69f4ac52 100644
--- a/lib/routes/huxiu/utils.js
+++ b/lib/routes/huxiu/utils.js
@@ -13,17 +13,17 @@ const ProcessFeed = async (list, cache) => {
             const single = await cache.tryGet(link, async () => {
                 const response = await got.get(link);
 
                 const $ = cheerio.load(response.data);
 
-                const __INITIAL_STATE__ = Function(
-                    'let window={};' +
-                        $('*')
-                            .html()
-                            .match(/window\.__INITIAL_STATE__.*};/gm)[0] +
-                        'return window.__INITIAL_STATE__'
-                )();
+                // const __INITIAL_STATE__ = Function(
+                //     'let window={};' +
+                //         $('*')
+                //             .html()
+                //             .match(/window\.__INITIAL_STATE__.*};/gm)[0] +
+                //         'return window.__INITIAL_STATE__'
+                // )();
 
                 $('.article__content')
                     .find('.lazyImg')
                     .each((i, e) => {
                         $(e).attr('src', $(e).attr('_src'));
@@ -40,13 +40,13 @@ const ProcessFeed = async (list, cache) => {
                 });
                 $('img.dialog_add_wxxy_qrcode_icon').remove();
 
                 let description = '';
 
-                if ('video_info' in __INITIAL_STATE__.articleDetail.articleDetail) {
-                    description += `<video height="100%" poster="${__INITIAL_STATE__.articleDetail.articleDetail.video_info.cover}" controls src="${__INITIAL_STATE__.articleDetail.articleDetail.video_info.hd_link}"></video>`;
-                }
+                // if ('video_info' in __INITIAL_STATE__.articleDetail.articleDetail) {
+                //     description += `<video height="100%" poster="${__INITIAL_STATE__.articleDetail.articleDetail.video_info.cover}" controls src="${__INITIAL_STATE__.articleDetail.articleDetail.video_info.hd_link}"></video>`;
+                // }
                 if ($('.top-img').html() !== null) {
                     description += $('.top-img').html();
                 }
 
                 return {
diff --git a/lib/routes/netease/news/data.js b/lib/routes/netease/news/data.js
deleted file mode 100644
index 97bcad19..00000000
--- a/lib/routes/netease/news/data.js
+++ /dev/null
@@ -1,39 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const iconv = require('iconv-lite');
-
-module.exports = async (ctx) => {
-    const response = await got({
-        url: 'https://data.163.com',
-        method: 'get',
-        responseType: 'buffer',
-    });
-    const $ = cheerio.load(iconv.decode(response.data, 'gbk'));
-    const dataStr = $('*')
-        .html()
-        .match(/var\sohnofuchlist=\[(.|\n)*"a"\];$/gm)[0];
-    const arr = new Function(dataStr + 'ohnofuchlist.pop();return ohnofuchlist;')();
-
-    const item = await Promise.all(
-        arr.slice(0, 20).map(async (item) => {
-            const single = await ctx.cache.tryGet(item.url, async () => {
-                const res = await got.get(item.url);
-                const doc = cheerio.load(res.data);
-                const description = doc('#main-content').html() || doc('.post_body').html();
-                return {
-                    title: item.title,
-                    link: item.url,
-                    pubDate: new Date(item.time),
-                    description,
-                };
-            });
-            return Promise.resolve(single);
-        })
-    );
-
-    ctx.state.data = {
-        title: '数读 - 网易新闻',
-        link: 'https://data.163.com/',
-        item,
-    };
-};
diff --git a/lib/routes/tencent/lemon/index.js b/lib/routes/tencent/lemon/index.js
deleted file mode 100644
index ce091b81..00000000
--- a/lib/routes/tencent/lemon/index.js
+++ /dev/null
@@ -1,29 +0,0 @@
-const got = require('@/utils/got');
-const date = require('@/utils/date');
-
-module.exports = async (ctx) => {
-    const url = 'https://lemon.qq.com/lab/js/source.js';
-
-    let data = (await got.get(url)).data.match(/(?<=(const list = ))(.*)(\])/gs)[0];
-
-    // eslint-disable-next-line no-eval
-    data = eval('(' + data + ')').slice(0, 10);
-
-    const items = data.map((i) => ({
-        title: i.name,
-        description: `
-        ${i.comment}</br>
-        <img src="${i.logo}"></br>
-        <a href="${i.downloadlink}">下载链接</a>
-        `,
-        link: `https://lemon.qq.com/lab/app/${i.shortname}.html`,
-        author: i.referrer,
-        pubDate: date(i.date),
-    }));
-
-    ctx.state.data = {
-        title: '腾讯柠檬精选',
-        link: 'https://lemon.qq.com/lab/',
-        item: items,
-    };
-};

Vulnerable code:         "no-prototype-builtins": 0
## 篝火营地

### 游戏资讯

<Route author="sintak" example="/gouhuo/news/switch" path="/gouhuo/news/:category" :paramsDesc="['资讯类型']">

| 精选       | 海外     | 原创    | PS4 | Xboxone | PC | Switch | 掌机     | 手游       | 新闻 | 评测   | 文化    | 视频  | 音频  | 折扣     |
| ---------- | -------- | ------- | --- | ------- | -- | ------ | -------- | ---------- | ---- | ------ | ------- | ----- | ----- | -------- |
| choiceness | overseas | orignal | ps4 | xboxone | pc | switch | handheld | mobilegame | news | review | culture | video | audio | discount |

</Route>

### 游戏攻略

<Route author="sintak" example="/gouhuo/strategy" path="/gouhuo/strategy"/>

## 黑白直播

### 直播间开播

<Route author="laampui" example="/heibaizhibo/room/195976" path="/heibaizhibo/room/:id" :paramsDesc="['直播间 id, 可在主播直播间页 URL 中找到']"/>

### 数读

<Route author="laampui" example="/netease/news/data" path="/netease/news/data"/>

## 腾讯柠檬 Lab

### 柠檬精选 Mac Apps

<Route author="HenryQW" example="/tencent/lemon" path="/tencent/lemon"/>

## 前端技术文章

<Route author="laampui" example="/front-end-rss" path="/front-end-rss" :paramsDesc="['分类']">
</Route>

// 篝火营地
router.get('/gouhuo/news/:category', require('./routes/gouhuo'));
router.get('/gouhuo/strategy', require('./routes/gouhuo/strategy'));

// 前端
router.get('/front-end-rss', require('./routes/frontend/index'));

// 腾讯柠檬精选
router.get('/tencent/lemon', require('./routes/tencent/lemon/index'));

router.get('/netease/news/data', require('./routes/netease/news/data'));
// 黑白直播
router.get('/heibaizhibo/room/:id', require('./routes/heibaizhibo/room'));

const got = require('@/utils/got');
const cheerio = require('cheerio');

module.exports = async (ctx) => {
    const response = await got.get(`https://front-end-rss.now.sh/`);
    const $ = cheerio.load(response.data);
    const fn = Function($($('script')[1]).html() + 'return Array.isArray(LINKS_DATA) ? LINKS_DATA : []');
    const items = fn().reduce(
        (acc, category) => [
            ...acc,
            ...category.items.map((item) => ({
                link: item.link,
                pubDate: item.date,
                title: item.title,
                author: category.title,
                description: category.title,
            })),
        ],
        []
    );

    ctx.state.data = {
        title: '前端技术文章',
        link: 'https://front-end-rss.now.sh/',
        item: items,
    };
};
const got = require('@/utils/got');
const cheerio = require('cheerio');

const self = {
    _getProfile: async (ctx) => {
        const key = 'gouhuo-profile';
        let profile = await ctx.cache.get(key);
        if (!profile) {
            const response = await got({
                method: 'get',
                url: `https://gouhuo.qq.com/`,
                headers: {
                    Referer: `https://gouhuo.qq.com/`,
                },
            });
            const body = response.data;
            const $ = cheerio.load(body);

            // eslint-disable-next-line no-eval
            const obj = eval(body.match(/(?<=<script>\s*window\.__NUXT__=)[\s\S]*?(?=<\/script>)/g)[0]);
            const tabNameMapping = {};
            for (const item of obj.data[0].tabList) {
                tabNameMapping[item.tab_id] = item.tab_name;
            }
            const title = $('title').text().split('-')[0].trim();
            const description = $('title').text().split('-')[1].trim();

            profile = JSON.stringify({
                title: title,
                description: description,
                tabNameMapping: tabNameMapping,
            });

            ctx.cache.set(key, profile);
        }
        return JSON.parse(profile);
    },
    getStaffs: async (ctx, tabId) => {
        const profile = await self._getProfile(ctx);
        return [profile.title, profile.description, profile.tabNameMapping[tabId]];
    },
};

module.exports = self;
const got = require('@/utils/got');
const cache = require('./cache');

module.exports = async (ctx) => {
    const category = ctx.params.category;

    const tabIdMapping = {
        choiceness: '1_110',
        overseas: '1_108',
        orignal: '1_109',
        ps4: '2_5',
        xboxone: '2_13',
        pc: '2_1',
        switch: '2_30',
        handheld: '3_1',
        mobilegame: '3_2',
        news: '1_101',
        review: '1_104',
        culture: '1_103',
        video: '1_102',
        audio: '1_107',
        discount: '1_120',
    };
    const tabId = (() => {
        if (tabIdMapping[category]) {
            return tabIdMapping[category];
        } else {
            throw Error('Unknow route.');
        }
    })();

    const response = await got({
        method: 'get',
        url: `https://gouhuo.qq.com/content/getContentByTab?tabId=${tabId}`,
        headers: {
            Referer: `https://gouhuo.qq.com/`,
        },
    });
    const list = response.data.data.list;

    const staffs = await cache.getStaffs(ctx, tabId);
    const title = staffs[0];
    const description = staffs[1];
    const tabName = staffs[2];

    ctx.state.data = {
        title: `${title} ${tabName}`,
        link: `https://gouhuo.qq.com/`,
        description: description,
        item:
            list &&
            list.map((item) => {
                const single = {
                    title: item.title,
                    description: `${item.title}<br><img src="${item.img_url}">`, // Get fulltext manually if needs be. Snippet like: $('.widget-article').first().html();
                    pubDate: new Date(item.publish_ts * 1000).toUTCString(),
                    link: item.link,
                };
                return single;
            }),
    };
};
const got = require('@/utils/got');
const cheerio = require('cheerio');

module.exports = async (ctx) => {
    const baseUrl = 'https://gouhuo.qq.com';
    const url = `${baseUrl}/guide`;
    const response = await got({
        method: 'get',
        url: url,
        headers: {
            Referer: `https://gouhuo.qq.com/`,
        },
    });
    const body = response.data;
    const $ = cheerio.load(body);

    // eslint-disable-next-line no-eval
    const obj = eval(body.match(/(?<=<script>\s*window\.__NUXT__=)[\s\S]*?(?=<\/script>)/g)[0]);
    const items = obj.data[0].newGuides.map((item) => {
        const img_url = item.img_url;
        const single = {
            title: item.title,
            description: `${item.title}<br><img src="${img_url}">`,
            pubDate: new Date(item.publish_ts * 1000).toUTCString(),
            link: `${baseUrl}${item.link}`,
        };
        return single;
    });

    ctx.state.data = {
        title: $('title').text().split('_')[0],
        link: url,
        item: items,
    };
};
const got = require('@/utils/got');

module.exports = async (ctx) => {
    const id = ctx.params.id;
    const response = await got.get(`https://www.heibaizhibo.com/anchorLive/${id}`);

    const liveInfo = Function('const window={};' + response.data.match(/window\.__NUXT__=.*;/gm)[0] + 'return window.__NUXT__')();
    const gtvId = liveInfo.data[0].gtvId;
    const res = await got.get(`https://sig.heibaizhibo.com/signal-front/live/matchLiveInfo?gtvId=${gtvId}&source=2&liveType=3&defi=hd`);
    const offline = res.data.data[0].score === -1;

    const item = offline
        ? []
        : [
              {
                  title: liveInfo.data[0].text,
                  author: liveInfo.data[0].anchorInfo.nickname,
                  link: response.url,
                  guid: response.url + liveInfo.data[0].live_info.startDate,
              },
          ];

    ctx.state.data = {
        title: `${liveInfo.data[0].anchorInfo.nickname} - 黑白直播`,
        image: liveInfo.data[0].anchorInfo.portrait,
        description: liveInfo.data[0].anchorInfo.notice,
        link: response.url,
        item,
        allowEmpty: true,
    };
};
                const __INITIAL_STATE__ = Function(
                    'let window={};' +
                        $('*')
                            .html()
                            .match(/window\.__INITIAL_STATE__.*};/gm)[0] +
                        'return window.__INITIAL_STATE__'
                )();
                if ('video_info' in __INITIAL_STATE__.articleDetail.articleDetail) {
                    description += `<video height="100%" poster="${__INITIAL_STATE__.articleDetail.articleDetail.video_info.cover}" controls src="${__INITIAL_STATE__.articleDetail.articleDetail.video_info.hd_link}"></video>`;
                }
const got = require('@/utils/got');
const cheerio = require('cheerio');
const iconv = require('iconv-lite');

module.exports = async (ctx) => {
    const response = await got({
        url: 'https://data.163.com',
        method: 'get',
        responseType: 'buffer',
    });
    const $ = cheerio.load(iconv.decode(response.data, 'gbk'));
    const dataStr = $('*')
        .html()
        .match(/var\sohnofuchlist=\[(.|\n)*"a"\];$/gm)[0];
    const arr = new Function(dataStr + 'ohnofuchlist.pop();return ohnofuchlist;')();

    const item = await Promise.all(
        arr.slice(0, 20).map(async (item) => {
            const single = await ctx.cache.tryGet(item.url, async () => {
                const res = await got.get(item.url);
                const doc = cheerio.load(res.data);
                const description = doc('#main-content').html() || doc('.post_body').html();
                return {
                    title: item.title,
                    link: item.url,
                    pubDate: new Date(item.time),
                    description,
                };
            });
            return Promise.resolve(single);
        })
    );

    ctx.state.data = {
        title: '数读 - 网易新闻',
        link: 'https://data.163.com/',
        item,
    };
};
const got = require('@/utils/got');
const date = require('@/utils/date');

module.exports = async (ctx) => {
    const url = 'https://lemon.qq.com/lab/js/source.js';

    let data = (await got.get(url)).data.match(/(?<=(const list = ))(.*)(\])/gs)[0];

    // eslint-disable-next-line no-eval
    data = eval('(' + data + ')').slice(0, 10);

    const items = data.map((i) => ({
        title: i.name,
        description: `
        ${i.comment}</br>
        <img src="${i.logo}"></br>
        <a href="${i.downloadlink}">下载链接</a>
        `,
        link: `https://lemon.qq.com/lab/app/${i.shortname}.html`,
        author: i.referrer,
        pubDate: date(i.date),
    }));

    ctx.state.data = {
        title: '腾讯柠檬精选',
        link: 'https://lemon.qq.com/lab/',
        item: items,
    };
};
Fixed code:         "no-prototype-builtins": 0,
        "no-new-func": 2
                // const __INITIAL_STATE__ = Function(
                //     'let window={};' +
                //         $('*')
                //             .html()
                //             .match(/window\.__INITIAL_STATE__.*};/gm)[0] +
                //         'return window.__INITIAL_STATE__'
                // )();
                // if ('video_info' in __INITIAL_STATE__.articleDetail.articleDetail) {
                //     description += `<video height="100%" poster="${__INITIAL_STATE__.articleDetail.articleDetail.video_info.cover}" controls src="${__INITIAL_STATE__.articleDetail.articleDetail.video_info.hd_link}"></video>`;
                // }