commit 0e949bb56ff9aedd9b8b9c46d1a7e4ff44c2bb2b Author: dreamer Date: Sun Oct 12 21:35:48 2025 +0200 first diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7ef0637 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +# FROM mileschou/lapis:alpine as wasted.audio +FROM openresty/openresty:1.27.1.2-4-alpine-fat + +ENV LAPIS_VERSION=1.16.0 + +RUN apk add openssl-dev git +RUN opm get spacewander/luafilesystem +RUN luarocks install luasec +RUN luarocks install busted +RUN luarocks install --check-lua-versions markov-text +RUN luarocks install lapis ${LAPIS_VERSION} +RUN luarocks install moonscript + +WORKDIR /srv/lapis + +CMD lapis server $ENVIRONMENT diff --git a/code/app.lua b/code/app.lua new file mode 100644 index 0000000..d574feb --- /dev/null +++ b/code/app.lua @@ -0,0 +1,32 @@ +local lapis = require("lapis") +local config = require("lapis.config").get() +local json_params = require("lapis.application").json_params + +local app = lapis.Application() +app:enable("etlua") +app.layout = require "views.layout" + +local autoload = require("lapis.util").autoload +local handlers = autoload("handlers") + +local page_titles = { + name = "DRMR", + url = "drmr.nl" +} + +app:get("/", function(self) + self.titles = page_titles + return handlers.Roothandler(self) +end) + +app:get("videos", "/videos", function(self) + self.titles = page_titles + return handlers.Videohandler(self) +end) + +app:get("links", "/links", function(self) + self.titles = page_titles + return handlers.Linkhandler(self) +end) + +return app diff --git a/code/config.lua b/code/config.lua new file mode 100644 index 0000000..ec362ce --- /dev/null +++ b/code/config.lua @@ -0,0 +1,22 @@ +local config = require("lapis.config") +config({"development", "production"}, { + host = "drmr.nl", + greeting = "Totally Wasted", + mount = "/mnt/data/", + postgres = { + host = "postgres", + user = "postgres", + password = "the_password", + database = "postgres" + } +}) + +config("production", { + greeting = "nothing here yet", + postgres = { + password = os.getenv('POSTGRES_PASSWORD') + }, + logging = { + queries = false + } +}) diff --git a/code/drmr/utils.lua b/code/drmr/utils.lua new file mode 100644 index 0000000..80a6c54 --- /dev/null +++ b/code/drmr/utils.lua @@ -0,0 +1,55 @@ +local lfs = require("lfs_ffi") +local cjson = require("cjson") + +local utils = {} + +-- we want to list the contents of a dir +function utils:dirlist( path ) + local files, dirs, images, audio = {}, {}, {}, {} + for file in lfs.dir( path ) do + local filepath = path .. "/" .. file + local attribute = lfs.attributes( filepath, "mode" ) or "nil" + if file ~= "." and file ~= ".." and not string.match(file, ".filepart") then + if lfs.attributes( filepath, "mode" ) == "file" then + if utils:match_image( file ) then + table.insert( images, file ) + elseif utils:match_audio( file) then + table.insert( audio, file ) + else + table.insert( files, file ) + end + elseif lfs.attributes( filepath, "mode" ) == "directory" then + table.insert( dirs, file ) + end + end + end + + table.sort( images ) + table.sort( files ) + table.sort( dirs ) + table.sort( audio ) + + local stuff = { + files = files, + dirs = dirs, + images = images, + audio = audio + } + return stuff +end + +-- open a json file and return the table +function utils:opendata( path ) + local data = io.open(path) + if data then + local data_file = data:read("a") + data:close() + local data_decode = cjson.decode(data_file) + + return data_decode + else + return nil + end +end + +return utils diff --git a/code/handlers/linkhandler.lua b/code/handlers/linkhandler.lua new file mode 100644 index 0000000..f03c4ab --- /dev/null +++ b/code/handlers/linkhandler.lua @@ -0,0 +1,14 @@ +local autoload = require("lapis.util").autoload +local config = require("lapis.config").get() + +local utils = require("drmr.utils") + +local drmr = autoload("drmr") + +local function Linkhandler(self) + self.promo = utils:opendata(config.mount .. "promo.json") + + return { render = "links"} +end + +return Linkhandler diff --git a/code/handlers/roothandler.lua b/code/handlers/roothandler.lua new file mode 100644 index 0000000..914ae87 --- /dev/null +++ b/code/handlers/roothandler.lua @@ -0,0 +1,24 @@ +local autoload = require("lapis.util").autoload +local config = require("lapis.config").get() + +local utils = require("drmr.utils") + +local drmr = autoload("drmr") + +local function Roothandler(self) + + + local function compare( a, b ) + if a.stop == "current" or b.stop == "current" then + return b.start < a.start + end + return a.stop > b.stop + end + -- table.sort(unsort_career.career, compare) + + self.promo = utils:opendata(config.mount .. "promo.json") + + return { render = "root"} +end + +return Roothandler diff --git a/code/handlers/videohandler.lua b/code/handlers/videohandler.lua new file mode 100644 index 0000000..45b5154 --- /dev/null +++ b/code/handlers/videohandler.lua @@ -0,0 +1,15 @@ +local autoload = require("lapis.util").autoload +local config = require("lapis.config").get() + +local utils = require("drmr.utils") + +local drmr = autoload("drmr") + +local function Videohandler(self) + + self.videos = utils:opendata(config.mount .. "videos.json") + + return { render = "video"} +end + +return Videohandler diff --git a/code/mime.types b/code/mime.types new file mode 100644 index 0000000..20a2850 --- /dev/null +++ b/code/mime.types @@ -0,0 +1,83 @@ +types { + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/x-lua lua; + application/x-moonscript moon; + application/x-javascript js; + application/atom+xml atom; + application/rss+xml rss; + application/json json; + application/x-bittorrent torrent; + + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; + + image/png png; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; + image/svg+xml svg svgz; + image/webp webp; + + application/java-archive jar war ear; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.ms-excel xls; + application/vnd.ms-powerpoint ppt; + application/vnd.wap.wmlc wmlc; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/zip zip; + + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream eot; + application/octet-stream iso img; + application/octet-stream msi msp msm; + + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; + + video/3gpp 3gpp 3gp; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; +} diff --git a/code/nginx.conf b/code/nginx.conf new file mode 100644 index 0000000..e03a7bb --- /dev/null +++ b/code/nginx.conf @@ -0,0 +1,50 @@ +worker_processes ${{NUM_WORKERS}}; +error_log stderr notice; +daemon off; +pid logs/nginx.pid; + +env POSTGRES_PASSWORD; +env STATION_SECRET_1; +env STATION_SECRET_2; +env STATION_SECRET_3; + +events { + worker_connections 1024; +} + +http { + include mime.types; + resolver 127.0.0.11; + + init_by_lua_block { + require("socket") + require("lpeg") + math.randomseed(os.time()+ngx.worker.id()) + } + + server { + listen ${{PORT}}; + lua_code_cache ${{CODE_CACHE}}; + + add_header Access-Control-Allow-Origin *; + + location /data/ { + root /mnt; + } + + location /static/ { + alias static/; + } + + location / { + default_type text/html; + content_by_lua_block { + require("lapis").serve("app") + } + } + + location /favicon.ico { + alias static/favicon.ico; + } + } +} diff --git a/code/static/favicon.ico b/code/static/favicon.ico new file mode 100644 index 0000000..7f123a1 Binary files /dev/null and b/code/static/favicon.ico differ diff --git a/code/static/style.css b/code/static/style.css new file mode 100644 index 0000000..a49498d --- /dev/null +++ b/code/static/style.css @@ -0,0 +1,308 @@ +* { + box-sizing: border-box; +} + +:root { + --main-bg-color: #222222; + --base-bg-color: #111111; + --text-color: #9d9d9d; + --wstd-green: #28a07d; + --wstd-yellow: #d5af14; + --wstd-blue: #186da1; + --wstd-red: #FF473D; + --wstd-purple: #662042; +} + +body { + width: 95%; + padding-left: 0%; + padding-right: 0%; + background-color: var(--main-bg-color); + font-family: monospace; + display: flex; + flex-direction: column; +} + +.footer { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 5px 12px; +} + +.p +{ + color: #7e7e7e; + margin-bottom: 45px; + font-size: 10px; +} + +.nav_bar { + width: 90%; + font-size: 12px; + margin: auto; + text-align: center; + color: var(--text-color); + font-weight: 600; +} + +.nav_drmr { + text-decoration: none; + background: var(--base-bg-color); + display: inline-flex; + margin: 4px; + padding: 5px 12px; +} + +.nav_drmr:hover { + animation: pulse 1.5s infinite; +} + +.ascii +{ + vertical-align: center; + background: var(--base-bg-color); + display: inline-flex; + flex-wrap: wrap; + justify-content: space-evenly; + margin: 4px; + padding: 5px 12px; + border-radius: 20px; + color: var(--text-color); + line-height: 1.1em; + white-space: pre; + text-align:left; + user-select: none; +} + + +/* == root page == */ +.root +{ + width: 90%; + margin-top: 20px; + margin-bottom: 40px; + display: flex; + justify-content: space-evenly; +} + +.rootcontainer +{ + width: 100%; + float: left; + clear: both; + justify-content: space-evenly; + flex-wrap: wrap; +} + +.roottext +{ + text-align: center; + color: var(--text-color); + font-weight: 600; + font-size: 10px; + text-decoration: none; + background: var(--base-bg-color); + /* display: inline-flex; */ + /* margin: 4px; */ + padding: 5px 12px; + border-radius: 20px; + /* column-count: 2; */ + margin: auto; + margin-top: 20px; + margin-bottom: 40px; + float: center; + clear: both; + display: flex; + width: 250px; + justify-content: space-evenly; +} + +.rootdesc +{ + text-align: center; + color: var(--text-color); + font-weight: 600; + font-size: 13px; + text-decoration: none; + background: var(--base-bg-color); + padding: 5px 12px; + border-radius: 20px; + margin: auto; + margin-top: 20px; + margin-bottom: 40px; + float: center; + clear: both; + display: flex; + width: 300px; + justify-content: space-evenly; + white-space: pre-line; + user-select: none; +} + +.videos +{ + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; +} + +.releasevideo +{ + height: 220px; + width: 350px; + color: var(--text-color); + font-weight: 600; + font-size: 10px; + text-decoration: none; + background: var(--base-bg-color); + display: inline-flex; + margin: 4px; + padding: 15px 12px; + border-radius: 20px; +} + +.releaseembed +{ + max-height:185px; + max-width:330px; + width: auto; + height: auto; + margin: 5px; + border-radius: 15px; + object-fit: cover; + overflow: hidden; +} + +.ytembed +{ + height: 185px; + width: 330px; +} + +.link, .link:visited +{ + color: inherit; + text-decoration: none; +} + +.rootdesc:hover { + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0% { + -webkit-box-shadow: 0 0 0 0 rgba(40, 160, 125, 1); + } + + 70% { + -webkit-box-shadow: 0 0 0 10px rgba(255, 0, 0, 0); + } + + 100% { + -webkit-box-shadow: 0 0 0 0 rgba(255, 0, 0, 0); + } +} + +@media screen and (min-width: 600px) { + body { + padding-left: 5%; + padding-right: 5%; + } + + .ascii { + font-size: 14px; + } + + .roottext { + font-size: 12px; + width: 300px; + } + + .rootdesc { + font-size: 15px; + width: 450px; + } + + .nav_bar { + font-size: 16px; + } + + .releasevideo + { + height: 280px; + min-width:460px; + font-size: 12px; + margin: 5px; + } + + .releaseembed + { + max-height:247px; + max-width:440px; + width: auto; + height: auto; + margin: 5px; + border-radius: 15px; + object-fit: cover; + overflow: hidden; + } + + .ytembed + { + height: 247px; + width: 440px; + } +} + +@media screen and (min-width: 768px) { + body { + padding-left: 10%; + padding-right: 10%; + } + + .ascii { + font-size: 17px; + } + + .roottext { + font-size: 15px; + width: 350px; + } + + .rootdesc { + font-size: 18px; + width: 550px; + } + + .nav_bar { + font-size: 20px; + } + + .releasevideo + { + height: 350px; + min-width: 580px; + margin: 6px; + font-size: 14px; + } + + .releaseembed + { + max-height:315px; + max-width:560px; + width: auto; + height: auto; + margin: 5px; + border-radius: 15px; + object-fit: cover; + overflow: hidden; + } + + .ytembed + { + height: 315px; + width: 560px; + } +} diff --git a/code/views/about.etlua b/code/views/about.etlua new file mode 100644 index 0000000..adbb3a1 --- /dev/null +++ b/code/views/about.etlua @@ -0,0 +1,5 @@ +
+ <% for i, item in ipairs(promo.description) do %> + <%= item %>
+ <% end %> +
diff --git a/code/views/layout.etlua b/code/views/layout.etlua new file mode 100644 index 0000000..f25ed53 --- /dev/null +++ b/code/views/layout.etlua @@ -0,0 +1,25 @@ + + + + <%= titles['name'] %> + <% if title then %> + - <%= title %> + <% end %> + + + + + + +
+
+ + <% render("views.navigation") %> + <% content_for("inner") %> + +
bookings <at> puikheid.nl
+
+
+ + + diff --git a/code/views/links.etlua b/code/views/links.etlua new file mode 100644 index 0000000..9f1fcdd --- /dev/null +++ b/code/views/links.etlua @@ -0,0 +1,7 @@ + <% for i, item in ipairs(promo.links) do %> + +
+ <%= item.name %>
+
+
+ <% end %> diff --git a/code/views/navigation.etlua b/code/views/navigation.etlua new file mode 100644 index 0000000..3362bad --- /dev/null +++ b/code/views/navigation.etlua @@ -0,0 +1,17 @@ +
  • +________ __________ _____ __________ +\______ \\______ \ / \\______ \ + | | \| _/ / \ / \| _/ + | ` \ | \/ Y \ | \ +/_______ /____|_ /\____|__ /____|_ / + \/ \/ \/ \/ +
  • +
    + + + +
    diff --git a/code/views/root.etlua b/code/views/root.etlua new file mode 100644 index 0000000..c99e75b --- /dev/null +++ b/code/views/root.etlua @@ -0,0 +1,5 @@ +
    + <% for i, item in ipairs(promo.description) do %> + <%= item %>
    + <% end %> +
    diff --git a/code/views/video.etlua b/code/views/video.etlua new file mode 100644 index 0000000..8d69e69 --- /dev/null +++ b/code/views/video.etlua @@ -0,0 +1,20 @@ +
    + + <% for i, item in ipairs(videos.videos) do %> +
    +
    + +
    +
    + <% end %> + +
    diff --git a/docker-compose-local.yaml b/docker-compose-local.yaml new file mode 100644 index 0000000..a15cdfa --- /dev/null +++ b/docker-compose-local.yaml @@ -0,0 +1,26 @@ +services: + drmr.nl: + environment: + - ENVIRONMENT + build: . + networks: + - web + volumes: + - ./code:/srv/lapis + - /media/drmr.nl:/mnt/data + labels: + - traefik.enable=true + - traefik.http.routers.wasted.rule=Host(`drmr.nl`) + - traefik.http.routers.wasted.entrypoints=web + - traefik.http.routers.wasted.middlewares=redirect-https-wasted + - traefik.http.middlewares.redirect-https-wasted.redirectscheme.scheme=https + + - traefik.http.routers.wasted_ssl.rule=Host(`drmr.nl`) + - traefik.http.routers.wasted_ssl.entrypoints=websecure + - traefik.http.routers.wasted_ssl.tls.certresolver=myresolver + + - traefik.http.services.wasted.loadbalancer.server.port=8080 + +networks: + web: + external: true diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..6af3e65 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,16 @@ +services: + drmr.nl: + environment: + - ENVIRONMENT + build: . + networks: + - web + volumes: + - ./code:/srv/lapis + - ./_assets:/mnt/data + ports: + - "8083:8080" + +networks: + web: + external: true