README.md

# Hanabi

Hanabi is a (work in progress) IRC server designed to build bridges between
services.

Since Hanabi is an IRC server, messages and errors are designed to match the
definitions of the IRC specification
([RFC1459](https://tools.ietf.org/html/rfc1459)) : see `Hanabi.IRC.Message` for
message structures and `Hanabi.IRC.Numeric` for reply/error codes. Most of
the interactions with this library are done via the `Hanabi.User` and
`Hanabi.Channel` modules.

## Useful links

  * Documentation [on hexdocs.pm](https://hexdocs.pm/hanabi/readme.html).
  * Changelog [on github.com](https://github.com/Fnux/hanabi/blob/master/CHANGELOG.md).
  * Internet Relay Chat Protocol : [RFC1459](https://tools.ietf.org/html/rfc1459),
    [RFC2811](https://tools.ietf.org/html/rfc2811),
    [modern.ircdocs.horse](https://modern.ircdocs.horse/)
  * Parts of the IRC-related code were inspired by
[radar/elixir-irc](https://github.com/radar/elixir-irc).

## Configuration

In order to use this library, you must add `hanabi` to your list of depenencies
in `mix.exs` :

```elixir
def deps do
  [
    {:hanabi, "~> 0.1.0"}
  ]
end
```

You also have to add the following to your `config/config.exs` file :

```
config :hanabi, port: 6667,
                hostname: "my.awesome.hostname",
                motd: "/path/to/motd.txt"
```

## Examples

Here are a few basic example. Feel free to ask for more examples
[here](https://github.com/Fnux/hanabi/) !

### Sending a private message to an user/channel

```elixir
# Sending to an user
iex> receiver = Hanabi.User.get_by(:nick, "fnux")
%Hanabi.User{channels: ["#test"], hostname: 'localhost', key: #Port<0.5044>,
 nick: "fnux", pid: nil, port: #Port<0.5044>, realname: "realname", type: :irc,
 username: "fnux"}

iex> sender = Hanabi.User.get_by(:nick, "sender")
# ...

###
# Using the helper
iex> Hanabi.User.send_privmsg sender, receiver, "Hello fnux! How are you?"
:ok

###
# Manually
iex> msg = %Hanabi.IRC.Message{prefix: Hanabi.User.ident_for(sender),
command: "PRIVMSG", middle: receiver.nick, trailing: "Hello fnux! How are you?"}
# ...

iex> Hanabi.User.send receiver, msg
:ok
```

```elixir
# Sending to a channel
iex> user = Hanabi.User.get_by(:nick, "fnux")
%Hanabi.User{channels: ["#test"], hostname: 'localhost', key: #Port<0.5044>,
 nick: "fnux", pid: nil, port: #Port<0.5044>, realname: "realname", type: :irc,
 username: "fnux"}

###
# Using the helper
iex> Hanabi.Channel.send_privmsg sender, "#test", "Hi there!"
:ok

###
# Manually
iex> msg = %Hanabi.IRC.Message{prefix: Hanabi.User.ident_for(sender),
command: "PRIVMSG", middle: "#test", trailing: "Hi there!"}
# ...

iex> Hanabi.Channel.broadcast "#test", msg
:ok
```

### Simple handling of a virtual user

```elixir
defmodule MyApp.IrcUser do
  alias Hanabi.User
  use GenServer

  @user %User{key: :default, type: :virtual, nick: "default",
  username: "default", realname: "Default User", hostname: "localhost"}

  def start_link() do
    GenServer.start_link(__MODULE__, nick)
  end

  def init(nick) do
    # register itself as the `default` user
    user = struct(@user, pid: self())
    {:ok, user.key} = User.add(user)
  end

  def handle_info(%Message{}=msg, state) do
    # msg is a message's struct as defined in Hanabi.IRC.Message :
    # %Hanabi.IRC.Message{prefix: "sender!~sender@localhost",
    # command: "PRIVMSG", middle: "default",
    # trailing: "Hi! How are you?"}
 
    # do stuff

    {:noreply, state}
  end

  # catch-all used for debugging
  def handle_info(msg, state) do
    IO.inspect msg

    {:noreply, state}
  end
end
```