====== Lemmy API PHP Command Line Client ======
After the recent (June 2023) influx of Lemmy spam accounts, there isn't an easy way to delete the hundreds of spam accounts that showed up over night (before I felt forced to enable captchas and email verification etc).
I built a small API command line client to basically allow me to run the [[https://join-lemmy.org/api/classes/LemmyHttp.html#purgePerson|purgePerson]] API command easily in a loop.
You can run it very simply with something like this:
./lemmy-api.php purgePerson 116
or to iterate over a number of ids:
for i in 145 156 162; do ./lemmy-api.php purgePerson $i; done
and to work through all IDs from 170-240:
for i in `seq 170 240`; do ./lemmy-api.php purgePerson $i; done 
You can view the code on my repo at https://git.mckillop.org/gitweb/?p=lemmy-api-php or checkout directly with git using:
git clone https://git.mckillop.org/lemmy-api-php
Made a copy of the config file and edit ''config.php'' to add your domain, username and password to get started.
cd lemmy-api-php
cp config.example.php config.php
Here is some example code for a PHP command line tool that will let you purge local users.
#!/usr/bin/php
 "PERSONID [reason]",
        "deletePost"    => "POSTID"
);
if(empty($argv[1]) or empty($argv[2])) {
        echo "Usage: ./".basename(__FILE__)." COMMAND [parameters]\n";
        echo "You can get help on a specific command with ./".basename(__FILE__)." help COMMAND\n";
        echo "Available commands: ".implode(", ", array_keys($implemented_commands))."\n";
        exit(0);
} else {
        $selected_command = $argv[1];
}
// generate token, or load one from the cache file
if(!file_exists($token_file)) {
        echo "Logging in for the first time and storing token...";
        $data = json_decode(http_post($lemmy_api_url."user/login", array('username_or_email'=>$username, 'password'=>$password)), true);
        $token = $data['jwt'];
        if(!empty($token)) {
                echo "OK";
                file_put_contents($token_file, $token);
        } else {
                echo "Error logging in.";
        }
        echo "\n";
} else {
        $token = file_get_contents($token_file);
}
switch($selected_command) {
        case "help":
                if(in_array($argv[2], array_keys($implemented_commands))) {
                        echo "Usage: ./".basename(__FILE__)." {$argv[2]} ".$implemented_commands[$argv[2]]."\n";
                } else {
                        echo "Unrecognised command, available commands: ".implode(", ", array_keys($implemented_commands))."\n";
                }
                break;
        case "purgePerson":
                if(sizeof($argv) > 4)
                        exit("Too many parameters, if supplying a reason, please use enclose with quotation marks\n");
                $person_id = $argv[2];
                $reason = "";
                if(!empty($argv[3]))
                        $reason = $argv[3];
                echo "Attempting to purge person $person_id...";
                $data = json_decode(http_post($lemmy_api_url."admin/purge/person", array('auth' => $token, 'person_id'=>intval($person_id), 'reason'=>$reason)), true);
                $status = "ERROR";
                if(!empty($data['success']) and $data['success'] == 1)
                        $status = "OK";
                echo $status."\n";
                break;
        case "deletePost":
                $post_id = $argv[2];
                echo "Attempting to delete post ID $post_id...";
                $data = json_decode(http_post($lemmy_api_url."post/delete", array('auth' => $token, 'post_id'=>intval($post_id), 'deleted'=>true)), true);
                $status = "ERROR";
                if(!empty($data['post_view']) and $data['post_view']['post']['deleted'] == 1)
                        $status = "OK";
                echo $status."\n";
                break;
        default:
                echo "Unrecognised command";
                break;
}
function http_post($url, $data) {
        $ch = curl_init();
        $payload = json_encode($data);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER,
                array('Content-Type:application/json')
        );
        $result = curl_exec($ch);
        if(curl_errno($ch))
                print_r(curl_error($ch));
        return $result;
}
?>
That should be enough to get you started using the API from the command line.  If I get time I'll put a more complete version of this with some other useful commands (like banPerson) on my repo as I find a use for them.
===== Getting Local Lemmy Users =====
To get the list of local users (person_id column) on your Lemmy instance, connect to the postgres database.  For me, in docker, this is something like:
sudo docker exec -it  bash
psql -U lemmy
select * from local_user;
===== Pre v0.18 =====
While working on this, I discovered the API purgePerson command didn't actually work - something to do with the order of routes.  Working with [[https://matrix.to/#/@ksynwa:matrix.org|@ksynwa:matrix.org]] in the Lemmy Development Matrix room, he found a fix and [[https://github.com/LemmyNet/lemmy/pull/3244/commits/53c9efc09fe1caced310da18ac9588b3d2fd2b01|made a PR]] that was accepted into v0.18 (so this should be working in subsequent version of Lemmy (after v0.17.4).