Compare commits

..

10 Commits

Author SHA1 Message Date
Hazel Noack
4f44974c58 draft 2025-08-01 10:45:26 +02:00
Hazel Noack
a62b445f19 registering templates 2025-07-17 11:10:17 +02:00
Hazel Noack
13fae1c23f implemented search on youtube 2025-07-16 17:38:28 +02:00
Hazel Noack
21719a6cf7 added demo toml 2025-07-16 17:27:03 +02:00
addaade269 Merge pull request 'layed out goroutine' (#2) from diyhrt/interval_fetching into main
Reviewed-on: #2
2025-07-16 15:22:43 +00:00
Hazel Noack
6ee6c9c8d9 layed out goroutine 2025-07-16 16:59:40 +02:00
Hazel Noack
a0133e0981 edited todo 2025-07-16 16:38:47 +02:00
70c668bdf1 Merge pull request 'cli' (#1) from cli into main
Reviewed-on: #1
2025-07-16 14:35:52 +00:00
Hazel Noack
68c89de1a4 made some metadata of the program dynamic 2025-07-16 16:25:22 +02:00
Hazel Noack
0b7de76874 edited readme 2025-07-16 16:13:48 +02:00
21 changed files with 277 additions and 463 deletions

View File

@@ -13,7 +13,7 @@ go install gitea.elara.ws/Hazel/transfem-startpage
Then you can run the program `transfem-startpage`
```sh
transfem-startpage
transfem-startpage help
```
To configure this new tab page as website, you can install the firefox extension [New Tab Override](https://addons.mozilla.org/en-US/firefox/addon/new-tab-override/). Then just configure the url as `http://127.0.0.1:{port}/`. The default port should be `5500` but it will also print it out when starting the server. Make sure to check the box `Set focus to the web page instead of the address bar` in the extension settings, because the new tab page auto focuses the search bar.
@@ -55,10 +55,9 @@ air dev
## TODO
- implementing proper command line args
- clear cache
- implement fetching in intervals
- host this website on a demo page
- implement templating for every one of the frontend files
- implement functionality to clear and clean cache
- host this website on a demo page
- implement ctl
- implement autocomplete with a nice go backend and fast communication. Since it all runs locally nobody should have privacy concerns NEEDS TO BE ABLE TO TOGGLED OFF FOR DEMO PAGE

17
demo.toml Normal file
View File

@@ -0,0 +1,17 @@
[Server]
Port = 1312
[DiyHrt]
FetchIntervals = 60
[Template]
ActiveCard = "listings"
PageTitle = "TransfemStartpage demo"
HeaderPhrases = [
"GirlJuice.Inject();",
"You.Cute = true;",
"You.Gay = true;",
"Nazi.Punch();",
"Dolls.GiveGuns();",
"Firefox > Chrome"
]

View File

@@ -1,293 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="350mm"
height="250mm"
viewBox="0 0 350 250"
version="1.1"
id="svg1"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
sodipodi:docname="bg.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#000000"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:export-bgcolor="#00000000"
inkscape:zoom="0.48315491"
inkscape:cx="734.75399"
inkscape:cy="595.04724"
inkscape:window-width="1672"
inkscape:window-height="957"
inkscape:window-x="816"
inkscape:window-y="1259"
inkscape:window-maximized="0"
inkscape:current-layer="layer1" />
<defs
id="defs1">
<rect
x="1105.2356"
y="300.11078"
width="161.4389"
height="53.812968"
id="rect4" />
<rect
x="203.42924"
y="897.13763"
width="220.99149"
height="62.931351"
id="rect3" />
<rect
x="140.49789"
y="166.84126"
width="339.53659"
height="86.347672"
id="rect2" />
<rect
x="125.8627"
y="753.71271"
width="357.09882"
height="87.811188"
id="rect1" />
<rect
x="125.8627"
y="753.71271"
width="357.09882"
height="87.811188"
id="rect1-7" />
<rect
x="125.8627"
y="753.71271"
width="357.09882"
height="87.811188"
id="rect1-2" />
<rect
x="125.8627"
y="753.71271"
width="357.09882"
height="87.811188"
id="rect1-9" />
<rect
x="125.8627"
y="753.71271"
width="357.09882"
height="87.811188"
id="rect1-6" />
<rect
x="140.49789"
y="166.84126"
width="339.53659"
height="86.347672"
id="rect2-0" />
<rect
x="140.49789"
y="166.84126"
width="339.53659"
height="86.347672"
id="rect2-2" />
<rect
x="140.49789"
y="166.84126"
width="339.53659"
height="86.347672"
id="rect2-2-6" />
<rect
x="1105.2356"
y="300.11078"
width="161.4389"
height="53.812969"
id="rect4-4" />
<rect
x="1105.2356"
y="300.11078"
width="161.4389"
height="53.812969"
id="rect4-3" />
<rect
x="1105.2356"
y="300.11078"
width="161.4389"
height="53.812969"
id="rect4-3-2" />
<rect
x="125.8627"
y="753.71271"
width="357.09882"
height="87.811188"
id="rect1-2-4" />
<rect
x="1105.2356"
y="300.11078"
width="161.4389"
height="53.812969"
id="rect4-3-3" />
<rect
x="1105.2356"
y="300.11078"
width="161.4389"
height="53.812969"
id="rect6" />
<rect
x="140.49789"
y="166.84126"
width="339.53659"
height="86.347672"
id="rect2-2-6-7" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
transform="matrix(0.26273149,-0.03124901,0.03124901,0.26273149,9.6318685,1.010781)"
id="text1"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect1);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="125.86328"
y="784.2323"
id="tspan7">Meow</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26223034,0.03520772,-0.03520772,0.26223034,181.67491,-73.913601)"
id="text1-3"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect1-7);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="125.86328"
y="784.2323"
id="tspan8">Meow</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.2637851,0.02053679,-0.02053679,0.2637851,9.5700315,-96.792778)"
id="text1-1"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect1-2);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="125.86328"
y="784.2323"
id="tspan9">Meow</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26279038,-0.03074987,0.03074987,0.26279038,54.519132,-87.602003)"
id="text1-1-6"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect1-2-4);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="125.86328"
y="784.2323"
id="tspan10">Meow</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26273149,-0.03124901,0.03124901,0.26273149,160.00124,-138.94545)"
id="text1-6"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect1-9);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="125.86328"
y="784.2323"
id="tspan11">Meow</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26430785,-0.01207042,0.01207042,0.26430785,123.83488,0.36913542)"
id="text1-8"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect1-6);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="125.86328"
y="784.2323"
id="tspan12">Meow</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,-21.357022,-13.142783)"
id="text2"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect2);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="140.49805"
y="197.36121"
id="tspan13">gock &lt;333</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26309895,-0.02798714,0.02798714,0.26309895,43.481131,24.812837)"
id="text2-3"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect2-0);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="140.49805"
y="197.36121"
id="tspan14">gock &lt;333</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26094671,-0.04371676,0.04371676,0.26094671,222.97079,141.94755)"
id="text2-8"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect2-2);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="140.49805"
y="197.36121"
id="tspan15">gock &lt;333</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26260965,-0.03225692,0.03225692,0.26260965,163.16927,187.98351)"
id="text2-8-2"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect2-2-6);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="140.49805"
y="197.36121"
id="tspan16">gock &lt;333</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26261141,0.03224256,-0.03224256,0.26261141,-26.436727,169.44502)"
id="text2-8-2-4"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect2-2-6-7);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="140.49805"
y="197.36121"
id="tspan17">gock &lt;333</tspan></text>
<text
xml:space="preserve"
transform="scale(0.26458333)"
id="text3"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect3);display:inline;fill:#ffffff;stroke-width:4.91339" />
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,20.26179,-16.976094)"
id="text4"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect4);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="1105.2363"
y="330.63074"
id="tspan18">Gay :3</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.25941349,0.05204788,-0.05204788,0.25941349,14.622996,-20.113934)"
id="text4-8"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect4-4);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="1105.2363"
y="330.63074"
id="tspan19">Gay :3</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,-185.03108,79.899068)"
id="text4-1"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect4-3);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="1105.2363"
y="330.63074"
id="tspan20">Gay :3</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26300551,-0.02885206,0.02885206,0.26300551,-153.43986,-14.753595)"
id="text4-1-6"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect4-3-2);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="1105.2363"
y="330.63074"
id="tspan21">Gay :3</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.25999838,0.04904269,-0.04904269,0.25999838,-255.80374,45.596021)"
id="text4-1-4"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect4-3-3);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="1105.2363"
y="330.63074"
id="tspan22">Gay :3</tspan></text>
<text
xml:space="preserve"
transform="matrix(0.25999838,0.04904269,-0.04904269,0.25999838,-255.80374,45.596021)"
id="text6"
style="font-size:37.7953px;line-height:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:start;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect6);display:inline;fill:#ffffff;stroke-width:4.91339"><tspan
x="1105.2363"
y="330.63074"
id="tspan23">Gay :3</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,93 +0,0 @@
console.log("adding features to search...");
const form = document.getElementById("search-form");
const input = document.getElementById("search-input");
// https://stackoverflow.com/a/3809435/16804841
const expression = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/gi;
const urlRegex = new RegExp(expression);
const searchEngines = {
"g": {
action: "https://www.google.com/search",
name: "q",
},
"d": {
action: "https://duckduckgo.com/",
name: "q",
},
"y": {
action: "https://yandex.com/search/",
name: "text",
},
"lure": {
action: "https://lure.sh/pkgs",
name: "q",
},
};
const translationPrefixes = [
"t",
"translation",
]
function getDeepLUrl(s) {
const parts = s.split("-")
if (parts.length != 3) {
return undefined
}
return `https://www.deepl.com/en/translator?/#${encodeURIComponent(parts[0].trim())}/${encodeURIComponent(parts[1].trim())}/${encodeURIComponent(parts[2].trim())}`;
}
form.addEventListener("submit", event => {
event.preventDefault();
s = input.value;
// check if url
if (s.match(urlRegex)) {
window.open(s, "_self");
return
}
// deepl translations
let doTranslation = false;
for (const value of translationPrefixes) {
const prefix = `!${value} `;
if (s.startsWith(prefix)) {
doTranslation = true;
s = s.slice(prefix.length); // Remove the !{key} prefix
break;
}
}
if (doTranslation) {
const url = getDeepLUrl(s);
if (url) {
window.open(url.toString(), "_self");
return;
}
}
// Check if the string starts with ! followed by a key from searchEngines
let selectedEngine = {
action: form.getAttribute("action"),
name: input.getAttribute("name"),
};
for (const [key, value] of Object.entries(searchEngines)) {
const prefix = `!${key} `;
if (s.startsWith(prefix)) {
selectedEngine = value;
s = s.slice(prefix.length); // Remove the !{key} prefix
break;
}
}
const url = new URL(selectedEngine.action);
url.searchParams.set(selectedEngine.name, s.trim());
window.open(url.toString(), "_self");
});

View File

@@ -0,0 +1,97 @@
console.log("adding features to search...");
const form = document.getElementById("search-form");
const input = document.getElementById("search-input");
// https://stackoverflow.com/a/3809435/16804841
const expression =
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/gi;
const urlRegex = new RegExp(expression);
const searchEngines = {
g: {
action: "https://www.google.com/search",
name: "q",
},
d: {
action: "https://duckduckgo.com/",
name: "q",
},
y: {
action: "https://www.youtube.com/results",
name: "search_query",
},
ya: {
action: "https://yandex.com/search/",
name: "text",
},
lure: {
action: "https://lure.sh/pkgs",
name: "q",
},
};
const translationPrefixes = ["t", "translation"];
function getDeepLUrl(s) {
const parts = s.split("-");
if (parts.length != 3) {
return undefined;
}
return `https://www.deepl.com/en/translator?/#${encodeURIComponent(
parts[0].trim()
)}/${encodeURIComponent(parts[1].trim())}/${encodeURIComponent(
parts[2].trim()
)}`;
}
form.addEventListener("submit", (event) => {
event.preventDefault();
s = input.value;
// check if url
if (s.match(urlRegex)) {
window.open(s, "_self");
return;
}
// deepl translations
let doTranslation = false;
for (const value of translationPrefixes) {
const prefix = `!${value} `;
if (s.startsWith(prefix)) {
doTranslation = true;
s = s.slice(prefix.length); // Remove the !{key} prefix
break;
}
}
if (doTranslation) {
const url = getDeepLUrl(s);
if (url) {
window.open(url.toString(), "_self");
return;
}
}
// Check if the string starts with ! followed by a key from searchEngines
let selectedEngine = {
action: form.getAttribute("action"),
name: input.getAttribute("name"),
};
for (const [key, value] of Object.entries(searchEngines)) {
const prefix = `!${key} `;
if (s.startsWith(prefix)) {
selectedEngine = value;
s = s.slice(prefix.length); // Remove the !{key} prefix
break;
}
}
const url = new URL(selectedEngine.action);
url.searchParams.set(selectedEngine.name, s.trim());
window.open(url.toString(), "_self");
});

2
go.mod
View File

@@ -6,6 +6,8 @@ require github.com/labstack/echo/v4 v4.13.4
require (
github.com/TwiN/go-color v1.4.1 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/labstack/echo v3.3.10+incompatible // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect

4
go.sum
View File

@@ -4,8 +4,12 @@ github.com/TwiN/go-color v1.4.1 h1:mqG0P/KBgHKVqmtL5ye7K0/Gr4l6hTksPgTgMk3mUzc=
github.com/TwiN/go-color v1.4.1/go.mod h1:WcPf/jtiW95WBIsEeY1Lc/b8aaWoiqQpu5cf8WFxu+s=
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/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f h1:dKccXx7xA56UNqOcFIbuqFjAWPVtP688j5QMgmo6OHU=
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f/go.mod h1:4rEELDSfUAlBSyUjPG0JnaNGjf13JySHFeRdD/3dLP0=
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/echo/v4 v4.13.4 h1:oTZZW+T3s9gAu5L8vmzihV7/lkXGZuITzTQkTEhcXEA=
github.com/labstack/echo/v4 v4.13.4/go.mod h1:g63b33BZ5vZzcIUF8AtRH40DrTlXnx4UMC8rBdndmjQ=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=

View File

@@ -10,6 +10,7 @@ import (
"os"
"path/filepath"
"gitea.elara.ws/Hazel/transfem-startpage/internal/utils"
"github.com/labstack/echo/v4"
)
@@ -23,7 +24,7 @@ func getCacheDir() (string, error) {
if err != nil {
baseDir = "/tmp"
}
cacheDir := filepath.Join(baseDir, "startpage")
cacheDir := filepath.Join(baseDir, utils.Name)
err = os.MkdirAll(cacheDir, 0o755)
if err != nil {
return "", err

View File

@@ -4,6 +4,7 @@ import (
"log"
"os"
"gitea.elara.ws/Hazel/transfem-startpage/internal/utils"
"github.com/TwiN/go-color"
)
@@ -22,8 +23,8 @@ type Argument struct {
Description string
}
var HelpHeader = `This is the help page of transfem-startpage.
` + color.Purple + `transfem-startpage {program} {...args}` + color.Reset + `
var HelpHeader = `This is the help page of ` + utils.Name + `.
` + color.Purple + utils.BinaryName + ` {program} {...args}` + color.Reset + `
The following Programs are available:`
var Programs = []Program{
{

View File

@@ -5,6 +5,7 @@ import (
"os"
"strings"
"gitea.elara.ws/Hazel/transfem-startpage/internal/utils"
"github.com/TwiN/go-color"
)
@@ -55,7 +56,7 @@ func specificHelp(programName string) error {
fmt.Println(color.Bold + "MAN PAGE FOR " + strings.ToUpper(programName) + color.Reset)
fmt.Println()
fmt.Println(color.Purple + "transfem-startpage " + programName + color.Reset + getArgumentString(program.Arguments))
fmt.Println(color.Purple + utils.BinaryName + " " + programName + color.Reset + getArgumentString(program.Arguments))
fmt.Println()
fmt.Println(color.Bold + "arguments" + color.Reset)

View File

@@ -1,7 +1,9 @@
package diyhrt
type DiyHrtConfig struct {
ApiKey string
ApiKey string
FetchIntervals int
StoreFilter StoreFilter
ListingFilter ListingFilter
}

View File

@@ -11,7 +11,7 @@ const endpoint = "https://diyhrt.market/api/listings"
func GetListings(apiKey string) ([]Listing, error) {
if apiKey == "" {
return nil, errors.New("API_KEY key not set. Set it as env or in DiyHrt.ApiKey")
return nil, errors.New("diyhrt API_KEY key not set. Set it as env or in DiyHrt.ApiKey")
}
// Create HTTP client

View File

@@ -7,6 +7,7 @@ import (
"path/filepath"
"gitea.elara.ws/Hazel/transfem-startpage/internal/diyhrt"
"gitea.elara.ws/Hazel/transfem-startpage/internal/utils"
"github.com/pelletier/go-toml"
)
@@ -62,7 +63,8 @@ func NewConfig() Config {
Port: 5500,
},
DiyHrt: diyhrt.DiyHrtConfig{
ApiKey: os.Getenv("API_KEY"),
ApiKey: os.Getenv("API_KEY"),
FetchIntervals: 60, // fetch every hour
StoreFilter: diyhrt.StoreFilter{
Limit: 0,
IncludeIds: []int{7},
@@ -105,7 +107,7 @@ func (rc *Config) ScanForConfigFile(profile string) error {
baseDir, cacheDirErr := os.UserConfigDir()
if cacheDirErr == nil {
configFile := filepath.Join(baseDir, "startpage", profileFile)
configFile := filepath.Join(baseDir, utils.Name, profileFile)
if err := rc.LoadConfigFile(configFile); !errors.Is(err, os.ErrNotExist) {
return err

View File

@@ -1,42 +0,0 @@
package server
import (
"bytes"
"embed"
"io/fs"
"log"
"net/http"
"text/template"
"github.com/labstack/echo/v4"
)
var FrontendFiles embed.FS
func getFileContent() string {
content, err := FrontendFiles.ReadFile("frontend/index.html")
if err != nil {
log.Fatal(err)
}
return string(content)
}
func getIndex(c echo.Context) error {
IndexTemplate := template.Must(template.New("index").Parse(getFileContent()))
var tpl bytes.Buffer
IndexTemplate.Execute(&tpl, Config.Template)
return c.HTML(http.StatusOK, tpl.String())
}
func getFileSystem() http.FileSystem {
fsys, err := fs.Sub(FrontendFiles, "frontend")
if err != nil {
panic(err)
}
return http.FS(fsys)
}

View File

@@ -3,50 +3,80 @@ package server
import (
"log"
"net/http"
"path/filepath"
"strconv"
"time"
"gitea.elara.ws/Hazel/transfem-startpage/internal/cache"
"gitea.elara.ws/Hazel/transfem-startpage/internal/rendering"
"github.com/labstack/echo/v4"
)
var Config = rendering.NewConfig()
func StartFetching() {
for {
log.Println("Fetch DiyHrt data...")
Config.FetchDiyHrt()
time.Sleep(time.Duration(Config.DiyHrt.FetchIntervals) * time.Second)
if Config.DiyHrt.FetchIntervals == 0 {
break
}
}
}
func GetFilepath(u string) string {
return filepath.Join("frontend", u)
}
func staticHandler(w http.ResponseWriter, r *http.Request) {
filepath := GetFilepath(r.URL.Path)
log.Println("serving file:", filepath)
http.ServeFileFS(w, r, FrontendFiles, filepath)
}
func Start(profile string) error {
err := Config.ScanForConfigFile(profile)
if err != nil {
return err
}
go StartFetching()
err = Config.FetchDiyHrt()
if err != nil {
log.Println(err)
}
e := echo.New()
http.HandleFunc("/static", staticHandler)
http.ListenAndServe(":"+strconv.Itoa(Config.Server.Port), nil)
// statically serve the file
cache := cache.NewCache(profile)
if !cache.Disabled {
cache.StartStaticServer(e)
/*
e := echo.New()
log.Println("downloading website icons...")
for i, w := range Config.Template.Websites {
u, err := cache.CacheUrl(w.ImageUrl)
if err != nil {
log.Println(err)
// statically serve the file
cache := cache.NewCache(profile)
if !cache.Disabled {
cache.StartStaticServer(e)
log.Println("downloading website icons...")
for i, w := range Config.Template.Websites {
u, err := cache.CacheUrl(w.ImageUrl)
if err != nil {
log.Println(err)
}
Config.Template.Websites[i].ImageUrl = u
Config.Template.Websites[i].IsFetched = true
}
Config.Template.Websites[i].ImageUrl = u
Config.Template.Websites[i].IsFetched = true
}
}
// https://echo.labstack.com/docs/cookbook/embed-resources
staticHandler := http.FileServer(getFileSystem())
e.GET("/assets/*", echo.WrapHandler(http.StripPrefix("/", staticHandler)))
e.GET("/scripts/*", echo.WrapHandler(http.StripPrefix("/", staticHandler)))
e.GET("/", getIndex)
// https://echo.labstack.com/docs/cookbook/embed-resources
staticHandler := http.FileServer(getFileSystem())
e.GET("/assets/*", echo.WrapHandler(http.StripPrefix("/", staticHandler)))
e.GET("/scripts/*", echo.WrapHandler(http.StripPrefix("/", staticHandler)))
e.GET("/", getIndex)
StartTemplating(e)
e.Logger.Fatal(e.Start(":" + strconv.Itoa(Config.Server.Port)))
e.Logger.Fatal(e.Start(":" + strconv.Itoa(Config.Server.Port)))
*/
return nil
}

View File

@@ -0,0 +1,80 @@
package server
import (
"bytes"
"embed"
"fmt"
"io"
"io/fs"
"log"
"net/http"
"path/filepath"
"text/template"
"github.com/labstack/echo/v4"
)
var FrontendFiles embed.FS
func getFileContent() string {
content, err := FrontendFiles.ReadFile("frontend/index.html")
if err != nil {
log.Fatal(err)
}
return string(content)
}
func getIndex(c echo.Context) error {
IndexTemplate := template.Must(template.New("index").Parse(getFileContent()))
var tpl bytes.Buffer
IndexTemplate.Execute(&tpl, Config.Template)
return c.HTML(http.StatusOK, tpl.String())
}
func getFileSystem() http.FileSystem {
fsys, err := fs.Sub(FrontendFiles, "frontend")
if err != nil {
panic(err)
}
return http.FS(fsys)
}
type Template struct {
templates *template.Template
}
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
return t.templates.ExecuteTemplate(w, name, data)
}
var t *template.Template
func ServeTemplate(c echo.Context) error {
filename := filepath.Base(c.Request().URL.Path)
if filename == "/" {
filename = "index.html"
}
fmt.Println(filename)
var tpl bytes.Buffer
t.ExecuteTemplate(&tpl, filename, Config.Template)
return c.HTML(http.StatusOK, tpl.String())
}
func StartTemplating(e *echo.Echo) {
// register templates as renderer
t = template.Must(template.ParseFS(
FrontendFiles,
"frontend/templates/*",
))
fmt.Println(t.ParseName)
e.GET("/*", ServeTemplate)
staticHandler := http.FileServer(getFileSystem())
e.GET("/static/*", echo.WrapHandler(http.StripPrefix("/", staticHandler)))
}

6
internal/utils/meta.go Normal file
View File

@@ -0,0 +1,6 @@
package utils
import "os"
var Name = "transfem-startpage"
var BinaryName = os.Args[0]

View File

@@ -1 +1 @@
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1