【RSS订阅 TO 飞书】除了L站还能订阅其他RSS?没错!一分钟搞定!开整!

昨天完成了L站rss订阅to飞书~
今天有友友联系我说:想订阅其他的RSS能不能实现
YES! 是可以的,怎么实现呢?
怎么搞?直接AI改写!一分钟搞定!

以下提问AI模板(V2EX为例),直接发给GPT即可:

(测试用的GPT-4o,直接成功)

====Linuxdo站rss订阅TO飞书代码开始====
const RSS_URL = 'https://linux.do/latest.rss';
const FEISHU_WEBHOOK_URL = 'https://open.feishu.cn/open-apis/bot/v2/hook/xxxxx';//飞书群机器人Webhook 地址
const COOKIE = '_ga=xxxx; _t=xxxx; _forum_session=xxxx; _ga_xxx=xxxx';//你的linuxdo_cookie~

export default {
  async scheduled(event, env, ctx) {
    try {
      const db = env.linuxdo_whfs;
      const rssResponse = await handleRequest(new Request(RSS_URL));
      const rssText = await rssResponse.text();
      const items = parseRSS(rssText);
      for (let item of items) {
        const alreadySent = await checkIfSent(db, item.Link.url);
        if (!alreadySent) {
          await postToFeishu(item);
          await recordSentUrl(db, item.Link.url);
        }
      }
    } catch (error) {
      console.error('Error in handleScheduledEvent:', error);
    }
  },
};

function parseRSS(rssText) {
  const itemRegex = /<item>(.*?)<\/item>/gs;
  let match, posts = [];
  while ((match = itemRegex.exec(rssText)) && posts.length < 30) {
    const itemContent = match[1];
    const title = itemContent.match(/<title>(.*?)<\/title>/s)[1];
    const creator = itemContent.match(/<dc:creator><!\[CDATA\[(.*?)\]\]><\/dc:creator>/s)[1];
    const link = itemContent.match(/<link>(.*?)<\/link>/s)[1];
    const description = itemContent.match(/<description><!\[CDATA\[(.*?)\]\]><\/description>/s)[1]
      .replace(/ {2,}/g, ' ')
      .replace(/<p><small>.*?">阅读完整话题<\/a><\/p>/s, '')
      .replace(/<[^>]*>/g, '')
      .replace(/^\s*[\r\n]/gm, '')
      .split('\n')
      .slice(0, 10)
      .join('\n');
    const category = itemContent.match(/<category>(.*?)<\/category>/s)[1];
    const pubDate = itemContent.match(/<pubDate>(.*?)<\/pubDate>/s)[1];

    posts.push({
      Title: title,
      Author: creator,
      Description: description,
      Category: category,
      Time: new Date(pubDate).toUTCString(),
      Link: { pc_url: "", android_url: "", ios_url: "", url: link }
    });
  }
  return posts;
}

//其中的template是我做的飞书卡片模板,如果不喜欢可以自己制作一个~替换掉template_id和version即可~
async function postToFeishu(post) {
  await fetch(FEISHU_WEBHOOK_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      msg_type: "interactive",
      card: { type: "template", data: { template_id: "AAq3OTs48BODR", template_version_name: "1.0.2", template_variable: post } }
    })
  });
}

async function handleRequest(request) {
  const modifiedRequest = new Request(RSS_URL, {
    headers: { ...request.headers, 'Cookie': COOKIE },
    method: request.method,
    body: request.body,
    redirect: 'follow'
  });
  const response = await fetch(modifiedRequest);
  return new Response(response.body, { ...response, headers: { ...response.headers, 'Access-Control-Allow-Origin': '*' } });
}

async function checkIfSent(db, url) {
  const query = 'SELECT 1 FROM topics WHERE topic = ?';
  const result = await db.prepare(query).bind(url).first();
  return result ? true : false;
}

async function recordSentUrl(db, url) {
  const query = 'INSERT INTO topics (topic) VALUES (?)';
  await db.prepare(query).bind(url).run();
}

export { handleRequest };
====Linuxdo站rss订阅TO飞书代码结束====

修改需求如下:
1. RSS_URL 改为:https://v2ex.com/index.xml;
2. handleRequest 直接请求,无需cookie;
3. db env使用 v2ex_rss;
4. parseRSS改为适配以下示例格式模板:
=====订阅模板示例内容开始=====
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>V2EX</title>
<subtitle>way to explore</subtitle>

<link rel="alternate" type="text/html" href="https://www.v2ex.com/" />
<link rel="self" type="application/atom+xml" href="https://www.v2ex.com/index.xml" />
<id>https://www.v2ex.com/</id>
<updated>2024-05-19T09:33:56Z</updated>
<rights>Copyright © 2010-2018, V2EX</rights>
<entry>
	<title>[MacBook] 关于 Mac Air 和 Mac Pro 的性能</title>
	<link rel="alternate" type="text/html" href="https://www.v2ex.com/t/1042046#reply0" />
	<id>tag:www.v2ex.com,2024-05-19:/t/1042046</id>
	<published>2024-05-19T09:36:56Z</published>
	<updated>2024-05-19T09:33:56Z</updated>
	<author>
		<name>seekseat</name>
		<uri>https://www.v2ex.com/member/seekseat</uri>
	</author>
	<content type="html" xml:base="https://www.v2ex.com/" xml:lang="en"><![CDATA[
	<p>今天去体验店发现新的 air 非常经验,不再是缓坡式设计,而且非常薄。</p>
<p>有几个问题: 为什么 pro 比 air 厚那么多,厚出来的部分主要是什么元器件导致的。</p>
<p>M2 芯片的 Air ,性能会比 2021 款的 M1 芯片的 Pro 要好吗?</p>
	]]></content>
</entry><entry>
	<title>[路由器] 家庭宽带 ip 固定</title>
	<link rel="alternate" type="text/html" href="https://www.v2ex.com/t/1042045#reply0" />
	<id>tag:www.v2ex.com,2024-05-19:/t/1042045</id>
	<published>2024-05-19T09:32:58Z</published>
	<updated>2024-05-19T09:29:58Z</updated>
	<author>
		<name>GopherRustaceans</name>
		<uri>https://www.v2ex.com/member/GopherRustaceans</uri>
	</author>
	<content type="html" xml:base="https://www.v2ex.com/" xml:lang="en"><![CDATA[
	<p>家里使用电信的宽带,访问公司某个资源时,每次需要同事帮忙加白名单。但是过一段时间 ip 就会变更,需要重新联系同事。</p>
<p>于是有两个疑惑:</p>
<ol>
<li>
<p>有没有什么办法把 IP 固定住?</p>
</li>
<li>
<p>一般多久会更换 ip ?什么操作会触发 ip 的变更?比如我把路由器电源拔掉重新连,会使出口 ip 发生变化吗?</p>
</li>
</ol>
	]]></content>
</entry><entry>
	<title>[问与答] 不懂就问,某音的搬游戏主播</title>
	<link rel="alternate" type="text/html" href="https://www.v2ex.com/t/1042044#reply0" />
	<id>tag:www.v2ex.com,2024-05-19:/t/1042044</id>
	<published>2024-05-19T09:23:13Z</published>
	<updated>2024-05-19T09:23:13Z</updated>
	<author>
		<name>QingquanBaby</name>
		<uri>https://www.v2ex.com/member/QingquanBaby</uri>
	</author>
	<content type="html" xml:base="https://www.v2ex.com/" xml:lang="en"><![CDATA[
	搬游戏什么的,什么操作,是割韭菜吗
	]]></content>
</entry><entry>
	<title>[iPhone] 是现在买 iPhone15Pro 还是等 16 出来?</title>
	<link rel="alternate" type="text/html" href="https://www.v2ex.com/t/1042043#reply0" />
	<id>tag:www.v2ex.com,2024-05-19:/t/1042043</id>
	<published>2024-05-19T09:13:50Z</published>
	<updated>2024-05-19T09:11:50Z</updated>
	<author>
		<name>t202201</name>
		<uri>https://www.v2ex.com/member/t202201</uri>
	</author>
	<content type="html" xml:base="https://www.v2ex.com/" xml:lang="en"><![CDATA[
	最近京东打折,iPhone15Pro 256G 7000 ,iPhone15 256G 5649 ,查价格似乎都是目前最低价了。但是不知道 16 会不会有很大的更新,有点点期待一手 iPhone 对 ai 的接入。<br /><br />之前的 xr 用了 5 年多了,前段时间升级系统后,实在是太慢了,所以想换个。<br /><br />如果是各位大佬,是等等还是现在就买?
	]]></content>
</entry><entry>
	<title>[NAS] 22t 西部数据 elements,含税包邮¥2960 划算吗?</title>
	<link rel="alternate" type="text/html" href="https://www.v2ex.com/t/1042042#reply3" />
	<id>tag:www.v2ex.com,2024-05-19:/t/1042042</id>
	<published>2024-05-19T09:10:13Z</published>
	<updated>2024-05-19T09:28:37Z</updated>
	<author>
		<name>kuanos</name>
		<uri>https://www.v2ex.com/member/kuanos</uri>
	</author>
	<content type="html" xml:base="https://www.v2ex.com/" xml:lang="en"><![CDATA[
	<p>大家感觉呢,最近苦于没有空间了</p>
	]]></content>
</entry><entry>
	<title>[程序员] 谷歌搜索结果展示是不是又回到了原来的分页形式?</title>
	<link rel="alternate" type="text/html" href="https://www.v2ex.com/t/1042040#reply1" />
	<id>tag:www.v2ex.com,2024-05-19:/t/1042040</id>
=====订阅模板示例内容结束=====

主要内容解释:

  1. RSS_URL 改为:<rss订阅链接>;
  2. handleRequest <有cookie不修改 / 直接请求,无需cookie>;
  3. db env使用 <D1数据库名称>;
  4. parseRSS改为适配以下示例格式模板:<rss订阅从第一行开始复制,需包含大部分段落>

AI回复效果测试通过

下附AI生成后的代码(V2EX v2ex.com/index.xml 订阅):
数据库名称为: v2ex_rss,
其他与Linuxdo订阅(Linuxdo新话题推送到tg?不!推送飞书!! - 软件分享 - LINUX DO)操作一致


const RSS_URL = 'https://v2ex.com/index.xml';
const FEISHU_WEBHOOK_URL = 'https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx'; // 飞书群机器人Webhook 地址

export default {
  async scheduled(event, env, ctx) {
    try {
      const db = env.v2ex_rss;
      const rssResponse = await handleRequest(new Request(RSS_URL));
      const rssText = await rssResponse.text();
      const items = parseRSS(rssText);
      for (let item of items) {
        const alreadySent = await checkIfSent(db, item.Link.url);
        if (!alreadySent) {
          await postToFeishu(item);
          await recordSentUrl(db, item.Link.url);
        }
      }
    } catch (error) {
      console.error('Error in handleScheduledEvent:', error);
    }
  },
};

function parseRSS(rssText) {
  const entryRegex = /<entry>(.*?)<\/entry>/gs;
  let match, posts = [];
  while ((match = entryRegex.exec(rssText)) && posts.length < 30) {
    const entryContent = match[1];
    const title = entryContent.match(/<title>(.*?)<\/title>/s)[1];
    const link = entryContent.match(/<link[^>]* href="(.*?)"/s)[1];
    const published = entryContent.match(/<published>(.*?)<\/published>/s)[1];
    const author = entryContent.match(/<author>.*?<name>(.*?)<\/name>.*?<\/author>/s)[1];
    const content = entryContent.match(/<content[^>]*><!\[CDATA\[(.*?)\]\]><\/content>/s)[1]
      .replace(/<[^>]*>/g, '')
      .replace(/^\s*[\r\n]/gm, '')
      .split('\n')
      .slice(0, 10)
      .join('\n');

    posts.push({
      Title: title,
      Author: author,
      Description: content,
      Time: new Date(published).toUTCString(),
      Link: { pc_url: "", android_url: "", ios_url: "", url: link }
    });
  }
  return posts;
}

async function postToFeishu(post) {
  await fetch(FEISHU_WEBHOOK_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      msg_type: "interactive",
      card: { type: "template", data: { template_id: "AAq3OTs48BODR", template_version_name: "1.0.2", template_variable: post } }
    })
  });
}

async function handleRequest(request) {
  const response = await fetch(RSS_URL, {
    headers: { ...request.headers },
    method: request.method,
    body: request.body,
    redirect: 'follow'
  });
  return new Response(response.body, { ...response, headers: { ...response.headers, 'Access-Control-Allow-Origin': '*' } });
}

async function checkIfSent(db, url) {
  const query = 'SELECT 1 FROM topics WHERE topic = ?';
  const result = await db.prepare(query).bind(url).first();
  return result ? true : false;
}

async function recordSentUrl(db, url) {
  const query = 'INSERT INTO topics (topic) VALUES (?)';
  await db.prepare(query).bind(url).run();
}

export { handleRequest };

替代你的不是AI,是善用AI的人

15 个赞

支持

1 个赞

感谢分享

1 个赞

mark,感谢分享,学习了

1 个赞

这个还不错哦~~ 推荐个win版的 飞书 吧

不错哦

太酷了!

有没有非cookie方式订阅L站,类似Tiny Tiny RSS的订阅,是不是只能走RssHub 本地实例中转了。