add config.json again, part 2
All checks were successful
ci / build (push) Successful in 1m6s

This commit is contained in:
Christopher Hase 2025-04-17 16:11:34 +02:00
parent 628855b5d9
commit bbad13f570
7 changed files with 2 additions and 248 deletions

View file

@ -11,10 +11,9 @@ This app will send an I-Ching horoscope to the pre-configured mailhog instance i
This app uses the I-Ching library app https://github.com/Velfi/i-ching.git.
<!--## Configuration
## Configuration
Properties of the app can be configured in the file config.json. It is possible to configure the mail host and port.
It is also possible to configure the intervall of days between the sending of horoscopes and the time of sending. The default is to send one email every seven days at 8 am.-->
It is also possible to configure the intervall of days between the sending of horoscopes and the time of sending. The default is to send one email every seven days at 8 am.
This will start the deployment of the app in the pod, the service and an ingress for the HTTP frontend server and an ingress for the backend server.
When a pod with the app is initally started, one email will be sent to the configured receiver.
@ -64,5 +63,3 @@ The app can be deployed by running:
$ kubectl apply -f deployment.yaml
```
Der HTTP-Server can be access in a browser with the address https://192-168-197-2.c-one-infra.de/iching/
<!-- TODO: make address configurable again -->

137
dist/backend/broker.js vendored
View file

@ -1,137 +0,0 @@
import { exec } from 'child_process';
import * as fs from 'fs';
import * as nodemailer from 'nodemailer';
import { fileURLToPath } from 'url';
import * as path from 'path';
var config;
export function executeCommand() {
exec('iching divine', (error, stdout, stderr) => {
console.log(`I-Ching-Broker: \'iching divine\' called`);
if (error) {
console.error(`Error: ${error.message}`);
return;
}
if (stderr) {
console.error(`Stderr: ${stderr}`);
return;
}
//Load config once
if (config == undefined) {
config = loadConfig();
}
console.log(`Horoscope received; sending E-Mail next`);
sendEmail(stdout);
});
}
// Run function once initially, called from Dockerfile
executeCommand();
// Load the Configuration
function loadConfig() {
console.log(`Load Config`);
//const data = fs.readFileSync('config.json', 'utf-8');
//const configPath = path.join(__dirname, 'config.json');
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const configPath = path.join(__dirname, 'config.json');
const data = fs.readFileSync(configPath, 'utf-8');
return JSON.parse(data);
}
// Send E-Mail
async function sendEmail(content) {
// Create Transporter
const transporter = nodemailer.createTransport({
host: config.mailHost, //"mailhog.mailhog.svc.cluster.local", //config.mailHost,
port: config.mailPort, //1025, //config.mailPort,
secure: false
});
try {
const info = await transporter.sendMail({
from: '"The Oracle" <the.oracle@holy.mountain>',
to: config.emailReceiver, //"test@mailhog.local", //config.emailReceiver,
subject: "Your Horoscope Is Ready",
text: content,
html: html(content)
});
console.log("E-Mail sent: ", info.messageId + "\n\n");
}
catch (error) {
console.error("Error Sending E-Mail:", error + "\n\n");
console.log("Failed to send this horoscope: \n", content + "\n");
}
}
// Generate 1) Parse Tree and 2) HTML
export function html(inputText) {
const parseTree = parse(inputText);
const htmlOutput = render(parseTree);
return htmlOutput;
}
// Generate the Parse Tree
function parse(input) {
console.log("Parse input text");
const root = { type: "Root" };
var currentNode = root;
const lines = input.split("\n");
for (const line of lines) {
if (line.startsWith("Hexagram")) {
const hexagram = { type: "Hexagram" };
currentNode.child = hexagram;
currentNode = hexagram;
currentNode.value = "<h1>" + line + "</h1>";
}
else if (line.startsWith("Judgement")) {
const judgement = { type: "Judgement" };
currentNode.child = judgement;
currentNode = judgement;
currentNode.value = "<h3>" + line + "</h3>";
}
else if (line.startsWith("Images")) {
const images = { type: "Images" };
currentNode.child = images;
currentNode = images;
currentNode.value = "<h3>" + line + "</h3>";
}
else if (line.startsWith("~") && currentNode.type != "ChangingLines") {
const changingLines = { type: "ChangingLines" };
currentNode.child = changingLines;
currentNode = changingLines;
currentNode.value = line;
}
else {
currentNode.value = currentNode.value + line + "<br>";
}
}
return root;
}
// Generate HTML from Parse Tree
function render(node) {
if (node == undefined) {
console.log("I-Ching-Broker: Rendering of nodes finished!");
return "";
}
var outputHTML = "";
switch (node.type) {
case "Root":
return render(node.child);
case "Hexagram":
node.value = node.value?.replace("<h1>", "<div style=\"border: 1px dotted gray; border-radius: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px; padding-bottom: 10px; width: auto; display: inline-block; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h1>");
node.value = node.value?.replace("</h1>", "</h1><div style=\"border: 1px solid gray; border-radius: 25px; padding-left: 30px; padding-right: 30px; padding-top: 20px; width: auto; display: inline-block; text-align: center; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h2>");
node.value = node.value?.replace("<br>", " - ");
outputHTML = "<br><p>" + node.value + "</h2></div></p>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
case "Images":
outputHTML = "<p>" + node.value + "</p></div>"; //EXTRA closing div (was opened at beginning of hexagram)
outputHTML = outputHTML + render(node.child);
return outputHTML;
case "ChangingLines":
const regex = new RegExp("~", "g");
node.value = node.value?.replace(regex, "");
outputHTML = "<br><br><p><div style=\"padding-left: 20px; padding-right: 20px; padding-top: 20px; display: inline-block; color: gray; text-align: center;\">" + node.value + "</div></p><br>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
default:
outputHTML = "<p>" + node.value + "</p>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
}
}

View file

@ -1,5 +0,0 @@
{
"emailReceiver": "test@mailhog.local",
"mailHost": "mailhog.mailhog.svc.cluster.local",
"mailPort": 1025
}

View file

@ -1,15 +0,0 @@
import express from 'express';
import cors from 'cors';
import { executeCommand } from './broker.js';
const app = express();
const port = 8090;
app.use(cors());
app.post('/iching/api/command', (req, res) => {
//TODO no logging from inside this method???
console.log(`Backend-Server: receiving POST to /iching/api/command`);
executeCommand();
res.status(200).send('Backend-Server: Broker was called\n');
});
app.listen(port, '0.0.0.0', () => {
console.log(`Backend-Server running on http://0.0.0.0:${port}`);
});

View file

@ -1 +0,0 @@
window.DEPLOY_MODE = 'local';

View file

@ -1,18 +0,0 @@
"use strict";
function handleClick() {
console.log("Der Button wurde geklickt!");
//const deployMode = (window as { DEPLOY_MODE?: 'docker' | 'k8s' }).DEPLOY_MODE ?? 'k8s';
const deployMode = window.DEPLOY_MODE ?? 'k8s';
const endpoint = deployMode === 'docker' || deployMode === 'local'
? 'http://localhost:8090/iching/api/command'
: '/iching/api/command';
console.log(`DEPLOY_MODE=${deployMode}, sende POST an: ${endpoint}`);
fetch(endpoint, { method: 'POST' })
.then(res => res.text())
.then(text => console.log("HTTP-Server says:", text))
.catch(error => console.error("HTTP-Server - Error:", error));
}
document.addEventListener("DOMContentLoaded", () => {
const button = document.getElementById("myButton");
button?.addEventListener("click", handleClick);
});

View file

@ -1,67 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Your I-Ging Horoscope</title>
<style>
body {
margin: 0;
padding: 0;
background: linear-gradient(to bottom right, #fdf6e3, #e3f2fd);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
text-align: center;
background: white;
padding: 2rem;
border-radius: 1rem;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
}
h1 {
margin-bottom: 1rem;
color: #3f51b5;
}
#myButton {
background-color: #3f51b5;
color: white;
border: none;
padding: 0.8rem 1.5rem;
font-size: 1.1rem;
border-radius: 0.5rem;
cursor: pointer;
transition: background-color 0.3s ease;
}
#myButton:hover {
background-color: #303f9f;
}
.footer {
margin-top: 2rem;
font-size: 0.9rem;
color: #666;
}
</style>
</head>
<body>
<div class="container">
<h1>Do you want to know the future?</h1>
<h2> ☝️ Look into the future with your personal I-Ging Horoscope! ☝️</h2>
<p>Click on the Button to receive your personal Horoscope. 100% accuracy guaranteed!</p>
<button id="myButton">✨ Receive Horoscope ✨</button>
<div class="footer">🧘 With Love & Fortune from the Cosmos 💫</div>
</div>
<script src="./deploy.js"></script>
<script type="module" src="./event.mjs"></script>
</body>
</html>