| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- package main
- import (
- "flag"
- "fmt"
- "io/fs"
- "log"
- "os"
- "runtime"
- "strings"
- "time"
- "github.com/nxadm/tail"
- )
- // findPath Find the path in which the log files are stored.
- func findPath(LogLocation string) (logPath string) {
- if LogLocation != "" {
- logPath = LogLocation
- return
- }
- var err error
- var homedir string
- var Path string
- var Paths []string
- var PathsLinux []string
- var PathsMac []string
- var PathsWindows []string
- // Determine the homedir of the user.
- homedir, err = os.UserHomeDir()
- if err != nil {
- log.Fatal(err)
- }
- // Define Paths to check out
- PathsLinux = append(PathsLinux, "/Documents/EVE/logs/")
- PathsLinux = append(PathsLinux, "/.local/share/Steam/steamapps/compatdata/8500/pfx/drive_c/users/steamuser/My Documents/EVE/logs/Chatlogs/")
- PathsMac = append(PathsMac, "/Documents/EVE/logs/")
- PathsMac = append(PathsMac, "/Library/Application Support/EVE Online/p_drive/User/My Documents/EVE/")
- PathsWindows = append(PathsWindows, "C:\\Users\\YourUserName\\Documents\\EVE\\logs")
- PathsWindows = append(PathsWindows, "MyDocuments -> EVE -> Logs")
- switch runtime.GOOS {
- case "linux":
- Paths = PathsLinux
- case "darwin":
- Paths = PathsMac
- case "windows":
- Paths = PathsWindows
- }
- for _, Path = range Paths {
- if _, err := os.Stat(homedir + Path); !os.IsNotExist(err) {
- logPath = homedir + Path
- }
- }
- return
- }
- // OrchestrateIntelMonitoring routine to periodically check the logpath for the intel channels.
- func OrchestrateIntelMonitoring(logPath string, intelChannel string, LogSystemsRaw string) {
- // Declare variables
- var files []fs.FileInfo
- var lastName string
- var tempName string
- // Enter a for-loop that periodically checks.
- for {
- files = fetchFileListing(logPath)
- tempName = findLatestLog(logPath, intelChannel, files)
- if !strings.EqualFold(lastName, tempName) {
- lastName = tempName
- fmt.Println("Tracking file:" + lastName)
- go TrackLogfile(lastName, LogSystemsRaw)
- }
- // Sleep a minute before we check again.
- time.Sleep(time.Second * 60)
- }
- }
- // TrackLogfile The actual work
- func TrackLogfile(logPath string, LogSystemsRaw string) {
- // Split the CSV string into different parts
- LogSystems := strings.Split(LogSystemsRaw, ",")
- // Do the main loop and start parsing the logfiles
- t, err := tail.TailFile(logPath, tail.Config{Follow: true})
- if err != nil {
- panic(err)
- }
- for line := range t.Lines {
- // Cast a line to a text, trim the trash
- logLine := string(line.Text)
- logLine = strings.Trim(logLine, "\n")
- // Figure out if this is a message we want to deal with
- // > is critical in this regard because it is the start of the message
- // and everything behind it until it hits ] is the username
- splitpos := strings.Index(logLine, ">")
- if -1 == splitpos {
- continue
- }
- // Somehow I cannot filter out this stuff.
- // EVE System > Channel MOTD
- LineDate, LineTime, LineUser, Payload := ParseChat(logLine)
- if CompareElements(LogSystems, Payload) {
- playBeep()
- fmt.Println("[", LineDate, LineTime, "]", LineUser, ">", Payload)
- }
- }
- // We should never reach this
- }
- // fetchFileListing As it says on the tin.
- func fetchFileListing(logPath string) (files []fs.FileInfo) {
- // Declare Variables
- var err error
- var folder *os.File
- // Open the folder we need to open.
- folder, err = os.Open(logPath)
- if err != nil {
- log.Fatal(err)
- }
- // Read the files UwU
- files, err = folder.Readdir(-1)
- folder.Close()
- if err != nil {
- log.Fatal(err)
- }
- // Off you go! \o/
- return
- }
- // findLatestLog Find the last log-file based on the Internet
- func findLatestLog(logPath string, intelChannel string, files []fs.FileInfo) (lastName string) {
- // Declare Variables
- var lastTime time.Time
- var tempTime time.Time
- for _, file := range files {
- file, err := os.Stat(logPath + file.Name())
- if err != nil {
- log.Fatal(err)
- }
- if strings.EqualFold(intelChannel, file.Name()[:len(intelChannel)]) {
- tempTime = file.ModTime()
- if tempTime.After(lastTime) {
- lastTime = tempTime
- lastName = logPath + file.Name()
- }
- }
- }
- // And there you are (or not)
- return
- }
- // StartIntelMonitoring -- The Main Loop!
- func StartIntelMonitoring(intelChannels string, LogSystemsRaw string, LogLocation string) {
- // Declare variables
- var logPath string
- var IntelChannelsSplit []string
- var IntelChannel string
- // Split the CSV string into different parts
- IntelChannelsSplit = strings.Split(intelChannels, ",")
- // Get the path we need to
- logPath = findPath(LogLocation)
- for _, IntelChannel = range IntelChannelsSplit {
- IntelChannel = strings.ReplaceAll(IntelChannel, " ", "_")
- go OrchestrateIntelMonitoring(logPath, IntelChannel, LogSystemsRaw)
- }
- }
- // ParseChat Parses a string, returns the payload of the chat
- // *sigh*
- // This took effing forever to get right.
- // "Lets start with Regex, cannot go wrong".
- // You have this string:
- // ��[ 2022.02.09 10:05:43 ] Kaysee Guru > EX-GBT clr nd
- // Cool. Looks easy.
- // .*\[ (.*?) (.*?) \] (.*?) > (.*)
- // regex101.com says its good
- // And no matter what I do just does not work for some magical reason.
- //
- // Lets do this with splitting by space and compare it with that. Do a bunch of ifs, it works in test aaaaaand....
- // It doesn't work.
- //
- // By now I have a somewhat reliable version, but it fails to look for the word MOTD.
- // I should prolly look into runes()
- // This is terrible
- func ParseChat(chatline string) (LineDate string, LineTime string, LineUser string, Payload []string) {
- logLine := chatline[3:]
- var LinePayload string
- var splitpos int
- splitpos = strings.Index(logLine, ">")
- LineDate = logLine[2:23]
- LineTime = logLine[25:41]
- LineUser = logLine[46 : splitpos-2]
- LinePayload = logLine[splitpos+4:]
- LinePayload = shorten(LinePayload)
- Payload = strings.Fields(LinePayload)
- //fmt.Println(logLine)
- //fmt.Println(LineDate)
- //fmt.Println(LineTime)
- //fmt.Println(LineUser)
- //fmt.Println(splitpos)
- //fmt.Println(LinePayload)
- //fmt.Println(Payload)
- return
- }
- func shorten(payload string) (logLine string) {
- runes := []rune(payload)
- for pos, char := range runes {
- if pos%2 == 0 && char != 13 {
- logLine = logLine + string(char)
- }
- }
- return
- }
- // CompareElements Compares a log msg with systems we wish to track
- func CompareElements(alerts []string, payload []string) bool {
- for _, word := range payload {
- for _, alert := range alerts {
- if strings.EqualFold(word, alert) {
- //fmt.Println("Found (EF): ", alert, "in", word)
- return true
- } //else {
- // fmt.Println(word, "!=", alert)
- //}
- // In the odd case somebody links "C-V6DQ*"
- if len(word) > 6 {
- //alert = alert[:len(word)]
- word = word[:6]
- }
- // In case of partials like "C-V"
- if len(word) < 6 && len(word) >= 3 {
- //word = word[:5]
- alert = alert[:len(word)]
- }
- if strings.EqualFold(word, alert) {
- //fmt.Println("Found: ", alert, "in", word)
- return true
- }
- }
- }
- return false
- }
- // playBeep Play a beep
- // Honestly, I tried to play alert.mp3, but after two executions I got a segfault and thought 0x07 it is!
- func playBeep() {
- fmt.Print("\a")
- }
- // main Something Importang. Dunno
- func main() {
- // Handle Parameters
- var intelChannels = flag.String("i", "Etherium Intel,Bean-Intel", "Comma-separated list of intel channels.")
- LogSystemsRaw := flag.String("s", "c-v6dq,1pf-bc,ex-gbt,z-fet0", "Comma-seperated list of systems to monitor for")
- LogLocation := flag.String("l", "", "Location of the log-file to track.")
- flag.Parse()
- // Start the main loop
- go StartIntelMonitoring(*intelChannels, *LogSystemsRaw, *LogLocation)
- // Go into the eternal loop and sit this one out.
- // But bug every hour, reminding them that you are still there.
- for {
- time.Sleep(time.Second * 3600)
- fmt.Println("Hi. This is your hourly reminder that this program is still runnig and hasn't crashed!")
- }
- }
|