From 4aa1d57094d37c581810ec3159f411e538b8da18 Mon Sep 17 00:00:00 2001 From: Simon Rieger Date: Thu, 24 Oct 2024 12:33:37 +0200 Subject: [PATCH] first commit --- README.md | 88 ++++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 38 ++++++++++++++++++++ go/Dockerfile | 28 +++++++++++++++ go/Dockerfile.old | 22 ++++++++++++ go/go.mod | 13 +++++++ go/go.sum | 28 +++++++++++++++ go/main.go | 66 ++++++++++++++++++++++++++++++++++ 7 files changed, 283 insertions(+) create mode 100644 README.md create mode 100755 docker-compose.yml create mode 100755 go/Dockerfile create mode 100755 go/Dockerfile.old create mode 100644 go/go.mod create mode 100644 go/go.sum create mode 100644 go/main.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..c17a241 --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# ICS to RSS Converter + +Dieses Projekt ist eine Go-Anwendung, die ICS-Kalenderdateien in RSS-Feeds konvertiert. Die Anwendung wird in einem Docker-Container ausgeführt und kann mit Docker Compose einfach bereitgestellt werden. + +## Voraussetzungen + +- [Docker](https://www.docker.com/get-started) +- [Docker Compose](https://docs.docker.com/compose/install/) + +## Installation + +1. **Repository klonen:** + + ```bash + git clone https://github.com/dein-benutzername/ics-to-rss.git + cd ics-to-rss + ``` + +2. **Docker Compose starten:** + + Stelle sicher, dass Docker und Docker Compose installiert sind und führe dann den folgenden Befehl aus: + + ```bash + docker-compose up -d --build + ``` + + Dieser Befehl baut das Docker-Image und startet den Container. + +## Verwendung + +Die Anwendung läuft auf `http://localhost:8080`. Um eine ICS-Datei in einen RSS-Feed zu konvertieren, verwende die folgende URL-Struktur: + +``` +http://localhost:8080/rss?ics= +``` + +Ersetze `` durch die URL deiner ICS-Datei. + +## Docker Compose Datei + +Hier ist der Inhalt der `docker-compose.yml` Datei: + +```yaml +version: '3.8' + +services: + ics-to-rss: + build: . + ports: + - "8080:8080" +``` + +## Dockerfile + +Stelle sicher, dass du auch eine `Dockerfile` im selben Verzeichnis hast: + +```dockerfile +# Verwende ein offizielles Golang-Image als Build-Umgebung +FROM golang:1.20 as builder + +WORKDIR /app + +# Kopiere den Go-Modul-Dateien und installiere Abhängigkeiten +COPY go.mod go.sum ./ +RUN go mod download + +# Kopiere den Rest des Codes +COPY . . + +# Baue die Anwendung +RUN CGO_ENABLED=0 GOOS=linux go build -o main . + +# Verwende ein schlankes Image für die Produktion +FROM alpine:3.18 + +WORKDIR /root/ + +# Kopiere das gebaute Go-Binary aus der vorherigen Stufe +COPY --from=builder /app/main . + +# Exponiere Port 8080 und starte die Anwendung +EXPOSE 8080 +CMD ["./main"] +``` + +## Lizenz + +Dieses Projekt steht unter der MIT-Lizenz. Weitere Informationen findest du in der `LICENSE` Datei. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100755 index 0000000..487e3e5 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,38 @@ +version: "3.9" + +services: + +# Go application service + go-app: + build: + context: go/. + args: + - GO111MODULE=on + #ports: + # - "8080:8080" + environment: + - VIRTUAL_HOST=ics.brothertec.eu + - VIRTUAL_PORT=8080 + - LETSENCRYPT_HOST=ics.brothertec.eu + - LETSENCRYPT_EMAIL=admin@brothertec.eu + + restart: always + + labels: + - flame.type=application + - flame.name=ICS to RSS + - flame.url=https://ics.brothertec.eu + - flame.icon=image + + networks: + default: + proxy: + edge-tier: + +networks: + proxy: + name: nginx-proxy + external: true + edge-tier: + name: edge + external: true diff --git a/go/Dockerfile b/go/Dockerfile new file mode 100755 index 0000000..265512e --- /dev/null +++ b/go/Dockerfile @@ -0,0 +1,28 @@ +# syntax=docker/dockerfile:1 + +# Build the application from source +FROM golang:1.19 AS build-stage + +WORKDIR /app + +COPY * ./ +RUN go mod download + +RUN CGO_ENABLED=0 GOOS=linux go build -o /main + +# Run the tests in the container +FROM build-stage AS run-test-stage +RUN go test -v ./... + +# Deploy the application binary into a lean image +FROM gcr.io/distroless/base-debian12 AS build-release-stage + +WORKDIR / + +COPY --from=build-stage /main /main + +EXPOSE 8080 + +USER nonroot:nonroot + +ENTRYPOINT ["/main"] diff --git a/go/Dockerfile.old b/go/Dockerfile.old new file mode 100755 index 0000000..2c572c4 --- /dev/null +++ b/go/Dockerfile.old @@ -0,0 +1,22 @@ +# Use an official Golang runtime as a parent image +FROM golang:1.21.4 + +# Set the working directory in the container +WORKDIR /go/src/app + +# Copy the local package files to the container's workspace +COPY . . + +# Download and install any required third-party dependencies into the container. +#RUN go get -u github.com/gorilla/mux +RUN go get -u github.com/go-sql-driver/mysql +RUN go get -u github.com/sirupsen/logrus + +# Build the Go application +RUN go build -o main . + +# Expose port 8080 to the outside world +EXPOSE 8080 + +# Command to run the application with environment variables +CMD ["./main"] diff --git a/go/go.mod b/go/go.mod new file mode 100644 index 0000000..ebcb2f0 --- /dev/null +++ b/go/go.mod @@ -0,0 +1,13 @@ +module ICStoRSS + +go 1.19 + +require ( + github.com/apognu/gocal v0.9.0 + github.com/gorilla/feeds v1.2.0 +) + +require ( + github.com/ChannelMeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61 // indirect + github.com/stretchr/testify v1.8.1 // indirect +) diff --git a/go/go.sum b/go/go.sum new file mode 100644 index 0000000..b0d719f --- /dev/null +++ b/go/go.sum @@ -0,0 +1,28 @@ +github.com/ChannelMeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61 h1:N5Vqww5QISEHsWHOWDEx4PzdIay3Cg0Jp7zItq2ZAro= +github.com/ChannelMeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61/go.mod h1:GnKXcK+7DYNy/8w2Ex//Uql4IgfaU82Cd5rWKb7ah00= +github.com/apognu/gocal v0.9.0 h1:2lGdZprjYs9A6l1RTEmapmpE1PiDbXNX8bUVqZt3vm4= +github.com/apognu/gocal v0.9.0/go.mod h1:ZOJfNOqpz8aasi3uqzDu+eWTT6VuEa/TvQWiYYWlb80= +github.com/channelmeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61 h1:o64h9XF42kVEUuhuer2ehqrlX8rZmvQSU0+Vpj1rF6Q= +github.com/channelmeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61/go.mod h1:Rp8e0DCtEKwXFOC6JPJQVTz8tuGoGvw6Xfexggh/ed0= +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= +github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc= +github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go/main.go b/go/main.go new file mode 100644 index 0000000..1c1ce55 --- /dev/null +++ b/go/main.go @@ -0,0 +1,66 @@ +package main + +import ( + "fmt" + "net/http" + "time" + + "github.com/apognu/gocal" + "github.com/gorilla/feeds" +) + +func convertICStoRSS(w http.ResponseWriter, r *http.Request) { + // Lese die ICS-URL aus dem Query-Parameter + icsURL := r.URL.Query().Get("ics") + if icsURL == "" { + http.Error(w, "Missing 'ics' query parameter", http.StatusBadRequest) + return + } + + // ICS-Datei herunterladen + resp, err := http.Get(icsURL) + if err != nil { + http.Error(w, "Unable to fetch ICS file", http.StatusInternalServerError) + return + } + defer resp.Body.Close() + + // ICS-Datei parsen + parser := gocal.NewParser(resp.Body) + parser.Parse() + + // RSS-Feed erstellen + feed := &feeds.Feed{ + Title: "Converted Calendar Feed", + Link: &feeds.Link{Href: icsURL}, + Description: "This is a converted calendar feed", + Created: time.Now(), + } + + for _, event := range parser.Events { + // Dereferenziere event.Start, um den time.Time Wert zu erhalten + item := &feeds.Item{ + Title: event.Summary, + Description: event.Description, + Link: &feeds.Link{Href: icsURL}, + Created: *event.Start, + } + feed.Items = append(feed.Items, item) + } + + // RSS als HTTP-Antwort senden + rssData, err := feed.ToRss() + if err != nil { + http.Error(w, "Unable to generate RSS feed", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/rss+xml") + w.Write([]byte(rssData)) +} + +func main() { + http.HandleFunc("/rss", convertICStoRSS) + fmt.Println("Server is running at :8080") + http.ListenAndServe(":8080", nil) +}