diff --git a/docs/multimedia.md b/docs/multimedia.md
index c3a83b6ab..0c4ee045f 100644
--- a/docs/multimedia.md
+++ b/docs/multimedia.md
@@ -1315,7 +1315,7 @@ Tiny Tiny RSS 会给所有 iframe 元素添加 `sandbox="allow-scripts"` 属性
### 频道
-
+
## 中国高清网
diff --git a/lib/router.js b/lib/router.js
index 6280249c3..b9da10952 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -995,9 +995,6 @@ router.get('/xidian/jwc/:category?', lazyloadRouteHandler('./routes/universities
// Westore
router.get('/westore/new', lazyloadRouteHandler('./routes/westore/new'));
-// 优酷
-router.get('/youku/channel/:channelId/:embed?', lazyloadRouteHandler('./routes/youku/channel'));
-
// 油价
router.get('/oilprice/:area', lazyloadRouteHandler('./routes/oilprice'));
diff --git a/lib/routes/youku/channel.js b/lib/routes/youku/channel.js
deleted file mode 100644
index 37b44634a..000000000
--- a/lib/routes/youku/channel.js
+++ /dev/null
@@ -1,56 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const path = require('path');
-
-module.exports = async (ctx) => {
- const channelId = ctx.params.channelId;
- const embed = !ctx.params.embed;
-
- const response = await got({
- method: 'get',
- url: `http://i.youku.com/i/${channelId}/videos`,
- headers: {
- Host: 'i.youku.com',
- Referer: `http://i.youku.com/i/${channelId}`,
- },
- });
-
- const data = response.data;
- const $ = cheerio.load(data);
- const list = $('.items > .v');
-
- ctx.state.data = {
- title: $('.username').text(),
- link: `http://i.youku.com/i/${channelId}`,
- description: $('.desc').text(),
- item:
- list &&
- list
- .map((index, item) => {
- item = $(item);
- const cover = item.find('.v-thumb img').attr('src');
- const title = item.find('.v-link a').attr('title');
- const $link = item.find('.v-meta-title > a');
- const link = $link.length > 0 ? `https:${$link.attr('href')}` : null;
-
- if (link) {
- const videoId = path.parse(link).name.replace(/^id_/g, '');
- const iframe = ``;
-
- return {
- title,
- description: `
- ${embed ? iframe : ''}
-
-
- `,
- link,
- };
- } else {
- return null;
- }
- })
- .get()
- .filter((item) => item),
- };
-};
diff --git a/lib/v2/youku/channel.js b/lib/v2/youku/channel.js
new file mode 100644
index 000000000..b42844c36
--- /dev/null
+++ b/lib/v2/youku/channel.js
@@ -0,0 +1,56 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const { art } = require('@/utils/render');
+const path = require('path');
+
+module.exports = async (ctx) => {
+ const channelId = ctx.params.channelId;
+ const embed = !ctx.params.embed;
+
+ const response = await got({
+ method: 'get',
+ url: `https://i.youku.com/i/${channelId}/videos`,
+ headers: {
+ Host: 'i.youku.com',
+ Referer: `https://i.youku.com/i/${channelId}`,
+ },
+ });
+
+ const data = response.data;
+ const $ = cheerio.load(data);
+ const list = $('div.videoitem_pack');
+
+ ctx.state.data = {
+ title: $('.username').text(),
+ link: `https://i.youku.com/i/${channelId}`,
+ description: $('.desc').text(),
+ item:
+ list &&
+ list
+ .map((_, item) => {
+ item = $(item);
+ const title = item.find('a.videoitem_videolink').attr('title');
+ const cover = item.find('a.videoitem_videolink > img').attr('src');
+ const $link = item.find('a.videoitem_videolink');
+ const link = $link.length > 0 ? `https:${$link.attr('href')}` : null;
+ const dateText = item.find('p.videoitem_subtitle').text().split('-').length === 2 ? `${new Date().getFullYear()}-${item.find('p.videoitem_subtitle').text()}` : item.find('p.videoitem_subtitle').text();
+ const pubDate = parseDate(dateText);
+
+ return link
+ ? {
+ title,
+ description: art(path.join(__dirname, 'templates/channel.art'), {
+ embed,
+ videoId: path.parse(link).name.replace(/^id_/g, ''),
+ cover,
+ }),
+ link,
+ pubDate,
+ }
+ : null;
+ })
+ .get()
+ .filter((item) => item),
+ };
+};
diff --git a/lib/v2/youku/maintainer.js b/lib/v2/youku/maintainer.js
new file mode 100644
index 000000000..62140a821
--- /dev/null
+++ b/lib/v2/youku/maintainer.js
@@ -0,0 +1,3 @@
+module.exports = {
+ '/channel/:channelId/:embed?': ['xyqfer', 'Fatpandac'],
+};
diff --git a/lib/v2/youku/radar.js b/lib/v2/youku/radar.js
new file mode 100644
index 000000000..401706bf9
--- /dev/null
+++ b/lib/v2/youku/radar.js
@@ -0,0 +1,13 @@
+module.exports = {
+ 'youku.com': {
+ _name: '优酷',
+ i: [
+ {
+ title: '订阅作者',
+ docs: 'https://docs.rsshub.app/multimedia.html#you-ku',
+ source: ['/i/:id'],
+ target: '/youku/channel/:id',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/youku/router.js b/lib/v2/youku/router.js
new file mode 100644
index 000000000..e10ea4401
--- /dev/null
+++ b/lib/v2/youku/router.js
@@ -0,0 +1,3 @@
+module.exports = function (router) {
+ router.get('/channel/:channelId/:embed?', require('./channel'));
+};
diff --git a/lib/v2/youku/templates/channel.art b/lib/v2/youku/templates/channel.art
new file mode 100644
index 000000000..dfde53402
--- /dev/null
+++ b/lib/v2/youku/templates/channel.art
@@ -0,0 +1,5 @@
+{{ if embed }}
+
+{{ /if }}
+
+