Skip to content
Extraits de code Groupes Projets

Comparer les révisions

Les modifications sont affichées comme si la révision source était fusionnée avec la révision cible. En savoir plus sur la comparaison des révisions.

Source

Sélectionner le projet cible
No results found

Cible

Sélectionner le projet cible
  • la-quadrature-du-net/Attrap
  • foggyfrog/Attrap
  • skhwiz/Attrap
  • precambrien/Attrap
  • ketsapiwiq/Attrap
  • Joseki/Attrap
  • kr1p/attrap-pref-12
  • kr1p/attrap-pref-46
  • kr1p/attrap-pi
  • Guinness/Attrap
  • astroidgritty/attrap-pref-84
  • davinov/Attrap
  • maettellite/attrap-pref-01
  • m242/Attrap
  • multi/Attrap
  • mverdeil/Attrap
  • olpo/Attrap
17 résultats
Afficher les modifications
import os, re, ssl
import subprocess
import logging
import requests
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions
from bs4 import BeautifulSoup
from pyvirtualdisplay import Display
from pdfminer.high_level import extract_text
from stem import Signal
from stem.control import Controller
import hashlib
import smtplib
from email.message import EmailMessage
logger = logging.getLogger(__name__)
class RAAspotter:
class RAA:
url = ""
date = ""
name = ""
filename = ""
sha256 = ""
def __init__(self, url, date, name, filename):
if not url == "":
self.url = url
if not date == "":
self.date = date
if not name == "":
self.name = name
if not filename == "":
self.filename = filename
def get_sha256(self):
if (self.sha256 == ""):
self.sha256 = hashlib.sha256(self.filename.encode('utf-8')).hexdigest()
return self.sha256
def __init__(self, data_dir, user_agent=''):
logger.debug('Initialisation de RAAspotter')
self.session = requests.Session()
self.data_dir = data_dir
self.found = False
self.output_file_path = os.path.dirname(os.path.abspath(__file__))+'/output.log'
self.sleep_time = 0
self.tor_enabled = False
self.tor_max_requests = 0
self.tor_requests = 0
self.update_user_agent(user_agent)
f = open(self.output_file_path,'w')
f.write('')
f.close()
def enable_tor(self, max_requests=0):
proxies = {
"http": f"socks5h://localhost:9050",
"https": f"socks5h://localhost:9050",
}
self.tor_enabled = True
self.tor_max_requests = max_requests
self.tor_requests = 0
self.session.proxies.update(proxies)
def disable_tor(self):
proxies = {}
self.tor_enabled = False
self.tor_max_requests = 0
self.tor_requests = 0
self.session.proxies.update(proxies)
def tor_get_new_id(self):
logger.info('Changement d\'identité Tor')
try:
controller = Controller.from_port(port = 9051)
controller.authenticate()
controller.signal(Signal.NEWNYM)
time.sleep(3)
self.tor_requests = 0
except:
logger.debug('Impossible de changer d\'identité Tor')
def get_sub_pages(self, page_content, element, host=""):
soup = BeautifulSoup(page_content, 'html.parser')
sub_pages = []
for a in soup.select(element):
url = f"{host}{a['href']}"
sub_page_content = self.get_page(url).content
if not self.has_pdf(sub_page_content):
logger.info(f'{url} ne contient pas de PDF, on récupère ses sous-pages')
for sub_sub_page in self.get_sub_pages(sub_page_content, element, host):
sub_pages.append(sub_sub_page)
else:
sub_pages.append(url)
return sub_pages
def set_sleep_time(self, sleep_time):
self.sleep_time = sleep_time
def has_pdf(self, page_content):
elements = []
soup = BeautifulSoup(page_content, 'html.parser')
for a in soup.find_all('a', href=True):
if a['href'].endswith('.pdf'):
return True
return False
# On démarre le navigateur
def get_session(self, url, wait_element=""):
webdriver_options = webdriver.ChromeOptions()
webdriver_options.add_argument("--no-sandbox")
webdriver_options.add_argument("--disable-extensions")
webdriver_options.add_argument("--disable-gpu")
webdriver_options.add_argument("--disable-dev-shm-usage")
webdriver_options.add_argument("--use_subprocess")
webdriver_options.add_argument("--disable-blink-features=AutomationControlled")
if not self.user_agent == "":
webdriver_options.add_argument(f"--user-agent={self.user_agent}")
webdriver_options.add_argument("--headless")
webdriver_options.add_argument("--window-size=1024,768")
display = Display(visible=False, size=(1024, 768))
display.start()
browser = webdriver.Chrome(options=webdriver_options)
# Téléchargement de l'URL
browser.get(url)
if not wait_element == "":
# On attend que le navigateur ait passé les tests anti-robots et que le contenu s'affiche
WebDriverWait(browser, 120).until(expected_conditions.presence_of_element_located((By.ID, wait_element)))
page_content = browser.page_source
# On récupère les cookies du navigateur pour les réutiliser plus tard
for cookie in browser.get_cookies():
self.session.cookies.set(cookie['name'], cookie['value'])
# On arrête le navigateur
browser.quit()
display.stop()
return page_content
def print_output(self, data):
print(data)
data = data.replace('\033[92m', '')
data = data.replace('\033[0m', '')
data = data.replace('\033[1m', '')
f = open(self.output_file_path,'a')
f.write(data+"\n")
f.close()
def get_page(self, url):
logger.debug(f'Chargement de la page {url}')
if self.sleep_time > 0:
time.sleep(self.sleep_time)
page = self.session.get(url)
if self.tor_enabled:
self.tor_requests+=1
if self.tor_max_requests>0 and self.tor_requests>self.tor_max_requests:
self.tor_get_new_id()
return page
def update_user_agent(self, user_agent):
self.user_agent = user_agent
self.session.headers.update({'User-Agent': self.user_agent})
def download_file(self, raa):
try:
os.makedirs(os.path.dirname(f'{self.data_dir}{raa.get_sha256()}.pdf'), exist_ok=True)
file = self.get_page(raa.url)
f = open(f'{self.data_dir}{raa.get_sha256()}.pdf','wb')
f.write(file.content)
f.close()
except (requests.exceptions.ConnectionError, requests.exceptions.ChunkedEncodingError):
logger.warning(f'ATTENTION: la connexion a été interrompue pendant le téléchargement de {raa.url}, nouvelle tentative...')
self.download_file(raa)
except Exception as exc:
logger.warning(f'ATTENTION: Impossible de télécharger le fichier {raa.url}: {exc}')
def parse_pdf(self, raa, keywords):
if not os.path.isfile(f'{self.data_dir}{raa.get_sha256()}.pdf'):
logger.warning(f'ATTENTION: le fichier {raa.get_sha256()}.pdf n\'existe pas')
else:
text = extract_text(f'{self.data_dir}{raa.get_sha256()}.pdf')
found = False
for keyword in keywords:
if re.search(keyword, text, re.IGNORECASE|re.MULTILINE):
if not found:
self.print_output(f'\033[92m{raa.name}\033[0m ({raa.date})')
found = True
self.found = True
self.print_output(f' Le terme \033[1m{keyword}\033[0m a été trouvé.')
# Écrit le texte du PDF dans un fichier texte pour une analyse future, puis supprime le PDF
f = open(f'{self.data_dir}{raa.get_sha256()}.txt','w')
f.write(text)
f.close()
os.remove(f'{self.data_dir}{raa.get_sha256()}.pdf')
if found:
self.print_output('')
def ocr(self, raa, retry_on_failure=True):
cmd = ['ocrmypdf', '-l', 'eng+fra', '--output-type', 'pdfa', '--redo-ocr', '--skip-big', '500' , f'{self.data_dir}{raa.get_sha256()}.pdf', f'{self.data_dir}{raa.get_sha256()}.pdf']
logger.debug(f'Lancement de ocrmypdf: {cmd}')
try:
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as exc:
if exc.returncode == 2 and retry_on_failure:
logger.warning('ATTENTION : Le fichier n\'est pas un PDF correct, nouvelle tentative de le télécharger')
self.download_file(raa)
self.ocr(raa,False)
elif (not exc.returncode == 6) and (not exc.returncode == 10):
logger.warning('ATTENTION : Impossible d\'OCRiser le document', exc.returncode, exc.output)
def parse_raa(self, elements, keywords):
for raa in elements:
# Si le fichier n'a pas déjà été parsé, on le télécharge et on le parse
if not os.path.isfile(f'{self.data_dir}{raa.get_sha256()}.txt'):
logger.info(f'Nouveau fichier : {raa.name} ({raa.date}). URL : {raa.url}')
self.download_file(raa)
self.ocr(raa, True)
self.parse_pdf(raa, keywords)
def get_raa(self, page_content):
logger.error('Cette fonction doit être surchargée')
def mailer(smtp_host, smtp_username, smtp_password, smtp_port,
smtp_starttls, smtp_ssl, email_from, email_to, email_object,
email_content):
try:
message = EmailMessage()
message.set_content(email_content)
message['Subject'] = email_object
message['From'] = email_from
context = ssl.create_default_context()
if smtp_ssl == True:
for address in email_to.split(','):
message['To'] = address
smtp = smtplib.SMTP_SSL(smtp_host, port, context=context)
smtp.login(smtp_username, smtp_password)
smtp.send_message(message)
smtp.quit()
elif smtp_starttls == True:
for address in email_to.split(','):
message['To'] = address
smtp = smtplib.SMTP(smtp_host)
smtp.starttls(context=context)
smtp.login(smtp_username, smtp_password)
smtp.send_message(message)
smtp.quit()
else:
for address in email_to.split(','):
message['To'] = address
smtp = smtplib.SMTP(smtp_host)
smtp.login(smtp_username, smtp_password)
smtp.send_message(message)
smtp.quit()
except Exception as exc:
logger.warning(f'Impossible d\'envoyer le courrier électronique : {exc}')
from bs4 import BeautifulSoup
from urllib.parse import unquote
from RAAspotter import RAAspotter
class RAAspotter_ppparis(RAAspotter):
# Config
__RAA_PAGE = 'https://www.prefecturedepolice.interieur.gouv.fr/actualites-et-presse/arretes/accueil-arretes'
__WAIT_ELEMENT = 'block-decree-list-block'
__USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'
def __init__(self, data_dir):
super().__init__(data_dir, self.__USER_AGENT)
def get_raa(self, keywords):
self.print_output('RAAspotter_ppparis')
self.print_output(f'Termes recherchés: {keywords}')
page_content = self.get_session()
raa_elements = self.get_raa_elements(page_content)
self.parse_raa(raa_elements, keywords.split(','))
def get_raa_elements(self, page_content):
elements = []
# On charge le parser
soup = BeautifulSoup(page_content, 'html.parser')
# Pour chaque balise a, on regarde si c'est un PDF, et si oui on le parse
for a in soup.find_all('a', href=True):
if a['href'].endswith('.pdf'):
if a['href'].startswith('/'):
url = 'https://www.prefecturedepolice.interieur.gouv.fr'+a['href']
else:
url = a['href']
name = a.find('span').get_text()
date = a.find('div', class_="field--type-datetime").get_text()
filename = unquote(url.split('/')[-1])
raa = RAAspotter.RAA(url, date, name, filename)
elements.append(raa)
return elements
def get_session(self):
return super().get_session(self.__RAA_PAGE, self.__WAIT_ELEMENT)
import os, sys
from bs4 import BeautifulSoup
from urllib.parse import unquote
from RAAspotter import RAAspotter
class RAAspotter_pref13(RAAspotter):
# Config
__HOST = 'https://www.bouches-du-rhone.gouv.fr'
__RAA_PAGE = f'{__HOST}/Publications/RAA-et-Archives'
__USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'
def __init__(self, data_dir):
super().__init__(data_dir, self.__USER_AGENT)
self.enable_tor(10)
def get_raa(self, keywords):
self.print_output('RAAspotter_pref13')
self.print_output(f'Termes recherchés: {keywords}')
page_content = self.get_page(self.__RAA_PAGE).content
sub_pages = self.get_sub_pages(page_content, 'div.fr-card__body div.fr-card__content h2.fr-card__title a', self.__HOST)
raa_elements = []
for page in sub_pages:
for element in self.get_raa_elements(self.get_page(page).content):
raa_elements.append(element)
self.parse_raa(raa_elements, keywords.split(','))
def get_raa_elements(self, page_content):
elements = []
# On charge le parser
soup = BeautifulSoup(page_content, 'html.parser')
# Pour chaque balise a, on regarde si c'est un PDF, et si oui on le parse
for a in soup.find_all('a', href=True):
if a['href'].endswith('.pdf'):
if a['href'].startswith('/'):
url = f"{self.__HOST}{a['href']}"
else:
url = a['href']
name = unquote(url.split('/')[-1])
date = "date non renseignée"
filename = unquote(url.split('/')[-1])
raa = RAAspotter.RAA(url, date, name, filename)
elements.append(raa)
return elements
# RAAspotter
# Attrap
Une série de scripts en Python qui récupère les derniers recueils des actes administratifs (RAA) pour y rechercher certains mots-clés prédéfinis.
Un logiciel qui récupère les derniers recueils des actes administratifs (RAA) pour y rechercher certains mots-clés prédéfinis.
Conçu pour être utilisé dans une CI.
Peut envoyer par email et sur Mastodon les résultats, par exemple avec <a rel="me" href="https://mamot.fr/@AttrapSurveillance">@AttrapSurveillance\@mamot.fr</a>.
## Installation
Il est recommandé d'utiliser virtualenv :
......@@ -14,7 +16,7 @@ source bin/activate
pip3 install -r requirements.txt
```
Vous devez avoir installé OCRmyPDF, les données `eng` et `fra` de Tesseract, et le démon Tor.
Vous devez avoir installé les données `eng` et `fra` de Tesseract et le démon Tor.
## Utilisation
......@@ -26,12 +28,109 @@ make
Attention, le premier lancement prendra plusieurs jours ! Si vous utilisez une CI, vous devez mettre en cache le dossier `data/` afin que les fichiers déjà analysés ne soient pas téléchargés à chaque lancement.
Il est possible de ne lancer l'analyse que pour une seule administration, en lançant le fichier correspondant à l'administration.
Il est possible de ne lancer l'analyse que pour une seule administration, avec la commande : `./cli.py identifiant`
## Options
Les options suivantes peuvent être précisées, par un paramètre si l'utilitaire `cli.py` est utilisé, ou par une variable d'environnement :
| CLI | Variable d'environnement | Signification | Valeur par défaut |
|---|---|---|---|
| `--keywords`, `-k` | `KEYWORDS` | Liste des mots-clés recherchés, séparés par une virgule. | Aucune |
| `--not-before` | `NOT_BEFORE` | Date (format relatif `1 week` ou `YYYY-MM-DD`) avant laquelle les RAA ne sont pas analysés. | `2024-01-01` |
| `--smtp-hostname` | `SMTP_HOSTNAME` | Nom d'hôte SMTP. | `localhost` |
| `--smtp-username` | `SMTP_USERNAME` | Nom d'utilisateur SMTP. | Aucun |
| `--smtp-password` | `SMTP_PASSWORD` | Mot de passe SMTP. | Aucun |
| `--smtp-port` | `SMTP_PORT` | Port SMTP. | `587` |
| `--smtp-starttls` | `SMTP_STARTTLS` | Si spécifié, la connexion SMTP se fait avec STARTTLS. | Non-spécifié |
| `--smtp-ssl` | `SMTP_SSL` | Si spécifié, la connexion SMTP se fait avec SSL. | Non-spécifié |
| `--email-from`, `-f` | `EMAIL_FROM` | Adresse de courrier électronique expéditrice des notifications. | Aucune (désactive l'envoi) |
| `--email-to`, `-t` | `EMAIL_TO` | Adresses de courriers électroniques destinataires des notifications, séparées par une virgule. | Aucune (désactive l'envoi) |
| `--**-email-to` | `--**-EMAIL-TO` | Pour chaque administration dont l'identifiant est **, adresses de courriers électroniques destinataires des notifications, séparées par une virgule, uniquement si l'analyse concerne cette administration en particulier. La liste s'ajoute à celle précisée dans `--email-to`. | Aucune |
| `--mastodon-access-token` | `MASTODON_ACCESS_TOKEN` | Jeton d'accès pour publier sur Mastodon. | Aucun (désactive la publication sur Mastodon) |
| `--mastodon-instance` | `MASTODON_INSTANCE` | URL de l'instance Mastodon de publication (doit inclure "http://" ou "https://"). | Aucune (désactive la publication sur Mastodon) |
| `-v` | `VERBOSE` | Si spécifié, relève le niveau de verbosité à INFO. | Non-spécifié |
| `-vv` | `VVERBOSE` | Si spécifié, relève le niveau de verbosité à DEBUG. | Non-spécifié |
Vous pouvez également activer le safe mode en spécifiant la variable d'environnement `SAFE_MODE`. Cela désactive Tor et limite les requêtes à une toutes les 30 secondes. Cette option ne doit être utilisée qu'en cas de blocage généralisé de Tor. Attention : avec le safe mode, la CI se connecte directement au serveur, et son IP risque d'être bloquée si trop de requêtes sont lancées. Pensez donc à limiter le nombre de jobs qui s'exécutent en parallèle si vous devez activer ce mode. Les requêtes via Selenium ne sont pas impactées par le safe mode.
## Administrations supportées
- Préfecture de police de Paris (`ppparis.py`)
- Préfecture des Bouches-du-Rhône (`pref13.py`)
- Préfecture de police de Paris (identifiant : `ppparis`)
- Préfecture de l'Ain (identifiant : `pref01`)
- Préfecture de l'Aisne (identifiant : `pref02`)
- Préfecture de l'Allier (identifiant : `pref03`)
- Préfecture des Alpes-de-Haute-Provence (identifiant : `pref04`)
- Préfecture des Hautes-Alpes (identifiant : `pref05`)
- Préfecture des Alpes-Maritimes (identifiant : `pref06`)
- Préfecture de l'Ariège (identifiant : `pref09`)
- Préfecture de l'Aube (identifiant : `pref10`)
- Préfecture de l'Aude (identifiant : `pref11`)
- Préfecture des Bouches-du-Rhône (identifiant : `pref13`)
- Préfecture de la Corse-du-Sud (identifiant : `pref2a`)
- Préfecture de Haute-Corse (identifiant : `pref2b`)
- Préfecture du Doubs (identifiant : `pref25`)
- Préfecture du Finistère (identifiant : `pref29`)
- Prefecture du Gard (identifiant : `pref30`)
- Préfecture de la Haute-Garonne (identifiant : `pref31`)
- Préfecture de la Gironde (identifiant : `pref33`)
- Préfecture de l'Hérault (identifiant : `pref34`)
- Préfecture d'Ille-et-Vilaine (identifiant : `pref35`)
- Préfecture de l'Isère (identifiant : `pref38`)
- Préfecture du Jura (identifiant : `pref39`)
- Préfecture de la Loire (identifiant : `pref42`)
- Préfecture de la Loire-Atlantique (identifiant : `pref44`)
- Préfecture de Maine-et-Loire (identifiant : `pref49`)
- Préfecture de la Manche (identifiant : `pref50`)
- Préfecture de la Haute-Marne (identifiant : `pref52`)
- Préfecture de Meurthe-et-Moselle (identifiant : `pref54`)
- Préfecture de la Meuse (identifiant : `pref55`)
- Préfecture du Nord (identifiant : `pref59`)
- Préfecture de l'Orne (identifiant : `pref61`)
- Préfecture du Pas-de-Calais (identifiant : `pref62`)
- Préfecture du Puy-de-Dôme (identifiant : `pref63`)
- Préfecture des Pyrénées-Atlantiques (identifiant : `pref64`)
- Préfecture des Hautes-Pyrénées (identifiant : `pref65`)
- Préfecture des Pyrénées-Orientales (identifiant : `pref66`)
- Préfecture du Rhône (identifiant : `pref69`)
- Préfecture de la Savoie (identifiant : `pref73`)
- Préfecture de la Haute-Savoie (identifiant : `pref74`)
- Préfecture de Paris (identifiant : `pref75`)
- Préfecture de la Seine-Maritime (identifiant : `pref76`)
- Préfecture de Seine-et-Marne (identifiant : `pref77`)
- Préfecture de la Somme (identifiant : `pref80`)
- Préfecture du Tarn (identifiant : `pref81`)
- Préfecture du Var (identifiant : `pref83`)
- Préfecture de la Haute-Vienne (identifiant : `pref87`)
- Préfecture de l'Essonne (identifiant : `pref91`)
- Préfecture des Hauts-de-Seine (identifiant : `pref92`)
- Préfecture de Seine-Saint-Denis (identifiant : `pref93`)
- Préfecture du Val-de-Marne (identifiant : `pref94`)
- Préfecture de Mayotte (identifiant : `pref976`)
- Préfecture de la région Bretagne (identifiant : `prefbretagne`)
- Préfecture de la région Île-de-France (identifiant : `prefidf`)
- Préfecture de la région Provence-Alpes-Côte-d'Azur (identifiant : `prefpaca`)
## Contributions
Les contributions à ce projet sont les bienvenues !
Chaque administration est gérée par un fichier dont le nom correspond à son identifiant (`Attrap_XXX.py`). Commencez par copier un de ces fichiers puis adaptez son code à l'administration que vous voulez ajouter. Il est impératif de lancer le moins de requêtes possibles vers le site de l'administration : lorsqu'une administration a une page par année ou par mois, ne lancez une requête que vers les pages qui correspondent à la plage temporelle demandée dans la valeur de configuration `NOT_BEFORE`.
Vous pouvez lancer la commande suivante pour connaître fonctions disponibles pour récupérer les RAA sur le site d'une administration :
```
bin/python -m pydoc Attrap
```
Avant d'ouvrir une merge request, assurez-vous que :
- l'administration est activée dans `cli.py` et dans `Makefile` ;
- il existe un job dans la CI (`.gitlab-ci.yml`) pour l'administration ;
- le fichier de README indique que la nouvelle administration est supportée ;
- vous n'avez qu'un seul commit par nouvelle préfecture (sinon, il faut faire un squash), de la forme `identifiant_de_l'administration: ajout de nom_complet_de_l'administration` ;
- `make lint` ne renvoie pas d'erreur.
Vous pouvez rejoindre le salon de discussion Matrix du projet : `#Attrap:laquadrature.net`.
## Licence
......
#!/usr/bin/env python3
import os
import argparse
import logging
import datetime
import dateparser
import importlib
from Attrap import Attrap
# Config
__KEYWORDS = os.getenv('KEYWORDS') or ''
__DATA_DIR_ROOT = os.path.dirname(os.path.abspath(__file__)) + '/data/'
__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'):
try:
relative_date = dateparser.parse(os.getenv('NOT_BEFORE'))
__NOT_BEFORE = datetime.datetime(year=relative_date.year, month=relative_date.month, day=relative_date.day)
except Exception as exc:
__NOT_BEFORE = datetime.datetime.strptime(
os.getenv('NOT_BEFORE'), '%Y-%m-%d'
)
else:
__NOT_BEFORE = datetime.datetime(2024, 1, 1)
__MASTODON_ACCESS_TOKEN = os.getenv('MASTODON_ACCESS_TOKEN')
__MASTODON_INSTANCE = os.getenv('MASTODON_INSTANCE')
# Liste des administrations supportées
available_administrations = [
'ppparis',
'pref01',
'pref02',
'pref03',
'pref04',
'pref05',
'pref06',
'pref09',
'pref10',
'pref11',
'pref13',
'pref2a',
'pref2b',
'pref25',
'pref29',
'pref30',
'pref31',
'pref33',
'pref34',
'pref35',
'pref38',
'pref39',
'pref42',
'pref44',
'pref49',
'pref50',
'pref52',
'pref54',
'pref55',
'pref59',
'pref61',
'pref62',
'pref63',
'pref64',
'pref65',
'pref66',
'pref69',
'pref73',
'pref74',
'pref75',
'pref76',
'pref77',
'pref80',
'pref81',
'pref83',
'pref87',
'pref91',
'pref92',
'pref93',
'pref94',
'pref976',
'prefbretagne',
'prefidf',
'prefpaca'
]
# Début du script
parser = argparse.ArgumentParser(
prog='cli.py',
description='Télécharge les RAA d\'une administration donnée et recherche des mots-clés'
)
parser.add_argument(
'administration',
action='store',
help='identifiant de l\'administration',
choices=available_administrations
)
parser.add_argument(
'-k',
'--keywords',
action='store',
help='liste des termes recherchés, séparés par une virgule (aucun par défaut)'
)
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 : 2024-01-01)'
)
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 courriers électroniques destinataires des notifications (séparées par une virgule)'
)
for administration in available_administrations:
parser.add_argument(
f'--{administration}-email-to',
action='store',
help=f'adresses de courrier électronique destinataires des notifications (séparées par une virgule) uniquement si l\'analyse concerne {administration} (s\'ajoute à celles précisées dans --email-to)'
)
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')) and not args.vv and not os.getenv('VVERBOSE'):
logging.basicConfig(level=logging.INFO)
logging.getLogger("stem").setLevel(logging.WARNING)
if args.vv or os.getenv('VVERBOSE'):
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("stem").setLevel(logging.WARNING)
if args.keywords:
__KEYWORDS = args.keywords
if args.not_before:
try:
relative_date = dateparser.parse(args.not_before)
__NOT_BEFORE = datetime.datetime(year=relative_date.year, month=relative_date.month, day=relative_date.day)
except Exception as exc:
__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
__DATA_DIR = f'{__DATA_DIR_ROOT}{args.administration}/'
# On calcule la liste des mails à notifier (liste générale EMAIL_TO + liste
# administration EMAIL_TO_ADMINISTRATION**)
__ADMINISTRATION_EMAIL_TO = ''
administration_var_name = f'{args.administration}_EMAIL_TO'.upper()
if os.getenv(administration_var_name):
__ADMINISTRATION_EMAIL_TO = os.getenv(administration_var_name)
else:
for arg in vars(args).items():
if arg[0] == f'{args.administration}_email_to':
__ADMINISTRATION_EMAIL_TO = arg[1]
if __ADMINISTRATION_EMAIL_TO and not __ADMINISTRATION_EMAIL_TO == '':
if __EMAIL_TO:
__EMAIL_TO = f'{__EMAIL_TO},{__ADMINISTRATION_EMAIL_TO}'
else:
__EMAIL_TO = __ADMINISTRATION_EMAIL_TO
module = importlib.import_module(f'Attrap_{args.administration}')
attrap = getattr(module, f'Attrap_{args.administration}')(__DATA_DIR)
attrap.not_before = __NOT_BEFORE
attrap.configure_mailer(__SMTP_HOSTNAME, __SMTP_USERNAME, __SMTP_PASSWORD, __SMTP_PORT, __SMTP_STARTTLS, __SMTP_SSL,
__EMAIL_FROM, __EMAIL_TO, f'[Attrap] [{attrap.full_name}] Nouveaux éléments trouvés')
attrap.configure_mastodon(__MASTODON_ACCESS_TOKEN, __MASTODON_INSTANCE, f'[{attrap.full_name}]', f'#{attrap.short_code}')
attrap.get_raa(__KEYWORDS)
#!/usr/bin/env bash
set -e
s3_key="${1}"
s3_secret="${2}"
s3_host="${3}"
s3_bucket="${4}"
dest="${5}"
root_path=$(dirname $(realpath "${BASH_SOURCE[0]}"))
administrations="ppparis
pref01
pref02
pref03
pref04
pref05
pref06
pref07
pref08
pref09
pref10
pref11
pref12
pref13
pref14
pref15
pref16
pref17
pref18
pref19
pref2a
pref2b
pref21
pref22
pref23
pref24
pref25
pref26
pref27
pref28
pref29
pref30
pref31
pref32
pref33
pref34
pref35
pref36
pref37
pref38
pref39
pref40
pref41
pref42
pref43
pref44
pref45
pref46
pref47
pref49
pref49
pref50
pref51
pref52
pref53
pref54
pref55
pref56
pref57
pref58
pref59
pref60
pref61
pref62
pref63
pref64
pref65
pref66
pref67
pref68
pref69
pref70
pref71
pref72
pref73
pref74
pref75
pref76
pref77
pref78
pref79
pref80
pref81
pref82
pref83
pref84
pref85
pref86
pref87
pref88
pref89
pref90
pref91
pref92
pref93
pref94
pref95
pref971
pref972
pref973
pref974
pref976
prefidf
prefpaca"
if test -z "$s3_key" || test -z "$s3_secret" || test -z "$s3_host" || test -z "$s3_bucket" || test -z "$dest"; then
echo "Usage: ${0} <s3_key> <s3_secret> <s3_host> <s3_bucket> <dest>"
exit 1
fi
for i in $administrations; do
${root_path}/download-from-s3.sh "${i}" "$s3_key" "$s3_secret" "$s3_host" "$s3_bucket" "$dest" || true
rm "${dest}/${i}.zip" || true
done
#!/usr/bin/env bash
set -e
pref="${1}"
s3_key="${2}"
s3_secret="${3}"
s3_host="${4}"
s3_bucket="${5}"
dest="${6}"
if test -z "$pref" || test -z "$s3_key" || test -z "$s3_secret" || test -z "$s3_host" || test -z "$s3_bucket" || test -z "$dest"; then
echo "Usage: ${0} <pref> <s3_key> <s3_secret> <s3_host> <s3_bucket> <dest>"
exit 1
fi
dest=$(realpath "${dest}")
mkdir -p "${dest}/"
cd "${dest}/"
file="${pref}.zip"
echo "Downloading ${pref}..."
ressource="/${s3_bucket}/${file}"
content_type="application/octet-stream"
date=$(date --utc -R)
signature=$(echo -en "GET\n\n${content_type}\n${date}\n${ressource}" | openssl sha1 -hmac "${s3_secret}" -binary | base64)
curl -X GET \
--silent \
-H "Date: ${date}" \
-H "Content-Type: ${content_type}" \
-H "Authorization: AWS ${s3_key}:${signature}" \
"${s3_host}${ressource}" \
-o "${file}"
unzip -o "${file}" > /dev/null
rm "${file}"
#!/usr/bin/env python3
import argparse
import json
import os
import re
from urllib.parse import unquote
import hashlib
parser = argparse.ArgumentParser(
prog='./misc/fix-pref75-prefidf-url.py',
description='Met à jour les URL des RAA de Paris et d\'Idf'
)
parser.add_argument(
'--data-dir',
action='store',
help='dossier de données (par défaut: data/)'
)
parser.add_argument(
'--dry-run',
action='store_true',
help='ne modifie aucun fichier, affiche seulement les modifications nécessaires (par défaut: false)'
)
args = parser.parse_args()
if args.data_dir:
data_dir = args.data_dir
else:
data_dir = 'data/'
dry_run = args.dry_run
if data_dir.startswith('/'):
data_dir = os.path.abspath(data_dir)
else:
data_dir = os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + '/../' + data_dir)
for administration in os.listdir(data_dir):
# On ne cherche que les dossiers prefidf et pref75
if administration == 'prefidf' or administration == 'pref75':
administration_path = os.path.abspath(data_dir + '/' + administration + '/raa/')
for raa in os.listdir(administration_path):
if raa.endswith('.json'):
raa_id = re.sub('\\.json$', '', raa)
fixed = False
raa_path = os.path.abspath(administration_path + '/' + raa)
txt_path = re.sub('\\.json$', '.txt', raa_path)
raa_file_read = open(raa_path, 'r')
raa_json = json.load(raa_file_read)
raa_file_read.close()
url = raa_json.get('url')
if url.startswith('https://www.prefectures-regions.gouv.fr/ile-de-france/ile-de-france/ile-de-france/irecontenu/telechargement/'):
raa_json['url'] = url.replace('https://www.prefectures-regions.gouv.fr/ile-de-france/ile-de-france/ile-de-france/irecontenu/telechargement/', 'https://www.prefectures-regions.gouv.fr/ile-de-france/irecontenu/telechargement/')
fixed_raa_json = {}
for key in raa_json:
fixed_raa_json[key] = raa_json[key]
fixed_raa_id = hashlib.sha256(unquote(raa_json['url']).encode('utf-8')).hexdigest()
fixed_raa_path = raa_path.replace(raa_id, fixed_raa_id)
fixed_txt_path = txt_path.replace(raa_id, fixed_raa_id)
print(f'{raa_id} -> {fixed_raa_id}:')
print(f" {raa_json['url']}")
print('')
if not dry_run:
raa_file_write = open(fixed_raa_path, 'w')
raa_file_write.write(json.dumps(fixed_raa_json))
raa_file_write.close()
os.remove(raa_path)
os.rename(txt_path, fixed_txt_path)
#!/usr/bin/env python3
import argparse
import datetime
import io
import json
import os
import pytz
import sys
import re
import requests
sys.path.append(os.path.dirname(__file__) + '/../')
from Attrap_pref976 import Attrap_pref976
from Attrap import Attrap
from pypdf import PdfReader
tz_paris = pytz.timezone('Europe/Paris')
session = requests.Session()
def fix_raa_date_v0(raa_json):
try:
raa_json['date'] = tz_paris.localize(datetime.datetime.strptime(raa_json['date'], '%d/%m/%Y')).strftime('%Y-%m-%d')
return raa_json
except Exception:
print(f"\033[91m{exc=}, {type(exc)=}\033[0m")
sys.exit(1)
return raa_json
def fix_pdf_date_v0(raa_json, json_key):
if not raa_json[json_key]:
return raa_json
try:
# On tente de parser avec fuseau horaire
raa_json[json_key] = datetime.datetime.strptime(raa_json[json_key], '%d/%m/%Y %H:%M:%S%z').astimezone(pytz.utc).isoformat(timespec="seconds")
return raa_json
except Exception:
try:
# Sinon on tente de parser sans fuseau horaire et on retourne une date avec le fuseau de Paris
raa_json[json_key] = tz_paris.localize(datetime.datetime.strptime(raa_json[json_key], '%d/%m/%Y %H:%M:%S')).astimezone(pytz.utc).isoformat(timespec="seconds")
return raa_json
except Exception as exc:
print(f"\033[91m{exc=}, {type(exc)=}\033[0m")
sys.exit(1)
return raa_json
def fix_json(raa_json, raa_id, administration):
version = raa_json.get('version')
match version:
# Si le fichier de métadonnées n'a pas de version, il a été généré avant le 14/11/2024 et doit être corrigé
# v0 -> v1 : les dates sont au format YYYY-MM-DD et heure locale
# les heures sont au format YYYY-MM-DD HH:mm:ss±ZZ:ZZ et heure UTC
case None:
print(f"{raa_id}: v0 -> v1")
date = raa_json['date']
first_seen_on = raa_json['first_seen_on']
pdf_creation_date = raa_json['pdf_creation_date']
pdf_modification_date = raa_json['pdf_modification_date']
print(f"{administration}: {raa_json['name']} ({raa_id}):")
fixed_raa_json = fix_raa_date_v0(raa_json)
if not date == fixed_raa_json['date']:
print(f" date: {date} -> {fixed_raa_json['date']}")
fixed_raa_json = fix_pdf_date_v0(fixed_raa_json, 'first_seen_on')
if not raa_json == fixed_raa_json:
print(f" first_seen_on: {first_seen_on} -> {fixed_raa_json['first_seen_on']}")
fixed_raa_json = fix_pdf_date_v0(fixed_raa_json, 'pdf_creation_date')
if not pdf_creation_date == fixed_raa_json['pdf_creation_date']:
print(f" pdf_creation_date: {pdf_creation_date} -> {fixed_raa_json['pdf_creation_date']}")
fixed_raa_json = fix_pdf_date_v0(fixed_raa_json, 'pdf_modification_date')
if not pdf_modification_date == fixed_raa_json['pdf_modification_date']:
print(f" pdf_modification_date: {pdf_modification_date} -> {fixed_raa_json['pdf_modification_date']}")
ordered_fixed_raa_json = {'version': 1}
for key in fixed_raa_json:
ordered_fixed_raa_json[key] = fixed_raa_json[key]
fixed_raa_json = ordered_fixed_raa_json
return fix_json(fixed_raa_json, raa_id, administration)
# Si le fichier de métadonnées est en version 1, il ne contient pas le fuseau horaire de l'administration.
# v1 -> v2: ajout du fuseau horaire (Europe/Paris sauf Mayotte Indian/Mayotte)
case 1:
print(f"{raa_id}: v1 -> v2")
if administration == 'pref976':
print(' Téléchargement du RAA pour recalculer les dates avec le fuseau horaire de Mayotte')
# Il faut retélécharger le RAA pour vérifier que les heures sont dans le bon fuseau
session.headers.update({'User-Agent': Attrap_pref976.user_agent})
pdf_resource = session.get(raa_json['url'], timeout=(10, 120), stream=True)
pdf = io.BytesIO(pdf_resource.content)
reader = PdfReader(pdf)
pdf_metadata = reader.metadata
if pdf_metadata:
if pdf_metadata.creation_date:
pdf_creation_date = Attrap.get_aware_datetime(pdf_metadata.creation_date, timezone=Attrap_pref976.timezone)
raa_json['pdf_creation_date'] = pdf_creation_date.astimezone(pytz.utc).isoformat(timespec="seconds")
if pdf_metadata.modification_date:
pdf_modification_date = Attrap.get_aware_datetime(pdf_metadata.modification_date, timezone=Attrap_pref976.timezone)
raa_json['pdf_modification_date'] = pdf_modification_date.astimezone(pytz.utc).isoformat(timespec="seconds")
print(' Ajout du fuseau horaire')
if administration == 'pref976':
raa_json['timezone'] = Attrap_pref976.timezone
else:
raa_json['timezone'] = 'Europe/Paris'
raa_json['version'] = 2
return fix_json(raa_json, raa_id, administration)
case 2:
return raa_json
case _:
print(f'Version inconnue : {version}')
sys.exit(1)
parser = argparse.ArgumentParser(
prog='./misc/update_metadata_format.py',
description='Met à jour le format des fichiers de métadonnées'
)
parser.add_argument(
'--data-dir',
action='store',
help='dossier de données (par défaut: data/)'
)
parser.add_argument(
'--dry-run',
action='store_true',
help='ne modifie aucun fichier, affiche seulement les modifications nécessaires (par défaut: false)'
)
args = parser.parse_args()
if args.data_dir:
data_dir = args.data_dir
else:
data_dir = 'data/'
dry_run = args.dry_run
if data_dir.startswith('/'):
data_dir = os.path.abspath(data_dir)
else:
data_dir = os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + '/../' + data_dir)
for administration in os.listdir(data_dir):
# On ne cherche que les dossiers ppparis et pref*
if administration.startswith('pref') or administration == 'ppparis':
administration_path = os.path.abspath(data_dir + '/' + administration + '/raa/')
for raa in os.listdir(administration_path):
if raa.endswith('.json'):
raa_id = re.sub('\\.json$', '', raa)
fixed = False
raa_path = os.path.abspath(administration_path + '/' + raa)
raa_file_read = open(raa_path, 'r')
raa_json = json.load(raa_file_read)
raa_file_read.close()
version = raa_json.get('version')
if version != 2:
fixed_raa_json = fix_json(raa_json, raa_id, administration)
if not dry_run:
raa_file_write = open(raa_path, 'w')
raa_file_write.write(json.dumps(fixed_raa_json))
raa_file_write.close()
else:
print(f'On ignore {administration}...')
#!/usr/bin/env bash
set -e
s3_key="${1}"
s3_secret="${2}"
s3_host="${3}"
s3_bucket="${4}"
data="${5}"
root_path=$(dirname $(realpath "${BASH_SOURCE[0]}"))
administrations="ppparis
pref01
pref02
pref03
pref04
pref05
pref06
pref07
pref08
pref09
pref10
pref11
pref12
pref13
pref14
pref15
pref16
pref17
pref18
pref19
pref2a
pref2b
pref21
pref22
pref23
pref24
pref25
pref26
pref27
pref28
pref29
pref30
pref31
pref32
pref33
pref34
pref35
pref36
pref37
pref38
pref39
pref40
pref41
pref42
pref43
pref44
pref45
pref46
pref47
pref49
pref49
pref50
pref51
pref52
pref53
pref54
pref55
pref56
pref57
pref58
pref59
pref60
pref61
pref62
pref63
pref64
pref65
pref66
pref67
pref68
pref69
pref70
pref71
pref72
pref73
pref74
pref75
pref76
pref77
pref78
pref79
pref80
pref81
pref82
pref83
pref84
pref85
pref86
pref87
pref88
pref89
pref90
pref91
pref92
pref93
pref94
pref95
pref971
pref972
pref973
pref974
pref976
prefidf
prefpaca"
if test -z "$s3_key" || test -z "$s3_secret" || test -z "$s3_host" || test -z "$s3_bucket" || test -z "$data"; then
echo "Usage: ${0} <s3_key> <s3_secret> <s3_host> <s3_bucket> <data>"
exit 1
fi
for i in $administrations; do
${root_path}/upload-to-s3.sh "${i}" "$s3_key" "$s3_secret" "$s3_host" "$s3_bucket" "$data" || true
done
#!/usr/bin/env bash
set -e
pref="${1}"
s3_key="${2}"
s3_secret="${3}"
s3_host="${4}"
s3_bucket="${5}"
data="${6}"
if test -z "$pref" || test -z "$s3_key" || test -z "$s3_secret" || test -z "$s3_host" || test -z "$s3_bucket" || test -z "$data"; then
echo "Usage: ${0} <pref> <s3_key> <s3_secret> <s3_host> <s3_bucket> <data>"
exit 1
fi
data=$(realpath "${data}")
cd "${data}/${pref}/raa"
cd "../../"
file="${pref}.zip"
find . -name "${file}" -type f -delete
zip "${file}" "${pref}/raa/"*.txt "${pref}/raa/"*.json > /dev/null
echo "Uploading ${file}..."
ressource="/${s3_bucket}/${file}"
content_type=$(file --mime-type "${file}")
date=$(date --utc -R)
signature=$(echo -en "PUT\n\n${content_type}\n${date}\n${ressource}" | openssl sha1 -hmac "${s3_secret}" -binary | base64)
curl -X PUT \
-T "${file}" \
-H "Date: ${date}" \
-H "Content-Type: ${content_type}" \
-H "Authorization: AWS ${s3_key}:${signature}" \
"${s3_host}${ressource}"
rm "${file}"
import os
import argparse
import logging
from RAAspotter import RAAspotter
from RAAspotter_ppparis import RAAspotter_ppparis
# Config
__KEYWORDS = os.getenv('KEYWORDS') or 'vidéoprotection,caméras,captation,aéronef'
__DATA_DIR = os.path.dirname(os.path.abspath(__file__))+'/data/ppparis/'
__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
# Début du script
parser = argparse.ArgumentParser(prog='ppparis.py', description='Télécharge les RAA de la Préfecture de police de Paris 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('--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('-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.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
# On crée le dossier de téléchargement
os.makedirs(__DATA_DIR, exist_ok=True)
raa_spotter = RAAspotter_ppparis(__DATA_DIR)
raa_spotter.get_raa(__KEYWORDS)
if raa_spotter.found == True and __SMTP_HOSTNAME and __SMTP_USERNAME and __SMTP_PASSWORD and __SMTP_PORT and __EMAIL_TO and __EMAIL_FROM:
output = open(raa_spotter.output_file_path)
RAAspotter.mailer(__SMTP_HOSTNAME, __SMTP_USERNAME, __SMTP_PASSWORD, __SMTP_PORT,
__SMTP_STARTTLS, __SMTP_SSL, __EMAIL_FROM, __EMAIL_TO,
'[RAAspotter] [ppparis] Nouveaux éléments trouvés',
output.read())
import os
import argparse
import logging
from RAAspotter import RAAspotter
from RAAspotter_pref13 import RAAspotter_pref13
# Config
__KEYWORDS = os.getenv('KEYWORDS') or 'vidéoprotection,caméras,captation,aéronef'
__DATA_DIR = os.path.dirname(os.path.abspath(__file__))+'/data/pref13/'
__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
# Début du script
parser = argparse.ArgumentParser(prog='pref13.py', description='Télécharge les RAA de la préfecture des Bouches-du-Rhône 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('--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('-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.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
# On crée le dossier de téléchargement
os.makedirs(__DATA_DIR, exist_ok=True)
raa_spotter = RAAspotter_pref13(__DATA_DIR)
raa_spotter.get_raa(__KEYWORDS)
if raa_spotter.found == True and __SMTP_HOSTNAME and __SMTP_USERNAME and __SMTP_PASSWORD and __SMTP_PORT and __EMAIL_TO and __EMAIL_FROM:
output = open(raa_spotter.output_file_path)
RAAspotter.mailer(__SMTP_HOSTNAME, __SMTP_USERNAME, __SMTP_PASSWORD, __SMTP_PORT,
__SMTP_STARTTLS, __SMTP_SSL, __EMAIL_FROM, __EMAIL_TO,
'[RAAspotter] [pref13] Nouveaux éléments trouvés',
output.read())