]> git.taranathan.com Git - filestuffs.git/commitdiff
wowza
authorTaran Nathan <moogoesmeow123@gmail.com>
Thu, 11 Jun 2026 03:40:08 +0000 (23:40 -0400)
committerTaran Nathan <moogoesmeow123@gmail.com>
Thu, 11 Jun 2026 03:40:15 +0000 (23:40 -0400)
12 files changed:
.github/workflows/test.yml [new file with mode: 0644]
.gitignore [new file with mode: 0644]
README.md [new file with mode: 0644]
files/focus.sh [new file with mode: 0644]
files/test.txt [new file with mode: 0644]
gleam.toml [new file with mode: 0644]
manifest.toml [new file with mode: 0644]
src/preview.gleam [new file with mode: 0644]
src/router.gleam [new file with mode: 0644]
static/form.html [new file with mode: 0644]
static/styles.css [new file with mode: 0644]
test/preview_test.gleam [new file with mode: 0644]

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644 (file)
index 0000000..eb4a679
--- /dev/null
@@ -0,0 +1,23 @@
+name: test
+
+on:
+  push:
+    branches:
+      - master
+      - main
+  pull_request:
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v6
+      - uses: erlef/setup-beam@v1
+        with:
+          otp-version: "28"
+          gleam-version: "1.16.0"
+          rebar3-version: "3"
+          # elixir-version: "1"
+      - run: gleam deps download
+      - run: gleam test
+      - run: gleam format --check src test
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..599be4e
--- /dev/null
@@ -0,0 +1,4 @@
+*.beam
+*.ez
+/build
+erl_crash.dump
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..6be9ddc
--- /dev/null
+++ b/README.md
@@ -0,0 +1,24 @@
+# preview
+
+[![Package Version](https://img.shields.io/hexpm/v/preview)](https://hex.pm/packages/preview)
+[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/preview/)
+
+```sh
+gleam add preview@1
+```
+```gleam
+import preview
+
+pub fn main() -> Nil {
+  // TODO: An example of the project in use
+}
+```
+
+Further documentation can be found at <https://hexdocs.pm/preview>.
+
+## Development
+
+```sh
+gleam run   # Run the project
+gleam test  # Run the tests
+```
diff --git a/files/focus.sh b/files/focus.sh
new file mode 100644 (file)
index 0000000..19de0b8
--- /dev/null
@@ -0,0 +1,19 @@
+regex='(YouTube|: r\/|Reddit|Lunar)'
+
+while true; do
+  # get window name (trim trailing newline)
+  name="$(kdotool getactivewindow getwindowname 2>/dev/null | tr -d '\r\n')"
+
+  if [[ -z "$name" ]]; then
+    sleep 1
+    continue
+  fi
+
+  if [[ "$name" =~ $regex ]]; then
+    echo "Match: $name"
+    notify-send "naughty boy"
+    # exit 0
+  fi
+
+  sleep 1
+done
diff --git a/files/test.txt b/files/test.txt
new file mode 100644 (file)
index 0000000..3fea1b8
--- /dev/null
@@ -0,0 +1,3 @@
+hello!
+
+bazinga!
diff --git a/gleam.toml b/gleam.toml
new file mode 100644 (file)
index 0000000..acf4aa9
--- /dev/null
@@ -0,0 +1,30 @@
+name = "preview"
+version = "1.0.0"
+
+# Fill out these fields if you intend to generate HTML documentation or publish
+# your project to the Hex package manager.
+#
+# description = ""
+# licences = ["Apache-2.0"]
+# repository = { type = "github", user = "", repo = "" }
+# links = [{ title = "Website", href = "" }]
+#
+# For a full reference of all the available options, you can have a look at
+# https://gleam.run/writing-gleam/gleam-toml/.
+
+[dependencies]
+gleam_stdlib = ">= 1.0.0 and < 2.0.0"
+argv = ">= 1.1.0 and < 2.0.0"
+gleam_erlang = ">= 1.3.0 and < 2.0.0"
+gleam_http = ">= 4.3.0 and < 5.0.0"
+logging = ">= 1.5.0 and < 2.0.0"
+wisp = ">= 2.2.2 and < 3.0.0"
+gleam_otp = ">= 1.2.0 and < 2.0.0"
+gleam_json = ">= 3.1.0 and < 4.0.0"
+gleam_time = ">= 1.8.0 and < 2.0.0"
+simplifile = ">= 2.4.0 and < 3.0.0"
+mist = ">= 6.0.3 and < 7.0.0"
+
+[dev_dependencies]
+gleeunit = ">= 1.0.0 and < 2.0.0"
+gleescript = ">= 1.5.2 and < 2.0.0"
diff --git a/manifest.toml b/manifest.toml
new file mode 100644 (file)
index 0000000..717b1ae
--- /dev/null
@@ -0,0 +1,46 @@
+# This file was generated by Gleam
+# You typically do not need to edit this file
+
+packages = [
+  { name = "argv", version = "1.1.0", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "3277D100448BDB4A29B6D58C0F36F631CBC349E8BDD09766C6309DF202831140" },
+  { name = "directories", version = "1.2.0", build_tools = ["gleam"], requirements = ["envoy", "gleam_stdlib", "platform", "simplifile"], otp_app = "directories", source = "hex", outer_checksum = "D13090CFCDF6759B87217E8DDD73A75903A700148A82C1D33799F333E249BF9E" },
+  { name = "envoy", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "9C6FBB6BFA02A52798BEEC5977A738CAD6E4A057F4B67FD0C8061AD2502C191A" },
+  { name = "exception", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "329D269D5C2A314F7364BD2711372B6F2C58FA6F39981572E5CA68624D291F8C" },
+  { name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
+  { name = "gleam_crypto", version = "1.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "2DE9E4EF53CF6FEE049D4F765731F7178F7A11AEFAE00EEE63BF7536B354AD3F" },
+  { name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" },
+  { name = "gleam_http", version = "4.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "82EA6A717C842456188C190AFB372665EA56CE13D8559BF3B1DD9E40F619EE0C" },
+  { name = "gleam_json", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "44FDAA8847BE8FC48CA7A1C089706BD54BADCC4C45B237A992EDDF9F2CDB2836" },
+  { name = "gleam_otp", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "BA6A294E295E428EC1562DC1C11EA7530DCB981E8359134BEABC8493B7B2258E" },
+  { name = "gleam_stdlib", version = "1.0.3", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "1F543AFBA5D33DA493E6087F4E4C4F20D899411343512686C98A8ABB2963CF22" },
+  { name = "gleam_time", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "533D8723774D61AD4998324F5DD1DABDCDBFABAFB9E87CB5D03C6955448FC97D" },
+  { name = "gleescript", version = "1.5.2", build_tools = ["gleam"], requirements = ["argv", "filepath", "gleam_erlang", "gleam_stdlib", "simplifile", "snag", "tom"], otp_app = "gleescript", source = "hex", outer_checksum = "27AC58481742ED29D9B37C506F78958A8AD798750A79ED08C8F8AFBA8F23563B" },
+  { name = "gleeunit", version = "1.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "EC31ABA74256AEA531EDF8169931D775BBB384FED0A8A1BDC4DD9354E3E21826" },
+  { name = "glisten", version = "9.0.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging"], otp_app = "glisten", source = "hex", outer_checksum = "7795AA50830656F3A0316A6B26595F893C83272DA901B3405E31339CAA31A10B" },
+  { name = "gramps", version = "6.0.1", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "D55636072DEE173F6586A5679D3C02EC7A0DE3F8646B78C351B72908FF223DF7" },
+  { name = "houdini", version = "1.2.1", build_tools = ["gleam"], requirements = [], otp_app = "houdini", source = "hex", outer_checksum = "6F8AC2F12974567FB744BEA66AC93CEB76AAEA19AD28564623F76CDA9BC26A85" },
+  { name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
+  { name = "logging", version = "1.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "BC5F18CE5DD9686100229FE5409BDC3DD5C46D5A7DF2F804AD2D8F0DD6C5060E" },
+  { name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" },
+  { name = "mist", version = "6.0.3", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "1B07F321D5FA0CB162D81496F2DE96AEB6EF8980F4F38230A4CC3F849497E020" },
+  { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" },
+  { name = "simplifile", version = "2.4.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "7C18AFA4FED0B4CE1FA5B0B4BAC1FA1744427054EA993565F6F3F82E5453170D" },
+  { name = "snag", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "274F41D6C3ECF99F7686FDCE54183333E41D2C1CA5A3A673F9A8B2C7A4401077" },
+  { name = "tom", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "tom", source = "hex", outer_checksum = "DCF04CB7AB35D58CFC598C66EA2E1816D160759802C89B2BA6238780D59BC256" },
+  { name = "wisp", version = "2.2.2", build_tools = ["gleam"], requirements = ["directories", "exception", "filepath", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "houdini", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "5FF5F1E288C3437252ABB93D8F9CF42FF652CE7AD54480CFE736038DC09C4F22" },
+]
+
+[requirements]
+argv = { version = ">= 1.1.0 and < 2.0.0" }
+gleam_erlang = { version = ">= 1.3.0 and < 2.0.0" }
+gleam_http = { version = ">= 4.3.0 and < 5.0.0" }
+gleam_json = { version = ">= 3.1.0 and < 4.0.0" }
+gleam_otp = { version = ">= 1.2.0 and < 2.0.0" }
+gleam_stdlib = { version = ">= 1.0.0 and < 2.0.0" }
+gleam_time = { version = ">= 1.8.0 and < 2.0.0" }
+gleescript = { version = ">= 1.5.2 and < 2.0.0" }
+gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+logging = { version = ">= 1.5.0 and < 2.0.0" }
+mist = { version = ">= 6.0.3 and < 7.0.0" }
+simplifile = { version = ">= 2.4.0 and < 3.0.0" }
+wisp = { version = ">= 2.2.2 and < 3.0.0" }
diff --git a/src/preview.gleam b/src/preview.gleam
new file mode 100644 (file)
index 0000000..947a17c
--- /dev/null
@@ -0,0 +1,39 @@
+import argv
+import gleam/erlang/process
+import gleam/io
+import mist
+import router
+import wisp
+import wisp/wisp_mist
+
+pub fn main() -> Nil {
+  let args: List(String) = argv.load().arguments
+  case args {
+    ["greet", name] -> io.println("hello " <> name <> "!")
+    ["web", file_path] -> web(file_path)
+    _ -> io.println("bad args")
+  }
+
+  // wisp.configure_logger()
+
+  Nil
+}
+
+pub fn wassup() -> Int {
+  42
+}
+
+fn web(file_path: String) -> Nil {
+  wisp.configure_logger()
+
+  let secret_key_base = wisp.random_string(64)
+
+  let assert Ok(_) =
+    router.handle_request(_, file_path)
+    |> wisp_mist.handler(secret_key_base)
+    |> mist.new
+    |> mist.port(8000)
+    |> mist.start
+
+  process.sleep_forever()
+}
diff --git a/src/router.gleam b/src/router.gleam
new file mode 100644 (file)
index 0000000..c32d12b
--- /dev/null
@@ -0,0 +1,90 @@
+import gleam/bool
+import gleam/list
+import gleam/result
+import simplifile
+import wisp
+
+pub fn handle_request(req: wisp.Request, file_path: String) -> wisp.Response {
+  use req <- middleware(req)
+  // use <- wisp.serve_static(req, "/files", file_path)
+
+  case req.path {
+    "/index.html" -> main_page(req)
+    "/" -> main_page(req)
+    "/styles.css" -> {
+      use <- wisp.serve_static(req, "/styles.css", "./static/styles.css")
+      wisp.ok()
+    }
+    "/new/" <> _path -> upload(req)
+    "/files/" <> path -> files(req, "/" <> path, file_path)
+    _ -> wisp.not_found()
+  }
+}
+
+fn files(req: wisp.Request, path: String, file_path) -> wisp.Response {
+  //TODO case req.headers smth smth
+  use <- wisp.serve_static(req, "/files", file_path)
+  wisp.ok()
+}
+
+const password = "greg"
+
+pub fn upload(req: wisp.Request) -> wisp.Response {
+  use form <- wisp.require_form(req)
+
+  //early return if incorrect password
+  use <- bool.guard(
+    when: result.unwrap(list.key_find(form.values, "password"), "") != password,
+    return: wisp.response(401),
+  )
+
+  wisp.log_debug(result.unwrap(list.key_find(form.values, "password"), ""))
+
+  case form.files {
+    [#("file", wisp.UploadedFile(file_name:, path: temp_path)), ..] -> {
+      let destination =
+        "./files/"
+        <> result.unwrap(list.key_find(form.values, "filename"), file_name)
+
+      let result = {
+        use _ <- result.try(simplifile.create_directory_all("./files"))
+
+        simplifile.copy(temp_path, destination)
+      }
+
+      case result {
+        Ok(_) ->
+          wisp.response(200)
+          |> wisp.set_body(wisp.Text("Upload successful"))
+
+        Error(_) -> wisp.internal_server_error()
+      }
+    }
+
+    _ -> wisp.bad_request("idk bro")
+  }
+}
+
+fn main_page(req: wisp.Request) -> wisp.Response {
+  wisp.html_response(
+    result.unwrap(simplifile.read("./static/form.html"), ""),
+    200,
+  )
+}
+
+fn middleware(
+  req: wisp.Request,
+  handler: fn(wisp.Request) -> wisp.Response,
+) -> wisp.Response {
+  let req = wisp.method_override(req)
+
+  use <- wisp.log_request(req)
+
+  use <- wisp.rescue_crashes
+
+  use req <- wisp.handle_head(req)
+
+  use req <- wisp.csrf_known_header_protection(req)
+
+  handler(req)
+}
diff --git a/static/form.html b/static/form.html
new file mode 100644 (file)
index 0000000..128f31a
--- /dev/null
@@ -0,0 +1,91 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>File Upload</title>
+    <link rel="stylesheet" href="/styles.css" />
+  </head>
+  <body>
+    <h1>File Upload</h1>
+
+    <form id="upload-form">
+      <div>
+        <label for="file">File:</label>
+        <input
+          type="file"
+          id="file"
+          name="file"
+          required
+        />
+      </div>
+
+      <div>
+        <label for="filename">Save as (optional):</label>
+        <input
+          type="text"
+          id="filename"
+          name="filename"
+          placeholder="Leave blank to keep original filename"
+        />
+      </div>
+
+      <div>
+        <label for="password">Password:</label>
+        <input
+          type="password"
+          id="password"
+          name="password"
+          required
+        />
+      </div>
+
+      <button type="submit">Upload</button>
+    </form>
+
+    <p id="response-message"></p>
+
+    <script>
+      document
+        .getElementById("upload-form")
+        .addEventListener("submit", async function (event) {
+          event.preventDefault();
+
+          const formData = new FormData();
+
+          const fileInput = document.getElementById("file");
+          const filenameInput = document.getElementById("filename");
+          const passwordInput = document.getElementById("password");
+          const responseMessage =
+            document.getElementById("response-message");
+
+          formData.append("file", fileInput.files[0]);
+          formData.append("password", passwordInput.value);
+
+          if (filenameInput.value.trim()) {
+            formData.append("filename", filenameInput.value.trim());
+          }
+
+          try {
+            const response = await fetch("/new/upload", {
+              method: "POST",
+              body: formData,
+            });
+
+            const text = await response.text();
+
+            if (response.ok) {
+              responseMessage.textContent = text;
+            } else {
+              responseMessage.textContent =
+                `Upload failed (${response.status}): ${text}`;
+            }
+          } catch (error) {
+            console.error(error);
+            responseMessage.textContent =
+              "An error occurred while uploading the file.";
+          }
+        });
+    </script>
+  </body>
+</html>
diff --git a/static/styles.css b/static/styles.css
new file mode 100644 (file)
index 0000000..25df8fe
--- /dev/null
@@ -0,0 +1,58 @@
+body {
+  font-family: sans-serif;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 100vh;
+  margin: 0;
+}
+
+h1 {
+  margin-bottom: 20px;
+}
+
+#upload-form {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+input {
+  padding: 10px;
+  margin-bottom: 10px;
+  width: 300px;
+  border: 1px solid #ccc;
+  border-radius: 4px;
+}
+
+button {
+  padding: 10px 20px;
+  border: none;
+  background-color: #007bff;
+  color: white;
+  border-radius: 4px;
+  cursor: pointer;
+}
+
+button:hover {
+  background-color: #0056b3;
+}
+
+#upload-form {
+  width: 400px;
+}
+
+#upload-form>div {
+  width: 100%;
+}
+
+#upload-form input {
+  width: 100%;
+  box-sizing: border-box;
+}
+
+#response-message {
+  margin-top: 20px;
+  font-size: 1.1em;
+}
\ No newline at end of file
diff --git a/test/preview_test.gleam b/test/preview_test.gleam
new file mode 100644 (file)
index 0000000..456d957
--- /dev/null
@@ -0,0 +1,18 @@
+import gleeunit
+import preview
+
+pub fn main() -> Nil {
+  gleeunit.main()
+}
+
+// gleeunit test functions end in `_test`
+pub fn hello_world_test() {
+  let name = "Joe"
+  let greeting = "Hello, " <> name <> "!"
+
+  assert greeting == "Hello, Joe!"
+}
+
+pub fn wassup_test() {
+  assert preview.wassup() == 42
+}