Thursday, September 19, 2024 11:46:57 PM
> settings

Customize


Authenticate

> message.rb
# frozen_string_literal: true

module ESM
  class Message
    #
    # Creates an instance of ESM::Message from JSON. See #to_h for the structure
    # @see #to_h
    #
    # @param json [String] The JSON to parse
    #
    # @return [Self]
    #
    def self.from_string(json)
      from_hash(json.to_h)
    end

    #
    # Creates a instance from a hash
    #
    # @param hash [Hash] The hash that contains the message contents
    #
    # @return [Self] The message
    #
    def self.from_hash(hash)
      hash = hash.deep_symbolize_keys

      message = new
      message = message.set_id(hash[:id]) if hash[:id].present?
      message = message.set_type(hash[:type]) if hash[:type].present?

      if hash[:data].present?
        message = message.set_data(**hash[:data])
      end

      if hash[:metadata].present?
        message = message.set_metadata(
          player: hash.dig(:metadata, :player),
          target: hash.dig(:metadata, :target)
        )
      end

      message = message.add_errors(hash[:errors]) if hash[:errors].present?
      message
    end

    attr_reader :id, :type, :data, :metadata, :errors
    attr_predicate :data

    def initialize
      @id = SecureRandom.uuid
      @type = :call
      @data = Data.new
      @metadata = Metadata.new
      @errors = []
    end

    def set_id(id)
      @id = id
      self
    end

    def set_type(type)
      @type = type.to_sym
      self
    end

    # The primary data for this message. It's the good stuff.
    def set_data(**data_attributes)
      @data = Data.new(**data_attributes)
      self
    end

    #
    # Sets various values used by the arma mod and internally by Message::Error
    #
    # @param player [ESM::User, nil] The user that executed the command
    # @param target [ESM::User, ESM::User::Ephemeral, nil] The user who is the target of this command
    # @param server_id [String, nil] The server the command is being executed on
    #   Used for error messages
    #
    # @return [Message] A referenced to the modified message
    #
    def set_metadata(player: nil, target: nil, server_id: nil)
      player = Player.from(player) if player
      target = Target.from(target) if target

      @metadata = Metadata.new(player:, target:, server_id:)
      self
    end

    # Each hash has the following attributes:
    #   type [Symbol, String] The type of error. Valid options are:
    #     code      # Uses the message to look up a predefined message in the locales
    #     message   # Treats the message like a string and sends it as is
    #   content [String] The content of this error.
    def add_errors(errors = [])
      errors.each do |error|
        error = error.symbolize_keys
        add_error(error[:type].to_s, error[:content])
      end

      self
    end

    #
    # Adds the provided error to this message
    #
    # @param type [String] The error type. Valid types are: "code" and "message"
    # @param message [String] The message or code for this error
    #
    def add_error(type, content)
      return if type.nil? || content.nil?

      @errors << Error.new(self, type, content)
      self
    end

    def data_attributes
      @data.to_h
    end

    #
    # Converts the message to JSON
    #
    # @return [String] The message as JSON
    #
    def to_s
      to_h.to_json
    end

    #
    # Converts the message to a Hash
    #
    # @param for_arma [Boolean] Is this hash arma bound?
    #
    # @return [Hash] The message as a Hash. It has the following keys
    #   {
    #     id: The ID of this message as a UUID
    #     type: The context of this message
    #     data: {
    #       type: Describes the structure of content
    #       content: The actual "data"
    #     },
    #     metadata: {
    #       type: Describes the structure of content
    #       content: The actual "metadata"
    #     },
    #     errors: Any errors associated to this message
    #   }
    #
    def to_h
      {
        id: id,
        type: type,
        data: data_attributes,
        metadata: metadata.to_h,
        errors: errors.map(&:to_h)
      }
    end

    #
    # Returns if there are any errors on this message
    #
    # @return [Boolean]
    #
    def errors?
      errors.any?
    end

    def error_messages
      errors.map(&:to_s)
    end

    def inspect
      "#<ESM::Message #{JSON.pretty_generate(to_h)}>"
    end
  end
end
All opinions represented herein are my own
- © 2024 itsthedevman
- build 3c15a1b