2016-04-02 01:04:58 +00:00
package main
import (
"flag"
"fmt"
"libnmdc"
"os"
"path/filepath"
"regexp"
"strings"
"time"
)
var BaseDir string = "."
var PMResponse string = ""
var LogConnectionState bool
var DebugMode bool
2016-04-03 01:15:57 +00:00
var VerifyTLS bool
2016-04-02 01:04:58 +00:00
var CharacterMatcher * regexp . Regexp
func init ( ) {
CharacterMatcher = regexp . MustCompile ( "[^a-zA-Z0-9]" )
}
func GetDirectoryNameForHub ( hub string ) string {
return filepath . Join ( BaseDir , CharacterMatcher . ReplaceAllString ( hub , "_" ) )
}
func LogMessage ( hub , message string ) {
instant := time . Now ( ) // using system timezone
// Log file path
monthStamp := instant . Format ( "2006-01" )
logFilePath := filepath . Join ( GetDirectoryNameForHub ( hub ) , monthStamp + ".log" )
// Produce a timestamp
timeStamp := instant . Format ( "2006-01-02 15:04:05" )
2016-04-03 01:29:49 +00:00
fh , err := os . OpenFile ( logFilePath , os . O_APPEND | os . O_CREATE | os . O_WRONLY , 0644 )
2016-04-02 01:04:58 +00:00
if err != nil {
fmt . Fprintf ( os . Stderr , "Couldn't open file '%s': %s\n" , logFilePath , err . Error ( ) )
return
}
defer fh . Close ( )
_ , err = fh . WriteString ( "[" + timeStamp + "] " + message + "\n" )
if err != nil {
fmt . Fprintf ( os . Stderr , "Error writing to file '%s': %s\n" , logFilePath , err . Error ( ) )
return
}
}
2016-04-16 06:21:38 +00:00
type HubWorker struct {
LastConnectionStateMessage string
}
func ( this * HubWorker ) MainLoop ( addr , nick , password string ) {
2016-04-02 01:04:58 +00:00
opts := libnmdc . HubConnectionOptions {
2016-04-03 01:15:57 +00:00
Address : libnmdc . HubAddress ( addr ) ,
SkipVerifyTLS : ! VerifyTLS ,
2016-04-10 04:37:21 +00:00
Self : * libnmdc . NewUserInfo ( nick ) ,
2016-04-03 01:15:57 +00:00
NickPassword : password ,
2016-04-02 01:04:58 +00:00
}
hub := opts . Connect ( )
for {
event := <- hub . OnEvent
if DebugMode {
fmt . Printf ( "DEBUG: %s %v\n" , addr , event )
}
switch event . EventType {
case libnmdc . EVENT_CONNECTION_STATE_CHANGED :
if LogConnectionState {
2016-04-16 06:21:38 +00:00
str := "* " + event . StateChange . Format ( )
2016-04-02 01:04:58 +00:00
if len ( event . Message ) > 0 {
2016-04-16 06:21:38 +00:00
str += " (" + event . Message + ")"
}
// Prevent logging the same message repeatedly
if str != this . LastConnectionStateMessage {
LogMessage ( addr , str )
2016-04-02 01:04:58 +00:00
}
2016-04-16 06:21:38 +00:00
this . LastConnectionStateMessage = str
2016-04-02 01:04:58 +00:00
}
case libnmdc . EVENT_PUBLIC :
LogMessage ( addr , "<" + event . Nick + "> " + event . Message )
case libnmdc . EVENT_PRIVATE :
fmt . Printf ( "Got PM %v\n" , event )
hub . SayPrivate ( event . Nick , PMResponse )
case libnmdc . EVENT_SYSTEM_MESSAGE_FROM_CONN , libnmdc . EVENT_SYSTEM_MESSAGE_FROM_HUB :
if strings . HasPrefix ( event . Message , "* " ) {
LogMessage ( addr , event . Message )
} else {
LogMessage ( addr , "* " + event . Message )
}
}
}
}
func main ( ) {
// Parse arguments
hubs := flag . String ( "Server" , "" , "Addresses to connect to (comma-separated)" )
nick := flag . String ( "Nick" , "nmdc-log-service" , "Nick" )
password := flag . String ( "Password" , "" , "Registered nick password" )
2016-04-02 01:17:47 +00:00
flag . StringVar ( & BaseDir , "Dir" , "." , "Output directory" )
2016-04-02 01:04:58 +00:00
flag . BoolVar ( & LogConnectionState , "LogConnectionState" , true , "Include connection state changes in log" )
flag . StringVar ( & PMResponse , "PMResponse" , "This is an automated service. For enquiries, please contact an administrator." , "Message to respond with on PM" )
flag . BoolVar ( & DebugMode , "Debug" , false , "Print additional information on stdout" )
2016-04-03 01:15:57 +00:00
flag . BoolVar ( & VerifyTLS , "VerifyTLS" , true , "Verify TLS certificates" )
2016-04-02 01:04:58 +00:00
flag . Parse ( )
// Assert dir exists
dinfo , err := os . Stat ( BaseDir )
if err != nil {
2016-04-03 01:29:58 +00:00
fmt . Fprintf ( os . Stderr , "FATAL: %s\n" , err . Error ( ) )
2016-04-02 01:04:58 +00:00
os . Exit ( 1 )
}
if ! dinfo . IsDir ( ) {
fmt . Fprintf ( os . Stderr , "FATAL: Path '%s' is not a directory\n" , BaseDir )
}
2016-04-03 01:32:19 +00:00
if ! VerifyTLS {
fmt . Fprintf ( os . Stderr , "WARNING: TLS certificates will not be verified!\n" )
}
2016-04-02 01:04:58 +00:00
// Launch loggers
all_hubs := strings . Split ( * hubs , "," )
launch_ct := 0
for _ , hubaddr := range all_hubs {
if len ( hubaddr ) == 0 {
continue
}
// Assert target directory exists
os . MkdirAll ( GetDirectoryNameForHub ( hubaddr ) , 0755 )
// Launch logger
2016-04-16 06:21:38 +00:00
hw := HubWorker { }
go hw . MainLoop ( hubaddr , * nick , * password )
2016-04-02 01:04:58 +00:00
launch_ct ++
}
if launch_ct == 0 {
fmt . Fprintln ( os . Stderr , "FATAL: No hubs specified" )
os . Exit ( 1 )
}
// Wait forever
var forever chan bool = nil
select {
case <- forever :
}
}