Credo: if over one-clause cond, map_join, no negated if/else

77991ba · Gabe Morell · 2026-11-04 20:34

17 files +331 -221

Files changed

modified lib/oh_my_ex_oh_ircd/irc/chan_serv.ex
+13 −10
@@ -326,17 +326,22 @@ defmodule OhMyExOhIrcd.IRC.ChanServ do
326 326
327 327 ## Reply helpers
328 328
329 − defp reply(target_nick, lines) when is_list(lines), do: Enum.each(lines, &reply(target_nick, &1))
329 + defp reply(target_nick, lines) when is_list(lines),
330 + do: Enum.each(lines, &reply(target_nick, &1))
330 331
331 332 defp reply(target_nick, line) when is_binary(line) do
332 333 case HordeRegistry.whereis({:user, String.downcase(target_nick)}) do
333 334 pid when is_pid(pid) ->
334 − send(pid, {:irc_privmsg, %{
335 − sender: nick(),
336 − target: target_nick,
337 − text: line,
338 − kind: :notice
339 − }})
335 + send(
336 + pid,
337 + {:irc_privmsg,
338 + %{
339 + sender: nick(),
340 + target: target_nick,
341 + text: line,
342 + kind: :notice
343 + }}
344 + )
340 345
341 346 nil ->
342 347 :ok
@@ -388,8 +393,6 @@ defmodule OhMyExOhIrcd.IRC.ChanServ do
388 393 defp founder_nick_for(_user), do: ""
389 394
390 395 defp format_changeset(%Ecto.Changeset{errors: errs}) do
391 − errs
392 − |> Enum.map(fn {field, {msg, _}} -> "#{field} #{msg}" end)
393 − |> Enum.join(", ")
396 + Enum.map_join(errs, ", ", fn {field, {msg, _}} -> "#{field} #{msg}" end)
394 397 end
395 398 end
modified lib/oh_my_ex_oh_ircd/irc/channel.ex
+38 −40
@@ -405,11 +405,17 @@ defmodule OhMyExOhIrcd.IRC.Channel do
405 405
406 406 access =
407 407 cond do
408 − existing -> existing.access
409 − user_id != nil and user_id == state.founder_user_id -> :founder
408 + existing ->
409 + existing.access
410 +
411 + user_id != nil and user_id == state.founder_user_id ->
412 + :founder
413 +
410 414 user_id != nil and Map.has_key?(state.persisted_access, user_id) ->
411 415 Map.get(state.persisted_access, user_id)
412 − true -> :member
416 +
417 + true ->
418 + :member
413 419 end
414 420
415 421 {user, host} = parse_prefix(prefix, nick)
@@ -463,6 +469,7 @@ defmodule OhMyExOhIrcd.IRC.Channel do
463 469
464 470 def handle_call({:message, sender, text, kind}, _from, state) do
465 471 sender_nick = sender |> String.split("!", parts: 2) |> List.first()
472 +
466 473 sender_access =
467 474 case sender_nick && Map.get(state.members, downcase(sender_nick)) do
468 475 %{access: a} -> a
@@ -569,8 +576,8 @@ defmodule OhMyExOhIrcd.IRC.Channel do
569 576
570 577 def handle_call(:topic_info, _from, state),
571 578 do:
572 − {:reply,
573 − %{text: state.topic, set_by: state.topic_set_by, set_at: state.topic_set_at}, state}
579 + {:reply, %{text: state.topic, set_by: state.topic_set_by, set_at: state.topic_set_at},
580 + state}
574 581
575 582 def handle_call({:set_topic, set_by, text}, _from, state) do
576 583 # Topic edit requires at least halfop on registered channels; on
@@ -581,28 +588,26 @@ defmodule OhMyExOhIrcd.IRC.Channel do
581 588 _ -> 0
582 589 end
583 590
584 − cond do
585 − state.founder_user_id != nil and granter_rank < rank(:halfop) ->
586 − {:reply, {:error, :not_authorized}, state}
587 −
588 − true ->
589 − now = System.system_time(:second)
591 + if state.founder_user_id != nil and granter_rank < rank(:halfop) do
592 + {:reply, {:error, :not_authorized}, state}
593 + else
594 + now = System.system_time(:second)
590 595
591 − state = %{
592 − state
593 − | topic: text,
594 − topic_set_by: set_by,
595 − topic_set_at: now
596 − }
596 + state = %{
597 + state
598 + | topic: text,
599 + topic_set_by: set_by,
600 + topic_set_at: now
601 + }
597 602
598 − OhMyExOhIrcd.Channels.put_topic(state.name, set_by, text, now)
603 + OhMyExOhIrcd.Channels.put_topic(state.name, set_by, text, now)
599 604
600 − Phoenix.PubSub.broadcast(@pubsub, MessageLog.channel_topic(state.name), {
601 − :irc_presence,
602 − {:topic, sender_prefix(state, set_by), state.name, text}
603 − })
605 + Phoenix.PubSub.broadcast(@pubsub, MessageLog.channel_topic(state.name), {
606 + :irc_presence,
607 + {:topic, sender_prefix(state, set_by), state.name, text}
608 + })
604 609
605 − {:reply, :ok, state}
610 + {:reply, :ok, state}
606 611 end
607 612 end
608 613
@@ -735,7 +740,9 @@ defmodule OhMyExOhIrcd.IRC.Channel do
735 740 ] do
736 741 cond do
737 742 auto_join_change?(change) ->
738 − if operator?, do: do_apply_non_prefix(state, granter, change), else: {:error, :not_authorized}
743 + if operator?,
744 + do: do_apply_non_prefix(state, granter, change),
745 + else: {:error, :not_authorized}
739 746
740 747 flood_exempt_change?(change) and granter_access != :founder ->
741 748 {:error, :not_authorized}
@@ -889,22 +896,13 @@ defmodule OhMyExOhIrcd.IRC.Channel do
889 896 end
890 897
891 898 defp do_revoke(state, member, access) do
892 − cond do
893 − member.access != access ->
894 − if rank(member.access) <= rank(access) do
895 − new = %{member | access: :member}
896 − members = Map.put(state.members, downcase(member.nick), new)
897 − state = persist_member_access(%{state | members: members}, member.user_id, :member)
898 − {:ok, state, {:revoke, access, member.nick}}
899 − else
900 − {:noop, state}
901 − end
902 −
903 − true ->
904 − new = %{member | access: :member}
905 − members = Map.put(state.members, downcase(member.nick), new)
906 − state = persist_member_access(%{state | members: members}, member.user_id, :member)
907 − {:ok, state, {:revoke, access, member.nick}}
899 + if member.access == access or rank(member.access) <= rank(access) do
900 + new = %{member | access: :member}
901 + members = Map.put(state.members, downcase(member.nick), new)
902 + state = persist_member_access(%{state | members: members}, member.user_id, :member)
903 + {:ok, state, {:revoke, access, member.nick}}
904 + else
905 + {:noop, state}
908 906 end
909 907 end
910 908
modified lib/oh_my_ex_oh_ircd/irc/connection.ex
+190 −82
@@ -379,17 +379,15 @@ defmodule OhMyExOhIrcd.IRC.Connection do
379 379 def handle_info(:check_idle, {socket, state}) do
380 380 idle_ms = (System.system_time(:second) - state.last_activity) * 1000
381 381
382 − cond do
383 − idle_ms >= state.ping_interval_ms ->
384 − token = Integer.to_string(System.unique_integer([:positive]))
385 − send_msg(socket, Message.build("PING", [token], state.server_name))
386 − ref = Process.send_after(self(), :check_pong, state.ping_timeout_ms)
387 − {:noreply, {socket, %{state | ping_token: token, ping_timer: ref}}}
388 −
389 − true ->
390 − remaining = state.ping_interval_ms - idle_ms
391 − ref = Process.send_after(self(), :check_idle, max(remaining, 1_000))
392 − {:noreply, {socket, %{state | ping_timer: ref}}}
382 + if idle_ms >= state.ping_interval_ms do
383 + token = Integer.to_string(System.unique_integer([:positive]))
384 + send_msg(socket, Message.build("PING", [token], state.server_name))
385 + ref = Process.send_after(self(), :check_pong, state.ping_timeout_ms)
386 + {:noreply, {socket, %{state | ping_token: token, ping_timer: ref}}}
387 + else
388 + remaining = state.ping_interval_ms - idle_ms
389 + ref = Process.send_after(self(), :check_idle, max(remaining, 1_000))
390 + {:noreply, {socket, %{state | ping_timer: ref}}}
393 391 end
394 392 end
395 393
@@ -446,8 +444,11 @@ defmodule OhMyExOhIrcd.IRC.Connection do
446 444 Enum.each(state.channels, fn ch -> Channel.part(ch, state.nick, "Connection closed") end)
447 445
448 446 case HordeRegistry.whereis({:user, downcase(state.nick)}) do
449 − pid when pid == self() -> Horde.Registry.unregister(HordeRegistry, {:user, downcase(state.nick)})
450 − _ -> :ok
447 + pid when pid == self() ->
448 + Horde.Registry.unregister(HordeRegistry, {:user, downcase(state.nick)})
449 +
450 + _ ->
451 + :ok
451 452 end
452 453 end
453 454
@@ -579,7 +580,10 @@ defmodule OhMyExOhIrcd.IRC.Connection do
579 580
580 581 cond do
581 582 nak != [] ->
582 − send_msg(socket, Message.build("CAP", [state.nick || "*", "NAK", reqs], state.server_name))
583 + send_msg(
584 + socket,
585 + Message.build("CAP", [state.nick || "*", "NAK", reqs], state.server_name)
586 + )
583 587
584 588 ack != [] ->
585 589 send_msg(
@@ -613,7 +617,11 @@ defmodule OhMyExOhIrcd.IRC.Connection do
613 617 %{state | sasl: nil}
614 618 end
615 619
616 − defp dispatch(%Message{command: "AUTHENTICATE", params: [payload | _]}, socket, %State{sasl: :awaiting_payload} = state) do
620 + defp dispatch(
621 + %Message{command: "AUTHENTICATE", params: [payload | _]},
622 + socket,
623 + %State{sasl: :awaiting_payload} = state
624 + ) do
617 625 case Auth.verify_sasl_plain(payload) do
618 626 {:ok, user} ->
619 627 send_numeric(socket, state, "900", [
@@ -673,6 +681,7 @@ defmodule OhMyExOhIrcd.IRC.Connection do
673 681
674 682 Horde.Registry.lookup(HordeRegistry, {:user, downcase(nick)}) != [] ->
675 683 send_numeric(socket, state, "433", [state.nick || "*", nick, "Nickname is already in use"])
684 +
676 685 state
677 686
678 687 state.registered? ->
@@ -788,7 +797,10 @@ defmodule OhMyExOhIrcd.IRC.Connection do
788 797 # of a per-user topic. Simpler: route through MessageLog with target=nick.
789 798 case HordeRegistry.whereis({:user, downcase(target)}) do
790 799 pid when is_pid(pid) ->
791 − send(pid, {:irc_privmsg, %{sender: prefix(state), target: target, text: text, kind: :privmsg}})
800 + send(
801 + pid,
802 + {:irc_privmsg, %{sender: prefix(state), target: target, text: text, kind: :privmsg}}
803 + )
792 804
793 805 nil ->
794 806 send_numeric(socket, state, "401", [state.nick, target, "No such nick/channel"])
@@ -827,7 +839,13 @@ defmodule OhMyExOhIrcd.IRC.Connection do
827 839 |> Enum.each(fn ch ->
828 840 members = safe_members(ch)
829 841 topic = safe_topic(ch)
830 − send_numeric(socket, state, "322", [state.nick || "*", ch, Integer.to_string(length(members)), topic])
842 +
843 + send_numeric(socket, state, "322", [
844 + state.nick || "*",
845 + ch,
846 + Integer.to_string(length(members)),
847 + topic
848 + ])
831 849 end)
832 850
833 851 send_numeric(socket, state, "323", [state.nick || "*", "End of /LIST"])
@@ -900,10 +918,19 @@ defmodule OhMyExOhIrcd.IRC.Connection do
900 918 :ok
901 919
902 920 {:error, :not_authorized} ->
903 − send_numeric(socket, state, "482", [state.nick, channel, "You're not channel operator"])
921 + send_numeric(socket, state, "482", [
922 + state.nick,
923 + channel,
924 + "You're not channel operator"
925 + ])
904 926
905 927 {:error, :no_such_member} ->
906 − send_numeric(socket, state, "441", [state.nick, target, channel, "They aren't on that channel"])
928 + send_numeric(socket, state, "441", [
929 + state.nick,
930 + target,
931 + channel,
932 + "They aren't on that channel"
933 + ])
907 934
908 935 {:error, :not_on_channel} ->
909 936 send_numeric(socket, state, "442", [state.nick, channel, "You're not on that channel"])
@@ -935,7 +962,11 @@ defmodule OhMyExOhIrcd.IRC.Connection do
935 962 send_numeric(socket, state, "401", [state.nick, nick, "No such nick/channel"])
936 963 end
937 964 else
938 − send_numeric(socket, state, "482", [state.nick, channel, "You're not channel operator"])
965 + send_numeric(socket, state, "482", [
966 + state.nick,
967 + channel,
968 + "You're not channel operator"
969 + ])
939 970 end
940 971
941 972 nil ->
@@ -966,7 +997,10 @@ defmodule OhMyExOhIrcd.IRC.Connection do
966 997 true ->
967 998 case HordeRegistry.whereis({:user, downcase(target)}) do
968 999 pid when is_pid(pid) ->
969 − send(pid, {:irc_privmsg, %{sender: prefix(state), target: target, text: text, kind: :notice}})
1000 + send(
1001 + pid,
1002 + {:irc_privmsg, %{sender: prefix(state), target: target, text: text, kind: :notice}}
1003 + )
970 1004
971 1005 nil ->
972 1006 :ok
@@ -977,16 +1011,25 @@ defmodule OhMyExOhIrcd.IRC.Connection do
977 1011 end
978 1012
979 1013 defp dispatch(%Message{command: "AWAY", params: []}, socket, state) do
980 − send_numeric(socket, state, "305", [state.nick || "*", "You are no longer marked as being away"])
1014 + send_numeric(socket, state, "305", [
1015 + state.nick || "*",
1016 + "You are no longer marked as being away"
1017 + ])
1018 +
981 1019 %{state | away: nil}
982 1020 end
983 1021
984 1022 defp dispatch(%Message{command: "AWAY", params: [reason | _]}, socket, state) do
985 1023 if reason == "" do
986 − send_numeric(socket, state, "305", [state.nick || "*", "You are no longer marked as being away"])
1024 + send_numeric(socket, state, "305", [
1025 + state.nick || "*",
1026 + "You are no longer marked as being away"
1027 + ])
1028 +
987 1029 %{state | away: nil}
988 1030 else
989 1031 send_numeric(socket, state, "306", [state.nick || "*", "You have been marked as being away"])
1032 +
990 1033 %{state | away: reason}
991 1034 end
992 1035 end
@@ -1001,7 +1044,9 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1001 1044 pid when is_pid(pid) ->
1002 1045 try do
1003 1046 info =
1004 − if pid == self(), do: local_whois_info(state), else: GenServer.call(pid, :whois_info, 1_000)
1047 + if pid == self(),
1048 + do: local_whois_info(state),
1049 + else: GenServer.call(pid, :whois_info, 1_000)
1005 1050
1006 1051 away_flag = if info.away, do: "-", else: "+"
1007 1052 ["#{info.nick}=#{away_flag}#{info.user}@#{info.host}"]
@@ -1235,24 +1280,22 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1235 1280
1236 1281 defp dispatch(%Message{command: cmd, params: [mask | _]}, socket, state)
1237 1282 when cmd in ["UNKLINE", "UNGLINE"] do
1238 − cond do
1239 − not state.operator? ->
1240 − send_numeric(socket, state, "481", [
1241 − state.nick || "*",
1242 − "Permission Denied - You're not an IRC operator"
1243 − ])
1244 −
1245 − true ->
1246 − case OhMyExOhIrcd.IRC.Klines.remove(mask) do
1247 − 0 ->
1248 − send_numeric(socket, state, "501", [state.nick, "No K-line matching #{mask}"])
1249 −
1250 − n ->
1251 − OhMyExOhIrcd.IRC.Broadcast.globops(
1252 − state.nick,
1253 − "#{cmd} removed: #{mask} (#{n} row#{if n == 1, do: "", else: "s"})"
1254 − )
1255 − end
1283 + if state.operator? do
1284 + case OhMyExOhIrcd.IRC.Klines.remove(mask) do
1285 + 0 ->
1286 + send_numeric(socket, state, "501", [state.nick, "No K-line matching #{mask}"])
1287 +
1288 + n ->
1289 + OhMyExOhIrcd.IRC.Broadcast.globops(
1290 + state.nick,
1291 + "#{cmd} removed: #{mask} (#{n} row#{if n == 1, do: "", else: "s"})"
1292 + )
1293 + end
1294 + else
1295 + send_numeric(socket, state, "481", [
1296 + state.nick || "*",
1297 + "Permission Denied - You're not an IRC operator"
1298 + ])
1256 1299 end
1257 1300
1258 1301 state
@@ -1402,7 +1445,12 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1402 1445 rescue
1403 1446 e ->
1404 1447 Logger.error("#{label} failed: #{Exception.format(:error, e, __STACKTRACE__)}")
1405 − send_server_notice(socket, state, "#{label} failed: #{Exception.message(e)} (see server log)")
1448 +
1449 + send_server_notice(
1450 + socket,
1451 + state,
1452 + "#{label} failed: #{Exception.message(e)} (see server log)"
1453 + )
1406 1454 catch
1407 1455 kind, reason ->
1408 1456 Logger.error("#{label} failed: #{inspect(kind)} #{inspect(reason)}")
@@ -1624,12 +1672,10 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1624 1672 end
1625 1673
1626 1674 rendered =
1627 − members
1628 − |> Enum.map(fn
1675 + Enum.map_join(members, " ", fn
1629 1676 %{nick: nick, access: access} -> Channel.prefix(access) <> nick
1630 1677 nick when is_binary(nick) -> nick
1631 1678 end)
1632 − |> Enum.join(" ")
1633 1679
1634 1680 send_numeric(socket, state, "353", [state.nick || "*", "=", channel, rendered])
1635 1681 send_numeric(socket, state, "366", [state.nick || "*", channel, "End of /NAMES list"])
@@ -1643,29 +1689,27 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1643 1689
1644 1690 defp maybe_complete_registration(%State{nick: nick, user: user} = state, socket)
1645 1691 when is_binary(nick) and is_binary(user) do
1646 − cond do
1647 − is_nil(state.account) and not state.allow_anonymous ->
1648 − send_numeric(socket, state, "464", [
1649 − state.nick || "*",
1650 − "Password required - authenticate via SASL or PASS"
1651 − ])
1652 −
1653 − state
1654 −
1655 − true ->
1656 − case OhMyExOhIrcd.IRC.Klines.match("#{state.user}@#{state.real_host}") do
1657 − %{reason: reason} = _kline ->
1658 − send_msg(
1659 − socket,
1660 − Message.build("ERROR", ["Closing link: K-Lined: " <> (reason || "")])
1661 − )
1692 + if is_nil(state.account) and not state.allow_anonymous do
1693 + send_numeric(socket, state, "464", [
1694 + state.nick || "*",
1695 + "Password required - authenticate via SASL or PASS"
1696 + ])
1662 1697
1663 − ThousandIsland.Socket.shutdown(socket, :write)
1664 − state
1698 + state
1699 + else
1700 + case OhMyExOhIrcd.IRC.Klines.match("#{state.user}@#{state.real_host}") do
1701 + %{reason: reason} = _kline ->
1702 + send_msg(
1703 + socket,
1704 + Message.build("ERROR", ["Closing link: K-Lined: " <> (reason || "")])
1705 + )
1706 +
1707 + ThousandIsland.Socket.shutdown(socket, :write)
1708 + state
1665 1709
1666 − _ ->
1667 − register_user(socket, state, nick)
1668 − end
1710 + _ ->
1711 + register_user(socket, state, nick)
1712 + end
1669 1713 end
1670 1714 end
1671 1715
@@ -1723,7 +1767,10 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1723 1767 end
1724 1768
1725 1769 defp send_welcome(socket, state) do
1726 − send_numeric(socket, state, "001", [state.nick, "Welcome to the #{state.network_name} IRC Network #{state.nick}"])
1770 + send_numeric(socket, state, "001", [
1771 + state.nick,
1772 + "Welcome to the #{state.network_name} IRC Network #{state.nick}"
1773 + ])
1727 1774
1728 1775 send_numeric(socket, state, "002", [
1729 1776 state.nick,
@@ -1767,7 +1814,10 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1767 1814 send_numeric(socket, state, "422", [state.nick || "*", "MOTD File is missing"])
1768 1815
1769 1816 lines ->
1770 − send_numeric(socket, state, "375", [state.nick || "*", "- #{state.server_name} Message of the Day -"])
1817 + send_numeric(socket, state, "375", [
1818 + state.nick || "*",
1819 + "- #{state.server_name} Message of the Day -"
1820 + ])
1771 1821
1772 1822 Enum.each(lines, fn line ->
1773 1823 send_numeric(socket, state, "372", [state.nick || "*", "- #{line}"])
@@ -1793,9 +1843,24 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1793 1843 "channels formed"
1794 1844 ])
1795 1845
1796 − send_numeric(socket, state, "255", [state.nick || "*", "I have #{users} clients and #{nodes} servers"])
1797 − send_numeric(socket, state, "265", [state.nick || "*", Integer.to_string(users), Integer.to_string(users), "Current local users #{users}, max #{users}"])
1798 − send_numeric(socket, state, "266", [state.nick || "*", Integer.to_string(users), Integer.to_string(users), "Current global users #{users}, max #{users}"])
1846 + send_numeric(socket, state, "255", [
1847 + state.nick || "*",
1848 + "I have #{users} clients and #{nodes} servers"
1849 + ])
1850 +
1851 + send_numeric(socket, state, "265", [
1852 + state.nick || "*",
1853 + Integer.to_string(users),
1854 + Integer.to_string(users),
1855 + "Current local users #{users}, max #{users}"
1856 + ])
1857 +
1858 + send_numeric(socket, state, "266", [
1859 + state.nick || "*",
1860 + Integer.to_string(users),
1861 + Integer.to_string(users),
1862 + "Current global users #{users}, max #{users}"
1863 + ])
1799 1864 end
1800 1865
1801 1866 defp send_topic(channel, socket, state) do
@@ -1842,7 +1907,12 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1842 1907 info.realname
1843 1908 ])
1844 1909
1845 − send_numeric(socket, state, "312", [state.nick || "*", info.nick, state.server_name, "oh_my_ex_oh_ircd"])
1910 + send_numeric(socket, state, "312", [
1911 + state.nick || "*",
1912 + info.nick,
1913 + state.server_name,
1914 + "oh_my_ex_oh_ircd"
1915 + ])
1846 1916
1847 1917 # RPL_WHOISACTUALLY — reveal the real IP behind a cloak/vhost, but
1848 1918 # only to operators. Skipped when the displayed host already is the
@@ -1859,7 +1929,11 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1859 1929 end
1860 1930
1861 1931 if info.channels != [] do
1862 − send_numeric(socket, state, "319", [state.nick || "*", info.nick, Enum.join(info.channels, " ")])
1932 + send_numeric(socket, state, "319", [
1933 + state.nick || "*",
1934 + info.nick,
1935 + Enum.join(info.channels, " ")
1936 + ])
1863 1937 end
1864 1938
1865 1939 if info.away do
@@ -1867,11 +1941,20 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1867 1941 end
1868 1942
1869 1943 if info.account do
1870 − send_numeric(socket, state, "330", [state.nick || "*", info.nick, info.account, "is logged in as"])
1944 + send_numeric(socket, state, "330", [
1945 + state.nick || "*",
1946 + info.nick,
1947 + info.account,
1948 + "is logged in as"
1949 + ])
1871 1950 end
1872 1951
1873 1952 if Map.get(info, :operator?) do
1874 − send_numeric(socket, state, "313", [state.nick || "*", info.nick, "is an IRC operator"])
1953 + send_numeric(socket, state, "313", [
1954 + state.nick || "*",
1955 + info.nick,
1956 + "is an IRC operator"
1957 + ])
1875 1958 end
1876 1959
1877 1960 send_numeric(socket, state, "317", [
@@ -1929,7 +2012,10 @@ defmodule OhMyExOhIrcd.IRC.Connection do
1929 2012 pid when is_pid(pid) ->
1930 2013 try do
1931 2014 info =
1932 − if pid == self(), do: local_whois_info(state), else: GenServer.call(pid, :whois_info, 1_000)
2015 + if pid == self(),
2016 + do: local_whois_info(state),
2017 + else: GenServer.call(pid, :whois_info, 1_000)
2018 +
1933 2019 flag = if info.away, do: "G", else: "H"
1934 2020
1935 2021 send_numeric(socket, state, "352", [
@@ -2161,7 +2247,9 @@ defmodule OhMyExOhIrcd.IRC.Connection do
2161 2247
2162 2248 case params do
2163 2249 [mask | tail] ->
2164 − change = if op == :grant, do: {:add_mask, type, mask}, else: {:remove_mask, type, mask}
2250 + change =
2251 + if op == :grant, do: {:add_mask, type, mask}, else: {:remove_mask, type, mask}
2252 +
2165 2253 do_parse_modes(rest, op, tail, [change | changes], views)
2166 2254
2167 2255 [] ->
@@ -2219,13 +2307,32 @@ defmodule OhMyExOhIrcd.IRC.Connection do
2219 2307
2220 2308 # ── RPL_BANLIST/RPL_EXCEPTLIST/RPL_INVITELIST renderers ──────────────
2221 2309 defp render_mask_list(:ban, target, socket, state),
2222 − do: render_mask_list_with(:ban, "367", "368", "End of channel ban list", target, socket, state)
2310 + do:
2311 + render_mask_list_with(:ban, "367", "368", "End of channel ban list", target, socket, state)
2223 2312
2224 2313 defp render_mask_list(:except, target, socket, state),
2225 − do: render_mask_list_with(:except, "348", "349", "End of channel exception list", target, socket, state)
2314 + do:
2315 + render_mask_list_with(
2316 + :except,
2317 + "348",
2318 + "349",
2319 + "End of channel exception list",
2320 + target,
2321 + socket,
2322 + state
2323 + )
2226 2324
2227 2325 defp render_mask_list(:invite, target, socket, state),
2228 − do: render_mask_list_with(:invite, "346", "347", "End of channel invite list", target, socket, state)
2326 + do:
2327 + render_mask_list_with(
2328 + :invite,
2329 + "346",
2330 + "347",
2331 + "End of channel invite list",
2332 + target,
2333 + socket,
2334 + state
2335 + )
2229 2336
2230 2337 defp render_mask_list_with(type, line_code, end_code, end_text, target, socket, state) do
2231 2338 try do
@@ -2261,7 +2368,8 @@ defmodule OhMyExOhIrcd.IRC.Connection do
2261 2368 |> Enum.join("")
2262 2369
2263 2370 mode_string =
2264 − "+nt" <> flag_letters <>
2371 + "+nt" <>
2372 + flag_letters <>
2265 2373 if(key, do: "k", else: "") <>
2266 2374 if(limit, do: "l", else: "")
2267 2375
modified lib/oh_my_ex_oh_ircd/irc/hlc.ex
+4 −3
@@ -26,9 +26,10 @@ defmodule OhMyExOhIrcd.IRC.HLC do
26 26 wall = System.system_time(:millisecond)
27 27
28 28 Agent.get_and_update(__MODULE__, fn {last_wall, last_logical} ->
29 − cond do
30 − wall > last_wall -> {{wall, 0, node()}, {wall, 0}}
31 − true -> {{last_wall, last_logical + 1, node()}, {last_wall, last_logical + 1}}
29 + if wall > last_wall do
30 + {{wall, 0, node()}, {wall, 0}}
31 + else
32 + {{last_wall, last_logical + 1, node()}, {last_wall, last_logical + 1}}
32 33 end
33 34 end)
34 35 end
modified lib/oh_my_ex_oh_ircd/irc/web_session.ex
+48 −54
@@ -77,33 +77,31 @@ defmodule OhMyExOhIrcd.IRC.WebSession do
77 77 user_id = state.user && state.user.id
78 78 prefix = "#{state.nick}!#{state.nick}@web"
79 79
80 − cond do
81 − not Channel.valid_name?(channel) ->
82 − notify(state, {:join_refused, channel, :bad_channel_name})
83 − {:reply, {:error, :bad_channel_name}, state}
84 −
85 − true ->
86 − case Channel.ensure_started(channel) do
87 − {:ok, _} ->
88 − Phoenix.PubSub.subscribe(@pubsub, MessageLog.channel_topic(channel))
89 −
90 − case Channel.join(channel, state.nick, self(), user_id, prefix, nil) do
91 − :ok ->
92 − backlog = MessageLog.entries(channel)
93 − notify(state, {:joined, channel, backlog, Channel.members(channel)})
94 −
95 − {:reply, :ok,
96 − %{state | channels: MapSet.put(state.channels, String.downcase(channel))}}
97 −
98 − {:error, reason} = err ->
99 − Phoenix.PubSub.unsubscribe(@pubsub, MessageLog.channel_topic(channel))
100 − notify(state, {:join_refused, channel, reason})
101 − {:reply, err, state}
102 − end
103 −
104 − err ->
105 − {:reply, err, state}
106 − end
80 + if Channel.valid_name?(channel) do
81 + case Channel.ensure_started(channel) do
82 + {:ok, _} ->
83 + Phoenix.PubSub.subscribe(@pubsub, MessageLog.channel_topic(channel))
84 +
85 + case Channel.join(channel, state.nick, self(), user_id, prefix, nil) do
86 + :ok ->
87 + backlog = MessageLog.entries(channel)
88 + notify(state, {:joined, channel, backlog, Channel.members(channel)})
89 +
90 + {:reply, :ok,
91 + %{state | channels: MapSet.put(state.channels, String.downcase(channel))}}
92 +
93 + {:error, reason} = err ->
94 + Phoenix.PubSub.unsubscribe(@pubsub, MessageLog.channel_topic(channel))
95 + notify(state, {:join_refused, channel, reason})
96 + {:reply, err, state}
97 + end
98 +
99 + err ->
100 + {:reply, err, state}
101 + end
102 + else
103 + notify(state, {:join_refused, channel, :bad_channel_name})
104 + {:reply, {:error, :bad_channel_name}, state}
107 105 end
108 106 end
109 107
@@ -113,8 +111,7 @@ defmodule OhMyExOhIrcd.IRC.WebSession do
113 111 Phoenix.PubSub.unsubscribe(@pubsub, MessageLog.channel_topic(channel))
114 112 notify(state, {:parted, channel})
115 113
116 − {:reply, :ok,
117 − %{state | channels: MapSet.delete(state.channels, String.downcase(channel))}}
114 + {:reply, :ok, %{state | channels: MapSet.delete(state.channels, String.downcase(channel))}}
118 115 else
119 116 {:reply, {:error, :not_on_channel}, state}
120 117 end
@@ -123,30 +120,28 @@ defmodule OhMyExOhIrcd.IRC.WebSession do
123 120 def handle_call({:privmsg, target, text}, _from, state) do
124 121 sender = "#{state.nick}!#{state.nick}@web"
125 122
126 − cond do
127 − channel_target?(target) ->
128 − if MapSet.member?(state.channels, String.downcase(target)) do
129 − case Channel.privmsg(target, sender, text) do
130 − :ok -> {:reply, :ok, %{state | last_activity: System.system_time(:second)}}
131 − {:error, _} = err -> {:reply, err, state}
132 − end
133 − else
134 − {:reply, {:error, :not_on_channel}, state}
135 − end
136 −
137 − true ->
138 − case HordeRegistry.whereis({:user, String.downcase(target)}) do
139 − pid when is_pid(pid) ->
140 − send(pid, {
141 − :irc_privmsg,
142 − %{sender: sender, target: target, text: text, kind: :privmsg}
143 − })
144 −
145 − {:reply, :ok, %{state | last_activity: System.system_time(:second)}}
146 −
147 − nil ->
148 − {:reply, {:error, :no_such_user}, state}
123 + if channel_target?(target) do
124 + if MapSet.member?(state.channels, String.downcase(target)) do
125 + case Channel.privmsg(target, sender, text) do
126 + :ok -> {:reply, :ok, %{state | last_activity: System.system_time(:second)}}
127 + {:error, _} = err -> {:reply, err, state}
149 128 end
129 + else
130 + {:reply, {:error, :not_on_channel}, state}
131 + end
132 + else
133 + case HordeRegistry.whereis({:user, String.downcase(target)}) do
134 + pid when is_pid(pid) ->
135 + send(pid, {
136 + :irc_privmsg,
137 + %{sender: sender, target: target, text: text, kind: :privmsg}
138 + })
139 +
140 + {:reply, :ok, %{state | last_activity: System.system_time(:second)}}
141 +
142 + nil ->
143 + {:reply, {:error, :no_such_user}, state}
144 + end
150 145 end
151 146 end
152 147
@@ -184,8 +179,7 @@ defmodule OhMyExOhIrcd.IRC.WebSession do
184 179 %{name: key, members: members}
185 180 end)
186 181
187 − {:reply,
188 − %{nick: state.nick, channels: channels, signon: state.signon}, state}
182 + {:reply, %{nick: state.nick, channels: channels, signon: state.signon}, state}
189 183 end
190 184
191 185 @impl true
modified lib/oh_my_ex_oh_ircd_web/live/user_live/scrobble.ex
+10 −12
@@ -110,18 +110,16 @@ defmodule OhMyExOhIrcdWeb.UserLive.Scrobble do
110 110 label = if String.trim(label) == "", do: nil, else: String.trim(label)
111 111 user = socket.assigns.current_scope.user
112 112
113 − cond do
114 − String.trim(who) == "" ->
115 − {:noreply, put_flash(socket, :error, "A display name (who) is required.")}
116 −
117 − true ->
118 − case Scrobbles.mint_token(socket.assigns.channel_name, user, who, label) do
119 − {:ok, display, _token} ->
120 − {:noreply, socket |> assign(:new_token, display) |> load_data()}
121 −
122 − _ ->
123 − {:noreply, put_flash(socket, :error, "Could not mint a token.")}
124 − end
113 + if String.trim(who) == "" do
114 + {:noreply, put_flash(socket, :error, "A display name (who) is required.")}
115 + else
116 + case Scrobbles.mint_token(socket.assigns.channel_name, user, who, label) do
117 + {:ok, display, _token} ->
118 + {:noreply, socket |> assign(:new_token, display) |> load_data()}
119 +
120 + _ ->
121 + {:noreply, put_flash(socket, :error, "Could not mint a token.")}
122 + end
125 123 end
126 124 end
127 125
modified lib/oh_my_ex_oh_ircd_web/live/web_irc_live.ex
+16 −16
@@ -20,12 +20,7 @@ defmodule OhMyExOhIrcdWeb.WebIrcLive do
20 20
21 21 @impl true
22 22 def mount(_params, _session, socket) do
23 − if not enabled?() do
24 − {:ok,
25 − socket
26 − |> put_flash(:error, "WebIRC is disabled in this deployment.")
27 − |> push_navigate(to: ~p"/")}
28 − else
23 + if enabled?() do
29 24 user = socket.assigns.current_scope && socket.assigns.current_scope.user
30 25 default_nick = default_nick_for(user)
31 26
@@ -41,6 +36,11 @@ defmodule OhMyExOhIrcdWeb.WebIrcLive do
41 36 |> assign(:input, "")
42 37 |> assign(:error, nil)
43 38 |> assign(:join_channel, "")}
39 + else
40 + {:ok,
41 + socket
42 + |> put_flash(:error, "WebIRC is disabled in this deployment.")
43 + |> push_navigate(to: ~p"/")}
44 44 end
45 45 end
46 46
@@ -242,7 +242,9 @@ defmodule OhMyExOhIrcdWeb.WebIrcLive do
242 242
243 243 def handle_info({:web_irc, {:parted, channel}}, socket) do
244 244 cs = Map.delete(socket.assigns.channels, channel)
245 − sel = if socket.assigns.current_channel == channel, do: nil, else: socket.assigns.current_channel
245 +
246 + sel =
247 + if socket.assigns.current_channel == channel, do: nil, else: socket.assigns.current_channel
246 248
247 249 {:noreply,
248 250 socket
@@ -269,15 +271,13 @@ defmodule OhMyExOhIrcdWeb.WebIrcLive do
269 271 def handle_info({:web_irc, {:irc_privmsg, entry}}, socket) do
270 272 target = entry.target
271 273
272 − cond do
273 − String.starts_with?(target, "#") or String.starts_with?(target, "&") ->
274 − {:noreply, push_message(socket, target, entry)}
275 −
276 − true ->
277 − # DM — surface in a synthetic "channel" named after the sender's nick.
278 − sender_nick = entry.sender |> String.split("!", parts: 2) |> List.first()
279 − chan = ensure_dm_channel(socket, sender_nick)
280 − {:noreply, push_message(chan, sender_nick, entry)}
274 + if String.starts_with?(target, "#") or String.starts_with?(target, "&") do
275 + {:noreply, push_message(socket, target, entry)}
276 + else
277 + # DM — surface in a synthetic "channel" named after the sender's nick.
278 + sender_nick = entry.sender |> String.split("!", parts: 2) |> List.first()
279 + chan = ensure_dm_channel(socket, sender_nick)
280 + {:noreply, push_message(chan, sender_nick, entry)}
281 281 end
282 282 end
283 283
modified test/oh_my_ex_oh_ircd/irc/channel_persistence_test.exs
+12 −4
@@ -43,9 +43,15 @@ defmodule OhMyExOhIrcd.IRC.ChannelPersistenceTest do
43 43
44 44 defp wait_until(fun, retries \\ 50) do
45 45 cond do
46 − fun.() -> :ok
47 − retries == 0 -> :ok
48 − true -> Process.sleep(20); wait_until(fun, retries - 1)
46 + fun.() ->
47 + :ok
48 +
49 + retries == 0 ->
50 + :ok
51 +
52 + true ->
53 + Process.sleep(20)
54 + wait_until(fun, retries - 1)
49 55 end
50 56 end
51 57
@@ -145,7 +151,9 @@ defmodule OhMyExOhIrcd.IRC.ChannelPersistenceTest do
145 151 rec = Channels.get(chan)
146 152
147 153 rows =
148 − Repo.all(from m in ChannelMembership, where: m.channel_id == ^rec.id and m.user_id == ^other.id)
154 + Repo.all(
155 + from m in ChannelMembership, where: m.channel_id == ^rec.id and m.user_id == ^other.id
156 + )
149 157
150 158 assert [%{access: "op"}] = rows
151 159

Parents: 97f137f