mirror of
				https://gitlab.crans.org/bde/nk20-scripts
				synced 2025-10-30 06:49:50 +01:00 
			
		
		
		
	✨ Export activities in the Crans Wiki
This commit is contained in:
		| @@ -63,6 +63,7 @@ class Command(ImportCommand): | |||||||
|                 "pk": pk_activity, |                 "pk": pk_activity, | ||||||
|                 "name": row["titre"], |                 "name": row["titre"], | ||||||
|                 "description": row["description"], |                 "description": row["description"], | ||||||
|  |                 "location": row["lieu"], | ||||||
|                 "activity_type_id": activity_type_id,  # By default Pot |                 "activity_type_id": activity_type_id,  # By default Pot | ||||||
|                 "creater_id": NoteUser.objects.get(pk=note).user.id, |                 "creater_id": NoteUser.objects.get(pk=note).user.id, | ||||||
|                 "organizer_id": organizer.pk, |                 "organizer_id": organizer.pk, | ||||||
|   | |||||||
							
								
								
									
										182
									
								
								management/commands/refresh_activities.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								management/commands/refresh_activities.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,182 @@ | |||||||
|  | # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay | ||||||
|  | # SPDX-License-Identifier: GPL-3.0-or-later | ||||||
|  |  | ||||||
|  | import os | ||||||
|  | from bs4 import BeautifulSoup | ||||||
|  | from django.core.management import BaseCommand | ||||||
|  | from django.urls import reverse | ||||||
|  | from django.utils import timezone | ||||||
|  | from urllib.parse import urlencode | ||||||
|  | from urllib.request import Request, urlopen | ||||||
|  |  | ||||||
|  | from activity.models import Activity | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Command(BaseCommand): | ||||||
|  |     acl_header = "#acl NoteKfet2015:read,write,admin NoteKfet2020:read,write,admin All:read Default\n" | ||||||
|  |  | ||||||
|  |     warning_header = """## NE PAS ÉDITER CETTE PAGE MANUELLEMENT | ||||||
|  | ## ELLE EST GÉNÉRÉE AUTOMATIQUEMENT PAR LA NOTE KFET 2020 | ||||||
|  | ## Adapté par [[WikiYnerant|ÿnérant]] du script de by 20-100, largement inspiré de la version de Barbichu. | ||||||
|  | """ | ||||||
|  |  | ||||||
|  |     intro_generic = """ * Elle est générée automatiquement par la [[NoteKfet/NoteKfet2020|Note Kfet 2020]] | ||||||
|  |  * Ne pas éditer cette page manuellement, toute modification sera annulée automatiquement. | ||||||
|  |  * Pour annoncer un nouvel événement, rendez-vous sur {activities_url} | ||||||
|  |  | ||||||
|  | """.format(activities_url="https://" + os.getenv("NOTE_URL") + reverse("activity:activity_list")) | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def connection(url): | ||||||
|  |         """Se logue sur le wiki et renvoie le cookie de session""" | ||||||
|  |         parameters = { | ||||||
|  |             'action': 'login', | ||||||
|  |             'login': 'Connexion', | ||||||
|  |             'name': os.getenv("WIKI_USER", "NoteKfet2020"), | ||||||
|  |             'password': os.getenv("WIKI_PASSWORD"), | ||||||
|  |         } | ||||||
|  |         # Il faut encoder ça proprement | ||||||
|  |         data = urlencode(parameters).encode("utf-8") | ||||||
|  |         request = Request(url, data) | ||||||
|  |         # La requête est envoyée en HTTP POST | ||||||
|  |         response = urlopen(request) | ||||||
|  |         # a priori la page elle-même je m'en carre… | ||||||
|  |         response.read(2) | ||||||
|  |         # …ce qui m'intéresse, c'est le cookie qu'elle me file | ||||||
|  |         cookie = response.headers['set-cookie'] | ||||||
|  |         return cookie | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def get_edition_ticket(url, cookie): | ||||||
|  |         """Récupère le ticket d'édition de la page""" | ||||||
|  |         # On crée la requête d'édition… | ||||||
|  |         suffix = "?action=edit&editor=text" | ||||||
|  |         request = Request(url + suffix) | ||||||
|  |         # …avec le cookie | ||||||
|  |         request.add_header("Cookie", cookie) | ||||||
|  |         # On l'envoie | ||||||
|  |         pagecontent = urlopen(request) | ||||||
|  |         html = pagecontent.read() | ||||||
|  |         soup = BeautifulSoup(html, features="lxml") | ||||||
|  |         # On va chercher le formulaire | ||||||
|  |         form = soup.find(name="form", attrs={"id": "editor"}) | ||||||
|  |         # On récupère le ticket dedans | ||||||
|  |         ticket = soup.find(name="input", attrs={"name": "ticket"}) | ||||||
|  |         return ticket["value"] | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def edit_wiki(page, content, comment=''): | ||||||
|  |         """Modifie une page du wiki""" | ||||||
|  |         url = "https://wiki.crans.org/" + page | ||||||
|  |  | ||||||
|  |         # On se connecte et on récupère le cookie de session | ||||||
|  |         cookie = Command.connection(url) | ||||||
|  |         # On demande l'édition et on récupère le ticket d'édition de la page | ||||||
|  |         ticket = Command.get_edition_ticket(url, cookie) | ||||||
|  |         # On construit la requête | ||||||
|  |         data = { | ||||||
|  |             'button_save': 'Enregistrer les modifications', | ||||||
|  |             'category': '', | ||||||
|  |             'comment': comment.encode("utf-8"), | ||||||
|  |             'savetext': content.encode("utf-8"), | ||||||
|  |             'action': 'edit', | ||||||
|  |             'ticket': ticket | ||||||
|  |         } | ||||||
|  |         request = Request(url, urlencode(data).encode("utf-8")) | ||||||
|  |         request.add_header("Cookie", cookie) | ||||||
|  |         # On la poste | ||||||
|  |         urlopen(request) | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def format_activity(act, raw=True): | ||||||
|  |         """Wiki-formate une activité, pour le calendrier raw si ``raw``, pour le human-readable sinon.""" | ||||||
|  |         if raw: | ||||||
|  |             return """== {title} == | ||||||
|  |  start:: {start} | ||||||
|  |  end:: {end} | ||||||
|  |  description:: {description} -- {club} | ||||||
|  |  location:: {location} | ||||||
|  | """.format( | ||||||
|  |                 title=act.name, | ||||||
|  |                 start=timezone.localtime(act.date_start).strftime("%Y-%m-%d %H:%M"), | ||||||
|  |                 end=timezone.localtime(act.date_end).strftime("%Y-%m-%d %H:%M"), | ||||||
|  |                 description=act.description, | ||||||
|  |                 club=act.organizer.name, | ||||||
|  |                 location=act.location, | ||||||
|  |             ) | ||||||
|  |         else: | ||||||
|  |             return "|| {start} || {title} || {description} || {club} || {location} ||".format( | ||||||
|  |                 title=act.name, | ||||||
|  |                 start=timezone.localtime(act.date_start).strftime("%d/%m/%Y"), | ||||||
|  |                 description=act.description, | ||||||
|  |                 club=act.organizer.name, | ||||||
|  |                 location=act.location, | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def get_raw_page(): | ||||||
|  |         page = "VieBde/PlanningSoirees/LeCalendrier" | ||||||
|  |         header = Command.acl_header + Command.warning_header | ||||||
|  |         header += """= Introduction = | ||||||
|  |  | ||||||
|  |  * Cette page a pour but de recenser les activités BDE afin d'être signalées sur le calendrier de la | ||||||
|  |  [[PageAccueil|page d'accueil]] du wiki. | ||||||
|  | """ | ||||||
|  |         header += Command.intro_generic | ||||||
|  |         body = "\n".join(Command.format_activity(activity) for activity in Activity.objects.filter(valid=True) | ||||||
|  |                          .order_by('-date_start').all()) | ||||||
|  |         footer = "\n----\nCatégorieCalendrierCampus" | ||||||
|  |         return page, header + body + footer | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def get_human_readable_page(): | ||||||
|  |         page = "VieBde/PlanningSoirees" | ||||||
|  |         header = Command.acl_header + Command.warning_header | ||||||
|  |         header += """= Planning de soirées = | ||||||
|  | == Introduction == | ||||||
|  |  * Cette page est destinée à accueillir le planning des soirées BDE. | ||||||
|  | """ | ||||||
|  |         header += Command.intro_generic + "\n" | ||||||
|  |         body = """== Planning des activités à venir == | ||||||
|  | ||'''Date'''||'''Titre'''||'''Description'''||'''Par''' ||'''Lieu'''|| | ||||||
|  | """ | ||||||
|  |         body += "\n".join(Command.format_activity(activity, False) for activity in Activity.objects | ||||||
|  |                           .filter(valid=True, date_end__gte=timezone.now()).order_by('-date_start').all()) | ||||||
|  |         body += """\n\n== Planning des activités passées == | ||||||
|  | ||'''Date'''||'''Titre'''||'''Description'''||'''Par'''||'''Lieu'''|| | ||||||
|  | """ | ||||||
|  |         body += "\n".join(Command.format_activity(activity, False) for activity in Activity.objects | ||||||
|  |                           .filter(valid=True, date_end__lt=timezone.now()).order_by('-date_start').all()) | ||||||
|  |         return page, header + body | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def refresh_raw_wiki_page(comment="refresh", debug=False): | ||||||
|  |         page, content = Command.get_raw_page() | ||||||
|  |         if debug: | ||||||
|  |             print(content) | ||||||
|  |         else: | ||||||
|  |             Command.edit_wiki(page, content, comment) | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def refresh_human_readable_wiki_page(comment="refresh", debug=False): | ||||||
|  |         page, content = Command.get_human_readable_page() | ||||||
|  |         if debug: | ||||||
|  |             print(content) | ||||||
|  |         else: | ||||||
|  |             Command.edit_wiki(page, content, comment) | ||||||
|  |  | ||||||
|  |     def add_arguments(self, parser): | ||||||
|  |         parser.add_argument("--human", "-H", action="store_true", help="Save human readable page") | ||||||
|  |         parser.add_argument("--raw", "-r", action="store_true", help="Save raw page, for the calendar") | ||||||
|  |         parser.add_argument("--comment", "-c", action="store", type=str, help="Comment of the modification") | ||||||
|  |         parser.add_argument("--debug", "-d", action="store_true", help="Don't commit to the wiki, render in stdout") | ||||||
|  |  | ||||||
|  |     def handle(self, *args, **options): | ||||||
|  |         with open("/tmp/abc", "w") as f: | ||||||
|  |             f.write("lalala") | ||||||
|  |             f.write(str(options)) | ||||||
|  |         if options["raw"]: | ||||||
|  |             Command.refresh_raw_wiki_page(options["comment"], options["debug"]) | ||||||
|  |         if options["human"]: | ||||||
|  |             Command.refresh_human_readable_wiki_page(options["comment"], options["debug"]) | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user