From 8a1040bd123395a47af2490e1b4e19c347f12f2a Mon Sep 17 00:00:00 2001
From: Bastien Le Querrec <blq@laquadrature.net>
Date: Tue, 19 Mar 2024 00:47:47 +0100
Subject: [PATCH] =?UTF-8?q?pref06:=20ajout=20de=20la=20pr=C3=A9fecture=20d?=
 =?UTF-8?q?es=20Alpes-Maritimes?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .gitlab-ci.yml       |  28 ++++++++++++
 Makefile             |   2 +
 RAAspotter_pref06.py |  95 +++++++++++++++++++++++++++++++++++++++
 README.md            |   1 +
 pref06.py            | 105 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 231 insertions(+)
 create mode 100644 RAAspotter_pref06.py
 create mode 100755 pref06.py

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 409bb3a..b93399f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -45,6 +45,34 @@ install:
     - lib/
     - pyvenv.cfg
 
+test_pref06:
+  stage: test
+  image: registry.git.laquadrature.net/bastien/raaspotter/base:latest
+  tags:
+  - unprivileged
+  needs: [install]
+  script:
+  - curl --silent --location --output artifacts.zip "${CI_SERVER_PROTOCOL}://${CI_SERVER_HOST}:${CI_SERVER_PORT}/api/v4/projects/${CI_PROJECT_ID}/jobs/artifacts/${CI_COMMIT_BRANCH}/download?job=${CI_JOB_NAME}&job_token=${CI_JOB_TOKEN}" || true
+  - unzip -q artifacts.zip data/pref06/* || true
+  - rm artifacts.zip || true
+  - source bin/activate
+  - /etc/init.d/tor start
+  - python ./pref06.py
+  retry: 2
+  only:
+  - main
+  cache:
+    key: $CI_COMMIT_REF_SLUG
+    paths:
+    - bin/
+    - lib/
+    - pyvenv.cfg
+  artifacts:
+    paths:
+    - data/pref06/*.txt
+    - output.log
+    expire_in: 1 hour
+
 test_pref13:
   stage: test
   image: registry.git.laquadrature.net/bastien/raaspotter/base:latest
diff --git a/Makefile b/Makefile
index 1f17ffc..5e48a15 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,8 @@
 make: pref13 pref35 ppparis
 pref13:
 	python pref13.py
+pref06:
+	python pref06.py
 pref35:
 	python pref35.py
 ppparis:
diff --git a/RAAspotter_pref06.py b/RAAspotter_pref06.py
new file mode 100644
index 0000000..f3f5833
--- /dev/null
+++ b/RAAspotter_pref06.py
@@ -0,0 +1,95 @@
+import os, sys
+import datetime
+
+from bs4 import BeautifulSoup
+from urllib.parse import unquote
+
+from RAAspotter import RAAspotter
+
+class RAAspotter_pref06(RAAspotter):
+
+  # Config
+  __HOST       = 'https://www.alpes-maritimes.gouv.fr'
+  __RAA_PAGE   = {'2024':
+                    [f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2024/Recueils-mensuels',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2024/Recueils-speciaux',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2024/Recueils-specifiques'],
+                  '2023':
+                    [f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2023/Recueils-mensuels',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2023/Recueils-speciaux',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2023/Recueils-specifiques'],
+                  '2022':
+                    [f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2022/Recueils-mensuels',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2022/Recueils-speciaux',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2022/Recueils-specifiques'],
+                  '2021':
+                    [f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2021/Recueils-mensuels',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2021/Recueils-speciaux',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2021/Recueils-specifiques'],
+                  '2020':
+                    [f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2020/Recueils-mensuels',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2020/Recueils-speciaux',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2020/Recueils-specifiques'],
+                  '2019':
+                    [f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2019/Recueils-mensuels',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2019/Recueils-speciaux',
+                    f'{__HOST}/Publications/Recueil-des-actes-administratifs-RAA/Annee-2019/Recueils-specifiques']}
+  __USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0'
+
+  def __init__(self, data_dir):
+    super().__init__(data_dir, self.__USER_AGENT)
+    self.enable_tor(20)
+
+  def get_raa(self, keywords):
+    self.print_output('RAAspotter_pref06')
+    self.print_output(f'Termes recherchés: {keywords}')
+    self.print_output('')
+
+    pages_to_parse = []
+    if self.not_before.year <= 2024:
+      for page in self.__RAA_PAGE['2024']:
+        pages_to_parse.append(page)
+    if self.not_before.year <= 2023:
+      for page in self.__RAA_PAGE['2023']:
+        pages_to_parse.append(page)
+    if self.not_before.year <= 2022:
+      for page in self.__RAA_PAGE['2022']:
+        pages_to_parse.append(page)
+    if self.not_before.year <= 2021:
+      for page in self.__RAA_PAGE['2021']:
+        pages_to_parse.append(page)
+    if self.not_before.year <= 2020:
+      for page in self.__RAA_PAGE['2020']:
+        pages_to_parse.append(page)
+    if self.not_before.year <= 2019:
+      for page in self.__RAA_PAGE['2019']:
+        pages_to_parse.append(page)
+
+    elements = self.get_raa_with_pager(pages_to_parse, ".fr-pagination__link.fr-pagination__link--next", self.__HOST)
+    self.tor_get_new_id()
+    self.set_sleep_time(10)
+    self.parse_raa(elements, keywords.split(','))
+    self.mailer()
+
+  def get_raa_elements(self, page_content):
+    elements = []
+    # On charge le parser
+    soup = BeautifulSoup(page_content, 'html.parser')
+
+    # Pour chaque élément fr-card__content, on cherche sa balise a, et si c'est un PDF on le parse
+    cards = soup.find_all('div', class_='fr-card__content')
+    for card in cards:
+      a = card.find('a')
+      if a['href'].endswith('.pdf'):
+        if a['href'].startswith('/'):
+          url = f"{self.__HOST}{a['href']}"
+        else:
+          url = a['href']
+
+        name     = a.get_text().strip()
+        date     = datetime.datetime.strptime(card.find('p', class_='fr-card__detail').get_text().replace('Publié le ', '').strip(), '%d/%m/%Y')
+        filename = unquote(url.split('/')[-1])
+
+        raa = RAAspotter.RAA(url, date, name, filename)
+        elements.append(raa)
+    return elements
diff --git a/README.md b/README.md
index 529793b..dd22f66 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,7 @@ Il est possible de ne lancer l'analyse que pour une seule administration, en lan
 
 ## Administrations supportées
 
+- Préfecture des Alpes-Maritimes  (`pref06.py`)
 - Préfecture des Bouches-du-Rhône (`pref13.py`)
 - Préfecture d'Ille-et-Vilaine (`pref35.py`)
 - Préfecture de police de Paris (`ppparis.py`)
diff --git a/pref06.py b/pref06.py
new file mode 100755
index 0000000..3ed803d
--- /dev/null
+++ b/pref06.py
@@ -0,0 +1,105 @@
+import os
+import argparse
+import logging
+import datetime
+
+from RAAspotter import RAAspotter
+from RAAspotter_pref06 import RAAspotter_pref06
+
+# Config
+__KEYWORDS = os.getenv('KEYWORDS') or 'vidéoprotection,caméras,captation,aéronef'
+__DATA_DIR = os.path.dirname(os.path.abspath(__file__))+'/data/pref06/'
+__SMTP_HOSTNAME = os.getenv('SMTP_HOSTNAME') or 'localhost'
+__SMTP_USERNAME = os.getenv('SMTP_USERNAME') or ''
+__SMTP_PASSWORD = os.getenv('SMTP_PASSWORD') or ''
+__EMAIL_FROM = os.getenv('EMAIL_FROM')
+__EMAIL_TO = os.getenv('EMAIL_TO')
+if os.getenv('SMTP_PORT'):
+  __SMTP_PORT = int(os.getenv('SMTP_PORT'))
+else:
+  __SMTP_PORT = 587
+if os.getenv('SMTP_STARTTLS'):
+  __SMTP_STARTTLS = True
+else:
+  __SMTP_STARTTLS = False
+if os.getenv('SMTP_SSL'):
+  __SMTP_SSL = True
+else:
+  __SMTP_SSL = False
+if os.getenv('NOT_BEFORE'):
+  __NOT_BEFORE = datetime.datetime.strptime(os.getenv('NOT_BEFORE'), '%Y-%m-%d')
+else:
+  __NOT_BEFORE = datetime.datetime(1970, 1, 1)
+__MASTODON_ACCESS_TOKEN = os.getenv('MASTODON_ACCESS_TOKEN')
+__MASTODON_INSTANCE = os.getenv('MASTODON_INSTANCE')
+
+# Début du script
+parser = argparse.ArgumentParser(prog='pref06.py', description='Télécharge les RAA de la préfecture d\'Ille-et-Vilaine et recherche des mots-clés')
+parser.add_argument('-k', '--keywords', action='store', help='liste des termes recherchés, séparés par une virgule (par défaut : vidéoprotection,caméras,captation,aéronef)')
+parser.add_argument('--not-before', action='store', help='n\'analyse pas les RAA datant d\'avant la date indiquée, au format YYYY-MM-DD (par défaut : analyse tous les RAA)')
+parser.add_argument('--smtp-hostname', action='store', help='nom d\'hôte SMTP (par défaut : localhost)')
+parser.add_argument('--smtp-username', action='store', help='nom d\'utilisateur SMTP (par défaut : vide)')
+parser.add_argument('--smtp-password', action='store', help='mot de passe SMTP (par défaut : vide)')
+parser.add_argument('--smtp-port', action='store', help='port SMTP (par défaut : 587)')
+parser.add_argument('--smtp-starttls', action='store_true', help='connexion SMTP avec STARTTLS')
+parser.add_argument('--smtp-ssl', action='store_true', help='connexion SMTP avec SSL')
+parser.add_argument('-f', '--email-from', action='store', help='adresse de courrier électronique expéditrice des notifications')
+parser.add_argument('-t', '--email-to', action='store', help='adresses de courrier électronique destinataires des notifications (séparées par une virgule)')
+parser.add_argument('--mastodon-access-token', action='store', help='jeton d\'accès pour publier sur Mastodon (par défaut : vide)')
+parser.add_argument('--mastodon-instance', action='store', help='URL de l\'instance (doit inclure "http://" ou "https://" ; par défaut : vide)')
+parser.add_argument('-v', action='store_true', help='relève le niveau de verbosité à INFO')
+parser.add_argument('-vv', action='store_true', help='relève le niveau de verbosité à DEBUG')
+args = parser.parse_args()
+
+if args.v or os.getenv('VERBOSE'):
+  logging.basicConfig(level=logging.INFO)
+
+if args.vv or os.getenv('VVERBOSE'):
+  logging.basicConfig(level=logging.DEBUG)
+
+if args.keywords:
+  __KEYWORDS = args.keywords
+
+if args.not_before:
+  __NOT_BEFORE = datetime.datetime.strptime(args.not_before, '%Y-%m-%d')
+
+if args.smtp_hostname:
+  __SMTP_HOSTNAME = args.smtp_hostname
+
+if args.smtp_username:
+  __SMTP_USERNAME = args.smtp_username
+
+if args.smtp_password:
+  __SMTP_PASSWORD = args.smtp_password
+
+if args.smtp_port:
+  __SMTP_PORT = int(args.smtp_port)
+
+if args.smtp_starttls:
+  __SMTP_STARTTLS = True
+
+if args.smtp_ssl:
+  __SMTP_SSL = True
+
+if args.email_from:
+  __EMAIL_FROM = args.email_from
+
+if args.email_to:
+  __EMAIL_TO = args.email_to
+
+if args.mastodon_access_token:
+  __MASTODON_ACCESS_TOKEN = args.mastodon_access_token
+
+if args.mastodon_instance:
+  __MASTODON_INSTANCE = args.mastodon_instance
+
+# On crée le dossier de téléchargement
+os.makedirs(__DATA_DIR, exist_ok=True)
+
+raa_spotter = RAAspotter_pref06(__DATA_DIR)
+raa_spotter.not_before = __NOT_BEFORE
+raa_spotter.configure_mailer(__SMTP_HOSTNAME, __SMTP_USERNAME, __SMTP_PASSWORD, __SMTP_PORT,
+                             __SMTP_STARTTLS, __SMTP_SSL, __EMAIL_FROM, __EMAIL_TO,
+                             '[RAAspotter] [Préfecture des Alpes-Maritimes] Nouveaux éléments trouvés')
+raa_spotter.configure_mastodon(__MASTODON_ACCESS_TOKEN, __MASTODON_INSTANCE, '[Préfecture des Alpes-Maritimes]', '#pref06')
+raa_spotter.get_raa(__KEYWORDS)
-- 
GitLab