From c8d5427e16352925906e32381e88299a13236316 Mon Sep 17 00:00:00 2001 From: ij Date: Thu, 17 Aug 2023 19:25:27 +0000 Subject: [PATCH] added cron option and deactivation Instead of deleting right away after the limit has been reached, the users will now be deactivated. The new "--cron" option can now be invoked more often (like hourly, daily, whatever) to delete the deactivated users. You can define how many accounts get deleted in each cron run. Default is 2 users. Reason for this is to prevent too much load on the server when hundreds or even thousands of users get deleted. Also there is some statistics at the end when the script runs. --- cleanup-mastodon-users.sh | 260 ++++++++++++++++++++++++++------------ 1 file changed, 182 insertions(+), 78 deletions(-) diff --git a/cleanup-mastodon-users.sh b/cleanup-mastodon-users.sh index 233b567..18c1036 100644 --- a/cleanup-mastodon-users.sh +++ b/cleanup-mastodon-users.sh @@ -10,9 +10,11 @@ UPPERLIMIT="7 months" TOOTCTL="~/live/bin/tootctl" set -f +# set the following variables accordingly to your site +# the admin will get a notification mail in BCC -# get some settings from the Mastodon config and write it to another file, so that we can source it and make use of it grep -e ^"DB_" -e ^"LOCAL_DOMAIN" /home/mastodon/live/.env.production > /home/mastodon/bin/cleanup-mastodon-users.conf + . /home/mastodon/bin/cleanup-mastodon-users.conf # the following lines should be moved to a config file, eg. /usr/local/etc/cleanup_friendica.conf @@ -23,23 +25,34 @@ mastodonpath="/home/mastodon/live" #DB_USER=mastodon #DB_PASS= -site="" -siteurl="" -siteadmin=" now()-'${UPPERLIMIT}'::interval and username not in ($sqlprotectedusers) limit ${limit_delete}" | tr -d " " ) + # when there is less then 1 user to delete (=0) then exit + if [ ${num_deactivated_total} -lt 1 ]; then + exit 0 + fi + echo "===================================" + echo "Number deactivated accounts: ${num_deactivated_total}" + echo "Deleting this many accounts: ${limit_delete}" + echo "===================================" + for u in $(psql -U ${DB_USER} -w -h ${DB_HOST} -p ${DB_PORT} -t ${DB_NAME} -c "select concat(username||';'||display_name||';'||email||';'||to_char(a.created_at, 'YYYY-MM-DD')||';'||to_char(current_sign_in_at,'YYYY-MM-DD')) from accounts a, users u where disabled is true and a.id=u.account_id and current_sign_in_at > now()-'${UPPERLIMIT}'::interval and username not in ($sqlprotectedusers) order by current_sign_in_at limit ${limit_delete}" | tr -d " " ); do + #echo ${u} + username=$(echo "${u}" | awk -F ";" '{print $1}') + dispname=$(echo "${u}" | awk -F ";" '{print $2}') + profileurl="https://nerdculture.de/@${username}" + usermail=$(echo "${u}" | awk -F ";" '{print $3}') + registered=$(echo "${u}" | awk -F ";" '{print $4}') + lastlogin=$(echo "${u}" | awk -F ";" '{print $5}') + # delete account when last login is older than 7 months and send mail about deletion + # you should copy & paste the text from 6 months for the first runs of this script + # and later change the text to a notification that the account has been deleted. + # if username is a protected user do nothing, else delete user + echo -n "${username} : " + ${mastodonpath}/bin/tootctl accounts delete "${username}" + notifyUserDeletion + num_deleted=$((num_deleted+1)) + RND=$(date +%s) + sec=$(( $RND %60 )) + ms=$(( $RND %23 )) + sleep ${sec}.${ms} + done + ;; + *) + # find & notify users that didn't logged in >6 months and send mail to log in again#psql -U ${DB_USER} -w -h ${DB_HOST} -p ${DB_PORT} -t ${DB_NAME} -c "select concat(username||';'||email) from accounts a, users u where domain is null and a.id=u.account_id and current_sign_in_at is null and u.created_at < now()-'2 weeks'::interval" | tr -d " " + #for username in $(psql -U ${DB_USER} -w -h ${DB_HOST} -p ${DB_PORT} -t ${DB_NAME} -c "select a.id, username, email, current_sign_in_at from accounts a, users u where domain is null and a.id=u.account_id and current_sign_in_at <'2019-01-01'" ) + for line in $(psql -U ${DB_USER} -w -h ${DB_HOST} -p ${DB_PORT} -t ${DB_NAME} -c "select concat(username||','||email) from accounts a, users u where domain is null and a.id=u.account_id and current_sign_in_at is null and u.created_at < now()-'2 weeks'::interval and username not in (${sqlprotectedusers})"| tr -d " "); do + #echo ${line} + username=$(echo ${line} | cut -f1 -d"," ) + mail=$(echo ${line} | cut -f2 -d"," ) + # if username is a protected user do nothing, else delete user + if [ -n "${protectedusers}" ]; then + pcheck=0 + for s in $(echo ${protectedusers}) ; do + if [ "${s}" = "${username}" ]; then + pcheck=1 + fi + done + if [ ${pcheck} -eq 0 ]; then + echo "Delete unconfirmed user ${username}" + if [ "${mode}" = "hotrun" ]; then + ${mastodonpath}/bin/tootctl accounts delete "${username}" + elif [ "${mode}" = "dryrun" ]; then + echo "${username}: skipped because of dryrun." + fi + fi fi done - if [ ${pcheck} -eq 0 ]; then - echo "Delete unconfirmed user ${username}" - if [ "${mode}" = "hotrun" ]; then - ${mastodonpath}/bin/tootctl accounts delete "${username}" - elif [ "${mode}" = "dryrun" ]; then - echo "${username}: skipped because of dryrun." - fi - fi - fi -done + #for u in $( ${mastodonpath}/bin/console user list active -c 10000 | grep -v '.*---.*' | sed 's/|/;/g' | tr -s "\ " | sed 's/^;\ //g' | sed 's/\ ;\ /;/g' | sed 's/\ /_/g' | tail -n +2 | grep -i -v -E ${protected} ); do + for mode2 in $(echo "warn disable"); do + #echo "mode2: $mode2" + case ${mode2} in + "warn") + #echo "in warn" + SQLSTATE="current_sign_in_at between now()-'${UPPERLIMIT}'::interval and now()-'${LOWERLIMIT}'::interval" + ;; + "disable") + #echo "in disable" + SQLSTATE="current_sign_in_at < now()-'${UPPERLIMIT}'::interval" + ;; + #"delete") + # #echo "in delete" + # SQLSTATE="current_sign_in_at < now()-'${UPPERLIMIT}'::interval" + # ;; + esac + #echo "SQL: $SQLSTATE" + for u in $( psql -U ${DB_USER} -w -h ${DB_HOST} -p ${DB_PORT} -t ${DB_NAME} -c "select concat(username||';'||display_name||';'||email||';'||to_char(a.created_at, 'YYYY-MM-DD')||';'||to_char(current_sign_in_at,'YYYY-MM-DD')) from accounts a, users u where domain is null and a.id=u.account_id and ${SQLSTATE} and username not in ($sqlprotectedusers) order by current_sign_in_at" | tr -d " " ); do + #echo ${u} + username=$(echo "${u}" | awk -F ";" '{print $1}') + dispname=$(echo "${u}" | awk -F ";" '{print $2}') + profileurl="https://nerdculture.de/@${username}" + usermail=$(echo "${u}" | awk -F ";" '{print $3}') + registered=$(echo "${u}" | awk -F ";" '{print $4}') + lastlogin=$(echo "${u}" | awk -F ";" '{print $5}') + case ${mode2} in + "warn") + if [ "${mode}" = "hotrun" ]; then + #echo -n "hotrun " + notifyUser + elif [ "${mode}" = "dryrun" ]; then + echo "Check ${username}: notify skipped because of dryrun." + fi + num_notified=$((num_notified+1)) + ;; + "disable") + # delete account when last login is older than 7 months and send mail about deletion + # you should copy & paste the text from 6 months for the first runs of this script + # and later change the text to a notification that the account has been deleted. + # if username is a protected user do nothing, else delete user + echo -n "${username} : " + if [ "${mode}" = "hotrun" ]; then + #echo -n "hotrun " + #${mastodonpath}/bin/tootctl accounts delete "${username}" + ${mastodonpath}/bin/tootctl accounts modify "${username}" --disable + #notifyUserDeletion + notifyUserDisable + #echo "deleted." + elif [ "${mode}" = "dryrun" ]; then + echo "will be disabled, but is skipped because of dryrun." + fi + num_disabled=$((num_disabled+1)) + ;; + esac + RND=$(date +%s) + sec=$(( $RND %5 )) + ms=$(( $RND %23 )) + sleep ${sec}.${ms} + done + done + ;; +esac -# find & notify users that didn't logged in >6 months and send mail to log in again -for mode2 in $(echo "warn delete"); do - #echo "mode2: $mode2" - case ${mode2} in - "warn") - #echo "in warn" - SQLSTATE="last_sign_in_at between now()-'${UPPERLIMIT}'::interval and now()-'${LOWERLIMIT}'::interval" - ;; - "delete") - #echo "in delete" - SQLSTATE="last_sign_in_at < now()-'${UPPERLIMIT}'::interval" - ;; - esac - #echo "SQL: $SQLSTATE" - for u in $( psql -U ${DB_USER} -w -h ${DB_HOST} -p ${DB_PORT} -t ${DB_NAME} -c "select concat(username||';'||display_name||';'||email||';'||to_char(a.created_at, 'YYYY-MM-DD')||';'||to_char(last_sign_in_at,'YYYY-MM-DD')) from accounts a, users u where domain is null and a.id=u.account_id and ${SQLSTATE} and username not in ($sqlprotectedusers) order by last_sign_in_at" | tr -d " " ); do - #echo ${u} - username=$(echo "${u}" | awk -F ";" '{print $1}') - dispname=$(echo "${u}" | awk -F ";" '{print $2}') - profileurl="https://nerdculture.de/@${username}" - usermail=$(echo "${u}" | awk -F ";" '{print $3}') - registered=$(echo "${u}" | awk -F ";" '{print $4}') - lastlogin=$(echo "${u}" | awk -F ";" '{print $5}') - case ${mode2} in - "warn") - if [ "${mode}" = "hotrun" ]; then - #echo -n "hotrun " - notifyUser - elif [ "${mode}" = "dryrun" ]; then - echo "Check ${username}: notify skipped because of dryrun." - fi - ;; - "delete") - # delete account when last login is older than 7 months and send mail about deletion - # you should copy & paste the text from 6 months for the first runs of this script - # and later change the text to a notification that the account has been deleted. - # if username is a protected user do nothing, else delete user - echo -n "${username} : " - if [ "${mode}" = "hotrun" ]; then - #echo -n "hotrun " - ${mastodonpath}/bin/tootctl accounts delete "${username}" - notifyUserDeletion - #echo "deleted." - elif [ "${mode}" = "dryrun" ]; then - echo "skipped because of dryrun." - fi - ;; - esac - done -done +ENDDATE=$(date +"%d.%m.%Y %H:%M:%S") + + +echo "===================================" +echo "Starting time : ${STARTDATE}" +echo "Ending time : ${ENDDATE}" +echo "Notified Users: $num_notified" +echo "Disabled Users: $num_disabled" +echo "Deleted Users : $num_deleted" +echo "==================================="