feat: drop bunnycdn
@@ -1,8 +1,6 @@
|
||||
services:
|
||||
lilou-cat:
|
||||
image: pihkaal/lilou-cat:latest
|
||||
environment:
|
||||
- API_KEY
|
||||
networks:
|
||||
- web
|
||||
labels:
|
||||
|
||||
76
main.go
@@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -10,66 +9,40 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:embed public/index.html
|
||||
var indexSrc string
|
||||
|
||||
const PORT = 3000
|
||||
const CACHE_TTL = 5 * time.Minute
|
||||
const STORAGE_URL = "https://storage.bunnycdn.com/lilou-cat/"
|
||||
const CDN_URL = "https://lilou-cat.b-cdn.net/"
|
||||
const IMAGES_DIR = "images"
|
||||
|
||||
type Image struct {
|
||||
ObjectName string
|
||||
}
|
||||
var cachedImages []string
|
||||
|
||||
var (
|
||||
cachedImages []string
|
||||
cacheExpiration time.Time
|
||||
)
|
||||
func loadImages() error {
|
||||
imagesDir := fmt.Sprintf("public/%s", IMAGES_DIR)
|
||||
|
||||
func list_images() []string {
|
||||
if time.Now().Before(cacheExpiration) {
|
||||
return cachedImages
|
||||
}
|
||||
|
||||
req, _ := http.NewRequest("GET", STORAGE_URL, nil)
|
||||
|
||||
req.Header.Add("Accept", "application/json")
|
||||
req.Header.Add("AccessKey", os.Getenv("API_KEY"))
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
entries, err := os.ReadDir(imagesDir)
|
||||
if err != nil {
|
||||
fmt.Printf("error: %s\n", err)
|
||||
return []string{}
|
||||
return fmt.Errorf("ERROR: Failed to read public/%s directory: %w", IMAGES_DIR, err)
|
||||
}
|
||||
|
||||
var images = []Image{}
|
||||
cachedImages = []string{}
|
||||
|
||||
err = json.NewDecoder(res.Body).Decode(&images)
|
||||
defer res.Body.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("error: %s\n", err)
|
||||
return []string{}
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".webp") {
|
||||
cachedImages = append(cachedImages, entry.Name())
|
||||
}
|
||||
}
|
||||
|
||||
var imageUrls = []string{}
|
||||
for _, image := range images {
|
||||
imageUrls = append(imageUrls, fmt.Sprintf("%s/%s", CDN_URL, image.ObjectName))
|
||||
}
|
||||
|
||||
cachedImages = imageUrls
|
||||
cacheExpiration = time.Now().Add(CACHE_TTL)
|
||||
|
||||
return imageUrls
|
||||
fmt.Printf("OK: Loaded %d images\n", len(cachedImages))
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPage(w http.ResponseWriter, r *http.Request) {
|
||||
var images = list_images()
|
||||
var image = images[rand.Intn(len(images))]
|
||||
src := strings.Replace(indexSrc, "{{ IMAGE_URL }}", image, 1)
|
||||
imageName := cachedImages[rand.Intn(len(cachedImages))]
|
||||
imageURL := fmt.Sprintf("/%s/%s", IMAGES_DIR, imageName)
|
||||
src := strings.Replace(indexSrc, "{{ IMAGE_URL }}", imageURL, 1)
|
||||
|
||||
io.WriteString(w, src)
|
||||
}
|
||||
@@ -79,15 +52,26 @@ func getFavicon(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := loadImages(); err != nil {
|
||||
fmt.Printf("ERROR: Error loading images: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if len(cachedImages) == 0 {
|
||||
fmt.Printf("ERROR: no images found in public/%s\n", IMAGES_DIR)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
http.HandleFunc("/", getPage)
|
||||
http.HandleFunc("/favicon.ico", getFavicon)
|
||||
http.Handle(fmt.Sprintf("/%s/", IMAGES_DIR), http.StripPrefix(fmt.Sprintf("/%s/", IMAGES_DIR), http.FileServer(http.Dir(fmt.Sprintf("public/%s", IMAGES_DIR)))))
|
||||
|
||||
fmt.Printf("OK: Listening on port %d\n", PORT)
|
||||
err := http.ListenAndServe(fmt.Sprintf(":%d", PORT), nil)
|
||||
fmt.Printf("listening on port %d\n", PORT)
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
fmt.Printf("server closed\n")
|
||||
fmt.Printf("OK: Server closed\n")
|
||||
} else if err != nil {
|
||||
fmt.Printf("error starting server: %s\n", err)
|
||||
fmt.Printf("ERROR: error starting server: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
BIN
public/images/002e29d556302d5858384de23e17ba38.webp
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
public/images/044edf7f26a23767a8675901fb8b3046.webp
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
public/images/07e311ec1ec115a529a14ce41ae1c10b.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/images/0821756bc4bae4cb9919a01aabfd0be2.webp
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
public/images/09430d5ffbeef4534bc8c8842fb8adcf.webp
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
public/images/0e72ba0bac1e1bb9bee6d8a7ebb57d34.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/images/0e9ab8ea0e973f31c38352f61e130e89.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/images/1386a2f0249a9299a5af49e66278f4c3.webp
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/images/1792014678d5827950badf3fccbf7120.webp
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
public/images/1b798a781625c1d459760dee450c80b5.webp
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
public/images/20bbfa996a79559b50f3529ffba77500.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/images/24ffd4b4d2f9bf84e68b2bee5853b582.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/images/281d950c92ac409642b0b840e9992d1d.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/images/292c73ff0ca23955fcf976e9e6616325.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/images/2cbad5faf546b6db148200a38b7b0fda.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/images/2f69b2a9f0952aa39fd2a78260c87fed.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/images/3046890b4423306d9daf9159983eb993.webp
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
public/images/328ad7a9ea335cd6cd16bdd9a591a82d.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
public/images/33ac9b0d3e136bb51838df766b9b2604.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/images/36baa3a948bd6d6940910a3921915da1.webp
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
public/images/38815cf794fd73c13d1bbb30b5626a3a.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
public/images/3a9ae801d732134e562adb5caa1d1bea.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
public/images/3b8aed92be5f56e5d248b4debe00ec57.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/images/3f9bd72c815d104c45357a5a7f848eb0.webp
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
public/images/4542d90ee99d9067c48527e2434eedfb.webp
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
public/images/467a545b9695232e33816de609b1ab66.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/images/47ed1ae3e4c0b79653422eb628b673dd.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/images/485535a2423942c7a650d21442edea0a.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/images/4b4418295f0ea5e576392f535346ddd4.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/images/4b67419a282f04e49e66ef5cd575272d.webp
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
public/images/4da9e40b99532ea41bd47742c5905ce7.webp
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
public/images/4df93962dfc4d27932a0c0d7d6168da9.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
public/images/55557db4fee8cea0770c0a60f80266f3.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/images/5bff76ba10b1a87882be33595434f164.webp
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/images/64ac3ed82df29cc7cd6045501afc42b4.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/images/667a0f811a1457cc1e94ec0638ab81f9.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/images/69ada673c7c190cba4b3c5104d65985f.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/images/6ff5ae5845175a214b07bd3bc246828c.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/images/702bbcf8b9357dc5fe83506d09f77662.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/images/70b8055685df3cecf8267c1edc8c2f9a.webp
Normal file
|
After Width: | Height: | Size: 185 KiB |
BIN
public/images/725a3eab0c243eee5811f1f06f4dd355.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/images/72ba6830f131d95f3325246b299f7976.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/images/8216920a69350fbbd7083dbdd39d8099.webp
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
public/images/8c55a36b68d07d546e8abdce69e56584.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/images/8f620d0eb9bf45817f7fc7f64606d094.webp
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
public/images/9059598a62c79773fd4dc10249ff2b16.webp
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
public/images/97a803c121e9462720d6ef9815af7318.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/images/97c4be30d60e73d6f4b8e7c2f308e27a.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
public/images/9cf7428258c3cb7b36aa456b674e6cb8.webp
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
public/images/a2f560c300bcfe7dc6685dab8ae82c93.webp
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/images/a32cc7f3475b202db8809fef2a0b1d0e.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
public/images/a3ab23d5b4b0733a74f7bccb35ea84fb.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/images/a454a38388adeb64c0f200e80a3f8d36.webp
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
public/images/a5022aaf712d0a507dddc7a205786b6d.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/images/a6e4b08a66d604d4aa8c3ef9b50d80df.webp
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
public/images/ab5f25e4a6d216c1fb261a1d3638d954.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/images/aba00ab171781a211e8edc4fb6649679.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/images/b5483ebf313f2522e8c486362d24f1c7.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/images/b5be61f4c83c35934c0387c580c23c6b.webp
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/images/bd178b01414754d8d3177423a2b51886.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/images/bfa2a5735244b17b5542ef676f267e9a.webp
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/images/c00b6cd4f2247bd659e3f99b5efb55ec.webp
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
public/images/c39dc10dfd5f76ef460f2697ebc59d3c.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/images/c5f57f9c2dec0dfb016c813aa5b21584.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/images/c8678ed7a73d50fcdc1aa2a3111ad213.webp
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/images/cc10681f11250849df9951f0262e3971.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/images/cc63b5bfd396d9d703b09f26c6d18783.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/images/cde954c7b14b657502b1b06cc0e49413.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/images/d07d978160cb445487d58f534a3660b3.webp
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
public/images/d0816a70521e03089c9407951562be16.webp
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
public/images/d3bee103cb0b354255be488bae06200b.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/images/d4a0d4e2c4c18a2984a2a3d691c3fe37.webp
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
public/images/e3debbf1724b1f2eaaec0f6d3b0abea7.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
public/images/e91a49aaf434208f8bf211da933d7b07.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/images/f3fad4b78ee3ab3749aa32fea8dcaa6c.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/images/f7818fcb320072eb1d54f439810b3814.webp
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
public/images/f7abfd952b526d501175d636b551d138.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
public/images/f8ee0861cb1d78c69cb3e5bd4f0cbe9f.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/images/faecf59bc6eff5a773819026c73a32ae.webp
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/images/faf4574c01166d3c8195cd5f559ae913.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/images/fc65e6bf4ee17b4f096d1cff6f5bc835.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
@@ -87,6 +87,7 @@
|
||||
img {
|
||||
width: 100%;
|
||||
max-width: 50vh;
|
||||
rotate: 90deg;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
|
||||