From 79c5ed7d8e2ea73f2f9f04b17e7449fe3dfea4b8 Mon Sep 17 00:00:00 2001 From: cynic Date: Tue, 23 Aug 2022 23:48:32 -0400 Subject: [PATCH] init --- .formatter.exs | 4 +++ .gitignore | 26 ++++++++++++++++ lib/tir_inna_noc.ex | 14 +++++++++ lib/tir_inna_noc/db.ex | 44 +++++++++++++++++++++++++++ lib/tir_inna_noc/imageboard.ex | 20 ++++++++++++ lib/tir_inna_noc/imageboard/post.ex | 3 ++ lib/tir_inna_noc/imageboard/thread.ex | 3 ++ lib/tir_inna_noc/meldh.ex | 29 ++++++++++++++++++ lib/tir_inna_noc/merlin.ex | 20 ++++++++++++ lib/tir_inna_noc/perenelle.ex | 14 +++++++++ lib/tir_inna_noc/sup.ex | 17 +++++++++++ mix.exs | 33 ++++++++++++++++++++ mix.lock | 14 +++++++++ readme.txt | 15 +++++++++ test/test_helper.exs | 1 + test/tir_inna_noc_test.exs | 5 +++ 16 files changed, 262 insertions(+) create mode 100644 .formatter.exs create mode 100644 .gitignore create mode 100644 lib/tir_inna_noc.ex create mode 100644 lib/tir_inna_noc/db.ex create mode 100644 lib/tir_inna_noc/imageboard.ex create mode 100644 lib/tir_inna_noc/imageboard/post.ex create mode 100644 lib/tir_inna_noc/imageboard/thread.ex create mode 100644 lib/tir_inna_noc/meldh.ex create mode 100644 lib/tir_inna_noc/merlin.ex create mode 100644 lib/tir_inna_noc/perenelle.ex create mode 100644 lib/tir_inna_noc/sup.ex create mode 100644 mix.exs create mode 100644 mix.lock create mode 100644 readme.txt create mode 100644 test/test_helper.exs create mode 100644 test/tir_inna_noc_test.exs diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd14b6f --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +tir_inna_noc-*.tar + +# Temporary files, for example, from tests. +/tmp/ diff --git a/lib/tir_inna_noc.ex b/lib/tir_inna_noc.ex new file mode 100644 index 0000000..dd53d5f --- /dev/null +++ b/lib/tir_inna_noc.ex @@ -0,0 +1,14 @@ +defmodule TirInnaNoc do + use Application + + @impl true + def start(_type, _args) do + IO.puts("starting~") + TirInnaNoc.Sup.start_link(name: :overseer) + #{:ok, c} = Redix.start_link(host: "localhost", port: 6379, name: :redix) + #Redix.command!(c, ["SET", "lol", "jews"]) + #Redix.command(c, ["GET", "lol"]) |> inspect |> IO.puts + #{:ok, c} + + end +end diff --git a/lib/tir_inna_noc/db.ex b/lib/tir_inna_noc/db.ex new file mode 100644 index 0000000..365ddd3 --- /dev/null +++ b/lib/tir_inna_noc/db.ex @@ -0,0 +1,44 @@ +defmodule TirInnaNoc.Db do + use GenServer + + def start_link(_) do + {:ok, conn} = Redix.start_link(host: "localhost", port: 6379, name: :db) + GenServer.start_link(__MODULE__, conn, name: TirInnaNoc.Db) + end + + def set(val, key) do + GenServer.call(TirInnaNoc.Db, {:cmd, ["SET", key, val]}) + end + def get(key) do + GenServer.call(TirInnaNoc.Db, {:cmd, ["GET", key]}) + end + def exists(key) do + GenServer.call(TirInnaNoc.Db, {:cmd, ["EXISTS", key]}) + end + def keys(pattern) do + GenServer.call(TirInnaNoc.Db, {:cmd, ["KEYS", pattern]}) + end + def hset(val, key, field) do + GenServer.call(TirInnaNoc.Db, {:cmd, ["HSET", key, field, val]}) + end + def hget(key, field) do + GenServer.call(TirInnaNoc.Db, {:cmd, ["HGET", key, field]}) + end + def sadd(member, key) do + GenServer.call(TirInnaNoc.Db, {:cmd, ["SADD", key, member]}) + end + def smembers(key) do + GenServer.call(TirInnaNoc.Db, {:cmd, ["SMEMBERS", key]}) + end + + @impl true + def init(c) do + {:ok, c} + end + + @impl true + def handle_call({:cmd, command}, _from, c) do + resp = Redix.command(c, command) + {:reply, resp, c} + end +end diff --git a/lib/tir_inna_noc/imageboard.ex b/lib/tir_inna_noc/imageboard.ex new file mode 100644 index 0000000..516ed9d --- /dev/null +++ b/lib/tir_inna_noc/imageboard.ex @@ -0,0 +1,20 @@ +defmodule TirInnaNoc.Imageboard do + use Tesla + + plug Tesla.Middleware.BaseUrl, "https://a.4cdn.org" + #plug Tesla.Middleware.Headers, [{"authorization", "token xyz"}] + plug Tesla.Middleware.JSON + + def boards() do + get("/boards.json") + end + def threads(board) do + get("/"<>board<>"/threads.json") + end + def thread(board, id) do + get("/"<>board<>"/thread/"<>to_string(id)<>".json") + end + def catalog(board) do + get("/"<>board<>"/catalog.json") + end +end diff --git a/lib/tir_inna_noc/imageboard/post.ex b/lib/tir_inna_noc/imageboard/post.ex new file mode 100644 index 0000000..0068822 --- /dev/null +++ b/lib/tir_inna_noc/imageboard/post.ex @@ -0,0 +1,3 @@ +defmodule TirInnaNoc.Imageboard.Post do + defstruct postJson: "", sage: "u" +end diff --git a/lib/tir_inna_noc/imageboard/thread.ex b/lib/tir_inna_noc/imageboard/thread.ex new file mode 100644 index 0000000..0e3613f --- /dev/null +++ b/lib/tir_inna_noc/imageboard/thread.ex @@ -0,0 +1,3 @@ +defmodule TirInnaNoc.Imageboard.Thread do + defstruct last_update: 0, on_page: 0, reply_number: 0, posts: "" +end diff --git a/lib/tir_inna_noc/meldh.ex b/lib/tir_inna_noc/meldh.ex new file mode 100644 index 0000000..31b919d --- /dev/null +++ b/lib/tir_inna_noc/meldh.ex @@ -0,0 +1,29 @@ +defmodule TirInnaNoc.Meldh do + use GenServer + + def start_link(state) do + GenServer.start_link(__MODULE__, state, name: String.to_atom(elem(state, 0)<>"Meldh")) + end + + @impl true + def handle_info({:checkin, no, pid}, state) do + state = {elem(state, 0), Map.put(elem(state, 1), no, pid)} + {:noreply, state} + end + + @impl true + def init(state) do + IO.puts("started meldh to archive board "<>elem(state, 0)) + {:ok, res} = TirInnaNoc.Imageboard.threads(elem(state, 0)) + res.body + |> Enum.each(fn page -> + Enum.each(page["threads"], fn thread -> + DynamicSupervisor.start_child( + String.to_atom(elem(state, 0)<>"Supervisor"), + {TirInnaNoc.Perenelle, {elem(state, 0), thread["no"]}} + ) + end) + end) + {:ok, state} + end +end diff --git a/lib/tir_inna_noc/merlin.ex b/lib/tir_inna_noc/merlin.ex new file mode 100644 index 0000000..71735de --- /dev/null +++ b/lib/tir_inna_noc/merlin.ex @@ -0,0 +1,20 @@ +defmodule TirInnaNoc.Merlin do + use GenServer + + def start_link(a) do + GenServer.start_link(__MODULE__, a) + end + + @impl true + def init(a) do + {:ok, relevant} = TirInnaNoc.Db.smembers("boards") + relevant + |> Enum.each(fn board -> + DynamicSupervisor.start_child( + MerlinSupervisor, {DynamicSupervisor, strategy: :one_for_one, name: String.to_atom(board<>"Supervisor")} + ) + DynamicSupervisor.start_child(MerlinSupervisor, {TirInnaNoc.Meldh, {board, %{}}}) + end) + {:ok, a} + end +end diff --git a/lib/tir_inna_noc/perenelle.ex b/lib/tir_inna_noc/perenelle.ex new file mode 100644 index 0000000..ba4faf6 --- /dev/null +++ b/lib/tir_inna_noc/perenelle.ex @@ -0,0 +1,14 @@ +defmodule TirInnaNoc.Perenelle do + use GenServer + + def start_link(state) do + GenServer.start_link(__MODULE__, state, name: String.to_atom(elem(state, 0)<>to_string(elem(state, 1))<>"Perenelle")) + end + + @impl true + def init(state) do + IO.puts("watching thread "<>inspect(state)) + send(String.to_atom(elem(state, 0)<>"Meldh"), {:checkin, elem(state, 1), self()}) + {:ok, state} + end +end diff --git a/lib/tir_inna_noc/sup.ex b/lib/tir_inna_noc/sup.ex new file mode 100644 index 0000000..104f97e --- /dev/null +++ b/lib/tir_inna_noc/sup.ex @@ -0,0 +1,17 @@ +defmodule TirInnaNoc.Sup do + use Supervisor + + def start_link(opts) do + Supervisor.start_link(__MODULE__, :ok, opts) + end + + @impl true + def init(:ok) do + children = [ + {TirInnaNoc.Db, [nil]}, + {DynamicSupervisor, strategy: :one_for_one, name: MerlinSupervisor}, + {TirInnaNoc.Merlin, [nil]} + ] + Supervisor.init(children, strategy: :one_for_one) + end +end diff --git a/mix.exs b/mix.exs new file mode 100644 index 0000000..e17c7c3 --- /dev/null +++ b/mix.exs @@ -0,0 +1,33 @@ +defmodule TirInnaNoc.MixProject do + use Mix.Project + + def project do + [ + app: :tir_inna_noc, + version: "0.1.0", + elixir: "~> 1.13", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + mod: {TirInnaNoc, []}, + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + {:redix, "~> 1.1"}, + {:tesla, "~> 1.4.0"}, + {:jason, "~> 1.3"}, + {:html_entities, "~> 0.5.2"} + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + ] + end +end diff --git a/mix.lock b/mix.lock new file mode 100644 index 0000000..1516e97 --- /dev/null +++ b/mix.lock @@ -0,0 +1,14 @@ +%{ + "castore": {:hex, :castore, "0.1.18", "deb5b9ab02400561b6f5708f3e7660fc35ca2d51bfc6a940d2f513f89c2975fc", [:mix], [], "hexpm", "61bbaf6452b782ef80b33cdb45701afbcf0a918a45ebe7e73f1130d661e66a06"}, + "finch": {:hex, :finch, "0.13.0", "c881e5460ec563bf02d4f4584079e62201db676ed4c0ef3e59189331c4eddf7b", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "49957dcde10dcdc042a123a507a9c5ec5a803f53646d451db2f7dea696fba6cc"}, + "hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"}, + "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, + "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"}, + "mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"}, + "mint": {:hex, :mint, "1.4.2", "50330223429a6e1260b2ca5415f69b0ab086141bc76dc2fbf34d7c389a6675b2", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "ce75a5bbcc59b4d7d8d70f8b2fc284b1751ffb35c7b6a6302b5192f8ab4ddd80"}, + "nimble_options": {:hex, :nimble_options, "0.4.0", "c89babbab52221a24b8d1ff9e7d838be70f0d871be823165c94dd3418eea728f", [:mix], [], "hexpm", "e6701c1af326a11eea9634a3b1c62b475339ace9456c1a23ec3bc9a847bca02d"}, + "nimble_pool": {:hex, :nimble_pool, "0.2.6", "91f2f4c357da4c4a0a548286c84a3a28004f68f05609b4534526871a22053cde", [:mix], [], "hexpm", "1c715055095d3f2705c4e236c18b618420a35490da94149ff8b580a2144f653f"}, + "redix": {:hex, :redix, "1.1.5", "6fc460d66a5c2287e83e6d73dddc8d527ff59cb4d4f298b41e03a4db8c3b2bd5", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "679afdd4c14502fe9c11387ff1cdcb33065a1cf511097da1eee407f17c7a418b"}, + "telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"}, + "tesla": {:hex, :tesla, "1.4.4", "bb89aa0c9745190930366f6a2ac612cdf2d0e4d7fff449861baa7875afd797b2", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.3", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "d5503a49f9dec1b287567ea8712d085947e247cb11b06bc54adb05bfde466457"}, +} diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..3e01377 --- /dev/null +++ b/readme.txt @@ -0,0 +1,15 @@ +hash post// -> + string postjson + string sage //y/n/m/u + +hash thread// -> + string last_update + string on_page + string reply_number + string posts //,,,... + +hash img -> + string // // binary + +set boards -> // all archived boards + string \ No newline at end of file diff --git a/test/test_helper.exs b/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/test/tir_inna_noc_test.exs b/test/tir_inna_noc_test.exs new file mode 100644 index 0000000..87a1169 --- /dev/null +++ b/test/tir_inna_noc_test.exs @@ -0,0 +1,5 @@ +defmodule TirInnaNocTest do + use ExUnit.Case + doctest TirInnaNoc + +end