Full bot functionality and multi user support
This commit is contained in:
parent
ac69fb6780
commit
81c9a496c0
5 changed files with 85 additions and 12 deletions
13
Bot/Untis.go
13
Bot/Untis.go
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
6
go.mod
|
|
@ -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
11
main.go
|
|
@ -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")
|
||||||
|
|
|
||||||
BIN
untislogger
BIN
untislogger
Binary file not shown.
Loading…
Reference in a new issue