1
0
Fork 0
MastodonStartpage/crawler/crawler.php
2019-12-01 09:07:45 +01:00

282 lines
8.6 KiB
PHP
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/php
<?php
/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define('N',"\n");
$inifp='crawler.ini';
$help='DESCRIZIONE
Questo script prende una lista di istanze mastodon sorellate, ciascuna
con (o anche senza, però sarebbe meglio con) una relativa lista di
istanze da essa bloccate, e genera una lista delle istanze note alle
istanze sorellate, escludendone quelle bloccate - più, al momento,
quelle il cui endpoint [istanza]/api/v1/instance non risponde, e quelle
che hanno chiusa la registrazione di nuovi utenti.
SINTASSI
crawler.php [opzioni]
OPZIONI
-i, --inifp
Imposta il file di configurazione (per default "'.$inifp.'").
Tutte le altre opzioni, che siano specificate prima o dopo questa,
hanno la precedenza su quelle definite nel file di configurazione.
-t, --timeout
Imposta il timeout delle richieste http.
-e, --excludeafter
Imposta il lasso di tempo (in secondi) dopo il quale un\'istanza che
non si identifica (il cui endpoint [istanza]/api/v1/instance non
risponde) viene eliminata dal listone di tutte le istanze testate.
-b, --biglistfp
Imposta il file da cui leggere le istanze già testate in passato (se
non è specificata l\'opzione "-d", vedi sotto) e in cui scrivere
il listone di tutte le istanze testate.
-p, --prodlistfp
Imposta il file in cui scrivere la lista delle istanze occhei.
-s, --sistersfp
Imposta il file da cui leggere le istanze sorelle e le relative liste
di istanze sospese-silenziate.
-d, --dontloadbl
Evita di caricare il listone delle istanze già testate in passato.
-h, --help
Mostra questo aiuto ed esce.
This program comes with ABSOLUTELY NO WARRANTY; for details see
the source.
This is free software, and you are welcome to redistribute it under
certain conditions; see <http://www.gnu.org/licenses/> for details.'.N;
function mexit($msg,$code) {
echo($msg);
exit($code);
}
$opts=array(
'excludeafter'=>60*60*24*30,
'sistersfp'=>'istanzesorelle',
'dontloadbl'=>0,
'timeout'=>5,
'biglistfp'=>'listona.json',
'prodlistfp'=>'listina.json'
);
for ($i=1; $i<$argc; $i++) {
if ($argv[$i]=='-i' || $argv[$i]=='--inifp') {
if ($i+1>=$argc || $argv[$i+1]=='')
mexit('Lopzione «'.$argv[$i].'» richiede di specificare un file di configurazione (usa «-h» per vedere la guida).'.N,1);
$i++;
$inifp=$argv[$i];
if (!file_exists($inifp) || !is_file($inifp) || !is_readable($inifp))
mexit('"'.$inifp.'" non esiste, non è un file o non è leggibile.'.N,1);
}
}
if (file_exists($inifp)) {
$buf=@parse_ini_file($inifp);
if ($buf!==false) {
foreach ($buf as $key=>$val) {
if (array_key_exists($key,$opts))
$opts[$key]=$val;
}
} else {
echo('Attenzione: non ho potuto leggere la configurazione dal file "'.$inifp.'", potrebbe essere non leggibile o corrotto.'.N);
}
}
$f=@fopen($inifp,'w');
if ($f!==false) {
foreach ($opts as $key=>$val)
fwrite($f,$key.'='.$val.N);
fclose($f);
} else {
echo('Attenzione: non ho potuto salvare la configurazione nel file "'.$inifp.'".'.N);
}
for ($i=1; $i<$argc; $i++) {
if (substr($argv[$i],0,1)=='-') {
switch($argv[$i]) {
case '-i':
case '--inifp':
$i++;
break;
case '-e':
case '--excludeafter':
if ($i+1>=$argc || preg_match('/^[0-9]+$/',$argv[$i+1])!==1)
mexit('Lopzione «'.$argv[$i].'» richiede un parametro numerico intero (usa «-h» per vedere la guida).'.N,1);
$i++;
$opts['excludeafter']=$argv[$i];
break;
case '-t':
case '--timeout':
if ($i+1>=$argc || preg_match('/^[0-9]+$/',$argv[$i+1])!==1)
mexit('Lopzione «'.$argv[$i].'» richiede un parametro numerico intero (usa «-h» per vedere la guida).'.N,1);
$i++;
$opts['timeout']=$argv[$i];
break;
case '-b':
case '--biglistfp':
if ($i+1>=$argc || $argv[$i+1]=='')
mexit('Lopzione «'.$argv[$i].'» richiede un parametro di tipo file (usa «-h» per vedere la guida).'.N,1);
$i++;
$opts['biglistfp']=$argv[$i];
break;
case '-p':
case '--biglistfp':
if ($i+1>=$argc || $argv[$i+1]=='')
mexit('Lopzione «'.$argv[$i].'» richiede un parametro di tipo file (usa «-h» per vedere la guida).'.N,1);
$i++;
$opts['biglistfp']=$argv[$i];
break;
case '-s':
case '--sistersfp':
if ($i+1>=$argc || $argv[$i+1]=='')
mexit('Lopzione «'.$argv[$i].'» richiede un parametro di tipo file (usa «-h» per vedere la guida).'.N,1);
$i++;
$opts['sistersfp']=$argv[$i];
break;
case '-d':
case '--dontloadbl':
$opts['dontloadbl']=1;
break;
case '-h':
case '--help':
mexit($help,1);
break;
default:
mexit('Opzione "'.$argv[$i].'" sconosciuta (usa «-h» per vedere la guida).'.N,1);
break;
}
} else {
mexit('Opzione "'.$argv[$i].'" sconosciuta (usa «-h» per vedere la guida).'.N,1);
}
}
$sisters=array();
echo('Carico il file delle istanze sorelle ("'.$opts['sistersfp'].'") ... ');
$buf=@file_get_contents($opts['sistersfp']);
if ($buf!==false) {
echo('OK :-)'.N);
$buf=explode(N,$buf);
foreach ($buf as $val) {
if ($val!='' && $val{0}!='#') {
$kv=explode('|',$val);
if ($kv[1]=='') $kv[1]=NULL;
$sisters[$kv[0]]=$kv[1];
}
}
} else {
mexit(N.'Non ho potuto aprire il file delle istanze sorelle "'.$opts['sistersfp'].'", muoio.'.N,1);
}
if (count($sisters)<1)
mexit('Il file delle istanze sorelle "'.$opts['sistersfp'].'" non contiene alcuna voce, muoio.'.N,1);
$biglist=array();
if ($opts['dontloadbl']==0) {
if (file_exists($opts['biglistfp']) && is_file($opts['biglistfp']) && is_readable($opts['biglistfp'])) {
echo('Carico la listona pre-esistente ("'.$opts['biglistfp'].'") ... ');
$buf=@file_get_contents($opts['biglistfp']);
if ($buf!==false) {
echo('OK :-)'.N);
$biglist=json_decode($buf,true);
} else {
echo('ERRORE :-('.N);
}
}
}
$context=stream_context_create(array('http'=>array('timeout'=>$opts['timeout'])));
$blinstances=array();
foreach ($sisters as $dom=>$bluri) {
if (!is_null($bluri)) {
echo('Recupero la lista delle istanze bloccate da "'.$dom.'" ("'.$bluri.'") ... ');
$f=@fopen($bluri,'r',false,$context);
if ($f!==false) {
// le prime 4 righe non ci interessano
for ($i=0; $i<4; $i++)
fgets($f);
while (!feof($f)) {
$lin=fgets($f);
if (preg_match('/^\|([^\|]*)\|([^\|]*)\|([^\|]*)\|$/',$lin,$buf)===1)
$blinstances[]=$buf[1];
}
fclose($f);
echo('OK :-)'.N);
} else {
echo('ERRORE :-('.N);
}
} else {
echo('NON recupero la lista delle istanze bloccate da "'.$dom.'": la url della stessa non è definita.'.N);
}
}
ksort($blinstances);
foreach ($sisters as $dom=>$bluri) {
echo('Recupero la lista delle istanze note a "'.$dom.'" ... ');
$buf=@file_get_contents('https://'.$dom.'/api/v1/instance/peers',false,$context);
if ($buf!==false) {
echo('OK :-)'.N);
$peers=json_decode($buf,true);
foreach ($peers as $pdom) {
if (!in_array($pdom,$blinstances) && !array_key_exists($pdom,$biglist)) {
$biglist[$pdom]=NULL;
}
}
} else {
echo('ERRORE :-('.N);
}
}
ksort($biglist);
$prodlist=array();
$i=0;
$qinst=count($biglist);
foreach ($biglist as $dom=>$oinfo) {
echo('Recupero le informazioni su "'.$dom.'" ('.($i+1).'/'.$qinst.' - '.round(100/$qinst*$i).'%) ... ');
$buf=@file_get_contents('https://'.$dom.'/api/v1/instance',false,$context);
if ($buf!==false) {
echo('OK :-)'.N);
$info=json_decode($buf,true);
$info['cr-last_checked']=time();
$info['cr-was_ok']=true;
$biglist[$dom]=$info;
if (!array_key_exists('registrations',$info) || $info['registrations']==true) {
$prodlist[$dom]=$info;
echo('"'.$dom.'" aggiunta alla lista delle istanze ok! :-)'.N);
}
} else {
echo('ERRORE :-( ... ');
if (is_null($oinfo) || time()-$oinfo['cr-last_checked']<=$opts['excludeafter']) {
echo('ma riproveremo...'.N);
$oinfo['cr-last_checked']=time();
$oinfo['cr-was_ok']=false;
$biglist[$dom]=$oinfo;
} else {
echo('e non riproveremo...'.N);
}
}
$i++;
}
$json=json_encode($biglist,JSON_PRETTY_PRINT);
file_put_contents($opts['biglistfp'],$json);
$json=json_encode($prodlist,JSON_PRETTY_PRINT);
file_put_contents($opts['prodlistfp'],$json);
echo('Totale istanze nella listona: '.count($biglist).N);
echo('Totale istanze nella listina di quelle occhei: '.count($prodlist).N);
?>