From 62ad00870bf716d6976648b40949e2cae4e03ecc Mon Sep 17 00:00:00 2001
From: tim20061 <116635896+tim20061@users.noreply.github.com>
Date: Mon, 15 Jun 2026 18:18:48 +0300
Subject: [PATCH] feat(provider): new notification provider: matrix
---
internal/domain/access.go | 7 ++
internal/domain/provider.go | 2 +
internal/notify/notifiers/sp_matrix.go | 27 ++++++
pkg/core/notifier/providers/matrix/matrix.go | 73 +++++++++++++++
.../notifier/providers/matrix/matrix_test.go | 51 +++++++++++
pkg/sdk3rd/matrix/api_send_message.go | 36 ++++++++
pkg/sdk3rd/matrix/api_versions.go | 17 ++++
pkg/sdk3rd/matrix/client.go | 88 +++++++++++++++++++
pkg/sdk3rd/matrix/options.go | 20 +++++
ui/public/imgs/providers/matrix.svg | 1 +
.../forms/AccessConfigFieldsProvider.tsx | 2 +
.../AccessConfigFieldsProviderMatrix.tsx | 88 +++++++++++++++++++
.../BizNotifyNodeConfigFieldsProvider.tsx | 2 +
...izNotifyNodeConfigFieldsProviderMatrix.tsx | 49 +++++++++++
ui/src/domain/provider.ts | 4 +
ui/src/i18n/resources/en/nls.access.json | 22 ++++-
ui/src/i18n/resources/en/nls.provider.json | 1 +
.../i18n/resources/en/nls.workflow.nodes.json | 15 ++--
ui/src/i18n/resources/zh/nls.access.json | 22 +++++
ui/src/i18n/resources/zh/nls.provider.json | 1 +
.../i18n/resources/zh/nls.workflow.nodes.json | 6 ++
21 files changed, 528 insertions(+), 6 deletions(-)
create mode 100644 internal/notify/notifiers/sp_matrix.go
create mode 100644 pkg/core/notifier/providers/matrix/matrix.go
create mode 100644 pkg/core/notifier/providers/matrix/matrix_test.go
create mode 100644 pkg/sdk3rd/matrix/api_send_message.go
create mode 100644 pkg/sdk3rd/matrix/api_versions.go
create mode 100644 pkg/sdk3rd/matrix/client.go
create mode 100644 pkg/sdk3rd/matrix/options.go
create mode 100644 ui/public/imgs/providers/matrix.svg
create mode 100644 ui/src/components/access/forms/AccessConfigFieldsProviderMatrix.tsx
create mode 100644 ui/src/components/workflow/designer/forms/BizNotifyNodeConfigFieldsProviderMatrix.tsx
diff --git a/internal/domain/access.go b/internal/domain/access.go
index 94fa1f70..d21c820a 100644
--- a/internal/domain/access.go
+++ b/internal/domain/access.go
@@ -398,6 +398,13 @@ type AccessConfigForLiteSSL struct {
AccessConfigForACMEExternalAccountBinding
}
+type AccessConfigForMatrix struct {
+ ServerUrl string `json:"serverUrl"`
+ UserId string `json:"userId"`
+ AccessToken string `json:"accessToken"`
+ RoomId string `json:"roomId,omitempty"`
+}
+
type AccessConfigForMattermost struct {
ServerUrl string `json:"serverUrl"`
Username string `json:"username"`
diff --git a/internal/domain/provider.go b/internal/domain/provider.go
index 4c67f554..8d5f57b7 100644
--- a/internal/domain/provider.go
+++ b/internal/domain/provider.go
@@ -89,6 +89,7 @@ const (
AccessProviderTypeLinode = AccessProviderType("linode")
AccessProviderTypeLiteSSL = AccessProviderType("litessl")
AccessProviderTypeLocal = AccessProviderType("local")
+ AccessProviderTypeMatrix = AccessProviderType("matrix")
AccessProviderTypeMattermost = AccessProviderType("mattermost")
AccessProviderTypeMohua = AccessProviderType("mohua")
AccessProviderTypeNamecheap = AccessProviderType("namecheap")
@@ -473,6 +474,7 @@ const (
NotificationProviderTypeDiscordBot = NotificationProviderType(AccessProviderTypeDiscordBot)
NotificationProviderTypeEmail = NotificationProviderType(AccessProviderTypeEmail)
NotificationProviderTypeLarkBot = NotificationProviderType(AccessProviderTypeLarkBot)
+ NotificationProviderTypeMatrix = NotificationProviderType(AccessProviderTypeMatrix)
NotificationProviderTypeMattermost = NotificationProviderType(AccessProviderTypeMattermost)
NotificationProviderTypeSlackBot = NotificationProviderType(AccessProviderTypeSlackBot)
NotificationProviderTypeTelegramBot = NotificationProviderType(AccessProviderTypeTelegramBot)
diff --git a/internal/notify/notifiers/sp_matrix.go b/internal/notify/notifiers/sp_matrix.go
new file mode 100644
index 00000000..1dd3f652
--- /dev/null
+++ b/internal/notify/notifiers/sp_matrix.go
@@ -0,0 +1,27 @@
+package notifiers
+
+import (
+ "fmt"
+
+ "github.com/certimate-go/certimate/internal/domain"
+ "github.com/certimate-go/certimate/pkg/core"
+ "github.com/certimate-go/certimate/pkg/core/notifier/providers/matrix"
+ xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
+)
+
+func init() {
+ Registries.MustRegister(domain.NotificationProviderTypeMatrix, func(options *ProviderFactoryOptions) (core.Notifier, error) {
+ credentials := domain.AccessConfigForMatrix{}
+ if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ provider, err := matrix.NewNotifier(&matrix.NotifierConfig{
+ ServerUrl: credentials.ServerUrl,
+ UserId: credentials.UserId,
+ AccessToken: credentials.AccessToken,
+ RoomId: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "roomId", credentials.RoomId),
+ })
+ return provider, err
+ })
+}
diff --git a/pkg/core/notifier/providers/matrix/matrix.go b/pkg/core/notifier/providers/matrix/matrix.go
new file mode 100644
index 00000000..7e168108
--- /dev/null
+++ b/pkg/core/notifier/providers/matrix/matrix.go
@@ -0,0 +1,73 @@
+package matrix
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "log/slog"
+
+ "github.com/certimate-go/certimate/pkg/core/notifier"
+ matrixsdk "github.com/certimate-go/certimate/pkg/sdk3rd/matrix"
+)
+
+type NotifierConfig struct {
+ // Homeserver URL (Element web URL or Matrix homeserver base URL).
+ // URL homeserver (адрес Element или базовый URL Matrix).
+ ServerUrl string `json:"serverUrl"`
+ // User ID (MXID), e.g. @bot:example.org.
+ // Идентификатор пользователя (MXID), например @bot:example.org.
+ UserId string `json:"userId"`
+ // Access token from the homeserver (bot or user).
+ // Access token с homeserver (бот или пользователь).
+ AccessToken string `json:"accessToken"`
+ // Room ID (!room:server) for notifications.
+ // ID комнаты (!room:server) для уведомлений.
+ RoomId string `json:"roomId"`
+}
+
+type Notifier struct {
+ config *NotifierConfig
+ logger *slog.Logger
+}
+
+var _ notifier.Provider = (*Notifier)(nil)
+
+func NewNotifier(config *NotifierConfig) (*Notifier, error) {
+ if config == nil {
+ return nil, errors.New("the configuration of the notifier provider is nil")
+ }
+
+ return &Notifier{
+ config: config,
+ logger: slog.Default(),
+ }, nil
+}
+
+func (n *Notifier) SetLogger(logger *slog.Logger) {
+ if logger == nil {
+ n.logger = slog.New(slog.DiscardHandler)
+ } else {
+ n.logger = logger
+ }
+}
+
+func (n *Notifier) Notify(ctx context.Context, subject string, message string) (*notifier.NotifyResult, error) {
+ if n.config.RoomId == "" {
+ return nil, errors.New("matrix: config `roomId` is required")
+ }
+
+ client, err := matrixsdk.NewClient(n.config.ServerUrl,
+ matrixsdk.WithUserId(n.config.UserId),
+ matrixsdk.WithAccessToken(n.config.AccessToken),
+ )
+ if err != nil {
+ return nil, fmt.Errorf("matrix: %w", err)
+ }
+
+ body := fmt.Sprintf("%s\n\n%s", subject, message)
+ if err := client.SendTextMessageToRoom(ctx, n.config.RoomId, body); err != nil {
+ return nil, fmt.Errorf("matrix: %w", err)
+ }
+
+ return ¬ifier.NotifyResult{}, nil
+}
diff --git a/pkg/core/notifier/providers/matrix/matrix_test.go b/pkg/core/notifier/providers/matrix/matrix_test.go
new file mode 100644
index 00000000..e8fcb8db
--- /dev/null
+++ b/pkg/core/notifier/providers/matrix/matrix_test.go
@@ -0,0 +1,51 @@
+package matrix_test
+
+import (
+ "testing"
+
+ "github.com/certimate-go/certimate/pkg/core/notifier/internal/tester"
+ impl "github.com/certimate-go/certimate/pkg/core/notifier/providers/matrix"
+)
+
+var (
+ fp = tester.Args("MATRIX_")
+ fServerUrl string
+ fUserId string
+ fAccessToken string
+ fRoomId string
+)
+
+func init() {
+ fp.DefineString(&fServerUrl, "SERVERURL")
+ fp.DefineString(&fUserId, "USERID")
+ fp.DefineString(&fAccessToken, "ACCESSTOKEN")
+ fp.DefineString(&fRoomId, "ROOMID")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./matrix_test.go -args \
+ --MATRIX_SERVERURL="https://example.com/your-matrix-server" \
+ --MATRIX_USERID="@bot:example.org" \
+ --MATRIX_ACCESSTOKEN="your-access-token" \
+ --MATRIX_ROOMID="!room:example.org"
+*/
+func TestProvider(t *testing.T) {
+ fp.Parse()
+
+ t.Run("Notify", func(t *testing.T) {
+ provider, err := impl.NewNotifier(&impl.NotifierConfig{
+ ServerUrl: fServerUrl,
+ UserId: fUserId,
+ AccessToken: fAccessToken,
+ RoomId: fRoomId,
+ })
+ if err != nil {
+ t.Errorf("err: %+v", err)
+ return
+ }
+
+ tester.TestNotify(t, provider, tester.TestNotifyArgs{})
+ })
+}
diff --git a/pkg/sdk3rd/matrix/api_send_message.go b/pkg/sdk3rd/matrix/api_send_message.go
new file mode 100644
index 00000000..36b22624
--- /dev/null
+++ b/pkg/sdk3rd/matrix/api_send_message.go
@@ -0,0 +1,36 @@
+package matrix
+
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "strings"
+)
+
+// SendText posts an m.room.message event (m.text).
+// Отправляет текстовое сообщение в комнату (m.room.message, msgtype m.text).
+// REF: https://spec.matrix.org/latest/client-server-api/#put_matrixclientv3roomsroomidsendeventtypetxnid
+func (c *Client) SendTextMessageToRoom(ctx context.Context, roomId, msgBody string) error {
+ if strings.TrimSpace(roomId) == "" {
+ return fmt.Errorf("sdkerr: unset roomId")
+ }
+
+ txnId := newTransactionId()
+ path := fmt.Sprintf("/_matrix/client/v3/rooms/%s/send/m.room.message/%s",
+ url.PathEscape(roomId), url.PathEscape(txnId))
+
+ payload := map[string]any{
+ "msgtype": "m.text",
+ "body": msgBody,
+ }
+
+ _, err := c.rc.R().
+ SetContext(ctx).
+ SetBody(payload).
+ Put(path)
+ if err != nil {
+ return fmt.Errorf("sdkerr: api error: %w", err)
+ }
+
+ return nil
+}
diff --git a/pkg/sdk3rd/matrix/api_versions.go b/pkg/sdk3rd/matrix/api_versions.go
new file mode 100644
index 00000000..94eb52cc
--- /dev/null
+++ b/pkg/sdk3rd/matrix/api_versions.go
@@ -0,0 +1,17 @@
+package matrix
+
+import (
+ "fmt"
+)
+
+// probeVersions checks that the homeserver exposes the Client-Server API.
+// Проверяет доступность homeserver (GET /_matrix/client/versions).
+// REF: https://spec.matrix.org/latest/client-server-api/#get_matrixclientversions
+func (c *Client) probeVersions() error {
+ _, err := c.rc.R().Get("/_matrix/client/versions")
+ if err != nil {
+ return fmt.Errorf("sdkerr: failed to probe Matrix Client API versions: %w", err)
+ }
+
+ return nil
+}
diff --git a/pkg/sdk3rd/matrix/client.go b/pkg/sdk3rd/matrix/client.go
new file mode 100644
index 00000000..6da4411c
--- /dev/null
+++ b/pkg/sdk3rd/matrix/client.go
@@ -0,0 +1,88 @@
+package matrix
+
+import (
+ "crypto/rand"
+ "crypto/tls"
+ "encoding/hex"
+ "fmt"
+ "net/url"
+ "strings"
+ "time"
+
+ "github.com/go-resty/resty/v2"
+
+ "github.com/certimate-go/certimate/internal/app"
+)
+
+type Client struct {
+ rc *resty.Client
+}
+
+func NewClient(serverUrl string, optFns ...OptionsFunc) (*Client, error) {
+ opts := &Options{}
+ for _, fn := range optFns {
+ fn(opts)
+ }
+
+ if serverUrl == "" {
+ return nil, fmt.Errorf("sdkerr: unset serverUrl")
+ }
+ if _, err := url.Parse(serverUrl); err != nil {
+ return nil, fmt.Errorf("sdkerr: invalid serverUrl: %w", err)
+ }
+ if opts.AccessToken == "" {
+ return nil, fmt.Errorf("sdkerr: unset accessToken")
+ }
+
+ baseUrl, _ := resolveBaseUrl(strings.TrimSuffix(serverUrl, "/"))
+ if baseUrl == "" {
+ baseUrl = serverUrl
+ }
+
+ client := &Client{}
+ client.rc = resty.New().
+ SetBaseURL(strings.TrimSuffix(baseUrl, "/")).
+ SetHeader("Authorization", "Bearer "+opts.AccessToken).
+ SetHeader("Content-Type", "application/json").
+ SetHeader("User-Agent", app.AppUserAgent).
+ if err := client.probeVersions(); err != nil {
+ return nil, err
+ }
+
+ return client, nil
+}
+
+func (c *Client) SetTimeout(timeout time.Duration) *Client {
+ c.rc.SetTimeout(timeout)
+ return c
+}
+
+func (c *Client) SetTLSConfig(config *tls.Config) *Client {
+ c.rc.SetTLSClientConfig(config)
+ return c
+}
+
+func resolveBaseUrl(serverUrl string) (string, error) {
+ var wkJSON struct {
+ Homeserver struct {
+ BaseURL string `json:"base_url"`
+ } `json:"m.homeserver"`
+ }
+
+ _, err := resty.New().R().
+ SetResult(&wkJSON).
+ Get(serverUrl + "/.well-known/matrix/client")
+ if err != nil {
+ return "", fmt.Errorf("failed to discovery Matrix Client API: %w", err)
+ } else if strings.TrimSpace(wkJSON.Homeserver.BaseURL) != "" {
+ return wkJSON.Homeserver.BaseURL, nil
+ } else {
+ return serverUrl, nil
+ }
+}
+
+func newTransactionId() string {
+ b := make([]byte, 8)
+ _, _ = rand.Read(b)
+ return fmt.Sprintf("certimate_%d_%s", time.Now().UnixNano(), hex.EncodeToString(b))
+}
diff --git a/pkg/sdk3rd/matrix/options.go b/pkg/sdk3rd/matrix/options.go
new file mode 100644
index 00000000..583b6bd5
--- /dev/null
+++ b/pkg/sdk3rd/matrix/options.go
@@ -0,0 +1,20 @@
+package matrix
+
+type Options struct {
+ UserId string
+ AccessToken string
+}
+
+type OptionsFunc func(*Options)
+
+func WithUserId(userId string) OptionsFunc {
+ return func(o *Options) {
+ o.UserId = userId
+ }
+}
+
+func WithAccessToken(accessToken string) OptionsFunc {
+ return func(o *Options) {
+ o.AccessToken = accessToken
+ }
+}
diff --git a/ui/public/imgs/providers/matrix.svg b/ui/public/imgs/providers/matrix.svg
new file mode 100644
index 00000000..95c28770
--- /dev/null
+++ b/ui/public/imgs/providers/matrix.svg
@@ -0,0 +1 @@
+
diff --git a/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx b/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx
index 16adf2a3..a6cc62e9 100644
--- a/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx
+++ b/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx
@@ -73,6 +73,7 @@ import AccessConfigFieldsProviderLarkBot from "./AccessConfigFieldsProviderLarkB
import AccessConfigFieldsProviderLeCDN from "./AccessConfigFieldsProviderLeCDN";
import AccessConfigFieldsProviderLinode from "./AccessConfigFieldsProviderLinode";
import AccessConfigFieldsProviderLiteSSL from "./AccessConfigFieldsProviderLiteSSL";
+import AccessConfigFieldsProviderMatrix from "./AccessConfigFieldsProviderMatrix";
import AccessConfigFieldsProviderMattermost from "./AccessConfigFieldsProviderMattermost";
import AccessConfigFieldsProviderMohua from "./AccessConfigFieldsProviderMohua";
import AccessConfigFieldsProviderNamecheap from "./AccessConfigFieldsProviderNamecheap";
@@ -196,6 +197,7 @@ const providerComponentMap: Partial {
+ const { i18n, t } = useTranslation();
+
+ const { parentNamePath } = useFormNestedFieldsContext();
+ const formSchema = z.object({
+ [parentNamePath]: getSchema({ i18n }),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+ const initialValues = getInitialValues();
+
+ return (
+ <>
+
+
+
+
+ }
+ >
+
+
+
+ }
+ >
+
+
+
+ }
+ >
+
+
+ >
+ );
+};
+
+const getInitialValues = (): Nullish>> => {
+ return {
+ serverUrl: "https://matrix-client.matrix.org",
+ userId: "",
+ accessToken: "",
+ roomId: "",
+ };
+};
+
+const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType }) => {
+ const { t: _ } = i18n;
+
+ return z.object({
+ serverUrl: z.url({ protocol: core.regexes.httpProtocol }),
+ userId: z.string().nonempty().startsWith("@"),
+ accessToken: z.string().nonempty(),
+ roomId: z.string().nullish(),
+ });
+};
+
+const _default = Object.assign(AccessConfigFormFieldsProviderMatrix, {
+ getInitialValues,
+ getSchema,
+});
+
+export default _default;
diff --git a/ui/src/components/workflow/designer/forms/BizNotifyNodeConfigFieldsProvider.tsx b/ui/src/components/workflow/designer/forms/BizNotifyNodeConfigFieldsProvider.tsx
index f62347aa..38ba65d3 100644
--- a/ui/src/components/workflow/designer/forms/BizNotifyNodeConfigFieldsProvider.tsx
+++ b/ui/src/components/workflow/designer/forms/BizNotifyNodeConfigFieldsProvider.tsx
@@ -4,6 +4,7 @@ import { NOTIFICATION_PROVIDERS, type NotificationProviderType } from "@/domain/
import BizNotifyNodeConfigFieldsProviderDiscordBot from "./BizNotifyNodeConfigFieldsProviderDiscordBot";
import BizNotifyNodeConfigFieldsProviderEmail from "./BizNotifyNodeConfigFieldsProviderEmail";
+import BizNotifyNodeConfigFieldsProviderMatrix from "./BizNotifyNodeConfigFieldsProviderMatrix";
import BizNotifyNodeConfigFieldsProviderMattermost from "./BizNotifyNodeConfigFieldsProviderMattermost";
import BizNotifyNodeConfigFieldsProviderSlackBot from "./BizNotifyNodeConfigFieldsProviderSlackBot";
import BizNotifyNodeConfigFieldsProviderTelegramBot from "./BizNotifyNodeConfigFieldsProviderTelegramBot";
@@ -16,6 +17,7 @@ const providerComponentMap: Partial {
+ const { i18n, t } = useTranslation();
+
+ const { parentNamePath } = useFormNestedFieldsContext();
+ const formSchema = z.object({
+ [parentNamePath]: getSchema({ i18n }),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+ const initialValues = getInitialValues();
+
+ return (
+ <>
+
+
+
+ >
+ );
+};
+
+const getInitialValues = (): Nullish> => {
+ return {};
+};
+
+const getSchema = (_opts?: { i18n?: ReturnType }) => {
+ return z.object({
+ roomId: z.string().nullish(),
+ });
+};
+
+const _default = Object.assign(BizNotifyNodeConfigFieldsProviderMatrix, {
+ getInitialValues,
+ getSchema,
+});
+
+export default _default;
diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts
index 4d5cf6ae..2cf23ad7 100644
--- a/ui/src/domain/provider.ts
+++ b/ui/src/domain/provider.ts
@@ -89,6 +89,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
LINODE: "linode",
LITESSL: "litessl",
LOCAL: "local",
+ MATRIX: "matrix",
MATTERMOST: "mattermost",
MOHUA: "mohua",
NAMECHEAP: "namecheap",
@@ -283,6 +284,7 @@ export const accessProvidersMap: Map
).map(([type, name, icon, usages, builtin]) => [
@@ -943,6 +945,7 @@ export const NOTIFICATION_PROVIDERS = Object.freeze({
DISCORDBOT: `${ACCESS_PROVIDERS.DISCORDBOT}`,
EMAIL: `${ACCESS_PROVIDERS.EMAIL}`,
LARKBOT: `${ACCESS_PROVIDERS.LARKBOT}`,
+ MATRIX: `${ACCESS_PROVIDERS.MATRIX}`,
MATTERMOST: `${ACCESS_PROVIDERS.MATTERMOST}`,
SLACKBOT: `${ACCESS_PROVIDERS.SLACKBOT}`,
TELEGRAMBOT: `${ACCESS_PROVIDERS.TELEGRAMBOT}`,
@@ -969,6 +972,7 @@ export const notificationProvidersMap: Map
).map(([type]) => [
diff --git a/ui/src/i18n/resources/en/nls.access.json b/ui/src/i18n/resources/en/nls.access.json
index 496c095d..edf5b859 100644
--- a/ui/src/i18n/resources/en/nls.access.json
+++ b/ui/src/i18n/resources/en/nls.access.json
@@ -879,6 +879,26 @@
"litessl_eab": {
"guide": "Learn more about using EAB key in LiteSSL: https://freessl.cn/automation/eab-manager "
},
+ "matrix_server_url": {
+ "label": "Matrix server URL",
+ "placeholder": "Please enter Matrix server URL"
+ },
+ "matrix_user_id": {
+ "label": "Matrix user ID",
+ "placeholder": "Please enter Matrix user ID",
+ "tooltip": "For more information, see https://docs.element.io/latest/element-support/matrix-account-management/creating-a-matrix-account/ "
+ },
+ "matrix_access_token": {
+ "label": "Matrix access token",
+ "placeholder": "Please enter Matrix access token",
+ "tooltip": "For more information, see https://docs.element.io/latest/element-support/element-webdesktop-client-settings/element-settings/ "
+ },
+ "matrix_room_id": {
+ "label": "Matrix room ID (Optional)",
+ "placeholder": "Please enter the default Matrix room ID",
+ "help": "Notes: It can be overrided in the workflows. Invite the bot to the room first.",
+ "tooltip": "For more information, see https://docs.element.io/latest/element-support/matrix-rooms/managing-a-room-room-settings/ "
+ },
"mattermost_server_url": {
"label": "Mattermost server URL",
"placeholder": "Please enter Mattermost server URL"
@@ -895,7 +915,7 @@
"label": "Mattermost channel ID (Optional)",
"placeholder": "Please enter the default Mattermost channel ID",
"help": "Notes: It can be overrided in the workflows.",
- "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."
+ "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."
},
"mohua_username": {
"label": "Mohua Cloud username",
diff --git a/ui/src/i18n/resources/en/nls.provider.json b/ui/src/i18n/resources/en/nls.provider.json
index 99dbffd7..f88e567a 100644
--- a/ui/src/i18n/resources/en/nls.provider.json
+++ b/ui/src/i18n/resources/en/nls.provider.json
@@ -191,6 +191,7 @@
"linode_los": "Linode - Object Storage",
"litessl": "LiteSSL",
"local": "Local host",
+ "matrix": "Matrix / ElementX",
"mattermost": "Mattermost",
"mohua": "Mohua",
"mohua_mvh": "Mohua - MVH (Virtual Host)",
diff --git a/ui/src/i18n/resources/en/nls.workflow.nodes.json b/ui/src/i18n/resources/en/nls.workflow.nodes.json
index eb122022..5858ef5a 100644
--- a/ui/src/i18n/resources/en/nls.workflow.nodes.json
+++ b/ui/src/i18n/resources/en/nls.workflow.nodes.json
@@ -2784,7 +2784,7 @@
"webhook_data": {
"label": "Webhook data (Optional)",
"placeholder": "Please enter Webhook data",
- "help": "Notes: Leave it blank to use the default Webhook data provided by the credential.",
+ "help": "Notes: Leave it blank to use the default Webhook data provided by the selected credential.",
"vartips": "Supported variables: ${CERTIMATE_DEPLOYER_COMMONNAME} : The primary domain or IP address of the certificate.${CERTIMATE_DEPLOYER_SUBJECTALTNAMES} : The domains or IP addresses of the certificate, separated by semicolons.${CERTIMATE_DEPLOYER_CERTIFICATE} : The PEM format content of the certificate file.${CERTIMATE_DEPLOYER_CERTIFICATE_SERVER} : The PEM format content of the server certificate file.${CERTIMATE_DEPLOYER_CERTIFICATE_INTERMEDIA} : The PEM format content of the intermediate CA certificate file.${CERTIMATE_DEPLOYER_PRIVATEKEY} : The PEM format content of the private key file. "
},
"webhook_timeout": {
@@ -2890,7 +2890,7 @@
"discordbot_channel_id": {
"label": "Discord channel ID (Optional)",
"placeholder": "Please enter Discord channel ID",
- "help": "Notes: Leave it blank to use the default channel ID provided by the credential."
+ "help": "Notes: Leave it blank to use the default channel ID provided by the selected credential."
},
"email_format": {
"label": "Message format (Optional)",
@@ -2909,15 +2909,20 @@
"placeholder": "Please enter receiver email address",
"help": "Notes: Leave it blank to use the default receiver email address provided by the selected credential."
},
+ "matrix_room_id": {
+ "label": "Matrix room ID (Optional)",
+ "placeholder": "Please enter Matrix room ID",
+ "help": "Notes: Leave it blank to use the default room ID provided by the selected credential."
+ },
"mattermost_channel_id": {
"label": "Mattermost channel ID (Optional)",
"placeholder": "Please enter Mattermost channel ID",
- "help": "Notes: Leave it blank to use the default channel ID provided by the credential."
+ "help": "Notes: Leave it blank to use the default channel ID provided by the selected credential."
},
"slackbot_channel_id": {
"label": "Slack channel ID (Optional)",
"placeholder": "Please enter Slack channel ID",
- "help": "Notes: Leave it blank to use the default channel ID provided by the credential."
+ "help": "Notes: Leave it blank to use the default channel ID provided by the selected credential."
},
"telegrambot_chat_id": {
"label": "Telegram chat ID (Optional)",
@@ -2927,7 +2932,7 @@
"webhook_data": {
"label": "Webhook data (Optional)",
"placeholder": "Please enter Webhook data",
- "help": "Notes: Leave it blank to use the default Webhook data provided by the credential.",
+ "help": "Notes: Leave it blank to use the default Webhook data provided by the selected credential.",
"vartips": "Supported variables: ${CERTIMATE_NOTIFIER_SUBJECT} : The subject of notification.${CERTIMATE_NOTIFIER_MESSAGE} : The message of notification. "
},
"webhook_timeout": {
diff --git a/ui/src/i18n/resources/zh/nls.access.json b/ui/src/i18n/resources/zh/nls.access.json
index 36ba7ae8..b19723b0 100644
--- a/ui/src/i18n/resources/zh/nls.access.json
+++ b/ui/src/i18n/resources/zh/nls.access.json
@@ -78,6 +78,7 @@
"placeholder": "搜索提供商……"
}
},
+
"shared_acme_eab_kid": {
"label": "ACME EAB KID",
"placeholder": "请输入 ACME EAB KID"
@@ -89,6 +90,7 @@
"shared_allow_insecure_conns": {
"label": "忽略 SSL/TLS 证书验证"
},
+
"1panel_server_url": {
"label": "1Panel 服务地址",
"placeholder": "请输入 1Panel 服务地址",
@@ -877,6 +879,26 @@
"litessl_eab": {
"guide": "点击下方链接了解如何获取 LiteSSL EAB:https://freessl.cn/automation/eab-manager "
},
+ "matrix_server_url": {
+ "label": "Matrix 服务地址",
+ "placeholder": "请输入 Matrix 服务地址"
+ },
+ "matrix_user_id": {
+ "label": "Matrix 用户 ID",
+ "placeholder": "请输入 Matrix 用户 ID",
+ "tooltip": "这是什么?请参阅 https://docs.element.io/latest/element-support/matrix-account-management/creating-a-matrix-account/ "
+ },
+ "matrix_access_token": {
+ "label": "Matrix Access token",
+ "placeholder": "请输入 Matrix Access token",
+ "tooltip": "这是什么?请参阅 https://docs.element.io/latest/element-support/element-webdesktop-client-settings/element-settings/ "
+ },
+ "matrix_room_id": {
+ "label": "Matrix 房间 ID(可选)",
+ "placeholder": "请输入默认的 Matrix 房间 ID",
+ "help": "提示:可在工作流中覆盖此设置。请先将机器人邀请进房间。",
+ "tooltip": "这是什么?请参阅 https://docs.element.io/latest/element-support/matrix-rooms/managing-a-room-room-settings/ "
+ },
"mattermost_server_url": {
"label": "Mattermost 服务地址",
"placeholder": "请输入 Mattermost 服务地址"
diff --git a/ui/src/i18n/resources/zh/nls.provider.json b/ui/src/i18n/resources/zh/nls.provider.json
index fe3462dc..79ce7000 100644
--- a/ui/src/i18n/resources/zh/nls.provider.json
+++ b/ui/src/i18n/resources/zh/nls.provider.json
@@ -191,6 +191,7 @@
"linode_los": "Linode - 对象存储",
"litessl": "LiteSSL",
"local": "本地主机",
+ "matrix": "Matrix / ElementX",
"mattermost": "Mattermost",
"mohua": "嘿华云",
"mohua_mvh": "嘿华云 - 虚拟主机 MVH ",
diff --git a/ui/src/i18n/resources/zh/nls.workflow.nodes.json b/ui/src/i18n/resources/zh/nls.workflow.nodes.json
index 91b4f54b..d59aa145 100644
--- a/ui/src/i18n/resources/zh/nls.workflow.nodes.json
+++ b/ui/src/i18n/resources/zh/nls.workflow.nodes.json
@@ -2873,6 +2873,7 @@
"params_config": {
"label": "参数设置"
},
+
"discordbot_channel_id": {
"label": "Discord 频道 ID(可选)",
"placeholder": "请输入 Discord 频道 ID",
@@ -2895,6 +2896,11 @@
"placeholder": "请输入收件人邮箱以覆盖默认值",
"help": "提示:不填写时,将使用所选通知渠道授权的默认收件人邮箱。"
},
+ "matrix_room_id": {
+ "label": "Matrix 房间 ID(可选)",
+ "placeholder": "请输入 Matrix 房间 ID",
+ "help": "提示:不填写时,将使用所选通知渠道授权的默认房间 ID。"
+ },
"mattermost_channel_id": {
"label": "Mattermost 频道 ID(可选)",
"placeholder": "请输入 Mattermost 频道 ID",