Code source de negatifs

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Codé par Skippy

""" Destiné à être appelé par cron pour spammer les gens en négatif
    et prévenir les respo-info.
    Adapté des scripts de mails de négatifs de la NK2012 """

import sys
import mail
import argparse

sys.path.append("../config")
import config

[docs]def required_year(cur): """Calcule l'année d'adhésion qu'on spamme par défaut à partir de la date actuelle.""" # On prend l'année précédente de la date en cours, on appelle la procédure qui donne début/fin # Si on est avant la fin de l'année précédente, il faut être adhérent pour l'année en cours - 1 req = """SELECT CAST(EXTRACT('year' from now()) AS int) - CAST(now() < fin AS int) AS required_year FROM start_end_year(CAST(EXTRACT('year' from now()) AS int) - 1);""" cur.execute(req) annee = cur.fetchone()["required_year"] return annee
[docs]def ramassage(cur, negatif, annee, noclub, quiet=True): """Récupère les données pertinentes dans la BDD.""" where_additionnal_clause = "" if noclub: where_additionnal_clause += "AND type='personne' " klubdge = "" if not annee: annee = [required_year(cur)] if not noclub: # On vérifie les années, donc comme les clubs ne réadhèrent pas, il faut les compter # spécifiquement si on n'est pas dans le cas où on les ignore klubdge = "type='club' OR " where_additionnal_clause += "AND (%s" % klubdge +" OR".join([" adhesions.annee=%s" % a for a in annee]) + ") " join_additionnal_clause = "INNER JOIN adhesions ON comptes.idbde=adhesions.idbde " req = """SELECT DISTINCT comptes.idbde, nom, prenom, pseudo, mail, solde, date_trunc('day', NOW() - last_negatif) AS duree FROM comptes %s WHERE NOT type = 'special' AND solde < %s %s ORDER BY solde;""" % (join_additionnal_clause, negatif, where_additionnal_clause) if not quiet: print req.encode("utf-8") cur.execute(req) l = cur.fetchall() # On décode, parce que la base nous fournit des str for result in l: for (k, v) in result.items(): if (type(v) == str): result[k] = v.decode("utf-8") return l
[docs]def affiche(l): """Pretty print de la liste""" if not l: return u"" out = u"" # On formate le solde et la date l = [dict(i) for i in l] for result in l: # solde result[u"solde€"] = unicode(result["solde"] / 100.) # durée de négatif duree = unicode(result["duree"]).split(',')[0] if duree == "None": duree = 'NK2012' if duree == '0:00:00': duree = '<1 day' result["duree"] = duree columns = [ u"nom", u"prenom", u"pseudo", u"mail", u"solde€", u"duree"] column_names = { u"nom" : u"Nom", u"prenom" : u"Prénom", u"pseudo" : u"Pseudo", u"mail" : u"Email", u"solde€" : u"Solde", u"duree" : u"Durée"} # On évalue quelles sont les tailles des colonnes nécessaires maxs = {col : max(len(column_names[col]), max([len(resultat[col]) for resultat in l])) for col in columns} # On affiche heads = ["%s%s%s" % (u" " * ((maxs[col] - len(column_names[col]))/2), column_names[col], u" " * ((maxs[col] - len(column_names[col]) + 1)/2)) for col in columns] title = u" " + u" | ".join(heads) # Le +2 correspond aux espaces de début et de fin de colonne separator = u"+".join([u"-" * (maxs[col] + 2) for col in columns]) out += title + u"\n" + separator + u"\n" for fields in l:#for nom, pnom, pseudo, mail, solde, duree in l: line = u" " + u" | ".join([fields[col] + u" " * (maxs[col] - len(fields[col])) for col in columns]) + u" " out += line + "\n" out += "\n-- \nLe script negatifs.py\n" return out
if __name__=="__main__": parser = argparse.ArgumentParser() parser.add_argument("--solde-lim", metavar='N', type=float, dest="sl", default=None, help=u"Selectionner les adhérents de solde inferieur à N €, nécessite --mail") parser.add_argument("--quiet", action="store_true", default=False, help=u"N'affiche plus la liste et la requête dans le terminal") parser.add_argument("--mail", action="store_true", default=False, help=u"Mail la liste des adhérents en négatif") parser.add_argument("--test", action="store_true", default=False, help=u"A le même comportement mais comme si il n'y avait que le compte de Toto, et à -9000 (et le mail des respo-info)") parser.add_argument("--spam", action="store_true", default=False, help=u"Envoie un mail aux adhérents en dessous de solde_tres_negatif comme défini dans la bdd") parser.add_argument("--msg", type=argparse.FileType('r'), help=u"Fichier contenant un message custom à ajouter au début du mail de spam.") parser.add_argument("--annee", action="append", type=int, default=[], help=u"Filtre sur une liste d'années d'adhésions") parser.add_argument("--noclub", action="store_true", default=False, help=u"Ignore les clubs") parser.add_argument("--subject", default=None, help=u"Si précisé, remplace le sujet du mail de spam.") parser.add_argument("--sender", default=config.mails_from, help=u"Si précisé, modifie le champ From du mail envoyé.") options = parser.parse_args() msg = "" if options.msg: msg = options.msg.read().decode("utf-8") con, cur = mail.getcursor(config.database) if options.sl is None: cur.execute("SELECT solde_tres_negatif FROM configurations WHERE used;") negatif = cur.fetchone()["solde_tres_negatif"] else: negatif = int(options.sl * 100) if options.test: people = [{"idbde" : 42, "nom" : u"Toto", "prenom" : u"Écumoir", "pseudo" : u"toto", "solde" : -900000, "mail" : config.ml_respo_info, "duree" : "9999 days, 0:00:00"}] else: people = ramassage(cur, negatif, options.annee, options.noclub, options.quiet) liste = affiche(people) if liste: if not options.quiet: print liste.encode("utf-8") if options.mail: mail.queue_mail(options.sender, [config.ml_tresoriers, config.ml_respo_info], u"Liste des négatifs", liste) if options.spam: for compte in people: mail.mail_negatif(options.sender, compte, custom_message=msg, custom_subject=options.subject)