A simple IRC notifier
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

148 lines
3.5 KiB

package main
import (
"bufio"
"errors"
"fmt"
"log"
"os"
"strings"
"git.sr.ht/~sircmpwn/getopt"
)
type Config struct {
Host string //irc-server
Pass string //pass
User string //user
Nick string //nick
Match []string //match
AppToken string //app-token
UserToken string //user-token
ExcludeChannels []string //exclude-channels
ExcludeUsers []string //exclude-users
}
//Partially adapted from:
//https://stackoverflow.com/questions/40022861/parsing-values-from-property-file-in-golang/46860900
func LoadConfig() (*Config, error) {
opts, optind, err := getopt.Getopts(os.Args, "h:u:p:m:n:a:t:")
if err != nil {
log.Fatalf("Unable to get options %s", err)
}
var config *Config
if optind < len(os.Args) {
filePath := os.Args[optind]
config, err = loadConfigFromFile(filePath)
if err != nil {
return nil, fmt.Errorf("Unable to read config file: %w", err)
}
} else {
config = &Config{User: "-bell"}
}
for _, opt := range opts {
switch opt.Option {
case 'h':
config.Host = opt.Value
case 'u':
config.User = opt.Value
case 'p':
config.Pass = opt.Value
case 'm':
config.Match = splitClean(opt.Value)
case 'n':
config.Nick = opt.Value
case 'a':
config.AppToken = opt.Value
case 't':
config.UserToken = opt.Value
case 'e':
config.ExcludeChannels = splitClean(opt.Value)
case 'x':
config.ExcludeUsers = splitClean(opt.Value)
}
}
if config.Host == "" {
return nil, errors.New("Most specify host either in config file or with -h")
}
if config.Nick == "" {
config.Nick = config.User
}
if len(config.Match) == 0 {
config.Match = []string{config.Nick}
}
if config.AppToken == "" || config.UserToken == "" {
return nil, errors.New("Must specify app-token and user-token for pushover")
}
return config, nil
}
func loadConfigFromFile(path string) (*Config, error) {
if len(path) == 0 {
return nil, errors.New("Cannot read empty path")
}
config := &Config{
User: "-bell",
}
file, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("Unable to open config file: %w", err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
//handle comments
if line[0] == '#' {
continue
}
// This is big and ugly
if equal := strings.Index(line, "="); equal >= 0 {
if key := strings.TrimSpace(line[:equal]); len(key) > 0 {
value := ""
if len(line) > equal {
value = strings.TrimSpace(line[equal+1:])
}
//TODO (noah): parse into config
switch key {
case "irc-server":
config.Host = value
case "pass":
config.Pass = value
case "user":
config.User = value
case "nick":
config.Nick = value
case "match":
config.Match = splitClean(value)
case "app-token":
config.AppToken = value
case "user-token":
config.UserToken = value
case "exclude-channels":
config.ExcludeChannels = splitClean(value)
case "exclude-users":
config.ExcludeUsers = splitClean(value)
default:
log.Printf("Unknown property in config file: %s=%s", key, value)
break
}
}
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("Unable to scan through config file: %w", err)
}
return config, nil
}
func splitClean(s string) []string {
split := strings.Split(strings.TrimSpace(s), ",")
output := make([]string, 0, len(split))
for _, v := range split {
if v != "" && v != " " {
output = append(output, strings.TrimSpace(v))
}
}
return output
}