Skip to content

Commit

Permalink
Use the csunibo/unibo library for common functions and data structures
Browse files Browse the repository at this point in the history
  • Loading branch information
VaiTon committed Dec 19, 2023
1 parent 8282218 commit ffda275
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 421 deletions.
21 changes: 11 additions & 10 deletions data.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"encoding/json"
"github.com/csunibo/unibo-go/opendata"
"os"
"path"
"strconv"
Expand All @@ -11,7 +12,7 @@ import (
"github.com/rs/zerolog/log"
"github.com/samber/lo"

"github.com/VaiTon/unibocalendar/unibo"
"github.com/VaiTon/unibocalendar/unibo_integ"
)

const (
Expand All @@ -23,7 +24,7 @@ const (
func downloadOpenDataIfNewer() {

// Get package
pack, err := unibo.GetPackage(packageId)
pack, err := opendata.FetchPackage(packageId)
if err != nil {
log.Warn().Err(err).Msg("unable to get package")
return
Expand All @@ -36,8 +37,8 @@ func downloadOpenDataIfNewer() {
}

// Get wanted resource
resource := pack.Result.Resources.GetByAlias(resourceAlias)
if resource == nil {
resource, found := pack.Result.Resources.GetByAlias(resourceAlias)
if !found {
log.Warn().Msgf("unable to find resource '%s'", resourceAlias)
return
}
Expand Down Expand Up @@ -67,15 +68,15 @@ func downloadOpenDataIfNewer() {
return
}

courses, err := resource.Download()
courses, err := unibo_integ.DownloadResource(resource)
if err != nil {
log.Panic().Err(err).Msg("Unable to download courses")
}

actualYear := time.Now().Year()

// Filter courses by actual year
courses = lo.Filter(courses, func(c unibo.Course, _ int) bool {
courses = lo.Filter(courses, func(c unibo_integ.Course, _ int) bool {
return strings.Contains(c.AnnoAccademico, strconv.Itoa(actualYear))
})

Expand All @@ -87,7 +88,7 @@ func downloadOpenDataIfNewer() {
log.Info().Msg("Opendata file downloaded")
}

func saveData(courses []unibo.Course) error {
func saveData(courses []unibo_integ.Course) error {
err := createDataFolder()
if err != nil {
return err
Expand All @@ -110,15 +111,15 @@ func createDataFolder() error {
return os.MkdirAll(path.Dir(coursesPathJson), os.ModePerm)
}

func openData() (unibo.CoursesMap, error) {
func openData() (unibo_integ.CoursesMap, error) {
// Open file
file, err := os.Open(coursesPathJson)
if err != nil {
return nil, err
}

// Decode json
courses := make([]unibo.Course, 0)
courses := make([]unibo_integ.Course, 0)
err = json.NewDecoder(file).Decode(&courses)
if err != nil {
return nil, err
Expand All @@ -131,7 +132,7 @@ func openData() (unibo.CoursesMap, error) {
}

// Create the map
courseMap := make(unibo.CoursesMap, len(courses))
courseMap := make(unibo_integ.CoursesMap, len(courses))
for _, course := range courses {
courseMap[course.Codice] = course
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.20

require (
github.com/arran4/golang-ical v0.1.0
github.com/csunibo/unibo-go v0.0.3
github.com/gin-contrib/multitemplate v0.0.0-20230212012517-45920c92c271
github.com/gin-contrib/size v0.0.0-20230212012657-e14a14094dc4
github.com/gin-gonic/gin v1.9.1
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhD
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/csunibo/unibo-go v0.0.2 h1:Y2zhrFPJFGHCaU7tmUOxKFiBp3zynntIFhPwSGqzreo=
github.com/csunibo/unibo-go v0.0.2/go.mod h1:h2+xnccHa7x48RNB6d07bpHQ01ozw4oihgDOlvVrJ9U=
github.com/csunibo/unibo-go v0.0.3 h1:NZfW6/2FyY1znyQC6irfWYXjf1UdAdu7fSSWDKYKUNs=
github.com/csunibo/unibo-go v0.0.3/go.mod h1:h2+xnccHa7x48RNB6d07bpHQ01ozw4oihgDOlvVrJ9U=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down
85 changes: 43 additions & 42 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import (
"os"
"path"
"slices"
"sort"
"strconv"
"strings"
"text/template"
"time"

"github.com/csunibo/unibo-go/curriculum"
"github.com/csunibo/unibo-go/timetable"

ics "github.com/arran4/golang-ical"
"github.com/gin-contrib/multitemplate"
limits "github.com/gin-contrib/size"
Expand All @@ -23,7 +25,7 @@ import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"

"github.com/VaiTon/unibocalendar/unibo"
"github.com/VaiTon/unibocalendar/unibo_integ"
)

const templateDir = "./templates"
Expand Down Expand Up @@ -70,7 +72,7 @@ func main() {
}
}

func setupRouter(courses unibo.CoursesMap) *gin.Engine {
func setupRouter(courses unibo_integ.CoursesMap) *gin.Engine {
r := gin.Default()
r.Use(compress.Compress())
// Limit payload to 10 MB. This fixes zip bombs.
Expand All @@ -84,7 +86,9 @@ func setupRouter(courses unibo.CoursesMap) *gin.Engine {
})

coursesList := courses.ToList()
sort.Sort(coursesList)
slices.SortFunc(coursesList, func(a, b unibo_integ.Course) int {
return b.Codice - a.Codice
})
r.GET("/courses", func(c *gin.Context) {
c.HTML(http.StatusOK, "courses", gin.H{
"courses": coursesList,
Expand All @@ -97,7 +101,7 @@ func setupRouter(courses unibo.CoursesMap) *gin.Engine {
return r
}

func coursePage(courses unibo.CoursesMap) func(c *gin.Context) {
func coursePage(courses unibo_integ.CoursesMap) func(c *gin.Context) {
return func(c *gin.Context) {
courseId := c.Param("id")
if courseId == "" {
Expand All @@ -120,7 +124,7 @@ func coursePage(courses unibo.CoursesMap) func(c *gin.Context) {
curricula, err := course.GetAllCurricula()
if err != nil {
_ = c.Error(fmt.Errorf("unable to retrieve curricula: %w", err))
curricula = map[int]unibo.Curricula{}
curricula = map[int]curriculum.Curricula{}
}

c.HTML(http.StatusOK, "course", gin.H{
Expand All @@ -132,50 +136,50 @@ func coursePage(courses unibo.CoursesMap) func(c *gin.Context) {

var calcache = cache.New(time.Minute*10, time.Minute*30)

func getCoursesCal(courses *unibo.CoursesMap) func(c *gin.Context) {
return func(c *gin.Context) {
id := c.Param("id")
anno := c.Param("anno")
func getCoursesCal(courses *unibo_integ.CoursesMap) func(c *gin.Context) {
return func(ctx *gin.Context) {
id := ctx.Param("id")
anno := ctx.Param("anno")

cacheKey := fmt.Sprintf("%s-%s", id, anno)
if cal, found := calcache.Get(cacheKey); found {
successCalendar(c, cal.(*bytes.Buffer))
successCalendar(ctx, cal.(*bytes.Buffer))
return
}

// Check if id is a number, otherwise return 400
annoInt, err := strconv.Atoi(anno)
if err != nil {
c.String(http.StatusBadRequest, "Invalid year")
ctx.String(http.StatusBadRequest, "Invalid year")
return
}

// Check if id is a number, otherwise return 400
idInt, err := strconv.Atoi(id)
if err != nil {
c.String(http.StatusBadRequest, "Invalid id")
ctx.String(http.StatusBadRequest, "Invalid id")
return
}

// Check if course exists, otherwise return 404
course, found := courses.FindById(idInt)
if !found {
c.String(http.StatusNotFound, "Course not found")
ctx.String(http.StatusNotFound, "Course not found")
return
}

if annoInt <= 0 || annoInt > course.DurataAnni {
c.String(http.StatusBadRequest, "Invalid year")
ctx.String(http.StatusBadRequest, "Invalid year")
return
}

curriculumId := c.Query("curriculum")
curriculum := unibo.Curriculum{}
curriculumId := ctx.Query("curr")
curr := curriculum.Curriculum{}
if curriculumId != "" {
curriculum.Value = curriculumId
curr.Value = curriculumId
}

subjectIds := c.Query("subjects")
subjectIds := ctx.Query("subjects")
var subjects []string
if subjectIds != "" {
subjects = strings.Split(subjectIds, ",")
Expand All @@ -184,30 +188,30 @@ func getCoursesCal(courses *unibo.CoursesMap) func(c *gin.Context) {
log.Debug().Any("subjects", subjects).Msg("Subjects")

// Try to retrieve timetable, otherwise return 500
timetable, err := course.GetTimetable(annoInt, curriculum, nil)
courseTimetable, err := course.GetTimetable(annoInt, curr, nil)
if err != nil {
_ = c.Error(err)
c.String(http.StatusInternalServerError, "Unable to retrieve timetable")
_ = ctx.Error(err)
ctx.String(http.StatusInternalServerError, "Unable to retrieve timetable")
return
}

cal, err := createCal(timetable, course, annoInt, subjects)
cal, err := createCal(courseTimetable, course, annoInt, subjects)
if err != nil {
_ = c.Error(err)
c.String(http.StatusInternalServerError, "Unable to create calendar")
_ = ctx.Error(err)
ctx.String(http.StatusInternalServerError, "Unable to create calendar")
return
}

buf := bytes.NewBuffer(nil)
err = cal.SerializeTo(buf)
if err != nil {
_ = c.Error(err)
c.String(http.StatusInternalServerError, "Unable to serialize calendar")
_ = ctx.Error(err)
ctx.String(http.StatusInternalServerError, "Unable to serialize calendar")
return
}
calcache.Set(cacheKey, buf, cache.DefaultExpiration)

successCalendar(c, buf)
successCalendar(ctx, buf)
}
}

Expand All @@ -226,8 +230,8 @@ func successCalendar(c *gin.Context, cal *bytes.Buffer) {
//
// If subjectCodes is not nil, it will be used to filter the timetable by subjects.
func createCal(
timetable unibo.Timetable,
course *unibo.Course,
timetable timetable.Timetable,
course *unibo_integ.Course,
year int,
subjectCodes []string,
) (*ics.Calendar, error) {
Expand All @@ -250,27 +254,24 @@ func createCal(
eventUid := fmt.Sprintf("%x", sha.Sum(nil))

e := cal.AddEvent(eventUid)
e.SetOrganizer(event.Docente)
e.SetOrganizer(event.Teacher)
e.SetSummary(event.Title)
e.SetStartAt(event.Start.Time)
e.SetEndAt(event.End.Time)

e.SetDtStampTime(time.Now()) // https://www.kanzaki.com/docs/ical/dtstamp.html

b := strings.Builder{}
b.WriteString(fmt.Sprintf("Docente: %s\n", event.Docente))
if len(event.Aule) > 0 {
b.WriteString(fmt.Sprintf("Aula: %s\n", event.Aule[0].DesRisorsa))
b.WriteString(fmt.Sprintf("Docente: %s\n", event.Teacher))
if len(event.Classrooms) > 0 {
b.WriteString(fmt.Sprintf("Aula: %s\n", event.Classrooms[0].Description))
e.SetLocation(event.Classrooms[0].Description)
}
b.WriteString(fmt.Sprintf("Cfu: %d\n", event.Cfu))
b.WriteString(fmt.Sprintf("Periodo: %s\n", event.Periodo))
b.WriteString(fmt.Sprintf("Periodo: %s\n", event.Interval))
b.WriteString(fmt.Sprintf("Codice modulo: %s\n", event.CodModulo))

e.SetDescription(b.String())

if len(event.Aule) > 0 {
e.SetLocation(event.Aule[0].DesRisorsa)
}
}

calName := fmt.Sprintf("%s - %d year", course.Descrizione, year)
Expand All @@ -283,9 +284,9 @@ func createCal(
return cal, nil
}

func filterTimetableBySubjects(timetable unibo.Timetable, codes []string) unibo.Timetable {
filtered := make(unibo.Timetable, 0, len(timetable))
for _, event := range timetable {
func filterTimetableBySubjects(t timetable.Timetable, codes []string) timetable.Timetable {
filtered := make([]timetable.Event, 0, len(t))
for _, event := range t {
if slices.Contains(codes, event.CodModulo) {
filtered = append(filtered, event)
}
Expand Down
31 changes: 0 additions & 31 deletions unibo/curriculum.go

This file was deleted.

Loading

0 comments on commit ffda275

Please sign in to comment.