cover

使用RSSHub自制Matataki RSS源 - Part 2

A

[TOC]

更新记录

  1. 2020-10-10 初稿 QmUGbHSqSrMgKUwKHFkeZjovrF9NXv2auEHbLFgbZtsyvP
  2. 2020-10-13 增加系列目录 QmT7tPygKSpP5jrUh87H7T6UVoxXXCy3qzax3tB2mmmG76
  3. 2020-10-14 调整用语;实现RSSHub Radar规则;新增主题订阅源实现

系列目录

概述

上一篇文章介绍了使用RSSHub自制Matataki RSS源的方法。实际使用一段时间后,发现了一些痛点,尝试解决,并做个记录

存在问题

代码重复

首先对之前的实现做一下分析:

通过对比几个路由脚本实现,我们会发现,整体逻辑其实都一样:

  1. 调用API,获取到数据
  2. 把数据转换为RSS Feed格式来消费

用到的API语义上都是各种get,只是url不同;
上述API的条目都是对应Matataki上的文章,所以item的格式也都是非常类似的,Feed Item需要的字段基本都能直接拿到;
IPFS版本则是因为需要获取Hash,中间需要多调一个API,这段代码都是一样的,可以很简单地提取出函数。

Feed标题重复

Fan票关联文章这类Feed,之前的方案是在文章标题里加上了作者昵称 ${item.title} - ${item.nickname},通过作者来区分来源。这样文章是可以区分开了,但是订阅源多了还是不好管理。最好每个订阅源的title都带上Fan票的名称,即 瞬Matataki - ${tokenName}关联文章 这种格式

Feed缓存

RSSHub本身是有缓存的,RSS Reader本身也有影响,可能不会把只是querystring不同的部分当成不同的订阅源,两者共同作用下只根据querystring来区分数据的API不能直接套查询条件,要在url上下点功夫

Feed Link不准确

官网版Feed之前统一连到首页文章去了,针对具体语义找更合适的url

具体实现

按照重构的思路,把各种通用逻辑封装成一个工具:

lib/utils/matataki-utils.js


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

/**
 *  Matataki 官网地址
 */
const MATATAKI_WEB_URL = 'https://www.matataki.io/';

/**
 *  IPFS网关的URL。可以换成其他公共网关,也可以换成自建的网关地址
 */
const IPFS_GATEWAY_URL = 'https://ipfs.io';

/**
 * 以`get` 方式调用Matataki API的简单封装
 *
 * @param {string} url
 */
async function get(url) {
    return await got({
        method: 'get',
        url: url,
        headers: {
            Referer: MATATAKI_WEB_URL,
        },
    });
}

exports.IPFS_GATEWAY_URL = IPFS_GATEWAY_URL;

exports.get = get;

/**
 * 获取用户信息昵称
 *
 * @param {number} userId
 */
exports.getUserNickname = async (userId) => {
    try {
        const userInfoResponse = await get(`https://api.smartsignature.io/user/${userId}`);
        return `${userInfoResponse.data.data.nickname}`;
    }
    catch (err) {
        return '';
    }
};


/**
 * 获取Fan票名称
 *
 * @param {number} tokenId
 */
exports.getTokenName = async (tokenId) => {
    try {
        const tokenInfoResponse = await get(`https://api.smartsignature.io/minetoken/${tokenId}`);
        return `${tokenInfoResponse.data.data.token.name}`;
    }
    catch (err) {
        return '';
    }
};

/**
 * 获取Matataki文章在IPFS上的Hash
 *
 * @param {number} postId
 */
exports.getPostIpfsHtmlHash = async (postId) => {
    const ipfsInfoResponse = await get(`https://api.smartsignature.io/p/${postId}/ipfs`);
    return `${ipfsInfoResponse.data.data[0].htmlHash}`;
};

/**
 * 将Matataki文章条目转为指向IPFS网关的RSS订阅源条目
 *
 * @param {Object} item
 */
exports.postToIpfsFeedItem = async (item) => {

    const ipfsHtmlHash = await this.getPostIpfsHtmlHash(item.id);

    return {
        title: `${item.title} - ${item.nickname}${item.token_name ? ' $' + item.token_name : ''}`,
        description: item.short_content,
        link: `${IPFS_GATEWAY_URL}/ipfs/${ipfsHtmlHash}`,
        guid: ipfsHtmlHash,
    };

};

/**
 * 将Matataki文章条目转为指向官网的RSS订阅源条目
 *
 * @param {Object} item
 */
exports.postToFeedItem = (item) => ({
    title: `${item.title} - ${item.nickname}`,
    description: item.short_content,
    link: `https://www.matataki.io/p/${item.id}`,
});

/**
 * 获取文章列表并转为IPFS Feed Item 数组
 *
 * @param {string} url Matataki文章相关API的url
 */
exports.getPostIpfsFeedItems = async (url) => {
    const response = await get(url);
    return await Promise.all(response.data.data.list.map(this.postToIpfsFeedItem));
};

/**
 * 获取文章列表并转为Feed Item数组
 *
 * @param {string} url Matataki文章相关API的url
 */
exports.getPostFeedItems = async (url) => {
    const response = await get(url);
    return response.data.data.list.map(this.postToFeedItem);
};


各个Feed都基于这个来实现,每个Feed只关注自己需要提供的内容

热门作品

官网版

lib/routes/matataki/posts/scoreranking.js

const matatakiUtils = require('@/utils/matataki-utils');

module.exports = async (ctx) => {

    const items = await matatakiUtils.getPostFeedItems(`https://api.smartsignature.io/posts/scoreRanking`);

    ctx.state.data = {
        title: `瞬Matataki - 热门作品`,
        link: `https://www.matataki.io/article/`,
        description: `瞬Matataki - 热门作品`,
        item: items
    };
};

IPFS版

lib/routes/ipfs/matataki/posts/scoreranking.js

const matatakiUtils = require('@/utils/matataki-utils');

module.exports = async (ctx) => {

    const items = await matatakiUtils.getPostIpfsFeedItems(`https://api.smartsignature.io/posts/scoreRanking`);

    ctx.state.data = {
        title: `瞬Matataki - 热门作品(IPFS)`,
        link: matatakiUtils.IPFS_GATEWAY_URL,
        description: `瞬Matataki - 热门作品(IPFS)`,
        item: items,
    };
};

Fan票关联作品

官网版

lib/routes/matataki/minetoken/related.js

const matatakiUtils = require('@/utils/matataki-utils');

module.exports = async (ctx) => {

    const id = ctx.params.id;
    const querystring = ctx.request.querystring;

    const tokenName = await matatakiUtils.getTokenName(id);
    const items = await matatakiUtils.getPostFeedItems(`https://api.smartsignature.io/minetoken/${id}/related?${querystring}`);

    ctx.state.data = {
        title: `瞬Matataki - ${tokenName ? tokenName : 'Fan票'}关联作品`,
        link: `https://www.matataki.io/token/${id}/circle`,
        description: `瞬Matataki - ${tokenName ? tokenName : 'Fan票'}关联作品`,
        allowEmpty: true,
        item: items,
    };

};

大体上就是填模板

IPFS版

lib/routes/ipfs/matataki/minetoken/related.js

const matatakiUtils = require('@/utils/matataki-utils');

module.exports = async (ctx) => {

    const id = ctx.params.id;
    const querystring = ctx.request.querystring;

    const tokenName = await matatakiUtils.getTokenName(id);
    const items = await matatakiUtils.getPostIpfsFeedItems(`https://api.smartsignature.io/minetoken/${id}/related?${querystring}`);

    ctx.state.data = {
        title: `瞬Matataki - ${tokenName ? tokenName : 'Fan票'}关联作品(IPFS)`,
        link: matatakiUtils.IPFS_GATEWAY_URL,
        description: `瞬Matataki - ${tokenName ? tokenName : 'Fan票'}关联作品(IPFS)`,
        allowEmpty: true,
        item: items,
    };

};

高度相似,Feed里title link description的不同算是刻意为之的

作者创作

追更具体的作者也是很常见的需求,这里就基于新版本的方式实现一下

调用API

GET https://api.smartsignature.io/posts/timeRanking?author=${authorId}

路由配置

这个authorId在订阅源地址里要放在path部分,否则同时订阅多个作者的时候可能会有问题

lib/router.js里增加的路由信息如下:

router.get('/matataki/user/:authorId/posts', require('./routes/matataki/posts/author'));

路由实现

lib/routes/matataki/posts/author.js

const matatakiUtils = require('@/utils/matataki-utils');

module.exports = async (ctx) => {

    const authorId = ctx.params.authorId;

    const authorName = await matatakiUtils.getUserNickname(authorId);

    const items = await matatakiUtils.getPostFeedItems(`https://api.smartsignature.io/posts/timeRanking?author=${authorId}`);

    ctx.state.data = {
        title: `瞬Matataki - ${authorName}作品`,
        link: `https://www.matataki.io/user/${authorId}`,
        description: `瞬Matataki - ${authorName}作品`,
        item: items,
    };
};

和Fan票类似,为了区分不同的作者订阅源,在titledescription里标明了作者。

IPFS版也只需要把getPostFeedItems换成getIpfsPostFeedItems就可以用了,Feed的link也可以像上面的IPFS版一样换成matatakiUtils.IPFS_GATEWAY_URL

效果

https://ssimg.frontenduse.top/article/2020/10/10/2c249f78f4387c0711b48f5b89a14a6d.png

订阅源对应的作者变得很清楚了

https://ssimg.frontenduse.top/article/2020/10/10/5cc46383315593a13bad9e825e74bd7d.png

这实质就成为一个收件箱,熟悉GTD等方法的,可以把这个纳入自己的工作流[1]

主题作品

基于tag来订阅

调用API

GET https://api.smartsignature.io/posts/getPostByTag?pagesize=20&tagid=${tagId}&extra=short_content&orderBy=hot_score&order=desc&page=1

路由配置

这个tagId在订阅源地址里要放在path部分,否则同时订阅多个主题的时候可能会有问题

lib/router.js里增加的路由信息如下:

router.get('/matataki/tags/:tagId/posts', require('./routes/matataki/posts/tag'));

路由实现

lib/routes/matataki/posts/tag.js

const matatakiUtils = require('@/utils/matataki-utils');

module.exports = async (ctx) => {

    const tagId = ctx.params.tagId;
    const tagName = ctx.request.query.name;

    const items = await matatakiUtils.getPostFeedItems(`https://api.smartsignature.io/posts/getPostByTag?pagesize=20&tagid=${tagId}&extra=short_content&orderBy=hot_score&order=desc&page=1`);

    ctx.state.data = {
        title: `瞬Matataki #${tagName}`,
        link: `https://www.matataki.io/tags/${tagId}`,
        description: `瞬Matataki #${tagName}`,
        item: items,
    };
};

和Fan票类似,为了区分不同的主题订阅源,在titledescription里标明了主题名称。

IPFS版也只需要把getPostFeedItems换成getIpfsPostFeedItems就可以用了,Feed的link也可以像上面的IPFS版一样换成matatakiUtils.IPFS_GATEWAY_URL

效果

https://ssimg.frontenduse.top/article/2020/10/14/e83d55778f9da1c1b36e2aee160c42b1.png

RSSHub Radar[2]

开发环境直接在Radar的源文件里添加规则

src/js/common/radar-rules.js

export default {
    'matataki.io': {
        _name: 'matataki',
        www: [
            {
                title: '最热作品',
                docs: 'https://docs.rsshub.app/new-media.html#matataki',
                source: ['/article', '/article/latest'],
                target: '/matataki/posts/scoreranking'
            },
            {
                title: '最新作品',
                docs: 'https://docs.rsshub.app/new-media.html#matataki',
                source: ['/article', '/article/latest'],
                target: '/matataki/posts/timeranking'
            },
            {
                title: '作者创作',
                docs: 'https://docs.rsshub.app/new-media.html#matataki',
                source: '/user/:uid',
                target: (params) => `/matataki/user/${params.uid}/posts`
            },
            {
                title: 'Fan票关联作品',
                docs: 'https://docs.rsshub.app/new-media.html#matataki',
                source: ['/token/:tid', '/token/:tid/circle'],
                target: (params) => `/matataki/minetoken/${params.tid}/related/3`
            },
            {
                title: '主题作品',
                docs: 'https://docs.rsshub.app/new-media.html#matataki',
                source: ['/tags/:tagId'],
                target: (params,url) => `/matataki/tags/${params.tagId}/posts?name=${new URL(url).searchParams.get('name')}`
            }
        ]

    },
    ...
    
}    

,‘mpm run build'生成新的dist后,浏览器加载扩展即可食用

最热作品&最新作品

在站点首页就可以检测到,如:https://www.matataki.io/article/

https://ssimg.frontenduse.top/article/2020/10/14/4726886aa7a823337b32b904061248ca.png

Fan票关联作品

在Fan票主页就可以检测到,如:https://www.matataki.io/token/22

https://ssimg.frontenduse.top/article/2020/10/14/0c399c7661c385e8afcc9b0cbba89e08.png

作者创作

在作者主页就可以检测到,如: https://www.matataki.io/user/2421

https://ssimg.frontenduse.top/article/2020/10/14/3132f2fef7f196691c3dfa264926ff9b.png

主题作品

首先在首页找到热门主题,选其中一个tag打开即可检测到,也可以“查看全部”后选择tag打开,如: https://www.matataki.io/tags/265?name=智能合约

https://ssimg.frontenduse.top/article/2020/10/14/395c7d9be9172507e1fc1147062cf850.png

连载类文章设置相同tag的话就可以从一个入口追了

代码仓库

Github仓库地址

和上次相比已经变了不少,感觉还能优化点什么,还是提交到仓库后继续打理下去比较好。

本文涉及的代码修改在feature/matataki分支。

見えるけど見えないもの

下一步

打算把路由文档和RSShub Radar扩展的部分搞定,订阅起来就不用手动找id拼url了,使用起来会更顺滑。

参考资料


  1. 收件箱管理——清空你的收件箱 ↩︎

  2. RSSHub Radar 是 RSSHub 的衍生项目,她是一个可以帮助你快速发现和订阅当前网站 RSS 和 RSSHub 的浏览器扩展 万物皆可 RSS ↩︎

本文发布于瞬matataki, 本文使用 知识共享 署名-非商业性使用-相同方式共享 4.0 协议 请遵守协议许可进行转载

免责声明:本文由用户「WhyYouAre」上传发布,内容为作者独立观点。不代表瞬Matataki立场,不构成投资建议,请谨慎对待。

Loading...
Price:
暂无价格
简 介:

Nothing

已持有:

0

喜欢就打赏Fan票吧~

avatar
0/500
评论0 打赏0