Skip to content

Instantly share code, notes, and snippets.

@boudra
Created September 14, 2020 09:22
Show Gist options
  • Save boudra/f84a7680ba6688eea23471fa9032de3a to your computer and use it in GitHub Desktop.
Save boudra/f84a7680ba6688eea23471fa9032de3a to your computer and use it in GitHub Desktop.
defmodule TBOE.Tasks.LunchBot do
@token "token here"
@channel "#lunch-bot"
@slack_endpoint "https://slack.com/api"
@last_couples_file "/tmp/lunch_last_couples.txt"
@greeting """
Hello @channel :wave:
:point_down: Here are next week's couples! have coffee or lunch anytime next week with the person you've been paired with :hugging_face:
{{couples}}
Bon profit :yum: and remember to post selfies! :selfie:
_Did I forget about you? :disappointed: Don't worry, have some patience and I'll match you next week._
"""
# usernames of users you wan't to prevent from being matched
@user_blacklist [
]
@start_apps [
:hackney,
:ssl,
:httpoison
]
def config do
%{
token: @token,
channel: @channel,
greeting: @greeting
}
end
def run() do
Enum.each(@start_apps, &Application.ensure_all_started/1)
case do_run(config()) do
{:error, error} ->
raise inspect(error)
_ ->
IO.puts("success")
end
end
defp do_run(%{token: token, greeting: greeting} = config) do
with {:ok, members} <- retrieve_users(token) do
banned = @user_blacklist
filtered_members =
members
|> Enum.reject(fn user ->
user["is_bot"] || user["is_app_user"] || user["is_restricted"] || user["deleted"] ||
user["tz"] != "Europe/Amsterdam" || Enum.member?(banned, user["name"])
end)
|> Enum.map(&Map.get(&1, "id"))
user_count = Float.floor(Enum.count(filtered_members) * 0.8) |> round
last_selected_couples = last_selected_couples() |> Enum.take(user_count)
last_selected_users = last_selected_couples() |> List.flatten() |> Enum.take(user_count * 2)
couples =
filtered_members
|> Enum.sort_by(&Enum.member?(last_selected_users, &1))
|> Enum.take(user_count)
|> Enum.shuffle()
|> Enum.chunk_every(2, 2, :discard)
|> Kernel.--(last_selected_couples)
couples
|> build_text(greeting)
|> post_to_slack(config)
|> case do
{:ok, _} ->
serialized_last_couples =
couples
|> Enum.map_join("", fn [a, b] ->
"#{a},#{b}\n"
end)
File.write(@last_couples_file, serialized_last_couples, [:append])
error ->
error
end
end
end
defp last_selected_couples() do
@last_couple_file
|> File.read()
|> case do
{:ok, data} ->
data
|> String.split("\n")
|> Enum.map(&String.split(&1, ","))
{:error, _} ->
[]
end
end
defp post_to_slack(text, %{token: token, channel: channel}) do
HTTPoison.post(
"#{@slack_endpoint}/chat.postMessage",
{:form, [as_user: true, token: token, channel: channel, text: text, link_names: true]}
)
end
def build_text(couples, greeting) do
text =
couples
|> Enum.map(fn [a, b] ->
"<@#{a}> with <@#{b}>"
end)
|> Enum.join("\n")
String.replace(greeting, "{{couples}}", text)
end
def retrieve_users(token) do
case HTTPoison.post(
"#{@slack_endpoint}/users.list",
{:form, [token: token]}
) do
{:ok, resp} ->
members =
resp
|> Map.get(:body, "")
|> Poison.decode!()
|> Map.get("members", [])
{:ok, members}
error ->
error
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment