#!/bin/bash # 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 . MASTHOME='/var/lib/mastodon' MASTENVFP="$MASTHOME/live/.env.production" SISTERSFP="istanzesorelle" LOCAL=0 INTERACTIVE=0 HELP="SINTASSI mastblocksmerge.sh [opzioni] DESCRIZIONE Questo script integra i dati di una o più blocklist esterne nella tabella domain_blocks di mastodon. Legge i domini delle istanze di cui recuperare la blocklist da un file di inizializzazione, per default \"$SISTERSP\" (formato del file: un dominio per riga), prova a recuperare ciascuna blocklist da https://[dominio]/domain_blocks.txt, costruisce dalle liste recuperate un\'unica lista senza duplicati, si collega al db di mastodon e scrive nella tabella domain_blocks i dati relativi alle istanze bloccate che non sono già presenti nella tabella stessa. Per la connessione al db di mastodon legge i dati necessari dal file di configurazione di mastodon, per default \"$MASTENVFP\" È pensato per essere eseguito periodicamente da un cron job, come utente mastodon oppure root oppure altro utente che abbia accesso in lettura al file di configurazione di mastodon. OPZIONI -H, --home Definisce la home di mastodon (per default \"$MASTHOME\") e di conseguenza il percorso del suo file di configurazione (per default \"$MASTENVFP\"). È comunque possibile specificare individualmente il percorso del file di configurazione di mastodon con l\'opzione che segue. -e, --envfp Definisce il percorso del file di configurazione di mastodon in uso. -s, --sistersfp Definisce il percorso del file di inizializzazione da cui leggere la lista dei domini delle istanze sorelle. -l, --local Interpreta il file di inizializzazione come lista di file locali contenenti blacklist (formato: un file per riga). -i, --interactive Modalità interattiva: se vengono nelle blocklist vengono trovate istanze ancora non presenti nel database di mastodon, viene chiesto per ciascuna se aggiungerla o meno. -h, --help Mostra questo aiuto ed esce." args=("$@") i=0 while [ $i -lt ${#args[@]} ]; do if [ "${args[$i]:0:1}" == "-" ]; then case "${args[$i]}" in "-H" | "--home" ) if [ -z "${args[$i+1]}" ]; then echo "L'opzione \"${args[$i]}\" richiede un parametro (usa \"-h\" per l'aiuto)." exit 1 else ((i++)) MASTHOME=$(echo "${args[$i]}" | sed -e 's/\/$//') MASTENVFP="$MASTHOME/live/.env.production" fi ;; "-e" | "--envfp" ) if [ -z "${args[$i+1]}" ]; then echo "L'opzione \"${args[$i]}\" richiede un parametro (usa \"-h\" per l'aiuto)." exit 1 else ((i++)) MASTENVFP="${args[$i]}" fi ;; "-s" | "--sistersfp" ) if [ -z "${args[$i+1]}" ]; then echo "L'opzione \"${args[$i]}\" richiede un parametro (usa \"-h\" per l'aiuto)." exit 1 else ((i++)) SISTERSFP="${args[$i]}" fi ;; "-l" | "--local" ) LOCAL=1 ;; "-i" | "--interactive" ) INTERACTIVE=1 ;; "-h" | "--help" ) echo "$HELP" exit 0 ;; *) echo "\"${args[$i]}\": opzione sconosciuta (usa \"-h\" per l'aiuto)." exit 1 ;; esac else echo "\"${args[$i]}\": opzione sconosciuta (usa \"-h\" per l'aiuto)." exit 1 fi ((i++)) done [ ! -e "$MASTENVFP" ] && echo "\"$MASTENVFP\" non esiste, muoio (usa \"-h\" per l'aiuto)." && exit 1 [ ! -f "$MASTENVFP" ] && echo "\"$MASTENVFP\" non è un file, muoio (usa \"-h\" per l'aiuto)." && exit 1 [ ! -r "$MASTENVFP" ] && echo "\"$MASTENVFP\" non è leggibile, muoio (usa \"-h\" per l'aiuto)." && exit 1 [ ! -e "$SISTERSFP" ] && echo "\"$SISTERSFP\" non esiste, muoio (usa \"-h\" per l'aiuto)." && exit 1 [ ! -f "$SISTERSFP" ] && echo "\"$SISTERSFP\" non è un file, muoio (usa \"-h\" per l'aiuto)." && exit 1 [ ! -r "$SISTERSFP" ] && echo "\"$SISTERSFP\" non è leggibile, muoio (usa \"-h\" per l'aiuto)." && exit 1 DB_HOST=`grep 'DB_HOST' "$MASTENVFP"|sed -e 's/[^=]*=//'` DB_PORT=`grep 'DB_PORT' "$MASTENVFP"|sed -e 's/[^=]*=//'` DB_NAME=`grep 'DB_NAME' "$MASTENVFP"|sed -e 's/[^=]*=//'` DB_USER=`grep 'DB_USER' "$MASTENVFP"|sed -e 's/[^=]*=//'` DB_PASS=`grep 'DB_PASS' "$MASTENVFP"|sed -e 's/[^=]*=//'` IFS=$'\n' function decode { #dominio record[0]=$(echo "$1" | sed -e 's/\t.*//') #data creazione record[1]=$(echo "$1" | sed -e 's/^[^\t]*\t\([^\t]*\).*/\1/') #data ultima modifica record[2]=$(echo "$1" | sed -e 's/^[^\t]*\t[^\t]*\t\([^\t]*\).*/\1/') #tipo di blocco record[3]=$(echo "$1" | sed -e 's/^[^\t]*\t[^\t]*\t[^\t]*\t\([^\t]*\).*/\1/') #rifiuto media record[4]=$(echo "$1" | sed -e 's/^[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t\([^\t]*\).*/\1/') #rifiuto reports record[5]=$(echo "$1" | sed -e 's/^[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t\([^\t]*\).*/\1/') #commento pubblico record[6]=$(echo "$1" | sed -e 's/^[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t\([^\t]*\).*/\1/') if [ "${record[4]}" == "f" ]; then record[4]="No" elif [ "${record[4]}" == "t" ]; then record[4]="Si" fi if [ "${record[5]}" == "f" ]; then record[5]="No" elif [ "${record[5]}" == "t" ]; then record[5]="Si" fi if [ "${record[3]}" == "0" ]; then record[3]="Silenziata" elif [ "${record[3]}" == "1" ]; then record[3]="Sospesa" elif [ "${record[3]}" == "2" ]; then record[3]="Nessuno" fi } for sisdom in $(grep -P '^[^#]+[^\s]+' "$SISTERSFP"); do if [ $LOCAL -eq 0 ]; then blocks+="$(curl --connect-timeout 3 -s "https://$sisdom/domain_blocks.txt" | grep -P '^[^#]+[^\s]+')$IFS" else blocks+="$(cat "$sisdom" | grep -P '^[^#]+[^\s]+')$IFS" fi done blocks=$(echo "$blocks" | head -n -1 | sort -u) echo "$blocks" echo "~~~~~~~~~~~~~~~~~~~~" okblocks='' for line in $blocks; do dom=$(echo "$line" | sed -e 's/\t.*//' -e 's/\./\\./g') echo "$okblocks" | grep -P "^$dom\t" if [ $? -ne 0 ]; then entries=$(echo "$blocks" | grep -P "^$dom\t") howmany=$(echo "$entries" | wc -l) if [ $howmany -gt 1 ]; then if [ $INTERACTIVE -eq 1 ]; then i=0 for entry in $entries; do ((i++)) echo "$i: $entry" done read else # qui ci vorrebbe codice "intelligente" che sceglie la entry più recente, ma per ora così okblocks+="$line$IFS" fi fi fi done okblocks=$(echo "$okblocks" | head -n -1 | sort) echo "$okblocks" echo "~~~~~~~~~~~~~~~~~~~~" exit blocks=$(PGPASSWORD="$DB_PASS" psql -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -U "$DB_USER" -c 'SELECT domain, updated_at, severity, public_comment FROM domain_blocks' -A -t -F $'\t') i=0 for line in $allblocks; do dom=$(echo "$line" | sed -e 's/\t.*//' -e 's/\./\\./g') echo "$blocks" | grep -P "^$dom\t" &>/dev/null [ $? -ne 0 ] && newblocks+="$line$IFS" && ((i++)) done newblocks=$(echo "$newblocks" | head -n -1 | sort) [ $i -eq 0 ] && echo "Non ho trovato nessuna nuova istanza bloccata." && exit 0 echo "Ho trovato $i istanza/e bloccata da aggiungere." if [ $INTERACTIVE -eq 1 ]; then for line in $newblocks; do decode "$line" echo "Dominio: ${record[0]}; Data creaz.: ${record[1]}; Data ult. mod.: ${record[2]}; Tipo blocco: ${record[3]}; Rifiuto media: ${record[4]}; Rifiuto reports: ${record[5]}; Commento pub.: ${record[6]}" ask=1 while [ $ask -eq 1 ]; do read -p "Vuoi aggiungere questa istanza alla tabella delle istanze bloccate? [S/n] " inp echo "$inp" | grep -P '^[sSnN]{0,1}$' &>/dev/null [ $? -eq 0 ] && ask=0 done if [ "$inp" == "" ] || [ "$inp" == "s" ] || [ "$inp" == "S" ]; then buf+="$line$IFS" fi done newblocks=$(echo "$buf" | head -n -1) fi echo "$newblocks" | PGPASSWORD="$DB_PASS" psql -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -U "$DB_USER" -A -t -c "COPY domain_blocks ( domain, created_at, updated_at, severity, reject_media, reject_reports, public_comment ) FROM STDIN WITH ( FORMAT text, DELIMITER ' ' )"