Automate Mobilizon
As I'm hacking a Mobilizon instance to push into the fediverse events fetched from different sources (e.g. the ticket selling platoforms popular in Italy, like VivaTicket), I have to put together some PHP script to automatically interact with the poorly documented Mobilizon API.
Even for the first step - the OAuth authentication - I had to iterate multiple times to obtain a working flow, enabled by the so-called Device Code grant type, which permits non-interactive authentication (at least, after the first abilitation) and unattended automations.
Here the full script intended to generate a client ID, a secret, an access token (to be then used with the GraphQL API) and a refresh token. It displays a URL and a code to be manually copied into the Mobilizon instance (when authenticated with the preferred user, of course).
<?php
/*
Stupid function to perform a POST with cURL
*/
function doPost($url, $params)
{
$curl = curl_init();
$postfields = [];
foreach($params as $name => $value) {
$postfields[] = sprintf('%s=%s', $name, urlencode($value));
}
$postfields = join('&', $postfields);
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $postfields,
CURLOPT_HTTPHEADER => [
"content-type: application/x-www-form-urlencoded"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
$ret = json_decode($response);
curl_close($curl);
return $ret;
}
/*
Configure here the URL of your Mobilizon instance.
$app_website and $app_redirect_uri can be any URL, those will never be used
*/
$mobilizon_instance = 'https://your.mobilizon.instance.com';
$app_name = 'My APP';
$app_scope = 'write:event:create write:event:update write:event:delete write:media:upload write:media:remove write:group:create write:group:update write:group:delete';
$app_website = 'https://www.doesntmatter.com/';
$app_redirect_uri = 'https://www.doesntmatter.com/callback';
/*
Step 1: register the app to obtain a client ID and a secret
*/
$ret = doPost($mobilizon_instance . '/apps', [
'name' => $app_name,
'redirect_uri' => $app_redirect_uri,
'website' => $app_website,
'scope' => $app_scope,
]);
$client_id = $ret->client_id;
$client_secret = $ret->client_secret;
$scope = $ret->scope;
/*
Step 2: ask for device authentication
*/
$ret = doPost($mobilizon_instance . '/login/device/code', [
'client_id' => $client_id,
'scope' => $scope,
]);
echo sprintf("Now go to\n%s\n", $ret->verification_uri);
echo sprintf("and digit the code\n%s\n", $ret->user_code);
/*
Step 3: wait for actual authentication by the user
*/
$device_code = $ret->device_code;
$grant_type = 'urn:ietf:params:oauth:grant-type:device_code';
for ($i = 0; $i < 30; $i++) {
try {
$ret = doPost($mobilizon_instance . '/oauth/token', [
'client_id' => $client_id,
'device_code' => $device_code,
'grant_type' => $grant_type,
]);
if (isset($ret->access_token)) {
/*
Save the parameters in your configuration file
*/
echo $client_id . "\n";
echo $client_secret . "\n";
echo $ret->access_token . "\n";
echo $ret->refresh_token . "\n";
echo $device_code . "\n";
echo "DONE\n";
break;
}
}
catch(\Exception $e) {
// dummy
}
sleep(2);
}