diff --git a/lib/discordhandler.ex b/lib/discordhandler.ex index 48bfd1f..5bedacb 100644 --- a/lib/discordhandler.ex +++ b/lib/discordhandler.ex @@ -8,7 +8,9 @@ defmodule Discordirc.DiscordHandler do end def handle_event({:MESSAGE_CREATE, msg, _ws_state}) do - unless msg.author.username == "discord-irc" and msg.author.discriminator == "8465" do + {:ok, me} = Api.get_current_user() + + unless msg.author.username == me.username and msg.author.discriminator == me.discriminator do case ChannelMap.irc(msg.channel_id) do {:ok, net, _} -> pid = String.to_atom(net) diff --git a/lib/formatter.ex b/lib/formatter.ex index d06cf68..9a67d68 100644 --- a/lib/formatter.ex +++ b/lib/formatter.ex @@ -1,4 +1,6 @@ defmodule Discordirc.Formatter do + alias Nostrum.Api, as: DiscordAPI + def from_irc(nick, msg) do from_irc(nick, msg, false) end @@ -26,16 +28,109 @@ defmodule Discordirc.Formatter do end end + defmodule DiscordUserInfo do + defstruct id: nil, username: nil, discriminator: nil, nickname: nil + + def from_id(id) do + {:ok, user} = DiscordAPI.get_user(id) + # currently we'll just use the first guild we're connected to to resolve nicks. + # TODO: implement mutli-guild functionality + g = DiscordAPI.get_current_user_guilds!() |> List.first() + {:ok, member} = DiscordAPI.get_guild_member(g.id(), user.id()) + + %DiscordUserInfo{ + id: id, + username: user.username, + discriminator: user.discriminator, + nickname: member.nick + } + end + end + + def tryreplace(s, m) do + pattern = ~r/\<\@\!(\d+)\>/um + dui = m[:dui] + r = m[:str] + + if String.match?(s, pattern) do + if s == r do + if is_binary(dui.nickname) do + String.replace(s, r, dui.nickname) + else + String.replace(s, r, dui.username <> "#" <> dui.discriminator) + end + else + nil + end + else + s + end + end + + def doallreplacements(split, matches, acc) do + [shead | stail] = split + {str, [m | mtail]} = acc + + s = tryreplace(shead, m) + + if is_nil(s) do + doallreplacements(split, matches, {str, mtail}) + else + if stail == [] do + str <> s + else + doallreplacements(stail, matches, {str <> s, matches}) + end + end + end + + def fixdiscordidstrings(content, bare \\ false) do + pattern = ~r/\<\@\!(\d+)\>/um + + matches = + Regex.scan(pattern, content) + |> Enum.uniq() + |> Enum.map(fn x -> + [ + str: List.first(x), + id: List.last(x), + dui: DiscordUserInfo.from_id(String.to_integer(List.last(x))) + ] + end) + + unless matches == [] do + if bare do + doallreplacements( + Regex.split(pattern, content, include_captures: true), + matches, + {"", matches} + ) + else + doallreplacements( + Regex.split(pattern, content, include_captures: true), + matches, + {"@", matches} + ) + end + else + content + end + end + def from_discord(user, msg) do usr = "#{user.username}\##{user.discriminator}" - messages = String.split(msg, "\n") + + messages = + msg + |> String.split("\n") + |> Enum.map(&fixdiscordidstrings(&1)) # discord may give... many lines. split and format. case Enum.count(messages) do 0 -> "<#{usr}> #{messages[0]}" - x -> + _ -> messages |> Enum.map(fn m -> "<#{usr}> #{m}" end) end