feat(route): add vimeo with more (#7604)

* add vimeo with more

* refactor: migrate to v2

Co-authored-by: TonyRL <TonyRL@users.noreply.github.com>
This commit is contained in:
MisteryMonster
2022-02-22 03:07:02 +08:00
committed by GitHub
co-authored by TonyRL
parent 68ba5b28bb
commit 0c7aaf8a5a
8 changed files with 301 additions and 0 deletions
+21
View File
@@ -336,6 +336,27 @@ This route requires Twitter token's corresponding id, therefore it's only availa
<RouteEn author="sakamossan" example="/twitter/trends/23424856" path="/twitter/trends/:woeid?" :paramsDesc="['Yahoo! Where On Earth ID. default to woeid=1 (World Wide)']" radar="1" rssbud="1"/>
## Vimeo
### User Profile
<RouteEn author="MisteryMonster" example="/vimeo/user/filmsupply/picks" path="/vimeo/user/:username/:cat?" :paramsDesc="['In this example [https://vimeo.com/filmsupply](https://vimeo.com/filmsupply) is `filmsupply`', 'deafult for all latest videos, others categories in this example such as `Docmentary`, `Narrative`, `Drama`. Set `picks` for promote orders, just orderd like web page. When `picks` added, published date won\'t show up']">
::: tip Special category name attention
Some of the categories contain slash like `3D/CG` , must change the slash `/` to the vertical bar`|`.
:::
</RouteEn>
### Channel
<RouteEn author="MisteryMonster" example="/vimeo/channel/bestoftheyear" path="/vimeo/channel/:channel" :paramsDesc="['channel name can get from url like `bestoftheyear` in [https://vimeo.com/channels/bestoftheyear/videos](https://vimeo.com/channels/bestoftheyear/videos) .']" radar="1"/>
### Category
<RouteEn author="MisteryMonster" example="/vimeo/category/documentary/staffpicks" path="/vimeo/category/:category/:staffpicks?" :paramsDesc="['Category name can get from url like `documentary` in [https://vimeo.com/categories/documentary/videos](https://vimeo.com/categories/documentary/videos) ', 'type `staffpicks` to sort with staffpicks']" radar="1"/>
## YouTube
::: tip Tiny Tiny RSS users please notice
+26
View File
@@ -695,6 +695,32 @@ Tiny Tiny RSS 会给所有 iframe 元素添加 `sandbox="allow-scripts"` 属性
<Route author="sakamossan" example="/twitter/trends/23424856" path="/twitter/trends/:woeid?" :paramsDesc="['Where On Earth ID. 默认 woeid=1 (World Wide)']" radar="1" rssbud="1"/>
## Vimeo
### 用户页面
<Route author="MisteryMonster" example="/vimeo/user/filmsupply/picks" path="/vimeo/user/:username/:cat" :paramsDesc="['用户名或者 uid,用户名可从地址栏获得,如 [https://vimeo.com/filmsupply](https://vimeo.com/filmsupply) 中为 `filmsupply`', '分类根据不同的用户页面获得,例子中有`Docmentary`,`Narrative`,`Drama`等。填入 `picks` 为和首页一样的推荐排序,推荐排序下没有发布时间信息']" radar="1">
::: tip 请注意带有斜杠的的标签名
如果分类名带有斜杠符号的如 `3D/CG` 时,必须把斜杠`/`转成 `|`
:::
</Route>
### 频道页面
<Route author="MisteryMonster" example="/vimeo/channel/bestoftheyear" path="/vimeo/channel/:channel" :paramsDesc="['channel 名可从 url 获得,如 [https://vimeo.com/channels/bestoftheyear/videos](https://vimeo.com/channels/bestoftheyear/videos) 中的 `bestoftheyear`']" radar="1">
</Route>
### 分类页面
<Route author="MisteryMonster" example="/vimeo/category/documentary/staffpicks" path="/vimeo/category/:category/:staffpicks?" :paramsDesc="['主分类名可从 url 获得,如 [https://vimeo.com/categories/documentary/videos](https://vimeo.com/categories/documentary/videos) 中的 `documentary`。', '填入 `staffpicks` 则按 staffpicks 排序']" radar="1">
</Route>
## VueVlog
### 用户
+64
View File
@@ -0,0 +1,64 @@
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 { category, staffpicks } = ctx.params;
const categoryparams = category;
let sortparams = '&direction=desc&sort=date';
let feedtitle = category;
if (staffpicks && staffpicks !== 'staffpicks') {
return;
}
if (staffpicks) {
sortparams += '&filter=conditional_featured';
feedtitle += `: ${category} staffpicks`;
}
const url = `https://api.vimeo.com/categories/${categoryparams}/videos?page=1&per_page=18${sortparams}`;
const tokenresponse = await got({
method: 'get',
url: 'https://vimeo.com/_rv/viewer',
});
const VimeoAuthorization = tokenresponse.data.jwt;
const response = await got({
method: 'get',
url,
headers: {
Authorization: `jwt ${VimeoAuthorization}`,
},
});
const vimeojs = response.data.data;
const feedlink = `https://vimeo.com/categories/${category}/videos/sort:latest`;
const feedlinkstaffpicks = '?staffpicked=ture';
const feedDescription = await ctx.cache.tryGet(feedlink + (staffpicks ? feedlinkstaffpicks : ''), async () => {
const response = await got({
url: feedlink + (staffpicks ? feedlinkstaffpicks : ''),
});
const description = cheerio.load(response.data);
return description('meta[name="description"]').attr('content');
});
ctx.state.data = {
title: `${feedtitle} | Vimeo category`,
link: feedlink + (staffpicks ? feedlinkstaffpicks : ''),
description: feedDescription,
item: vimeojs.map((item) => ({
title: item.name,
description: art(path.join(__dirname, 'templates/description.art'), {
videoUrl: item.uri.replace(`/videos`, ''),
vdescription: item.description ? item.description : '',
}),
pubDate: parseDate(item.created_time),
link: item.link,
author: item.user.name,
})),
};
};
+72
View File
@@ -0,0 +1,72 @@
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 channel = ctx.params.channel;
const url = `https://vimeo.com/channels/${channel}/videos`;
const page1 = await got({
method: 'get',
url: `${url}/page:1/sort:date/format:detail`,
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
});
const page2 =
channel === `bestoftheyear`
? await got({
method: 'get',
url: `${url}/page:2/sort:date/format:detail`,
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
})
: '';
const pagedata = page1.data.concat(page2.data);
const $ = cheerio.load(pagedata);
const list = $('ol li.clearfix');
const description = await Promise.all(
list.get().map((item) => {
item = $(item);
const link = item.find('.more').attr('href');
return ctx.cache.tryGet(link, async () => {
const response2 = await got({
method: 'get',
url: `https://vimeo.com${link}/description?breeze=1`,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) ',
},
});
const articledata = response2.data;
const $2 = cheerio.load(articledata);
$2('span').remove();
return $2.html();
});
})
);
ctx.state.data = {
title: `${channel} | Vimeo channel`,
link: url,
item: list
.map((index, item) => {
item = $(item);
const title = item.find('.title a').text();
const author = item.find('.meta a').text();
return {
title,
description: art(path.join(__dirname, 'templates/description.art'), {
videoUrl: item.find('.more').attr('href'),
vdescription: description[index] ? description[index] : '',
}),
pubDate: parseDate(item.find('time').attr('datetime')),
link: `https://vimeo.com${item.find('.more').attr('href')}`,
author,
};
})
.get(),
};
};
+33
View File
@@ -0,0 +1,33 @@
module.exports = {
'vimeo.com': {
_name: 'Vimeo',
'.': [
{
title: 'User videos',
docs: 'https://docs.rsshub.app/social-media.html#vimeo-yong-hu-ye-mian',
source: '/:username/',
target: (params, url, document) => {
const uid = document && document.querySelector('html').innerHTML.match(/app.vimeo.com\/users\/([0-9]+)/)[1];
return uid ? `/vimeo/user/${uid}` : '';
},
},
{
title: 'User Video Category',
docs: 'https://docs.rsshub.app/social-media.html#vimeo-yong-hu-ye-mian',
source: '/',
},
{
title: 'Channel',
docs: 'https://docs.rsshub.app/social-media.html#vimeo-channel',
source: ['/channels/:channel', '/channels/:channel/videos', '/channels/:channel/videos/:sort/:format'],
target: '/vimeo/channel/:channel',
},
{
title: 'Category',
docs: 'https://docs.rsshub.app/social-media.html#vimeo-category',
source: ['/categories/:category', '/categories/:category/:subcategory', '/categories/:category/:subcategory/videos'],
target: (params) => `/vimeo/category/:category${params.subcategory ? `/` + params.subcategory : ''}`,
},
],
},
};
+5
View File
@@ -0,0 +1,5 @@
module.exports = (router) => {
router.get('/category/:category/:staffpicks?', require('./category'));
router.get('/channel/:channel', require('./channel'));
router.get('/user/:username/:cat?', require('./usr-videos'));
};
+4
View File
@@ -0,0 +1,4 @@
<iframe width="640" height="360" src="https://player.vimeo.com/video{{ videoUrl }}" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
{{ if vdescription }}
<p>{{@ vdescription }}</p>
{{ /if }}
+76
View File
@@ -0,0 +1,76 @@
const got = require('@/utils/got');
const { parseDate } = require('@/utils/parse-date');
const { art } = require('@/utils/render');
const path = require('path');
module.exports = async (ctx) => {
const tokenresponse = await got({
method: 'get',
url: 'https://vimeo.com/_rv/viewer',
});
const VimeoAuthorization = tokenresponse.data.jwt;
const { username, cat } = ctx.params;
const profileresponse = await got({
method: 'get',
url: `https://api.vimeo.com/users/${username}?fields=name,gender,bio,uri,link,categories&fetch_user_profile=1`,
headers: {
Authorization: `jwt ${VimeoAuthorization}`,
},
});
const profilesjs = profileresponse.data;
const catjs = profileresponse.data.categories;
let catword;
if (cat && catjs.length > 0) {
for (let s = 0; s < catjs.length; s++) {
if (decodeURIComponent(cat).replace('|', '/') === catjs[s].name) {
catword = catjs[s].word;
}
}
}
let urlfilter = `&filter=category&filter_category=${catword}`;
if (!cat) {
urlfilter = '';
}
if (!catword && cat && cat !== 'picks') {
return '';
}
const picked = cat && cat === 'picks';
const Vimeocat = `${profilesjs.uri}/videos?fields=name,uri,description,created_time&include_videos=1&page=1&per_page=10${urlfilter}`;
const Vimeoallpicks = `/users/${username}/profile_sections?fields=videos.data.clip.name,videos.data.clip.uri,videos.data.clip.description,videos.data.clip.created_time&include_videos=1&badge=1&page=1&per_page=10`;
const contentresponse = await got({
method: 'get',
url: `https://api.vimeo.com${picked ? Vimeoallpicks : Vimeocat}`,
headers: {
Authorization: `jwt ${VimeoAuthorization}`,
},
});
const vimeojs = picked ? contentresponse.data.data[0].videos.data : contentresponse.data.data;
ctx.state.data = {
title: `${profilesjs.name} ${catword ? cat.replace('|', '/') : ''} ${picked ? 'picks' : ''} | Vimeo `,
link: profilesjs.link,
description: profilesjs.bio,
item: vimeojs.map((item) => {
const vdescription = picked ? item.clip.description : item.description;
return {
title: picked ? item.clip.name : item.name,
description: art(path.join(__dirname, 'templates/description.art'), {
videoUrl: picked ? item.clip.uri.replace('/videos', '') : item.uri.replace('/videos', ''),
vdescription: vdescription ? vdescription.replace(/\n/g, '<br>') : '',
}),
pubDate: parseDate(picked || cat ? '' : item.created_time),
link: `https://vimeo.com${picked ? item.clip.uri.replace('videos/', '') : item.uri.replace('videos/', '')}`,
author: profilesjs.name,
};
}),
};
};