Wednesday, July 15, 2026 2:04:09 AM
> user.rb
# frozen_string_literal: true

module ESM
  class User < ApplicationRecord
    attr_writer :discord_user

    delegate :on, to: :discord_user, allow_nil: true

    #########################
    # Public Methods
    #########################

    # Parses and finds a user based off of SteamUID, Discord ID, or Discord Mention
    def self.parse(input)
      return if input.nil?

      # In case of frozen strings
      input = input.dup if input.frozen?

      # Discordrb stores the Discord ID as an Integer.
      input = input.to_s if !input.is_a?(String)

      if ESM::Regex::DISCORD_TAG_ONLY.match?(input)
        # Remove the extra stuff from a mention
        find_by_discord_id(input.gsub(/[<@!&>]/, ""))
      elsif input.steam_uid?
        find_by_steam_uid(input)
      else
        find_by_discord_id(input)
      end
    end

    def self.from_discord(discord_user)
      return if discord_user.nil?

      user = order(:discord_id)
        .where(discord_id: discord_user.id)
        .first_or_initialize

      user.update!(discord_username: discord_user.username, discord_avatar: discord_user.avatar_url)
      user.discord_user = discord_user
      user
    end

    #########################
    # Instance Methods
    #########################

    def developer?
      ESM.config.dev_user_allowlist.include?(discord_id)
    end

    def discord_user
      return if discord_id.nil?

      @discord_user ||= lambda do
        discord_user = ESM.discord_bot.user(discord_id)
        return if discord_user.nil?

        # Keep the discord user data up-to-date
        incoming_attributes = [discord_user.username, discord_user.avatar_url]
        current_attributes = [discord_username, discord_avatar]

        if current_attributes != incoming_attributes
          update!(
            discord_username: discord_user.username,
            discord_avatar: discord_user.avatar_url
          )
        end

        # Save some data for later consumption
        discord_user.esm_user = self
        discord_user
      end.call
    end

    def discord_servers
      return if discord_id.nil?

      @discord_servers ||= ESM.discord_bot.servers.values.select do |server|
        server.users.any? { |user| user.id.to_s == discord_id }
      end
    end

    def can_modify?(guild_id)
      return false if discord_id.nil?
      return true if developer? && !Rails.env.development?

      community = Community.find_by_guild_id(guild_id)
      return false if community.nil?

      server = community.discord_server
      return false if server.nil?

      # Check if they're the owner or admin
      community.modifiable_by?(on(server))
    end

    def channel_permission?(permission, channel)
      !!on(channel.server)&.permission?(permission, channel)
    end
  end
end
All opinions represented herein are my own
- © 2024 - 2026 itsthedevman
- build 43aa0d7