fuzzyworld

quantum-inspiration / commit

Adding a GitLab Pages page that shows all the articles and the chosen one.

0c14bc4fe175772d7d89e3751c4a9e51c4edaec3 · Pavel Safronov · 2023-09-06 15:31:18 -0700 · parents 15da5b5bbbcd

Adding a GitLab Pages page that shows all the articles and the chosen one.
Adding daily caching of wiki random articles.
 .gitignore        |  1 +
 .gitlab-ci.yml    | 11 ++++++--
 http-cache.go     | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 main.go           | 45 +++++++++++++++++++++++++++---
 public/index.html | 32 ++++++++++++++++++++++
 wiki.go           | 41 ++++++----------------------
 6 files changed, 172 insertions(+), 40 deletions(-)

diff --git a/.gitignore b/.gitignore
index 185145a..cbe2dfe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 cache/
 __debug_bin
+public/results.js
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c99721d..50eefd6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,7 +2,7 @@ image: golang:latest
 
 stages:
   - build-and-test
-  - run
+  - run-and-deploy
 
 before_script:
  - go version
@@ -14,7 +14,12 @@ build-job:
     - make build
     - make test
 
-run-job:
-  stage: run
+pages:
+  stage: run-and-deploy
   script:
     - make run
+  artifacts:
+    paths:
+      - public
+  only:
+    - main
\ No newline at end of file
diff --git a/http-cache.go b/http-cache.go
new file mode 100644
index 0000000..ccac112
--- /dev/null
+++ b/http-cache.go
@@ -0,0 +1,82 @@
+package main
+
+import (
+	"fmt"
+	"io"
+	"net/http"
+	"os"
+	"path/filepath"
+	"time"
+)
+
+func getCachedUrl(
+	url string,
+	id string,
+	cacheFileTimeFormat string,
+) ([]byte, error) {
+	return getCachedUrlFunc(url, id, cacheFileTimeFormat, func(bytes []byte) ([]byte, error) {
+		return bytes, nil
+	})
+}
+func getCachedUrlFunc(
+	url string,
+	id string,
+	cacheFileTimeFormat string,
+	byteProcessor func([]byte) ([]byte, error),
+) ([]byte, error) {
+	now := time.Now()
+	nowFormatted := now.Format(cacheFileTimeFormat)
+	cacheFile := fmt.Sprintf("cache/%s-%s.txt", id, nowFormatted)
+	dir := filepath.Dir(cacheFile)
+	_, err := os.Stat(dir)
+	dirExists := err == nil || !os.IsNotExist(err)
+	if !dirExists {
+		err = os.Mkdir(dir, 0755)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	_, err = os.Stat(cacheFile)
+	fileExists := err == nil || !os.IsNotExist(err)
+	if fileExists {
+		f, err := os.Open(cacheFile)
+		if err != nil {
+			return nil, err
+		}
+		defer f.Close()
+		bytes, err := io.ReadAll(f)
+		if err != nil {
+			return nil, err
+		}
+		return bytes, nil
+	} else {
+		resp, err := http.Get(url)
+		if err != nil {
+			return nil, err
+		}
+		defer resp.Body.Close()
+
+		body, err := io.ReadAll(resp.Body)
+		if err != nil {
+			return nil, err
+		}
+
+		body, err = byteProcessor(body)
+		if err != nil {
+			return nil, err
+		}
+
+		f, err := os.Create(cacheFile)
+		if err != nil {
+			return nil, err
+		}
+		defer f.Close()
+		_, err = f.Write(body)
+		if err != nil {
+			return nil, err
+		}
+
+		return body, nil
+	}
+}
diff --git a/main.go b/main.go
index a7a1994..eabb283 100644
--- a/main.go
+++ b/main.go
@@ -1,14 +1,51 @@
 package main
 
-import "fmt"
+import (
+	"encoding/json"
+	"fmt"
+	"os"
+	"time"
+)
+
+type Results struct {
+	CreationDate string
+	RandomNumber uint8
+	Pages        []WikiPage
+}
 
 func main() {
-	title, url, err := GetRandomWikiPage()
+	random256Pages, err := getRandomWikipediaPages(256)
 	if err != nil {
-		panic(err)
+		panic(fmt.Errorf("error getting random Wikipedia pages: %v", err))
+	}
+
+	randomNumbers, err := GetRandomNumbers(1)
+	if err != nil {
+		panic(fmt.Errorf("error getting random numbers: %v", err))
+	}
+
+	random := randomNumbers[0]
+
+	result := Results{
+		Pages:        random256Pages,
+		RandomNumber: random,
+		CreationDate: time.Now().Format("2006-01-02"),
+	}
+	resultJson, err := json.MarshalIndent(result, "", "  ")
+	if err != nil {
+		panic(fmt.Errorf("error marshalling results: %v", err))
+	}
+	completeJson := fmt.Sprintf("var results = %s;", resultJson)
+	outPath := "./public/results.js"
+	err = os.WriteFile(outPath, []byte(completeJson), 0644)
+	if err != nil {
+		panic(fmt.Errorf("error writing to %s: %v", outPath, err))
 	}
 
-	message := fmt.Sprintf("Quantum inspiration for the day: <a href='%s'>%s</a>", url, title)
+	page := random256Pages[random]
+	title := page.Title
+	url := page.Url
+	message := fmt.Sprintf("Quantum inspiration for the day: <a href='%s'>%s</a>\n\n<a href='https://pavelsafronov.gitlab.io/quantum-inspiration/'>More...</a>", url, title)
 	err = SendPushoverMessage(message)
 	if err != nil {
 		panic(err)
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..776453b
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Quantum Inspiration - Results</title>
+    </head>
+    <body>
+        <h1 id="header">Quantum Inspiration</h1>
+        <h2 id="subheader"></h2>
+        <div id="root"></div>
+        <script src="results.js"></script>
+        <script>
+            header.innerHTML = `Quantum Inspiration - ${results.CreationDate}`;
+
+            const chosenPage = results.Pages[results.RandomNumber];
+            subheader.innerHTML = `Today's randomly chosen page: <a href="#chosen">#${results.RandomNumber + 1}</a> - <a href="${chosenPage.Url}">${chosenPage.Title}</a>`;
+
+            results.Pages.forEach(function (page, index) {
+                var div = document.createElement('div');
+                div.innerHTML = `${index + 1} - <a href="${page.Url}">${page.Title}</a>`;
+
+                const isChosen = results.RandomNumber === index;
+                if (isChosen) {
+                    div.style.fontWeight = 'bold';
+                    div.id = 'chosen';
+                }
+
+                root.appendChild(div);
+            });
+        </script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/wiki.go b/wiki.go
index 3ae04da..636c985 100644
--- a/wiki.go
+++ b/wiki.go
@@ -3,29 +3,11 @@ package main
 import (
 	"encoding/json"
 	"fmt"
-	"io"
-	"net/http"
 )
 
-func GetRandomWikiPage() (title string, url string, err error) {
-	random256Pages, err := getRandomWikipediaPages(256)
-	if err != nil {
-		return "", "", fmt.Errorf("error getting random Wikipedia pages: %v", err)
-	}
-
-	randomNumbers, err := GetRandomNumbers(1)
-	if err != nil {
-		return "", "", fmt.Errorf("error getting random numbers: %v", err)
-	}
-
-	titles := []string{}
-	for title := range random256Pages {
-		titles = append(titles, title)
-	}
-	random := randomNumbers[0]
-	randomTitle := titles[random]
-	randomPage := random256Pages[randomTitle]
-	return randomTitle, randomPage, nil
+type WikiPage struct {
+	Title string
+	Url   string
 }
 
 type WikipediaResponse struct {
@@ -39,18 +21,12 @@ type WikipediaResponse struct {
 	} `json:"query"`
 }
 
-func getRandomWikipediaPages(count int) (nameToUrlMap map[string]string, err error) {
+func getRandomWikipediaPages(count int) (pages []WikiPage, err error) {
 	url := fmt.Sprintf("https://en.wikipedia.org/w/api.php?format=json&action=query&generator=random&grnnamespace=0&grnlimit=%d", count)
-	resp, err := http.Get(url)
+	body, err := getCachedUrl(url, "wikipedia-randoms", "2006-01-02-15")
 	if err != nil {
 		return nil, fmt.Errorf("error fetching Wikipedia pages: %v", err)
 	}
-	defer resp.Body.Close()
-
-	body, err := io.ReadAll(resp.Body)
-	if err != nil {
-		return nil, fmt.Errorf("error reading Wikipedia response: %v", err)
-	}
 
 	var wikiResponse WikipediaResponse
 	err = json.Unmarshal(body, &wikiResponse)
@@ -58,13 +34,12 @@ func getRandomWikipediaPages(count int) (nameToUrlMap map[string]string, err err
 		return nil, fmt.Errorf("error unmarshalling Wikipedia JSON: %v", err)
 	}
 
-	nameToUrlMap = map[string]string{}
+	pages = []WikiPage{}
 	for pageID := range wikiResponse.Query.Pages {
 		title := wikiResponse.Query.Pages[pageID].Title
 		url := fmt.Sprintf("http://en.m.wikipedia.org/?curid=%s", pageID)
-		nameToUrlMap[title] = url
-		fmt.Printf("title: %s, url: %s\n", title, url)
+		pages = append(pages, WikiPage{Title: title, Url: url})
 	}
 
-	return nameToUrlMap, nil
+	return pages, nil
 }