Emulate User Activity with Bots
Tags: laravel, ecommerce, bots, php
Published: 2024-06-09 17:26:03

In our sales events platform, [Auctibles](https://auctibles.com), sellers have the exciting opportunity to create various events. These range from a sale event at a fixed price to live auctions, where buyers bid the price up, providing a dynamic and engaging experience. 

# The Technology

We use the Laravel framework in the context of the TALL stack: Tailwind, Alpine.js, Laravel, and Livewire. 

# Why Emulation?

For a demo environment, it's crucial that we accurately emulate buyers'  activity for a seller. This includes sending buy orders and chat messages. The purpose of the emulation is to allow the seller to get a feeling of how the event with multiple buyers will be observed from the event control screens. This includes changing the quantities of items still available, dynamic price changes, and chat messages from buyers.

# Ordinary Buyers

The buy screen is a Livewire component. Clicking the BUY button sends a broadcast event: `LiveBuy,` `LiveBid`,... 

Similarly, buyers send chat messages via a broadcast event ChatMessage. 

# Bots for Emulation

We emulate buyers' activity via a bot. The bot is a ReactPHP server that periodically sends the same broadcast events that ordinary buyers send. 

The server receives a `set_timer` GET call at the event's start and a `stop_timer` GET call at its end. 

	$loop = Factory::create();
	$server = new Server(function (ServerRequestInterface $request) use($loop) {
        
            $path = $request->getUri()->getPath();
            $method = $request->getMethod();
            
            if ($path == '/set_timer' && $method === 'GET') {

              $params = $request->getQueryParams();
			        $event_id = $params['event_id'] ?? null;
			        
			        // start emulation
			        
			        return Response::plaintext('timer set')->withStatus(Response::STATUS_OK);   
			        
		        } else if ($path == '/stop_timer' && $method === 'GET') {

                $params = $request->getQueryParams();
		            $event_id = $params['event_id'] ?? null;   
		            
		            // stop emulation
		            
		            return Response::plaintext('timer stopped')->withStatus(Response::STATUS_OK);               
						}
        
	});
        
	$socket = new SocketServer('0.0.0.0:' . config('app.BOT_SERVER_PORT'));
	$server->listen($socket);
	
	$loop->run();
	
# Laravel to ReactPHP 
	
These calls are received from the component where the seller controls the event, using  `Http`:

 	  $url = config('app.BOT_SERVER_URL') . ':' . config('app.BOT_SERVER_PORT') . '/set_timer';
	  $data = [
      'event_id' => $this->event->id,
	  ];

    $response = Http::withQueryParameters($data)->get($url);
  
# Starting the Bot 
   
To start the emulation, we set a periodic timer, 

    $timer = $loop->addPeriodicTimer($this->period_in_seconds, function () use ($event_id) {
	                           
       $this->send_bid($event_id);
       $this->send_message($event_id);
	
    });
    
We store the timer in an array:

	$this->timers[$event_id] = $timer;

# Stopping the Bot 	
    
    $loop->cancelTimer($this->timers[$event_id]);
    unset($this->timers[$event_id]);