From 3ccbe8ec748a62de4289ecd8f02dfa63e0b14d18 Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 25 Mar 2025 19:59:17 +0100 Subject: [PATCH 1/7] =?UTF-8?q?Updates=20f=C3=BCr=20SoSe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dummydata/rooms.sql | 2 +- dummydata/summerCourses.sql | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/dummydata/rooms.sql b/dummydata/rooms.sql index 1a06c1a..7416dc3 100644 --- a/dummydata/rooms.sql +++ b/dummydata/rooms.sql @@ -3,5 +3,5 @@ INSERT INTO `room` (name, max_occupy) VALUES ('S2|15-336', 2), ('S2|15-345', 2), ('S2|15-415', 1), -('S2|15-444', 1), +('S2|15-444', 0), ('Sonstige', 1024); diff --git a/dummydata/summerCourses.sql b/dummydata/summerCourses.sql index ca13de7..fb322ce 100644 --- a/dummydata/summerCourses.sql +++ b/dummydata/summerCourses.sql @@ -1,8 +1,14 @@ INSERT INTO `course` (name) VALUES +('Algebraic Geometry'), ('Algorithmic Discrete Mathematics'), ('Analysis II'), ('Analysis II (engl.)'), ('Aussagen- und Prädikatenlogik'), +('Automorphic Forms'), +('Basic Applied Proof Theory'), +('Computational Complexity'), +('Data Assimilation for Fluid Dynamics'), +('Deep Learning Lab'), ('Discrete Optimization'), ('Einführung in die Algebra'), ('Einführung in die Finanzmathematik'), @@ -17,7 +23,9 @@ INSERT INTO `course` (name) VALUES ('LA für Physik und Lehramt'), ('Linear Algebra II (engl.)'), ('Lineare Algebra II'), +('Logics of Knowledge and Information'), ('Logik und Grundlagen'), +('Machine Learning for Fluid Dynamics'), ('Mathe für Chemiker'), ('Mathe II für Informatik'), ('Mathe II für Bauwesen'), @@ -27,11 +35,20 @@ INSERT INTO `course` (name) VALUES ('Mathe IV (ET) / Mathe III (Inf) / Praktische Mathe (MEd)'), ('Mathe für MINT'), ('Mathe & Statistik für Biologen'), +('Mathematical Modelling of Fluid Interfaces'), +('Mathematical Statistics'), ('Mathematik im Kontext'), ('Model Theory'), +('Nonsmooth Optimization'), ('Nichtlineare Optimierung'), +('Numerics of Fluid Dynamics (incompressible)'), +('Numerics of Hyperbolic Equations'), ('Numerische Lineare Algebra'), +('PDE II'), ('Riemannsche Flächen'), +('Seitenkanalangriffe gegen IT-Systeme'), ('Sobolev Spaces'), +('Spin Systems and Statistical Mechanics'), ('Topologie'), +('Variations of geometric energies'), ('Vertrauenspersonen'); From d3cb4bc375ab3e0d8ebec332068cb300d8c0ab87 Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 25 Mar 2025 21:18:13 +0100 Subject: [PATCH 2/7] Change to more powerful mail library that especially adds a correct `Date` heeader for us. --- go.mod | 7 ++- go.sum | 68 +++++++++++++++++++++++++++ repositories/request.go | 40 ++++++++++++---- templating/templates/confirmationMail | 5 -- 4 files changed, 106 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index bef8ddc..dfba090 100644 --- a/go.mod +++ b/go.mod @@ -6,4 +6,9 @@ require github.com/mattn/go-sqlite3 v1.14.24 require github.com/go-sql-driver/mysql v1.8.1 -require filippo.io/edwards25519 v1.1.0 // indirect +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/wneessen/go-mail v0.6.2 // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/text v0.22.0 // indirect +) diff --git a/go.sum b/go.sum index 201a2b0..a11fb32 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,75 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/wneessen/go-mail v0.6.2 h1:c6V7c8D2mz868z9WJ+8zDKtUyLfZ1++uAZmo2GRFji8= +github.com/wneessen/go-mail v0.6.2/go.mod h1:L/PYjPK3/2ZlNb2/FjEBIn9n1rUWjW+Toy531oVmeb4= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/repositories/request.go b/repositories/request.go index 47e418d..315388f 100644 --- a/repositories/request.go +++ b/repositories/request.go @@ -10,7 +10,7 @@ import ( "html/template" "log" "math/big" - "net/smtp" + "github.com/wneessen/go-mail" "officeHours/config" "officeHours/models" "officeHours/templating" @@ -132,13 +132,13 @@ func (r *RequestRepo) newSecret() (string, error) { } func (r *RequestRepo) sendConfirmationMail(request models.Request) error { - var message bytes.Buffer + var messageText bytes.Buffer var data = struct { Config config.Config Request models.Request MessageId template.HTML }{r.config, request, template.HTML("<" + randomString(15) + "@" + r.config.Server.Domain + ">")} - err := templating.WriteTemplate(&message, "confirmationMail", data) + err := templating.WriteTemplate(&messageText, "confirmationMail", data) if err != nil { err = fmt.Errorf("error parsing confirmation Mail: %w", err) log.Println(err.Error()) @@ -147,10 +147,35 @@ func (r *RequestRepo) sendConfirmationMail(request models.Request) error { switch r.config.Mailer.Type { case "Stdout": - fmt.Println(message.String()) + fmt.Println(messageText.String()) case "Smtp": - to := []string{request.OfficeHour.Tutor.Email} - var auth smtp.Auth + message := mail.NewMsg() + if err := message.From(r.config.Mailer.FromAddress); err != nil { + log.Println(err.Error()) + return err + } + if err := message.To(request.OfficeHour.Tutor.Email); err != nil { + log.Println(err.Error()) + return err; + } + switch request.Action { + case models.RequestActivate: + message.Subject("Sprechstunde anlegen") + case models.RequestDelete: + message.Subject("Sprechstunde löschen") + } + message.SetBodyString(mail.TypeTextPlain, messageText.String()) + client, err := mail.NewClient(r.config.Mailer.SmtpHost, mail.WithPort(r.config.Mailer.SmtpPort))/*, mail.WithSMTPAuth(mail.SMTPAuthPlain), + mail.WithUsername(r.config.Mailer.SmtpIdentity), mail.WithPassword(r.config.Mailer.SmtpPassword))*/ + if err != nil { + log.Println(err.Error()) + return err; + } + if err := client.DialAndSend(message); err != nil { + log.Println(err.Error()) + return err; + } +/* var auth smtp.Auth if r.config.Mailer.SmtpUseAuth { auth = smtp.PlainAuth(r.config.Mailer.SmtpIdentity, r.config.Mailer.FromAddress, r.config.Mailer.SmtpPassword, r.config.Mailer.SmtpHost) } @@ -158,8 +183,7 @@ func (r *RequestRepo) sendConfirmationMail(request models.Request) error { if err != nil { err = fmt.Errorf("error sending mail by smtp: %w", err) log.Println(err.Error()) - } - return err + }*/ } return nil } diff --git a/templating/templates/confirmationMail b/templating/templates/confirmationMail index f996ee7..30205e1 100644 --- a/templating/templates/confirmationMail +++ b/templating/templates/confirmationMail @@ -1,8 +1,3 @@ -From: {{.Config.Mailer.FromName}} -To: {{.Request.OfficeHour.Tutor.Email}} -Subject: Sprechstunde {{if eq .Request.Action 0}}anlegen{{end}}{{if eq .Request.Action 1}}löschen{{end}} -Message-ID: {{.MessageId}} - Hallo {{.Request.OfficeHour.Tutor.Name}}, mit deiner Emailadresse soll eine Sprechstunde mit folgenden Daten {{if eq .Request.Action 0}}angelegt werden{{end}}{{if eq .Request.Action 1}}gelöscht werden{{end}}: From 22a079e10fb95be79cf17a57724286113919eb6f Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 25 Mar 2025 19:59:17 +0100 Subject: [PATCH 3/7] =?UTF-8?q?Updates=20f=C3=BCr=20SoSe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dummydata/rooms.sql | 2 +- dummydata/summerCourses.sql | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/dummydata/rooms.sql b/dummydata/rooms.sql index 1a06c1a..7416dc3 100644 --- a/dummydata/rooms.sql +++ b/dummydata/rooms.sql @@ -3,5 +3,5 @@ INSERT INTO `room` (name, max_occupy) VALUES ('S2|15-336', 2), ('S2|15-345', 2), ('S2|15-415', 1), -('S2|15-444', 1), +('S2|15-444', 0), ('Sonstige', 1024); diff --git a/dummydata/summerCourses.sql b/dummydata/summerCourses.sql index ca13de7..fb322ce 100644 --- a/dummydata/summerCourses.sql +++ b/dummydata/summerCourses.sql @@ -1,8 +1,14 @@ INSERT INTO `course` (name) VALUES +('Algebraic Geometry'), ('Algorithmic Discrete Mathematics'), ('Analysis II'), ('Analysis II (engl.)'), ('Aussagen- und Prädikatenlogik'), +('Automorphic Forms'), +('Basic Applied Proof Theory'), +('Computational Complexity'), +('Data Assimilation for Fluid Dynamics'), +('Deep Learning Lab'), ('Discrete Optimization'), ('Einführung in die Algebra'), ('Einführung in die Finanzmathematik'), @@ -17,7 +23,9 @@ INSERT INTO `course` (name) VALUES ('LA für Physik und Lehramt'), ('Linear Algebra II (engl.)'), ('Lineare Algebra II'), +('Logics of Knowledge and Information'), ('Logik und Grundlagen'), +('Machine Learning for Fluid Dynamics'), ('Mathe für Chemiker'), ('Mathe II für Informatik'), ('Mathe II für Bauwesen'), @@ -27,11 +35,20 @@ INSERT INTO `course` (name) VALUES ('Mathe IV (ET) / Mathe III (Inf) / Praktische Mathe (MEd)'), ('Mathe für MINT'), ('Mathe & Statistik für Biologen'), +('Mathematical Modelling of Fluid Interfaces'), +('Mathematical Statistics'), ('Mathematik im Kontext'), ('Model Theory'), +('Nonsmooth Optimization'), ('Nichtlineare Optimierung'), +('Numerics of Fluid Dynamics (incompressible)'), +('Numerics of Hyperbolic Equations'), ('Numerische Lineare Algebra'), +('PDE II'), ('Riemannsche Flächen'), +('Seitenkanalangriffe gegen IT-Systeme'), ('Sobolev Spaces'), +('Spin Systems and Statistical Mechanics'), ('Topologie'), +('Variations of geometric energies'), ('Vertrauenspersonen'); From a05407eba01a80e8a2ec294a110232eb61223ce2 Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 25 Mar 2025 21:18:13 +0100 Subject: [PATCH 4/7] Change to more powerful mail library that especially adds a correct `Date` heeader for us. --- go.mod | 7 ++- go.sum | 68 +++++++++++++++++++++++++++ repositories/request.go | 55 +++++++++++++++------- templating/templates/confirmationMail | 5 -- 4 files changed, 111 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index bef8ddc..dfba090 100644 --- a/go.mod +++ b/go.mod @@ -6,4 +6,9 @@ require github.com/mattn/go-sqlite3 v1.14.24 require github.com/go-sql-driver/mysql v1.8.1 -require filippo.io/edwards25519 v1.1.0 // indirect +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/wneessen/go-mail v0.6.2 // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/text v0.22.0 // indirect +) diff --git a/go.sum b/go.sum index 201a2b0..a11fb32 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,75 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/wneessen/go-mail v0.6.2 h1:c6V7c8D2mz868z9WJ+8zDKtUyLfZ1++uAZmo2GRFji8= +github.com/wneessen/go-mail v0.6.2/go.mod h1:L/PYjPK3/2ZlNb2/FjEBIn9n1rUWjW+Toy531oVmeb4= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/repositories/request.go b/repositories/request.go index 47e418d..0d88dda 100644 --- a/repositories/request.go +++ b/repositories/request.go @@ -7,10 +7,9 @@ import ( "database/sql" "errors" "fmt" - "html/template" + "github.com/wneessen/go-mail" "log" "math/big" - "net/smtp" "officeHours/config" "officeHours/models" "officeHours/templating" @@ -132,13 +131,12 @@ func (r *RequestRepo) newSecret() (string, error) { } func (r *RequestRepo) sendConfirmationMail(request models.Request) error { - var message bytes.Buffer + var messageText bytes.Buffer var data = struct { - Config config.Config - Request models.Request - MessageId template.HTML - }{r.config, request, template.HTML("<" + randomString(15) + "@" + r.config.Server.Domain + ">")} - err := templating.WriteTemplate(&message, "confirmationMail", data) + Config config.Config + Request models.Request + }{r.config, request} + err := templating.WriteTemplate(&messageText, "confirmationMail", data) if err != nil { err = fmt.Errorf("error parsing confirmation Mail: %w", err) log.Println(err.Error()) @@ -147,19 +145,40 @@ func (r *RequestRepo) sendConfirmationMail(request models.Request) error { switch r.config.Mailer.Type { case "Stdout": - fmt.Println(message.String()) + fmt.Println(messageText.String()) case "Smtp": - to := []string{request.OfficeHour.Tutor.Email} - var auth smtp.Auth - if r.config.Mailer.SmtpUseAuth { - auth = smtp.PlainAuth(r.config.Mailer.SmtpIdentity, r.config.Mailer.FromAddress, r.config.Mailer.SmtpPassword, r.config.Mailer.SmtpHost) - } - err = smtp.SendMail(fmt.Sprintf("%s:%d", r.config.Mailer.SmtpHost, r.config.Mailer.SmtpPort), auth, string(r.config.Mailer.FromName), to, message.Bytes()) - if err != nil { - err = fmt.Errorf("error sending mail by smtp: %w", err) + message := mail.NewMsg() + if err := message.From(r.config.Mailer.FromAddress); err != nil { log.Println(err.Error()) + return err + } + if err := message.To(request.OfficeHour.Tutor.Email); err != nil { + log.Println(err.Error()) + return err + } + switch request.Action { + case models.RequestActivate: + message.Subject("Sprechstunde anlegen") + case models.RequestDelete: + message.Subject("Sprechstunde löschen") + } + message.SetBodyString(mail.TypeTextPlain, messageText.String()) + + var options []mail.Option + if r.config.Mailer.SmtpUseAuth { + options = append(options, mail.WithSMTPAuth(mail.SMTPAuthPlain)) + options = append(options, mail.WithUsername(r.config.Mailer.SmtpIdentity)) + options = append(options, mail.WithPassword(r.config.Mailer.SmtpPassword)) + } + client, err := mail.NewClient(r.config.Mailer.SmtpHost, mail.WithPort(r.config.Mailer.SmtpPort)) + if err != nil { + log.Println(err.Error()) + return err + } + if err := client.DialAndSend(message); err != nil { + log.Println(err.Error()) + return err } - return err } return nil } diff --git a/templating/templates/confirmationMail b/templating/templates/confirmationMail index f996ee7..30205e1 100644 --- a/templating/templates/confirmationMail +++ b/templating/templates/confirmationMail @@ -1,8 +1,3 @@ -From: {{.Config.Mailer.FromName}} -To: {{.Request.OfficeHour.Tutor.Email}} -Subject: Sprechstunde {{if eq .Request.Action 0}}anlegen{{end}}{{if eq .Request.Action 1}}löschen{{end}} -Message-ID: {{.MessageId}} - Hallo {{.Request.OfficeHour.Tutor.Name}}, mit deiner Emailadresse soll eine Sprechstunde mit folgenden Daten {{if eq .Request.Action 0}}angelegt werden{{end}}{{if eq .Request.Action 1}}gelöscht werden{{end}}: From 6ef93951406eaf982c9baa2fe52ff8381411bdf1 Mon Sep 17 00:00:00 2001 From: Gonne Date: Wed, 26 Mar 2025 13:32:51 +0100 Subject: [PATCH 5/7] Apply all options to smtp session --- repositories/request.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/repositories/request.go b/repositories/request.go index 0d88dda..011f015 100644 --- a/repositories/request.go +++ b/repositories/request.go @@ -165,12 +165,13 @@ func (r *RequestRepo) sendConfirmationMail(request models.Request) error { message.SetBodyString(mail.TypeTextPlain, messageText.String()) var options []mail.Option + options = append(options, mail.WithPort(r.config.Mailer.SmtpPort)) if r.config.Mailer.SmtpUseAuth { options = append(options, mail.WithSMTPAuth(mail.SMTPAuthPlain)) options = append(options, mail.WithUsername(r.config.Mailer.SmtpIdentity)) options = append(options, mail.WithPassword(r.config.Mailer.SmtpPassword)) } - client, err := mail.NewClient(r.config.Mailer.SmtpHost, mail.WithPort(r.config.Mailer.SmtpPort)) + client, err := mail.NewClient(r.config.Mailer.SmtpHost, options...) if err != nil { log.Println(err.Error()) return err From 5e954ca751c08394713282e558fe041ae8ac96c3 Mon Sep 17 00:00:00 2001 From: Gonne Date: Wed, 26 Mar 2025 13:33:18 +0100 Subject: [PATCH 6/7] Remove deliverability hint There are no forwards anymore and we have deployed DKIM which should help. --- templating/templates/addSuccess.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/templating/templates/addSuccess.html b/templating/templates/addSuccess.html index 849a20f..ef4c343 100644 --- a/templating/templates/addSuccess.html +++ b/templating/templates/addSuccess.html @@ -6,9 +6,5 @@ Du solltest eine Mail mit einem Aktivierungslink erhalten haben. Klicke auf diesen, um die Sprechstunde öffentlich anzuzeigen. -
- Wir haben vermehrt erfahren, dass Mails, die an GMX oder Web.de weitergeleitet werden, nicht zugestellt werden. - Falls du davon betroffen bist, melde dich bei sprechstundentool@mathebau.de. -
{{end}} From b1eba08dd99ec5ce4897e07bcfad2de9e60df853 Mon Sep 17 00:00:00 2001 From: Gonne Date: Wed, 2 Apr 2025 14:50:42 +0200 Subject: [PATCH 7/7] =?UTF-8?q?=C3=84ndere=20Wochenfeld=20zu=20mehr=20Ausw?= =?UTF-8?q?ahl.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #28 --- controllers/addOfficeHourHandler.go | 4 ++-- models/date.go | 2 +- repositories/officeHour.go | 4 +--- templating/templates/addMask.html | 9 ++++++--- templating/templates/confirmationMail | 1 + templating/templates/deleteMailForm.html | 2 +- templating/templates/td.html | 2 +- 7 files changed, 13 insertions(+), 11 deletions(-) diff --git a/controllers/addOfficeHourHandler.go b/controllers/addOfficeHourHandler.go index 20c3b8d..4e498e1 100644 --- a/controllers/addOfficeHourHandler.go +++ b/controllers/addOfficeHourHandler.go @@ -73,8 +73,8 @@ func (b *BaseHandler) AddOfficeHourHandler(w http.ResponseWriter, req *http.Requ if err != nil { errors = append(errors, "Die Vorlesungswoche muss eine ganze Zahl sein.") } - if !(week >= 0 && week <= 2) { - errors = append(errors, "Sprechstunden müssen jede, jede gerade oder jede ungerade Vorlesungswoche stattfinden.") + if !(week >= 0 && week <= 5) { + errors = append(errors, "Bitte wähle eine der vorgegebenen Optionen für Vorlesungswochen.") } day, err := strconv.Atoi(req.FormValue("tag")) if err != nil { diff --git a/models/date.go b/models/date.go index 61ce6a3..bea4dc4 100644 --- a/models/date.go +++ b/models/date.go @@ -5,7 +5,7 @@ import ( ) type Date struct { - Week int // Set whether the date is all weeks (0), odd weeks (1) or even weeks (2). + Week int // Set whether the date is all weeks (0), weeks with exercise session (1) or weeks without exercise session (2), even weeks (3), odd weeks (4) or other (5). Day int Hour int Minute int diff --git a/repositories/officeHour.go b/repositories/officeHour.go index 27ccd86..4a0243a 100644 --- a/repositories/officeHour.go +++ b/repositories/officeHour.go @@ -245,9 +245,7 @@ func (r *OfficeHourRepo) NumberByTimeSpanAndRoom(date models.Date, duration int, for _, officeHour := range officeHours { // increase count if officehour starts before this point in time and ends later if models.DateLess(officeHour.Date, models.GetEndDate(date, minute, false)) && models.DateLess(models.GetEndDate(date, minute, false), models.GetEndDate(officeHour.Date, officeHour.Duration, false)) { - if date.Week == 0 || officeHour.Week == 0 || date.Week == officeHour.Week { // office hours in alternating weeks should not collide - minuteCount += 1 - } + minuteCount += 1 } } if minuteCount > count { diff --git a/templating/templates/addMask.html b/templating/templates/addMask.html index 98152d7..634a4f4 100644 --- a/templating/templates/addMask.html +++ b/templating/templates/addMask.html @@ -59,9 +59,12 @@
diff --git a/templating/templates/confirmationMail b/templating/templates/confirmationMail index 30205e1..1d61fdb 100644 --- a/templating/templates/confirmationMail +++ b/templating/templates/confirmationMail @@ -5,6 +5,7 @@ mit deiner Emailadresse soll eine Sprechstunde mit folgenden Daten {{if eq .Requ {{.Request.OfficeHour.Course.Name}} {{DayName .Request.OfficeHour.Date.Day}} {{printf "%02d" .Request.OfficeHour.Date.Hour}}:{{printf "%02d" .Request.OfficeHour.Date.Minute}} Uhr bis {{printf "%02d" .Request.OfficeHour.EndDate.Hour}}:{{printf "%02d" .Request.OfficeHour.EndDate.Minute}} Uhr +{{if eq 0 .Request.OfficeHour.Date.Week}}Jede Woche{{end}}{{if eq 1 .Request.OfficeHour.Date.Week}}In Wochen mit Übung{{end}}{{if eq 2 .Request.OfficeHour.Date.Week}}In Wochen ohne Übung{{end}}{{if eq 3 .Request.OfficeHour.Date.Week}}In geraden Vorlesungswochen{{end}}{{if eq 4 .Request.OfficeHour.Date.Week}}In ungeraden Vorlesungswochen{{end}} {{.Request.OfficeHour.Tutor.Name}} {{.Request.OfficeHour.Room.Name}} diff --git a/templating/templates/deleteMailForm.html b/templating/templates/deleteMailForm.html index 378e6e7..11a8119 100644 --- a/templating/templates/deleteMailForm.html +++ b/templating/templates/deleteMailForm.html @@ -11,7 +11,7 @@

Willst du die Sprechstunde
{{printf "%02d" .OfficeHour.Date.Hour}}:{{printf "%02d" .OfficeHour.Date.Minute}} - {{printf "%02d" .OfficeHour.EndDate.Hour}}:{{printf "%02d" .OfficeHour.EndDate.Minute}}
- {{if eq .OfficeHour.Date.Week 1}}in ungeraden Vorlesungswochen
{{end}}{{if eq .OfficeHour.Date.Week 2}}in geraden Vorlesungswochen
{{end}} + {{if eq 0 $.Date.Week}}>Jede Woche
{{end}}{{if eq 1 $.Date.Week}}In Wochen mit Übung
{{end}}{{if eq 2 $.Date.Week}}In Wochen ohne Übung
{{end}}{{if eq 3 $.Date.Week}}In geraden Vorlesungswochen
{{end}}{{if eq 4 $.Date.Week}}In ungeraden Vorlesungswochen
{{end}} {{.OfficeHour.Course.Name}}
{{.OfficeHour.Tutor.Name}}
{{.OfficeHour.Room.Name}}
diff --git a/templating/templates/td.html b/templating/templates/td.html index cb1f041..76fc5e1 100644 --- a/templating/templates/td.html +++ b/templating/templates/td.html @@ -1,7 +1,7 @@ {{if .DeleteIcons}}

{{end}} {{printf "%02d" .OfficeHour.Date.Hour}}:{{printf "%02d" .OfficeHour.Date.Minute}} - {{printf "%02d" .OfficeHour.EndDate.Hour}}:{{printf "%02d" .OfficeHour.EndDate.Minute}}
- {{if eq .OfficeHour.Date.Week 1}}in ungeraden Vorlesungswochen
{{end}}{{if eq .OfficeHour.Date.Week 2}}in geraden Vorlesungswochen
{{end}} + {{if eq 1 .OfficeHour.Date.Week}}In Wochen mit Übung
{{end}}{{if eq 2 .OfficeHour.Date.Week}}In Wochen ohne Übung
{{end}}{{if eq 3 .OfficeHour.Date.Week}}In geraden Vorlesungswochen
{{end}}{{if eq 4 .OfficeHour.Date.Week}}In ungeraden Vorlesungswochen
{{end}} {{.OfficeHour.Course.Name}}
{{.OfficeHour.Tutor.Name}}
{{.OfficeHour.Room.Name}}