2021-10-24 03:29:45 +02:00
// Package cmd provides the ntfy CLI application
package cmd
import (
2021-10-29 05:50:38 +02:00
"errors"
2021-10-24 03:29:45 +02:00
"fmt"
"github.com/urfave/cli/v2"
"github.com/urfave/cli/v2/altsrc"
"heckel.io/ntfy/config"
"heckel.io/ntfy/server"
2021-10-29 19:58:14 +02:00
"heckel.io/ntfy/util"
2021-10-24 03:29:45 +02:00
"log"
"os"
2021-10-29 19:58:14 +02:00
"time"
2021-10-24 03:29:45 +02:00
)
// New creates a new CLI application
func New ( ) * cli . App {
flags := [ ] cli . Flag {
& cli . StringFlag { Name : "config" , Aliases : [ ] string { "c" } , EnvVars : [ ] string { "NTFY_CONFIG_FILE" } , Value : "/etc/ntfy/config.yml" , DefaultText : "/etc/ntfy/config.yml" , Usage : "config file" } ,
altsrc . NewStringFlag ( & cli . StringFlag { Name : "listen-http" , Aliases : [ ] string { "l" } , EnvVars : [ ] string { "NTFY_LISTEN_HTTP" } , Value : config . DefaultListenHTTP , Usage : "ip:port used to as listen address" } ) ,
2021-10-29 05:50:38 +02:00
altsrc . NewStringFlag ( & cli . StringFlag { Name : "firebase-key-file" , Aliases : [ ] string { "F" } , EnvVars : [ ] string { "NTFY_FIREBASE_KEY_FILE" } , Usage : "Firebase credentials file; if set additionally publish to FCM topic" } ) ,
2021-10-29 19:58:14 +02:00
altsrc . NewDurationFlag ( & cli . DurationFlag { Name : "message-buffer-duration" , Aliases : [ ] string { "b" } , EnvVars : [ ] string { "NTFY_MESSAGE_BUFFER_DURATION" } , Value : config . DefaultMessageBufferDuration , Usage : "buffer messages in memory for this time to allow `since` requests" } ) ,
2021-10-27 20:56:17 +02:00
altsrc . NewDurationFlag ( & cli . DurationFlag { Name : "keepalive-interval" , Aliases : [ ] string { "k" } , EnvVars : [ ] string { "NTFY_KEEPALIVE_INTERVAL" } , Value : config . DefaultKeepaliveInterval , Usage : "default interval of keepalive messages" } ) ,
2021-10-29 19:58:14 +02:00
altsrc . NewDurationFlag ( & cli . DurationFlag { Name : "manager-interval" , Aliases : [ ] string { "m" } , EnvVars : [ ] string { "NTFY_MANAGER_INTERVAL" } , Value : config . DefaultManagerInterval , Usage : "default interval of for message pruning and stats printing" } ) ,
2021-10-24 03:29:45 +02:00
}
return & cli . App {
Name : "ntfy" ,
Usage : "Simple pub-sub notification service" ,
UsageText : "ntfy [OPTION..]" ,
HideHelp : true ,
HideVersion : true ,
EnableBashCompletion : true ,
UseShortOptionHandling : true ,
Reader : os . Stdin ,
Writer : os . Stdout ,
ErrWriter : os . Stderr ,
Action : execRun ,
Before : initConfigFileInputSource ( "config" , flags ) ,
Flags : flags ,
}
}
func execRun ( c * cli . Context ) error {
// Read all the options
listenHTTP := c . String ( "listen-http" )
2021-10-29 05:50:38 +02:00
firebaseKeyFile := c . String ( "firebase-key-file" )
2021-10-29 19:58:14 +02:00
messageBufferDuration := c . Duration ( "message-buffer-duration" )
2021-10-27 20:56:17 +02:00
keepaliveInterval := c . Duration ( "keepalive-interval" )
2021-10-29 19:58:14 +02:00
managerInterval := c . Duration ( "manager-interval" )
2021-10-24 03:29:45 +02:00
2021-10-29 05:50:38 +02:00
// Check values
2021-10-29 19:58:14 +02:00
if firebaseKeyFile != "" && ! util . FileExists ( firebaseKeyFile ) {
2021-10-29 05:50:38 +02:00
return errors . New ( "if set, FCM key file must exist" )
2021-10-29 19:58:14 +02:00
} else if keepaliveInterval < 5 * time . Second {
return errors . New ( "keepalive interval cannot be lower than five seconds" )
} else if managerInterval < 5 * time . Second {
return errors . New ( "manager interval cannot be lower than five seconds" )
} else if messageBufferDuration < managerInterval {
return errors . New ( "message buffer duration cannot be lower than manager interval" )
2021-10-29 05:50:38 +02:00
}
2021-10-29 19:58:14 +02:00
// Run server
2021-10-24 03:29:45 +02:00
conf := config . New ( listenHTTP )
2021-10-29 05:50:38 +02:00
conf . FirebaseKeyFile = firebaseKeyFile
2021-10-29 19:58:14 +02:00
conf . MessageBufferDuration = messageBufferDuration
2021-10-27 20:56:17 +02:00
conf . KeepaliveInterval = keepaliveInterval
2021-10-29 19:58:14 +02:00
conf . ManagerInterval = managerInterval
2021-10-29 05:50:38 +02:00
s , err := server . New ( conf )
if err != nil {
log . Fatalln ( err )
}
2021-10-24 03:29:45 +02:00
if err := s . Run ( ) ; err != nil {
log . Fatalln ( err )
}
log . Printf ( "Exiting." )
return nil
}
// initConfigFileInputSource is like altsrc.InitInputSourceWithContext and altsrc.NewYamlSourceFromFlagFunc, but checks
// if the config flag is exists and only loads it if it does. If the flag is set and the file exists, it fails.
func initConfigFileInputSource ( configFlag string , flags [ ] cli . Flag ) cli . BeforeFunc {
return func ( context * cli . Context ) error {
configFile := context . String ( configFlag )
2021-10-29 19:58:14 +02:00
if context . IsSet ( configFlag ) && ! util . FileExists ( configFile ) {
2021-10-24 03:29:45 +02:00
return fmt . Errorf ( "config file %s does not exist" , configFile )
2021-10-29 19:58:14 +02:00
} else if ! context . IsSet ( configFlag ) && ! util . FileExists ( configFile ) {
2021-10-24 03:29:45 +02:00
return nil
}
inputSource , err := altsrc . NewYamlSourceFromFile ( configFile )
if err != nil {
return err
}
return altsrc . ApplyInputSourceValues ( context , inputSource , flags )
}
}