Reddit是一个了解网络开发新闻的好地方,如果你像我一样,你可能会关注r/node或r/javascript等子reddits。我最近发现了一个很好的方法,只用我的JavaScript知识就可以建立一个Zapier Reddit集成--这样我就可以在我的团队频道中分享那些流行的Reddit帖子。
在这篇文章中,你会学到。
- 如何建立一个Slack机器人集成。
- 如何在Zapier中创建触发器和行动工作流程,将信息发布到Slack频道。
- 如何使用Reddit API密钥来访问帖子,使用本地Reddit访问令牌和刷新令牌。
- 如何使用匿名JSON端点访问Reddit帖子。
- 编写JavaScript代码(与Node.js版本10兼容,注意是End of Life),用
node-fetchHTTP客户端来获取Reddit信息。
你能用Slack机器人做什么?
本教程教你如何用JavaScript编写Slack机器人,但Zapier功能丰富的API生态系统允许你将许多其他信息源连接到Slack机器人的API。虽然这个Slack机器人教程侧重于JavaScript,但如果你把你的Node.js应用程序托管在云端,你也可以用Zapier的HTTP网络钩子编写一个Slack机器人Node.js应用程序。
构建一个Zapier Reddit集成来处理新的趋势性话题
什么是Zapier?
Zapier是一个自动化平台,它允许你与许多其他平台集成,以连接它们并产生一个工作流程。它主要用于API和原生集成,当这些在Zapier市场上可用时,但它进一步闪耀,为你提供集成点的原始输入和输出,并允许你通过代码定制工作流程的过程。
为了促进Slack机器人的集成,我们将使用Zapier,它已经有了自己与Slack的原生集成--这意味着我们不需要将我们的机器人托管在专用服务器中,也不需要创建另一个单独的Slack机器人集成。
既然我们有了Slack机器人与Zapier的集成,我们的下一步将是。
- 定义一个集成运行的时间表。这可以是一个经常性的时间表,其中Zapier任务将启动并开始处理。
- 在Zapier中定义一个自定义的JavaScript代码任务,从Reddit的JSON端点获取我们感兴趣的趋势话题。
- 根据我们的喜好对趋势话题进行格式化,并通过Zapier内置的原生Slack机器人集成,将其发送到Slack频道。
在Zapier的工作流程界面中,整个过程看起来像。

触发器:Zapier的Schedule中的每周
我们首先要为Zapier工作流程设置循环时间表。具体来说,我选择了每周一在UTC时间上午8点运行它。

如何实现Slack消息的自动化?
在这个Slack机器人教程中,我们选择了使用由Zapier触发的及时计划。然而,Zapier API平台有许多其他触发器,可以驱动Slack自动化。一些例子是。Twitter提及、Google Sheets更新、Google日历事件更新、RSS订阅更新,以及其他一些你可以插入Slack机器人的JavaScript自动化。你甚至可以将Snyk安全通知自动化,用于你的团队的漏洞追踪
行动:通过Zapier在代码中运行JavaScript
现在我们已经定义了基于时间的触发器来启动工作流程,我们可以开始创建行动来执行一些任务。Zapier集成允许我们连接从这些任务中处理的数据,并将其送入链中的下一个动作。
选择一个Run JavaScript in Code by Zapier 的行动类型。在Event 配置中,选择Run JavaScript 。最初的设置应该如下。

然后,展开设置行动配置,在这里我们将添加相关的JavaScript代码,从Reddit API端点获取我们的趋势主题的信息。
如何使用Reddit API密钥
有几种方法来检索Reddit新闻。我们将介绍两种方法来接收有趣的Reddit线程的更新。
- 使用Reddit API密钥,这需要注册一个Reddit用户账户。
- 使用一个公开可用的Reddit API端点。
如果你只需要读取subreddits和趋势帖子,请使用更简单的工作流程,不涉及Reddit oAuth API工作流程--并跳到本章Reddit API访问的第二部分。
注册Reddit API密钥
首先导航到Reddit API应用偏好,点击屏幕底部的Create an app 。然后,输入你的API使用案例的信息。你需要将应用程序的类型设置为webapp ,并提供一个重定向URI来处理访问令牌。

然后你将收到你的ClientID 和ClientSecret ,你可以用它来进行API调用。如果你不确定如何查询Reddit API和通过Reddit oAuth工作流程,请查看其他入门教程,如关于搜刮Reddit的这篇教程。
值得注意的是,你应该通读Reddit的API访问条款,以熟悉你必须满足的Reddit API规则和条件。
Reddit API的JavaScript例子
我们将专注于使用JavaScript来获取有趣的Reddit线程。要做到这一点,我们需要上面提到的ClientID 和ClientSecret 凭证,以及refresh_token 值,如果你选择了创建一个永久性的Reddit oAuth访问令牌,那么这个值就存在。
下面是一个Reddit API密钥的好例子,它可以使用本地JavaScript代码查询subreddit帖子。用上面提到的Reddit凭证替换下面的ABCD 文本,以使代码片段正常运行。
js
// start -- get access token
const clientId = ‘ABCD’;
const clientSecret = ABCD’;
const dataSecrets = `${clientId}:${clientSecret}`;
const text = Buffer.from(dataSecrets).toString("base64");
var url = new URL('https://www.reddit.com/api/v1/access_token');
var params = {grant_type: 'refresh_token', refresh_token: ‘ABCD'};
url.search = new URLSearchParams(params).toString();
const settings = {
method: 'POST',
headers: {
'User-Agent': 'query-api 1.0',
'Accept': 'application/json',
'Authorization': `Basic ${text}`,
},
credentials: 'omit'
};
const res = await fetch(url.href, settings);
const body = await res.json();
const accessToken = body.access_token;
// -----------------------------------------------------
// make reddit api request
const params2 = {'limit': 3, 't': 'week'};
const url2 = new URL('https://oauth.reddit.com/r/node/top');
url2.search = new URLSearchParams(params2).toString();
const settings2 = {
method: 'GET',
headers: {
'User-Agent': 'query-api 1.0',
'Accept': 'application/json',
'Authorization': `Bearer ${accessToken}`,
},
credentials: 'omit'
};
const res2 = await fetch(url2.href, settings2);
const body2 = await res2.json();
let data = [];
let message = `Top Node.js posts this week:\n\n`;
const topPosts = body2.data.children;
topPosts.forEach((post) => {
data.push({
link: post.data.url,
redditLink: post.data.permalink,
text: post.data.title,
score: post.data.score,
replies: post.data.num_comments
});
const text = post.data.title;
const redditLink = post.data.permalink;
message = message + `<https://reddit.com${redditLink}|${text}> \n`;
});
return {id: 1, message: message};
这个Reddit API的JavaScript代码片段使用refresh_token 来查询Reddit API并请求access_token 。一旦我们获得Reddit API的访问令牌,我们就可以创建一个新的HTTP请求--它可以获取提交到r/node 子reddit的趋势Reddit帖子。最后,我们循环浏览所有的帖子数据,并创建一个信息字符串,将其传递给我们的下一个动作。
从前面的代码片断中可以看到两个重要的观察。
-
你会注意到,正确的、最新的查询Reddit数据的API是使用
t中使用的查询参数params2。然而,一些过时的教程和指南仍然提到使用time来代替。 -
另一个有趣的地方是,由于Zapier限制我们使用旧版本的
node-fetch,运行在Node.js运行时间的终结版(Node.js v10)上,你实际上可以直接使用URL对象来进行HTTP请求。
js
const url2 = new URL('https://oauth.reddit.com/r/node/top');
const res2 = await fetch(url2, settings2);
用公共JSON端点查询Reddit信息
在继续其他JavaScript Zapier动作之前,让我们快速介绍一下如何查询Reddit的API,而不需要使用oAuth认证,或任何其他类型的API密钥。
Reddit使用以下端点以JSON格式提供subreddit线程信息,该端点是公开的,没有经过认证。
sh
https://www.reddit.com/r/node/top.json
你甚至可以通过添加以下查询参数,请求该子红点的热门帖子,并提供一个时间框架。
sh
https://www.reddit.com/r/node/top.json?limit=1&t=month
来自Reddit的JSON响应将是类似于以下的内容。
json
{
"kind": "Listing",
"data": {
"after": "t3_vuyxes",
"dist": 1,
"modhash": "6v201d03619751a685b19dcf05febbf88ed6d115afa5d16b78",
"geo_filter": "",
"children": [
{
"kind": "t3",
"data": {
"approved_at_utc": null,
"subreddit": "node",
"selftext": "",
"author_fullname": "t2_7eb9a4k5",
"saved": false,
"mod_reason_title": null,
"gilded": 0,
"clicked": false,
"title": "Deno in 2022",
"link_flair_richtext": [],
"subreddit_name_prefixed": "r/node",
"hidden": false,
"pwls": 6,
"link_flair_css_class": null,
"downs": 0,
"top_awarded_type": null,
"hide_score": false,
"name": "t3_vuyxes",
"quarantine": false,
"link_flair_text_color": "dark",
"upvote_ratio": 0.92,
"author_flair_background_color": null,
"subreddit_type": "public",
"ups": 745,
"total_awards_received": 0,
"media_embed": {},
"author_flair_template_id": null,
"is_original_content": false,
"user_reports": [],
"secure_media": null,
"is_reddit_media_domain": true,
"is_meta": false,
"category": null,
"secure_media_embed": {},
"link_flair_text": null,
"can_mod_post": false,
"score": 745,
"approved_by": null,
"is_created_from_ads_ui": false,
"author_premium": false,
"thumbnail": "",
"edited": false,
"author_flair_css_class": null,
"author_flair_richtext": [],
"gildings": {},
"content_categories": null,
"is_self": false,
"mod_note": null,
"created": 1657363081,
"link_flair_type": "text",
"wls": 6,
"removed_by_category": null,
"banned_by": null,
"author_flair_type": "text",
"domain": "i.redd.it",
"allow_live_comments": true,
"selftext_html": null,
"likes": null,
"suggested_sort": null,
"banned_at_utc": null,
"url_overridden_by_dest": "https://i.redd.it/hjv8r84ttia91.jpg",
"view_count": null,
"archived": false,
"no_follow": false,
"is_crosspostable": true,
"pinned": false,
"over_18": false,
"all_awardings": [],
"awarders": [],
"media_only": false,
"can_gild": true,
"spoiler": false,
"locked": false,
"author_flair_text": null,
"treatment_tags": [],
"visited": false,
"removed_by": null,
"num_reports": null,
"distinguished": null,
"subreddit_id": "t5_2reca",
"author_is_blocked": false,
"mod_reason_by": null,
"removal_reason": null,
"link_flair_background_color": "",
"id": "vuyxes",
"is_robot_indexable": true,
"report_reasons": null,
"author": "m_ax__",
"discussion_type": null,
"num_comments": 184,
"send_replies": true,
"whitelist_status": "all_ads",
"contest_mode": false,
"mod_reports": [],
"author_patreon_flair": false,
"author_flair_text_color": null,
"permalink": "/r/node/comments/vuyxes/deno_in_2022/",
"parent_whitelist_status": "all_ads",
"stickied": false,
"url": "https://i.redd.it/hjv8r84ttia91.jpg",
"subreddit_subscribers": 215851,
"created_utc": 1657363081,
"num_crossposts": 0,
"media": null,
"is_video": false
}
}
],
"before": null
}
}
格式化Zapier动作的JavaScript响应
无论你如何获得和格式化Reddit的JSON数据,我们都需要为下一步Slack机器人的整合做准备。你可以在之前的JavaScript Zapier Action中整体完成,或者将其作为自己的专用Zapier Action运行--这样,如果Reddit的格式方法发生变化,你就可以重新使用它。
这段代码相当简单,告诉你如何使用inputData 变量接受输入到JavaScript Zapier Action中,并将其作为输出。
js
const slackMessage = inputData.message
output = [{id: 123, message: slackMessage}];
严格来说,数组表示法并不是必需的,但它是一种让Zapier知道它需要重复这个动作之后的后续动作的方式,多次重复数组中的每个有效载荷(或对象值)。
下面是一个截图供参考。

在Slack中发送频道信息
我们终于到了建立Slack机器人Reddit自动化的最后一步--将我们在前几步中处理过的信息发布到Slack频道。
要做到这一点,请确保你已经将Zapier认证为Slack中的一般集成应用,并赋予它列出Slack频道的权限和其他权限,如消息发布。
添加一个新的Zapier行动,并选择Slack作为应用程序的选项。在事件表格领域,选择发送频道信息。然后,进入选择账户 选项,最好是输入你的Slack账户,这样消息就会来自你的用户资料。否则,你可以使用Slack盒子集成账户作为普通用户。
目前,这应该看起来如下。

然后,进入设置行动,输入以下信息。
- 要发布消息的频道(在用户界面中表示为频道选项)
- 消息文本选项,应该由之前的Zapier动作
Message字段预先填入。
设置应该与下面类似。

最后,你可以触发这个Zapier工作流程的手动测试执行,它应该如下所示。

在审查和运行Zapier工作流程的测试后,点击发布Zap按钮--这将启用工作流程,并根据我们设置为触发器的经常性时间表开始自动化。
如何将Slack API连接到其他API?
你可以建立Slack机器人API,而不仅仅是用Zapier发送一个频道消息。这里有一些Slack机器人的JavaScript想法,你可以建立在Zapier之上:当Google Sheet行更新时发送Slack消息,将接近的Google日历事件发送到Slack频道,在Slack中分享新的Twitter提及,甚至只是在Google日历事件期间或基于其他活动更新你的Slack状态,你可以与Zapier APIs连接。
你建立了一个Zapier Reddit集成!
今天,我们学习了如何建立一个Slack机器人,使用公开访问的JSON端点或Reddit oAuth API密钥,自动发送来自顶级趋势Reddit新闻的频道信息。
作为结束语,如果你正在构建一个由JavaScript代码驱动的Slack机器人集成,请确保你正在跟进相关的JavaScript安全实践,并了解相关的风险,这样你就不会因为安全问题而危及你的业务。