Next time to room

This commit is contained in:
Jannover5000r 2025-06-27 12:55:28 +02:00
parent 71d83a6ada
commit 04acd01078
2 changed files with 64 additions and 145 deletions

View file

@ -41,8 +41,10 @@ func Main() {
Subjects(cookies) Subjects(cookies)
//getTeachers sends empty response -> commented out Timetable(cookies)
//Teachers(cookies)
//getTeachers sends empty response
Teachers(cookies)
} }
func Auth() ([]*http.Cookie, error) { func Auth() ([]*http.Cookie, error) {

203
main.go
View file

@ -9,7 +9,9 @@ import (
"net/http" "net/http"
"os" "os"
"os/signal" "os/signal"
"strings" "sort"
// "strings"
"syscall" "syscall"
"time" "time"
Untis "untislogger/Bot" Untis "untislogger/Bot"
@ -49,113 +51,76 @@ func init() {
} }
func main() { func main() {
go Untis.Main() //starting API calls function Untis.Main() //starting API calls function
//checking for time //checking for time
log.Println("starting Timetable checks")
go checkTimetableChanges()
go notifyUpcomingLessons()
// Create a channel to receive OS signals
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.")
Run()
// Block until we receive a signal // Block until we receive a signal
<-sigChan <-sigChan
log.Println("Shutting down...") log.Println("Shutting down...")
} }
func loadTimetableFilled(path string) ([]NamedTimetableEntry, error) { /*
#Main Run Function
*/
func Run() {
roomByStartTime, err := MapTimeToRoom("timetableFilled.json")
if err != nil {
log.Fatal(err)
}
now := time.Now().Format("15:04")
nextTime, room, found := NextRoomForTime(roomByStartTime, now)
if found {
fmt.Printf("Next time: %s, Room: %s\n", nextTime, room)
}
}
/*
*/
func NextRoomForTime(roomByStartTime map[string]string, current string) (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 roomByStartTime {
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 timeToStr[t], roomByStartTime[timeToStr[t]], true
}
}
return "", "", false
}
func MapTimeToRoom(path string) (map[string]string, error) {
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var entries []NamedTimetableEntry var table []NamedTimetableEntry
if err := json.Unmarshal(data, &entries); err != nil { err = json.Unmarshal(data, &table)
if err != nil {
return nil, err return nil, err
} }
return entries, nil roomByStartTime := make(map[string]string)
} for _, entry := range table {
roomByStartTime[entry.StartTime] = entry.Ro[0]
func checkTimetableChanges() {
var lastTimetable []NamedTimetableEntry
for {
current, err := loadTimetableFilled("timetableFilled.json")
if err != nil {
log.Println("Error loading timetable:", err)
time.Sleep(time.Hour)
continue
}
// Compare with last timetable (simple string comparison)
log.Println("Checking if something changed")
if !equalTimetables(lastTimetable, current) && len(lastTimetable) > 0 {
// Find and send changes
changes := diffTimetables(lastTimetable, current)
oldMap := make(map[int]NamedTimetableEntry)
for _, e := range lastTimetable {
oldMap[e.ID] = e
}
for _, newLesson := range changes {
oldLesson, found := oldMap[newLesson.ID]
if found {
sendTimetableChangeWebhook(oldLesson, newLesson)
} else {
// If it's a new lesson, you can send a simple notification or skip
sendTimetableChangeWebhook(NamedTimetableEntry{}, newLesson)
}
}
}
lastTimetable = current
time.Sleep(time.Hour)
}
}
func equalTimetables(a, b []NamedTimetableEntry) bool {
aj, _ := json.Marshal(a)
bj, _ := json.Marshal(b)
return bytes.Equal(aj, bj)
}
func diffTimetables(old, new []NamedTimetableEntry) []NamedTimetableEntry {
// Simple diff: return lessons in new that are not in old
var diff []NamedTimetableEntry
oldMap := make(map[int]NamedTimetableEntry)
for _, e := range old {
oldMap[e.ID] = e
}
for _, e := range new {
if _, found := oldMap[e.ID]; !found {
diff = append(diff, e)
}
}
return diff
}
func notifyUpcomingLessons() {
log.Println("checking for new Lesson")
for {
entries, err := loadTimetableFilled("timetableFilled.json")
if err != nil {
log.Println("Error loading timetable:", err)
time.Sleep(time.Minute)
continue
}
now := time.Now()
for _, lesson := range entries {
// Parse date and time
lessonTime, err := time.Parse("02-01-2006 15:04", lesson.Date+" "+lesson.StartTime)
if err != nil {
continue
}
if lessonTime.Sub(now) > 4*time.Minute && lessonTime.Sub(now) < 6*time.Minute {
sendNextLessonWebhook(lesson)
}
}
time.Sleep(time.Minute)
} }
return roomByStartTime, nil
} }
// Discord webhook configuration // Discord webhook configuration
@ -181,67 +146,19 @@ type Field struct {
Inline bool `json:"inline"` Inline bool `json:"inline"`
} }
func sendTimetableChangeWebhook(oldLesson, newLesson NamedTimetableEntry) {
var changes []string
if !equalStringSlices(oldLesson.Su, newLesson.Su) {
changes = append(changes, fmt.Sprintf("Subject: %v → %v", strings.Join(oldLesson.Su, ", "), strings.Join(newLesson.Su, ", ")))
}
if !equalStringSlices(oldLesson.Ro, newLesson.Ro) {
changes = append(changes, fmt.Sprintf("Room: %v → %v", strings.Join(oldLesson.Ro, ", "), strings.Join(newLesson.Ro, ", ")))
}
if oldLesson.StartTime != newLesson.StartTime {
changes = append(changes, fmt.Sprintf("Time: %s → %s", oldLesson.StartTime, newLesson.StartTime))
}
if oldLesson.Code != newLesson.Code {
changes = append(changes, fmt.Sprintf("Code: %s → %s", oldLesson.Code, newLesson.Code))
}
if len(changes) == 0 {
changes = append(changes, "Other details changed")
}
content := fmt.Sprintf("**Timetable Change**\nLesson: %v\nTime: %s\nChanged: %s",
strings.Join(newLesson.Su, ", "),
newLesson.StartTime,
strings.Join(changes, "; "),
)
sendDiscordWebhook(content)
}
func sendNextLessonWebhook(lesson NamedTimetableEntry) {
content := fmt.Sprintf(
"**Next Lesson Reminder**\nLesson: %v\nTime: %s\nRoom: %v",
strings.Join(lesson.Su, ", "),
lesson.StartTime,
strings.Join(lesson.Ro, ", "),
)
sendDiscordWebhook(content)
}
func equalStringSlices(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func sendDiscordWebhook(ip string) { func sendDiscordWebhook(ip string) {
log.Println("Sending Discord webhook notification...") log.Println("Sending Discord webhook notification...")
// Create a rich embed message // Create a rich embed message
embed := Embed{ embed := Embed{
Title: "🌐 Public IP Address Changed!", Title: "A Lesson has changed ",
Description: "Your public IP address has been updated.", Description: "A lesson on your timetable has changed ",
Color: 3066993, // Green color Color: 3066993, // Green color
Timestamp: time.Now().Format(time.RFC3339), Timestamp: time.Now().Format(time.RFC3339),
Fields: []Field{ Fields: []Field{
{ {
Name: "New IP Address", Name: "New Lesson",
Value: fmt.Sprintf("`%s`", ip), // Value: fmt.Sprintf("`%s`", ip),
Inline: true, Inline: true,
}, },
{ {