Compare commits

..

3 Commits

Author SHA1 Message Date
ij
daf3cdff94 Minor changes and corrections
Rewording of "deactivated" instead of "disabled", replacement of $profileurl and some changes to the stats output. Additionally some hints in the mail texts about notifiying by mail.

Signed-off-by: ij <ij@noreply.codeberg.org>
2023-12-13 20:05:13 +00:00
ij
c31c0ab0e5 reflect recent changes in options 2023-11-18 20:24:12 +00:00
ij
c3bd7d2d5f Some more changes, added subroutine to create config 2023-11-18 21:18:16 +01:00
2 changed files with 78 additions and 60 deletions

View File

@@ -8,6 +8,7 @@ The script does two things:
# Installation
* save the script in home directory of Mastodon (eg. ~/bin, not under /root, maybe /usr/local/bin)
* make the script executable (e.g. `chown mastodon:mastodon bin/cleanup-mastodon-users.sh && chmod u+rx bin/cleanup-mastodon-users.sh)`
* create a config file at `$HOME/.cleanup-mastodon-users.conf` by calling the script with `--init` argument and edit the file to fit your needs
* create a crontab to execute the script, e.g.: `20 8 * * 4 /home/mastodon/bin/cleanup-mastodon-users.sh --dowhatimean` to execute the script every week. In the example it is executed every Thursday (4th day of week) at 8:20 in the morning.
* for the first runs you should set `UPPERLIMIT` to a high number and keep the deleting of the user commented out (`${mastodonpath}/bin/tootctl accounts delete "${username}"`). After the first few runs you can reduce `UPPERLIMIT` to a lower setting and repeat this until you reached the final value. You shouldn't have too many weeks between `LOWERLIMIT` and `UPPERLIMIT`. Sensible values might be 6 and 7 months or 12 and 13 months or so.
* change the variables at the begin of the script to your site settings.
@@ -15,6 +16,7 @@ The script does two things:
# Usage
```
Usage:
--init : create bin/cleanup-mastodon-users.sh/.cleanup-mastodon-users.conf config file.
--dry-run : make a dry-run, no deletion will be done, no mails are sent.
--cron : delete deactivated users in a regularly cron run step by step to avoid mass flooding.
--dowhatimean : add this option if you really want to delete users.

View File

@@ -2,9 +2,8 @@
set -f
if [ -f ${HOME}/.cleanup-mastodon-users.conf ]; then
. ${HOME}/.cleanup-mastodon-users.conf
else
# create a default config when started with --init
initConfig() {
(
cat <<EOF
LOWERLIMIT="6 months" # all accounts below 6 months inactivity are safe, start notifiying them when >6 months
@@ -19,25 +18,59 @@ SQLPROTECTEDUSERS="'user', 'foo', 'bar', 'baz'"
LIMIT_DELETE="2"
EOF
) > ${HOME}/.cleanup-mastodon-users.conf
sleep 1
. ${HOME}/.cleanup-mastodon-users.conf
fi
) > "${HOME}"/.cleanup-mastodon-users.conf
echo "✅ - Configuration file created. You can now edit "${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}"
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
source "${LIVE_PATH}/.env.production"
. "${LIVE_PATH}/.env.production" 2>/dev/null
run_tootctl() {
"${TOOTCTL}" "$@"
@@ -50,29 +83,11 @@ num_deleted=0
STARTDATE=$(date +"%d.%m.%Y %H:%M:%S")
case $1 in
"--dry-run")
mode="dryrun"
;;
"--cron")
mode="cron"
;;
"--dowhatimean")
mode="hotrun"
;;
*)
echo "Usage: "
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."
exit 0
;;
esac
# 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() {
(
@@ -83,7 +98,7 @@ you have registered your account on ${LOCAL_DOMAIN} at ${registered} and last ti
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).
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.
You can access your profile at https://${LOCAL_DOMAIN}/@${username} or you can cancel your account on your own when logged in at https://${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.
Sincerely,
your ${SITE} admins
@@ -91,7 +106,6 @@ your ${SITE} admins
EOF
) | 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
#((num_notified++))
}
# notify user that the account has been deleted because of inactivity
@@ -102,13 +116,15 @@ Dear ${dispname},
you have registered your account on ${LOCAL_DOMAIN} at ${registered} and last time you logged in was at ${lastlogin}.
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.
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 (after ${DELDELIMIT}). Until then you can still request reactivattion from the admins. See ${LOCAL_DOMAIN}/about for contact information.
You will just receive the final confirmation mail of account deletion and no further mails!
Sincerely,
your ${SITE} admins
EOF
) | sed 's/_/\ /g' | /usr/bin/mail -s "Your account ${username} on ${SITE} has been deleted!" -r "${SMTP_FROM_ADDRESS}" -- "${usermail}"
) | sed 's/_/\ /g' | /usr/bin/mail -s "Your account ${username} on ${SITE} has been deactivated!" -r "${SMTP_FROM_ADDRESS}" -- "${usermail}"
# add '-b "$SITEADMIN"' before the "--" above to receive BCC mails
}
@@ -122,6 +138,8 @@ you have registered your account on ${LOCAL_DOMAIN} at ${registered} and last ti
Since you haven't reacted to the previous mails and didn't login again, your account including all your data has now been deleted.
This is the last and final mail about your account on ${LOCAL_DOMAIN}
Sincerely,
your ${SITE} admins
@@ -130,19 +148,15 @@ EOF
# add '-b "$SITEADMIN"' before the "--" above to receive BCC mails
}
# delete users that never logged in and never posted content
# filtering for "weeks" will result in accounts with 2 weeks old accounts,
# filter for just "week" will do the same after 1 week.
# same should apply to "month" and "months", but untested.
#for username in $( "${TOOTCTL}" user list active -c 10000 | grep 'never.*never' | grep weeks | awk '{print $2}') ; do
# 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'
# main loop
case ${mode} in
"init")
initConfig
;;
"cron")
# get the total number of deactivated accounts
# the intention is that you can better judge how often you need to invoke the cron option
# or by increasing the limit_delete variable
# 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
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 " " )
@@ -151,15 +165,15 @@ case ${mode} in
exit 0
fi
echo "==================================="
echo "Total deactivated accounts: ${num_deactivated_total}"
echo "Number deactivated accounts over grace: ${num_deactivated_overgrace}"
echo "Deleting this many accounts: ${limit_delete}"
echo "Account summary:"
echo "Total deactivated (>${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
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}')
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}')
@@ -180,7 +194,7 @@ case ${mode} in
*)
# 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
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"," )
@@ -212,7 +226,8 @@ case ${mode} in
;;
"disable")
#echo "in disable"
SQLSTATE="current_sign_in_at < now()-'${UPPERLIMIT}'::interval"
#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"
@@ -220,11 +235,10 @@ case ${mode} in
# ;;
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
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}')
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}')
@@ -252,9 +266,10 @@ case ${mode} in
notifyUserDisable
#echo "deleted."
elif [ "${mode}" = "dryrun" ]; then
echo "will be disabled, but is skipped because of dryrun."
echo "will be deactivated, but is skipped because of dryrun."
fi
num_disabled=$((num_disabled+1))
exit
;;
esac
RND=$(date +%s)
@@ -263,6 +278,7 @@ case ${mode} in
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
@@ -272,6 +288,6 @@ 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 "Deactivated : $num_disabled"
echo "To be deleted : $num_deactivated_total"
echo "==================================="