From 71f50b9fb29c4fcb623a14742c321c400978e7e2 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Sat, 17 Oct 2026 17:30:15 +0200 Subject: [PATCH] [dev] adding 0* for the token access + job-* for auto suspend and refuse subscription processed, works :) --- .gitignore | 1 + 00-app-create.php | 26 ++++++++++++ 01-inscription-mastodon.php | 24 +++++++++++ 02-get-access-token.php | 23 +++++++++++ job-auto-suspend-account.php | 60 +++++++++++++++++++++++++++ job-refuse-auto-subscription.php | 70 ++++++++++++++++++++++++++++++++ 6 files changed, 204 insertions(+) create mode 100644 00-app-create.php create mode 100644 01-inscription-mastodon.php create mode 100644 02-get-access-token.php create mode 100644 job-auto-suspend-account.php create mode 100644 job-refuse-auto-subscription.php diff --git a/.gitignore b/.gitignore index 96506f5..ab753e3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ config.php pic/ old/ vendor/ +cache/ diff --git a/00-app-create.php b/00-app-create.php new file mode 100644 index 0000000..a598bd9 --- /dev/null +++ b/00-app-create.php @@ -0,0 +1,26 @@ +build() + ->setBaseUri('https://'.$conf['instance']); + +// create an app and get app based authorization: +$app = $client->methods()->apps()->create( + 'Admin Bot', + ['https://admin.piaille.fr/callback.php'], + 'read write admin:read admin:write', + 'https://piaille.fr', +); + +if (!isset($app->client_id, $app->client_secret)) { + exit('could not create app!'); +} + +echo "client_id: ".$app->client_id."\n"; +echo "client_secret: ".$app->client_secret."\n"; +echo "set them in config.php\n"; diff --git a/01-inscription-mastodon.php b/01-inscription-mastodon.php new file mode 100644 index 0000000..54fe951 --- /dev/null +++ b/01-inscription-mastodon.php @@ -0,0 +1,24 @@ +build() + ->setBaseUri('https://'.$conf['instance']); + +// get user based authorization: +// generate authorize url +// (we'll reuse the app created above) +$authUrl = $client->getAuthorizeUrl( + 'code', + $conf['client_id'], + 'https://admin.piaille.fr/callback.php', + 'read write admin:read admin:write', +); + +// redirect user to this url, where they can log in: +echo "URL: ".$authUrl."&state=".$argv[1]."\n"; + diff --git a/02-get-access-token.php b/02-get-access-token.php new file mode 100644 index 0000000..7a24b9d --- /dev/null +++ b/02-get-access-token.php @@ -0,0 +1,23 @@ +build() + ->setBaseUri('https://'.$conf['instance']); + +$code=$argv[1]; + +// obtain a token using this code: +$token = $client->methods()->oauth()->token( + 'authorization_code', // NB: different from app token call above! + $code, + $conf['client_id'], + $conf['client_secret'], + 'https://admin.piaille.fr/callback.php', + null, + 'read write admin:read admin:write', +); +echo "TOKEN: ".$token->access_token."
\n"; diff --git a/job-auto-suspend-account.php b/job-auto-suspend-account.php new file mode 100644 index 0000000..54e03f5 --- /dev/null +++ b/job-auto-suspend-account.php @@ -0,0 +1,60 @@ +build() + ->setBaseUri('https://'.$conf['instance']); +$client->setAccessToken($conf['token']); + +$badidfile=__DIR__."/cache/latest-auto-suspend-id"; +//$pending = $client->methods()->admin()->accounts()->v2('local','pending'); + +// get 1000 recent statuses from the latest we had and search for bad message patterns : + +if (is_file($badidfile)) + $latest=intval(file_get_contents($badidfile)); +else + $latest=0; + +echo "starting at $latest\n"; + +$suspend_stmt = $db->prepare('SELECT username,domain, suspended_at from accounts WHERE id=?'); + +$sql= 'select id, account_id, text from statuses '; +if ($latest) $sql.=' WHERE id> '.$latest.' '; +$sql.=' order by id desc limit 10000;'; + +$stmt = $db->prepare($sql); +$stmt->execute(); +$first=true; +while ($status = $stmt->fetch(PDO::FETCH_ASSOC)) { + if ($first) $latest=$status['id']; + + if (preg_match('#/share.google#',$status['text'])) { + preg_match_all('#mention">@([^<]*)#',$status['text'],$mat); + if (isset($mat[1]) && count($mat[1])>10) { + // more than 10 mentions + /share.google = suspend this account. + $suspend_stmt->execute([$status['account_id']]); + $badboy = $suspend_stmt->fetch(PDO::FETCH_ASSOC); + if (!$badboy) { + echo "WEIRD: found account ".$status['account_id']." in the statuses but not in the DB !\n"; + continue; + } + + if ($badboy['suspended_at']) { + echo "found account ".$badboy['username']."@".$badboy['domain']." but already suspended, skip\n"; + } else { + echo "found account ".$badboy['username']."@".$badboy['domain']." will suspend it\n"; + $client->methods()->admin()->accounts()->action( id: $status['account_id'], type: 'suspend', text: 'Automatic suspention from the Admin Bot Case #1'); + } + + } + + } + $first=false; +} + +file_put_contents($badidfile,$latest); diff --git a/job-refuse-auto-subscription.php b/job-refuse-auto-subscription.php new file mode 100644 index 0000000..8bc98f2 --- /dev/null +++ b/job-refuse-auto-subscription.php @@ -0,0 +1,70 @@ +build() + ->setBaseUri('https://'.$conf['instance']); +$client->setAccessToken($conf['token']); + +$pending = $client->methods()->admin()->accounts()->v2('local','pending'); +// pending is now a Vazaha\Mastodon\Results\Admin\AccountResult whose "items" are Vazaha\Mastodon\Models\Admin\AccountModel Objects +//print_r($pending); + + +$roles=[ + 0 => '_unknown_ ', + 1 => 'hosting ', + 3 => 'cdn ', + 4 => 'land isp ', + 5 => 'reserved ', + 6 => 'mobile isp', + 8 => 'commercial', + 9 => 'government', + 10 => 'university', +]; + +if (!($pending instanceof Vazaha\Mastodon\Results\Admin\AccountResult)) { + echo "Pending is not a AccountResult, weird\n"; + print_r($pending); + exit(); +} + +// now scan all the results and refuse the one we want to refuse: +// if we have a account request with more than 20 character from any of those maps, we refuse the account request: +$refuse_map=[ + "ru" => "абвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓєѕіїјљњћќѝўџАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЭЮЯ", + "ar" => "ﺍﺎبﺏﺐﺒﺑتﺕﺖﺘﺗثﺙﺚﺜﺛجﺝﺞﺠﺟحﺡﺢﺤﺣخﺥﺦﺨﺧدﺩﺪذﺫﺬرﺭﺮزﺯﺰسﺱﺲﺴﺳشﺵﺶﺸﺷصﺹﺺﺼﺻضﺽﺾﻀﺿطﻁﻂﻄﻃظﻅﻆﻈﻇعﻉﻊﻌﻋغﻍﻎﻐﻏفﻑﻒﻔﻓقﻕﻖﻘﻗكﻙﻚﻜﻛلﻝﻞﻠﻟمﻡﻢﻤﻣنﻥﻦﻨﻧﻩﻪﻬوﻭﻮيﻱﻲﻴﻳآﺁﺂةﺓﺔىﻯﻰ" +]; + + +foreach ($pending as $account) { + if ($account->invite_request=="Automated protocol deliverability probe") { + echo "Will REFUSE immediately this automated account: ".$account->username."\n"; + $client->methods()->admin()->accounts()->reject($account->id); + } else { + + echo "Pending account ".$account->username." ID ".$account->id."\n"; + echo "Languager: ".$account->locale." Reason: ".$account->invite_request."\n"; + echo "IP: ".$account->ip." (info: ".ipinfo($account->ip)."\n"; + echo "\n"; + } + // $client->methods()->admin()->accounts()->reject($account->id); +} + + +function ipinfo($ip) { + global $roles; + $res=json_decode(file_get_contents('https://waf1.octopuce.fr/ipinfo.php?ip='.$ip),true); + $s=""; + $s .= "role: ".($roles[($res['role']??0)]??' ')." "; + $s .= "ip: $ip "; + $s .= "country: ".($res['country']??'unknown')." "; + $s .= "score: ".($res['score']??0)." "; + $s .= "prefix: ".($res['rdap']??'unknown')." "; + $s .= "isp: ".($res['isp']??'unknown')." "; + if (isset($res['whitelisted']) && $res['whitelisted']) $s .= "WHITELISTED! "; + return $s; +}