🚀 发送新星通知的 4 大方法⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️
TL;DR
TL;DR
在上一篇文章中,我讨论了如何创建GitHub 星星监控器。
 在本文中,我将向您展示如何每天获取新星星的信息。
 我们将学习:
- 如何构建通用系统来创建和使用提供程序。
- 如何使用提供程序发送通知。
- 使用不同提供商的不同用例。
您的后台工作平台🔌
Trigger.dev 是一个开源库,可让您使用 NextJS、Remix、Astro 等为您的应用程序创建和监控长时间运行的作业!
请帮我们点个星🥹。
 这有助于我们创作更多类似的文章💖
让我们开始吧🔥
我们将创建不同的提供商,以便在有新星出现时通知我们。我们将设置Email、SMS、Slack和Discord通知。
我们的目标是让每个贡献者都能在未来轻松地贡献更多服务。
每个提供商都会有一组不同的参数,有些只有参数API keys,有些只有电话号码,具体取决于提供商。
为了验证这些密钥,让我们安装zod;它是一个定义模式并根据模式检查数据的很棒的库。
您可以通过运行以下命令开始:
npm install zod --save
完成后,创建一个名为 的新文件夹providers,然后在其中创建一个名为 的新文件register.provider.ts。
这是该文件的代码:
import {Schema} from "zod";
export function registerProvider<T>(
    name: string,
    options: {active: boolean},
    validation: Schema<T>,
    run: (libName: string, stars: number, values: T) => Promise<void>
) {
    // if not active, we can just pass an empty function, nothing will run
    if (!options.active) {
        return () => {};
    }
    // will validate and remove unnecessary values (Security wise)
    const env = validation.parse(process.env);
    // return the function we will run at the end of the job
    return async (libName: string, stars: number) => {
        console.log(`Running provider ${name}`);
        await run(libName, stars, env as T);
        console.log(`Finished running provider ${name}`);
    }
}
代码并不多,但可能有点复杂。
我们首先创建一个名为 的新函数registerProvider。该函数具有一个泛型类型T,这基本上是我们所需的环境变量。
然后我们还有 4 个参数:
- 名称 - 可以是Twilio、Discord、Slack或 中的任意一个Resend。
- 选项 - 目前,一个参数是提供商是否处于活动状态?
- 验证 - 在这里,我们zod在 .env 文件中传递所需参数的模式。
- run - 它实际上用于发送通知。请注意,传递给它的参数是库名称、星数以及我们在validation
然后我们有实际的功能:
首先,我们检查服务提供者是否处于活动状态。如果不是,则发送一个空函数。
然后,我们验证并提取我们在模式中指定的变量。如果变量缺失,zod则会发送错误,并且不会让应用程序运行。
最后,我们返回一个获取库名称和星星数量并触发通知的函数。
在我们的文件夹中providers,创建一个名为的新文件providers.ts并在其中添加以下代码:
export const Providers = [];
稍后,我们将在那里添加所有提供商。
修改 TriggerDev 作业
本文是上一篇关于创建GitHub 星星监视器的文章的延续。
编辑该文件jobs/sync.stars.ts,在文件底部添加如下代码:
const triggerNotification = client.defineJob({
    id: "trigger-notification",
    name: "Trigger Notification",
    version: "0.0.1",
    trigger: invokeTrigger({
      schema: z.object({
        stars: z.number(),
        library: z.string(),
        providerNumber: z.number(),
      })
    }),
    run: async (payload, io, ctx) => {
      await io.runTask("trigger-notification", async () => {
        return Providers[payload.providerNumber](payload.library, payload.stars);
      });
    }
});
此项工作获取星号、库名称和提供商编号,并从先前定义的提供商触发针对特定提供商的通知。
现在,让我们继续修改,getStars在函数末尾添加以下代码:
for (let i = 0; i < Providers.length; i++) {
      await triggerNotification.invoke(payload.name + '-' + i, {
          library: payload.name,
          stars: stargazers_count - payload.previousStarCount,
          providerNumber: i,
      });
  }
这将触发每个图书馆的通知。
完整页面代码:
import { cronTrigger, invokeTrigger } from "@trigger.dev/sdk";
import { client } from "@/trigger";
import { prisma } from "../../helper/prisma";
import axios from "axios";
import { z } from "zod";
import {Providers} from "@/providers/providers";
// Your first job
// This Job will be triggered by an event, log a joke to the console, and then wait 5 seconds before logging the punchline.
client.defineJob({
  id: "sync-stars",
  name: "Sync Stars Daily",
  version: "0.0.1",
  // Run a cron every day at 23:00 AM
  trigger: cronTrigger({
    cron: "0 23 * * *",
  }),
  run: async (payload, io, ctx) => {
    const repos = await io.runTask("get-stars", async () => {
      // get all libraries and current amount of stars
      return await prisma.repository.groupBy({
        by: ["name"],
        _sum: {
          stars: true,
        },
      });
    });
    //loop through all repos and invoke the Job that gets the latest stars
    for (const repo of repos) {
      await getStars.invoke(repo.name, {
        name: repo.name,
        previousStarCount: repo?._sum?.stars || 0,
      });
    }
  },
});
const getStars = client.defineJob({
  id: "get-latest-stars",
  name: "Get latest stars",
  version: "0.0.1",
  // Run a cron every day at 23:00 AM
  trigger: invokeTrigger({
    schema: z.object({
      name: z.string(),
      previousStarCount: z.number(),
    }),
  }),
  run: async (payload, io, ctx) => {
    const stargazers_count = await io.runTask("get-stars", async () => {
      const {data} = await axios.get(`https://api.github.com/repos/${payload.name}`, {
        headers: {
          authorization: `token ${process.env.TOKEN}`,
        },
      });
      return data.stargazers_count as number;
    });
    await io.runTask("upsert-stars", async () => {
      await prisma.repository.upsert({
        where: {
          name_day_month_year: {
            name: payload.name, month: new Date().getMonth() + 1, year: new Date().getFullYear(), day: new Date().getDate(),
          },
        }, update: {
          stars: stargazers_count - payload.previousStarCount,
        }, create: {
          name: payload.name, stars: stargazers_count - payload.previousStarCount, month: new Date().getMonth() + 1, year: new Date().getFullYear(), day: new Date().getDate(),
        },
      });
    });
    for (let i = 0; i < Providers.length; i++) {
        await triggerNotification.invoke(payload.name + '-' + i, {
            library: payload.name,
            stars: stargazers_count - payload.previousStarCount,
            providerNumber: i,
        });
    }
  },
});
const triggerNotification = client.defineJob({
    id: "trigger-notification",
    name: "Trigger Notification",
    version: "0.0.1",
    trigger: invokeTrigger({
      schema: z.object({
        stars: z.number(),
        library: z.string(),
        providerNumber: z.number(),
      })
    }),
    run: async (payload, io, ctx) => {
      await io.runTask("trigger-notification", async () => {
        return Providers[payload.providerNumber](payload.library, payload.stars);
      });
    }
});
现在,有趣的部分🎉
让我们继续创建我们的提供商!
首先创建一个名为providers/lists
1. Discord
创建一个名为的新文件discord.provider.ts并添加以下代码:
import {object, string} from "zod";
import {registerProvider} from "@/providers/register.provider";
import axios from "axios";
export const DiscordProvider = registerProvider(
    "discord",
    {active: true},
    object({
        DISCORD_WEBHOOK_URL: string(),
    }),
    async (libName, stars, values) => {
        await axios.post(values.DISCORD_WEBHOOK_URL, {content: `The library ${libName} has ${stars} new stars!`});
    }
);
如您所见,我们正在使用registerProvider来创建一个名为 DiscordProvider 的新提供程序
- 我们将名称设置为discord
- 我们将其设置为活跃
- 我们指定我们需要一个名为的环境变量DISCORD_WEBHOOK_URL。
- 我们使用 Axios 的简单 post 命令将信息添加到检查中。
要得到DISCORD_WEBHOOK_URL:
- 前往您的 Discord 服务器
- 点击其中一个频道的编辑
- 前往Integrations
- 点击Create Webhook
- 点击创建的 webhook,然后点击Copy webhook URL
编辑我们.env的根项目上的文件并添加
SLACK_WEBHOOK_URL=<your copied url>
2. Slack
创建一个名为的新文件slack.provider.ts并添加以下代码:
import {object, string} from "zod";
import {registerProvider} from "@/providers/register.provider";
import axios from "axios";
export const SlackProvider = registerProvider(
    "slack",
    {active: true},
    object({
        SLACK_WEBHOOK_URL: string(),
    }),
    async (libName, stars, values) => {
        await axios.post(values.SLACK_WEBHOOK_URL, {text: `The library ${libName} has ${stars} new stars!`});
    }
);
如您所见,我们正在使用registerProvider来创建一个名为 SlackProvider 的新提供程序
- 我们将名称设置为slack
- 我们将其设置为活跃
- 我们指定我们需要一个名为的环境变量SLACK_WEBHOOK_URL。
- 我们使用 Axios 的简单 post 命令将信息添加到检查中。
要得到SLACK_WEBHOOK_URL:
- 使用以下 URL 创建一个新的 Slack 应用程序:https://api.slack.com/apps? new_app=1
- 选择第一个选项:“从头开始”
- 输入一个应用程序名称(任意),并在 Slack 中指定您想要添加通知的工作区。点击Create App。
- 在“添加特性和功能”中,点击Incoming hook
- 在激活传入 Webhook 中,将其更改为“开”。
- 点击“将新的 Webhook 添加到工作区”。
- 选择您想要的频道并点击“允许”。
- 复制 webhook URL。
编辑我们.env的根项目上的文件并添加
SLACK_WEBHOOK_URL=<your copied url>
3. 电子邮件
您可以使用不同类型的电子邮件提供商。例如,我们将使用Resend来发送电子邮件。
为此,让我们在项目上安装重新发送:
npm install resend --save
创建一个名为的新文件resend.provider.ts并添加以下代码:
import {object, string} from "zod";
import {registerProvider} from "@/providers/register.provider";
import axios from "axios";
import { Resend } from 'resend';
export const ResendProvider = registerProvider(
    "resend",
    {active: true},
    object({
        RESEND_API_KEY: string(),
    }),
    async (libName, stars, values) => {
        const resend = new Resend(values.RESEND_API_KEY);
        await resend.emails.send({
            from: "Eric Allam <eric@trigger.dev>",
            to: ['eric@trigger.dev'],
            subject: 'New GitHub stars',
            html: `The library ${libName} has ${stars} new stars!`,
        });
    }
);
如您所见,我们正在使用registerProvider创建一个名为 ResendProvider 的新提供程序
- 我们将名称设置为resend
- 我们将其设置为活跃
- 我们指定我们需要一个名为的环境变量RESEND_API_KEY。
- 我们使用 Resend 库向我们自己发送一封包含新星星数量的电子邮件。
要得到RESEND_API_KEY:
- 在以下网址创建新帐户:https://resend.com
- 转到API Keys或使用此 URL https://resend.com/api-keys
- 点击“+ 创建 API 密钥”,添加密钥名称,选择“发送访问权限”,并使用默认的“所有域”。点击“添加”。
- 复制 API 密钥。
编辑我们.env的根项目上的文件并添加
RESEND_API_KEY=<your API key>
4. 短信
SMS 稍微复杂一些,因为它们需要多个变量。
为此,让我们在项目上安装 Twilio:
npm install twilio --save
创建一个名为的新文件twilio.provider.ts并添加以下代码:
import {object, string} from "zod";
import {registerProvider} from "@/providers/register.provider";
import axios from "axios";
import client from 'twilio';
export const TwilioProvider = registerProvider(
    "twilio",
    {active: true},
    object({
        TWILIO_SID: string(),
        TWILIO_AUTH_TOKEN: string(),
        TWILIO_FROM_NUMBER: string(),
        TWILIO_TO_NUMBER: string(),
    }),
    async (libName, stars, values) => {
        const twilio = client(values.TWILIO_SID, values.TWILIO_AUTH_TOKEN);
        await twilio.messages.create({
            body: `The library ${libName} has ${stars} new stars!`,
            from: values.TWILIO_FROM_NUMBER,
            to: values.TWILIO_TO_NUMBER,
        });
    }
);
如您所见,我们正在使用registerProvider来创建一个名为 TwilioProvider 的新提供程序
- 我们将名称设置为twilio
- 我们将其设置为活跃
- 我们指定需要的环境变量:TWILIO_SID、、和TWILIO_AUTH_TOKENTWILIO_FROM_NUMBERTWILIO_TO_NUMBER
- 我们使用 Twiliocreate功能发送短信。
得到TWILIO_SID、和TWILIO_AUTH_TOKENTWILIO_FROM_NUMBERTWILIO_TO_NUMBER
- 在https://twilio.com创建新帐户
- 标记您想使用它来发送短信。
- 点击“获取电话号码”
- 复制“帐户 SID”、“授权令牌”和“我的 Twilio 电话号码”
编辑我们.env的根项目上的文件并添加
TWILIO_SID=<your SID key>
TWILIO_AUTH_TOKEN=<your AUTH TOKEN key>
TWILIO_FROM_NUMBER=<your FROM number>
TWILIO_TO_NUMBER=<your TO number>
创建新的提供商
如您所见,现在创建提供程序非常容易。
您还可以使用开源社区来创建新的提供商,因为他们只需要在providers/list目录中创建一个新文件。
最后要做的是编辑您的providers.ts文件并添加所有提供商。
import {DiscordProvider} from "@/providers/list/discord.provider";
import {ResendProvider} from "@/providers/list/resend.provider";
import {SlackProvider} from "@/providers/list/slack.provider";
import {TwilioProvider} from "@/providers/list/twilio.provider";
export const Providers = [
    DiscordProvider,
    ResendProvider,
    SlackProvider,
    TwilioProvider,
];
随意创建更多推送通知、网络推送通知、应用内通知等提供程序。
你就完成了🥳
让我们联系吧!🔌
作为开源开发者,我们诚邀您加入我们的 社区 ,贡献力量并与维护人员互动。欢迎访问我们的 GitHub 代码库 ,贡献代码并创建与 Trigger.dev 相关的问题。
本教程的源代码可以在这里找到:
https://github.com/triggerdotdev/blog/tree/main/stars-monitor-notifications
感谢您的阅读!
文章来源:https://dev.to/triggerdotdev/top-4-ways-to-send-notifications-about-new-stars-1cgb 后端开发教程 - Java、Spring Boot 实战 - msg200.com
            后端开发教程 - Java、Spring Boot 实战 - msg200.com
          








