2020-01-03 07:38:36 +01:00
#!/usr/bin/env python3
# coding: utf-8
# -*- coding: utf-8 -*-
# A Fediverse (decentralized social network, for instance using Mastodon) bot
from mastodon import StreamListener
from logging . handlers import RotatingFileHandler
from pprint import pprint
from utils . config import get_parameter , init_log , init_mastodon
2020-01-03 12:00:55 +01:00
from datetime import datetime , timezone , timedelta
2020-01-03 07:38:36 +01:00
2020-01-03 12:00:55 +01:00
import requests , os , sys , time , json , logging , argparse , re , smtplib , array
2020-01-03 07:38:36 +01:00
config_file = " config.txt "
secrets_filepath = get_parameter ( " secrets_filepath " , config_file )
log_filepath = get_parameter ( " log_filepath " , config_file )
log = init_log ( log_filepath )
mastodon = init_mastodon ( config_file , secrets_filepath )
2020-01-03 13:20:34 +01:00
email = {
' host ' : get_parameter ( ' email_host ' , config_file ) ,
' port ' : get_parameter ( ' email_port ' , config_file ) ,
' from ' : get_parameter ( ' email_from ' , config_file ) ,
' fromname ' : get_parameter ( ' email_fromname ' , config_file ) ,
' username ' : get_parameter ( ' email_username ' , config_file ) ,
' password ' : get_parameter ( ' email_password ' , config_file ) ,
' encryption ' : get_parameter ( ' email_encryption ' , config_file )
}
2020-01-03 12:00:55 +01:00
class bcolors :
HEADER = ' \033 [95m '
OKBLUE = ' \033 [94m '
OKGREEN = ' \033 [92m '
WARNING = ' \033 [93m '
FAIL = ' \033 [91m '
ENDC = ' \033 [0m '
BOLD = ' \033 [1m '
UNDERLINE = ' \033 [4m '
def list_accounts ( days ) :
users_count = mastodon . instance ( ) [ ' stats ' ] [ ' user_count ' ]
mastodon_accounts = mastodon . admin_accounts ( remote = False , status = ' active ' , limit = users_count )
for account in mastodon_accounts :
uid = account [ ' id ' ]
username = account [ ' username ' ]
email = account [ ' email ' ]
if account [ ' account ' ] [ ' last_status_at ' ] == None :
last_activity = account [ ' account ' ] [ ' created_at ' ]
else :
last_activity = account [ ' account ' ] [ ' last_status_at ' ]
today = datetime . now ( timezone . utc )
if today - last_activity > timedelta ( int ( days ) ) :
log . info ( " User " + username + " https://miaou.drycat.fr/admin/accounts/ " + str ( uid ) + " will be delete " )
def alert_accounts ( days ) :
users_count = mastodon . instance ( ) [ ' stats ' ] [ ' user_count ' ]
mastodon_accounts = mastodon . admin_accounts ( remote = False , status = ' active ' , limit = users_count )
for account in mastodon_accounts :
uid = account [ ' id ' ]
username = account [ ' username ' ]
mail = account [ ' email ' ]
if account [ ' account ' ] [ ' last_status_at ' ] == None :
last_activity = account [ ' account ' ] [ ' created_at ' ]
else :
last_activity = account [ ' account ' ] [ ' last_status_at ' ]
today = datetime . now ( timezone . utc )
if today - last_activity > timedelta ( int ( days ) ) :
log . info ( " User " + username + " https://miaou.drycat.fr/admin/accounts/ " + str ( uid ) + " will be delete " )
2020-01-03 13:20:34 +01:00
sender = email [ ' from ' ]
2020-01-03 12:00:55 +01:00
receivers = [ ' ' + mail + ' ' ]
2020-01-03 13:20:34 +01:00
message = """ From: """ + email [ ' fromname ' ] + """ < """ + email [ ' from ' ] + """ >
2020-01-03 12:00:55 +01:00
To : """ +username+ """ < """ +mail+ """ >
2020-01-03 13:45:14 +01:00
Subject : Your account has been inactive for more than """ +days+ """ days
2020-01-03 12:00:55 +01:00
- - - -
English message bellow .
- - - -
Bonjour
2020-01-03 13:45:14 +01:00
Votre compte est inactif depuis plus de """ +days+ """ jours .
2020-01-03 12:00:55 +01:00
Si vous ne souhaitez pas conserver ce compte sur l ' instance Mastodon miaou.drycat.fr, oubliez ce mail.
Sinon , connectez vous et par messure de sécurité , envoyez un message privée à vous même .
Sans action de votre part , votre compte sera clôturé sous 7 jours .
Cordialement
2020-01-03 13:20:34 +01:00
L ' équipe d ' administration de """ +email[ ' fromname ' ]+ """ .
2020-01-03 12:00:55 +01:00
- - - - - - - -
Hello
2020-01-03 13:45:14 +01:00
Your account has been inactive for more than """ +days+ """ days .
2020-01-03 12:00:55 +01:00
If you do not wish to keep this account on the instance Mastodon miaou . drycat . fr , forget this mail .
Otherwise , log in and by security measure , send a private message to yourself .
Without action on your part , your account will be closed within 7 days .
Cordially
2020-01-03 13:20:52 +01:00
The """ +email[ ' fromname ' ]+ """ ' s administration team.
2020-01-03 12:00:55 +01:00
"""
try :
2020-01-03 13:20:34 +01:00
smtpObj = smtplib . SMTP ( email [ ' host ' ] , email [ ' port ' ] )
smtpObj . ehlo ( )
if email [ ' encryption ' ] == " SSL " :
smtpObj . ssl ( )
elif email [ ' encryption ' ] == " STARTTLS " :
smtpObj . starttls ( )
else :
log . warning ( " No encryption select. It ' s dangerous " )
smtpObj . login ( email [ ' username ' ] , email [ ' password ' ] )
2020-01-03 12:00:55 +01:00
smtpObj . sendmail ( sender , receivers , message . replace ( " \xe9 " , " " ) . encode ( " ascii " , errors = " ignore " ) )
log . info ( " Successfully sent email " )
except smtplib . SMTPException as e :
log . debug ( e )
log . error ( " Error: unable to send email " )
2020-01-03 13:45:14 +01:00
def drop_accounts ( days ) :
users_count = mastodon . instance ( ) [ ' stats ' ] [ ' user_count ' ]
mastodon_accounts = mastodon . admin_accounts ( remote = False , status = ' active ' , limit = users_count )
for account in mastodon_accounts :
uid = account [ ' id ' ]
username = account [ ' username ' ]
mail = account [ ' email ' ]
if account [ ' account ' ] [ ' last_status_at ' ] == None :
last_activity = account [ ' account ' ] [ ' created_at ' ]
else :
last_activity = account [ ' account ' ] [ ' last_status_at ' ]
today = datetime . now ( timezone . utc )
if today - last_activity > timedelta ( int ( days ) ) :
log . info ( " User " + username + " https://miaou.drycat.fr/admin/accounts/ " + str ( uid ) + " is deleted " )
mastodon . admin_account_moderate ( uid , action = " suspend " , report_id = None , warning_preset_id = None , text = " Autodeleting old account " , send_email_notification = False )
sender = email [ ' from ' ]
receivers = [ ' ' + mail + ' ' ]
message = """ From: """ + email [ ' fromname ' ] + """ < """ + email [ ' from ' ] + """ >
To : """ +username+ """ < """ +mail+ """ >
Subject : Your account has been deleted
- - - -
English message bellow .
- - - -
Bonjour
Votre compte est inactif depuis plus de """ +days+ """ jours .
Vous n ' avez pas donné suite à notre mail d ' hier .
Nous avons donc clôturé votre compte .
Cordialement
L ' équipe d ' administration de """ +email[ ' fromname ' ]+ """ .
- - - - - - - -
Hello
Your account has been inactive for more than """ +days+ """ days .
You did not respond to our email yesterday .
We have therefore closed your account .
Without action on your part , your account will be closed within 7 days .
Cordially
The """ +email[ ' fromname ' ]+ """ ' s administration team.
"""
try :
smtpObj = smtplib . SMTP ( email [ ' host ' ] , email [ ' port ' ] )
smtpObj . ehlo ( )
if email [ ' encryption ' ] == " SSL " :
smtpObj . ssl ( )
elif email [ ' encryption ' ] == " STARTTLS " :
smtpObj . starttls ( )
else :
log . warning ( " No encryption select. It ' s dangerous " )
smtpObj . login ( email [ ' username ' ] , email [ ' password ' ] )
smtpObj . sendmail ( sender , receivers , message . replace ( " \xe9 " , " " ) . encode ( " ascii " , errors = " ignore " ) )
log . info ( " Successfully sent email " )
except smtplib . SMTPException as e :
log . debug ( e )
log . error ( " Error: unable to send email " )
2020-01-03 12:00:55 +01:00
def main ( ) :
parser = argparse . ArgumentParser ( description = ' Choose between alert, list or drop old accounts ' )
parser . add_argument ( " -a " , " --alert " , action = ' store_true ' , help = " Alert account by email " )
parser . add_argument ( " -l " , " --list " , action = ' store_true ' , help = " Only list old accounts (dry run mode) " )
parser . add_argument ( " -d " , " --drop " , action = ' store_true ' , help = " Drop old accounts " )
2020-01-03 13:45:14 +01:00
parser . add_argument ( " --forceyes " , action = ' store_true ' , help = " Accept dropping old accounts " )
2020-01-03 12:00:55 +01:00
parser . add_argument ( " --days " , help = " Number of days to keep account " )
args = parser . parse_args ( )
if args . list :
list_accounts ( args . days )
elif args . alert :
alert_accounts ( args . days )
elif args . drop :
2020-01-03 13:45:14 +01:00
if args . forceyes :
drop_accounts
else :
print ( " Please use --forceyes to confirm dropping accounts " )
2020-01-03 12:00:55 +01:00
else :
print ( " Require an argument. Use --help to display help " )
main ( )