from datetime import date from io import BytesIO from urllib.error import HTTPError from urllib.request import urlopen from django.conf import settings from django.core.files import File from django.core.management.base import BaseCommand from fiches.models import Profile from ._ldap import AnnuaireLDAP class Command(BaseCommand): help = "Si possible, import les photos des conscrit·e·s dans l'annuaire." def add_arguments(self, parser): group = parser.add_mutually_exclusive_group() group.add_argument( "--all", action="store_true", help="Importe l'intégralité des promotions" ) group.add_argument("--promo", type=int, help="Spécifie la promotion à importer") def get_current_promo(self): today = date.today() year = today.year if today.month < 9: year -= 1 return year def handle(self, *args, **options): if options["all"]: promo = None elif options["promo"] is not None: promo = options["promo"] if promo < 100: promo = 2000 + promo else: promo = self.get_current_promo() verbosity = options["verbosity"] no_images = Profile.objects.select_related("user").filter(picture="") if promo is not None: no_images = no_images.filter(promotion=promo) cri_ldap = AnnuaireLDAP() base_annuaire = "{PROTOCOL}://{URL}:{PORT}".format(**settings.ANNUAIRE) success = 0 for profile in no_images: cri_login = cri_ldap.try_match( profile, verbosity=verbosity, stderr=self.stderr ) if cri_login is not None: img_url = "{}/photos/{}.jpg".format(base_annuaire, cri_login) try: istream = urlopen(img_url) profile.picture.save( name="{}.jpg".format(profile.user.username), content=File(BytesIO(istream.read())), ) success += 1 if verbosity == 3: self.stdout.write( "Photo trouvée pour {} ({})".format( profile.user.username, profile.promotion ) ) except HTTPError: # Parfois, même si on trouve un login CRI, il y a une erreur 404. # Dans ce cas, pas de photo : on échoue gracieusement. if verbosity >= 2: self.stdout.write( "Login CRI trouvé mais pas de photo pour {} ({})".format( profile.user.username, profile.promotion ) ) pass elif verbosity >= 2: self.stdout.write( "Pas de login CRI trouvé pour {} ({})".format( profile.user.username, profile.promotion ) ) if verbosity >= 1: self.stdout.write( "{} profils traités ; {} images importées.".format( no_images.count(), success ) )