annuaire-eleves/fiches/management/commands/get_photos.py

96 lines
3.3 KiB
Python

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, importe 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
)
)