PHP to Rust via Copilot

Joe • May 2, 2024

learning php rust copilot

PHP to Rust via Copilot

I set out to build a small project in Rust. I wanted to scrape a website and parse a JSON payload. I ran into issues quickly as this was my first real project build it Rust. I thought this might be a great use case to see if GitHub Copilot could help me convert some PHP code I had to Rust.

Below is the PHP code I wanted to convert to Rust. Savvy PHP developers will quickly spot this is a Laravel Artisan Command.

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Spatie\DiscordAlerts\Facades\DiscordAlert;

class live extends Command
{
    protected $signature = 'app:live';

    protected $description = 'Check if ConkDetects is live on TikTok and send a Discord alert if they are.';

    public function handle()
    {
        $httpClient = new \GuzzleHttp\Client();
        $response = $httpClient->get('https://www.tiktok.com/@conkdetects/live');
        $htmlString = (string) $response->getBody();
        $doc = new \DOMDocument();
        libxml_use_internal_errors(true);
        $doc->loadHTML($htmlString);
        $xpath = new \DOMXPath($doc);

        $full_json = $xpath->evaluate("//script[@id=\"SIGI_STATE\"]");
        $parsed = json_decode($full_json[0]->nodeValue, true);
        $user_count = $parsed['LiveRoom']['liveRoomUserInfo']['liveRoom']['liveRoomStats']['userCount'];

        if ($user_count > 10) {
            DiscordAlert::message("ConkDetects is live with {$user_count} viewers", [
                [
                    'title' => '@ConkDetects is live, YEAH!',
                    'description' => 'https://www.tiktok.com/@conkdetects/live',
                    'color' => '#50C878',
                ]
            ]);
        }
    }
}

Using Copilot Chat in PHPStorm I asked Copilot to convert this PHP code to Rust. Below is the first part of the conversation.

Asking Copilot to convert PHP code to Rust

The complete Rust code Copilot gave me is below:

use reqwest::blocking::Client;
use scraper::{Html, Selector};
use serde_json::Value;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    let client = Client::new();
    let response = client.get("https://www.tiktok.com/@conkdetects/live").send()?;
    let body = response.text()?;
    let document = Html::parse_document(&body);
    let script_selector = Selector::parse(r#"script[id="SIGI_STATE"]"#).unwrap();
    let script_element = document.select(&script_selector).next().unwrap();
    let json_str = script_element.text().collect::<String>();
    let parsed: Value = serde_json::from_str(&json_str)?;
    let user_count = parsed["LiveRoom"]["liveRoomUserInfo"]["liveRoom"]["liveRoomStats"]["userCount"]
        .as_u64()
        .unwrap_or(0);

    if user_count > 10 {
        send_discord_alert(user_count)?;
    }

    Ok(())
}

fn send_discord_alert(user_count: u64) -> Result<(), Box<dyn Error>> {
    let client = Client::new();
    let webhook_url = "https://discord.com/api/webhooks/your_webhook_id/your_webhook_token";
    let payload = json!({
        "content": format!("ConkDetects is live with {} viewers", user_count),
        "embeds": [
            {
                "title": "@ConkDetects is live, YEAH!",
                "description": "https://www.tiktok.com/@conkdetects/live",
                "color": 3368703
            }
        ]
    });
    client.post(webhook_url).json(&payload).send()?;

    Ok(())
}

Rust lang code generated from Copilot chat

When I ran the code it failed to compile because I was missing the json feature from the reqwest crate. I asked Copilot to fix the error and it gave me instructions on how to update my Cargo.toml file. I followed the instructions to add the json feature to the reqwest crate in my Cargo.toml file and everything compiled and ran as expected.

Asking Copilot to fix the error generated from the code it produced

Updated code runs exactly as expected.

Updated the Rust code and everything compiles and runs as expected

This was my first time attempting to build something in Rust and leveraging GitHub Copilot to learn how to do what I already knew how to do in PHP. It was a great learning experience and if you're not already using a tool similar to Copilot you should look into it!