From d8404ce857fdaab7bc02d4c69b7e87cb0fdfab19 Mon Sep 17 00:00:00 2001 From: DanielS Date: Sun, 20 Sep 2026 22:48:46 +0200 Subject: [PATCH] initial commit --- .gitea/workflows/deploy.yaml | 41 ++++ Dockerfile | 16 ++ Getraenkekarte.pdf | 86 ++++++++ Getraenkekarte_50_Geburtstag.pdf | 86 ++++++++ create_pdf.py | 187 +++++++++++++++++ docker-compose.yml | 7 + getraenkekarte.html | 187 +++++++++++++++++ index.html | 348 +++++++++++++++++++++++++++++++ 8 files changed, 958 insertions(+) create mode 100644 .gitea/workflows/deploy.yaml create mode 100644 Dockerfile create mode 100644 Getraenkekarte.pdf create mode 100644 Getraenkekarte_50_Geburtstag.pdf create mode 100644 create_pdf.py create mode 100644 docker-compose.yml create mode 100644 getraenkekarte.html create mode 100644 index.html diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml new file mode 100644 index 0000000..7ae183a --- /dev/null +++ b/.gitea/workflows/deploy.yaml @@ -0,0 +1,41 @@ +name: Build and Deploy + +on: + push: + branches: + - main + - staging + +jobs: + build: + runs-on: webserver + container: + image: catthehacker/ubuntu:act-latest + steps: + - name: Code auschecken + uses: actions/checkout@v4 + + - name: Docker login to Gitea registry + run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login gitea.hephex.de -u "${{ secrets.REGISTRY_USER }}" --password-stdin + + - name: Build Docker image + run: docker build -t gitea.hephex.de/daniel/getraenkekarte:latest -f Dockerfile . + + - name: Push Docker image + run: docker push gitea.hephex.de/daniel/getraenkekarte:latest + + - name: Clean up runner cache + run: | + docker image prune -f + docker builder prune -f + + - name: Deploy to Proxmox LXC via SSH + uses: appleboy/ssh-action@v0.1.5 + with: + host: 192.168.178.132 + username: ${{ secrets.PROXMOX_USER }} + key: ${{ secrets.PROXMOX_SSH_KEY }} + script: | + cd /opt/getraenkekarte + docker compose pull + docker compose up -d diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..31fded6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM caddy:2-alpine + +RUN echo -e ":80 {\n\ + root * /usr/share/caddy\n\ + encode zstd gzip\n\ + file_server\n\ + header {\n\ + Cache-Control \"public, max-age=3600\"\n\ + X-Content-Type-Options nosniff\n\ + }\n\ +}" > /etc/caddy/Caddyfile + +COPY index.html /usr/share/caddy/ +COPY Getraenkekarte.pdf /usr/share/caddy/ + +EXPOSE 80 diff --git a/Getraenkekarte.pdf b/Getraenkekarte.pdf new file mode 100644 index 0000000..bb827de --- /dev/null +++ b/Getraenkekarte.pdf @@ -0,0 +1,86 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 5 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/BaseFont /ZapfDingbats /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +5 0 obj +<< +/BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font +>> +endobj +6 0 obj +<< +/Contents 10 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 9 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/PageMode /UseNone /Pages 9 0 R /Type /Catalog +>> +endobj +8 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20260920223817+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260920223817+02'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +9 0 obj +<< +/Count 1 /Kids [ 6 0 R ] /Type /Pages +>> +endobj +10 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1640 +>> +stream +GauHL>Bf'b&:WeD9HUj$m/bbKpsuoZ82a2Jkm"_G:(Ju^"=P*K/">ZH^V1q&Cd[QBB$!AqD)B\"^2InFJq\-3r?!ZnNX,(N)$S/j0Eiq^JADum#-I>GRS2A!E*I8kXs8a^[l=nR$+6`#:tWJH=UWiWKc438M(0@H9EfKr!m3LmQt>=Q@"P/$CU>+1KYcKN8SpHU%;psV&t^h(QUeN;*oq?g9cs9;h/0j8bqJjpgT'bC>NONGG-AM^jm0#UTN6docaN*u`+E>YZ@/TM17lD4C*^2dWD"Ik?m7HJ#9&3E'RD5PRJiPe>Eb]4/*r8/go]4EA]&r(m7G[>;jPGB'O@k:kKl_PiI'E-mV_&$77L]EHtUO)Q'\+%#1(`mquK*.lJp)tW=u/@uHY]PTs6lMqO@'mA_C^1W9L]\1;OD6lOg%FsX!2f*mOrJU9n7t\QpHZ4"HE]H+j\E\!OYB(,1EJNM4W#5@3^*%NpK=gUm0>fXrGIXp`a-l_PBIGA/pgKkTi1@%iLL5LOp^6g+\q4F6Eqk$k,Ub_ck#EE\Tg@-\c/:n@*1FGYi]i%LkU1b05dghnKBP'A09&80ff"P24e'iqK1\ae(hZmR>f5>JZ.Yb=V,qck>`etc.rUE"se*b,8]0\`]=U1bJD2BUD_G>3U:5M&mX3hl:5K.2F-tbi1b$*;2?JUrfZ5lR9HbGlhn,\Z;qZ$/0UuQ$JB%dns=h86DL)?Jc<,!5``\+etU`>+)6/Z92$IB_^\iFmJ>(6`DQ1Q6Y,Ru?8Xaul;l"qT.QoN1ZGMli-;]VqnT)K(=qUdq?"#cDtLNEhp?"5XL;qU_k,1G^1Cj@b<)u>hR@/b9@4%X^j9-cFL#1VclNIkPR.pUUGk+)7Gl+c)C-e6JuK6UDC+`L$MGT$H)Sbe`G&RS#`mMhSo!El[>a??H)'?qbdIM4+u47D63$[@oLntm=fj9C(R1g0*J,/9Su2S4%]1c5fV*XkdN8Y<)@C#MfV?MlM1ZOlVkH\b5a'"Yq%=:YA=+LT^%$_Pf6kYGArsc,$\"l$hO6BWU&R;8l:sqLeW<,0h$)s'L6b/Np=otnU/2,_8R$R*:?m'@Od"!]%WV$L6FXGTDXjZ+cTp-AWXdIUuDLYbgj$ZSm[s'8JE[MBjP(+47h+1VuZ.;,70YV8RMb`_@]Og@rnHt@kP8tI_;?$I9OS6jO$nBh\3Z8YrS[if0ai8+calhq(F=5rendstream +endobj +xref +0 11 +0000000000 65535 f +0000000061 00000 n +0000000122 00000 n +0000000229 00000 n +0000000341 00000 n +0000000424 00000 n +0000000539 00000 n +0000000743 00000 n +0000000811 00000 n +0000001091 00000 n +0000001150 00000 n +trailer +<< +/ID +[] +% ReportLab generated PDF document -- digest (opensource) + +/Info 8 0 R +/Root 7 0 R +/Size 11 +>> +startxref +2882 +%%EOF diff --git a/Getraenkekarte_50_Geburtstag.pdf b/Getraenkekarte_50_Geburtstag.pdf new file mode 100644 index 0000000..891a1f2 --- /dev/null +++ b/Getraenkekarte_50_Geburtstag.pdf @@ -0,0 +1,86 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 5 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/BaseFont /ZapfDingbats /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +5 0 obj +<< +/BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font +>> +endobj +6 0 obj +<< +/Contents 10 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 9 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/PageMode /UseNone /Pages 9 0 R /Type /Catalog +>> +endobj +8 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20260920223503+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260920223503+02'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +9 0 obj +<< +/Count 1 /Kids [ 6 0 R ] /Type /Pages +>> +endobj +10 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1719 +>> +stream +GauHL=``:f&:WeDFC%jU$ac?if=kYu+6t-j;!b26?3CZj5tK9l`"i=Km1DYt=L)(b"H8J1eo^Z\od(2(nP-=hP81li%tC/_+;F_k&8lIVYG(Eo^9pKaBb>u#S2"u!gT^/YYJXq(R)H<;m!l']$hkp#)Vf:c.O\+lX.Yj^7Lb,,DWA;m`Ds@Qg5\@Is7P&6D)h"]K+Tp8m8a1d2t6\uU=94e1iVR;bJ54r]lV8u4_RLg&*WH8K!'UCGFeW0VrBn`?EjICmloL9c[fVA$.EWPDHMq2*Q@CV7t.hP&Y_,MgB$.M'#KqX%GGd:!F)(+i$e.a3@8g]`*"R?rtAHI]bhka/KOnkpRg"lRo5MXuh_n:jkB"#@W4q!1+\MOhPMGH-4g*a!QO-@?KoN%bL!Y[*_Z()W9^gKXfu5IP$gk9;%o5M/B#`B=9jIi'b1#M'$^a[4J:(Ih&B>!-;hnR[3-qaLS+rZ2LpsaD3a/QHQ"\kH)8=l9qh%)&IQG15H^E@?Mp(^MC]*tF/c9b]@o?o;4Kp@0^4LQS]a_n7F!"*q?OlFPn,#W`+"NhhM#fPT15R+3AfZauHVklk2YqSU7G@CJKPV3pi9DCraE.?Yk0X*OSHc'LrlXaU>G3t1a4"VHahno^r*$6kMP5LcY:J[$rOt!ONNR1L[)E-Q]AE5c;)mE!)RlQ*Z2729)S0(7AEe)kN6HiFH,Y:`3+d)/uKh3Lm)l_TYtD?:mlZfK(7cT;/%,P(u.O[3M`ULUs-*DG;ZnC@'=9[?W[9Zq=G[9pe!*+N<;g*.\5K[Q2M/Wch/G4ut;E)lA<3*MeP^#r5X^YTcJEZPDe\1Fkk8@S4/hr4Ag(kA5F"1rog"O!2%AsSE5C!LIoaD3b:,Ee)M=.4-Sk,-\=jV:1iseq*Nj1L-Z-L5C(^I3fj[5V@endstream +endobj +xref +0 11 +0000000000 65535 f +0000000061 00000 n +0000000122 00000 n +0000000229 00000 n +0000000341 00000 n +0000000424 00000 n +0000000539 00000 n +0000000743 00000 n +0000000811 00000 n +0000001091 00000 n +0000001150 00000 n +trailer +<< +/ID +[] +% ReportLab generated PDF document -- digest (opensource) + +/Info 8 0 R +/Root 7 0 R +/Size 11 +>> +startxref +2961 +%%EOF diff --git a/create_pdf.py b/create_pdf.py new file mode 100644 index 0000000..98cb358 --- /dev/null +++ b/create_pdf.py @@ -0,0 +1,187 @@ +import os +from reportlab.lib.pagesizes import A4 +from reportlab.lib import colors +from reportlab.lib.units import mm +from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle +from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle +from reportlab.pdfgen import canvas + +class NumberedCanvas(canvas.Canvas): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._saved_page_states = [] + + def showPage(self): + self._saved_page_states.append(dict(self.__dict__)) + self._startPage() + + def save(self): + num_pages = len(self._saved_page_states) + for state in self._saved_page_states: + self.__dict__.update(state) + self.draw_page_decorations() + super().showPage() + super().save() + + def draw_page_decorations(self): + self.saveState() + self.setStrokeColor(colors.HexColor("#D4AF37")) + self.setLineWidth(2) + self.rect(10*mm, 10*mm, 190*mm, 277*mm) + self.setLineWidth(0.7) + self.rect(11.5*mm, 11.5*mm, 187*mm, 274*mm) + self.restoreState() + +def generate_pdf(filename): + doc = SimpleDocTemplate( + filename, + pagesize=A4, + leftMargin=16*mm, + rightMargin=16*mm, + topMargin=16*mm, + bottomMargin=16*mm + ) + + styles = getSampleStyleSheet() + + title_style = ParagraphStyle( + 'MainTitle', + fontName='Helvetica-Bold', + fontSize=22, + leading=26, + alignment=1, + textColor=colors.HexColor("#1A1A1A"), + spaceAfter=3 + ) + + subtitle_style = ParagraphStyle( + 'SubTitle', + fontName='Helvetica-Oblique', + fontSize=10, + leading=13, + alignment=1, + textColor=colors.HexColor("#555555"), + spaceAfter=10 + ) + + section_style = ParagraphStyle( + 'SectionHeader', + fontName='Helvetica-Bold', + fontSize=12, + leading=15, + textColor=colors.HexColor("#8A6D1C"), + spaceBefore=6, + spaceAfter=6, + alignment=0 + ) + + drink_title_style = ParagraphStyle( + 'DrinkTitle', + fontName='Helvetica-Bold', + fontSize=10, + leading=12, + textColor=colors.HexColor("#111111"), + spaceAfter=2 + ) + + drink_text_style = ParagraphStyle( + 'DrinkText', + fontName='Helvetica', + fontSize=8.5, + leading=11, + textColor=colors.HexColor("#333333") + ) + + footer_style = ParagraphStyle( + 'Footer', + fontName='Helvetica-Oblique', + fontSize=9, + leading=12, + alignment=1, + textColor=colors.HexColor("#777777"), + spaceBefore=8 + ) + + story = [] + + # Header + story.append(Paragraph("🍸 GETRÄNKEKARTE 🍸", title_style)) + story.append(Paragraph("Frisch zubereitet an der Bar auf Eis.", subtitle_style)) + + # Line + line_table = Table([[""]], colWidths=[178*mm], rowHeights=[1]) + line_table.setStyle(TableStyle([('LINEABOVE', (0,0), (-1,-1), 1, colors.HexColor("#D4AF37"))])) + story.append(line_table) + story.append(Spacer(1, 4*mm)) + + # Cocktails + story.append(Paragraph("🍹 SIGNATURE COCKTAILS", section_style)) + + cocktails = [ + ("1. Moscow Mule", "Zutaten: Wodka, frischer Limettensaft, Ginger Beer, Minzzweig & Limettenspalte.
Geschmack: Scharf-würzig, erfrischend und spritzig."), + ("2. Gin & Tonic", "Zutaten: Klassischer Gin, Tonic Water, Limettenscheibe.
Geschmack: Der elegante Klassiker – herb, bitter und ohne Zuckerüberhang."), + ("3. Mojito", "Zutaten: Weißer Rum, frische Minzblätter, Zuckersirup, Limettensaft, Sprudelwasser.
Geschmack: Aromatisches Bar-Feeling mit frischer Minze."), + ("4. Cuba Libre", "Zutaten: Weißer Rum, erfrischende Cola, frischer Limettensaft, Limette.
Geschmack: Der süße, vertraute Party-Dauerbrenner."), + ("5. Vodka Cranberry", "Zutaten: Wodka, Cranberrysaft, Soda, frischer Limettensaft, Limettenscheibe.
Geschmack: Angenehm säuerlich-herb statt klebrig-süß."), + ("6. Skinny Bitch", "Zutaten: Wodka, spritziges Mineralwasser, viel frischer Limettensaft.
Geschmack: Der leichte, komplett zucker- und kalorienfreie Drink.") + ] + + col_width = 87 * mm + table_data = [] + for i in range(0, len(cocktails), 2): + cell_left = [ + Paragraph(cocktails[i][0], drink_title_style), + Paragraph(cocktails[i][1], drink_text_style) + ] + cell_right = [ + Paragraph(cocktails[i+1][0], drink_title_style), + Paragraph(cocktails[i+1][1], drink_text_style) + ] + table_data.append([cell_left, cell_right]) + + cocktail_table = Table(table_data, colWidths=[col_width, col_width]) + cocktail_table.setStyle(TableStyle([ + ('VALIGN', (0,0), (-1,-1), 'TOP'), + ('BOTTOMPADDING', (0,0), (-1,-1), 8), + ('RIGHTPADDING', (0,0), (0,-1), 6), + ('LEFTPADDING', (1,0), (1,-1), 6), + ])) + story.append(cocktail_table) + + story.append(Spacer(1, 2*mm)) + story.append(Paragraph("🍃 0.0% MOCKTAILS (ALKOHOLFREI)", section_style)) + + mocktails = [ + ("Virgin Mojito", "Frische Minze, Zuckersirup, Limettensaft, aufgegossen mit Ginger Beer & Sprudelwasser."), + ("Cranberry Ginger Splash", "Feinherber Cranberrysaft, frischer Limettensaft & würziges Ginger Beer."), + ("Homemade Lime Soda", "Frischer Limettensaft, süßer Zuckersirup, Minze & eiskaltes Sprudelwasser.") + ] + + m_data = [] + m_col_width = 58 * mm + row_cells = [] + for m in mocktails: + cell = [ + Paragraph(f"{m[0]}", drink_title_style), + Paragraph(m[1], drink_text_style) + ] + row_cells.append(cell) + m_data.append(row_cells) + + mocktail_table = Table(m_data, colWidths=[m_col_width, m_col_width, m_col_width]) + mocktail_table.setStyle(TableStyle([ + ('VALIGN', (0,0), (-1,-1), 'TOP'), + ('RIGHTPADDING', (0,0), (-1,-1), 4), + ('LEFTPADDING', (0,0), (-1,-1), 4), + ])) + story.append(mocktail_table) + + story.append(Spacer(1, 6*mm)) + story.append(Paragraph("✨ Cheers! Cheers to great drinks and good vibes! ✨", footer_style)) + + doc.build(story, canvasmaker=NumberedCanvas) + print("PDF updated.") + +if __name__ == "__main__": + out_path = r"C:\Users\Danie\.gemini\antigravity-ide\scratch\Getraenkekarte.pdf" + generate_pdf(out_path) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..dbd2bc4 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,7 @@ +services: + getraenkekarte: + image: gitea.hephex.de/daniel/getraenkekarte:latest + container_name: getraenkekarte + restart: unless-stopped + ports: + - "8085:80" diff --git a/getraenkekarte.html b/getraenkekarte.html new file mode 100644 index 0000000..c1b4313 --- /dev/null +++ b/getraenkekarte.html @@ -0,0 +1,187 @@ + + + + + + + + +
+

🍸 GETRÄNKEKARTE 🍸

+

50. Geburtstag — Frisch zubereitet an der Bar auf Eis

+
+ +
+
🍹 Cocktail-Highlights
+
+
+
1. Moscow Mule
+
+ Zutaten: Wodka, Limettensaft, Ginger Beer, Minze & Limette.
+ Geschmack: Scharf-würzig, erfrischend & spritzig. +
+
+ +
+
2. Gin & Tonic
+
+ Zutaten: Gin, Tonic Water, Limettenscheibe.
+ Geschmack: Eleganter Klassiker – herb, bitter & rein. +
+
+ +
+
3. Mojito
+
+ Zutaten: Weißer Rum, frische Minze, Zuckersirup, Limettensaft, Soda.
+ Geschmack: Aromatisches Bar-Feeling mit frischer Minze. +
+
+ +
+
4. Cuba Libre
+
+ Zutaten: Weißer Rum, Cola, frischer Limettensaft, Limettenspalte.
+ Geschmack: Süßer & vertrauter Party-Klassiker. +
+
+ +
+
5. Vodka Cranberry
+
+ Zutaten: Wodka, Cranberrysaft, Soda, frischer Limettensaft.
+ Geschmack: Fruchtig-rot, angenehm herb & säuerlich. +
+
+ +
+
6. Skinny Bitch
+
+ Zutaten: Wodka, Mineralwasser, viel frischer Limettensaft.
+ Geschmack: Leicht, frisch, zucker- & kalorienfrei. +
+
+
+
+ +
+
🍃 Alkoholfreie Mocktails
+
+
+
Virgin Mojito
+
Frische Minze, Limettensaft, Zuckersirup, Ginger Beer & Sprudel.
+
+ +
+
Cranberry Ginger Splash
+
Cranberrysaft, frischer Limettensaft & würziges Ginger Beer.
+
+ +
+
Homemade Lime Soda
+
Frischer Limettensaft, Zuckersirup, aromatische Minze & Eiswasser.
+
+
+
+ + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..f3b3488 --- /dev/null +++ b/index.html @@ -0,0 +1,348 @@ + + + + + + BAR & COCKTAILS + + + + + + + +
+
+
🔥 Open Bar
+

GETRÄNKEKARTE

+

Frisch im Glas zubereitet. Wähle deinen Drink!

+
+ + +
+
🍹 Signature Cocktails
+ +
+ + +
+
🍃 0.0% Mocktails
+ +
+ + +
+ + +