#!/bin/sh set -f # create a default config when started with --init initConfig() { ( cat <6 months UPPERLIMIT="7 months" # inactive accounts older than 7 months will be deactivated DELDELIMIT="1 year" # all accounts not used within a year will get deleted LIVE_PATH="${HOME}/live/" # Path to live data from mastodon TOOTCTL="${HOME}/live/bin/tootctl" SITE="Mastodon" SITEADMIN="root@localhost" PROTECTEDUSERS="user foo bar baz" SQLPROTECTEDUSERS="'user', 'foo', 'bar', 'baz'" LIMIT_DELETE="2" EOF ) > "${HOME}"/.cleanup-mastodon-users.conf echo "✅ - Configuration file created. You can now edit "${HOME}"/.cleanup-mastodon-users.conf" } case $1 in "--init") initConfig exit 0 ;; "--dry-run") mode="dryrun" ;; "--cron") mode="cron" ;; "--dowhatimean") mode="hotrun" ;; *) echo "Usage: " echo " --init \t: create $0/.cleanup-mastodon-users.conf config file." echo " --dry-run \t: make a dry-run, no deletion will be done, no mails are sent." echo " --cron \t: delete deactivated users in a regularly cron run step by step to avoid mass flooding." echo " --dowhatimean \t: add this option if you really want to delete users." echo "" if [ ! -f "${HOME}"/.cleanup-mastodon-users.conf ]; then echo "❌ - No configuration file found!" echo "Please start with \"$0 --init\" to create config files" echo "and edit the file \"${HOME}/.cleanup-mastodon-users.conf\" to your needs." exit 0 fi exit 0 ;; esac . "${HOME}"/.cleanup-mastodon-users.conf LOWERLIMIT="${LOWERLIMIT:-'6 months'}" # all accounts below 6 months inactivity are safe, start notifiying them when >6 months UPPERLIMIT="${UPPERLIMIT:-'7 months'}" # inactive accounts older than 7 months will be deactivated DELDELIMIT="${DELDELIMIT:-'1 year'}" # all accounts not used within a year will get deleted LIVE_PATH="${LIVE_PATH:-${HOME}/live/}" # Path to live data from mastodon TOOTCTL="${TOOTCTL:-${HOME}/bin/tootctl}" SITE="${SITE:-$LOCAL_DOMAIN}" SITEADMIN="${SITEADMIN:-root@localhost}" LIMIT_DELETE="${LIMIT_DELETE:-2}" cd "${LIVE_PATH}" || exit # shellcheck source=/dev/null . "${LIVE_PATH}/.env.production" 2>/dev/null run_tootctl() { "${TOOTCTL}" "$@" } num_notified=0 num_disabled=0 num_deleted=0 STARTDATE=$(date +"%d.%m.%Y %H:%M:%S") # make a list to be used for grep -E PROTECTED=$(echo "$PROTECTEDUSERS" | sed 's/\"//g' | sed 's/\ /\\\|/g') #echo $PROTECTED # notify the user that s/he needs to re-login after 6 months to prevent account deletion notifyUser() { ( cat <${UPPERLIMIT}): ${num_deactivated_total}" echo "Over grace (${DELDELIMIT}): ${num_deactivated_overgrace}" echo "Deleting at once: ${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()-'${DELDELIMIT}'::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}') 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} : " run_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 disabled is false 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 ${PROTECTEDUSERS} ; do if [ "${s}" = "${username}" ]; then pcheck=1 fi done if [ ${pcheck} -eq 0 ]; then echo "Delete unconfirmed user ${username}" if [ "${mode}" = "hotrun" ]; then run_tootctl accounts delete "${username}" elif [ "${mode}" = "dryrun" ]; then echo "${username}: skipped because of dryrun." fi fi fi done #for u in $( ${LIVE_PATH}/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" SQLSTATE="current_sign_in_at between now()-'${UPPERLIMIT}'::interval and now()-'${UPPERLIMIT}'::interval-'1 week'::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 disabled is false 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}') 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 " #run_tootctl accounts delete "${username}" run_tootctl accounts modify "${username}" --disable #notifyUserDeletion notifyUserDisable #echo "deleted." elif [ "${mode}" = "dryrun" ]; then echo "will be deactivated, but is skipped because of dryrun." fi num_disabled=$((num_disabled+1)) exit ;; esac RND=$(date +%s) sec=$(( $RND %5 )) ms=$(( $RND %23 )) sleep ${sec}.${ms} done done num_deactivated_total=$(psql -U "${DB_USER}" -w -h "${DB_HOST}" -p "${DB_PORT}" -t "${DB_NAME}" -c "select count(username) from accounts a, users u where disabled is true and a.id=u.account_id and username not in ($SQLPROTECTEDUSERS)" | tr -d " " ) ;; esac ENDDATE=$(date +"%d.%m.%Y %H:%M:%S") echo "===================================" echo "Starting time : ${STARTDATE}" echo "Ending time : ${ENDDATE}" echo "Notified Users: $num_notified" echo "Deactivated : $num_disabled" echo "To be deleted : $num_deactivated_total" echo "==================================="