commit
79c5ed7d8e
@ -0,0 +1,4 @@ |
||||
# Used by "mix format" |
||||
[ |
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] |
||||
] |
@ -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/ |
@ -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 |
@ -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 |
@ -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 |
@ -0,0 +1,3 @@ |
||||
defmodule TirInnaNoc.Imageboard.Post do |
||||
defstruct postJson: "", sage: "u" |
||||
end |
@ -0,0 +1,3 @@ |
||||
defmodule TirInnaNoc.Imageboard.Thread do |
||||
defstruct last_update: 0, on_page: 0, reply_number: 0, posts: "" |
||||
end |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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"}, |
||||
} |
@ -0,0 +1,15 @@ |
||||
hash post/<board>/<id> -> |
||||
string postjson |
||||
string sage //y/n/m/u |
||||
|
||||
hash thread/<board>/<id> -> |
||||
string last_update |
||||
string on_page |
||||
string reply_number |
||||
string posts //<id>,<id>,<id>,... |
||||
|
||||
hash img -> |
||||
string <board>/<tim>/<ext> // binary |
||||
|
||||
set boards -> // all archived boards |
||||
string <board> |
@ -0,0 +1 @@ |
||||
ExUnit.start() |
@ -0,0 +1,5 @@ |
||||
defmodule TirInnaNocTest do |
||||
use ExUnit.Case |
||||
doctest TirInnaNoc |
||||
|
||||
end |
Loading…
Reference in new issue