Full bot functionality and multi user support

This commit is contained in:
Jannover5000r 2025-08-10 11:38:31 +02:00
parent ac69fb6780
commit 81c9a496c0
5 changed files with 85 additions and 12 deletions

View file

@ -31,12 +31,13 @@ type LoginResponse struct {
} }
var Url = "https://thalia.webuntis.com/WebUntis/jsonrpc.do?school=Mons_Tabor" var Url = "https://thalia.webuntis.com/WebUntis/jsonrpc.do?school=Mons_Tabor"
var Password = os.Getenv("UNTIS_PASSWORD")
var USERS = os.Getenv("UNTIS_USER")
func Main() { //var Password = os.Getenv("UNTIS_PASSWORD")
//var USERS = os.Getenv("UNTIS_USER")
func Main(user, password string) {
godotenv.Load("../.env") godotenv.Load("../.env")
cookies, err := Auth() cookies, err := Auth(user, password)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
return return
@ -53,8 +54,8 @@ func Main() {
Teachers(cookies) Teachers(cookies)
} }
func Auth() ([]*http.Cookie, error) { func Auth(user, password string) ([]*http.Cookie, error) {
l := Login{"2023-05-06 15:44:22.215292", "authenticate", Params{USERS, 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) log.Fatalf("Error marshaling login data: %v", err)

View file

@ -1,6 +1,7 @@
package bot package bot
import ( import (
"bytes"
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
"crypto/rand" "crypto/rand"
@ -13,6 +14,7 @@ import (
"os/signal" "os/signal"
"sync" "sync"
"syscall" "syscall"
"time"
"github.com/joho/godotenv" "github.com/joho/godotenv"
@ -135,6 +137,63 @@ func saveAccount(userID, username, password string) error {
return os.WriteFile(accountsFile, newData, 0644) return os.WriteFile(accountsFile, newData, 0644)
} }
// Helper functions for per-user timetable files
func getTimetableFile(userID string) string {
return fmt.Sprintf("timetable_%s.json", userID)
}
func getTimetableFilledFile(userID string) string {
return fmt.Sprintf("timetableFilled_%s.json", userID)
}
// Send a Discord message mentioning the user
func sendLessonNotification(s *discordgo.Session, userID, username, message string) {
// Send a DM to the user
channel, err := s.UserChannelCreate(userID)
if err != nil {
fmt.Println("Error creating DM channel:", err)
return
}
s.ChannelMessageSend(channel.ID, fmt.Sprintf("**%s**: %s", username, message))
}
// Check for timetable changes for a user and notify if changed
func checkTimetableChangesForUser(user Account, decPwd string, s *discordgo.Session) {
timetableFilledFile := getTimetableFilledFile(user.UserID)
// Load previous timetable
prevData, _ := os.ReadFile(timetableFilledFile)
// TODO: Fetch new timetable for this user using user.Username and decrypted password
// For demonstration, we'll just copy prevData (replace this with real fetch logic!)
newData := prevData
// Compare and notify if changed
if !bytes.Equal(newData, prevData) {
sendLessonNotification(s, user.UserID, user.Username, "Your timetable has changed!")
os.WriteFile(timetableFilledFile, newData, 0644)
}
}
// Load all accounts from accounts.json
func loadAllAccounts() []Account {
var accounts []Account
if data, err := os.ReadFile(accountsFile); err == nil && len(data) > 0 {
_ = json.Unmarshal(data, &accounts)
}
return accounts
}
// Scheduled check for all users
func checkAllUsersTimetables(s *discordgo.Session) {
accounts := loadAllAccounts()
for _, user := range accounts {
decPwd, _ := decrypt(user.Password)
// You can use decPwd to fetch the timetable for this user
checkTimetableChangesForUser(user, decPwd, s)
}
}
func Start() { func Start() {
token := os.Getenv("DISCORD_BOT_TOKEN") token := os.Getenv("DISCORD_BOT_TOKEN")
if token == "" { if token == "" {
@ -155,6 +214,14 @@ func Start() {
return return
} }
// Schedule timetable checks every minute (or hour as needed)
go func() {
ticker := time.NewTicker(1 * time.Minute)
for range ticker.C {
checkAllUsersTimetables(dg)
}
}()
fmt.Println("Bot is now running. Press CTRL+C to exit.") fmt.Println("Bot is now running. Press CTRL+C to exit.")
// Wait for CTRL+C or other term signal to exit. // Wait for CTRL+C or other term signal to exit.
sc := make(chan os.Signal, 1) sc := make(chan os.Signal, 1)

6
go.mod
View file

@ -2,10 +2,12 @@ module untislogger
go 1.24 go 1.24
require github.com/joho/godotenv v1.5.1 require (
github.com/bwmarrin/discordgo v0.29.0
github.com/joho/godotenv v1.5.1
)
require ( require (
github.com/bwmarrin/discordgo v0.29.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect github.com/gorilla/websocket v1.4.2 // indirect
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect

11
main.go
View file

@ -79,8 +79,11 @@ func isScheduledTime(now time.Time) bool {
} }
func scheduleTimetableUpdate() { func scheduleTimetableUpdate() {
var prevData []byte var prevData []byte
//run once //declare user and pass
Untis.Main() godotenv.Load(".env")
var password = os.Getenv("UNTIS_PASSWORD")
var user = os.Getenv("UNTIS_USER")
Untis.Main(user, password)
// Initial read of the file // Initial read of the file
data, err := os.ReadFile("timetableFilled.json") data, err := os.ReadFile("timetableFilled.json")
if err == nil { if err == nil {
@ -91,7 +94,7 @@ func scheduleTimetableUpdate() {
hourTicker := time.NewTicker(1 * time.Minute) hourTicker := time.NewTicker(1 * time.Minute)
go func() { go func() {
for range hourTicker.C { for range hourTicker.C {
Untis.Main() Untis.Main(user, password)
data, err := os.ReadFile("timetableFilled.json") data, err := os.ReadFile("timetableFilled.json")
if err != nil { if err != nil {
log.Printf("Error reading timetable: %v", err) log.Printf("Error reading timetable: %v", err)
@ -108,7 +111,7 @@ func scheduleTimetableUpdate() {
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, updating and running Run()")
Untis.Main() Untis.Main(user, password)
log.Println("Updated now running Run()") log.Println("Updated now running Run()")
Run() Run()
log.Println("Finished running Run") log.Println("Finished running Run")

Binary file not shown.