automatic Logging

This commit is contained in:
Jannover5000r 2025-07-03 14:13:59 +02:00
parent 0308cf0985
commit 056fda8cff

190
main.go
View file

@ -10,8 +10,6 @@ import (
"os" "os"
"os/signal" "os/signal"
"sort" "sort"
// "strings"
"syscall" "syscall"
"time" "time"
Untis "untislogger/Bot" Untis "untislogger/Bot"
@ -51,25 +49,88 @@ func init() {
} }
func main() { func main() {
Untis.Main() //starting API calls function //Untis.Main() //starting API calls function| happens in schedule func
//Run()
//checking for time //Starts logging the timetable for each new Lesson and logs changes
scheduleTimetableUpdate()
sigChan := make(chan os.Signal, 1) sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
log.Println("Program is running. Press Ctrl+C to stop.") log.Println("Program is running. Press Ctrl+C to stop.")
//Start logging //Start logging
Run() //Run()
// Block until we receive a signal // Block until we receive a signal
<-sigChan <-sigChan
log.Println("Shutting down...") log.Println("Shutting down...")
} }
func isScheduledTime(now time.Time) bool {
scheduled := []string{"07:45", "08:35", "09:35", "10:25", "11:25", "12:15", "13:45", "14:25"}
current := now.Format("15:04")
for _, t := range scheduled {
if t == current {
return true
}
}
return false
}
func scheduleTimetableUpdate() {
var prevData []byte
//run once
Untis.Main()
// Initial read of the file
data, err := os.ReadFile("timetableFilled.json")
if err == nil {
prevData = data
}
// Ticker for checking timetable changes every hour
hourTicker := time.NewTicker(1 * time.Hour)
go func() {
for range hourTicker.C {
Untis.Main()
data, err := os.ReadFile("timetableFilled.json")
if err != nil {
log.Printf("Error reading timetable: %v", err)
} else if !bytes.Equal(data, prevData) {
log.Println("Timetable file has changed.")
sendUpdateDiscordWebhook()
prevData = data
}
}
}()
// Ticker for checking scheduled times every minute
startMinuteTicker(func() {
now := time.Now()
if isScheduledTime(now) {
log.Println("Scheduled time reached, updating and running Run()")
Untis.Main()
log.Println("Updated now running Run()")
Run()
log.Println("Finished running Run")
}
})
}
func startMinuteTicker(f func()) {
now := time.Now()
next := now.Truncate(time.Minute).Add(time.Minute)
time.Sleep(time.Until(next))
ticker := time.NewTicker(1 * time.Minute)
go func() {
for {
f()
<-ticker.C
}
}()
}
/* /*
#Main Run Function #Main Run Function
*/ */
func Run() { func Run() {
log.Println("Sending next Lesson")
codeByStartTime, err := MapTimeToCode("timetableFilled.json") codeByStartTime, err := MapTimeToCode("timetableFilled.json")
if err != nil { if err != nil {
log.Println(err) log.Println(err)
@ -79,14 +140,25 @@ func Run() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
subjectByStartTime, err := MapTimeToSubject("timetableFilled.json")
if err != nil {
log.Fatal(err)
}
now := time.Now().Format("15:04") now := time.Now().Format("15:04")
nextTime, room, found := NextRoomForTime(roomByStartTime, now) nextTime, room, found := NextRoomForTime(roomByStartTime, now)
if found { if found {
Status, found := NextCodeForTime(codeByStartTime, now) log.Println("found Room")
Subject, found := NextSubjectForTime(subjectByStartTime, now)
if found { if found {
log.Println("Found Subject")
fmt.Printf("Next time: %s, Room: %s\n", nextTime, room) Status, found := NextCodeForTime(codeByStartTime, now)
sendDiscordWebhook(room, nextTime, Status) if found {
log.Println("Found Status")
fmt.Printf("Next time: %s, Room: %s\n", nextTime, room)
sendDiscordWebhook(Subject, room, nextTime, Status)
} else {
sendDiscordWebhook(Subject, room, nextTime, "")
}
} }
} }
@ -118,6 +190,30 @@ func NextRoomForTime(roomByStartTime map[string]string, current string) (string,
} }
return "", "", false return "", "", false
} }
func NextSubjectForTime(subjectByStartTime map[string]string, current string) (string, bool) {
layout := "15:04"
now, err := time.Parse(layout, current)
if err != nil {
return "", false
}
var times []time.Time
timeToStr := make(map[time.Time]string)
for t := range subjectByStartTime {
parsed, err := time.Parse(layout, t)
if err != nil {
continue
}
times = append(times, parsed)
timeToStr[parsed] = t
}
sort.Slice(times, func(i, j int) bool { return times[i].Before(times[j]) })
for _, t := range times {
if t.After(now) {
return subjectByStartTime[timeToStr[t]], true
}
}
return "", false
}
func NextCodeForTime(codeByStartTime map[string]string, current string) (string, bool) { func NextCodeForTime(codeByStartTime map[string]string, current string) (string, bool) {
layout := "15:04" layout := "15:04"
@ -156,7 +252,9 @@ func MapTimeToRoom(path string) (map[string]string, error) {
} }
roomByStartTime := make(map[string]string) roomByStartTime := make(map[string]string)
for _, entry := range table { for _, entry := range table {
roomByStartTime[entry.StartTime] = entry.Ro[0] if len(entry.Ro) > 0 {
roomByStartTime[entry.StartTime] = entry.Ro[0]
}
} }
if roomByStartTime == nil { if roomByStartTime == nil {
return nil, nil return nil, nil
@ -175,7 +273,11 @@ func MapTimeToCode(path string) (map[string]string, error) {
} }
codeByStartTime := make(map[string]string) codeByStartTime := make(map[string]string)
for _, entry := range table { for _, entry := range table {
codeByStartTime[entry.StartTime] = entry.Code if len(entry.Code) > 0 {
if _, exists := codeByStartTime[entry.StartTime]; !exists {
codeByStartTime[entry.StartTime] = entry.Code
}
}
} }
return codeByStartTime, nil return codeByStartTime, nil
} }
@ -191,7 +293,9 @@ func MapTimeToSubject(path string) (map[string]string, error) {
} }
subjectByStartTime := make(map[string]string) subjectByStartTime := make(map[string]string)
for _, entry := range table { for _, entry := range table {
subjectByStartTime[entry.StartTime] = entry.Su[0] if len(entry.Su) > 0 {
subjectByStartTime[entry.StartTime] = entry.Su[0]
}
} }
return subjectByStartTime, nil return subjectByStartTime, nil
} }
@ -220,12 +324,12 @@ type Field struct {
Inline bool `json:"inline"` Inline bool `json:"inline"`
} }
func sendDiscordWebhook(room string, nextTime string, Status string) { func sendDiscordWebhook(subject string, room string, nextTime string, Status string) {
log.Println("Sending Discord webhook notification...") log.Println("Sending Discord webhook notification...")
// Create a rich embed message // Create a rich embed message
message := fmt.Sprintf( message := fmt.Sprintf(
"Room: %s\nStart-Time: %s\nStatus: %s", "Subject: %s\nRoom: %s\nStart-Time: %s\nStatus: %s",
room, nextTime, Status, subject, room, nextTime, Status,
) )
/*embed := Embed{ /*embed := Embed{
Title: "Next Lesson ", Title: "Next Lesson ",
@ -276,3 +380,57 @@ func sendDiscordWebhook(room string, nextTime string, Status string) {
log.Printf("Discord webhook failed with status %d: %s", resp.StatusCode, string(body)) log.Printf("Discord webhook failed with status %d: %s", resp.StatusCode, string(body))
} }
} }
func sendUpdateDiscordWebhook() {
log.Println("Sending Discord webhook notification...")
// Create a rich embed message
message := "A lesson on your timetable has changed"
/*embed := Embed{
Title: "Next Lesson ",
Description: "The next lesson is starting soon: ",
Color: 3066993, // Green color
Timestamp: time.Now().Format(time.RFC3339),
Fields: []Field{
{
Name: "New Lesson",
// Value: fmt.Sprintf("`%s`", ip),
Value: fmt.Sprintf("Room: %s", room),
Inline: true,
},
{
Name: "Start-Time",
Value: fmt.Sprintf("Start time: %s", nextTime),
Inline: true,
},
{
Name: "Status",
Value: fmt.Sprintf("Status: %s", Status),
Inline: true,
},
},
}
*/
payload := DiscordWebhookPayload{
Content: message,
}
jsonData, err := json.Marshal(payload)
if err != nil {
log.Printf("Error marshaling webhook payload: %v", err)
return
}
resp, err := http.Post(discordWebhookURL, "application/json", bytes.NewBuffer(jsonData))
if err != nil {
log.Printf("Error sending Discord webhook: %v", err)
return
}
defer resp.Body.Close()
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
log.Println("Discord webhook notification sent successfully")
} else {
body, _ := ioutil.ReadAll(resp.Body)
log.Printf("Discord webhook failed with status %d: %s", resp.StatusCode, string(body))
}
}