Friday, September 20, 2024 4:38:27 AM
> settings

Customize


Authenticate

> responses.rb
# frozen_string_literal: true

class WebsocketClient
  module Responses
    # This controls how the websocket server treats the command.
    # Valid options:
    #   send_ignore_message [Boolean] Does this command need to send the ignore message. This matches the expected behavior from the DLL
    #   delay [Range] Delay sending the response by some random number between this range (in seconds). Simulates the delay from the Arma server
    CONFIG = {
      server_success_command: {},
      server_error_command: {},
      post_initialization: {send_ignore_message: true},
      me: {delay: 0..1},
      territories: {delay: 0..1},
      pay: {send_ignore_message: true, delay: 0..3},
      gamble: {send_ignore_message: true, delay: 0..3},
      setterritoryid: {delay: 0..1},
      add: {send_ignore_message: true, delay: 0..3},
      allterritories: {send_ignore_message: true, delay: 0..3},
      exec: {send_ignore_message: true, delay: 0..3},
      promote: {send_ignore_message: true, delay: 0..3},
      demote: {send_ignore_message: true, delay: 0..3},
      remove: {send_ignore_message: true, delay: 0..3},
      upgrade: {send_ignore_message: true, delay: 0..3},
      restore: {delay: 0..1},
      player: {send_ignore_message: true, delay: 0..3},
      reward: {send_ignore_message: true, delay: 0..3},
      info: {send_ignore_message: true, delay: 0..3},
      stuck: {delay: 0..1},
      reset: {delay: 0..1},
      logs: {delay: 0..1}
    }.freeze

    def response_server_success_command
      send_response
    end

    def response_server_error_command
      send_response(parameters: [{error: "oops"}])
    end

    def response_post_initialization
      @connected = true

      # The data the bot sends to the server to be stored
      @server_data = @data.parameters
      @server_id = @data.parameters.server_id
    end

    def response_me
      territories = {}

      Faker::Number.within(range: 1..3).times do
        territories[Faker::FunnyName.two_word_name] = Faker::Crypto.md5[0, 3]
      end

      send_response(
        parameters: {
          locker: Faker::Number.within(range: 1..30_000),
          score: Faker::Number.within(range: 1..30_000),
          name: Faker::Internet.username,
          money: Faker::Number.within(range: 1..30_000),
          damage: Faker::Number.within(range: 1..100),
          hunger: Faker::Number.within(range: 1..100),
          thirst: Faker::Number.within(range: 1..100),
          kills: Faker::Number.within(range: 1..100),
          deaths: Faker::Number.within(range: 1..100),
          territories: territories.to_json
        }
      )
    end

    def response_territories
      return send_response if @flags.RETURN_NO_TERRITORIES

      # One static to test large amounts of moderators
      territories = [
        TerritoryGenerator.generate(moderator_count: 60)
      ]

      # Some random ones
      Faker::Number.within(range: 1..5).times do
        territories << TerritoryGenerator.generate
      end

      send_response(parameters: territories)
    end

    def response_pay
      send_response(
        parameters: [{
          payment: Faker::Number.between(from: 20, to: 600),
          locker: Faker::Number.between(from: 2000, to: 1_000_000_000)
        }]
      )
    end

    def response_gamble
      return send_response(parameters: [{error: "Not enough poptabs!"}]) if @flags.NOT_ENOUGH_MONEY

      amount = @data.parameters.amount.to_i
      locker_before = amount

      if rand > 0.50
        type = "won"
        locker_after = locker_before + amount
      else
        type = "loss"
        locker_after = locker_before - amount
      end

      send_response(
        parameters: [{
          type: type,
          amount: amount,
          locker_before: locker_before,
          locker_after: locker_after
        }]
      )
    end

    # The command is actually !setid, but the v1 DLL is expecting this.
    def response_setterritoryid
      return send_response(parameters: [{success: false, reason: "Some reason"}]) if @flags.FAIL_WITH_REASON
      return send_response(parameters: [{success: false}]) if @flags.FAIL_WITHOUT_REASON

      send_response(parameters: [{success: true}])
    end

    def response_add
      send_response
    end

    def response_allterritories
      return send_response(parameters: []) if @flags.RETURN_NO_TERRITORIES

      territories = []
      Faker::Number.between(from: 75, to: 100).times do
        territories << {
          id: (rand < 0.5) ? SecureRandom.uuid[0..4] : Faker::Lorem.sentence[0..20],
          territory_name: Faker::Lorem.sentence,
          owner_name: Faker::Name.name,
          owner_uid: Faker::Number.number(digits: 17).to_s
        }
      end

      send_response(parameters: territories)
    end

    # !sqf
    def response_exec
      message =
        if @data.parameters.target == "server"
          if @flags.WITH_RETURN
            "Executed on server successfully. Returned: ```true```"
          else
            "Executed code on server"
          end
        elsif @flags.ERROR # For some reason, I decided not to use the error system
          "Invalid target or target is not online"
        else
          "Executed code on target"
        end

      send_response(parameters: [{message: message}])
    end

    def response_promote
      send_response
    end

    def response_demote
      send_response
    end

    def response_remove
      send_response
    end

    def response_upgrade
      territory = TerritoryGenerator.generate

      send_response(
        parameters: [{
          cost: Faker::Number.between(from: 0, to: 10_000_000),
          level: territory[:level],
          range: territory[:radius],
          locker: Faker::Number.between(from: 0, to: 10_000_000)
        }]
      )
    end

    def response_restore
      send_response(
        parameters: [{
          success: @flags.SUCCESS
        }]
      )
    end

    def response_player
      # This handles kill and heal
      response = {type: @data.parameters.type}

      if %w[money locker respect].include?(@data.parameters.type)
        modified_amount = @data.parameters.value.to_i
        previous_amount = Faker::Number.between(from: 5000, to: 5_000_000)

        response = response.merge(
          modified_amount: modified_amount,
          previous_amount: previous_amount,
          new_amount: previous_amount + modified_amount
        )
      end

      send_response(parameters: [response])
    end

    def response_reward
      receipt = @server_data.reward_items.to_h
      receipt << ["Poptabs (Player)", @server_data.reward_player_poptabs] if @server_data.reward_player_poptabs.positive?
      receipt << ["Poptabs (Locker)", @server_data.reward_locker_poptabs] if @server_data.reward_locker_poptabs.positive?
      receipt << ["Respect", @server_data.reward_respect] if @server_data.reward_respect.positive?

      send_response(parameters: [{receipt: receipt}])
    end

    def response_info
      response = {}

      case @data.parameters.query
      when "territory_info"
        response = TerritoryGenerator.generate
      when "player_info"
        territories = {}

        if rand < 0.5
          Faker::Number.within(range: 1..3).times do
            territories[Faker::FunnyName.two_word_name] = Faker::Crypto.md5[0, 3]
          end
        end

        response = {
          locker: Faker::Number.within(range: 1..30_000),
          score: Faker::Number.within(range: 1..30_000),
          name: Faker::Internet.username,
          kills: Faker::Number.within(range: 1..100),
          deaths: Faker::Number.within(range: 1..100),
          territories: territories
        }

        if @flags.PLAYER_ALIVE
          response = response.merge(
            money: Faker::Number.within(range: 1..30_000),
            damage: Faker::Number.within(range: 0..0.9),
            hunger: Faker::Number.within(range: 1..100),
            thirst: Faker::Number.within(range: 1..100)
          )
        end
      end

      send_response(parameters: [response])
    end

    def response_stuck
      send_response(parameters: [{success: @flags.SUCCESS}])
    end

    def response_reset
      send_response(parameters: [{success: @flags.SUCCESS}])
    end

    # 0: The search parameters
    # 1..-1: The parsed logs
    #   date: <String> October 11 2020
    #   file_name (Exile_TradingLog.log): <Array>
    #     line: <Integer>
    #     entry: <String>
    #     date: <String 2020-10-11>
    def response_logs
      return send_response(parameters: [{}]) if @flags.NO_LOGS

      # The first object is not used, but is required
      logs = [{}]

      Faker::Number.between(from: 1, to: 4).times do
        logs << {
          :date => Faker::Date.in_date_period,
          "ExileTradingLog.log" => LogGenerator.generate_trading_log,
          "ExileTerritoryLog.log" => LogGenerator.generate_territory_log,
          "ExileDeathLog.log" => LogGenerator.generate_death_log
        }
      end

      send_response(parameters: logs)
    end
  end
end
All opinions represented herein are my own
- © 2024 itsthedevman
- build 340fbb8