From 1f7c2b415a67049fa217ac1b7495e78267ec4808 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Tue, 5 Jan 2016 17:39:25 +0100 Subject: added initial watch-dir control interface diff --git a/src/helsinki.at/rhimportd/ctrlWatchDir.go b/src/helsinki.at/rhimportd/ctrlWatchDir.go new file mode 100644 index 0000000..f4e3a54 --- /dev/null +++ b/src/helsinki.at/rhimportd/ctrlWatchDir.go @@ -0,0 +1,191 @@ +// +// rhimportd +// +// The Radio Helsinki Rivendell Import Daemon +// +// +// Copyright (C) 2015-2016 Christian Pointner +// +// This file is part of rhimportd. +// +// rhimportd is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// rhimportd is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with rhimportd. If not, see . +// + +package main + +import ( + "encoding/json" + "fmt" + "helsinki.at/rhimport" + "net/http" + "os" + "time" +) + +type watchDirRequestData struct { + UserName string `json:"LOGIN_NAME"` + ShowId uint `json:"SHOW_ID"` + ClearShowCarts bool `json:"CLEAR_SHOW_CARTS"` + MusicPoolGroup string `json:"MUSIC_POOL_GROUP"` + Cart uint `json:"CART_NUMBER"` + ClearCart bool `json:"CLEAR_CART"` + Cut uint `json:"CUT_NUMBER"` + Channels uint `json:"CHANNELS"` + NormalizationLevel int `json:"NORMALIZATION_LEVEL"` + AutotrimLevel int `json:"AUTOTRIM_LEVEL"` + UseMetaData bool `json:"USE_METADATA"` + SourceUri string `json:"SOURCE_URI"` +} + +func newWatchDirRequestData(conf *rhimport.Config) *watchDirRequestData { + rd := new(watchDirRequestData) + rd.UserName = "" + rd.ShowId = 0 + rd.ClearShowCarts = false + rd.MusicPoolGroup = "" + rd.Cart = 0 + rd.ClearCart = false + rd.Cut = 0 + rd.Channels = conf.ImportParamDefaults.Channels + rd.NormalizationLevel = conf.ImportParamDefaults.NormalizationLevel + rd.AutotrimLevel = conf.ImportParamDefaults.AutotrimLevel + rd.UseMetaData = conf.ImportParamDefaults.UseMetaData + rd.SourceUri = "" + + return rd +} + +type watchDirResponseData struct { + ResponseCode int `json:"REPONSE_CODE"` + ErrorString string `json:"ERROR_STRING"` + Cart uint `json:"CART_NUMBER"` + Cut uint `json:"CUT_NUMBER"` +} + +func watchDirErrorResponse(code int, errStr string) { + encoder := json.NewEncoder(os.Stdout) + respdata := watchDirResponseData{code, errStr, 0, 0} + encoder.Encode(respdata) +} + +func watchDirResponse(result *rhimport.Result) { + encoder := json.NewEncoder(os.Stdout) + respdata := watchDirResponseData{result.ResponseCode, result.ErrorString, result.Cart, result.Cut} + encoder.Encode(respdata) +} + +func watchDirParseRequest(conf *rhimport.Config, rddb *rhimport.RdDbChan, filename string) (ctx *rhimport.Context, err error) { + + decoder := json.NewDecoder(os.Stdin) + reqdata := newWatchDirRequestData(conf) + if jsonerr := decoder.Decode(reqdata); jsonerr != nil { + err = fmt.Errorf("Error parsing JSON response: %s", jsonerr) + return + } + + ctx = rhimport.NewContext(conf, rddb) + ctx.UserName = reqdata.UserName + ctx.Trusted = true + ctx.ShowId = reqdata.ShowId + ctx.ClearShowCarts = reqdata.ClearShowCarts + ctx.GroupName = reqdata.MusicPoolGroup + ctx.Cart = reqdata.Cart + ctx.ClearCart = reqdata.ClearCart + ctx.Cut = reqdata.Cut + ctx.Channels = reqdata.Channels + ctx.NormalizationLevel = reqdata.NormalizationLevel + ctx.AutotrimLevel = reqdata.AutotrimLevel + ctx.UseMetaData = reqdata.UseMetaData + ctx.SourceUri = reqdata.SourceUri + return +} + +func watchDirHandler(conf *rhimport.Config, rddb *rhimport.RdDbChan, filename string) { + rhdl.Printf("WatchDirHandler: request for '%s'", filename) + + var ctx *rhimport.Context + var err error + if ctx, err = watchDirParseRequest(conf, rddb, filename); err != nil { + watchDirErrorResponse(http.StatusBadRequest, err.Error()) + return + } + + if err = ctx.SanityCheck(); err != nil { + watchDirErrorResponse(http.StatusBadRequest, err.Error()) + return + } + + var res *rhimport.Result + if res, err = rhimport.FetchFile(ctx); err != nil { + watchDirErrorResponse(http.StatusInternalServerError, err.Error()) + return + } + if res.ResponseCode != http.StatusOK { + watchDirErrorResponse(res.ResponseCode, res.ErrorString) + return + } + + if res, err = rhimport.ImportFile(ctx); err != nil { + watchDirErrorResponse(http.StatusInternalServerError, err.Error()) + return + } + if res.ResponseCode == http.StatusOK { + rhl.Println("ImportFile succesfully imported", ctx.SourceFile) + } else { + rhl.Println("ImportFile import of", ctx.SourceFile, "was unsuccesful") + } + + watchDirResponse(res) + return +} + +func watchDirRun(dir *os.File, conf *rhimport.Config, rddb *rhimport.RdDbChan) { + rhl.Printf("watch-dir-ctrl: watching for files in %s", dir.Name()) + for { + var err error + if _, err = dir.Seek(0, 0); err != nil { + rhl.Printf("watch-dir-ctrl: reading directory contents failed: %s", err) + return + } + + var names []string + if names, err = dir.Readdirnames(0); err != nil { + rhl.Printf("watch-dir-ctrl: reading directory contents failed: %s", err) + return + } + rhdl.Printf("watch-dir-ctrl: got: %q", names) + time.Sleep(1 * time.Second) + } +} + +func StartWatchDir(dirname string, conf *rhimport.Config, rddb *rhimport.RdDbChan) { + for { + time.Sleep(5 * time.Second) + dir, err := os.Open(dirname) + if err != nil { + rhl.Printf("watch-dir-ctrl: %s", err) + continue + } + if i, err := dir.Stat(); err != nil { + rhl.Printf("watch-dir-ctrl: %s", err) + continue + } else { + if !i.IsDir() { + rhl.Printf("watch-dir-ctrl: %s is not a directory", dirname) + continue + } + } + watchDirRun(dir, conf, rddb) + } +} diff --git a/src/helsinki.at/rhimportd/main.go b/src/helsinki.at/rhimportd/main.go index 4bd779e..d941b05 100644 --- a/src/helsinki.at/rhimportd/main.go +++ b/src/helsinki.at/rhimportd/main.go @@ -70,6 +70,8 @@ func main() { flag.Var(webAddr, "web-addr", "addr:port to listen on (environment: RHIMPORTD_WEB_ADDR)") telnetAddr := newEnvStringValue("RHIMPORTD_TELNET_ADDR", "localhost:4023") flag.Var(telnetAddr, "telnet-addr", "addr:port to listen on (environment: RHIMPORTD_TELNET_ADDR)") + watchDir := newEnvStringValue("RHIMPORTD_WATCH_DIR", "") + flag.Var(watchDir, "watch-dir", "directory to look for file based requests (environment: RHIMPORTD_WATCH_DIR)") rdconf := newEnvStringValue("RHIMPORTD_RD_CONF", "/etc/rd.conf") flag.Var(rdconf, "rdconf", "path to the Rivendell config file (environment: RHIMPORTD_RD_CONF)") rdxportUrl := newEnvStringValue("RHIMPORTD_RDXPORT_URL", "http://localhost/rd-bin/rdxport.cgi") @@ -108,21 +110,35 @@ func main() { var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - rhl.Println("starting web-ctrl") - StartControlWeb(webAddr.Get().(string), conf, rddb.GetInterface(), sessions.GetInterface()) - rhl.Println("web-ctrl finished") - }() + if webAddr.Get().(string) != "" { + wg.Add(1) + go func() { + defer wg.Done() + rhl.Println("starting web-ctrl") + StartControlWeb(webAddr.Get().(string), conf, rddb.GetInterface(), sessions.GetInterface()) + rhl.Println("web-ctrl finished") + }() + } - wg.Add(1) - go func() { - defer wg.Done() - rhl.Println("starting telnet-ctrl") - StartControlTelnet(telnetAddr.Get().(string), conf, rddb.GetInterface(), sessions.GetInterface()) - rhl.Println("telnet-ctrl finished") - }() + if telnetAddr.Get().(string) != "" { + wg.Add(1) + go func() { + defer wg.Done() + rhl.Println("starting telnet-ctrl") + StartControlTelnet(telnetAddr.Get().(string), conf, rddb.GetInterface(), sessions.GetInterface()) + rhl.Println("telnet-ctrl finished") + }() + } + + if watchDir.Get().(string) != "" { + wg.Add(1) + go func() { + defer wg.Done() + rhl.Println("starting watch-dir-ctrl") + StartWatchDir(watchDir.Get().(string), conf, rddb.GetInterface()) + rhl.Println("watch-dir-ctrl finished") + }() + } alldone := make(chan bool) go func() { -- cgit v0.10.2