Friday, September 20, 2024 2:51:04 AM
> settings

Customize


Authenticate

> arguments.rb
# frozen_string_literal: true

module ESM
  module Command
    class Arguments < Hash
      attr_reader :templates, :command_instance, :display_name_mapping

      def initialize(command = nil, templates: {}, values: {})
        @command_instance = command
        @templates = templates.symbolize_keys

        # Map the display name to the name itself
        @display_name_mapping = templates.values.each_with_object({}) { |a, hash| hash[a.display_name] = a.name }

        prepare(values.symbolize_keys)
      end

      def validate!
        # This collects all of the invalid arguments together and sends one message instead of breaking at the first invalid argument
        invalid_arguments =
          templates.filter_map do |(name, template)|
            # Apply pre-defined transformations and then validate the content
            self[name] = template.transform_and_validate!(self[name], command_instance)

            nil
          rescue ESM::Exception::InvalidArgument => e
            self[name] = nil
            e.data
          end

        # All the arguments are valid
        return if invalid_arguments.empty?

        embed =
          ESM::Embed.build do |e|
            help_documentation = invalid_arguments.map_join("\n\n", &:help_documentation)

            help_usage = ESM::Command.get(:help).usage(
              with_args: true,
              arguments: {with: command_instance.usage(with_slash: false, with_args: false)}
            )

            argument_word = "argument".pluralize(invalid_arguments.size)

            e.title = "**Invalid #{argument_word}**"
            e.description = <<~STRING
              ```#{command_instance.usage(with_args: true, use_placeholders: true, arguments: self)}```
              **Please read the following and correct any errors before trying again.**

              **Missing #{argument_word}**
              #{help_documentation}

              For more information, use the following command:
              ```#{help_usage}```
            STRING

            e.add_field(
              name: I18n.t("commands.help.command.examples"),
              value: command_instance.examples
            )
          end

        raise ESM::Exception::CheckFailure, embed
      end

      def inspect
        ESM::JSON.pretty_generate(
          values: self,
          command: command_instance&.command_name,
          templates: templates.map(&:to_h)
        )
      end

      def with_templates
        each_with_object({}) do |(name, value), hash|
          hash[name] = [templates[name], value]
        end
      end

      def template(name)
        name = name.to_sym
        mapping = @display_name_mapping[name] || name

        templates[mapping]
      end

      ###
      # Allows referencing arguments that may not exist on the current command, but does on others
      def method_missing(method_name, *arguments, &block)
        self[method_name.to_sym]
      end

      def respond_to_missing?(method_name, _include_private = false)
        key?(method_name.to_sym) || super
      end
      #
      ###

      private

      def prepare(values)
        return if templates.empty?

        templates.values.each do |argument|
          name = argument.name

          # self[server_id] = value from discord
          self[name] = values[argument.display_name]

          # self.server_id
          define_method(name) { self[name] }

          # self.for #=> server_id
          define_method(argument.display_name) { self[name] }

          # self.server_id = value
          define_method(:"#{name}=") { |value| self[name] = value }
        end
      end
    end
  end
end
All opinions represented herein are my own
- © 2024 itsthedevman
- build 340fbb8