Added “new instance announcement toot” function

This commit is contained in:
pezcurrel 2024-08-06 14:14:43 +02:00
parent adbac86540
commit d2743164d3

View file

@ -17,6 +17,7 @@
*/
const N="\n";
const RN="\r\n";
define('SNAME',basename(__FILE__));
const LIBDP='/../lib';
@ -28,6 +29,8 @@ require __DIR__.LIBDP.'/mb_lcfirst.php';
require __DIR__.LIBDP.'/ghs.php';
require __DIR__.LIBDP.'/ght.php';
require __DIR__.LIBDP.'/supplangs.php';
require __DIR__.LIBDP.'/gettlds.php';
require __DIR__.LIBDP.'/mastodon_postlen.php';
require __DIR__.LIBDP.'/vendor/autoload.php';
use LanguageDetection\Language;
@ -52,10 +55,13 @@ $opts=[
'functimeout'=>20,
'ldtoots'=>40,// number of toots to check with the automatic language detection function
'dryrun'=>false,
'sendtoot'=>true,
'fetchusers'=>false,
'udiratts'=>5,
'udirfailst'=>90,
'minmsgimplev'=>1
'minmsgimplev'=>1,
'bothost'=>null,
'bottoken'=>null
];
$msglevs=['Debug', 'Info', 'Warning', 'Error', 'None'];
@ -93,11 +99,15 @@ OPTIONS
SPECIFICATION» below to see how to specify time.
DEFAULT: '.ght($opts['conntimeout'],null,0).'
-T, --functimeout <time>
Sets the timeout for every downloa. See section «TIME SPECIFICATION» below
Sets the timeout for every download. See section «TIME SPECIFICATION» below
to see how to specify time.
DEFAULT: '.ght($opts['functimeout'],null,0).'
-d, --dryrun
If this option is set, the script wont write anything in the database.
-S, --dontoot
If this option is set, the script wont try to read «getinstinfo.ini» file
and wont post an announcement toot about a new instance.
See NEW INSTANCE ANNOUNCEMENT TOOT below for more info.
-m, --minmsgimplev <«debug»|«info»|«warning»|«error»|«none»>
Defines the minimum “importance level” of messages to be written to the
text user interface. There are 4 “importance levels”, in this order of
@ -116,6 +126,17 @@ TIME SPECIFICATION
7 minutes and 12 seconds you can use «1y,6M,2w,3d,5h,7m,12; but you can
also use «12s,7m,5h,3d,2w,6M,1, or even «18M,1w,1w,2d,1d,3h,2h,7m,12.
NEW INSTANCE ANNOUNCEMENT TOOT
This script can send an announcement toot when the instance it checks is new.
You can disable this function with the «- or «--dontoot» options (see
above). If new instance announcement toot is enabled, this script expects
to find a «getinstinfo.ini» file in the same directory it lives in, with
a «bothost» parameter defining the instance to use to send the toot,
a «bottoken» parameter defining the token to be used to post, and
a «botmaxchars» parameter defining the maximum number of characters allowed
for toots on the defined instance.
LICENSE
This program comes with ABSOLUTELY NO WARRANTY; for details see the source.
@ -152,6 +173,8 @@ for ($i=1; $i<$argc; $i++) {
$opts['ldtoots']=$argv[$i]+0;
} elseif ($argv[$i]=='-d' || $argv[$i]=='--dryrun') {
$opts['dryrun']=true;
} elseif ($argv[$i]=='-S' || $argv[$i]=='--dontoot') {
$opts['sendtoot']=false;
} elseif ($argv[$i]=='-m' || $argv[$i]=='--minmsgimplev') {
if ($i+1>=$argc || !in_array(ucfirst(strtolower($argv[$i+1])),$msglevs))
mexit('option «'.$argv[$i].'» requires a “message importance level” value as an argument (use «-h» to read help).'.N,1);
@ -182,6 +205,14 @@ catch (Exception $error) { mexit('could not set «utf8mb4» charset for MySQL: '
// for php versions < 8
if ($res===false) mexit('could not set MySQL charset: '.mysqli_error($link).' ['.mysqli_errno($link).'].'.N,1,true);
if ($opts['sendtoot']) {
$inifp=__DIR__.'/getinstinfo.ini';
$iniarr=@parse_ini_file($inifp)
or mexit('could not open config file «'.$inifp.'»'.N,1);
if (!isset($iniarr['bothost']) || !isset($iniarr['bottoken']) || !isset($iniarr['botmaxchars']) || preg_match('/^[0-9]+$/',$iniarr['botmaxchars'])!=1)
mexit('config file «'.$inifp.'» is malformed, please check its format in the help text (you can read it using the «-h» or «--help» options).'.N,1);
}
$mastodons=[];
$res=myq($link,'SELECT Name FROM Platforms WHERE Consider=1',__LINE__);
while ($row=mysqli_fetch_assoc($res))
@ -756,6 +787,66 @@ if (isset($idata['blocks']) && is_array($idata['blocks'])) {
}
}
if ($opts['sendtoot'] && $instanswered && $idata['IsMastodon'] && $idata['FirstSeen']==$now) {
gettlds();
eecho(0,'«'.$opts['hostname'].'»: this instance is new, trying to send a toot about it...'.N);
$endpoint='https://'.$iniarr['bothost'].'/api/v1/statuses';
$toot='A new Mastodon instance, https://'.$opts['hostname'].', has been found by the crawler at https://mastodon.help'.N.N.'Name: ';
(is_null($idata['Title'])) ? $toot.='unspecified' : $toot.=$idata['Title'];
$toot.=N.N.'Languages: ';
(array_key_exists('languages',$idata) && is_array($idata['languages']) && count($idata['languages'])>0) ? $toot.=implode($idata['languages']) : $toot.='unspecified/undetectable';
$toot.=N.N.'Users: ';
(is_null($idata['UserCount'])) ? $toot.='unspecified' : $toot.=$idata['UserCount'];
$toot.=N.N.'Max. characters per post: ';
(is_null($idata['MaxTootChars']) || $idata['MaxTootChars']==500) ? $toot.='500' : $toot.=$idata['MaxTootChars'];
$toot.=N.N.'Registration: ';
if (is_null($idata['RegOpen'])) {
$toot.='unspecified';
} elseif ($idata['RegOpen']==1) {
$toot.='open';
if ($idata['RegReqApproval']==1)
$toot.=' (requires admins approval)';
elseif ($idata['RegReqApproval']==0)
$toot.=' (does not require admins approval)';
} elseif ($idata['RegOpen']==0) {
$toot.='closed';
}
$toot.=N.N.'Short description: ';
(is_null($idata['ShortDesc'])) ? $toot.='unspecified' : $toot.=$idata['ShortDesc'];
$toot.=N.N.'Long description: ';
(is_null($idata['LongDesc'])) ? $toot.='unspecified' : $toot.=html2text($idata['LongDesc']);
if (postlen($toot)>$iniarr['botmaxchars']) {
while (postlen($toot)+2>$iniarr['botmaxchars'])
$toot=preg_replace('#\s+(\S|\n)+$#u','',$toot);
$toot.=' …';
}
$context=[
'http'=>[
'header'=>'Authorization: Bearer '.$iniarr['bottoken'].RN.
'Idempotency-Key'.md5($iniarr['bothost'].$now.rand(1000,9999)).RN.
'Content-type: application/x-www-form-urlencoded'.RN,
'method'=>'POST',
'content'=>http_build_query([
'status'=>$toot,
'visibility'=>'direct',
'language'=>'en'
]),
'timeout'=>$opts['conntimeout']
]
];
$context=stream_context_create($context);
$res=@file_get_contents($endpoint,false,$context);
if ($res===false) {
eecho(2,'«'.$opts['hostname'].'»: could not connect to «'.$iniarr['bothost'].'».'.N);
} else {
$res=@json_decode($res,true);
if ($res===false)
eecho(2,'«'.$opts['hostname'].'»: trying to post a toot about this new instance, «'.$iniarr['bothost'].'» has not returned valid JSON data.'.N);
else
eecho(1,'«'.$opts['hostname'].'»: correctly posted announcement about this new instance on «'.$iniarr['bothost'].'» :-)'.N);
}
}
if ($instanswered && $opts['fetchusers'] && $idata['IsMastodon'] && !is_null($idata['Version']) && $idata['Version']>='4.0.0') {
eecho(0,'«'.$opts['hostname'].'»: trying to fetch users info from directory API...'.N);
$users=[];// array of users in this instance's directory
@ -1294,4 +1385,31 @@ function waituntilonline() {
if ($gotoff) eecho(1,'it seems we are back online! :-)'.N);
}
function headcb($arr) {
$lpad='';
$rpad='';
for ($i=0; $i<7-$arr[2]; $i++) {
$lpad.='[';
$rpad.=']';
}
return "{$lpad} ".mb_strtoupper($arr[4])." {$rpad}\n\n";
}
function html2text($html,$keeplinks=false) {
$html=preg_replace('#\r#','',$html);
//$html=preg_replace('#\n|\r#','',$html);
if ($keeplinks) $html=preg_replace('#<a\s.*href="(.*)".*>#iU',' [link: $1] ',$html);
$html=preg_replace('#<li>#i',' * ',$html);
$html=preg_replace_callback('#(<h)(\d)(>)(.*)(</h\d>)#iU','headcb',$html);
$html=preg_replace('#<p>|<div>|<ul>|<ol>#i',"\n\n",$html);
$html=preg_replace('#</p>|</div>|</ul>|</ol>|</li>#i',"\n\n",$html);
$html=preg_replace('#<br>|<br />#i',"\n",$html);
$html=strip_tags($html);
$html=preg_replace('#\s\n#',"\n",$html);
$html=preg_replace('# +#',' ',$html);
$html=preg_replace('#\n+#',"\n\n",$html);
$html=trim($html)."\n";
return $html;
}
?>