feat: implement gotify hook type

This commit is contained in:
garethgeorge
2024-01-29 21:06:35 -08:00
parent 25924b6197
commit e0ce6558c0
8 changed files with 313 additions and 38 deletions
+144 -32
View File
@@ -600,6 +600,7 @@ type Hook struct {
// *Hook_ActionCommand
// *Hook_ActionWebhook
// *Hook_ActionDiscord
// *Hook_ActionGotify
Action isHook_Action `protobuf_oneof:"action"`
}
@@ -670,6 +671,13 @@ func (x *Hook) GetActionDiscord() *Hook_Discord {
return nil
}
func (x *Hook) GetActionGotify() *Hook_Gotify {
if x, ok := x.GetAction().(*Hook_ActionGotify); ok {
return x.ActionGotify
}
return nil
}
type isHook_Action interface {
isHook_Action()
}
@@ -686,12 +694,18 @@ type Hook_ActionDiscord struct {
ActionDiscord *Hook_Discord `protobuf:"bytes,102,opt,name=action_discord,json=actionDiscord,proto3,oneof"`
}
type Hook_ActionGotify struct {
ActionGotify *Hook_Gotify `protobuf:"bytes,103,opt,name=action_gotify,json=actionGotify,proto3,oneof"`
}
func (*Hook_ActionCommand) isHook_Action() {}
func (*Hook_ActionWebhook) isHook_Action() {}
func (*Hook_ActionDiscord) isHook_Action() {}
func (*Hook_ActionGotify) isHook_Action() {}
type Hook_Command struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -841,6 +855,77 @@ func (x *Hook_Discord) GetTemplate() string {
return ""
}
type Hook_Gotify struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
BaseUrl string `protobuf:"bytes,1,opt,name=base_url,json=baseUrl,proto3" json:"base_url,omitempty"`
Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"`
Template string `protobuf:"bytes,100,opt,name=template,proto3" json:"template,omitempty"` // template for the webhook payload.
TitleTemplate string `protobuf:"bytes,101,opt,name=title_template,json=titleTemplate,proto3" json:"title_template,omitempty"` // template for the webhook title.
}
func (x *Hook_Gotify) Reset() {
*x = Hook_Gotify{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_config_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Hook_Gotify) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Hook_Gotify) ProtoMessage() {}
func (x *Hook_Gotify) ProtoReflect() protoreflect.Message {
mi := &file_v1_config_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Hook_Gotify.ProtoReflect.Descriptor instead.
func (*Hook_Gotify) Descriptor() ([]byte, []int) {
return file_v1_config_proto_rawDescGZIP(), []int{6, 3}
}
func (x *Hook_Gotify) GetBaseUrl() string {
if x != nil {
return x.BaseUrl
}
return ""
}
func (x *Hook_Gotify) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
func (x *Hook_Gotify) GetTemplate() string {
if x != nil {
return x.Template
}
return ""
}
func (x *Hook_Gotify) GetTitleTemplate() string {
if x != nil {
return x.TitleTemplate
}
return ""
}
var File_v1_config_proto protoreflect.FileDescriptor
var file_v1_config_proto_rawDesc = []byte{
@@ -913,7 +998,7 @@ var file_v1_config_proto_rawDesc = []byte{
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x62, 0x63, 0x72, 0x79, 0x70, 0x74, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x42,
0x63, 0x72, 0x79, 0x70, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
0x64, 0x22, 0xa4, 0x04, 0x0a, 0x04, 0x48, 0x6f, 0x6f, 0x6b, 0x12, 0x32, 0x0a, 0x0a, 0x63, 0x6f,
0x64, 0x22, 0xda, 0x05, 0x0a, 0x04, 0x48, 0x6f, 0x6f, 0x6b, 0x12, 0x32, 0x0a, 0x0a, 0x63, 0x6f,
0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x12,
0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69,
0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x39,
@@ -927,30 +1012,42 @@ var file_v1_config_proto_rawDesc = []byte{
0x68, 0x6f, 0x6f, 0x6b, 0x12, 0x39, 0x0a, 0x0e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64,
0x69, 0x73, 0x63, 0x6f, 0x72, 0x64, 0x18, 0x66, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76,
0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x72, 0x64, 0x48, 0x00,
0x52, 0x0d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x72, 0x64, 0x1a,
0x23, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d,
0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x2a, 0x0a, 0x07, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x12,
0x1f, 0x0a, 0x0b, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x55, 0x72, 0x6c,
0x1a, 0x46, 0x0a, 0x07, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x77,
0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0a, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x55, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08,
0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6e,
0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54,
0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x17, 0x0a,
0x13, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x4e, 0x59, 0x5f, 0x45,
0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54,
0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x4e, 0x41, 0x50, 0x53, 0x48, 0x4f, 0x54, 0x5f, 0x53, 0x54, 0x41,
0x52, 0x54, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f,
0x4e, 0x5f, 0x53, 0x4e, 0x41, 0x50, 0x53, 0x48, 0x4f, 0x54, 0x5f, 0x45, 0x4e, 0x44, 0x10, 0x03,
0x12, 0x1c, 0x0a, 0x18, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x4e,
0x41, 0x50, 0x53, 0x48, 0x4f, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x42, 0x08,
0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72, 0x65, 0x74, 0x68, 0x67, 0x65, 0x6f,
0x72, 0x67, 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x72, 0x65, 0x73, 0x74, 0x2f, 0x67, 0x65, 0x6e,
0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x52, 0x0d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x72, 0x64, 0x12,
0x36, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x67, 0x6f, 0x74, 0x69, 0x66, 0x79,
0x18, 0x67, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b,
0x2e, 0x47, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x47, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x1a, 0x23, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x2a, 0x0a, 0x07,
0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x65, 0x62, 0x68, 0x6f,
0x6f, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x65,
0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x55, 0x72, 0x6c, 0x1a, 0x46, 0x0a, 0x07, 0x44, 0x69, 0x73, 0x63,
0x6f, 0x72, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x75,
0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f,
0x6b, 0x55, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
0x1a, 0x7c, 0x0a, 0x06, 0x47, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61,
0x73, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61,
0x73, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x74,
0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x64, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74,
0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x69, 0x74, 0x6c, 0x65,
0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x65, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0d, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x93,
0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x15, 0x0a, 0x11,
0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57,
0x4e, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e,
0x5f, 0x41, 0x4e, 0x59, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18,
0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x4e, 0x41, 0x50, 0x53, 0x48,
0x4f, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4f,
0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x4e, 0x41, 0x50, 0x53, 0x48, 0x4f, 0x54,
0x5f, 0x45, 0x4e, 0x44, 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54,
0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x4e, 0x41, 0x50, 0x53, 0x48, 0x4f, 0x54, 0x5f, 0x45, 0x52, 0x52,
0x4f, 0x52, 0x10, 0x04, 0x42, 0x08, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x2c,
0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x72,
0x65, 0x74, 0x68, 0x67, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x72, 0x65,
0x73, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -966,7 +1063,7 @@ func file_v1_config_proto_rawDescGZIP() []byte {
}
var file_v1_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_v1_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_v1_config_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_v1_config_proto_goTypes = []interface{}{
(Hook_Condition)(0), // 0: v1.Hook.Condition
(*Config)(nil), // 1: v1.Config
@@ -979,6 +1076,7 @@ var file_v1_config_proto_goTypes = []interface{}{
(*Hook_Command)(nil), // 8: v1.Hook.Command
(*Hook_Webhook)(nil), // 9: v1.Hook.Webhook
(*Hook_Discord)(nil), // 10: v1.Hook.Discord
(*Hook_Gotify)(nil), // 11: v1.Hook.Gotify
}
var file_v1_config_proto_depIdxs = []int32{
2, // 0: v1.Config.repos:type_name -> v1.Repo
@@ -992,11 +1090,12 @@ var file_v1_config_proto_depIdxs = []int32{
8, // 8: v1.Hook.action_command:type_name -> v1.Hook.Command
9, // 9: v1.Hook.action_webhook:type_name -> v1.Hook.Webhook
10, // 10: v1.Hook.action_discord:type_name -> v1.Hook.Discord
11, // [11:11] is the sub-list for method output_type
11, // [11:11] is the sub-list for method input_type
11, // [11:11] is the sub-list for extension type_name
11, // [11:11] is the sub-list for extension extendee
0, // [0:11] is the sub-list for field type_name
11, // 11: v1.Hook.action_gotify:type_name -> v1.Hook.Gotify
12, // [12:12] is the sub-list for method output_type
12, // [12:12] is the sub-list for method input_type
12, // [12:12] is the sub-list for extension type_name
12, // [12:12] is the sub-list for extension extendee
0, // [0:12] is the sub-list for field type_name
}
func init() { file_v1_config_proto_init() }
@@ -1125,6 +1224,18 @@ func file_v1_config_proto_init() {
return nil
}
}
file_v1_config_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Hook_Gotify); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_v1_config_proto_msgTypes[5].OneofWrappers = []interface{}{
(*User_PasswordBcrypt)(nil),
@@ -1133,6 +1244,7 @@ func file_v1_config_proto_init() {
(*Hook_ActionCommand)(nil),
(*Hook_ActionWebhook)(nil),
(*Hook_ActionDiscord)(nil),
(*Hook_ActionGotify)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -1140,7 +1252,7 @@ func file_v1_config_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_v1_config_proto_rawDesc,
NumEnums: 1,
NumMessages: 10,
NumMessages: 11,
NumExtensions: 0,
NumServices: 0,
},
+60
View File
@@ -0,0 +1,60 @@
package hook
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/url"
"strings"
v1 "github.com/garethgeorge/backrest/gen/go/v1"
)
func (h *Hook) doGotify(cmd *v1.Hook_ActionGotify, vars HookVars, output io.Writer) error {
payload, err := h.renderTemplateOrDefault(cmd.ActionGotify.GetTemplate(), defaultTemplate, vars)
if err != nil {
return fmt.Errorf("template rendering: %w", err)
}
title, err := h.renderTemplateOrDefault(cmd.ActionGotify.GetTitleTemplate(), "Backrest Event", vars)
if err != nil {
return fmt.Errorf("title template rendering: %w", err)
}
message := struct {
Message string `json:"message"`
Title string `json:"title"`
Priority int `json:"priority"`
}{
Title: title,
Priority: 5,
Message: payload,
}
b, err := json.Marshal(message)
if err != nil {
return fmt.Errorf("json marshal: %w", err)
}
baseUrl := strings.Trim(cmd.ActionGotify.GetBaseUrl(), "/")
postUrl := fmt.Sprintf(
"%s/message?token=%s",
baseUrl,
url.QueryEscape(cmd.ActionGotify.GetToken()))
output.Write([]byte(fmt.Sprintf("Sending gotify message to %s\n", postUrl)))
body, err := post(postUrl, "application/json", bytes.NewReader(b))
if err != nil {
return fmt.Errorf("send gotify message: %w", err)
}
if body != "" {
output.Write([]byte(body))
}
return nil
}
+3 -1
View File
@@ -17,7 +17,7 @@ import (
)
var (
defaultTemplate = `{{.Summary}}`
defaultTemplate = `{{ .Summary }}`
)
// ExecuteHooks schedules tasks for the hooks subscribed to the given event. The vars map is used to substitute variables
@@ -138,6 +138,8 @@ func (h *Hook) Do(event v1.Hook_Condition, vars HookVars, output io.Writer) erro
return h.doCommand(action, vars, output)
case *v1.Hook_ActionDiscord:
return h.doDiscord(action, vars, output)
case *v1.Hook_ActionGotify:
return h.doGotify(action, vars, output)
default:
return fmt.Errorf("unknown hook action: %v", action)
}
+1 -1
View File
@@ -9,7 +9,7 @@ import (
func post(url string, contentType string, body io.Reader) (string, error) {
r, err := http.Post(url, contentType, body)
if err != nil {
return "", fmt.Errorf("send request: %w", url, err)
return "", fmt.Errorf("send request %v: %w", url, err)
}
if r.StatusCode == 204 {
return "", nil
+1 -1
View File
@@ -17,7 +17,7 @@ const (
// - it has no snapshot associated with it
// - it has a forgotten snapshot associated with it
gcHistoryAge = 30 * 24 * time.Hour
gcHistoryMaxCount = 200
gcHistoryMaxCount = 1000
)
type CollectGarbageTask struct {
+9 -1
View File
@@ -78,6 +78,7 @@ message Hook {
Command action_command = 100 [json_name="actionCommand"];
Webhook action_webhook = 101 [json_name="actionWebhook"];
Discord action_discord = 102 [json_name="actionDiscord"];
Gotify action_gotify = 103 [json_name="actionGotify"];
}
message Command {
@@ -90,7 +91,14 @@ message Hook {
message Discord {
string webhook_url = 1 [json_name="webhookUrl"];
string template = 2; // template for the webhook payload.
string template = 2 [json_name="template"]; // template for the webhook payload.
}
message Gotify {
string base_url = 1 [json_name="baseUrl"];
string token = 3 [json_name="token"];
string template = 100 [json_name="template"]; // template for the webhook payload.
string title_template = 101 [json_name="titleTemplate"]; // template for the webhook title.
}
}
+66
View File
@@ -478,6 +478,12 @@ export class Hook extends Message<Hook> {
*/
value: Hook_Discord;
case: "actionDiscord";
} | {
/**
* @generated from field: v1.Hook.Gotify action_gotify = 103;
*/
value: Hook_Gotify;
case: "actionGotify";
} | { case: undefined; value?: undefined } = { case: undefined };
constructor(data?: PartialMessage<Hook>) {
@@ -492,6 +498,7 @@ export class Hook extends Message<Hook> {
{ no: 100, name: "action_command", kind: "message", T: Hook_Command, oneof: "action" },
{ no: 101, name: "action_webhook", kind: "message", T: Hook_Webhook, oneof: "action" },
{ no: 102, name: "action_discord", kind: "message", T: Hook_Discord, oneof: "action" },
{ no: 103, name: "action_gotify", kind: "message", T: Hook_Gotify, oneof: "action" },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Hook {
@@ -676,3 +683,62 @@ export class Hook_Discord extends Message<Hook_Discord> {
}
}
/**
* @generated from message v1.Hook.Gotify
*/
export class Hook_Gotify extends Message<Hook_Gotify> {
/**
* @generated from field: string base_url = 1;
*/
baseUrl = "";
/**
* @generated from field: string token = 3;
*/
token = "";
/**
* template for the webhook payload.
*
* @generated from field: string template = 100;
*/
template = "";
/**
* template for the webhook title.
*
* @generated from field: string title_template = 101;
*/
titleTemplate = "";
constructor(data?: PartialMessage<Hook_Gotify>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "v1.Hook.Gotify";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "base_url", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 3, name: "token", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 100, name: "template", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 101, name: "title_template", kind: "scalar", T: 9 /* ScalarType.STRING */ },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Hook_Gotify {
return new Hook_Gotify().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Hook_Gotify {
return new Hook_Gotify().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Hook_Gotify {
return new Hook_Gotify().fromJsonString(jsonString, options);
}
static equals(a: Hook_Gotify | PlainMessage<Hook_Gotify> | undefined, b: Hook_Gotify | PlainMessage<Hook_Gotify> | undefined): boolean {
return proto3.util.equals(Hook_Gotify, a, b);
}
}
+29 -2
View File
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { Hook, Hook_Command, Hook_Condition, Hook_Discord, Hook_Webhook } from '../../gen/ts/v1/config_pb';
import { Hook, Hook_Command, Hook_Condition, Hook_Discord, Hook_Gotify, Hook_Webhook } from '../../gen/ts/v1/config_pb';
import { Button, Card, Collapse, CollapseProps, Form, FormListFieldData, Input, Popover, Radio, Row, Select, Tooltip } from 'antd';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
@@ -123,6 +123,17 @@ const hookTypes: {
}),
}
},
{
name: "Gotify", action: {
case: "actionGotify",
value: new Hook_Gotify({
baseUrl: "",
token: "",
template: "{{ .Summary }}",
titleTemplate: "Backrest {{ .EventName .Event }} in plan {{ .Plan.Id }}",
}),
}
}
];
const HookBuilder = ({ field, hook }: { field: FormListFieldData, hook: Hook }) => {
@@ -133,7 +144,7 @@ const HookBuilder = ({ field, hook }: { field: FormListFieldData, hook: Hook })
<Form.Item name={[field.name, "action", "value", "webhookUrl"]} required={true}>
<Input addonBefore={<div style={{ width: "8em" }}>Discord Webhook</div>} />
</Form.Item>
Text:
Text Template:
<Form.Item name={[field.name, "action", "value", "template"]} required={true}>
<Input.TextArea style={{ width: "100%", fontFamily: "monospace" }} />
</Form.Item>
@@ -147,6 +158,22 @@ const HookBuilder = ({ field, hook }: { field: FormListFieldData, hook: Hook })
<Input.TextArea style={{ width: "100%", fontFamily: "monospace" }} />
</Form.Item>
</>
case "actionGotify":
return <>
<Form.Item name={[field.name, "action", "value", "baseUrl"]} required={true}>
<Input addonBefore={<div style={{ width: "8em" }}>Gotify Base URL</div>} />
</Form.Item>
<Form.Item name={[field.name, "action", "value", "token"]} required={true}>
<Input addonBefore={<div style={{ width: "8em" }}>Gotify Token</div>} />
</Form.Item>
<Form.Item name={[field.name, "action", "value", "titleTemplate"]} required={true}>
<Input addonBefore={<div style={{ width: "8em" }}>Title Template</div>} />
</Form.Item>
Text Template:
<Form.Item name={[field.name, "action", "value", "template"]} required={true}>
<Input.TextArea style={{ width: "100%", fontFamily: "monospace" }} />
</Form.Item>
</>
default:
return <p>Unknown hook {hook.action.case}</p>
}