• Stars
    star
    152
  • Rank 244,685 (Top 5 %)
  • Language
    Elixir
  • License
    MIT License
  • Created almost 11 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

IRC client adapter for Elixir projects

ExIRC

Build Status .github/workflows/tests.yaml Hex.pm Version

ExIRC is a IRC client library for Elixir projects. It aims to have a clear, well documented API, with the minimal amount of code necessary to allow you to connect and communicate with IRC servers effectively. It aims to implement the full RFC2812 protocol, and relevant parts of RFC1459.

Getting Started

Add ExIRC as a dependency to your project in mix.exs, and add it as an application:

  defp deps do
    [{:exirc, "~> x.x.x"}]
  end

  defp application do
    [applications: [:exirc],
     ...]
  end

Then fetch it using mix deps.get.

To use ExIRC, you need to start a new client process, and add event handlers. An example event handler module is located in lib/exirc/example_handler.ex. The example handler is kept up to date with all events you can expect to receive from the client. A simple module is defined below as an example of how you might use ExIRC in practice. ExampleHandler here is the one that comes bundled with ExIRC.

There is also a variety of examples in examples, the most up to date of which is examples/bot.

defmodule ExampleSupervisor do
    defmodule State do
        defstruct host: "chat.freenode.net",
                  port: 6667,
                  pass: "",
                  nick: "bitwalker",
                  user: "bitwalker",
                  name: "Paul Schoenfelder",
                  client: nil,
                  handlers: []
    end

    def start_link(_) do
        :gen_server.start_link(__MODULE__, [%State{}])
    end

    def init(state) do
        # Start the client and handler processes, the ExIRC supervisor is automatically started when your app runs
        {:ok, client}  = ExIRC.start_link!()
        {:ok, handler} = ExampleHandler.start_link(nil)

        # Register the event handler with ExIRC
        ExIRC.Client.add_handler client, handler

        # Connect and logon to a server, join a channel and send a simple message
        ExIRC.Client.connect!   client, state.host, state.port
        ExIRC.Client.logon      client, state.pass, state.nick, state.user, state.name
        ExIRC.Client.join       client, "#elixir-lang"
        ExIRC.Client.msg        client, :privmsg, "#elixir-lang", "Hello world!"

        {:ok, %{state | :client => client, :handlers => [handler]}}
    end

    def terminate(_, state) do
        # Quit the channel and close the underlying client connection when the process is terminating
        ExIRC.Client.quit state.client, "Goodbye, cruel world."
        ExIRC.Client.stop! state.client
        :ok
    end
end

A more robust example usage will wait until connected before it attempts to logon and then wait until logged on until it attempts to join a channel. Please see the examples directory for more in-depth examples cases.

defmodule ExampleApplication do
  use Application

  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @impl true
  def start(_type, _args) do
    {:ok, client} = ExIRC.start_link!

    children = [
      # Define workers and child supervisors to be supervised
      {ExampleConnectionHandler, client},
      # here's where we specify the channels to join:
      {ExampleLoginHandler, [client, ["#ohaibot-testing"]]}
    ]

    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: ExampleApplication.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

defmodule ExampleConnectionHandler do
  defmodule State do
    defstruct host: "chat.freenode.net",
              port: 6667,
              pass: "",
              nick: "bitwalker",
              user: "bitwalker",
              name: "Paul Schoenfelder",
              client: nil
  end

  def start_link(client, state \\ %State{}) do
    GenServer.start_link(__MODULE__, [%{state | client: client}])
  end

  def init([state]) do
    ExIRC.Client.add_handler state.client, self
    ExIRC.Client.connect! state.client, state.host, state.port
    {:ok, state}
  end

  def handle_info({:connected, server, port}, state) do
    debug "Connected to #{server}:#{port}"
    ExIRC.Client.logon state.client, state.pass, state.nick, state.user, state.name
    {:noreply, state}
  end

  # Catch-all for messages you don't care about
  def handle_info(msg, state) do
    debug "Received unknown messsage:"
    IO.inspect msg
    {:noreply, state}
  end

  defp debug(msg) do
    IO.puts IO.ANSI.yellow() <> msg <> IO.ANSI.reset()
  end
end

defmodule ExampleLoginHandler do
  @moduledoc """
  This is an example event handler that listens for login events and then
  joins the appropriate channels. We actually need this because we can't
  join channels until we've waited for login to complete. We could just
  attempt to sleep until login is complete, but that's just hacky. This
  as an event handler is a far more elegant solution.
  """
  def start_link(client, channels) do
    GenServer.start_link(__MODULE__, [client, channels])
  end

  def init([client, channels]) do
    ExIRC.Client.add_handler client, self
    {:ok, {client, channels}}
  end

  def handle_info(:logged_in, state = {client, channels}) do
    debug "Logged in to server"
    channels |> Enum.map(&ExIRC.Client.join client, &1)
    {:noreply, state}
  end

  # Catch-all for messages you don't care about
  def handle_info(_msg, state) do
    {:noreply, state}
  end

  defp debug(msg) do
    IO.puts IO.ANSI.yellow() <> msg <> IO.ANSI.reset()
  end
end

Projects using ExIRC (in the wild!)

Below is a list of projects that we know of (if we've missed anything, send a PR!) that use ExIRC in the wild.

More Repositories

1

distillery

Simplify deployments in Elixir with OTP releases!
Elixir
2,944
star
2

timex

A complete date/time library for Elixir projects.
Elixir
1,732
star
3

swarm

Easy clustering, registration, and distribution of worker processes for Erlang/Elixir
Elixir
1,201
star
4

exrm

Automatically generate a release for your Elixir project!
Elixir
923
star
5

exprotobuf

Protocol Buffers in Elixir made easy!
Elixir
485
star
6

libgraph

A graph data structure library for Elixir projects
Elixir
454
star
7

conform

Easy, powerful, and extendable configuration tooling for releases.
Elixir
378
star
8

keys.js

Easy keybindings for browser applications!
JavaScript
360
star
9

alpine-elixir-phoenix

An Alpine Linux base image containing Elixir, Erlang, Node, Hex, and Rebar. Ready for Phoenix applications!
Makefile
349
star
10

alpine-elixir

A Dockerfile based on my alpine-erlang image for Elixir applications
Makefile
202
star
11

toml-elixir

An implementation of TOML for Elixir projects, compliant with the latest specification
Elixir
196
star
12

combine

A parser combinator library for Elixir projects
Elixir
194
star
13

libring

A fast consistent hash ring implementation in Elixir
Elixir
192
star
14

timex_ecto

An adapter for using Timex DateTimes with Ecto
Elixir
161
star
15

artificery

A toolkit for creating terminal user interfaces in Elixir
Elixir
121
star
16

alpine-erlang

An alpine image with Erlang installed, intended for releases
Dockerfile
82
star
17

strukt

Extends defstruct with schemas, changeset validation, and more
Elixir
71
star
18

ex_unit_clustered_case

An extension for ExUnit for simplifying tests against a clustered application
Elixir
57
star
19

uniq

Provides UUID generation, parsing, and formatting. Supports RFC 4122, and the v6 draft extension
Elixir
52
star
20

distillery-aws-example

An example application to go with the AWS guide in the Distillery documentation
Elixir
50
star
21

distillery-umbrella-test

An example Elixir application for working with umbella apps and Distillery.
Elixir
49
star
22

pluginhost

An example C# application which provides runtime extensibility via plugins
C#
31
star
23

picosat_elixir

Elixir + Erlang bindings for the PicoSAT solver
C
17
star
24

docker-release-toolkit

My personal toolkit for building releases with Docker
Makefile
16
star
25

distillery-test

Elixir application which demonstrates a bare-minimum release-ready app using Distillery.
Elixir
16
star
26

8bit-background

A sweet series of 8-bit backgrounds, which changes based on the time of day.
Shell
15
star
27

libswagger

A Swagger client library for Elixir projects
Elixir
15
star
28

stringex

A string extensions library for node.js
JavaScript
15
star
29

scaladiff

A diff library built in Scala, for Scala projects
Scala
13
star
30

dotfiles

My assorted dotfiles
Shell
10
star
31

resume

The TeX source for my current resume.
TeX
7
star
32

fogbugz-cli

FogBugz Command Line Client
Ruby
7
star
33

aria

An experiment in programming language design
7
star
34

s2i-alpine-base

An S2I base image using Alpine Linux
Python
5
star
35

RPNCalculator

Reverse Polish Notation calculator built in Scala for a impromptu code challenge at work
Scala
5
star
36

uniq_compat

A compatibility shim for ::elixir_uuid when used with :uniq
Elixir
4
star
37

aws-dist-test

Clone of distillery-aws-example to illustrate distribution
Elixir
4
star
38

centos7-elixir

A CentOS7 base image for use with the Distillery AWS guide
Dockerfile
4
star
39

firefly

TBD
Elixir
3
star
40

conform_exrm

Conform plugin for ExRM
Elixir
3
star
41

alpine-toolbox

A toolbox image based on Alpine Linux for when I want to troubleshoot things in my OpenShift cluster
Makefile
3
star
42

SharpTools

A collection of practical C# code to build upon
C#
2
star
43

functools

Functional programming tools for Go
Go
2
star
44

toolbox.js

A general purpose javascript utility library. Contains everything you need, and most anything worth having (other than DOM manipulation).
JavaScript
1
star
45

erl_tar2

A re-implementation of erl_tar to support common tar archive formats
Erlang
1
star
46

s2i-elixir

An S2I image which provides Elixir, Erlang, and Node.js
Shell
1
star
47

blog

My personal blog source
CSS
1
star
48

s2i-erlang

An S2I image which provides Erlang and Node.js
Shell
1
star