From 0ff0403a1bb438d85e91c4d77022b6118cf09d2b Mon Sep 17 00:00:00 2001 From: cynic Date: Fri, 22 Jul 2022 01:29:28 -0400 Subject: [PATCH] first commit --- .formatter.exs | 4 ++++ .gitignore | 26 +++++++++++++++++++++++++ README.md | 21 ++++++++++++++++++++ lib/ircked_elixir.ex | 9 +++++++++ lib/ircked_elixir/chatter.ex | 29 ++++++++++++++++++++++++++++ lib/ircked_elixir/chatter/message.ex | 20 +++++++++++++++++++ lib/ircked_elixir/chatter/privmsg.ex | 9 +++++++++ lib/ircked_elixir/overseer.ex | 15 ++++++++++++++ mix.exs | 29 ++++++++++++++++++++++++++++ test/ircked_elixir_test.exs | 4 ++++ test/test_helper.exs | 1 + 11 files changed, 167 insertions(+) create mode 100644 .formatter.exs create mode 100644 .gitignore create mode 100644 README.md create mode 100644 lib/ircked_elixir.ex create mode 100644 lib/ircked_elixir/chatter.ex create mode 100644 lib/ircked_elixir/chatter/message.ex create mode 100644 lib/ircked_elixir/chatter/privmsg.ex create mode 100644 lib/ircked_elixir/overseer.ex create mode 100644 mix.exs create mode 100644 test/ircked_elixir_test.exs create mode 100644 test/test_helper.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..d1dfc42 --- /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"). +ircked_elixir-*.tar + +# Temporary files, for example, from tests. +/tmp/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..deaf9ad --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# IrckedElixir + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `ircked_elixir` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:ircked_elixir, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at . + diff --git a/lib/ircked_elixir.ex b/lib/ircked_elixir.ex new file mode 100644 index 0000000..7ce81ef --- /dev/null +++ b/lib/ircked_elixir.ex @@ -0,0 +1,9 @@ +defmodule IrckedElixir do + use Application + + @impl true + def start(_type, _args) do + IO.puts("starting~") + IrckedElixir.Overseer.start_link(name: IrckedElixir.Overseer) + end +end diff --git a/lib/ircked_elixir/chatter.ex b/lib/ircked_elixir/chatter.ex new file mode 100644 index 0000000..3c7975c --- /dev/null +++ b/lib/ircked_elixir/chatter.ex @@ -0,0 +1,29 @@ +defmodule IrckedElixir.Chatter do + alias IrckedElixir.Chatter.Message, as: Message + alias IrckedElixir.Chatter.Privmsg, as: Privmsg + def start(server, port, nick) do + {:ok, socket} = :gen_tcp.connect(to_charlist(server), port, [:binary, active: false]) + + :gen_tcp.send(socket, ["USER ", nick, " 0 * :", nick, "\r\n"]) + :gen_tcp.send(socket, ["NICK ", nick, "\r\n"]) + + run(socket) + end + def run(socket) do + {:ok, data} = :gen_tcp.recv(socket, 0) + String.split(data, "\r\n") |> Enum.each(fn raw -> handle(Message.parse(raw), socket) end) + run(socket) + end + def handle(msg, socket) do + case msg.command do + "PING" -> Message.construct("", "PONG", msg.parameters) |> Message.send(socket) + "001" -> Message.construct("", "JOIN", ["#qrs"]) |> Message.send(socket) + "PRIVMSG" -> + pm = Privmsg.parse(msg) + IO.puts(inspect pm.message) + Privmsg.construct("functism", pm.to, "hai").message |> Message.send(socket) + "" -> "" + _ -> IO.puts(inspect msg) + end + end +end diff --git a/lib/ircked_elixir/chatter/message.ex b/lib/ircked_elixir/chatter/message.ex new file mode 100644 index 0000000..d1d0652 --- /dev/null +++ b/lib/ircked_elixir/chatter/message.ex @@ -0,0 +1,20 @@ +defmodule IrckedElixir.Chatter.Message do + defstruct prefix: "", command: "", parameters: [] + def parse(raw) do + parts = String.split(raw, " ") + + is_prefix = String.starts_with?(Enum.at(parts, 0), ":") + + pre = if(is_prefix, [do: Enum.at(parts, 0), else: ""]) + comm = if(is_prefix, [do: Enum.at(parts, 1), else: Enum.at(parts, 0)]) + param = if(is_prefix, [do: Enum.slice(parts, 2..999), else: Enum.slice(parts, 1..999)]) + %IrckedElixir.Chatter.Message{prefix: pre, command: comm, parameters: param} + end + def construct(prefix, command, parameters) do + %IrckedElixir.Chatter.Message{prefix: prefix, command: command, parameters: parameters} + end + def send(msg, socket) do + :gen_tcp.send(socket, [if(msg.prefix == "", [do: "", else: msg.prefix<>" "]), msg.command, " ", Enum.join(msg.parameters, " "), "\r\n"]) + IO.puts([if(msg.prefix == "", [do: "", else: msg.prefix<>" "]), msg.command, " ", Enum.join(msg.parameters, " "), "\r\n"]) + end +end diff --git a/lib/ircked_elixir/chatter/privmsg.ex b/lib/ircked_elixir/chatter/privmsg.ex new file mode 100644 index 0000000..c813620 --- /dev/null +++ b/lib/ircked_elixir/chatter/privmsg.ex @@ -0,0 +1,9 @@ +defmodule IrckedElixir.Chatter.Privmsg do + defstruct message: %IrckedElixir.Chatter.Message{}, from: "", to: "", body: "" + def parse(message) do + %IrckedElixir.Chatter.Privmsg{message: message, from: String.slice(message.prefix, 1..999), to: Enum.at(message.parameters, 0), body: Enum.join(Enum.slice(message.parameters, 1..999), " ")} + end + def construct(from, to, body) do + %IrckedElixir.Chatter.Privmsg{message: %IrckedElixir.Chatter.Message{prefix: ":"<>from, command: "PRIVMSG", parameters: ([] |> List.insert_at(0, to)) ++ String.split(":"<>body, " ")}, from: from, to: to, body: body} + end +end diff --git a/lib/ircked_elixir/overseer.ex b/lib/ircked_elixir/overseer.ex new file mode 100644 index 0000000..c7c2b89 --- /dev/null +++ b/lib/ircked_elixir/overseer.ex @@ -0,0 +1,15 @@ +defmodule IrckedElixir.Overseer do + use Supervisor + + def start_link(opts) do + Supervisor.start_link(__MODULE__, :ok, opts) + end + + @impl true + def init(:ok) do + children = [ + {Task, fn -> IrckedElixir.Chatter.start("localhost", 6667, "functism") end} + ] + Supervisor.init(children, strategy: :one_for_one) + end +end diff --git a/mix.exs b/mix.exs new file mode 100644 index 0000000..97c5fa6 --- /dev/null +++ b/mix.exs @@ -0,0 +1,29 @@ +defmodule IrckedElixir.MixProject do + use Mix.Project + + def project do + [ + app: :ircked_elixir, + 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: {IrckedElixir, []}, + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {: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/test/ircked_elixir_test.exs b/test/ircked_elixir_test.exs new file mode 100644 index 0000000..94363a6 --- /dev/null +++ b/test/ircked_elixir_test.exs @@ -0,0 +1,4 @@ +defmodule IrckedElixirTest do + use ExUnit.Case + doctest IrckedElixir +end 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()