diff --git a/.formatter.exs b/.formatter.exs index d304ff3..d2cda26 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -1,3 +1,4 @@ +# Used by "mix format" [ inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] ] diff --git a/.gitignore b/.gitignore index b48064a..3828b1f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,31 @@ -/_build -/deps -/doc +# 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 -.idea -*.iml +# Ignore package tarball (built via "mix hex.build"). +slack-*.tar + +# Temporary files for e.g. tests. +/tmp +# Misc. .elixir_ls/ +.idea +*.iml diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md diff --git a/README.md b/README.md index b2c658e..dc71106 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,15 @@ -[![Build -Status](https://api.travis-ci.org/BlakeWilliams/Elixir-Slack.svg?branch=master)](https://travis-ci.org/BlakeWilliams/Elixir-Slack) - # Elixir-Slack +[![Elixir CI](https://github.com/BlakeWilliams/Elixir-Slack/actions/workflows/elixir.yml/badge.svg)](https://github.com/BlakeWilliams/Elixir-Slack/actions/workflows/elixir.yml) +[![Module Version](https://img.shields.io/hexpm/v/slack.svg)](https://hex.pm/packages/slack) +[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/slack/) +[![Total Download](https://img.shields.io/hexpm/dt/slack.svg)](https://hex.pm/packages/slack) +[![License](https://img.shields.io/hexpm/l/slack.svg)](https://github.com/BlakeWilliams/Elixir-Slack/blob/master/LICENSE.md) +[![Last Updated](https://img.shields.io/github/last-commit/BlakeWilliams/Elixir-Slack.svg)](https://github.com/BlakeWilliams/Elixir-Slack/commits/master) + This is a Slack [Real Time Messaging API] client for Elixir. You'll need a Slack API token which can be retrieved by following the [Token Generation -Instructions] or by creating a -new [bot integration]. +Instructions] or by creating a new [bot integration]. [Real time Messaging API]: https://api.slack.com/rtm [Token Generation Instructions]: https://hexdocs.pm/slack/token_generation_instructions.html @@ -14,17 +17,21 @@ new [bot integration]. ## Installing -Add Slack to your `mix.exs` `dependencies` function. +Add `:slack` to your `mix.exs` `dependencies` function: [websocket_client]: https://github.com/jeremyong/websocket_client ```elixir def application do - [extra_applications: [:logger]] + [ + extra_applications: [:logger] + ] end def deps do - [{:slack, "~> 0.23.6"}] + [ + {:slack, "~> 0.23.6"} + ] end ``` @@ -45,7 +52,7 @@ slack |> Map.put(:users, Slack.Web.Users.list(%{token: token}) |> Map.get("members")) ``` -## RTM (Bot) Usage +## Real Time Messaging (RTM) Bot Usage Define a module that uses the Slack behaviour and defines the appropriate callback methods. @@ -170,3 +177,9 @@ config :slack, url: "http://localhost:8000" ``` [documentation]: http://hexdocs.pm/slack/ + +## Copyright and License + +Copyright (c) 2014 Blake Williams + +Source code is released under [the MIT license](./LICENSE.md). diff --git a/guides/token_generation_instructions.md b/guides/token_generation_instructions.md index e90e5cc..bac4136 100644 --- a/guides/token_generation_instructions.md +++ b/guides/token_generation_instructions.md @@ -4,8 +4,11 @@ 2. If you have already created your app then click on it, otherwise create a new app. 3. Click on "Add features and functionality" to expand that section 4. Click on "Permissions" + ![Step 4](./assets/access-token1.png "Step 4 Screenshot") + 5. Copy the "OAuth Access Token" + ![Step 5](./assets/access-token2.png "Step 5 Screenshot") -Note: The Elixir Slack library only uses the "OAuth Access Token" or "Bot User OAuth Access Token", it does not use the "Client ID", "Client Secret", "Signing Secret", or "Verification Token" +Note: The Elixir Slack library only uses the "OAuth Access Token" or "Bot User OAuth Access Token", it does not use the "Client ID", "Client Secret", "Signing Secret", or "Verification Token". diff --git a/lib/mix/tasks/update_slack_api.exs b/lib/mix/tasks/update_slack_api.exs index 1af0c84..3150b83 100644 --- a/lib/mix/tasks/update_slack_api.exs +++ b/lib/mix/tasks/update_slack_api.exs @@ -1,5 +1,7 @@ defmodule Mix.Tasks.UpdateSlackApi do - @moduledoc "Updates Slack API documentation files for generating API code" + @moduledoc """ + Updates Slack API documentation files for generating API code. + """ use Mix.Task @dir System.tmp_dir() diff --git a/lib/slack.ex b/lib/slack.ex index 2daf15c..13b2d39 100644 --- a/lib/slack.ex +++ b/lib/slack.ex @@ -10,7 +10,7 @@ defmodule Slack do [Token Generation Instructions]: https://hexdocs.pm/slack/token_generation_instructions.html [bot integration]: https://api.slack.com/bot-users - ## Example + ## Examples ``` defmodule Bot do diff --git a/lib/slack/bot.ex b/lib/slack/bot.ex index dcc4bd8..ba30ed9 100644 --- a/lib/slack/bot.ex +++ b/lib/slack/bot.ex @@ -1,13 +1,13 @@ defmodule Slack.Bot do - require Logger - - @behaviour :websocket_client - @moduledoc """ This module is used to spawn bots and is used to manage the connection to Slack while delegating events to the specified bot module. """ + require Logger + + @behaviour :websocket_client + @doc """ Connects to Slack and delegates events to `bot_handler`. @@ -16,11 +16,11 @@ defmodule Slack.Bot do * `keepalive` - How long to wait for the connection to respond before the client kills the connection. * `name` - registers a name for the process with the given atom - ## Example + ## Examples - {:ok, pid} = Slack.Bot.start_link(MyBot, [1,2,3], "abc-123", %{name: :slack_bot}) + {:ok, pid} = Slack.Bot.start_link(MyBot, [1,2,3], "abc-123", %{name: :slack_bot}) - :sys.get_state(:slack_bot) + :sys.get_state(:slack_bot) """ def start_link(bot_handler, initial_state, token, options \\ %{}) do diff --git a/lib/slack/lookups.ex b/lib/slack/lookups.ex index c568907..b775746 100644 --- a/lib/slack/lookups.ex +++ b/lib/slack/lookups.ex @@ -1,4 +1,8 @@ defmodule Slack.Lookups do + @moduledoc """ + Utility functions for looking up slack state information. + """ + require Logger @username_warning """ @@ -6,8 +10,6 @@ defmodule Slack.Lookups do For more information see https://api.slack.com/changelog/2017-09-the-one-about-usernames """ - @moduledoc "Utility functions for looking up slack state information" - @doc ~S""" Turns a string like `"@USER_NAME"` into the ID that Slack understands (`"U…"`). @@ -84,15 +86,13 @@ defmodule Slack.Lookups do end @doc ~S""" - Turns a Slack channel ID (`"C…"`) into a string in the format "#CHANNEL_NAME". + Turns a Slack channel ID (`"C…"`) or a Slack private channel ID (`"G…"`) into + a string in the format "#CHANNEL_NAME". """ def lookup_channel_name(channel_id = "C" <> _id, slack) do "#" <> slack.channels[channel_id].name end - @doc ~S""" - Turns a Slack private channel ID (`"G…"`) into a string in the format "#CHANNEL_NAME". - """ def lookup_channel_name(channel_id = "G" <> _id, slack) do "#" <> slack.groups[channel_id].name end diff --git a/lib/slack/sends.ex b/lib/slack/sends.ex index d20a729..f5ed0de 100644 --- a/lib/slack/sends.ex +++ b/lib/slack/sends.ex @@ -1,5 +1,8 @@ defmodule Slack.Sends do - @moduledoc "Utility functions for sending slack messages" + @moduledoc """ + Utility functions for sending slack messages. + """ + alias Slack.Lookups @doc """ diff --git a/lib/slack/state.ex b/lib/slack/state.ex index 5a5547f..c3bf6a2 100644 --- a/lib/slack/state.ex +++ b/lib/slack/state.ex @@ -1,5 +1,8 @@ defmodule Slack.State do - @moduledoc "Slack state" + @moduledoc """ + Slack state. + """ + @behaviour Access def fetch(client, key) diff --git a/lib/slack/web/client.ex b/lib/slack/web/client.ex index c957d6f..79c1f06 100644 --- a/lib/slack/web/client.ex +++ b/lib/slack/web/client.ex @@ -9,7 +9,7 @@ defmodule Slack.Web.Client do @type body :: form_body() | multipart_form_body() @doc """ - Return value is passed directly to caller of generated Web API + Returned value is passed directly to caller of generated Web API module/functions. Can be any term. """ @callback post!(url :: url, body :: body) :: term() diff --git a/lib/slack/web/default_client.ex b/lib/slack/web/default_client.ex index 57484c2..4633d60 100644 --- a/lib/slack/web/default_client.ex +++ b/lib/slack/web/default_client.ex @@ -10,9 +10,10 @@ defmodule Slack.Web.DefaultClient do Additional error handling or response wrapping can be controlled as needed by configuring a custom client module. - ``` - config :slack, :web_http_client, YourApp.CustomClient - ``` + ## Examples + + config :slack, :web_http_client, YourApp.CustomClient + """ @behaviour Slack.Web.Client diff --git a/mix.exs b/mix.exs index 1aaa4cf..f62953f 100644 --- a/mix.exs +++ b/mix.exs @@ -1,17 +1,18 @@ defmodule Slack.Mixfile do use Mix.Project + @source_url "https://github.com/BlakeWilliams/Elixir-Slack" + @version "0.23.6" + def project do [ app: :slack, - version: "0.23.6", + version: @version, elixir: "~> 1.7", elixirc_paths: elixirc_paths(Mix.env()), name: "Slack", deps: deps(), docs: docs(), - source_url: "https://github.com/BlakeWilliams/Elixir-Slack", - description: "A Slack Real Time Messaging API client.", package: package() ] end @@ -30,7 +31,7 @@ defmodule Slack.Mixfile do {:httpoison, "~> 1.2"}, {:websocket_client, "~> 1.2.4"}, {:jason, "~> 1.1"}, - {:ex_doc, "~> 0.19", only: :dev}, + {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, {:credo, "~> 0.5", only: [:dev, :test]}, {:plug, "~> 1.6", only: :test}, {:cowboy, "~> 1.0.0", only: :test} @@ -39,21 +40,27 @@ defmodule Slack.Mixfile do def docs do [ - {:main, Slack}, - {:assets, "guides/assets"}, - {:extra_section, "GUIDES"}, - {:extras, ["guides/token_generation_instructions.md"]} + extras: [ + {:"LICENSE.md", [title: "License"]}, + {:"README.md", [title: "Overview"]}, + "guides/token_generation_instructions.md" + ], + main: "readme", + source_url: @source_url, + assets: "guides/assets", + extra_section: "GUIDES", + formatters: ["html"] ] end defp package do - %{ + [ + description: "A Slack Real Time Messaging API client.", maintainers: ["Blake Williams"], licenses: ["MIT"], links: %{ - Github: "https://github.com/BlakeWilliams/Elixir-Slack", - Documentation: "http://hexdocs.pm/slack/" + GitHub: @source_url } - } + ] end end diff --git a/mix.lock b/mix.lock index b121288..c29fe60 100644 --- a/mix.lock +++ b/mix.lock @@ -5,17 +5,19 @@ "cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm", "db622da03aa039e6366ab953e31186cc8190d32905e33788a1acb22744e6abd2"}, "credo": {:hex, :credo, "0.10.0", "66234a95effaf9067edb19fc5d0cd5c6b461ad841baac42467afed96c78e5e9e", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "893f53d5a5cb0bb6f96bde8732c20376e24be208fa052bdefd49119f77b64df6"}, "earmark": {:hex, :earmark, "1.3.1", "73812f447f7a42358d3ba79283cfa3075a7580a3a2ed457616d6517ac3738cb9", [:mix], [], "hexpm", "000aaeff08919e95e7aea13e4af7b2b9734577b3e6a7c50ee31ee88cab6ec4fb"}, - "ex_doc": {:hex, :ex_doc, "0.19.3", "3c7b0f02851f5fc13b040e8e925051452e41248f685e40250d7e40b07b9f8c10", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "0e11d67e662142fc3945b0ee410c73c8c956717fbeae4ad954b418747c734973"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"}, + "ex_doc": {:hex, :ex_doc, "0.24.2", "e4c26603830c1a2286dae45f4412a4d1980e1e89dc779fcd0181ed1d5a05c8d9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "e134e1d9e821b8d9e4244687fb2ace58d479b67b282de5158333b0d57c6fb7da"}, "hackney": {:hex, :hackney, "1.13.0", "24edc8cd2b28e1c652593833862435c80661834f6c9344e84b6a2255e7aeef03", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "4d605d33dd07ee1b82b105033cccb02379515105fceb1850746591814b00c205"}, "httpoison": {:hex, :httpoison, "1.2.0", "2702ed3da5fd7a8130fc34b11965c8cfa21ade2f232c00b42d96d4967c39a3a3", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "712d9b1dfde2470ed000dff4b2faddaf56d038e5ac1944abc0a81c901a368391"}, "idna": {:hex, :idna, "5.1.2", "e21cb58a09f0228a9e0b95eaa1217f1bcfc31a1aaa6e1fdf2f53a33f7dbd9494", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "8fddb3aec4692c71647d67de72536254bce9069851754e370a99f2aae69fbdf4"}, "jason": {:hex, :jason, "1.1.1", "d3ccb840dfb06f2f90a6d335b536dd074db748b3e7f5b11ab61d239506585eb2", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "639645cfac325e34938167b272bae0791fea3a34cf32c29525abf1d323ed4c18"}, - "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5fbc8e549aa9afeea2847c0769e3970537ed302f93a23ac612602e805d9d1e7f"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "adf0218695e22caeda2820eaba703fa46c91820d53813a2223413da3ef4ba515"}, + "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "1.3.0", "5e8d45a39e95c650900d03f897fbf99ae04f60ab1daa4a34c7a20a5151b7a5fe", [:mix], [], "hexpm", "5e839994289d60326aa86020c4fbd9c6938af188ecddab2579f07b66cd665328"}, "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm", "7a4c8e1115a2732a67d7624e28cf6c9f30c66711a9e92928e745c255887ba465"}, - "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm", "5c040b8469c1ff1b10093d3186e2e10dbe483cd73d79ec017993fb3985b8a9b3"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, "parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm", "578b1d484720749499db5654091ddac818ea0b6d568f2c99c562d2a6dd4aa117"}, "plug": {:hex, :plug, "1.6.2", "e06a7bd2bb6de5145da0dd950070110dce88045351224bd98e84edfdaaf5ffee", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm", "b2713c085797012661a6c10e1898a009f0cc2bae556cc00341b69600074c757b"}, "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm", "ba8836feea4b394bb718a161fc59a288fe0109b5006d6bdf97b6badfcf6f0f25"},