Cointime

扫码下载App
iOS & Android

用OpenFaaS和Golang构建一个无服务器的Discord机器人

项目方

了解如何使用OpenFaaS和Golang构建一个可以按需创建Zoom会议的Discord机器人

如果你过去曾经尝试过建立一个机器人,你可能已经注意到,他们往往依赖于一个长期存在的websocket。这意味着你的代码需要作为一个守护程序一直运行下去。

无服务器方法意味着要编写高效、无状态的函数,对事件作出响应,并可独立扩展。它们只需要在有事件发生时运行,在不使用时可以缩减到零。幸运的是,大多数支持websockets的平台,也支持webhooks来响应事件。

我为什么要为 Discord 构建一个机器人?

我们最近将公司的通信从Slack迁移到了Discord--它是小型团队和社区的一个绝佳工具。我们还没做的一件事是能够在DM或频道中按需创建一个Zoom会议。Discord有自己的屏幕共享和视频通话功能,所以也许对他们来说,使Zoom易于使用不是他们的目标。我们已经使用了Discord的语音聊天功能,但高清屏幕共享需要额外的订阅,当我们已经为Zoom付费时,这就没有意义了。

对于Slack来说,建立一个webhook驱动的Slash命令是微不足道的,但是对于Discord来说,我发现这个过程是漫长且费解的。所以我写了这个教程来帮助你用OpenFaaS创建你自己的Discord机器人。我将使用Go语言--但一旦你理解了它的工作原理,你可以相对容易地将步骤翻译成其他语言。

Discord到Zoom机器人的概念性架构

以下Slack Slash命令的例子:

像Slack和Discord这样的消息传递产品有两种常见的集成方式:

1. 你的代码通过消息平台托管的HTTPS端点向一个频道或用户发送消息

2. 用户在频道或DM中键入一个命令,消息平台向你的代码发送一个事件。

在这个演练中,我们还介绍了第二种类型的整合,但我在最后也有一个例子,说明如何通过webhook向渠道发送消息。

我将带领你学习一些代码,但其余的代码可以在GitHub上找到。在文章的最后,我们将把机器人部署到OpenFaaS--使用Kubernetes或faasd。faasd可以在虚拟机上运行,对资源的要求很低,所以它是一个开始使用机器人和一些cron作业的好方法。

如果你正在跟随我们做 - 那么我们将把一些秘密保存到本地的.secrets文件夹中,然后使用faas-cli secret create来使它们对函数可用。

从目标向后工作

我们知道我们想要一个可以输入的命令来启动一个Zoom会议--但是通过API来创建一个Zoom呼叫是否是可能的呢?

这就是我的出发点--结果发现,Zoom的API并不是只有一个版本,而是两个。而且不是只有一种方法来验证一个像函数一样的后台进程,而是有多种。经过几个小时跟踪过时的文档,我发现你需要的是V2 API和一个通过OAuth2流程获得的JWT令牌。

你可以在这里找到Zoom的开发者文档

你需要点击创建一个应用程序

我为本教程创建的应用程序

我们还需要将client_id和account_id保存到zoom_config.yaml文件中,复制一份example.zoom_config.yaml。

将账户ID保存为.secrets/zoom-account-id,客户ID保存为.secrets/zoom-client-id和客户秘密(.secrets/zoom-client-secret)。所有这些都是对Zoom进行API调用的必要条件,以获得一个短期的JWT代币。JWT代币将被用于管理会议的API端点。

创建会议所需的范围

根据你希望你的命令做什么,你可以选择你自己的范围。

由于这个机器人只供我们团队内部使用,我选择了: 打算发布: No 和 Account-level: app。如果你想发布你的机器人供他人使用,那么你将需要通过一些额外的验证和步骤。

如果你看一下我创建的zoom.go文件,你会看到requestZoomToken函数被调用以获得JWT访问代币。

一个HTTP POST被发送到https://zoom.us/oauth/token,grant_type of account_credentials,然后客户端ID和客户端秘密被编码为Authorization中的用户名/密码: Basic HTTP header。

了解更多关于Zoom认证的信息

响应包含代币:

// ZoomTokenResponse是Zoom的OAuth端点的响应。
// ZoomTokenResponse is the response fromZoom's OAuth endpoint
// when requesting a token for server to server authentication.

type ZoomTokenResponse struct {
  AccessToken string `json:"access_token"`
  TokenType   string `json:"token_type"`
  ExpiresIn   int64 `json:"expires_in"`
  Scope       string `json:"scope"`
}

之后,当被Discord机器人调用时,会议将由createMeeting功能创建。

一个HTTP POST被发送到https://api.zoom.us/v2/users/${userId}/meetings,包含JWT代币的:Authorization: Bearer header。

会议有一个可选的主题,但开始时间是即时的,密码是自动生成的,然后在 Discord 频道中返回给用户。

还有其他的输入和输出可以玩,但这是最小的可行的输入。

也请参见: Zoom:为用户创建一个会议

构建Discord机器人

对于Discord的整合,我们需要:

1. 在Discord开发者门户网站上创建一个应用程序

2. 创建一个机器人用户并获得其代币

3. 配置一个传入的webhook URL到该函数中

4. 从该函数中注册斜线命令

5. 验证测试webhooks

6. 最后解析该命令并调用Zoom API

这就相当多了。而Slack和Discord之间的一个主要区别就是上述所有的事情都很复杂。斜线命令也是从你的函数中注册的,而不是在Discord开发者门户中创建的。

创建应用程序和机器人用户

进入 Discord 开发者门户,点击 "新应用程序"。

记下客户端ID--这不是一个秘密,将通过复制example.discord_config.yaml将其设置在discord_config.yaml的函数上。

点击 "Bot "标签,然后点击 "Reset token"--将结果保存为.secrets/discord-bot-token,这是你的Bot的API代币。

获取机器人代币

我们从Discord收到的每条消息都会有一个签名头,我们需要验证。一旦我们验证了消息,我们就可以根据允许使用机器人的用户名的自定义访问控制列表(ACL)来使用用户名。我只是把这个列表设置为我自己的用户名,是通过查看Discord用户界面获得的。

在discord_config.yaml的discord_usernames字段下设置该值。或者,如果你有多个人要使用机器人,在你添加的每个用户名之间加一个逗号。

接下来,你需要一种方法来接收传入的webhooks到你的函数。

如果你的OpenFaaS集群或faasd服务器是暴露在互联网上的,你只需使用你设置的公共域,并添加一个/function/discord-start-zoom或类似的路径。在我的例子中,我在家里的网络上运行,所以我使用inlets创建了一个HTTPS隧道

将交互URL设置为你的函数的公共URL

注意,你可能想在函数完全部署和配置后再设置这个URL,因为编辑URL会导致向该URL发送挑战。

当你的函数启动时,它应该注册它需要的任何命令。我使用一个文本字段作为输入,但是如果你需要的话,Discord支持丰富的输入和输出。

discordClientID := os.Getenv("discord_client_id")

if len(discordClientID) == 0 {
  panic("discord_client_id not set")
}

registerCommand := fmt.Sprintf("https://discord.com/api/v10/applications/%s/commands", discordClientID)
botToken, err := sdk.ReadSecret("discord-bot-token")

if err != nil {
  panic(err)
}

commandOptions := `{
  "name": "zoom", 
  "description": "Create a Zoom meeting", 
  "options": [
    {
      "name": "topic", 
      "description": "The topic of the meeting", 
      "type": 3, 
      "required": false
    }
    ]
  }`

req, err := http.NewRequest(http.MethodPost, registerCommand, strings.NewReader(commandOptions))

if err != nil {
  panic(err)
}

req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "DiscordBot (https://alexellis.io, 1)")
req.Header.Set("Authorization", "Bot "+botToken)

不幸的是,信息和输入的类型都是用整数表示的,这意味着你需要在开发过程中努力记住这些信息或在你的脑海中映射它们。另见: 消息组件

我把上述代码放在Go函数的init()中,所以每当函数被部署或从零开始扩展时,它就会被执行。

一旦你在Discord开发者门户中设置了你的函数的URL,Discord的服务器就会发送一个API挑战,消息类型为type: 1,这是一个需要响应的挑战

你可以在接收和响应文档中准确地阅读这个工作原理,或者跳到我的机器人中的verify.go。

如果你过去验证过GitHub的webhooks,那么感觉会很相似,不过这要复杂一些,是使用Ed25519算法。

你的机器人会有自己的公钥,用来签署信息,你需要从仪表板上保存它,然后为它创建一个单独的秘密。将文本保存到.secrets/discord-bot-public-key。

添加机器人到你的服务器

由于机器人被归类为内部集成,而不是公共集成,你需要使用OAuth2授权流程手动将其添加到你的服务器。

export discord_client_id="1067047141857570857"

echo "https://discord.com/api/oauth2/authorize?client_id=${discord_client_id}&scope=bot&permissions=0"
为你的机器人应用提供OAuth2同意界面

你应该看到在你的服务器中出现这个场景,可以通过进入服务器设置然后是应用程序来查看:

安装在你的服务器上的机器人

测试它

如果你已经在Zoom和Discord的开发者门户中完成了所有的设置,那么下一步就是:

1. 使用保存在.secrets/中的文件创建所有需要的秘密

 faas-cli secret create discord-bot-token --from-file .secrets/discord-bot-token

 faas-cli secret create discord-public-key --from-file .secrets/discord-public-key

 faas-cli secret create zoom-account-id --from-file .secrets/zoom-account-id

 faas-cli secret create zoom-client-id --from-file .secrets/zoom-client-id

 faas-cli secret create zoom-client-secret --from-file .secrets/zoom-client-secret

2. 仔细检查discord_config.yaml和zoom_config.yaml中的值。

3. 将该功能部署到你的集群中

 faas-cli deploy

4. 通过检查logs来验证挑战是否被通过

 faas-cli logs discord-start-zoom

 2023-05-12T10:35:06Z 2023/05/12 10:35:06 Ping verified? true

 2023-05-12T10:35:06Z 2023/05/12 10:35:06 POST / - 200 OK - ContentLength: 11B (0.0030s)

 2023-05-12T10:35:07Z 2023/05/12 10:35:07 Ping verified?

 2023-05-12T10:35:07Z 2023/05/12 10:35:07 POST / - 401 Unauthorized - ContentLength: 26B (0.0013s)

5. 用OAuth2网址在你的服务器上安装机器人

6. 在Discord中向你的机器人发送一个消息

创建一个Zoom会议来重温这篇博文

我们可以看到创会议叫的日志:

faas-cli logs discord-start-zoom

2023-05-12T10:41:33Z 2023/05/12 10:41:33 Created a Zoom call for: Business chat

2023-05-12T10:41:33Z 2023/05/12 10:41:33 POST / - 200 OK - ContentLength: 303B (1.0553s)

会议被展示在频道上

如果你想看到通过 Discord 发送的请求的全文,那么你可以编辑 stack.yaml 并将 print_input 环境变量设置为 true,然后重新部署该函数。

如果你想定制我的机器人,那么只需做以下工作:

1. 分叉仓库 - 在GitHub上

2. 克隆你的分叉版本到你自己的机器上

3. 编辑你想修改的文件

4. 把我在 stack.yaml 的 image: 字段下的用户名/Docker Hub 帐号换成你自己的。

5. 运行faas-cli并尝试新的改变。

总结

我试图让你快速掌握使用Golang和OpenFaaS创建Webhook驱动的Discord机器人的能力。

Webhook驱动的功能可以被部署到FaaS平台上,在闲置时被缩减为零,并且不需要在用户有请求的情况下全天候运行。这使得它们的运行成本更低--无状态,比一直运行的守护程序要高效得多。

这里的大部分工作不是在编写机器人,而是在了解授权和集成模式如何运作--包括与 Discord 和任何其他你想集成的平台。

还有一种与 Discord 集成的方法更简单,那就是在外部系统发生事情的时候发送单向消息。

我建立了一个机器人,只要有人在Gumroad上结账,就向Discord频道发送消息。你可以在这里阅读代码: 每当你在Gumroad上卖出一个产品时,在Slack中获得webhooks。它是用JavaScript编写的,使用Node.js作为运行时。还有一个与AWS SES的集成,可以在特定条件下向客户发送电子邮件。

有了OpenFaaS,你可以用任何你喜欢的语言编写你自己的集成,并将它们部署到Kubernetes与OpenFaaS,或使用faasd项目部署到一台机器。它们的运行情况几乎是一样的,对于个人使用或小团队来说,你可能根本不需要让功能扩展。

当我第一次在每周的OpenFaaS社区电话会议上分享这个机器人的演示时,Kevin Lindsay建议做一些通用函数,可以注册许多不同的函数,然后当它收到不同的调用时,会把它们分散到不同的函数中。这意味着与Discord合作的复杂部分可以被隐藏起来。

你会用webhook驱动的Discord机器人建立什么?请在Twitter上告诉我@alexellisuk。

评论

所有评论

推荐阅读

  • 美团开源560B参数定理证明模型:72次推理通过率97.1%,刷新开源模型SOTA

    据 1M AI News 监测,美团 LongCat 团队开源 LongCat-Flash-Prover,一个 5600 亿参数的 MoE 模型,专攻形式化定理证明语言 Lean4 的数学推理任务。模型权重以 MIT 协议发布,已上线 GitHub、Hugging Face 和 ModelScope。模型将形式化推理拆解为三项独立能力:自动形式化(将自然语言数学问题转化为 Lean4 形式语句)、草图生成(产出引理风格的证明框架)和完整证明生成。三项能力均通过 Agent 工具集成推理(TIR)与 Lean4 编译器实时交互验证。训练方面,团队提出 Hybrid-Experts Iteration Framework 生成冷启动数据,并在强化学习阶段引入 HisPO 算法稳定 MoE 模型的长程任务训练,同时加入定理一致性和合法性检测机制防止 reward hacking。基准测试显示,LongCat-Flash-Prover 在开源权重模型中刷新了自动形式化和定理证明两项 SOTA。MiniF2F-Test 上仅用 72 次推理即达 97.1% 通过率,ProverBench 和 PutnamBench 分别达到 70.8% 和 41.5%,每题推理次数不超过 220 次。

  • Erik Voorhees再次增持1.44万枚ETH,总持仓量突破11.7万枚

    3 月 21 日,据 AI 姨监测,ShapeShift 创始人、比特币早期支持者 Erik Voorhees 关联地址,过去 11 小时买入 14,424.53 ETH,总持仓突破 11.7 万枚,持仓均价 2,160.24 美元,当前浮亏 114.5 万美元。

  • 消息人士:特朗普政府正制定方案以夺取伊朗核材料储备

    Cointime 报道,3月21日消息,据美国哥伦比亚广播公司(CBS)报道,多位知情人士透露,特朗普政府一直在谋划获取或转移伊朗核材料的方法和选项。此时,由美国和以色列领导的针对伊朗的军事行动正进入一个更加不确定的阶段。 关于特朗普是否会下令实施此类行动,目前时机尚不明确。一位消息人士表示,他尚未做出任何决定。但两位消息人士表示,相关规划的核心是可能部署来自联合特种作战司令部的部队,该部队是精英军事单位,常负责最敏感的防扩散任务。(金十)

  • GameFi板块市值暂报45.15亿美元,FLOKI排名第一

    3 月 21 日,据 Coingecko 数据,GameFi 板块市值暂报 45.15 亿美元,FLOKI 以 2.86 亿美元市值排名第一,排在第二第三位的分别为:The Sandbox(2.18 亿美元)、Undeads Games(2.11 亿美元)。此前 Solana 基金会主席 Lily Liu 表示,区块链游戏「不会再回归」。她认为,尽管行业曾寄望通过链上资产与开放世界推动 Web3 与元宇宙发展,但实际表现远未达预期。市场观点称链游长期依赖「Play-to-Earn」等代币激励模式,却缺乏真正吸引核心玩家的游戏性与内容构建能力,导致用户留存与生态可持续性不足。包括 Andreessen Horowitz(a16z)、Framework Ventures、Animoca Brands 在内的机构曾向该领域投入数十亿美元,但回报表现不佳。

  • Karpathy:大多数App不该存在,3个提示词让AI接管整个智能家居

    据 1M AI News 监测,Andrej Karpathy 在 No Priors 播客中称,应用商店里的大多数智能家居 App「根本不该存在,一切都该是 API 端点,Agent 才是智能粘合层」。他分享了今年 1 月构建的家庭 Agent「Dobby the elf claw」:只用三个提示词,Agent 自行扫描局域网发现了 Sonos 音响,逆向工程其协议后接管播放控制。如今 Dobby 通过 WhatsApp 对话统一控制灯光、空调、窗帘、泳池、安防系统,取代了此前六个独立 App。他还接入了视觉模型监控安防摄像头,有人到访时自动推送图片消息到 WhatsApp。「这在一两年内应该是免费的,不涉及任何 vibe coding,这是基本功,」Karpathy 说,「客户不再是人类了,而是代替人类行事的 Agent。这场重构的规模将相当可观。」

  • OpenAI创始成员:12月以来没写过一行代码,Agent用不好?「那是你菜」

    据 1M AI News 监测,「vibe coding」概念提出者、OpenAI 创始成员 Andrej Karpathy 在 No Priors 播客中透露,去年 12 月是他工作方式的分水岭。此前他自己写代码与委托 Agent 的比例约为 80:20,12 月之后反转为 20:80,「到现在可能已经不止了」,「我大概从 12 月起就没打过一行代码」。他将这种状态称为「AI 精神病」(AI psychosis):Agent 的能力边界尚未被充分探索,「一切皆有可能,而一切失败归根结底都是技能问题(skill issue)」。他开始像 PhD 时期看 GPU 利用率一样关注 Token 吞吐量,「订阅额度没用完就意味着你没有最大化产出」。他还描述了 Agent 的「锯齿感」:「我同时感觉在和一个极其聪明的、做了一辈子系统编程的博士生对话,又在和一个十岁小孩对话。」

  • 日媒:伊朗准备允许日本船只通过霍尔木兹海峡

    3 月 21 日,据日本共同社报道,伊朗外长阿巴斯·阿拉格奇表示,经两国官员协商,伊朗已准备好允许与日本相关的船舶通过霍尔木兹海峡。日本石油进口严重依赖中东地区。伊朗战争促使日本本月动用石油储备。日本一直面临特朗普要求其协助保卫该海峡的压力。本周早些时候,日本首相高市早苗在华盛顿与特朗普当面会晤时,向其说明了日本参与此类行动在法律上的限制。同时,她也强调了双方共识领域,包括承诺增加从美国进口石油以及就导弹研发开展合作。(金十)

  • Solana基金会主席:链游已「死亡」,行业数十亿美元投入或成最差赌注之一

    3 月 21 日,Solana 基金会主席 Lily Liu 表示,区块链游戏「不会再回归」。她认为,尽管行业曾寄望通过链上资产与开放世界推动 Web3 与元宇宙发展,但实际表现远未达预期。Solana 曾被视为最有潜力支撑大规模链游的公链之一,凭借高性能和低成本支持实时交互。然而,包括 Star Atlas、Stepn 等项目虽一度获得关注,但整体 GameFi 赛道自 2021 年高峰后持续下滑。市场观点指出,链游长期依赖「Play-to-Earn」等代币激励模式,却缺乏真正吸引核心玩家的游戏性与内容构建能力,导致用户留存与生态可持续性不足。包括 Andreessen Horowitz(a16z)、Framework Ventures、Animoca Brands 在内的机构曾向该领域投入数十亿美元,但回报表现不佳。不过,部分公司仍在探索转型路径,例如 Mythical Games 与 Gunzilla Games,逐步弱化区块链要素,将其作为可选功能而非核心机制,以提升用户体验与市场接受度。

  • 现货黄金失守4500美元关口,现货白银日内跌近7%

    3 月 21 日,据 Bitget 行情数据,现货黄金失守 4500 美元/盎司关口,日内跌超 3%;现货白银日内跌近 7%,现报 67.845 美元/盎司。消息面上,受美元走强影响,以及有报导称美国已为在伊部署地面部队做好详细准备,加剧了市场对油价上涨、通胀以及随之而来的利率上升的担忧。独立贵金属交易员 Tai Wong 表示:「随着市场的担忧在周末前走高,金银价格正被拖累走低。在经历了本周因加息担忧引发的剧烈回调后,贵金属走势尤为震荡。价格应会很快进行盘整,但过程将充满波折。」全球主要券商认为,欧洲央行和英国央行加息的可能性正在增加,最早可能在 4 月。美联储周三维持利率不变,并预测通胀将走高,而主席鲍威尔表示,由于战争的影响,未来的政策路径面临异常高的不确定性。

  • Web3数据和AI公司Validation Cloud完成1000万美元新一轮融资

    Web3数据和AI公司Validation Cloud宣布从True Global Ventures获得1000万美元融资,该公司计划利用这笔资金扩展其AI产品,实现对Web3数据的无缝访问。 据介绍,该公司的产品平台由三个部分组成:质押、节点API以及数据和AI。在质押方面,Validation Cloud的质押资产已超过10亿美元。Validation Cloud的一些客户包括 Chainlink、Aptos、Consensys、Stellar和Hedera。