Files
cleanup-mastodon-users.sh/cleanup-mastodon-users.sh
T

272 lines
12 KiB
Bash
Raw Normal View History

2021-08-05 10:14:46 +02:00
#!/bin/sh
# LOWERLIMIT="'6 months'" or "'24 weeks'"
# UPPERLIMIT="'7 months'" or "'28 weeks'"
# this defines the range of inactivity where users get notified
# before the account will be deleted when UPPERLIMIT is surpassed.
2023-10-25 15:46:46 +02:00
readonly LOWERLIMIT="6 months" # all accounts below 6 months inactivity are safe, start notifiying them when >6 months
readonly UPPERLIMIT="7 months" # inactive accounts older than 7 months will be deactivated
readonly DELDELIMIT="1 year" # all accounts not used within a year will get deleted
readonly LIVE_PATH="${MASTO_PATH}" # Path to live data from mastodon
readonly TOOTCTL="bin/tootctl"
2021-08-05 10:14:46 +02:00
2023-10-25 15:46:46 +02:00
cd "${LIVE_PATH}" || exit
2021-08-05 10:14:46 +02:00
2023-10-25 15:46:46 +02:00
# shellcheck source=/dev/null
source "${LIVE_PATH}/.env.production"
2021-08-05 10:14:46 +02:00
2023-10-25 15:46:46 +02:00
run_tootctl() {
"${TOOTCTL}" "$@"
}
2023-08-17 19:25:27 +00:00
2023-10-25 15:46:46 +02:00
set -f
# set the following variables accordingly to your site
# the admin will get a notification mail in BCC
2021-08-05 10:14:46 +02:00
# the following lines should be moved to a config file, eg. /usr/local/etc/cleanup_friendica.conf
#DB_HOST=127.0.0.1
#DB_PORT=6432
#DB_NAME=mastodon
#DB_USER=mastodon
#DB_PASS=
2023-08-17 19:25:27 +00:00
site="Nerdculture.de"
2023-10-25 15:46:46 +02:00
#siteadmin="ij@bluespice.org"
2023-08-17 19:25:27 +00:00
protectedusers="ij kirschwipfel xmppcompliance order kirschwipfeltest"
sqlprotectedusers="'ij', 'kirschwipfel', 'xmppcompliance', 'order', 'kirschwipfeltest'"
limit_delete=2
num_notified=0
num_disabled=0
num_deleted=0
STARTDATE=$(date +"%d.%m.%Y %H:%M:%S")
2021-08-05 10:14:46 +02:00
case $1 in
"--dry-run")
mode="dryrun"
;;
2023-08-17 19:25:27 +00:00
"--cron")
mode="cron"
;;
2021-08-05 10:14:46 +02:00
"--dowhatimean")
mode="hotrun"
;;
*)
echo "Usage: "
echo " --dry-run \t: make a dry-run, no deletion will be done, no mails are sent."
2023-08-17 19:25:27 +00:00
echo " --cron \t: delete deactivated users in a regularly cron run step by step to avoid mass flooding."
2021-08-05 10:14:46 +02:00
echo " --dowhatimean \t: add this option if you really want to delete users."
exit 0
;;
esac
#. /usr/local/etc/cleanup_friendica.conf
2023-10-25 15:46:46 +02:00
# make a list to be used for grep -E
protected=$(echo "$protectedusers" | sed 's/\"//g' | sed 's/\ /\\\|/g')
#echo $protected
2021-08-05 10:14:46 +02:00
# notify the user that s/he needs to re-login after 6 months to prevent account deletion
2023-10-25 15:46:46 +02:00
notifyUser() {
(
cat <<EOF
Dear ${dispname},
2021-08-05 10:14:46 +02:00
2023-10-25 15:46:46 +02:00
you have registered your account on ${LOCAL_DOMAIN} at ${registered} and last time you logged in was at ${lastlogin}.
2021-08-05 10:14:46 +02:00
2023-10-25 15:46:46 +02:00
If you want to continue to keep your Mastodon account on Nerdculture then please log in at least every 6 months via web browser to keep your account alive. Otherwise we assume that you don't want to use it anymore and will deactivate your account 7 months after your last login (and delete it later).
2021-08-05 10:14:46 +02:00
2023-10-25 15:46:46 +02:00
You can access your profile at ${profileurl} or you can cancel your account on your own when logged in at ${LOCAL_DOMAIN}removeme - however we would like to see you become an active user again and contribute to the Fediverse, but of course it's up to you.
2021-08-05 10:14:46 +02:00
Sincerely,
your ${site} admins
2023-10-25 15:46:46 +02:00
2021-08-05 10:14:46 +02:00
EOF
2023-10-25 15:46:46 +02:00
) | sed 's/_/\ /g' | /usr/bin/mail -s "The Fediverse misses you, ${username}!" -r "${SMTP_FROM_ADDRESS}" -- "${usermail}"
# add '-b "$siteadmin"' before the "--" above to receive BCC mails
2023-08-17 19:25:27 +00:00
#((num_notified++))
}
# notify user that the account has been deleted because of inactivity
2023-10-25 15:46:46 +02:00
notifyUserDisable() {
(
cat <<EOF
Dear ${dispname},
2023-08-17 19:25:27 +00:00
2023-10-25 15:46:46 +02:00
you have registered your account on ${LOCAL_DOMAIN} at ${registered} and last time you logged in was at ${lastlogin}.
2023-08-17 19:25:27 +00:00
2023-10-25 15:46:46 +02:00
Since you haven't reacted to the previous mails and didn't login again, your account including all your data has now been deactivated and will be deleted at a (random) later time.
2023-08-17 19:25:27 +00:00
Sincerely,
your ${site} admins
2023-10-25 15:46:46 +02:00
2023-08-17 19:25:27 +00:00
EOF
2023-10-25 15:46:46 +02:00
) | sed 's/_/\ /g' | /usr/bin/mail -s "Your account ${username} on ${site} has been deleted!" -r "${SMTP_FROM_ADDRESS}" -- "${usermail}"
# add '-b "$siteadmin"' before the "--" above to receive BCC mails
2021-08-05 10:14:46 +02:00
}
# notify user that the account has been deleted because of inactivity
2023-10-25 15:46:46 +02:00
notifyUserDeletion() {
(
cat <<EOF
Dear ${dispname},
2021-08-05 10:14:46 +02:00
2023-10-25 15:46:46 +02:00
you have registered your account on ${LOCAL_DOMAIN} at ${registered} and last time you logged in was at ${lastlogin}.
2021-08-05 10:14:46 +02:00
2023-10-25 15:46:46 +02:00
Since you haven't reacted to the previous mails and didn't login again, your account including all your data has now been deleted.
2021-08-05 10:14:46 +02:00
Sincerely,
your ${site} admins
2023-10-25 15:46:46 +02:00
2021-08-05 10:14:46 +02:00
EOF
2023-10-25 15:46:46 +02:00
) | sed 's/_/\ /g' | /usr/bin/mail -s "Your account ${username} on ${site} has been deleted!" -r "${SMTP_FROM_ADDRESS}" -- "${usermail}"
# add '-b "$siteadmin"' before the "--" above to receive BCC mails
2021-08-05 10:14:46 +02:00
}
2023-08-17 19:25:27 +00:00
# delete users that never logged in and never posted content
2023-10-25 15:46:46 +02:00
# filtering for "weeks" will result in accounts with 2 weeks old accounts,
2023-08-17 19:25:27 +00:00
# filter for just "week" will do the same after 1 week.
# same should apply to "month" and "months", but untested.
2023-10-25 15:46:46 +02:00
#for username in $( "${TOOTCTL}" user list active -c 10000 | grep 'never.*never' | grep weeks | awk '{print $2}') ; do
2023-08-17 19:25:27 +00:00
# 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'
case ${mode} in
"cron")
2023-10-25 15:46:46 +02:00
# get the total number of deactivated accounts
2023-08-17 19:25:27 +00:00
# the intention is that you can better judge how often you need to invoke the cron option
# or by increasing the limit_delete variable
# the backlog queue shouldn't pile up but also not run empty to fast to reduce the load
2023-10-25 15:46:46 +02:00
num_deactivated_overgrace=$(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 current_sign_in_at < now()-'${DELDELIMIT}'::interval and username not in ($sqlprotectedusers)" | tr -d " " )
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 " " )
2023-08-17 19:25:27 +00:00
# when there is less then 1 user to delete (=0) then exit
2023-10-25 15:46:46 +02:00
if [ "${num_deactivated_overgrace}" -lt 1 ]; then
2023-08-17 19:25:27 +00:00
exit 0
2021-08-05 10:14:46 +02:00
fi
2023-08-17 19:25:27 +00:00
echo "==================================="
2023-08-20 17:11:49 +00:00
echo "Total deactivated accounts: ${num_deactivated_total}"
echo "Number deactivated accounts over grace: ${num_deactivated_overgrace}"
2023-08-17 19:25:27 +00:00
echo "Deleting this many accounts: ${limit_delete}"
echo "==================================="
2023-10-25 15:46:46 +02:00
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
2023-08-17 19:25:27 +00:00
#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
2023-10-25 15:46:46 +02:00
# and later change the text to a notification that the account has been deleted.
2023-08-17 19:25:27 +00:00
# if username is a protected user do nothing, else delete user
echo -n "${username} : "
2023-10-25 15:46:46 +02:00
run_tootctl accounts delete "${username}"
2023-08-17 19:25:27 +00:00
notifyUserDeletion
num_deleted=$((num_deleted+1))
RND=$(date +%s)
sec=$(( $RND %60 ))
ms=$(( $RND %23 ))
2023-10-25 15:46:46 +02:00
sleep ${sec}.${ms}
2023-08-17 19:25:27 +00:00
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'" )
2023-10-25 15:46:46 +02:00
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
2023-08-17 19:25:27 +00:00
#echo ${line}
2023-10-25 15:46:46 +02:00
username=$(echo "${line}" | cut -f1 -d"," )
mail=$(echo "${line}" | cut -f2 -d"," )
2023-08-17 19:25:27 +00:00
# if username is a protected user do nothing, else delete user
if [ -n "${protectedusers}" ]; then
pcheck=0
2023-10-25 15:46:46 +02:00
for s in ${protectedusers} ; do
2023-08-17 19:25:27 +00:00
if [ "${s}" = "${username}" ]; then
pcheck=1
fi
done
if [ ${pcheck} -eq 0 ]; then
echo "Delete unconfirmed user ${username}"
if [ "${mode}" = "hotrun" ]; then
2023-10-25 15:46:46 +02:00
run_tootctl accounts delete "${username}"
2023-08-17 19:25:27 +00:00
elif [ "${mode}" = "dryrun" ]; then
echo "${username}: skipped because of dryrun."
fi
2021-08-05 10:14:46 +02:00
fi
2023-08-17 19:25:27 +00:00
fi
done
2023-10-25 15:46:46 +02:00
#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
2023-08-17 19:25:27 +00:00
for mode2 in $(echo "warn disable"); do
#echo "mode2: $mode2"
case ${mode2} in
"warn")
#echo "in warn"
2023-10-25 15:46:46 +02:00
SQLSTATE="current_sign_in_at between now()-'${UPPERLIMIT}'::interval and now()-'${LOWERLIMIT}'::interval"
2023-08-17 19:25:27 +00:00
;;
"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"
2023-10-25 15:46:46 +02:00
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
2023-08-17 19:25:27 +00:00
#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
2023-10-25 15:46:46 +02:00
# and later change the text to a notification that the account has been deleted.
2023-08-17 19:25:27 +00:00
# if username is a protected user do nothing, else delete user
echo -n "${username} : "
if [ "${mode}" = "hotrun" ]; then
#echo -n "hotrun "
2023-10-25 15:46:46 +02:00
#run_tootctl accounts delete "${username}"
run_tootctl accounts modify "${username}" --disable
2023-08-17 19:25:27 +00:00
#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
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 "==================================="