Aggiunta deduzione lingua dell'istanza dai toot.
This commit is contained in:
parent
2d81910b04
commit
aa143ed793
4 changed files with 253 additions and 55 deletions
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
web/admin/crawler/crawler.log
|
||||
web/admin/crawler/currinst.job
|
||||
web/admin/crawler/instances.job
|
||||
web/admin/crawler/instances.json
|
||||
vendor
|
||||
composer.lock
|
23
.vscode/launch.json
vendored
Normal file
23
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Listen for XDebug",
|
||||
"type": "php",
|
||||
"request": "launch",
|
||||
"port": 9000
|
||||
},
|
||||
{
|
||||
"name": "Launch currently open script",
|
||||
"type": "php",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"cwd": "${fileDirname}",
|
||||
"port": 9000,
|
||||
"runtimeExecutable": "C:\\wamp64\\bin\\php\\php7.3.12\\php.exe"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -16,6 +16,9 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
require __DIR__ . "/../../vendor/autoload.php";
|
||||
use LanguageDetection\Language;
|
||||
|
||||
define('N',"\n");
|
||||
|
||||
$link=false;
|
||||
|
@ -23,27 +26,29 @@ $logf=false;
|
|||
$jsonf=false;
|
||||
|
||||
declare(ticks=1);
|
||||
pcntl_signal(SIGTERM,'signalHandler');// Termination ('kill' was called)
|
||||
pcntl_signal(SIGHUP,'signalHandler');// Terminal log-out
|
||||
pcntl_signal(SIGINT,'signalHandler');// Interrupted (Ctrl-C is pressed)
|
||||
function signalHandler($signal) {
|
||||
global $link, $logf, $jsonf;
|
||||
lecho(N.'Sono stato interrotto.'.N);
|
||||
if ($link) {
|
||||
lecho('La connessione MySQL è aperta, la chiudo.'.N);
|
||||
mysqli_close($link);
|
||||
if(defined("pcntl_signal")) {
|
||||
pcntl_signal(SIGTERM,'signalHandler');// Termination ('kill' was called)
|
||||
pcntl_signal(SIGHUP,'signalHandler');// Terminal log-out
|
||||
pcntl_signal(SIGINT,'signalHandler');// Interrupted (Ctrl-C is pressed)
|
||||
function signalHandler($signal) {
|
||||
global $link, $logf, $jsonf;
|
||||
lecho(N.'Sono stato interrotto.'.N);
|
||||
if ($link) {
|
||||
lecho('La connessione MySQL è aperta, la chiudo.'.N);
|
||||
mysqli_close($link);
|
||||
}
|
||||
if ($jsonf) {
|
||||
lecho('Il file di dump json è aperto, lo chiudo.'.N);
|
||||
// qui no, altrimenti "riprendi" fa poi casino
|
||||
// fwrite($jsonf,'"Fine?": true'.N.'}'.N);
|
||||
fclose($jsonf);
|
||||
}
|
||||
if ($logf) {
|
||||
lecho('Il file di log è aperto, lo chiudo.'.N);
|
||||
fclose($logf);
|
||||
}
|
||||
exit(2);
|
||||
}
|
||||
if ($jsonf) {
|
||||
lecho('Il file di dump json è aperto, lo chiudo.'.N);
|
||||
// qui no, altrimenti "riprendi" fa poi casino
|
||||
// fwrite($jsonf,'"Fine?": true'.N.'}'.N);
|
||||
fclose($jsonf);
|
||||
}
|
||||
if ($logf) {
|
||||
lecho('Il file di log è aperto, lo chiudo.'.N);
|
||||
fclose($logf);
|
||||
}
|
||||
exit(2);
|
||||
}
|
||||
|
||||
$opts=array(
|
||||
|
@ -257,7 +262,7 @@ function flushtronc($id) {
|
|||
|
||||
function truncs($str,$tab,$col,$ctx) {
|
||||
global $tables, $tronconi;
|
||||
$size=$tables[$tab][$col];
|
||||
$size=$tables[strtolower($tab)][$col];
|
||||
$len=mb_strlen($str,'UTF-8');
|
||||
if ($len>$size) {
|
||||
$tronconi[]=array('id'=>null,'tab'=>$tab,'col'=>$col,'ctx'=>$ctx,'len'=>$len,'size'=>$size);
|
||||
|
@ -269,12 +274,12 @@ function truncs($str,$tab,$col,$ctx) {
|
|||
function truncn($num,$tab,$col,$ctx) {
|
||||
global $tables;
|
||||
if (is_numeric($num)) {
|
||||
if ($num>$tables[$tab][$col]['max']) {
|
||||
notify($ctx.': ho dovuto troncare «'.$num.'» al valore massimo «'.$tables[$tab][$col]['max'].'» che può avere nella colonna «'.$col.'» della tabella «'.$tab.'»).',2);
|
||||
$num=$tables[$tab][$col]['max'];
|
||||
} elseif ($num<$tables[$tab][$col]['min']) {
|
||||
notify($ctx.': ho dovuto troncare «'.$num.'» al valore minimo «'.$tables[$tab][$col]['min'].'» che può avere nella colonna «'.$col.'» della tabella «'.$tab.'»).',2);
|
||||
$num=$tables[$tab][$col]['min'];
|
||||
if ($num>$tables[strtolower($tab)][$col]['max']) {
|
||||
notify($ctx.': ho dovuto troncare «'.$num.'» al valore massimo «'.$tables[strtolower($tab)][$col]['max'].'» che può avere nella colonna «'.$col.'» della tabella «'.$tab.'»).',2);
|
||||
$num=$tables[strtolower($tab)][$col]['max'];
|
||||
} elseif ($num<$tables[strtolower($tab)][$col]['min']) {
|
||||
notify($ctx.': ho dovuto troncare «'.$num.'» al valore minimo «'.$tables[strtolower($tab)][$col]['min'].'» che può avere nella colonna «'.$col.'» della tabella «'.$tab.'»).',2);
|
||||
$num=$tables[strtolower($tab)][$col]['min'];
|
||||
}
|
||||
} else {
|
||||
notify($ctx.': truncn(): mi aspettavo un numero, invece non lo era; ritorno «0».',3);
|
||||
|
@ -401,7 +406,7 @@ if (!$riprendi) {
|
|||
|
||||
function willtrunc($str,$tab,$col) {
|
||||
global $tables;
|
||||
if (mb_strlen($str,'UTF-8')>$tables[$tab][$col])
|
||||
if (mb_strlen($str,'UTF-8')>$tables[strtolower($tab)][$col])
|
||||
return(true);
|
||||
else
|
||||
return(false);
|
||||
|
@ -450,36 +455,195 @@ function subarimp($glue,$key,&$arr) {
|
|||
function notify($msg,$sev) {
|
||||
global $link, $tables;
|
||||
lecho('NOTIFICAZIÒ: '.strip_tags($msg).N);
|
||||
mysqli_query($link,'INSERT INTO Notifications (ID, Notification, Severity, Microtime, Seen) VALUES (NULL, \''.myesc($link,mb_substr($msg,0,$tables['Notifications']['Notification'],'UTF-8')).'\', '.$sev.', \''.microtime(true).'\', 0)')
|
||||
mysqli_query($link,'INSERT INTO Notifications (ID, Notification, Severity, Microtime, Seen) VALUES (NULL, \''.myesc($link,mb_substr($msg,0,$tables['notifications']['Notification'],'UTF-8')).'\', '.$sev.', \''.microtime(true).'\', 0)')
|
||||
or mexit(mysqli_error($link).N,3);
|
||||
}
|
||||
|
||||
function langs($instid) {
|
||||
/** <LANGUAGE MANAGEMENT> */
|
||||
/**
|
||||
* Effettua una chiamata alla API di Mastodon.
|
||||
*
|
||||
* @param string $host L'host da chiamare (e.g.: "mastodon.bida.im")
|
||||
* @param string $path Il path della API (e.g.: "/api/v1/timelines/public?local=true")
|
||||
* @return mixed L'oggetto ritornato dalla chiamata, già parsato da json_decode, o NULL se la chiamata fallisce
|
||||
*/
|
||||
function get_api($host, $path) {
|
||||
global $context;
|
||||
try {
|
||||
$buf = @file_get_contents('https://' . $host . $path, false, $context);
|
||||
} catch(Exception $e) {
|
||||
echo "error:";
|
||||
echo $e;
|
||||
return NULL;
|
||||
}
|
||||
if ($buf!==false) {
|
||||
$data = json_decode($buf, true);
|
||||
return $data;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Torna un elenco di linguaggi riconosciuti nel toot fornito con relativa probabilità.
|
||||
*
|
||||
* @param mixed $toot Il toot da analizzare, come ritornato dalle API
|
||||
* @return array Mappa tra codice lingua e probabilità che il toot sia in quella lingua.
|
||||
*/
|
||||
function get_toot_languages($toot) {
|
||||
$l = $toot['language'];
|
||||
$res = [];
|
||||
if($l !== NULL) {
|
||||
// la lingua è specificata già nel toot: usa quella
|
||||
$langs[$l] = 1;
|
||||
} else {
|
||||
// la lingua non è specificata: deducila
|
||||
$text = strip_tags($toot['content']);
|
||||
$ld = new Language;
|
||||
$langs = $ld->detect($text)->bestResults()->close();
|
||||
}
|
||||
// raggruppa le lingue derivate, e.g.: "zh" e "zh-CN"
|
||||
$grouped_langs = array();
|
||||
foreach($langs as $key => $value) {
|
||||
$l = explode("-", $key)[0];
|
||||
if(array_key_exists($l, $grouped_langs)) {
|
||||
$grouped_langs[$l] = max($grouped_langs[$l], $value);
|
||||
} else {
|
||||
$grouped_langs[$l] = $value;
|
||||
}
|
||||
}
|
||||
return $grouped_langs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Date le probabilità di lingua per ogni toot, calcola la media.
|
||||
*
|
||||
* @param array $detected_langs Array di mappe tra lingua e probabilità
|
||||
* @return array Mappa tra lingua e probabilità
|
||||
*/
|
||||
function summary($detected_langs) {
|
||||
$res = Array();
|
||||
foreach($detected_langs as $langs) {
|
||||
foreach($langs as $l => $weight) {
|
||||
if(!array_key_exists($l, $res)) {
|
||||
$res[$l] = 0;
|
||||
}
|
||||
$res[$l] += $weight;
|
||||
}
|
||||
}
|
||||
foreach($res as $l => $sumweight) {
|
||||
$res[$l] = $sumweight / count($detected_langs);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function per usort: compara due array usando il primo elemento.
|
||||
*
|
||||
* @param array $entry1 Primo array da comparare
|
||||
* @param array $entry2 Secondo array da comparare
|
||||
* @return number -1, 0 o 1 a seconda che $entry1[0] sia minore, uguale o superiore a $entry2[0]
|
||||
*/
|
||||
function sort_weights($entry1, $entry2) {
|
||||
$w1 = $entry1[0];
|
||||
$w2 = $entry2[0];
|
||||
return $w1 < $w2 ? 1 : $w1 == $w2 ? 0 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data una mappa di lingue, ritorna una lista di linguaggi considerati probabili.
|
||||
*
|
||||
* @param array $summary Mappa tra lingue e probabilità
|
||||
* @return string[] Elenco di lingue considerate probabili
|
||||
*/
|
||||
function get_languages($summary) {
|
||||
$lst = [];
|
||||
foreach($summary as $code => $weight) {
|
||||
$lst[] = [$weight, $code];
|
||||
}
|
||||
usort($lst, 'sort_weights');
|
||||
$languages = [];
|
||||
$lastweight = 0;
|
||||
foreach($lst as $entry) {
|
||||
$l = $entry[1];
|
||||
$weight = $entry[0];
|
||||
if($weight < $lastweight * 2 / 3) {
|
||||
break;
|
||||
}
|
||||
$languages[] = $l;
|
||||
$lastweight = $weight;
|
||||
}
|
||||
return $languages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ritorna una lista di lingue probabili per la data istanza.
|
||||
*
|
||||
* @param string $host Hostname dell'istanza (e.g.: "mastodon.bida.im")
|
||||
* @return string[] Lista di lingue probabili
|
||||
*/
|
||||
function get_instance_langs($host) {
|
||||
$data = get_api($host, '/api/v1/timelines/public?local=true');
|
||||
if($data == NULL) {
|
||||
return [];
|
||||
}
|
||||
$detected_langs = array_map('get_toot_languages', $data);
|
||||
$summary = summary($detected_langs);
|
||||
$languages = get_languages($summary);
|
||||
return $languages;
|
||||
}
|
||||
/** </LANGUAGE MANAGEMENT> */
|
||||
|
||||
/**
|
||||
* ucfirst UTF-8 aware function
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
* @see http://ca.php.net/ucfirst
|
||||
*/
|
||||
function my_ucfirst($string, $e ='utf-8') {
|
||||
if (function_exists('mb_strtoupper') && function_exists('mb_substr') && !empty($string)) {
|
||||
$string = mb_strtolower($string, $e);
|
||||
$upper = mb_strtoupper($string, $e);
|
||||
preg_match('#(.)#us', $upper, $matches);
|
||||
$string = $matches[1] . mb_substr($string, 1, mb_strlen($string, $e), $e);
|
||||
} else {
|
||||
$string = ucfirst($string);
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
function langs($instid, $uri) {
|
||||
global $info, $instrow, $link;
|
||||
$instlangs=array();
|
||||
if (akeavinn('languages',$info)) {
|
||||
$pos=0;
|
||||
foreach ($info['languages'] as $lang) {
|
||||
$res=mysqli_query($link,'SELECT * FROM Languages WHERE Code=\''.myesc($link,$lang).'\'')
|
||||
or mexit(mysqli_error($link).N,3);
|
||||
if (mysqli_num_rows($res)<1) {
|
||||
$NameIt=myesc($link,truncs(ucfirst(locale_get_display_name($lang,'it')),'Languages','NameIT','«'.$instrow['URI'].'»'));
|
||||
$NameEn=myesc($link,truncs(ucfirst(locale_get_display_name($lang,'en')),'Languages','NameEN','«'.$instrow['URI'].'»'));
|
||||
$NameFr=myesc($link,truncs(ucfirst(locale_get_display_name($lang,'fr')),'Languages','NameFR','«'.$instrow['URI'].'»'));
|
||||
$NameEs=myesc($link,truncs(ucfirst(locale_get_display_name($lang,'es')),'Languages','NameES','«'.$instrow['URI'].'»'));
|
||||
$NameOrig=myesc($link,truncs(ucfirst(locale_get_display_name($lang,$lang)),'Languages','NameOrig','«'.$instrow['URI'].'»'));
|
||||
mysqli_query($link,'INSERT INTO Languages (ID, Code, NameIT, NameEN, NameFR, NameES, NameOrig) VALUES (NULL, \''.myesc($link,truncs($lang,'Languages','Code','«'.$instrow['URI'].'»')).'\', \''.$NameIt.'\', \''.$NameEn.'\', \''.$NameFr.'\', \''.$NameEs.'\', \''.$NameOrig.'\')')
|
||||
or mexit(mysqli_error($link).N,3);
|
||||
$langid=mysqli_insert_id($link);
|
||||
flushtronc($langid);
|
||||
} else {
|
||||
$row=mysqli_fetch_assoc($res);
|
||||
$langid=$row['ID'];
|
||||
}
|
||||
$pos++;
|
||||
$instlangs[]=array('InstID'=>$instid,'LangID'=>$langid,'Pos'=>$pos,'Code'=>$lang);
|
||||
}
|
||||
$languages = get_instance_langs($uri);
|
||||
if(count($languages) == 0 && akeavinn('languages',$info)) {
|
||||
$languages = $info['languages'];
|
||||
}
|
||||
echo "Lingue trovate: " . implode(", ", $languages).N;
|
||||
$pos=0;
|
||||
foreach($languages as $lang) {
|
||||
$res=mysqli_query($link,'SELECT * FROM Languages WHERE Code=\''.myesc($link,$lang).'\'')
|
||||
or mexit(mysqli_error($link).N,3);
|
||||
if (mysqli_num_rows($res)<1) {
|
||||
$NameIt=myesc($link,truncs(my_ucfirst(locale_get_display_name($lang,'it')),'Languages','NameIT','«'.$instrow['URI'].'»'));
|
||||
$NameEn=myesc($link,truncs(my_ucfirst(locale_get_display_name($lang,'en')),'Languages','NameEN','«'.$instrow['URI'].'»'));
|
||||
$NameFr=myesc($link,truncs(my_ucfirst(locale_get_display_name($lang,'fr')),'Languages','NameFR','«'.$instrow['URI'].'»'));
|
||||
$NameEs=myesc($link,truncs(my_ucfirst(locale_get_display_name($lang,'es')),'Languages','NameES','«'.$instrow['URI'].'»'));
|
||||
$NameOrig=myesc($link,truncs(my_ucfirst(locale_get_display_name($lang,$lang)),'Languages','NameES','«'.$instrow['URI'].'»'));
|
||||
$q = 'INSERT INTO Languages (ID, Code, NameIT, NameEN, NameFR, NameES, NameOrig) VALUES (NULL, \''.myesc($link,truncs($lang,'Languages','Code','«'.$instrow['URI'].'»')).'\', \''.$NameIt.'\', \''.$NameEn.'\', \''.$NameFr.'\', \''.$NameEs.'\', \''.$NameOrig.'\')';
|
||||
mysqli_query($link, $q)
|
||||
or mexit(mysqli_error($link).N,3);
|
||||
$langid=mysqli_insert_id($link);
|
||||
flushtronc($langid);
|
||||
} else {
|
||||
$row=mysqli_fetch_assoc($res);
|
||||
$langid=$row['ID'];
|
||||
}
|
||||
$pos++;
|
||||
$instlangs[]=array('InstID'=>$instid,'LangID'=>$langid,'Pos'=>$pos,'Code'=>$lang);
|
||||
}
|
||||
// }
|
||||
return($instlangs);
|
||||
}
|
||||
|
||||
|
@ -597,7 +761,7 @@ while ($i<$cinsts) {
|
|||
$ok=false;
|
||||
lecho('ERRORE :-('.N);
|
||||
// questo è anche il limbo delle istanze che non rispondono, perciò controlliamo se già esistono nel db e, nel caso, aggiorniamo InstChecks
|
||||
$res=mysqli_query($link,'SELECT * FROM Instances WHERE URI=\''.myesc($link,mb_substr($dom,0,$tables['Instances']['URI'],'UTF-8')).'\'')
|
||||
$res=mysqli_query($link,'SELECT * FROM Instances WHERE URI=\''.myesc($link,mb_substr($dom,0,$tables['instances']['URI'],'UTF-8')).'\'')
|
||||
or mexit(mysqli_error($link).N,3);
|
||||
if (mysqli_num_rows($res)>0) {
|
||||
lecho('«'.$dom.'» non risponde, ma è presente nel database; aggiorno InstChecks.'.N);
|
||||
|
@ -742,7 +906,7 @@ while ($i<$cinsts) {
|
|||
$oldinstlangs=array();
|
||||
while ($row=mysqli_fetch_assoc($res))
|
||||
$oldinstlangs[]=$row;
|
||||
$instlangs=langs($instrow['ID']);
|
||||
$instlangs=langs($instrow['ID'], $instrow['URI']);
|
||||
if ($instlangs!=$oldinstlangs) {
|
||||
notify('La lista delle lingue utilizzate dichiarate dall’istanza «<a href="editinst.php?id='.$instrow['ID'].'">'.$instrow['URI'].'</a>» è cambiata da «'.subarimp(', ','Code',$oldinstlangs).'» a «'.subarimp(', ','Code',$instlangs).'».',1);
|
||||
mysqli_query($link,'DELETE FROM InstLangs WHERE InstID='.$instrow['ID'])
|
||||
|
@ -773,7 +937,7 @@ while ($i<$cinsts) {
|
|||
|
||||
flushtronc($instid);
|
||||
|
||||
$instlangs=langs($instid);
|
||||
$instlangs=langs($instid, $instrow['URI']);
|
||||
foreach ($instlangs as $row) {
|
||||
mysqli_query($link,'INSERT INTO InstLangs (InstID, LangID, Pos) VALUES ('.$row['InstID'].', '.$row['LangID'].', '.$row['Pos'].')')
|
||||
or mexit(mysqli_error($link).N,3);
|
||||
|
|
5
web/composer.json
Normal file
5
web/composer.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"require": {
|
||||
"patrickschur/language-detection": "^3.4"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue