feat: Implement multi-user timetable tracking and notifications #1
4 changed files with 226 additions and 135 deletions
106
Bot/Timetable.go
106
Bot/Timetable.go
|
|
@ -88,67 +88,73 @@ func ReadLoginResultFromFile(path string) (Loginresult, error) {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Timetable(cookies []*http.Cookie) {
|
func Timetable(cookies []*http.Cookie, userID string) {
|
||||||
loginResult, err := ReadLoginResultFromFile("login.json")
|
loginFile := "login.json"
|
||||||
if err != nil {
|
if userID != "" {
|
||||||
log.Fatal(err)
|
loginFile = "login_" + userID + ".json"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loginResult, err := ReadLoginResultFromFile(loginFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Could not read login result for user %s: %v", userID, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
today := time.Now().Format("20060102")
|
today := time.Now().Format("20060102")
|
||||||
g := getTimetable{"2023-05-06 15:44:22.215292", "getTimetable", params{today, today, loginResult.PersonID, loginResult.PersonType}, "2.0"}
|
g := getTimetable{"2023-05-06 15:44:22.215292", "getTimetable", params{today, today, loginResult.PersonID, loginResult.PersonType}, "2.0"}
|
||||||
TimetablesJson, err := json.Marshal(g)
|
timetablesJson, err := json.Marshal(g)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error marshaling login data: %v", err)
|
log.Printf("Error marshaling timetable request: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
timetable := bytes.NewReader(TimetablesJson)
|
timetable := bytes.NewReader(timetablesJson)
|
||||||
|
|
||||||
prompt, err := http.NewRequest("GET", Url, timetable)
|
req, err := http.NewRequest("GET", Url, timetable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error creatingrequest: %v", err)
|
log.Printf("Error creating timetable request: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//log.Println("prompt without extra header or cookie ", prompt)
|
req.Header.Set("Content-Type", "application/json")
|
||||||
//log.Println("Cookie: ", cookies)
|
|
||||||
|
|
||||||
prompt.Header.Set("Content-Type", "application/json")
|
|
||||||
prompt.Header.Set("User-Agent", "Webuntis Test")
|
|
||||||
|
|
||||||
for _, cookie := range cookies {
|
for _, cookie := range cookies {
|
||||||
//if cookie.Name == "JSESSIONID" {
|
req.AddCookie(cookie)
|
||||||
prompt.AddCookie(cookie)
|
|
||||||
//log.Printf("Added JSESSIONID cookie: %s=%s", cookie.Name, cookie.Value)
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
//log.Println("Request JSON:", string(TeachersJson))
|
|
||||||
out, err := http.DefaultClient.Do(prompt)
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error during request: %v", err)
|
log.Printf("Error fetching timetable: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer out.Body.Close()
|
defer resp.Body.Close()
|
||||||
//log.Println(out.Status)
|
|
||||||
response, err := io.ReadAll(out.Body)
|
response, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error reading response body: %v", err)
|
log.Printf("Error reading timetable response: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//responseString := string(response)
|
|
||||||
//log.Println("Repsonse ", responseString)
|
|
||||||
var Response TimetableResponse
|
var Response TimetableResponse
|
||||||
err = json.Unmarshal(response, &Response)
|
if err := json.Unmarshal(response, &Response); err != nil {
|
||||||
if err != nil {
|
log.Printf("Error unmarshaling timetable response: %v", err)
|
||||||
log.Fatalf("Error unmarshaling response: %v", err)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := json.MarshalIndent(Response.Result, "", " ")
|
data, err := json.MarshalIndent(Response.Result, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Printf("Error marshaling timetable result: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
err = os.WriteFile("timetable.json", data, 0644)
|
|
||||||
if err != nil {
|
timetableFile := "timetable.json"
|
||||||
log.Fatal(err)
|
if userID != "" {
|
||||||
|
timetableFile = "timetable_" + userID + ".json"
|
||||||
}
|
}
|
||||||
log.Println("Updated Timetable")
|
if err := os.WriteFile(timetableFile, data, 0644); err != nil {
|
||||||
setTimetable()
|
log.Printf("Error writing timetable file: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Updated timetable for user %s", userID)
|
||||||
|
setTimetable(userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadIDMap(path string) (map[int]string, error) {
|
func LoadIDMap(path string) (map[int]string, error) {
|
||||||
|
|
@ -189,14 +195,18 @@ func formatDate(date int) string {
|
||||||
day := s[6:8]
|
day := s[6:8]
|
||||||
return fmt.Sprintf("%s-%s-%s", day, month, year)
|
return fmt.Sprintf("%s-%s-%s", day, month, year)
|
||||||
}
|
}
|
||||||
func setTimetable() {
|
func setTimetable(userID string) {
|
||||||
subjects, _ := LoadIDMap("subjects.json")
|
subjects, _ := LoadIDMap("subjects.json")
|
||||||
rooms, _ := LoadIDMap("rooms.json")
|
rooms, _ := LoadIDMap("rooms.json")
|
||||||
classes, _ := LoadIDMap("classes.json")
|
classes, _ := LoadIDMap("classes.json")
|
||||||
timetable, _ := LoadTimetable("timetable.json")
|
|
||||||
|
timetableFile := "timetable.json"
|
||||||
|
if userID != "" {
|
||||||
|
timetableFile = "timetable_" + userID + ".json"
|
||||||
|
}
|
||||||
|
timetable, _ := LoadTimetable(timetableFile)
|
||||||
|
|
||||||
var namedTimetable []NamedTimetableEntry
|
var namedTimetable []NamedTimetableEntry
|
||||||
|
|
||||||
for _, lesson := range timetable {
|
for _, lesson := range timetable {
|
||||||
var klNames, suNames, roNames []string
|
var klNames, suNames, roNames []string
|
||||||
for _, kl := range lesson.Kl {
|
for _, kl := range lesson.Kl {
|
||||||
|
|
@ -224,11 +234,17 @@ func setTimetable() {
|
||||||
|
|
||||||
data, err := json.MarshalIndent(namedTimetable, "", " ")
|
data, err := json.MarshalIndent(namedTimetable, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Printf("Error marshaling named timetable: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
err = os.WriteFile("timetableFilled.json", data, 0644)
|
|
||||||
if err != nil {
|
timetableFilledFile := "timetableFilled.json"
|
||||||
log.Fatal(err)
|
if userID != "" {
|
||||||
|
timetableFilledFile = "timetableFilled_" + userID + ".json"
|
||||||
}
|
}
|
||||||
log.Println("Filled Timetable")
|
if err := os.WriteFile(timetableFilledFile, data, 0644); err != nil {
|
||||||
|
log.Printf("Error writing timetableFilled file: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf("Filled timetable for user %s", userID)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
49
Bot/Untis.go
49
Bot/Untis.go
|
|
@ -35,70 +35,59 @@ var Url = "https://thalia.webuntis.com/WebUntis/jsonrpc.do?school=Mons_Tabor"
|
||||||
//var Password = os.Getenv("UNTIS_PASSWORD")
|
//var Password = os.Getenv("UNTIS_PASSWORD")
|
||||||
//var USERS = os.Getenv("UNTIS_USER")
|
//var USERS = os.Getenv("UNTIS_USER")
|
||||||
|
|
||||||
func Main(user, password string) {
|
func Main(user, password, userID string) {
|
||||||
godotenv.Load("../.env")
|
godotenv.Load("../.env")
|
||||||
cookies, err := Auth(user, password)
|
cookies, err := Auth(user, password, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Printf("Authentication failed for user %s: %v", user, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Rooms(cookies)
|
Rooms(cookies)
|
||||||
|
|
||||||
Classes(cookies)
|
Classes(cookies)
|
||||||
|
|
||||||
Subjects(cookies)
|
Subjects(cookies)
|
||||||
|
Timetable(cookies, userID)
|
||||||
Timetable(cookies)
|
|
||||||
|
|
||||||
//getTeachers sends empty response
|
|
||||||
Teachers(cookies)
|
Teachers(cookies)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Auth(user, password string) ([]*http.Cookie, error) {
|
func Auth(user, password, userID string) ([]*http.Cookie, error) {
|
||||||
l := Login{"2023-05-06 15:44:22.215292", "authenticate", Params{user, password, "WebUntis Test"}, "2.0"}
|
l := Login{"2023-05-06 15:44:22.215292", "authenticate", Params{user, password, "WebUntis Test"}, "2.0"}
|
||||||
loginJSON, err := json.Marshal(l)
|
loginJSON, err := json.Marshal(l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error marshaling login data: %v", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
login := bytes.NewReader(loginJSON)
|
login := bytes.NewReader(loginJSON)
|
||||||
|
|
||||||
//log.Println("Run")
|
|
||||||
LoginOut, err := http.Post(Url, "application/json", login)
|
LoginOut, err := http.Post(Url, "application/json", login)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error during authentication: %v", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer LoginOut.Body.Close()
|
defer LoginOut.Body.Close()
|
||||||
|
|
||||||
// Parse cookies from response
|
|
||||||
cookies := LoginOut.Cookies()
|
cookies := LoginOut.Cookies()
|
||||||
//log.Println("Received cookies:", cookies)
|
log.Printf("Login successful for user: %s", user)
|
||||||
//log.Println("Set-Cookie headers:", LoginOut.Header["Set-Cookie"])
|
|
||||||
//loginRespBody, _ := io.ReadAll(LoginOut.Body)
|
|
||||||
//log.Println("Login response body:", string(loginRespBody))
|
|
||||||
|
|
||||||
log.Println("Login successful")
|
|
||||||
|
|
||||||
//log.Println("Login successful")
|
|
||||||
response, err := io.ReadAll(LoginOut.Body)
|
response, err := io.ReadAll(LoginOut.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error reading response body: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var Response LoginResponse
|
var Response LoginResponse
|
||||||
err = json.Unmarshal(response, &Response)
|
if err := json.Unmarshal(response, &Response); err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
log.Fatalf("Error unmarshaling response: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := json.MarshalIndent(Response.Result, "", " ")
|
data, err := json.MarshalIndent(Response.Result, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
err = os.WriteFile("login.json", data, 0644)
|
|
||||||
if err != nil {
|
loginFile := "login.json"
|
||||||
log.Fatal(err)
|
if userID != "" {
|
||||||
|
loginFile = "login_" + userID + ".json"
|
||||||
|
}
|
||||||
|
if err := os.WriteFile(loginFile, data, 0644); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return cookies, nil
|
return cookies, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -248,6 +248,35 @@ func Start() {
|
||||||
dg.Close()
|
dg.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecryptedAccount holds user information with a decrypted password.
|
||||||
|
type DecryptedAccount struct {
|
||||||
|
UserID string
|
||||||
|
Username string
|
||||||
|
DecryptedPassword string
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadAndDecryptAccounts loads all accounts from the JSON file and decrypts their passwords.
|
||||||
|
func LoadAndDecryptAccounts() ([]DecryptedAccount, error) {
|
||||||
|
accounts := loadAllAccounts()
|
||||||
|
decryptedAccounts := make([]DecryptedAccount, 0, len(accounts))
|
||||||
|
|
||||||
|
for _, acc := range accounts {
|
||||||
|
decPwd, err := decrypt(acc.Password)
|
||||||
|
if err != nil {
|
||||||
|
// Log the error but continue with other accounts
|
||||||
|
fmt.Printf("Error decrypting password for user %s: %v\n", acc.UserID, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
decryptedAccounts = append(decryptedAccounts, DecryptedAccount{
|
||||||
|
UserID: acc.UserID,
|
||||||
|
Username: acc.Username,
|
||||||
|
DecryptedPassword: decPwd,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return decryptedAccounts, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Expose this for main.go to trigger notifications
|
// Expose this for main.go to trigger notifications
|
||||||
func NotifyAllUsers() {
|
func NotifyAllUsers() {
|
||||||
if DiscordSession != nil {
|
if DiscordSession != nil {
|
||||||
|
|
@ -255,6 +284,27 @@ func NotifyAllUsers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendDM sends a direct message to a user.
|
||||||
|
func SendDM(userID, message string) {
|
||||||
|
if DiscordSession == nil {
|
||||||
|
fmt.Println("Discord session not initialized, cannot send DM.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Avoid sending messages to the "default" user placeholder
|
||||||
|
if userID == "default" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
channel, err := DiscordSession.UserChannelCreate(userID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error creating DM channel for %s: %v\n", userID, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = DiscordSession.ChannelMessageSend(channel.ID, message)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error sending DM to %s: %v\n", userID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||||
// Ignore bot's own messages
|
// Ignore bot's own messages
|
||||||
if m.Author.ID == s.State.User.ID {
|
if m.Author.ID == s.State.User.ID {
|
||||||
|
|
|
||||||
156
main.go
156
main.go
|
|
@ -80,45 +80,74 @@ func isScheduledTime(now time.Time) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func scheduleTimetableUpdate() {
|
func scheduleTimetableUpdate() {
|
||||||
var prevData []byte
|
prevData := make(map[string][]byte)
|
||||||
//declare user and pass
|
|
||||||
godotenv.Load(".env")
|
// Function to update all users
|
||||||
var password = os.Getenv("UNTIS_PASSWORD")
|
updateAllUsers := func() {
|
||||||
var user = os.Getenv("UNTIS_USER")
|
// Load all registered users
|
||||||
Untis.Main(user, password)
|
accounts, err := BotStart.LoadAndDecryptAccounts()
|
||||||
// Initial read of the file
|
if err != nil {
|
||||||
data, err := os.ReadFile("timetableFilled.json")
|
log.Printf("Error loading accounts: %v", err)
|
||||||
if err == nil {
|
|
||||||
prevData = data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ticker for checking timetable changes every hour
|
// Add the default user from .env
|
||||||
hourTicker := time.NewTicker(1 * time.Minute)
|
defaultUser := os.Getenv("UNTIS_USER")
|
||||||
|
defaultPassword := os.Getenv("UNTIS_PASSWORD")
|
||||||
|
if defaultUser != "" && defaultPassword != "" {
|
||||||
|
accounts = append(accounts, BotStart.DecryptedAccount{
|
||||||
|
UserID: "default",
|
||||||
|
Username: defaultUser,
|
||||||
|
DecryptedPassword: defaultPassword,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process each user
|
||||||
|
for _, acc := range accounts {
|
||||||
|
// Fetch the latest timetable
|
||||||
|
Untis.Main(acc.Username, acc.DecryptedPassword, acc.UserID)
|
||||||
|
|
||||||
|
// Check for changes
|
||||||
|
timetableFile := fmt.Sprintf("timetableFilled_%s.json", acc.UserID)
|
||||||
|
if acc.UserID == "default" {
|
||||||
|
timetableFile = "timetableFilled.json"
|
||||||
|
}
|
||||||
|
data, err := os.ReadFile(timetableFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error reading timetable for user %s: %v", acc.Username, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if prev, ok := prevData[acc.UserID]; ok && !bytes.Equal(data, prev) {
|
||||||
|
log.Printf("Timetable has changed for user %s.", acc.Username)
|
||||||
|
BotStart.SendDM(acc.UserID, "Your timetable has changed!")
|
||||||
|
}
|
||||||
|
prevData[acc.UserID] = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial update
|
||||||
|
updateAllUsers()
|
||||||
|
|
||||||
|
// Ticker for periodic updates
|
||||||
|
hourTicker := time.NewTicker(1 * time.Minute) // For testing, 1 minute. Change to 1 * time.Hour for production.
|
||||||
go func() {
|
go func() {
|
||||||
for range hourTicker.C {
|
for range hourTicker.C {
|
||||||
Untis.Main(user, password)
|
updateAllUsers()
|
||||||
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
|
|
||||||
}
|
|
||||||
// Trigger bot notifications for all users
|
|
||||||
BotStart.NotifyAllUsers()
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Ticker for checking scheduled times every minute
|
// Ticker for scheduled lesson notifications
|
||||||
startMinuteTicker(func() {
|
startMinuteTicker(func() {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
if isScheduledTime(now) {
|
if isScheduledTime(now) {
|
||||||
log.Println("Scheduled time reached, updating and running Run()")
|
log.Println("Scheduled time reached, running notifications...")
|
||||||
Untis.Main(user, password)
|
accounts, _ := BotStart.LoadAndDecryptAccounts()
|
||||||
log.Println("Updated now running Run()")
|
// Also notify the default user
|
||||||
Run()
|
accounts = append(accounts, BotStart.DecryptedAccount{UserID: "default"})
|
||||||
log.Println("Finished running Run")
|
for _, acc := range accounts {
|
||||||
|
Run(acc.UserID)
|
||||||
|
}
|
||||||
|
log.Println("Finished running notifications.")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -136,42 +165,49 @@ func startMinuteTicker(f func()) {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func Run(userID string) {
|
||||||
#Main Run Function
|
timetableFile := "timetableFilled.json"
|
||||||
*/
|
if userID != "default" {
|
||||||
func Run() {
|
timetableFile = fmt.Sprintf("timetableFilled_%s.json", userID)
|
||||||
log.Println("Sending next Lesson")
|
}
|
||||||
codeByStartTime, err := MapTimeToCode("timetableFilled.json")
|
log.Printf("Sending next lesson for user %s", userID)
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
// Check if the timetable file exists
|
||||||
|
if _, err := os.Stat(timetableFile); os.IsNotExist(err) {
|
||||||
|
log.Printf("Timetable file %s not found for user %s.", timetableFile, userID)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
roomByStartTime, err := MapTimeToRoom("timetableFilled.json")
|
codeByStartTime, _ := MapTimeToCode(timetableFile)
|
||||||
if err != nil {
|
roomByStartTime, _ := MapTimeToRoom(timetableFile)
|
||||||
log.Fatal(err)
|
subjectByStartTime, _ := MapTimeToSubject(timetableFile)
|
||||||
}
|
|
||||||
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, foundRoom := NextRoomForTime(roomByStartTime, now)
|
||||||
if found {
|
if !foundRoom {
|
||||||
log.Println("found Room")
|
return // No upcoming lessons
|
||||||
Subject, found := NextSubjectForTime(subjectByStartTime, now)
|
|
||||||
if found {
|
|
||||||
log.Println("Found Subject")
|
|
||||||
Status, found := NextCodeForTime(codeByStartTime, now)
|
|
||||||
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, "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subject, foundSubject := NextSubjectForTime(subjectByStartTime, now)
|
||||||
|
if !foundSubject {
|
||||||
|
return // Should not happen if room was found
|
||||||
|
}
|
||||||
|
|
||||||
|
status, _ := NextCodeForTime(codeByStartTime, now)
|
||||||
|
|
||||||
|
var message string
|
||||||
|
if status != "" {
|
||||||
|
message = fmt.Sprintf("Next lesson: **%s** in room **%s** at **%s**. Status: **%s**", subject, room, nextTime, status)
|
||||||
|
} else {
|
||||||
|
message = fmt.Sprintf("Next lesson: **%s** in room **%s** at **%s**.", subject, room, nextTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
if userID == "default" {
|
||||||
|
// The default user still sends to the webhook
|
||||||
|
sendDiscordWebhook(subject, room, nextTime, status)
|
||||||
|
} else {
|
||||||
|
BotStart.SendDM(userID, message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue