Wednesday, July 15, 2026 4:56:16 AM
> server.rb
# frozen_string_literal: true

module ESM
  module Command
    module Server
      class Server < ApplicationCommand
        #################################
        #
        # Arguments (required first, then order matters)
        #

        # See Argument::TEMPLATES[:server_id]
        argument :server_id, display_name: :for

        #
        # Configuration
        #

        command_namespace :server, command_name: :details
        command_type :player

        does_not_require :registration

        # Reason: It's nice accessing the connection info even when it is offline
        skip_action :connected_server

        #################################

        def on_execute
          embed =
            ESM::Embed.build do |e|
              e.title = target_server.server_name
              e.color = target_server.connected? ? :green : :red

              if !target_server.connected?
                e.description =
                  if target_server.disconnected_at.nil?
                    I18n.t("commands.servers.offline")
                  else
                    I18n.t("commands.servers.offline_for", time: target_server.time_since_last_connection)
                  end
              end

              # Server ID, IP, port, status
              add_connection_info(e)

              # Map, players, game version
              add_server_info(e)

              # Mods
              add_server_mods(e)
            end

          reply(embed)
        end

        #########################
        # Command Methods
        #########################
        def query_server
          # I store the connection port. Query port is always +1
          server = SourceServer.new(IPAddr.new(target_server.server_ip), target_server.server_port.to_i + 1)

          # Connect to the server
          server.init

          # This contains:
          #     :protocol_version, :server_name, :map_name, :game_directory, :game_description, :app_id, :number_of_players,
          #     :max_players, :number_of_bots, :dedicated, :operating_system, :password_needed, :secure, :game_version, :server_port,
          #     :server_id, :server_tags, :game_id
          server.server_info.to_istruct
        rescue
          nil
        end

        def add_connection_info(e)
          e.add_field(name: I18n.t(:server_id), value: "```#{target_server.server_id}```")
          e.add_field(name: I18n.t(:ip), value: "```#{target_server.server_ip}```", inline: true)
          e.add_field(name: I18n.t(:port), value: "```#{target_server.server_port}```")
          return unless target_server.connected?

          e.add_field(name: I18n.t("commands.server.online_for"), value: "```#{target_server.uptime}```")
          e.add_field(name: I18n.t("commands.server.restart_in"), value: "```#{target_server.time_left_before_restart}```")
        end

        def add_server_info(e)
          query_response = query_server
          return if query_response.nil?

          e.add_field(name: I18n.t(:map), value: query_response.map_name, inline: true)
          e.add_field(name: I18n.t(:players), value: "#{query_response.number_of_players}/#{query_response.max_players}", inline: true)
          e.add_field(name: I18n.t(:game_version), value: query_response.game_version, inline: true)
        end

        def add_server_mods(e)
          return if target_server.server_mods.blank?

          grouped_mods = target_server.server_mods.group_by { |mod| mod.mod_required? ? I18n.t(:required_mods) : I18n.t(:optional_mods) }
          grouped_mods.each do |header, mods|
            mod_field = {name: header, value: [], inline: true}
            process_mods(e, mod_field, mods)
          end
        end

        def process_mods(e, mod_field, mods)
          mods.each do |mod|
            # If we have a mod_link, convert that to be a hyperlink
            mod_line =
              if mod.mod_link.blank?
                "#{mod.mod_name} #{mod.mod_version}"
              else
                "[#{mod.mod_name} #{mod.mod_version}](#{mod.mod_link})"
              end

            # If the owner added more mods than our field can hold, send it and create a new field
            if (mod_field[:value].total_size + mod_line.size) > ESM::Embed::Limit::FIELD_VALUE_LENGTH_MAX
              e.add_field(**mod_field)
              mod_field = {name: "#{mod_field[:name]} #{I18n.t(:continued)}", value: [], inline: true}
            end

            mod_field[:value] << mod_line
          end

          e.add_field(**mod_field)
        end
      end
    end
  end
end
All opinions represented herein are my own
- © 2024 - 2026 itsthedevman
- build 43aa0d7