2024-08-14 12:28:29 -04:00
|
|
|
// modbot is a system information agregator
|
2024-07-30 04:02:05 -04:00
|
|
|
// Copyright (C) 2024 frosty <inthishouseofcards@gmail.com>
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Affero General Public License as published
|
|
|
|
// by the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program 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 Affero General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
2024-08-14 16:19:18 -04:00
|
|
|
// along with this prograb. If not, see <https://www.gnu.org/licenses/>.
|
2024-07-30 04:02:05 -04:00
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-08-14 16:19:18 -04:00
|
|
|
"bytes"
|
2024-07-30 04:02:05 -04:00
|
|
|
"fmt"
|
2024-08-14 16:19:18 -04:00
|
|
|
"html/template"
|
2024-07-30 04:02:05 -04:00
|
|
|
"log"
|
2024-08-14 16:19:18 -04:00
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"sync"
|
|
|
|
"syscall"
|
|
|
|
"time"
|
2024-07-30 04:02:05 -04:00
|
|
|
)
|
|
|
|
|
2024-08-14 16:19:18 -04:00
|
|
|
var (
|
|
|
|
updateChan = make(chan int)
|
|
|
|
moduleOutputs = make([]string, len(modules))
|
|
|
|
|
|
|
|
mutex sync.Mutex
|
|
|
|
lastOutput string
|
2024-07-30 04:14:13 -04:00
|
|
|
)
|
|
|
|
|
2024-08-14 16:19:18 -04:00
|
|
|
type Module struct {
|
|
|
|
Func func() (interface{}, error)
|
|
|
|
Interval time.Duration
|
|
|
|
Template string
|
|
|
|
Signal int
|
2024-07-30 04:02:05 -04:00
|
|
|
|
2024-08-14 16:19:18 -04:00
|
|
|
// Internal
|
|
|
|
pos int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Module) Run() {
|
|
|
|
if m.pos < 0 || m.pos >= len(modules) {
|
|
|
|
log.Printf("invalid module index %d\n", m.pos)
|
|
|
|
return
|
2024-07-30 04:02:05 -04:00
|
|
|
}
|
|
|
|
|
2024-08-14 16:19:18 -04:00
|
|
|
info, err := m.Func()
|
2024-07-30 04:02:05 -04:00
|
|
|
if err != nil {
|
2024-08-14 16:19:18 -04:00
|
|
|
moduleOutputs[m.pos] = "failed"
|
|
|
|
return
|
2024-07-30 04:02:05 -04:00
|
|
|
}
|
2024-08-14 16:19:18 -04:00
|
|
|
|
|
|
|
var output string
|
|
|
|
if m.Template != "" {
|
|
|
|
// Parse the output and apply the provided template
|
|
|
|
tmpl, err := template.New("module").Parse(m.Template)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("template parsing error: %v\n", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
if err := tmpl.Execute(&buf, info); err != nil {
|
|
|
|
log.Printf("template execution error: %v\n", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
output = buf.String()
|
|
|
|
} else {
|
|
|
|
// Use the output as is
|
|
|
|
output = fmt.Sprintf("%v", info)
|
2024-08-14 12:28:29 -04:00
|
|
|
}
|
|
|
|
|
2024-08-14 16:19:18 -04:00
|
|
|
mutex.Lock()
|
|
|
|
moduleOutputs[m.pos] = output
|
|
|
|
updateChan <- 1
|
|
|
|
mutex.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
sigChan := make(chan os.Signal, 1024)
|
|
|
|
signalMap := make(map[os.Signal][]*Module)
|
|
|
|
|
|
|
|
// Initialize modules
|
|
|
|
for i := range modules {
|
|
|
|
go func(m *Module, i int) {
|
|
|
|
m.pos = i
|
|
|
|
|
|
|
|
if m.Signal != 0 {
|
|
|
|
sig := syscall.Signal(34 + m.Signal)
|
|
|
|
if _, exists := signalMap[sig]; !exists {
|
|
|
|
signal.Notify(sigChan, sig)
|
|
|
|
}
|
|
|
|
signalMap[sig] = append(signalMap[sig], m)
|
|
|
|
}
|
|
|
|
|
|
|
|
m.Run()
|
|
|
|
if m.Interval > 0 {
|
|
|
|
for {
|
|
|
|
time.Sleep(m.Interval)
|
|
|
|
m.Run()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}(&modules[i], i)
|
2024-08-14 12:28:29 -04:00
|
|
|
}
|
|
|
|
|
2024-08-14 16:19:18 -04:00
|
|
|
// Update output on difference
|
|
|
|
go func() {
|
|
|
|
for range updateChan {
|
|
|
|
mutex.Lock()
|
|
|
|
var combinedOutput string
|
|
|
|
for i, output := range moduleOutputs {
|
|
|
|
if i > 0 {
|
|
|
|
combinedOutput += delim
|
|
|
|
}
|
|
|
|
combinedOutput += output
|
|
|
|
}
|
|
|
|
combinedOutput = prefix + combinedOutput + suffix
|
|
|
|
mutex.Unlock()
|
2024-08-14 12:28:29 -04:00
|
|
|
|
2024-08-14 16:19:18 -04:00
|
|
|
if combinedOutput != lastOutput {
|
|
|
|
fmt.Printf("%v\n", combinedOutput)
|
|
|
|
lastOutput = combinedOutput
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Handle module signals
|
|
|
|
for sig := range sigChan {
|
|
|
|
go func(sig *os.Signal) {
|
|
|
|
ms := signalMap[*sig]
|
|
|
|
for _, m := range ms {
|
|
|
|
go m.Run()
|
|
|
|
}
|
|
|
|
}(&sig)
|
2024-08-14 12:28:29 -04:00
|
|
|
}
|
2024-07-30 04:02:05 -04:00
|
|
|
}
|