mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-07 21:19:51 +00:00
feat: new notification provider: discord bot
This commit is contained in:
parent
cd9dac7765
commit
8e23b14bf3
@ -121,6 +121,11 @@ type AccessConfigForDingTalkBot struct {
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
type AccessConfigForDiscordBot struct {
|
||||
BotToken string `json:"botToken"`
|
||||
DefaultChannelId string `json:"defaultChannelId,omitempty"`
|
||||
}
|
||||
|
||||
type AccessConfigForDNSLA struct {
|
||||
ApiId string `json:"apiId"`
|
||||
ApiSecret string `json:"apiSecret"`
|
||||
|
@ -33,6 +33,7 @@ const (
|
||||
AccessProviderTypeDeSEC = AccessProviderType("desec")
|
||||
AccessProviderTypeDigitalOcean = AccessProviderType("digitalocean")
|
||||
AccessProviderTypeDingTalkBot = AccessProviderType("dingtalkbot")
|
||||
AccessProviderTypeDiscordBot = AccessProviderType("discordbot")
|
||||
AccessProviderTypeDNSLA = AccessProviderType("dnsla")
|
||||
AccessProviderTypeDogeCloud = AccessProviderType("dogecloud")
|
||||
AccessProviderTypeDuckDNS = AccessProviderType("duckdns")
|
||||
@ -269,6 +270,7 @@ type NotificationProviderType string
|
||||
*/
|
||||
const (
|
||||
NotificationProviderTypeDingTalkBot = NotificationProviderType(AccessProviderTypeDingTalkBot)
|
||||
NotificationProviderTypeDiscordBot = NotificationProviderType(AccessProviderTypeDiscordBot)
|
||||
NotificationProviderTypeEmail = NotificationProviderType(AccessProviderTypeEmail)
|
||||
NotificationProviderTypeLarkBot = NotificationProviderType(AccessProviderTypeLarkBot)
|
||||
NotificationProviderTypeMattermost = NotificationProviderType(AccessProviderTypeMattermost)
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/usual2970/certimate/internal/domain"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
||||
pDingTalkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalkbot"
|
||||
pDiscordBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/discordbot"
|
||||
pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
|
||||
pLarkBot "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/larkbot"
|
||||
pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost"
|
||||
@ -42,6 +43,19 @@ func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier
|
||||
})
|
||||
}
|
||||
|
||||
case domain.NotificationProviderTypeDiscordBot:
|
||||
{
|
||||
access := domain.AccessConfigForDiscordBot{}
|
||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
return pDiscordBot.NewNotifier(&pDiscordBot.NotifierConfig{
|
||||
BotToken: access.BotToken,
|
||||
ChannelId: maputil.GetOrDefaultString(options.ProviderServiceConfig, "channelId", access.DefaultChannelId),
|
||||
})
|
||||
}
|
||||
|
||||
case domain.NotificationProviderTypeEmail:
|
||||
{
|
||||
access := domain.AccessConfigForEmail{}
|
||||
|
@ -0,0 +1,67 @@
|
||||
package discordbot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/notifier"
|
||||
)
|
||||
|
||||
type NotifierConfig struct {
|
||||
// Discord Bot API Token。
|
||||
BotToken string `json:"botToken"`
|
||||
// Discord Channel ID。
|
||||
ChannelId string `json:"channelId"`
|
||||
}
|
||||
|
||||
type NotifierProvider struct {
|
||||
config *NotifierConfig
|
||||
logger *slog.Logger
|
||||
httpClient *resty.Client
|
||||
}
|
||||
|
||||
var _ notifier.Notifier = (*NotifierProvider)(nil)
|
||||
|
||||
func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
|
||||
if config == nil {
|
||||
panic("config is nil")
|
||||
}
|
||||
|
||||
client := resty.New()
|
||||
|
||||
return &NotifierProvider{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
httpClient: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier {
|
||||
if logger == nil {
|
||||
n.logger = slog.Default()
|
||||
} else {
|
||||
n.logger = logger
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
|
||||
// REF: https://discord.com/developers/docs/resources/message#create-message
|
||||
req := n.httpClient.R().
|
||||
SetHeader("Content-Type", "application/json").
|
||||
SetHeader("Authorization", "Bot "+n.config.BotToken).
|
||||
SetBody(map[string]any{
|
||||
"content": subject + "\n" + message,
|
||||
})
|
||||
resp, err := req.Post(fmt.Sprintf("https://discord.com/api/v9/channels/%s/messages", n.config.ChannelId))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("discord api error: failed to send request: %w", err)
|
||||
} else if resp.IsError() {
|
||||
return nil, fmt.Errorf("discord api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
|
||||
}
|
||||
|
||||
return ¬ifier.NotifyResult{}, nil
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package discordbot_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/discordbot"
|
||||
)
|
||||
|
||||
const (
|
||||
mockSubject = "test_subject"
|
||||
mockMessage = "test_message"
|
||||
)
|
||||
|
||||
var (
|
||||
fApiToken string
|
||||
fChannelId string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_NOTIFIER_DISCORDBOT_"
|
||||
|
||||
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
|
||||
flag.StringVar(&fChannelId, argsPrefix+"CHANNELID", 0, "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./discordbot_test.go -args \
|
||||
--CERTIMATE_NOTIFIER_DISCORDBOT_APITOKEN="your-bot-token" \
|
||||
--CERTIMATE_NOTIFIER_DISCORDBOT_CHANNELID="your-channel-id"
|
||||
*/
|
||||
func TestNotify(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Notify", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("APITOKEN: %v", fApiToken),
|
||||
fmt.Sprintf("CHANNELID: %v", fChannelId),
|
||||
}, "\n"))
|
||||
|
||||
notifier, err := provider.NewNotifier(&provider.NotifierConfig{
|
||||
BotToken: fApiToken,
|
||||
ChannelId: fChannelId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := notifier.Notify(context.Background(), mockSubject, mockMessage)
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
}
|
@ -17,14 +17,14 @@ const (
|
||||
|
||||
var (
|
||||
fApiToken string
|
||||
fChartId int64
|
||||
fChatId int64
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_NOTIFIER_TELEGRAMBOT_"
|
||||
|
||||
flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
|
||||
flag.Int64Var(&fChartId, argsPrefix+"CHATID", 0, "")
|
||||
flag.Int64Var(&fChatId, argsPrefix+"CHATID", 0, "")
|
||||
}
|
||||
|
||||
/*
|
||||
@ -41,12 +41,12 @@ func TestNotify(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("APITOKEN: %v", fApiToken),
|
||||
fmt.Sprintf("CHATID: %v", fChartId),
|
||||
fmt.Sprintf("CHATID: %v", fChatId),
|
||||
}, "\n"))
|
||||
|
||||
notifier, err := provider.NewNotifier(&provider.NotifierConfig{
|
||||
BotToken: fApiToken,
|
||||
ChatId: fChartId,
|
||||
ChatId: fChatId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
|
1
ui/public/imgs/providers/discord.svg
Normal file
1
ui/public/imgs/providers/discord.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M0 512C0 229.2224 229.2224 0 512 0c282.7776 0 512 229.2224 512 512 0 282.7776-229.2224 512-512 512C229.2224 1024 0 794.7776 0 512z" fill="#7A8CD2"></path><path d="M758.613333 281.207467a1.792 1.792 0 0 0-0.938666-0.8192 591.598933 591.598933 0 0 0-144.298667-44.032 2.218667 2.218667 0 0 0-2.321067 1.0752 398.114133 398.114133 0 0 0-17.954133 36.3008 548.437333 548.437333 0 0 0-162.082133 0 364.663467 364.663467 0 0 0-18.244267-36.317867 2.269867 2.269867 0 0 0-2.321067-1.0752 589.943467 589.943467 0 0 0-144.298666 44.032 2.048 2.048 0 0 0-0.955734 0.8192c-91.904 135.099733-117.077333 266.888533-104.721066 397.038933a2.3552 2.3552 0 0 0 0.9216 1.621334 591.5648 591.5648 0 0 0 177.015466 88.064 2.321067 2.321067 0 0 0 2.491734-0.8192 412.16 412.16 0 0 0 36.215466-57.9584 2.184533 2.184533 0 0 0-1.2288-3.072 390.212267 390.212267 0 0 1-55.296-25.941334 2.269867 2.269867 0 0 1-1.1264-1.792 2.218667 2.218667 0 0 1 0.887467-1.911466c3.7376-2.730667 7.389867-5.563733 10.990933-8.465067a2.2016 2.2016 0 0 1 2.286934-0.3072c116.0192 52.1216 241.629867 52.1216 356.266666 0a2.218667 2.218667 0 0 1 2.321067 0.273067c3.601067 2.9184 7.2704 5.751467 11.008 8.4992a2.2528 2.2528 0 0 1 0.904533 1.911466 2.2016 2.2016 0 0 1-1.092266 1.792 366.0288 366.0288 0 0 1-55.330134 25.9072 2.269867 2.269867 0 0 0-1.314133 1.297067 2.184533 2.184533 0 0 0 0.1024 1.809067 462.506667 462.506667 0 0 0 36.181333 57.941333 2.286933 2.286933 0 0 0 2.491734 0.836267 589.636267 589.636267 0 0 0 177.322666-88.064 2.269867 2.269867 0 0 0 0.904534-1.604267c14.7968-150.459733-24.746667-281.173333-104.789334-397.038933z m-364.168533 317.781333c-34.935467 0-63.709867-31.573333-63.709867-70.314667s28.2112-70.314667 63.709867-70.314666c35.771733 0 64.273067 31.829333 63.709867 70.314666 0 38.741333-28.228267 70.314667-63.709867 70.314667z m235.554133 0c-34.9184 0-63.709867-31.573333-63.709866-70.314667s28.228267-70.314667 63.709866-70.314666c35.771733 0 64.273067 31.829333 63.709867 70.314666 0 38.741333-27.938133 70.314667-63.709867 70.314667z" fill="#FFFFFF"></path></svg>
|
After Width: | Height: | Size: 2.3 KiB |
@ -31,6 +31,7 @@ import AccessFormCMCCCloudConfig from "./AccessFormCMCCCloudConfig";
|
||||
import AccessFormDeSECConfig from "./AccessFormDeSECConfig";
|
||||
import AccessFormDigitalOceanConfig from "./AccessFormDigitalOceanConfig";
|
||||
import AccessFormDingTalkBotConfig from "./AccessFormDingTalkBotConfig";
|
||||
import AccessFormDiscordBotConfig from "./AccessFormDiscordBotConfig";
|
||||
import AccessFormDNSLAConfig from "./AccessFormDNSLAConfig";
|
||||
import AccessFormDogeCloudConfig from "./AccessFormDogeCloudConfig";
|
||||
import AccessFormDuckDNSConfig from "./AccessFormDuckDNSConfig";
|
||||
@ -222,6 +223,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
|
||||
return <AccessFormDigitalOceanConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.DINGTALKBOT:
|
||||
return <AccessFormDingTalkBotConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.DISCORDBOT:
|
||||
return <AccessFormDiscordBotConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.DNSLA:
|
||||
return <AccessFormDNSLAConfig {...nestedFormProps} />;
|
||||
case ACCESS_PROVIDERS.DOGECLOUD:
|
||||
|
70
ui/src/components/access/AccessFormDiscordBotConfig.tsx
Normal file
70
ui/src/components/access/AccessFormDiscordBotConfig.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { type AccessConfigForDiscordBot } from "@/domain/access";
|
||||
|
||||
type AccessFormDiscordBotConfigFieldValues = Nullish<AccessConfigForDiscordBot>;
|
||||
|
||||
export type AccessFormDiscordBotConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: AccessFormDiscordBotConfigFieldValues;
|
||||
onValuesChange?: (values: AccessFormDiscordBotConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): AccessFormDiscordBotConfigFieldValues => {
|
||||
return {
|
||||
botToken: "",
|
||||
};
|
||||
};
|
||||
|
||||
const AccessFormDiscordBotConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormDiscordBotConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
botToken: z
|
||||
.string({ message: t("access.form.discordbot_token.placeholder") })
|
||||
.min(1, t("access.form.discordbot_token.placeholder"))
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 })),
|
||||
defaultChannelId: z.string().nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="botToken"
|
||||
label={t("access.form.discordbot_token.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.discordbot_token.tooltip") }}></span>}
|
||||
>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.discordbot_token.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="defaultChannelId"
|
||||
label={t("access.form.discordbot_default_channel_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.discordbot_default_channel_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input allowClear placeholder={t("access.form.discordbot_default_channel_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default AccessFormDiscordBotConfig;
|
@ -26,8 +26,8 @@ const AccessFormTelegramBotConfig = ({ form: formInst, formName, disabled, initi
|
||||
|
||||
const formSchema = z.object({
|
||||
botToken: z
|
||||
.string({ message: t("access.form.telegram_bot_token.placeholder") })
|
||||
.min(1, t("access.form.telegram_bot_token.placeholder"))
|
||||
.string({ message: t("access.form.telegrambot_token.placeholder") })
|
||||
.min(1, t("access.form.telegrambot_token.placeholder"))
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 })),
|
||||
defaultChatId: z
|
||||
.preprocess(
|
||||
@ -38,7 +38,7 @@ const AccessFormTelegramBotConfig = ({ form: formInst, formName, disabled, initi
|
||||
.refine((v) => {
|
||||
if (v == null || v + "" === "") return true;
|
||||
return !Number.isNaN(+v!) && +v! !== 0;
|
||||
}, t("access.form.telegram_bot_default_chat_id.placeholder"))
|
||||
}, t("access.form.telegrambot_default_chat_id.placeholder"))
|
||||
)
|
||||
.nullish(),
|
||||
});
|
||||
@ -59,20 +59,20 @@ const AccessFormTelegramBotConfig = ({ form: formInst, formName, disabled, initi
|
||||
>
|
||||
<Form.Item
|
||||
name="botToken"
|
||||
label={t("access.form.telegram_bot_token.label")}
|
||||
label={t("access.form.telegrambot_token.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.telegram_bot_token.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.telegrambot_token.tooltip") }}></span>}
|
||||
>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.telegram_bot_token.placeholder")} />
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.telegrambot_token.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="defaultChatId"
|
||||
label={t("access.form.telegram_bot_default_chat_id.label")}
|
||||
label={t("access.form.telegrambot_default_chat_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.telegram_bot_default_chat_id.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.telegrambot_default_chat_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input allowClear placeholder={t("access.form.telegram_bot_default_chat_id.placeholder")} />
|
||||
<Input allowClear placeholder={t("access.form.telegrambot_default_chat_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
|
@ -17,6 +17,7 @@ import { useAntdForm, useAntdFormName, useZustandShallowSelector } from "@/hooks
|
||||
import { useAccessesStore } from "@/stores/access";
|
||||
import { useNotifyChannelsStore } from "@/stores/notify";
|
||||
|
||||
import NotifyNodeConfigFormDiscordBotConfig from "./NotifyNodeConfigFormDiscordBotConfig";
|
||||
import NotifyNodeConfigFormEmailConfig from "./NotifyNodeConfigFormEmailConfig";
|
||||
import NotifyNodeConfigFormMattermostConfig from "./NotifyNodeConfigFormMattermostConfig";
|
||||
import NotifyNodeConfigFormTelegramBotConfig from "./NotifyNodeConfigFormTelegramBotConfig";
|
||||
@ -110,6 +111,8 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
||||
NOTICE: If you add new child component, please keep ASCII order.
|
||||
*/
|
||||
switch (fieldProvider) {
|
||||
case NOTIFICATION_PROVIDERS.DISCORDBOT:
|
||||
return <NotifyNodeConfigFormDiscordBotConfig {...nestedFormProps} />;
|
||||
case NOTIFICATION_PROVIDERS.EMAIL:
|
||||
return <NotifyNodeConfigFormEmailConfig {...nestedFormProps} />;
|
||||
case NOTIFICATION_PROVIDERS.MATTERMOST:
|
||||
|
@ -0,0 +1,61 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
type NotifyNodeConfigFormDiscordBotConfigFieldValues = Nullish<{
|
||||
channelId?: string;
|
||||
}>;
|
||||
|
||||
export type NotifyNodeConfigFormDiscordBotConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: NotifyNodeConfigFormDiscordBotConfigFieldValues;
|
||||
onValuesChange?: (values: NotifyNodeConfigFormDiscordBotConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): NotifyNodeConfigFormDiscordBotConfigFieldValues => {
|
||||
return {};
|
||||
};
|
||||
|
||||
const NotifyNodeConfigFormDiscordBotConfig = ({
|
||||
form: formInst,
|
||||
formName,
|
||||
disabled,
|
||||
initialValues,
|
||||
onValuesChange,
|
||||
}: NotifyNodeConfigFormDiscordBotConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
channelId: z.string().nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="channelId"
|
||||
label={t("workflow_node.notify.form.discordbot_channel_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.notify.form.discordbot_channel_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input allowClear placeholder={t("workflow_node.notify.form.discordbot_channel_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotifyNodeConfigFormDiscordBotConfig;
|
@ -38,7 +38,7 @@ const NotifyNodeConfigFormTelegramBotConfig = ({
|
||||
.refine((v) => {
|
||||
if (v == null || v + "" === "") return true;
|
||||
return !Number.isNaN(+v!) && +v! !== 0;
|
||||
}, t("workflow_node.notify.form.telegram_bot_chat_id.placeholder"))
|
||||
}, t("workflow_node.notify.form.telegrambot_chat_id.placeholder"))
|
||||
)
|
||||
.nullish(),
|
||||
});
|
||||
@ -59,11 +59,11 @@ const NotifyNodeConfigFormTelegramBotConfig = ({
|
||||
>
|
||||
<Form.Item
|
||||
name="chatId"
|
||||
label={t("workflow_node.notify.form.telegram_bot_chat_id.label")}
|
||||
label={t("workflow_node.notify.form.telegrambot_chat_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.notify.form.telegram_bot_chat_id.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.notify.form.telegrambot_chat_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input allowClear placeholder={t("workflow_node.notify.form.telegram_bot_chat_id.placeholder")} />
|
||||
<Input allowClear placeholder={t("workflow_node.notify.form.telegrambot_chat_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
|
@ -26,6 +26,7 @@ export interface AccessModel extends BaseModel {
|
||||
| AccessConfigForDeSEC
|
||||
| AccessConfigForDigitalOcean
|
||||
| AccessConfigForDingTalkBot
|
||||
| AccessConfigForDiscordBot
|
||||
| AccessConfigForDNSLA
|
||||
| AccessConfigForDogeCloud
|
||||
| AccessConfigForDuckDNS
|
||||
@ -181,6 +182,11 @@ export type AccessConfigForDingTalkBot = {
|
||||
secret?: string;
|
||||
};
|
||||
|
||||
export type AccessConfigForDiscordBot = {
|
||||
botToken: string;
|
||||
defaultChannelId?: string;
|
||||
};
|
||||
|
||||
export type AccessConfigForDNSLA = {
|
||||
apiId: string;
|
||||
apiSecret: string;
|
||||
|
@ -25,6 +25,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
|
||||
DESEC: "desec",
|
||||
DIGITALOCEAN: "digitalocean",
|
||||
DINGTALKBOT: "dingtalkbot",
|
||||
DISCORDBOT: "discordbot",
|
||||
DNSLA: "dnsla",
|
||||
DOGECLOUD: "dogecloud",
|
||||
DUCKDNS: "duckdns",
|
||||
@ -172,8 +173,9 @@ export const accessProvidersMap: Map<AccessProvider["type"] | string, AccessProv
|
||||
[ACCESS_PROVIDERS.DINGTALKBOT, "provider.dingtalkbot", "/imgs/providers/dingtalk.svg", [ACCESS_USAGES.NOTIFICATION]],
|
||||
[ACCESS_PROVIDERS.LARKBOT, "provider.larkbot", "/imgs/providers/lark.svg", [ACCESS_USAGES.NOTIFICATION]],
|
||||
[ACCESS_PROVIDERS.WECOMBOT, "provider.wecombot", "/imgs/providers/wecom.svg", [ACCESS_USAGES.NOTIFICATION]],
|
||||
[ACCESS_PROVIDERS.MATTERMOST, "provider.mattermost", "/imgs/providers/mattermost.svg", [ACCESS_USAGES.NOTIFICATION]],
|
||||
[ACCESS_PROVIDERS.DISCORDBOT, "provider.discordbot", "/imgs/providers/discord.svg", [ACCESS_USAGES.NOTIFICATION]],
|
||||
[ACCESS_PROVIDERS.TELEGRAMBOT, "provider.telegrambot", "/imgs/providers/telegram.svg", [ACCESS_USAGES.NOTIFICATION]],
|
||||
[ACCESS_PROVIDERS.MATTERMOST, "provider.mattermost", "/imgs/providers/mattermost.svg", [ACCESS_USAGES.NOTIFICATION]],
|
||||
].map((e) => [
|
||||
e[0] as string,
|
||||
{
|
||||
@ -588,6 +590,7 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
|
||||
*/
|
||||
export const NOTIFICATION_PROVIDERS = Object.freeze({
|
||||
DINGTALKBOT: `${ACCESS_PROVIDERS.DINGTALKBOT}`,
|
||||
DISCORDBOT: `${ACCESS_PROVIDERS.DISCORDBOT}`,
|
||||
EMAIL: `${ACCESS_PROVIDERS.EMAIL}`,
|
||||
LARKBOT: `${ACCESS_PROVIDERS.LARKBOT}`,
|
||||
MATTERMOST: `${ACCESS_PROVIDERS.MATTERMOST}`,
|
||||
@ -616,8 +619,9 @@ export const notificationProvidersMap: Map<NotificationProvider["type"] | string
|
||||
[NOTIFICATION_PROVIDERS.DINGTALKBOT],
|
||||
[NOTIFICATION_PROVIDERS.LARKBOT],
|
||||
[NOTIFICATION_PROVIDERS.WECOMBOT],
|
||||
[NOTIFICATION_PROVIDERS.MATTERMOST],
|
||||
[NOTIFICATION_PROVIDERS.DISCORDBOT],
|
||||
[NOTIFICATION_PROVIDERS.TELEGRAMBOT],
|
||||
[NOTIFICATION_PROVIDERS.MATTERMOST],
|
||||
].map(([type]) => [
|
||||
type,
|
||||
{
|
||||
|
@ -161,6 +161,12 @@
|
||||
"access.form.dingtalkbot_secret.label": "DingTalk bot secret",
|
||||
"access.form.dingtalkbot_secret.placeholder": "Please enter DingTalk bot secret",
|
||||
"access.form.dingtalkbot_secret.tooltip": "For more information, see <a href=\"https://open.dingtalk.com/document/orgapp/customize-robot-security-settings\" target=\"_blank\">https://open.dingtalk.com/document/orgapp/customize-robot-security-settings</a>",
|
||||
"access.form.discordbot_token.label": "Discord bot token",
|
||||
"access.form.discordbot_token.placeholder": "Please enter Discord bot token",
|
||||
"access.form.discordbot_token.tooltip": "How to get it? Please refer to <a href=\"https://docs.discordbotstudio.org/setting-up-dbs/finding-your-bot-token\" target=\"_blank\">https://docs.discordbotstudio.org/setting-up-dbs/finding-your-bot-token</a>",
|
||||
"access.form.discordbot_default_channel_id.label": "Default Discord channel ID (Optional)",
|
||||
"access.form.discordbot_default_channel_id.placeholder": "Please enter default Discord channel ID",
|
||||
"access.form.discordbot_default_channel_id.tooltip": "For more information, see <a href=\"https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID\" target=\"_blank\">https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID</a>",
|
||||
"access.form.dnsla_api_id.label": "DNS.LA API ID",
|
||||
"access.form.dnsla_api_id.placeholder": "Please enter DNS.LA API ID",
|
||||
"access.form.dnsla_api_id.tooltip": "For more information, see <a href=\"https://www.dns.la/docs/ApiDoc\" target=\"_blank\">https://www.dns.la/docs/ApiDoc</a>",
|
||||
@ -284,7 +290,7 @@
|
||||
"access.form.mattermost_password.placeholder": "Please enter Mattermost password",
|
||||
"access.form.mattermost_default_channel_id.label": "Default Mattermost channel ID (Optional)",
|
||||
"access.form.mattermost_default_channel_id.placeholder": "Please enter default Mattermost channel ID",
|
||||
"access.form.mattermost_default_channel_id.tooltip": "How to get the channel ID? Select the target channel from the left sidebar, click on the channel name at the top, and choose ”Channel Details.” You can directly see the channel ID on the pop-up page.",
|
||||
"access.form.mattermost_default_channel_id.tooltip": "How to get it? Select the target channel from the left sidebar, click on the channel name at the top, and choose ”Channel Details.” You can directly see the channel ID on the pop-up page.",
|
||||
"access.form.namecheap_username.label": "Namecheap username",
|
||||
"access.form.namecheap_username.placeholder": "Please enter Namecheap username",
|
||||
"access.form.namecheap_username.tooltip": "For more information, see <a href=\"https://www.namecheap.com/support/api/intro/\" target=\"_blank\">https://www.namecheap.com/support/api/intro/</a>",
|
||||
@ -380,12 +386,12 @@
|
||||
"access.form.sslcom_eab_hmac_key.label": "ACME EAB HMAC key",
|
||||
"access.form.sslcom_eab_hmac_key.placeholder": "Please enter ACME EAB HMAC key",
|
||||
"access.form.sslcom_eab_hmac_key.tooltip": "For more information, see <a href=\"https://www.ssl.com/how-to/generate-acme-credentials-for-reseller-customers/#ftoc-heading-6\" target=\"_blank\">https://www.ssl.com/how-to/generate-acme-credentials-for-reseller-customers/</a>",
|
||||
"access.form.telegram_bot_token.label": "Telegram bot token",
|
||||
"access.form.telegram_bot_token.placeholder": "Please enter Telegram bot token",
|
||||
"access.form.telegram_bot_token.tooltip": "How to get the bot token? Please refer to <a href=\"https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a\" target=\"_blank\">https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a</a>",
|
||||
"access.form.telegram_bot_default_chat_id.label": "Default Telegram chat ID (Optional)",
|
||||
"access.form.telegram_bot_default_chat_id.placeholder": "Please enter default Telegram chat ID",
|
||||
"access.form.telegram_bot_default_chat_id.tooltip": "How to get the chat ID? Please refer to <a href=\"https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a\" target=\"_blank\">https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a</a>",
|
||||
"access.form.telegrambot_token.label": "Telegram bot token",
|
||||
"access.form.telegrambot_token.placeholder": "Please enter Telegram bot token",
|
||||
"access.form.telegrambot_token.tooltip": "How to get it? Please refer to <a href=\"https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a\" target=\"_blank\">https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a</a>",
|
||||
"access.form.telegrambot_default_chat_id.label": "Default Telegram chat ID (Optional)",
|
||||
"access.form.telegrambot_default_chat_id.placeholder": "Please enter default Telegram chat ID",
|
||||
"access.form.telegrambot_default_chat_id.tooltip": "How to get it? Please refer to <a href=\"https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a\" target=\"_blank\">https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a</a>",
|
||||
"access.form.tencentcloud_secret_id.label": "Tencent Cloud SecretId",
|
||||
"access.form.tencentcloud_secret_id.placeholder": "Please enter Tencent Cloud SecretId",
|
||||
"access.form.tencentcloud_secret_id.tooltip": "For more information, see <a href=\"https://cloud.tencent.com/document/product/598/40488?lang=en\" target=\"_blank\">https://cloud.tencent.com/document/product/598/40488?lang=en</a>",
|
||||
|
@ -60,6 +60,7 @@
|
||||
"provider.desec": "deSEC",
|
||||
"provider.digitalocean": "DigitalOcean",
|
||||
"provider.dingtalkbot": "DingTalk Bot",
|
||||
"provider.discordbot": "Discord Bot",
|
||||
"provider.dnsla": "DNS.LA",
|
||||
"provider.dogecloud": "Doge Cloud",
|
||||
"provider.dogecloud.cdn": "Doge Cloud - CDN (Content Delivery Network)",
|
||||
|
@ -815,6 +815,9 @@
|
||||
"workflow_node.notify.form.provider_access.placeholder": "Please select an authorization of notification provider",
|
||||
"workflow_node.notify.form.provider_access.button": "Create",
|
||||
"workflow_node.notify.form.params_config.label": "Parameter settings",
|
||||
"workflow_node.notify.form.discordbot_channel_id.label": "Discord channel ID (Optional)",
|
||||
"workflow_node.notify.form.discordbot_channel_id.placeholder": "Please enter Discord channel ID to override the default value",
|
||||
"workflow_node.notify.form.discordbot_channel_id.tooltip": "Leave it blank to use the default channel ID provided by the authorization.",
|
||||
"workflow_node.notify.form.email_sender_address.label": "Sender email address (Optional)",
|
||||
"workflow_node.notify.form.email_sender_address.placeholder": "Please enter sender email address to override the default value",
|
||||
"workflow_node.notify.form.email_sender_address.tooltip": "Leave it blank to use the default sender email address provided by the authorization.",
|
||||
@ -822,11 +825,11 @@
|
||||
"workflow_node.notify.form.email_receiver_address.placeholder": "Please enter receiver email address to override the default value",
|
||||
"workflow_node.notify.form.email_receiver_address.tooltip": "Leave it blank to use the default receiver email address provided by the selected authorization.",
|
||||
"workflow_node.notify.form.mattermost_channel_id.label": "Mattermost channel ID (Optional)",
|
||||
"workflow_node.notify.form.mattermost_channel_id.placeholder": "Please enter Mattermost channel ID to override the default value",
|
||||
"workflow_node.notify.form.mattermost_channel_id.placeholder": "Please enter Mattermost channel ID to override the default value",
|
||||
"workflow_node.notify.form.mattermost_channel_id.tooltip": "Leave it blank to use the default channel ID provided by the authorization.",
|
||||
"workflow_node.notify.form.telegram_bot_chat_id.label": "Telegram chat ID (Optional)",
|
||||
"workflow_node.notify.form.telegram_bot_chat_id.placeholder": "Please enter Telegram chat ID to override the default value",
|
||||
"workflow_node.notify.form.telegram_bot_chat_id.tooltip": "Leave it blank to use the default chat ID provided by the selected authorization.",
|
||||
"workflow_node.notify.form.telegrambot_chat_id.label": "Telegram chat ID (Optional)",
|
||||
"workflow_node.notify.form.telegrambot_chat_id.placeholder": "Please enter Telegram chat ID to override the default value",
|
||||
"workflow_node.notify.form.telegrambot_chat_id.tooltip": "Leave it blank to use the default chat ID provided by the selected authorization.",
|
||||
"workflow_node.notify.form.webhook_data.label": "Webhook data (Optional)",
|
||||
"workflow_node.notify.form.webhook_data.placeholder": "Please enter Webhook data to override the default value",
|
||||
"workflow_node.notify.form.webhook_data.tooltip": "Leave it blank to use the default Webhook data provided by the authorization.",
|
||||
|
@ -155,6 +155,12 @@
|
||||
"access.form.dingtalkbot_secret.label": "钉钉群机器人加签密钥",
|
||||
"access.form.dingtalkbot_secret.placeholder": "请输入钉钉群机器人加签密钥",
|
||||
"access.form.dingtalkbot_secret.tooltip": "这是什么?请参阅 <a href=\"https://open.dingtalk.com/document/orgapp/customize-robot-security-settings\" target=\"_blank\">https://open.dingtalk.com/document/orgapp/customize-robot-security-settings</a>",
|
||||
"access.form.discordbot_token.label": "Discord 机器人 API Token",
|
||||
"access.form.discordbot_token.placeholder": "请输入 Discord 机器人 API Token",
|
||||
"access.form.discordbot_token.tooltip": "如何获取此参数?请参阅 <a href=\"https://docs.discordbotstudio.org/setting-up-dbs/finding-your-bot-token\" target=\"_blank\">https://docs.discordbotstudio.org/setting-up-dbs/finding-your-bot-token</a>",
|
||||
"access.form.discordbot_default_channel_id.label": "默认的 Discord 频道 ID(可选)",
|
||||
"access.form.discordbot_default_channel_id.placeholder": "请输入默认的 Discord 频道 ID",
|
||||
"access.form.discordbot_default_channel_id.tooltip": "这是什么?请参阅 <a href=\"https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID\" target=\"_blank\">https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID</a>",
|
||||
"access.form.dnsla_api_id.label": "DNS.LA API ID",
|
||||
"access.form.dnsla_api_id.placeholder": "请输入 DNS.LA API ID",
|
||||
"access.form.dnsla_api_id.tooltip": "这是什么?请参阅 <a href=\"https://www.dns.la/docs/ApiDoc\" target=\"_blank\">https://www.dns.la/docs/ApiDoc</a>",
|
||||
@ -278,7 +284,7 @@
|
||||
"access.form.mattermost_password.placeholder": "请输入 Mattermost 密码",
|
||||
"access.form.mattermost_default_channel_id.label": "默认的 Mattermost 频道 ID(可选)",
|
||||
"access.form.mattermost_default_channel_id.placeholder": "请输入默认的 Mattermost 频道 ID",
|
||||
"access.form.mattermost_default_channel_id.tooltip": "如何获取频道 ID?从左侧边栏中选择目标频道,点击顶部的频道名称,选择“频道详情”,即可在弹出页面中直接看到频道 ID。",
|
||||
"access.form.mattermost_default_channel_id.tooltip": "如何获取此参数?从左侧边栏中选择目标频道,点击顶部的频道名称,选择“频道详情”,即可在弹出页面中直接看到频道 ID。",
|
||||
"access.form.namecheap_username.label": "Namecheap 用户名",
|
||||
"access.form.namecheap_username.placeholder": "请输入 Namecheap 用户名",
|
||||
"access.form.namecheap_username.tooltip": "这是什么?请参阅 <a href=\"https://www.namecheap.com/support/api/intro/\" target=\"_blank\">https://www.namecheap.com/support/api/intro/</a>",
|
||||
@ -374,12 +380,12 @@
|
||||
"access.form.sslcom_eab_hmac_key.label": "ACME EAB HMAC key",
|
||||
"access.form.sslcom_eab_hmac_key.placeholder": "请输入 ACME EAB HMAC key",
|
||||
"access.form.sslcom_eab_hmac_key.tooltip": "这是什么?请参阅 <a href=\"https://www.ssl.com/how-to/generate-acme-credentials-for-reseller-customers/#ftoc-heading-6\" target=\"_blank\">https://www.ssl.com/how-to/generate-acme-credentials-for-reseller-customers/</a>",
|
||||
"access.form.telegram_bot_token.label": "Telegram 群机器人 API Token",
|
||||
"access.form.telegram_bot_token.placeholder": "请输入 Telegram 群机器人 API Token",
|
||||
"access.form.telegram_bot_token.tooltip": "如何获取机器人 API Token?请参阅 <a href=\"https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a\" target=\"_blank\">https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a</a>",
|
||||
"access.form.telegram_bot_default_chat_id.label": "默认的 Telegram 会话 ID(可选)",
|
||||
"access.form.telegram_bot_default_chat_id.placeholder": "请输入默认的 Telegram 会话 ID",
|
||||
"access.form.telegram_bot_default_chat_id.tooltip": "如何获取会话 ID?请参阅 <a href=\"https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a\" target=\"_blank\">https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a</a>",
|
||||
"access.form.telegrambot_token.label": "Telegram 机器人 API Token",
|
||||
"access.form.telegrambot_token.placeholder": "请输入 Telegram 机器人 API Token",
|
||||
"access.form.telegrambot_token.tooltip": "如何获取此参数?请参阅 <a href=\"https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a\" target=\"_blank\">https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a</a>",
|
||||
"access.form.telegrambot_default_chat_id.label": "默认的 Telegram 会话 ID(可选)",
|
||||
"access.form.telegrambot_default_chat_id.placeholder": "请输入默认的 Telegram 会话 ID",
|
||||
"access.form.telegrambot_default_chat_id.tooltip": "如何获取此参数?请参阅 <a href=\"https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a\" target=\"_blank\">https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a</a>",
|
||||
"access.form.tencentcloud_secret_id.label": "腾讯云 SecretId",
|
||||
"access.form.tencentcloud_secret_id.placeholder": "请输入腾讯云 SecretId",
|
||||
"access.form.tencentcloud_secret_id.tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/598/40488\" target=\"_blank\">https://cloud.tencent.com/document/product/598/40488</a>",
|
||||
|
@ -60,6 +60,7 @@
|
||||
"provider.desec": "deSEC",
|
||||
"provider.digitalocean": "DigitalOcean",
|
||||
"provider.dingtalkbot": "钉钉群机器人",
|
||||
"provider.discordbot": "Discord 机器人",
|
||||
"provider.dnsla": "DNS.LA",
|
||||
"provider.dogecloud": "多吉云",
|
||||
"provider.dogecloud.cdn": "多吉云 - 内容分发网络 CDN",
|
||||
@ -119,7 +120,7 @@
|
||||
"provider.safeline": "雷池",
|
||||
"provider.ssh": "SSH 部署",
|
||||
"provider.sslcom": "SSL.com",
|
||||
"provider.telegrambot": "Telegram 群机器人",
|
||||
"provider.telegrambot": "Telegram 机器人",
|
||||
"provider.tencentcloud": "腾讯云",
|
||||
"provider.tencentcloud.cdn": "腾讯云 - 内容分发网络 CDN",
|
||||
"provider.tencentcloud.clb": "腾讯云 - 负载均衡 CLB",
|
||||
|
@ -814,6 +814,9 @@
|
||||
"workflow_node.notify.form.provider_access.placeholder": "请选择通知渠道授权",
|
||||
"workflow_node.notify.form.provider_access.button": "新建",
|
||||
"workflow_node.notify.form.params_config.label": "参数设置",
|
||||
"workflow_node.notify.form.discordbot_channel_id.label": "Discord 频道 ID(可选)",
|
||||
"workflow_node.notify.form.discordbot_channel_id.placeholder": "请输入 Discord 频道 ID 以覆盖默认值",
|
||||
"workflow_node.notify.form.discordbot_channel_id.tooltip": "不填写时,将使用所选通知渠道授权的默认频道 ID。",
|
||||
"workflow_node.notify.form.email_sender_address.label": "发送邮箱地址(可选)",
|
||||
"workflow_node.notify.form.email_sender_address.placeholder": "请输入发送邮箱地址以覆盖默认值",
|
||||
"workflow_node.notify.form.email_sender_address.tooltip": "不填写时,将使用所选通知渠道授权的默认发送邮箱地址。",
|
||||
@ -823,9 +826,9 @@
|
||||
"workflow_node.notify.form.mattermost_channel_id.label": "Mattermost 频道 ID(可选)",
|
||||
"workflow_node.notify.form.mattermost_channel_id.placeholder": "请输入 Mattermost 频道 ID 以覆盖默认值",
|
||||
"workflow_node.notify.form.mattermost_channel_id.tooltip": "不填写时,将使用所选通知渠道授权的默认频道 ID。",
|
||||
"workflow_node.notify.form.telegram_bot_chat_id.label": "Telegram 会话 ID(可选)",
|
||||
"workflow_node.notify.form.telegram_bot_chat_id.placeholder": "请输入 Telegram 会话 ID 以覆盖默认值",
|
||||
"workflow_node.notify.form.telegram_bot_chat_id.tooltip": "不填写时,将使用所选通知渠道授权的默认会话 ID。",
|
||||
"workflow_node.notify.form.telegrambot_chat_id.label": "Telegram 会话 ID(可选)",
|
||||
"workflow_node.notify.form.telegrambot_chat_id.placeholder": "请输入 Telegram 会话 ID 以覆盖默认值",
|
||||
"workflow_node.notify.form.telegrambot_chat_id.tooltip": "不填写时,将使用所选通知渠道授权的默认会话 ID。",
|
||||
"workflow_node.notify.form.webhook_data.label": "Webhook 回调数据(可选)",
|
||||
"workflow_node.notify.form.webhook_data.placeholder": "请输入 Webhook 回调数据以覆盖默认值",
|
||||
"workflow_node.notify.form.webhook_data.tooltip": "不填写时,将使用所选部署目标授权的默认 Webhook 回调数据。",
|
||||
|
Loading…
x
Reference in New Issue
Block a user