diff --git a/ctdo.go b/ctdo.go new file mode 100644 index 0000000..72bb3e5 --- /dev/null +++ b/ctdo.go @@ -0,0 +1,61 @@ +package main + +import ( + "strconv" + "strings" + "time" +) + +// jeden ersten donnerstag und dritten dienstag +func getNextTopic() topic { + date := time.Now() + + var output topic + + for i := 0; i < 31; i++ { + newDate := stringSplit(date.AddDate(0, 0, 1*i).Format(time.UnixDate), " ") + + if newDate[0] == "Thu" || newDate[0] == "Tue" { + dayA, errA := strconv.Atoi(newDate[2]) + errorPanic(errA) + + dayB, errB := strconv.Atoi(newDate[2]) + errorPanic(errB) + + if ifFloatRange(float64(dayA)/7, 0, 1, false, true) || (ifFloatRange(float64(dayB)/7, 2, 3, false, true) && newDate[0] == "Tue") { + output.date = date.AddDate(0, 0, 1*i).Format("02.01.2006") + output.days = i + break + } + } + } + + return output +} + +func getRoomState() status { + var err error + body := httpGetBody("https://status.ctdo.de/api/simple/v2") + + bodyString := string(body) + + temp := []string{} + + bodyString = strings.ReplaceAll(bodyString, "{", "") + bodyString = strings.ReplaceAll(bodyString, "}", "") + + Temp := strings.Split(bodyString, ",") + + for _, element := range Temp { + TEmp := strings.Split(element, ":") + temp = append(temp, TEmp[1]) + } + + roomState := new(status) + + roomState.state = temp[0] == "true" + roomState.power, err = strconv.ParseInt(temp[2], 0, 64) + errorPanic(err) + + return *roomState +} diff --git a/func.go b/func.go index 4745d5b..0f1f1f3 100644 --- a/func.go +++ b/func.go @@ -1,187 +1,9 @@ package main import ( - "io" - "net/http" - "strconv" "strings" - "time" ) -func logger(input string) { - println("[" + time.Now().Format("15:04:05") + "] " + input) - fileAddLine("["+time.Now().Format("15:04:05")+"] "+input, "./log/"+time.Now().Format("2006-02-01")+".log") -} - -func handler() { - logger("Pages:") - - //pages - httpHandleFunc("", "./web/pages/home.html", "text/html") - httpHandleFunc("home", "./web/pages/home.html", "text/html") - httpHandleFunc("treff", "./web/pages/treff.html", "text/html") - httpHandleFunc("events", "./web/pages/events.html", "text/html") - httpHandleFunc("about", "./web/pages/about.html", "text/html") - - //contact pages - httpHandleFunc("kontakt", "./web/pages/kontakt.html", "text/html") - httpHandleFunc("kontakt/adresse", "./web/pages/kontakt/adresse.html", "text/html") - httpHandleFunc("kontakt/irc", "./web/pages/kontakt/irc.html", "text/html") - httpHandleFunc("kontakt/mail", "./web/pages/kontakt/mail.html", "text/html") - httpHandleFunc("kontakt/tel", "./web/pages/kontakt/tel.html", "text/html") - - //pages - httpHandleFunc("verein", "./web/pages/verein.html", "text/html") - httpHandleFunc("support", "./web/pages/support.html", "text/html") - httpHandleFunc("impressum", "./web/pages/impressum.html", "text/html") - httpHandleFunc("datenschutz", "./web/pages/datenschutz.html", "text/html") - - //admin pages - keys := getAdminKeys() - - //this check is necessary! - if keys != nil { - for _, key := range keys { - httpHandleFunc("admin/"+key, "./web/pages/admin/dashboard.html", "text/html") - httpHandleFuncWithPOST("admin/"+key+"/addEvent", "./web/pages/admin/dashboard.html", "text/html") - } - } - - //styles - httpHandleFunc("style/main.css", "./web/styles/main.css", "text/css") - httpHandleFunc("style/kontakt.css", "./web/styles/kontakt.css", "text/css") - httpHandleFunc("style/home.css", "./web/styles/home.css", "text/css") - httpHandleFunc("style/events.css", "./web/styles/events.css", "text/css") - httpHandleFunc("style/dashboard.css", "./web/styles/dashboard.css", "text/css") - - //images - httpHandleFunc("image/logo_ctdo.svg", "./web/images/logo_ctdo.svg", "image/svg+xml") - httpHandleFunc("image/header.jpg", "./web/images/header.jpg", "image/jpeg") - httpHandleFunc("image/adresse_knopf.webp", "./web/images/adresse_knopf.webp", "image/webp") - httpHandleFunc("image/chat_knopf.webp", "./web/images/chat_knopf.webp", "image/webp") - httpHandleFunc("image/mail_knopf.webp", "./web/images/mail_knopf.webp", "image/webp") - httpHandleFunc("image/tel_knopf.webp", "./web/images/tel_knopf.webp", "image/webp") -} - -func getPages() [][]string { - output := [][]string{} - - output = append(output, []string{"home", "/home"}) - output = append(output, []string{"zeiten & location", "/treff"}) - output = append(output, []string{"events", "/events"}) - output = append(output, []string{"über uns", "/about"}) - output = append(output, []string{"kontakt", "/kontakt"}) - output = append(output, []string{"verein", "/verein"}) - output = append(output, []string{"unterstützung", "/support"}) - - return output -} - -func getFooterPages() [][]string { - output := [][]string{} - - output = append(output, []string{"impressum", "/impressum"}) - output = append(output, []string{"datenschutzerklärung", "/datenschutz"}) - - return output -} - -func getRoomState() status { - c := &http.Client{Timeout: 10 * time.Second} - r, err := c.Get("https://status.ctdo.de/api/simple/v2") - if err != nil { - panic(err.Error()) - } - defer r.Body.Close() - - var body []byte - body, err = io.ReadAll(r.Body) - errorPanic(err) - - bodyString := string(body) - - temp := []string{} - - bodyString = strings.ReplaceAll(bodyString, "{", "") - bodyString = strings.ReplaceAll(bodyString, "}", "") - - Temp := strings.Split(bodyString, ",") - - for _, element := range Temp { - TEmp := strings.Split(element, ":") - temp = append(temp, TEmp[1]) - } - - roomState := new(status) - - roomState.state = temp[0] == "true" - roomState.power, err = strconv.ParseInt(temp[2], 0, 64) - errorPanic(err) - - return *roomState -} - -func htmlNewBanner(text string, link string) string { - output := "" - - output += htmlElement("div", htmlLinkElement(text, link, true, ""), "class=\"newBanner\"") - - return output -} - -func htmlReplacer(input string, activePage string) string { - output := strings.ReplaceAll(input, "!NAV", htmlNav(getPages(), activePage)) - - if getRoomState().state { - output = strings.ReplaceAll(output, "!RAUMSTATUS", "
Raumstatus: offen
") - } else { - output = strings.ReplaceAll(output, "!RAUMSTATUS", "Raumstatus: geschlossen
") - } - - output = strings.ReplaceAll(output, "!FOOTERNAV", htmlNav(getFooterPages(), activePage)) - - if getNextTopic().days == 0 { - output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet Heute statt!", "")) - } else if getNextTopic().days == 1 { - output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet Morgen statt!", "class=\"topic\"")+htmlElement("p", "Am "+getNextTopic().date, "class=\"topic\"")) - } else if getNextTopic().days < 10 { - output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet in "+strconv.FormatInt(int64(getNextTopic().days), 10)+" Tagen statt!", "class=\"topic\"")+htmlElement("p", "Am "+getNextTopic().date, "class=\"topic\"")) - } else { - output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet in "+string(getNextTopic().days)+" Tagen statt!", "class=\"topic\"")+htmlElement("p", "Am "+getNextTopic().date, "class=\"topic\"")) - } - - events := getEvents() - - if len(events) == 0 { - output = strings.ReplaceAll(output, "!EVENTS", htmlElement("h4", "Keine Events in der nächsten Zeit.", "")) - output = strings.ReplaceAll(output, "!NEXTEVENTS", htmlElement("h4", "Keine Events in der nächsten Zeit.", "")) - } else { - tempA, tempB := "", "" - for i, Event := range events { - if i == 24 { - break - } - - tempA = htmlElement("h2", Event.title, "") - tempA += htmlElement("p", Event.description, "") - tempA += htmlElement("p", Event.date, "") - tempB += htmlElement("div", tempA, "class=\"event\"") - } - output = strings.ReplaceAll(output, "!EVENTS", htmlElement("div", tempB, "class=\"eventList\"")) - output = strings.ReplaceAll(output, "!NEXTEVENTS", htmlElement("div", string(tempB[0]+tempB[1]+tempB[2]+tempB[3]), "class=\"eventList\"")) - } - - output = strings.ReplaceAll(output, "!NEWBANNER", htmlNewBanner("Rundgang", "https://www.chaostreff-dortmund.de/rundgang/")) - - if strings.Contains(activePage, "/addEvent") { - output = strings.ReplaceAll(output, "!ADMINKEY", activePage) - } else { - output = strings.ReplaceAll(output, "!ADMINKEY", activePage+"/addEvent") - } - - return output -} - func ifFloatRange(variable float64, min float64, max float64, includeMin bool, includeMax bool) bool { a, b := false, false @@ -210,106 +32,11 @@ func stringSplit(input string, sep string) []string { return output } -// jeden ersten donnerstag und dritten dienstag -func getNextTopic() topic { - date := time.Now() - - var output topic - - for i := 0; i < 31; i++ { - newDate := stringSplit(date.AddDate(0, 0, 1*i).Format(time.UnixDate), " ") - - if newDate[0] == "Thu" || newDate[0] == "Tue" { - dayA, errA := strconv.Atoi(newDate[2]) - errorPanic(errA) - - dayB, errB := strconv.Atoi(newDate[2]) - errorPanic(errB) - - if ifFloatRange(float64(dayA)/7, 0, 1, false, true) || (ifFloatRange(float64(dayB)/7, 2, 3, false, true) && newDate[0] == "Tue") { - output.date = date.AddDate(0, 0, 1*i).Format("02.01.2006") - output.days = i - break - } +func stringListContains(list []string, searched string) bool { + for _, item := range list { + if item == searched { + return true } } - - return output -} - -func readDatabaseYML() database { - file := fileRead("./config/database.yml") - - rows := [][]string{} - - for _, row := range strings.Split(file, "\n") { - rows = append(rows, strings.Split(row, ": ")) - } - - output := new(database) - - for i, row := range rows { - switch i { - case 0: - output.username = row[1] - case 1: - output.password = row[1] - case 2: - output.address = row[1] - case 3: - output.port = row[1] - case 4: - output.database = row[1] - default: - logger("func.go:259 -> switch-case is out of range") - } - } - - return *output -} - -func readHttpYML() string { - file := fileRead("./config/http.yml") - - rows := [][]string{} - - for _, row := range strings.Split(file, "\n") { - rows = append(rows, strings.Split(row, ": ")) - } - - for i, row := range rows { - switch i { - case 0: - return row[1] - default: - logger("func.go:280 -> switch-case is out of range") - } - } - - return "" -} - -/* - func generateRandomString(length int) string { - chars := "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - chars += strings.ToLower(chars) - - output := "" - - for i := 0; i < length; i++ { - output += string(chars[rand.Intn(len(chars)-1)]) - } - - return output - } -*/ - -func errorPanic(err error, logBefore ...string) { - if err != nil { - for _, log := range logBefore { - logger(log) - } - logger(err.Error()) - panic("----------------ERROR----------------") - } + return false } diff --git a/html.go b/html.go index 7cc9c44..d1a897c 100644 --- a/html.go +++ b/html.go @@ -1,5 +1,10 @@ package main +import ( + "strconv" + "strings" +) + func htmlElement(tag string, innerHTML string, args string) string { return "<" + tag + " " + args + ">" + innerHTML + "" + tag + ">" } @@ -30,3 +35,64 @@ func htmlNav(pages [][]string, activePage string) string { return htmlElement("nav", htmlElement("ul", output, ""), "") } + +func htmlNewBanner(text string, link string) string { + output := "" + + output += htmlElement("div", htmlLinkElement(text, link, true, ""), "class=\"newBanner\"") + + return output +} + +func htmlReplacer(input string, activePage string) string { + output := strings.ReplaceAll(input, "!NAV", htmlNav(getPages(), activePage)) + + if getRoomState().state { + output = strings.ReplaceAll(output, "!RAUMSTATUS", "Raumstatus: offen
") + } else { + output = strings.ReplaceAll(output, "!RAUMSTATUS", "Raumstatus: geschlossen
") + } + + output = strings.ReplaceAll(output, "!FOOTERNAV", htmlNav(getFooterPages(), activePage)) + + if getNextTopic().days == 0 { + output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet Heute statt!", "")) + } else if getNextTopic().days == 1 { + output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet Morgen statt!", "class=\"topic\"")+htmlElement("p", "Am "+getNextTopic().date, "class=\"topic\"")) + } else if getNextTopic().days < 10 { + output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet in "+strconv.FormatInt(int64(getNextTopic().days), 10)+" Tagen statt!", "class=\"topic\"")+htmlElement("p", "Am "+getNextTopic().date, "class=\"topic\"")) + } else { + output = strings.ReplaceAll(output, "!TOPICTREFF", htmlElement("h3", "Nächster Topictreff findet in "+string(getNextTopic().days)+" Tagen statt!", "class=\"topic\"")+htmlElement("p", "Am "+getNextTopic().date, "class=\"topic\"")) + } + + events := getEvents() + + if len(events) == 0 { + output = strings.ReplaceAll(output, "!EVENTS", htmlElement("h4", "Keine Events in der nächsten Zeit.", "")) + output = strings.ReplaceAll(output, "!NEXTEVENTS", htmlElement("h4", "Keine Events in der nächsten Zeit.", "")) + } else { + tempA, tempB := "", "" + for i, Event := range events { + if i == 24 { + break + } + + tempA = htmlElement("h2", Event.title, "") + tempA += htmlElement("p", Event.description, "") + tempA += htmlElement("p", Event.date, "") + tempB += htmlElement("div", tempA, "class=\"event\"") + } + output = strings.ReplaceAll(output, "!EVENTS", htmlElement("div", tempB, "class=\"eventList\"")) + output = strings.ReplaceAll(output, "!NEXTEVENTS", htmlElement("div", string(tempB[0]+tempB[1]+tempB[2]+tempB[3]), "class=\"eventList\"")) + } + + output = strings.ReplaceAll(output, "!NEWBANNER", htmlNewBanner("Rundgang", "https://www.chaostreff-dortmund.de/rundgang/")) + + if strings.Contains(activePage, "/addEvent") { + output = strings.ReplaceAll(output, "!ADMINKEY", activePage) + } else { + output = strings.ReplaceAll(output, "!ADMINKEY", activePage+"/addEvent") + } + + return output +} diff --git a/http.go b/http.go index 9c14353..644f8c4 100644 --- a/http.go +++ b/http.go @@ -5,6 +5,7 @@ import ( "net/http" "os" "strings" + "time" ) func httpHandleFunc(urlPath string, filepath string, contentType string) { @@ -72,3 +73,16 @@ func httpHandleFuncWithPOST(urlPath string, filepath string, contentType string) io.WriteString(w, htmlReplacer(fileRead(filepath), urlPath)) }) } + +func httpGetBody(url string) []byte { + c := &http.Client{Timeout: 10 * time.Second} + r, err := c.Get(url) + errorPanic(err) + defer r.Body.Close() + + var body []byte + body, err = io.ReadAll(r.Body) + errorPanic(err) + + return body +} diff --git a/logger.go b/logger.go new file mode 100644 index 0000000..f1ee85f --- /dev/null +++ b/logger.go @@ -0,0 +1,18 @@ +package main + +import "time" + +func logger(input string) { + println("[" + time.Now().Format("15:04:05") + "] " + input) + fileAddLine("["+time.Now().Format("15:04:05")+"] "+input, "./log/"+time.Now().Format("2006-02-01")+".log") +} + +func errorPanic(err error, logBefore ...string) { + if err != nil { + for _, log := range logBefore { + logger(log) + } + logger(err.Error()) + panic("----------------ERROR----------------") + } +} diff --git a/main.go b/main.go index 4044612..438625f 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,9 @@ package main import ( + "io/ioutil" "net/http" + "strings" ) /* @@ -24,3 +26,143 @@ func main() { defer logger("----------------END----------------") } + +func handler() { + logger("Pages:") + + //pages + httpHandleFunc("", "./web/pages/home.html", "text/html") + handleFilesInFolder("", "./web/pages/", true) + /* + httpHandleFunc("home", "./web/pages/home.html", "text/html") + httpHandleFunc("treff", "./web/pages/treff.html", "text/html") + httpHandleFunc("events", "./web/pages/events.html", "text/html") + httpHandleFunc("about", "./web/pages/about.html", "text/html") + + //contact pages + httpHandleFunc("kontakt", "./web/pages/kontakt.html", "text/html") + httpHandleFunc("kontakt/adresse", "./web/pages/kontakt/adresse.html", "text/html") + httpHandleFunc("kontakt/irc", "./web/pages/kontakt/irc.html", "text/html") + httpHandleFunc("kontakt/mail", "./web/pages/kontakt/mail.html", "text/html") + httpHandleFunc("kontakt/tel", "./web/pages/kontakt/tel.html", "text/html") + + //pages + httpHandleFunc("verein", "./web/pages/verein.html", "text/html") + httpHandleFunc("support", "./web/pages/support.html", "text/html") + httpHandleFunc("impressum", "./web/pages/impressum.html", "text/html") + httpHandleFunc("datenschutz", "./web/pages/datenschutz.html", "text/html") + */ + + //admin pages + keys := getAdminKeys() + + if len(keys) > 0 { + for _, key := range keys { + httpHandleFunc("admin/"+key, "./web/pages/admin/dashboard.html", "text/html") + httpHandleFuncWithPOST("admin/"+key+"/addEvent", "./web/pages/admin/dashboard.html", "text/html") + } + } + + //styles + handleFilesInFolder("style/", "./web/styles/", false) + /* + httpHandleFunc("style/main.css", "./web/styles/main.css", "text/css") + httpHandleFunc("style/kontakt.css", "./web/styles/kontakt.css", "text/css") + httpHandleFunc("style/home.css", "./web/styles/home.css", "text/css") + httpHandleFunc("style/events.css", "./web/styles/events.css", "text/css") + httpHandleFunc("style/dashboard.css", "./web/styles/dashboard.css", "text/css") + */ + + //images + handleFilesInFolder("image/", "./web/images/", false) + /* + httpHandleFunc("image/logo_ctdo.svg", "./web/images/logo_ctdo.svg", "image/svg+xml") + httpHandleFunc("image/header.jpg", "./web/images/header.jpg", "image/jpeg") + httpHandleFunc("image/adresse_knopf.webp", "./web/images/adresse_knopf.webp", "image/webp") + httpHandleFunc("image/chat_knopf.webp", "./web/images/chat_knopf.webp", "image/webp") + httpHandleFunc("image/mail_knopf.webp", "./web/images/mail_knopf.webp", "image/webp") + httpHandleFunc("image/tel_knopf.webp", "./web/images/tel_knopf.webp", "image/webp") + */ +} + +var alreadyHandledFiles []string = []string{} + +func handleFilesInFolder(urlPrefix string, folderpath string, handleWithoutFileSuffix bool) { + if folderpath[len(folderpath)-1] != '/' { + folderpath += "/" + } + files, err := ioutil.ReadDir(folderpath) + errorPanic(err) + + for _, file := range files { + alreadyHandled := stringListContains(alreadyHandledFiles, folderpath+file.Name()) + + if !file.IsDir() { + if !alreadyHandled { + f := strings.Split(file.Name(), ".") + ContentType := f[len(f)-1] + filename := "" + + if handleWithoutFileSuffix { + for index, item := range f { + if index < len(f)-1 { + filename += item + } + } + } else { + filename = file.Name() + } + + switch ContentType { + case "png": + httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/png") + case "webp": + httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/webp") + case "svg": + httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/svg+xml") + case "jpeg": + httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/jpeg") + case "jpg": + httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/jpeg") + case "gif": + httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "image/gif") + case "css": + httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "text/css") + case "html": + httpHandleFunc(urlPrefix+filename, folderpath+file.Name(), "text/html") + default: + logger("handleFilesInFolder -> content-type unknown : " + folderpath + file.Name()) + } + alreadyHandledFiles = append(alreadyHandledFiles, folderpath+file.Name()) + } else { + logger("handleFilesInFolder -> already handled : " + folderpath + file.Name()) + } + } else { + childFolder := file.Name() + handleFilesInFolder(childFolder, folderpath+childFolder, handleWithoutFileSuffix) + } + } +} + +func getPages() [][]string { + output := [][]string{} + + output = append(output, []string{"home", "/home"}) + output = append(output, []string{"zeiten & location", "/treff"}) + output = append(output, []string{"events", "/events"}) + output = append(output, []string{"über uns", "/about"}) + output = append(output, []string{"kontakt", "/kontakt"}) + output = append(output, []string{"verein", "/verein"}) + output = append(output, []string{"unterstützung", "/support"}) + + return output +} + +func getFooterPages() [][]string { + output := [][]string{} + + output = append(output, []string{"impressum", "/impressum"}) + output = append(output, []string{"datenschutzerklärung", "/datenschutz"}) + + return output +} diff --git a/yml.go b/yml.go new file mode 100644 index 0000000..fd61fc3 --- /dev/null +++ b/yml.go @@ -0,0 +1,55 @@ +package main + +import "strings" + +func readDatabaseYML() database { + file := fileRead("./config/database.yml") + + rows := [][]string{} + + for _, row := range strings.Split(file, "\n") { + rows = append(rows, strings.Split(row, ": ")) + } + + output := new(database) + + for i, row := range rows { + switch i { + case 0: + output.username = row[1] + case 1: + output.password = row[1] + case 2: + output.address = row[1] + case 3: + output.port = row[1] + case 4: + output.database = row[1] + default: + logger("func.go:259 -> switch-case is out of range") + } + } + + return *output +} + +func readHttpYML() string { + file := fileRead("./config/http.yml") + + rows := [][]string{} + + for _, row := range strings.Split(file, "\n") { + rows = append(rows, strings.Split(row, ": ")) + } + + for i, row := range rows { + switch i { + case 0: + return row[1] + default: + logger("func.go:280 -> switch-case is out of range") + } + } + + return "" +}