diff options
author | href <href@random.sh> | 2018-02-10 21:40:22 +0100 |
---|---|---|
committer | href <href@random.sh> | 2018-02-10 21:40:22 +0100 |
commit | 935a36eecc0faea60236101e11bc9f7cf1872686 (patch) | |
tree | b7b4358dee2eb3fc60681852f62c750ae8c05cb9 /lib/lsg | |
parent | sse / embedded player (diff) |
update
Diffstat (limited to '')
-rw-r--r-- | lib/lsg/application.ex | 11 | ||||
-rw-r--r-- | lib/lsg_irc/broadcast_handler.ex | 2 | ||||
-rw-r--r-- | lib/lsg_irc/connection_handler.ex | 4 | ||||
-rw-r--r-- | lib/lsg_irc/dice_handler.ex | 72 | ||||
-rw-r--r-- | lib/lsg_irc/last_fm_handler.ex | 138 | ||||
-rw-r--r-- | lib/lsg_irc/login_handler.ex | 2 | ||||
-rw-r--r-- | lib/lsg_irc/np_handler.ex | 8 | ||||
-rw-r--r-- | lib/lsg_irc/text_trigger_handler.ex | 218 | ||||
-rw-r--r-- | lib/lsg_irc/youtube_handler.ex | 77 | ||||
-rw-r--r-- | lib/lsg_web/controllers/irc_controller.ex | 51 | ||||
-rw-r--r-- | lib/lsg_web/controllers/page_controller.ex | 11 | ||||
-rw-r--r-- | lib/lsg_web/router.ex | 9 | ||||
-rw-r--r-- | lib/lsg_web/templates/irc/index.html.eex | 29 | ||||
-rw-r--r-- | lib/lsg_web/templates/irc/txt.html.eex | 19 | ||||
-rw-r--r-- | lib/lsg_web/templates/irc/txts.html.eex | 8 | ||||
-rw-r--r-- | lib/lsg_web/templates/layout/app.html.eex | 23 | ||||
-rw-r--r-- | lib/lsg_web/templates/page/api.html.eex | 35 | ||||
-rw-r--r-- | lib/lsg_web/templates/page/index.html.eex | 37 | ||||
-rw-r--r-- | lib/lsg_web/templates/page/irc.html.eex | 19 | ||||
-rw-r--r-- | lib/lsg_web/views/irc_view.ex | 3 |
20 files changed, 712 insertions, 64 deletions
diff --git a/lib/lsg/application.ex b/lib/lsg/application.ex index 73ec04d..0df3c87 100644 --- a/lib/lsg/application.ex +++ b/lib/lsg/application.ex @@ -18,9 +18,7 @@ defmodule LSG.Application do worker(LSG.Icecast, []), worker(LSG.IRC.ConnectionHandler, [irc_client]), worker(LSG.IRC.LoginHandler, [irc_client]), - worker(LSG.IRC.BroadcastHandler, [irc_client]), - worker(LSG.IRC.NpHandler, [irc_client]), - ] + ] ++ irc_handlers(irc_client) # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options @@ -34,4 +32,11 @@ defmodule LSG.Application do LSGWeb.Endpoint.config_change(changed, removed) :ok end + + defp irc_handlers(irc_client) do + import Supervisor.Spec + for handler <- Application.get_env(:lsg, :irc)[:handlers] do + worker(handler, [irc_client]) + end + end end diff --git a/lib/lsg_irc/broadcast_handler.ex b/lib/lsg_irc/broadcast_handler.ex index 22ffbaf..19c41ea 100644 --- a/lib/lsg_irc/broadcast_handler.ex +++ b/lib/lsg_irc/broadcast_handler.ex @@ -1,4 +1,6 @@ defmodule LSG.IRC.BroadcastHandler do + def irc_doc, do: "" + def start_link(client) do GenServer.start_link(__MODULE__, [client]) end diff --git a/lib/lsg_irc/connection_handler.ex b/lib/lsg_irc/connection_handler.ex index f3bb1d4..337fe00 100644 --- a/lib/lsg_irc/connection_handler.ex +++ b/lib/lsg_irc/connection_handler.ex @@ -3,9 +3,9 @@ defmodule LSG.IRC.ConnectionHandler do defstruct host: "irc.quakenet.org", port: 6667, pass: "", - nick: "bot115ans", + nick: "`115ans", user: "115ans", - name: "115ans.net", + name: "https://sys.115ans.net/irc", client: nil end diff --git a/lib/lsg_irc/dice_handler.ex b/lib/lsg_irc/dice_handler.ex new file mode 100644 index 0000000..b865100 --- /dev/null +++ b/lib/lsg_irc/dice_handler.ex @@ -0,0 +1,72 @@ +defmodule LSG.IRC.DiceHandler do + require Logger + + @moduledoc """ + # dice + + !dice [6 | faces] [1 | rolls] + roll X times a dice of X faces. + """ + + @default_faces 6 + @default_rolls 1 + @max_rolls 50 + + defstruct client: nil, dets: nil + + def irc_doc, do: @moduledoc + + def start_link(client) do + GenServer.start_link(__MODULE__, [client]) + end + + def init([client]) do + ExIRC.Client.add_handler(client, self()) + {:ok, %__MODULE__{client: client}} + end + + def handle_info({:received, "!dice", sender, chan}, state) do + roll(state, sender, chan, @default_faces, @default_rolls) + {:noreply, state} + end + + def handle_info({:received, "!dice "<>params, sender, chan}, state) do + {faces, rolls} = case String.split(params, " ", parts: 2) do + [faces, rolls] -> {faces, rolls} + [faces] -> {faces, "1"} + end + + to_integer = fn(string, default) -> + case Integer.parse(string) do + {int, _} -> int + _ -> default + end + end + + {faces, rolls} = {to_integer.(faces, @default_faces), to_integer.(rolls, @default_rolls)} + + roll(state, sender, chan, faces, rolls) + + {:noreply, state} + end + + def handle_info(info, state) do + {:noreply, state} + end + + defp roll(state, %{nick: nick}, chan, faces, 1) when faces > 0 do + random = :crypto.rand_uniform(1, faces+1) + ExIRC.Client.msg(state.client, :privmsg, chan, "#{nick} dice: #{random}") + end + defp roll(state, %{nick: nick}, chan, faces, rolls) when faces > 0 and rolls > 0 and rolls <= @max_rolls do + {results, acc} = Enum.map_reduce(Range.new(1, rolls), 0, fn(i, acc) -> + random = :crypto.rand_uniform(1, faces+1) + {random, acc + random} + end) + results = Enum.join(results, "; ") + ExIRC.Client.msg(state.client, :privmsg, chan, "#{nick} dice [#{acc}] #{results}") + end + + defp roll(_, _, _, _, _), do: nil + +end diff --git a/lib/lsg_irc/last_fm_handler.ex b/lib/lsg_irc/last_fm_handler.ex new file mode 100644 index 0000000..ad6dae9 --- /dev/null +++ b/lib/lsg_irc/last_fm_handler.ex @@ -0,0 +1,138 @@ +defmodule LSG.IRC.LastFmHandler do + require Logger + + @moduledoc """ + # last.fm + + !lastfm [nick|username] + say what nick/specified username is listening on lastfm; if last.fm username is known (via +lastfm). + !lastfmall + say what known users (+lastfm) are listening + +lastfm <username> + links the nick who use the command to <username> last.fm account. + -lastfm + unlinks the nick's previously set last.fm username. + """ + + defstruct client: nil, dets: nil + + def irc_doc, do: @moduledoc + + def start_link(client) do + GenServer.start_link(__MODULE__, [client]) + end + + def init([client]) do + ExIRC.Client.add_handler(client, self()) + dets_filename = Application.get_env(:lsg, __MODULE__)[:dets_path] + {:ok, dets} = :dets.open_file(dets_filename, []) + {:ok, %__MODULE__{client: client, dets: dets}} + end + + def handle_info({:received, "+lastfm " <> username, sender, chan}, state) do + username = String.strip(username) + :ok = :dets.insert(state.dets, {String.downcase(sender.nick), username}) + ExIRC.Client.msg(state.client, :privmsg, chan, "#{sender.nick}: nom d'utilisateur last.fm configuré: \"#{username}\"") + {:noreply, state} + end + + def handle_info({:received, "-lastfm", sender, chan}, state) do + text = case :dets.lookup(state.dets, sender.nick) do + [{_nick, username}] -> + :dets.delete(state.dets, sender.nick) + "#{sender.nick}: nom d'utilisateur last.fm enlevé" + _ -> "" + end + ExIRC.Client.msg(state.client, :privmsg, chan, text) + {:noreply, state} + end + + def handle_info({:received, "!lastfm", sender, chan}, state) do + irc_now_playing(sender.nick, chan, state) + {:noreply, state} + end + + def handle_info({:received, "!lastfm " <> nick_or_user, sender, chan}, state) do + irc_now_playing(nick_or_user, chan, state) + {:noreply, state} + end + + def handle_info({:received, "!lastfmall", sender, chan}, state) do + foldfun = fn({_nick, user}, acc) -> [user|acc] end + usernames = :dets.foldl(foldfun, [], state.dets) + |> Enum.uniq + for u <- usernames, do: irc_now_playing(u, chan, state) + {:noreply, state} + end + + def handle_info(info, state) do + {:noreply, state} + end + + defp irc_now_playing(nick_or_user, chan, state) do + nick_or_user = String.strip(nick_or_user) + username = case :dets.lookup(state.dets, nick_or_user) do + [{^nick_or_user, username}] -> username + _ -> nick_or_user + end + + case now_playing(username) do + {:error, text} when is_binary(text) -> ExIRC.Client.msg(state.client, :privmsg, chan, text) + {:ok, map} when is_map(map) -> + text = format_now_playing(map) + user = lookup_nick(username, state) + if user && text, do: ExIRC.Client.msg(state.client, :privmsg, chan, "#{user} #{text}") + other -> + IO.inspect(other) + nil + end + end + + defp now_playing(user) do + api = Application.get_env(:lsg, __MODULE__)[:api_key] + url = "http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&format=json&limit=1" <> "&api_key=" <> api <> "&user="<> user + case HTTPoison.get(url) do + {:ok, %HTTPoison.Response{status_code: 200, body: body}} -> Jason.decode(body) + {:ok, %HTTPoison.Response{status_code: 400}} -> {:error, "last.fm: utilisateur #{user} inexistant"} + {:ok, %HTTPoison.Response{status_code: code}} -> {:error, "last.fm: erreur #{to_string(code)}"} + error -> + Logger.error "Lastfm http error: #{inspect error}" + :error + end + end + + defp format_now_playing(%{"recenttracks" => %{"track" => [track = %{"@attr" => %{"nowplaying" => "true"}}, _old]}}) do + format_track(true, track) + end + + defp format_now_playing(%{"recenttracks" => %{"track" => [track]}}) do + format_track(false, track) + end + + defp format_now_playing(%{"error" => err, "message" => message}) do + "last.fm error #{err}: #{message}" + end + + defp format_now_playing(miss) do + nil + end + + defp format_track(np, track) do + album = if track["album"]["#text"] do + " (" <> track["album"]["#text"] <> ")" + else + "" + end + action = if np, do: "écoute ", else: "a écouté " + action <> track["artist"]["#text"] <> " - " <> track["name"] <> album <> " — " <> track["url"] + end + + defp lookup_nick(username, state) do + case :dets.match(state.dets, {:'$1', username}) do + [[match]] -> match + [[match] | _many] -> match + _ -> username + end + end + +end diff --git a/lib/lsg_irc/login_handler.ex b/lib/lsg_irc/login_handler.ex index b4757b1..f989b40 100644 --- a/lib/lsg_irc/login_handler.ex +++ b/lib/lsg_irc/login_handler.ex @@ -5,7 +5,7 @@ defmodule LSG.IRC.LoginHandler do def init([client]) do ExIRC.Client.add_handler client, self - {:ok, {client, ["#lsg"]}} + {:ok, {client, ["#lsg", "#lsgtest"]}} end def handle_info(:logged_in, state = {client, channels}) do diff --git a/lib/lsg_irc/np_handler.ex b/lib/lsg_irc/np_handler.ex index 8bde293..b198cbc 100644 --- a/lib/lsg_irc/np_handler.ex +++ b/lib/lsg_irc/np_handler.ex @@ -1,4 +1,12 @@ defmodule LSG.IRC.NpHandler do + @moduledoc """ + # np + + !np + now playing on 115ans.net + """ + + def irc_doc, do: @moduledoc def start_link(client) do GenServer.start_link(__MODULE__, [client]) end diff --git a/lib/lsg_irc/text_trigger_handler.ex b/lib/lsg_irc/text_trigger_handler.ex new file mode 100644 index 0000000..0e9ef50 --- /dev/null +++ b/lib/lsg_irc/text_trigger_handler.ex @@ -0,0 +1,218 @@ +defmodule LSG.IRC.TxtHandler do + @moduledoc """ + # [txt](/irc/txt) + + !txt + statistics, file list + +txt <file> + create new <file> + + !FILE + read a random line from the file + !FILE <index> + read line #<index> from the file + !FILE <query> + return a phrase from file who matches <query> + +FILE <text> + add <text> in FILE + -FILE <index> + remove line in FILE at index <index> + """ + + def irc_doc, do: @moduledoc + + def start_link(client) do + GenServer.start_link(__MODULE__, [client]) + end + + defstruct client: nil, triggers: %{} + + def init([client]) do + state = %__MODULE__{client: client} + ExIRC.Client.add_handler(client, self()) + {:ok, %__MODULE__{state | triggers: load()}} + end + + def handle_info({:received, "!reload", _, chan}, state) do + {:noreply, %__MODULE__{state | triggers: load()}} + end + + def handle_info({:received, "!txt", _, chan}, state) do + map = Enum.map(state.triggers, fn({key, data}) -> + "#{key}: #{to_string(Enum.count(data))}" + end) + total = Enum.reduce(state.triggers, 0, fn({_, data}, acc) -> + acc + Enum.count(data) + end) + detail = Enum.join(map, ", ") + total = ". total: #{Enum.count(state.triggers)} fichiers, #{to_string(total)} lignes. Détail: https://sys.115ans.net/irc/txt" + (detail<>total) + |> String.codepoints + |> Enum.chunk_every(440) + |> Enum.map(&Enum.join/1) + |> Enum.map(fn(line) -> ExIRC.Client.msg(state.client, :privmsg, chan, line) end) + {:noreply, state} + end + + def handle_info({:received, "!"<>trigger, _, chan}, state) do + {trigger, opts} = clean_trigger(trigger) + line = get_random(state.triggers, trigger, opts) + if line do + ExIRC.Client.msg(state.client, :privmsg, chan, line) + end + {:noreply, state} + end + + def handle_info({:received, "+txt "<>trigger, _, chan}, state) do + {trigger, _} = clean_trigger(trigger) + if create_file(trigger) do + ExIRC.Client.msg(state.client, :privmsg, chan, "#{trigger}.txt créé. Ajouter: `+#{trigger} …` ; Lire: `!#{trigger}`") + {:noreply, %__MODULE__{state | triggers: load()}} + else + {:noreply, state} + end + end + + def handle_info({:received, "+"<>trigger_and_content, _, chan}, state) do + if idx = add(state.triggers, trigger_and_content) do + ExIRC.Client.msg(state.client, :privmsg, chan, "ajouté. (#{idx})") + {:noreply, %__MODULE__{state | triggers: load()}} + else + {:noreply, state} + end + end + + def handle_info({:received, "-"<>trigger_and_id, _, chan}, state) do + with \ + [trigger, id] <- String.split(trigger_and_id, " ", parts: 2), + {trigger, _} = clean_trigger(trigger), + data <- Map.get(state.triggers, trigger), + {id, ""} <- Integer.parse(id), + {text, _id} <- Enum.find(data, fn({_, idx}) -> id-1 == idx end) + do + data = data |> Enum.into(Map.new) + data = Map.delete(data, text) + ExIRC.Client.msg(state.client, :privmsg, chan, "#{trigger}.txt##{id} supprimée: #{text}") + dump(trigger, data) + {:noreply, %__MODULE__{state | triggers: load()}} + else + error -> + IO.inspect("error " <> inspect(error)) + {:noreply, state} + end + end + + def handle_info(msg, state) do + {:noreply, state} + end + + # Load/Reloads text files from disk + defp load() do + dir = env()[:directory] + Path.wildcard(dir <> "/*.txt") + |> Enum.reduce(%{}, fn(path, m) -> + file = Path.basename(path) + [key, "txt"] = String.split(file, ".", parts: 2) + data = dir <> file + |> File.read! + |> String.split("\n") + |> Enum.reject(fn(line) -> + cond do + line == "" -> true + !line -> true + true -> false + end + end) + |> Enum.with_index + Map.put(m, key, data) + end) + |> Enum.sort + |> Enum.into(Map.new) + end + + defp dump(trigger, data) do + data = data + |> Enum.sort_by(fn({_, idx}) -> idx end) + |> Enum.map(fn({text, _}) -> text end) + |> Enum.join("\n") + File.write!(env()[:directory] <> "/" <> trigger <> ".txt", data<>"\n", []) + end + + defp get_random(triggers, trigger, []) do + if data = Map.get(triggers, trigger) do + {data, _idx} = Enum.random(data) + data + else + nil + end + end + + defp get_random(triggers, trigger, [opt]) do + arg = case Integer.parse(opt) do + {pos, ""} -> {:index, pos} + {_pos, _some_string} -> {:grep, opt} + _error -> {:grep, opt} + end + get_with_param(triggers, trigger, arg) + end + + defp get_with_param(triggers, trigger, {:index, pos}) do + data = Map.get(triggers, trigger, %{}) + case Enum.find(data, fn({_, index}) -> index+1 == pos end) do + {text, _} -> text + _ -> nil + end + end + + defp get_with_param(triggers, trigger, {:grep, query}) do + data = Map.get(triggers, trigger, %{}) + regex = Regex.compile!("#{query}", "i") + out = Enum.filter(data, fn({txt, _}) -> Regex.match?(regex, txt) end) + |> Enum.map(fn({txt, _}) -> txt end) + if !Enum.empty?(out) do + Enum.random(out) + end + end + + defp create_file(name) do + File.touch!(env()[:directory] <> "/" <> name <> ".txt") + true + end + + defp add(triggers, trigger_and_content) do + case String.split(trigger_and_content, " ", parts: 2) do + [trigger, content] -> + {trigger, _} = clean_trigger(trigger) + if Map.has_key?(triggers, trigger) do + File.write!(env()[:directory] <> "/" <> trigger <> ".txt", content<>"\n", [:append]) + Enum.count(triggers[trigger])+1 + end + _ -> false + end + end + + # fixme: this is definitely the ugliest thing i've ever done + defp clean_trigger(trigger) do + [trigger | opts] = trigger + |> String.strip + |> String.split(" ", parts: 2) + + trigger = trigger + |> String.downcase + |> String.replace("à", "a") + |> String.replace("ä", "a") + |> String.replace("â", "a") + |> String.replace("é", "e") + |> String.replace("è", "e") + |> String.replace("ê", "e") + |> String.replace("ë", "e") + |> String.replace("ç", "c") + |> String.replace("ï", "i") + |> String.replace("î", "i") + + {trigger, opts} + end + + defp env(), do: Application.get_env(:lsg, __MODULE__) + +end diff --git a/lib/lsg_irc/youtube_handler.ex b/lib/lsg_irc/youtube_handler.ex new file mode 100644 index 0000000..769f220 --- /dev/null +++ b/lib/lsg_irc/youtube_handler.ex @@ -0,0 +1,77 @@ +defmodule LSG.IRC.YouTubeHandler do + require Logger + + @moduledoc """ + # youtube + + !youtube <recherche> + !yt <recherche> + cherche sur youtube (seulement le premier résultat). + """ + + defstruct client: nil, dets: nil + + def irc_doc, do: @moduledoc + + def start_link(client) do + GenServer.start_link(__MODULE__, [client]) + end + + def init([client]) do + ExIRC.Client.add_handler(client, self()) + {:ok, %__MODULE__{client: client}} + end + + def handle_info({:received, "!youtube " <> query, sender, chan}, state) do + irc_search(query, chan, state) + {:noreply, state} + end + + def handle_info({:received, "!yt " <> query, sender, chan}, state) do + irc_search(query, chan, state) + {:noreply, state} + end + + def handle_info(info, state) do + {:noreply, state} + end + + defp irc_search(query, chan, state) do + case search(query) do + {:ok, %{"items" => [item | _]}} -> + title = get_in(item, ["snippet", "title"]) + url = "https://youtube.com/watch?v=" <> get_in(item, ["id", "videoId"]) + msg = "#{title} — #{url}" + ExIRC.Client.msg(state.client, :privmsg, chan, msg) + {:error, error} -> + ExIRC.Client.msg(state.client, :privmsg, chan, "Erreur YouTube: "<>error) + _ -> + nil + end + end + + defp search(query) do + query = query + |> String.strip + key = Application.get_env(:lsg, __MODULE__)[:api_key] + params = %{ + "key" => key, + "maxResults" => 1, + "part" => "snippet", + "safeSearch" => "none", + "type" => "video", + "q" => query, + } + url = "https://www.googleapis.com/youtube/v3/search" + case HTTPoison.get(url, [], params: params) do + {:ok, %HTTPoison.Response{status_code: 200, body: body}} -> Jason.decode(body) + {:ok, %HTTPoison.Response{status_code: 400, body: body}} -> + Logger.error "YouTube HTTP 400: #{inspect body}" + {:error, "http 400"} + error -> + Logger.error "YouTube http error: #{inspect error}" + :error + end + end + +end diff --git a/lib/lsg_web/controllers/irc_controller.ex b/lib/lsg_web/controllers/irc_controller.ex new file mode 100644 index 0000000..a5a68f7 --- /dev/null +++ b/lib/lsg_web/controllers/irc_controller.ex @@ -0,0 +1,51 @@ +defmodule LSGWeb.IrcController do + use LSGWeb, :controller + + def index(conn, _) do + commands = for mod <- Application.get_env(:lsg, :irc)[:handlers] do + mod.irc_doc() + end + render conn, "index.html", commands: commands + end + + def txt(conn, %{"name" => name}), do: do_txt(conn, name) + def txt(conn, _), do: do_txt(conn, nil) + + defp do_txt(conn, nil) do + render conn, "txts.html", data: data() + end + + defp do_txt(conn, txt) do + data = data() + if Map.has_key?(data, txt) do + render(conn, "txt.html", name: txt, data: data[txt]) + else + conn + |> put_status(404) + end + end + + defp data() do + dir = Application.get_env(:lsg, LSG.IRC.TxtHandler)[:directory] + Path.wildcard(dir <> "/*.txt") + |> Enum.reduce(%{}, fn(path, m) -> + path = String.split(path, "/") + file = List.last(path) + [key, "txt"] = String.split(file, ".", parts: 2) + data = dir <> file + |> File.read! + |> String.split("\n") + |> Enum.reject(fn(line) -> + cond do + line == "" -> true + !line -> true + true -> false + end + end) + Map.put(m, key, data) + end) + |> Enum.sort + |> Enum.into(Map.new) + end + +end diff --git a/lib/lsg_web/controllers/page_controller.ex b/lib/lsg_web/controllers/page_controller.ex index 3d4e444..b356b9c 100644 --- a/lib/lsg_web/controllers/page_controller.ex +++ b/lib/lsg_web/controllers/page_controller.ex @@ -5,6 +5,17 @@ defmodule LSGWeb.PageController do render conn, "index.html" end + def api(conn, _params) do + render conn, "api.html" + end + + def irc(conn, _) do + bot_helps = for mod <- Application.get_env(:lsg, :irc)[:handlers] do + mod.irc_doc() + end + render conn, "irc.html", bot_helps: bot_helps + end + def icecast(conn, _params) do conn |> json(LSG.IcecastAgent.get) diff --git a/lib/lsg_web/router.ex b/lib/lsg_web/router.ex index db0e5cd..9373e85 100644 --- a/lib/lsg_web/router.ex +++ b/lib/lsg_web/router.ex @@ -14,9 +14,14 @@ defmodule LSGWeb.Router do end scope "/", LSGWeb do - pipe_through :browser # Use the default browser stack - + pipe_through :browser + get "/", PageController, :index get "/embed/widget", PageController, :widget + get "/api", PageController, :api + + get "/irc", IrcController, :index + get "/irc/txt", IrcController, :txt + get "/irc/txt/:name", IrcController, :txt end scope "/api", LSGWeb do diff --git a/lib/lsg_web/templates/irc/index.html.eex b/lib/lsg_web/templates/irc/index.html.eex new file mode 100644 index 0000000..91873e6 --- /dev/null +++ b/lib/lsg_web/templates/irc/index.html.eex @@ -0,0 +1,29 @@ +<h1>bot `115ans</h1> + +<p> +Si vous cherchez l'IRC c'est <a href="https://115ans.net/irc/">par là</a>. +<br /> +<a href="/irc/stats/">Statistiques</a>. +</p> + + +<style type="text/css"> +.help-entry h1 { + font-size: 18px; +} +.help-entry h2 { + font-size: 16px; +} +</style> + +<div class="irchelps"> + <%= for help <- @commands do %> + <div class="help-entry"><%= help |> Earmark.as_html! |> raw() %></div> + <% end %> +</div> + +<p> +<small> + source: <a href="https://git.yt/115ans/sys">git.yt/115ans/sys</a> +</small> +</p> diff --git a/lib/lsg_web/templates/irc/txt.html.eex b/lib/lsg_web/templates/irc/txt.html.eex new file mode 100644 index 0000000..4ffde50 --- /dev/null +++ b/lib/lsg_web/templates/irc/txt.html.eex @@ -0,0 +1,19 @@ +<style type="text/css"> +h1 small { + font-size: 14px; +} +ol li { + margin-bottom: 5px +} +</style> + +<h1> + <small><a href="/irc/txt">irc.txt</a>:</small><br/> + <%= @name %>.txt</h1> + +<ol> + <%= for {txt, id} <- Enum.with_index(@data) do %> + <li id="<%= @name %>-<%= id %>"><%= txt %></li> + <% end %> +</ol> + diff --git a/lib/lsg_web/templates/irc/txts.html.eex b/lib/lsg_web/templates/irc/txts.html.eex new file mode 100644 index 0000000..7c96ed9 --- /dev/null +++ b/lib/lsg_web/templates/irc/txts.html.eex @@ -0,0 +1,8 @@ +<h1>irc.txt</h1> + +<ul> + <%= for {txt, data} <- @data do %> + <li><a href="/irc/txt/<%= txt %>"><%= txt %></a> <i>(<%= Enum.count(data) %>)</i></li> + <% end %> +</ul> + diff --git a/lib/lsg_web/templates/layout/app.html.eex b/lib/lsg_web/templates/layout/app.html.eex index 0d91f12..1c8f900 100644 --- a/lib/lsg_web/templates/layout/app.html.eex +++ b/lib/lsg_web/templates/layout/app.html.eex @@ -4,32 +4,15 @@ <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> - <meta name="description" content=""> - <meta name="author" content=""> - - <title>Hello LSG!</title> - <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>"> + <link rel="stylesheet" href="<%= static_path(@conn, "/assets/css/app.css") %>"> </head> <body> <div class="container"> - <header class="header"> - <nav role="navigation"> - <ul class="nav nav-pills pull-right"> - <li><a href="http://www.phoenixframework.org/docs">Get Started</a></li> - </ul> - </nav> - <span class="logo"></span> - </header> - - <p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p> - <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p> - <main role="main"> <%= render @view_module, @view_template, assigns %> </main> - - </div> <!-- /container --> - <script src="<%= static_path(@conn, "/js/app.js") %>"></script> + </div> + <script src="<%= static_path(@conn, "/assets/js/app.js") %>"></script> </body> </html> diff --git a/lib/lsg_web/templates/page/api.html.eex b/lib/lsg_web/templates/page/api.html.eex new file mode 100644 index 0000000..03dfa6b --- /dev/null +++ b/lib/lsg_web/templates/page/api.html.eex @@ -0,0 +1,35 @@ +<h1>sys.115ans.net/api</h1> + +<h2>Icecast Status</h2> + +<h3>GET /api/icecast.json</h3> + +<p> + Content-Type: <code>application/json</code> +</p> + +<pre><code> +{ + "np": String, + "genre": null | String, + "live": false | true +} +</pre></code> + +<h3>GET /api/icecast.sse</h3> +<p> + Content-Type: <code>text/event-stream</code> +</p> + +<p> + Stream of: +</p> + + <ul> + <li><strong>icecast</strong> events (same format as <code>/api/icecast.json</code>)</li> + <li><strong>ping</strong> events (to keep-alive connection. You can safely ignore them)</li> + </ul> +<p> + On client connection, the server sends the latest <code>icecast</code> status known. +</p> + diff --git a/lib/lsg_web/templates/page/index.html.eex b/lib/lsg_web/templates/page/index.html.eex index 0988ea5..98e407c 100644 --- a/lib/lsg_web/templates/page/index.html.eex +++ b/lib/lsg_web/templates/page/index.html.eex @@ -1,36 +1 @@ -<div class="jumbotron"> - <h2><%= gettext "Welcome to %{name}!", name: "Phoenix" %></h2> - <p class="lead">A productive web framework that<br />does not compromise speed and maintainability.</p> -</div> - -<div class="row marketing"> - <div class="col-lg-6"> - <h4>Resources</h4> - <ul> - <li> - <a href="http://phoenixframework.org/docs/overview">Guides</a> - </li> - <li> - <a href="https://hexdocs.pm/phoenix">Docs</a> - </li> - <li> - <a href="https://github.com/phoenixframework/phoenix">Source</a> - </li> - </ul> - </div> - - <div class="col-lg-6"> - <h4>Help</h4> - <ul> - <li> - <a href="http://groups.google.com/group/phoenix-talk">Mailing list</a> - </li> - <li> - <a href="http://webchat.freenode.net/?channels=elixir-lang">#elixir-lang on freenode IRC</a> - </li> - <li> - <a href="https://twitter.com/elixirphoenix">@elixirphoenix</a> - </li> - </ul> - </div> -</div> +<p>Vous n'avez rien de mieux à faire ? Non ? Allez sur <a href="https://115ans.net">115ans.net</a>, alors.</p> diff --git a/lib/lsg_web/templates/page/irc.html.eex b/lib/lsg_web/templates/page/irc.html.eex new file mode 100644 index 0000000..f6598ee --- /dev/null +++ b/lib/lsg_web/templates/page/irc.html.eex @@ -0,0 +1,19 @@ +<h1>bot `115ans</h1> + +<p>Si vous cherchez l'IRC c'est <a href="https://115ans.net/irc/">par là</a>.</p> + +<style type="text/css"> +.help-entry h1 { + font-size: 18px; +} +.help-entry h2 { + font-size: 16px; +} +</style> + +<div class="irchelps"> + <%= for help <- @bot_helps do %> + <div class="help-entry"><%= help |> Earmark.as_html! |> raw() %></div> + <% end %> +</div> + diff --git a/lib/lsg_web/views/irc_view.ex b/lib/lsg_web/views/irc_view.ex new file mode 100644 index 0000000..36a9bc4 --- /dev/null +++ b/lib/lsg_web/views/irc_view.ex @@ -0,0 +1,3 @@ +defmodule LSGWeb.IrcView do + use LSGWeb, :view +end |