From 39f9bccef432c43fe92064029b1eb930c938e164 Mon Sep 17 00:00:00 2001 From: zervo Date: Mon, 9 Dec 2024 19:12:24 +0100 Subject: [PATCH] Integrate schedules (half complete) --- .cspell/custom-dictionary.txt | 5 +- cmd/goskola24api/main.go | 9 ++++ goskola24api.go | 4 ++ internal/requests/get_schedule.go | 89 +++++++++++++++++++++++++++++++ internal/types/req_schedule.go | 48 +++++++++++++++++ internal/types/response.go | 21 +++++--- internal/utility/request.go | 10 ++++ 7 files changed, 178 insertions(+), 8 deletions(-) create mode 100644 internal/requests/get_schedule.go create mode 100644 internal/types/req_schedule.go diff --git a/.cspell/custom-dictionary.txt b/.cspell/custom-dictionary.txt index ad433d1..e069b11 100644 --- a/.cspell/custom-dictionary.txt +++ b/.cspell/custom-dictionary.txt @@ -1,7 +1,8 @@ # Custom Dictionary Words -skola goskola pubtypes +skola +xscope +zadachin zervo zervó -zadachin \ No newline at end of file diff --git a/cmd/goskola24api/main.go b/cmd/goskola24api/main.go index e986079..db91016 100644 --- a/cmd/goskola24api/main.go +++ b/cmd/goskola24api/main.go @@ -28,6 +28,8 @@ func main() { } } + terms, _ := api.GetTerms() + rooms, err := api.GetRooms(schools[4], true) if err != nil { fmt.Println(err.Error()) @@ -56,4 +58,11 @@ func main() { } fmt.Println(key) + + schedule, err := api.GetWeekSchedule(2024, 50, schools[4], terms.ActiveTerms[0], classes[0]) + if err != nil { + fmt.Println(err.Error()) + } + + fmt.Println(schedule) } diff --git a/goskola24api.go b/goskola24api.go index 2c094e5..485f2a8 100644 --- a/goskola24api.go +++ b/goskola24api.go @@ -56,3 +56,7 @@ func (api Skola24API) GetStudents(school pubtypes.School, checkAvailability bool func (api Skola24API) GetClasses(school pubtypes.School, checkAvailability bool) (_result []pubtypes.Class, _error error) { return requests.GetClasses(school, checkAvailability) } + +func (api Skola24API) GetWeekSchedule(year int, week int, school pubtypes.School, term pubtypes.SchoolTerm, class pubtypes.Class) (_result any, _error error) { + return requests.GetSchedule(year, week, 0, school, term, class) +} diff --git a/internal/requests/get_schedule.go b/internal/requests/get_schedule.go new file mode 100644 index 0000000..23016c5 --- /dev/null +++ b/internal/requests/get_schedule.go @@ -0,0 +1,89 @@ +/* +GoSkola24API +Copyright (C) 2024, Zervó Zadachin + +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License version 3 +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License version 3 for more details. + +This program incorporates external libraries for certain functionalities. +These libraries are covered by their respective licenses, and their usage +agreements are as outlined in their respective documentation or source +code. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ + +package requests + +import ( + "errors" + "fmt" + + "git.zervo.org/zervo/goskola24api/internal/types" + "git.zervo.org/zervo/goskola24api/internal/utility" + + pubtypes "git.zervo.org/zervo/goskola24api/types" +) + +func GetSchedule(year int, week int, day int, school pubtypes.School, term pubtypes.SchoolTerm, class pubtypes.Class) (_result any, _error error) { + // Verify week number + if week > 52 || week < 1 { + return nil, errors.New("week number out of range (1-53): " + fmt.Sprint(week)) + } + + // Verify year + if year > 9999 || year < 2000 { + return nil, errors.New("year number out of range (2000-9999): " + fmt.Sprint(year)) + } + + // Verify day + if day > 7 || day < 0 { + return nil, errors.New("day number out of range (0-7): " + fmt.Sprint(day)) + } + + // Get render key + renderKey, err := utility.GetRendererKey() + if err != nil { + return nil, errors.New("failed to get render key: " + err.Error()) + } + + // Construct request + request := types.RequestSchedule{ + RenderKey: renderKey, + Host: school.HostName, + UnitGuid: school.SchoolId, + StartDate: nil, + EndDate: nil, + ScheduleDay: day, + BlackAndWhite: false, + Width: 1000, + Height: 1000, + SelectionType: 0, + Selection: class.ClassId, + ShowHeader: false, + PeriodText: "", + Week: week, + Year: year, + SchoolYear: term.TermId, + PersonalTimetable: false, + PrivateFreeTextMode: nil, + PrivateSelectionMode: false, + CustomerKey: "", + } + + response, err := utility.Request(request, "render/timetable") + if err != nil { + return nil, errors.New("could not get schedule data: " + err.Error()) + } + + return response, nil +} diff --git a/internal/types/req_schedule.go b/internal/types/req_schedule.go new file mode 100644 index 0000000..ca7a9e4 --- /dev/null +++ b/internal/types/req_schedule.go @@ -0,0 +1,48 @@ +/* +GoSkola24API +Copyright (C) 2024, Zervó Zadachin + +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License version 3 +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License version 3 for more details. + +This program incorporates external libraries for certain functionalities. +These libraries are covered by their respective licenses, and their usage +agreements are as outlined in their respective documentation or source +code. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ + +package types + +type RequestSchedule struct { + RenderKey string `json:"renderKey"` + Host string `json:"host"` + UnitGuid string `json:"unitGuid"` + StartDate *string `json:"startDate"` + EndDate *string `json:"endDate"` + ScheduleDay int `json:"scheduleDay"` + BlackAndWhite bool `json:"blackAndWhite"` + Width int `json:"width"` + Height int `json:"height"` + SelectionType int `json:"selectionType"` + Selection string `json:"selection"` + ShowHeader bool `json:"showHeader"` + PeriodText any `json:"periodText"` + Week int `json:"week"` + Year int `json:"year"` + SchoolYear string `json:"schoolYear"` + PersonalTimetable bool `json:"personalTimetable"` + PrivateFreeTextMode *string `json:"privateFreeTextMode"` + PrivateSelectionMode bool `json:"privateSelectionMode"` + CustomerKey string `json:"customerKey"` +} diff --git a/internal/types/response.go b/internal/types/response.go index fc95366..c7d0bc4 100644 --- a/internal/types/response.go +++ b/internal/types/response.go @@ -25,10 +25,19 @@ along with this program. If not, see . package types type BaseResponse struct { - Error interface{} `json:"error"` - Data interface{} `json:"data"` - Exception interface{} `json:"exception"` - Validation []interface{} `json:"validation"` - SessionExpires interface{} `json:"sessionExpires"` - NeedSessionRefresh bool `json:"needSessionRefresh"` + Error interface{} `json:"error"` + Data interface{} `json:"data"` + Exception *ResponseError `json:"exception"` + Validation []interface{} `json:"validation"` + SessionExpires interface{} `json:"sessionExpires"` + NeedSessionRefresh bool `json:"needSessionRefresh"` +} + +type ResponseError struct { + Code int `json:"code"` + Context string `json:"context"` + ErrorId int `json:"errorId"` + ErrorTime string `json:"errorTime"` + Message *string `json:"message"` + Source any `json:"source"` } diff --git a/internal/utility/request.go b/internal/utility/request.go index 86ecd86..5db1335 100644 --- a/internal/utility/request.go +++ b/internal/utility/request.go @@ -71,6 +71,16 @@ func Request(data any, endpoint string) (_response interface{}, _error error) { var responseData types.BaseResponse json.Unmarshal(bodyBytes, &responseData) + // Check for reported exceptions + if responseData.Exception != nil { + return nil, errors.New("server replied with an exception") + } + + // Check for reported errors + if responseData.Error != nil { + return nil, errors.New("server replied with an error") + } + // Return as raw bytes (let consumer do type assertion) return responseData.Data, nil }