IO4IT 3.0.3.2__tar.gz → 3.0.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. io4it-3.0.4.1/PKG-INFO +38 -0
  2. io4it-3.0.4.1/io4it.egg-info/PKG-INFO +38 -0
  3. {io4it-3.0.3.2 → io4it-3.0.4.1}/io4it.egg-info/SOURCES.txt +4 -1
  4. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/utils/keys_manager.py +138 -13
  5. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/utils/mail.py +41 -126
  6. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWExportMarkdown.py +12 -9
  7. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWExtractTablesDocxToXlsx.py +47 -43
  8. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWInboxMailMonitoring.py +9 -5
  9. io4it-3.0.4.1/orangecontrib/IO4IT/widgets/OWJsonToDataTable.py +80 -0
  10. io4it-3.0.3.2/orangecontrib/IO4IT/widgets/designer/owdocxtoxlsx.ui → io4it-3.0.4.1/orangecontrib/IO4IT/widgets/designer/ow_extract_tables_docx_to_xlsx.ui +34 -44
  11. io4it-3.0.4.1/orangecontrib/IO4IT/widgets/designer/ow_json_to_data_table.ui +138 -0
  12. io4it-3.0.4.1/orangecontrib/IO4IT/widgets/icons/json-file.png +0 -0
  13. {io4it-3.0.3.2 → io4it-3.0.4.1}/setup.py +1 -1
  14. io4it-3.0.3.2/PKG-INFO +0 -7
  15. io4it-3.0.3.2/io4it.egg-info/PKG-INFO +0 -7
  16. {io4it-3.0.3.2 → io4it-3.0.4.1}/io4it.egg-info/dependency_links.txt +0 -0
  17. {io4it-3.0.3.2 → io4it-3.0.4.1}/io4it.egg-info/entry_points.txt +0 -0
  18. {io4it-3.0.3.2 → io4it-3.0.4.1}/io4it.egg-info/namespace_packages.txt +0 -0
  19. {io4it-3.0.3.2 → io4it-3.0.4.1}/io4it.egg-info/requires.txt +0 -0
  20. {io4it-3.0.3.2 → io4it-3.0.4.1}/io4it.egg-info/top_level.txt +0 -0
  21. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/__init__.py +0 -0
  22. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/ocr_function/__init__.py +0 -0
  23. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/ocr_function/word_converter.py +0 -0
  24. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/utils/__init__.py +0 -0
  25. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/utils/pool_exec_utils.py +0 -0
  26. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/utils/secret_manager.py +0 -0
  27. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/utils/utils_md.py +0 -0
  28. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWChatGpt.py +0 -0
  29. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWDeep_Search.py +0 -0
  30. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWDoclingASR.py +0 -0
  31. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWDoclingToMarkdown.py +0 -0
  32. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWMD2HTML.py +0 -0
  33. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWMarkdownLoader.py +0 -0
  34. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWMarkdownizer.py +0 -0
  35. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWOfficeNormalizer.py +0 -0
  36. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWParserHTML.py +0 -0
  37. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWPdfType.py +0 -0
  38. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWProcessPoolExecutor.py +0 -0
  39. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWS3Uploader.py +0 -0
  40. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWS3downloader.py +0 -0
  41. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWS3list.py +0 -0
  42. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWSpeechToText.py +0 -0
  43. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWWebSearch.py +0 -0
  44. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWmailLoader.py +0 -0
  45. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWmailSender.py +0 -0
  46. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/OWwordpdf2docx.py +0 -0
  47. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/__init__.py +0 -0
  48. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/__init__.py +0 -0
  49. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/nogui.ui +0 -0
  50. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/ow_file_ext_selector.ui +0 -0
  51. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owchatgpt.ui +0 -0
  52. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owdeepsearch.ui +0 -0
  53. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owdoclingasr.ui +0 -0
  54. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owdoclingtomarkdown.ui +0 -0
  55. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owexportmarkdown.ui +0 -0
  56. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owinboxmailmonitoring.ui +0 -0
  57. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owmailloader.ui +0 -0
  58. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owmailsender.ui +0 -0
  59. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owmarkdownizer.ui +0 -0
  60. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owmarkdownloader.ui +0 -0
  61. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owmd2html.ui +0 -0
  62. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owofficenormalizer.ui +0 -0
  63. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owparserhtml.ui +0 -0
  64. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owpdftype.ui +0 -0
  65. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owprocesspoolexecutor.ui +0 -0
  66. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owspeechtotext.ui +0 -0
  67. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owvisualizationer.ui +0 -0
  68. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/owwebsearch.ui +0 -0
  69. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/designer/wordpdf2docx.ui +0 -0
  70. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/__init__.py +0 -0
  71. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/chatgpt.png +0 -0
  72. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/check_pdf.png +0 -0
  73. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/deepsearch.svg +0 -0
  74. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/dep_md_old.png +0 -0
  75. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/download.png +0 -0
  76. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/export_md.png +0 -0
  77. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/extract_table.png +0 -0
  78. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/file_extensor.png +0 -0
  79. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/html.png +0 -0
  80. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/list_aws.png +0 -0
  81. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/load_md.png +0 -0
  82. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/mail_loader.png +0 -0
  83. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/mail_writer.png +0 -0
  84. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/md.png +0 -0
  85. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/monitor-email.svg +0 -0
  86. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/office_normalizer.png +0 -0
  87. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/owmd2html.svg +0 -0
  88. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/process_pool_executor.png +0 -0
  89. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/speech_to_text.png +0 -0
  90. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/upload.png +0 -0
  91. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/visualizationer.png +0 -0
  92. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/websearch.png +0 -0
  93. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons/wordpdf2docx.png +0 -0
  94. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/IO4IT/widgets/icons_dev/__init__.py +0 -0
  95. {io4it-3.0.3.2 → io4it-3.0.4.1}/orangecontrib/__init__.py +0 -0
  96. {io4it-3.0.3.2 → io4it-3.0.4.1}/setup.cfg +0 -0
io4it-3.0.4.1/PKG-INFO ADDED
@@ -0,0 +1,38 @@
1
+ Metadata-Version: 2.1
2
+ Name: io4it
3
+ Version: 3.0.4.1
4
+ Summary: UNKNOWN
5
+ Home-page:
6
+ Author:
7
+ Author-email:
8
+ License: UNKNOWN
9
+ Keywords: orange3 add-on
10
+ Platform: UNKNOWN
11
+ Requires-Dist: torchvision==0.23.0
12
+ Requires-Dist: torchaudio==2.8.0
13
+ Requires-Dist: torch==2.8.0
14
+ Requires-Dist: pylatexenc
15
+ Requires-Dist: docopt
16
+ Requires-Dist: boto3
17
+ Requires-Dist: opencv-python-headless==4.6.0.66
18
+ Requires-Dist: docling==2.30.0
19
+ Requires-Dist: docling-core==2.26.3
20
+ Requires-Dist: speechbrain
21
+ Requires-Dist: whisper
22
+ Requires-Dist: whisper-openai
23
+ Requires-Dist: pyannote.audio==3.4.0
24
+ Requires-Dist: pyannote-core
25
+ Requires-Dist: pypandoc
26
+ Requires-Dist: pypandoc-binary
27
+ Requires-Dist: scikit-learn
28
+ Requires-Dist: openai
29
+ Requires-Dist: pip-system-certs==5.0
30
+ Requires-Dist: docx2pdf
31
+ Requires-Dist: doc2docx
32
+ Requires-Dist: msal
33
+ Requires-Dist: exchangelib
34
+ Requires-Dist: html2text
35
+ Requires-Dist: ddgs
36
+ Requires-Dist: CATEGORIT
37
+
38
+ UNKNOWN
@@ -0,0 +1,38 @@
1
+ Metadata-Version: 2.1
2
+ Name: io4it
3
+ Version: 3.0.4.1
4
+ Summary: UNKNOWN
5
+ Home-page:
6
+ Author:
7
+ Author-email:
8
+ License: UNKNOWN
9
+ Keywords: orange3 add-on
10
+ Platform: UNKNOWN
11
+ Requires-Dist: torchvision==0.23.0
12
+ Requires-Dist: torchaudio==2.8.0
13
+ Requires-Dist: torch==2.8.0
14
+ Requires-Dist: pylatexenc
15
+ Requires-Dist: docopt
16
+ Requires-Dist: boto3
17
+ Requires-Dist: opencv-python-headless==4.6.0.66
18
+ Requires-Dist: docling==2.30.0
19
+ Requires-Dist: docling-core==2.26.3
20
+ Requires-Dist: speechbrain
21
+ Requires-Dist: whisper
22
+ Requires-Dist: whisper-openai
23
+ Requires-Dist: pyannote.audio==3.4.0
24
+ Requires-Dist: pyannote-core
25
+ Requires-Dist: pypandoc
26
+ Requires-Dist: pypandoc-binary
27
+ Requires-Dist: scikit-learn
28
+ Requires-Dist: openai
29
+ Requires-Dist: pip-system-certs==5.0
30
+ Requires-Dist: docx2pdf
31
+ Requires-Dist: doc2docx
32
+ Requires-Dist: msal
33
+ Requires-Dist: exchangelib
34
+ Requires-Dist: html2text
35
+ Requires-Dist: ddgs
36
+ Requires-Dist: CATEGORIT
37
+
38
+ UNKNOWN
@@ -23,6 +23,7 @@ orangecontrib/IO4IT/widgets/OWDoclingToMarkdown.py
23
23
  orangecontrib/IO4IT/widgets/OWExportMarkdown.py
24
24
  orangecontrib/IO4IT/widgets/OWExtractTablesDocxToXlsx.py
25
25
  orangecontrib/IO4IT/widgets/OWInboxMailMonitoring.py
26
+ orangecontrib/IO4IT/widgets/OWJsonToDataTable.py
26
27
  orangecontrib/IO4IT/widgets/OWMD2HTML.py
27
28
  orangecontrib/IO4IT/widgets/OWMarkdownLoader.py
28
29
  orangecontrib/IO4IT/widgets/OWMarkdownizer.py
@@ -41,12 +42,13 @@ orangecontrib/IO4IT/widgets/OWwordpdf2docx.py
41
42
  orangecontrib/IO4IT/widgets/__init__.py
42
43
  orangecontrib/IO4IT/widgets/designer/__init__.py
43
44
  orangecontrib/IO4IT/widgets/designer/nogui.ui
45
+ orangecontrib/IO4IT/widgets/designer/ow_extract_tables_docx_to_xlsx.ui
44
46
  orangecontrib/IO4IT/widgets/designer/ow_file_ext_selector.ui
47
+ orangecontrib/IO4IT/widgets/designer/ow_json_to_data_table.ui
45
48
  orangecontrib/IO4IT/widgets/designer/owchatgpt.ui
46
49
  orangecontrib/IO4IT/widgets/designer/owdeepsearch.ui
47
50
  orangecontrib/IO4IT/widgets/designer/owdoclingasr.ui
48
51
  orangecontrib/IO4IT/widgets/designer/owdoclingtomarkdown.ui
49
- orangecontrib/IO4IT/widgets/designer/owdocxtoxlsx.ui
50
52
  orangecontrib/IO4IT/widgets/designer/owexportmarkdown.ui
51
53
  orangecontrib/IO4IT/widgets/designer/owinboxmailmonitoring.ui
52
54
  orangecontrib/IO4IT/widgets/designer/owmailloader.ui
@@ -72,6 +74,7 @@ orangecontrib/IO4IT/widgets/icons/export_md.png
72
74
  orangecontrib/IO4IT/widgets/icons/extract_table.png
73
75
  orangecontrib/IO4IT/widgets/icons/file_extensor.png
74
76
  orangecontrib/IO4IT/widgets/icons/html.png
77
+ orangecontrib/IO4IT/widgets/icons/json-file.png
75
78
  orangecontrib/IO4IT/widgets/icons/list_aws.png
76
79
  orangecontrib/IO4IT/widgets/icons/load_md.png
77
80
  orangecontrib/IO4IT/widgets/icons/mail_loader.png
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import re
2
3
  import json
3
4
  import hashlib
4
5
  import getpass
@@ -11,6 +12,21 @@ else:
11
12
  from orangecontrib.AAIT.utils import MetManagement
12
13
  from orangecontrib.IO4IT.utils import secret_manager
13
14
 
15
+
16
+
17
+ def _normalize_single_quotes_json(s: str) -> str:
18
+ """
19
+ Convertit un pseudo-JSON avec quotes simples
20
+ en JSON valide, de manière contrôlée.
21
+ """
22
+ # ⚠️ On ne touche qu'aux clés et valeurs simples
23
+ # 'key': 'value' → "key": "value"
24
+ s = re.sub(r"'([^']*)'\s*:", r'"\1":', s)
25
+ s = re.sub(r":\s*'([^']*)'", r': "\1"', s)
26
+ return s
27
+
28
+
29
+
14
30
  def ask_secure():
15
31
  while True:
16
32
  resp = input("Secure? (Y/N) : ").strip().lower()
@@ -240,6 +256,25 @@ def enregistrer_config_owa_secure(mail, alias, server, username, password, inter
240
256
 
241
257
 
242
258
 
259
+
260
+ def lire_config_imap4_ssl_dict_sec(chemin_fichier):
261
+ if len(chemin_fichier)<5:
262
+ print(f"❌ Error path not correct", chemin_fichier)
263
+ return None
264
+ if not chemin_fichier.endswith(".sec"):
265
+ chemin_fichier += ".sec"
266
+ try:
267
+ service = "IMAP4_SSL__" + chemin_fichier[:-4]
268
+ sm = secret_manager.SecretManager(service)
269
+ contenu = sm.load_all()
270
+ return contenu
271
+
272
+
273
+ except Exception as e:
274
+ print(f"❌ Erreur lors de la lecture : {e}")
275
+ return None
276
+
277
+
243
278
  # Fonction pour lire le fichier de configuration et déchiffrer le mot de passe
244
279
  def lire_config_imap4_ssl(chemin_fichier):
245
280
  # renvoie une liste =["agent","domain",mdp,"interval_second"]
@@ -251,6 +286,7 @@ def lire_config_imap4_ssl(chemin_fichier):
251
286
  service = "IMAP4_SSL__" + chemin_fichier[:-4]
252
287
  sm = secret_manager.SecretManager(service)
253
288
  contenu = sm.load_all()
289
+ print(contenu)
254
290
  return [
255
291
  contenu["agent"],
256
292
  contenu["domain"],
@@ -284,14 +320,30 @@ def lire_config_imap4_ssl(chemin_fichier):
284
320
  print(f"❌ Erreur lors de la lecture : {e}")
285
321
  return None
286
322
 
287
- def lire_config_oauth2(chemin_fichier):
323
+ def lire_config_oauth2_dict_sec(chemin_fichier, type="MICROSOFT_EXCHANGE_OAUTH2"):
324
+ # renvoie une liste =["agent","domain",mdp,"interval_second"]
325
+ if len(chemin_fichier) < 5:
326
+ print(f"❌ Error path not correct", chemin_fichier)
327
+ return None
328
+ if not chemin_fichier.endswith(".sec"):
329
+ chemin_fichier+=".sec"
330
+ try:
331
+ service = type + "__" + chemin_fichier[:-4]
332
+ sm = secret_manager.SecretManager(service)
333
+ contenu = sm.load_all()
334
+ return contenu
335
+ except Exception as e:
336
+ print(f"❌ Erreur lors de la lecture : {e}")
337
+ return None
338
+
339
+ def lire_config_oauth2(chemin_fichier, type="MICROSOFT_EXCHANGE_OAUTH2"):
288
340
  # renvoie une liste =["agent","domain",mdp,"interval_second"]
289
341
  if len(chemin_fichier) < 5:
290
342
  print(f"❌ Error path not correct", chemin_fichier)
291
343
  return None
292
344
  if chemin_fichier.endswith(".sec"):
293
345
  try:
294
- service = "MICROSOFT_EXCHANGE_OAUTH2__" + chemin_fichier[:-4]
346
+ service = type + "__" + chemin_fichier[:-4]
295
347
  sm = secret_manager.SecretManager(service)
296
348
  contenu = sm.load_all()
297
349
  return [
@@ -305,7 +357,7 @@ def lire_config_oauth2(chemin_fichier):
305
357
  print(f"❌ Erreur lors de la lecture : {e}")
306
358
  return None
307
359
  try:
308
- chemin_fichier = os.path.join(get_keys_dir("MICROSOFT_EXCHANGE_OAUTH2"), chemin_fichier)
360
+ chemin_fichier = os.path.join(get_keys_dir(type), chemin_fichier)
309
361
  # Lecture du fichier JSON
310
362
  with open(chemin_fichier, "r", encoding="utf-8") as f:
311
363
  contenu = json.load(f)
@@ -327,6 +379,21 @@ def lire_config_oauth2(chemin_fichier):
327
379
  print(f"❌ Erreur lors de la lecture : {e}")
328
380
  return None
329
381
 
382
+ def lire_config_owa_dict_sec(chemin_fichier):
383
+ if len(chemin_fichier)<5:
384
+ print(f"❌ Error path not correct", chemin_fichier)
385
+ return None
386
+ if not chemin_fichier.endswith(".sec"):
387
+ chemin_fichier += ".sec"
388
+ try:
389
+ service="MICROSOFT_EXCHANGE_OWA__"+chemin_fichier[:-4]
390
+ sm = secret_manager.SecretManager(service)
391
+ contenu = sm.load_all()
392
+ return contenu
393
+
394
+ except Exception as e:
395
+ print(f"❌ Erreur lors de la lecture : {e}")
396
+ return None
330
397
 
331
398
 
332
399
  def lire_config_owa(chemin_fichier):
@@ -412,15 +479,15 @@ def enregistrer_config_cli_owa():
412
479
  if 0 != enregistrer_config_owa_secure(mail, alias, server, username, mdp, interval):
413
480
  print("erreur!")
414
481
 
415
- def enregistrer_config_oauth2_secure(client_id, client_secret, tenant_id, user_email):
416
- dossier = get_keys_dir("MICROSOFT_EXCHANGE_OAUTH2")
482
+ def enregistrer_config_oauth2_secure(client_id, client_secret, tenant_id, user_email, type="MICROSOFT_EXCHANGE_OAUTH2"):
483
+ dossier = get_keys_dir(type)
417
484
  # Crée le dossier s'il n'existe pas
418
485
  if not os.path.exists(dossier):
419
486
  os.makedirs(dossier)
420
487
 
421
488
  # Nom du fichier (remplace @ par _at_ pour éviter les problèmes)
422
489
  nom_fichier = os.path.join(dossier, f"{user_email.replace('@', '_at_')}.sec")
423
- service_name = f"MICROSOFT_EXCHANGE_OAUTH2__{alias.replace('@', '_at_')}"
490
+ service_name = f"{type}__{user_email.replace('@', '_at_')}"
424
491
  key = get_user_key()
425
492
 
426
493
  contenu = {
@@ -440,8 +507,8 @@ def enregistrer_config_oauth2_secure(client_id, client_secret, tenant_id, user_e
440
507
  return 0
441
508
 
442
509
 
443
- def enregistrer_config_oauth2(client_id, client_secret, tenant_id, user_email):
444
- dossier = get_keys_dir("MICROSOFT_EXCHANGE_OAUTH2")
510
+ def enregistrer_config_oauth2(client_id, client_secret, tenant_id, user_email, type="MICROSOFT_EXCHANGE_OAUTH2"):
511
+ dossier = get_keys_dir(type)
445
512
  # Crée le dossier s'il n'existe pas
446
513
  if not os.path.exists(dossier):
447
514
  os.makedirs(dossier)
@@ -472,27 +539,32 @@ def enregistrer_config_oauth2(client_id, client_secret, tenant_id, user_email):
472
539
 
473
540
  def enregistrer_config_cli_oauth2():
474
541
  print("\n📝 Écriture d’un fichier de configuration OAuth2 :")
542
+ type = input(
543
+ "📄 Nom du service à choisir entre MICROSOFT_EXCHANGE_OAUTH2 et MICROSOFT_EXCHANGE_OAUTH2_MICROSOFT_GRAPH : ").strip()
475
544
  client_id = input("🆔 Client ID : ").strip()
476
545
  client_secret = input("🔑 Client Secret : ").strip()
477
546
  tenant_id = input("🏢 Tenant ID (GUID Azure) : ").strip()
478
547
  user_email = input("📨 Adresse email de l'utilisateur Exchange : ").strip()
479
548
  store = ask_secure()
480
549
  if not store:
481
- if 0 != enregistrer_config_oauth2(client_id, client_secret, tenant_id, user_email):
550
+ if 0 != enregistrer_config_oauth2(client_id, client_secret, tenant_id, user_email, type):
482
551
  print("erreur!")
483
552
  return
484
- if 0 != enregistrer_config_oauth2_secure(client_id, client_secret, tenant_id, user_email):
553
+ if 0 != enregistrer_config_oauth2_secure(client_id, client_secret, tenant_id, user_email, type):
485
554
  print("erreur!")
486
555
 
487
556
 
488
557
 
489
558
 
490
- def lire_config_cli_oauth2():
559
+ def lire_config_cli_oauth2(type=""):
560
+ if type == "":
561
+ type = input("📄 Nom du service à choisir entre MICROSOFT_EXCHANGE_OAUTH2 et MICROSOFT_EXCHANGE_OAUTH2_MICROSOFT_GRAPH : ").strip()
491
562
  chemin_fichier = input("📄 nom fichier json (pas le chemin!) JSON : ").strip()
492
- config = lire_config_oauth2(chemin_fichier)
563
+ print("oeoeo ", chemin_fichier, type)
564
+ config = lire_config_oauth2(chemin_fichier, type)
493
565
  if config == None:
494
566
  print("erreur")
495
- print(config)
567
+
496
568
 
497
569
 
498
570
 
@@ -539,6 +611,59 @@ def enregistrer_config_api(service_name, api_key, description=""):
539
611
  print(f"❌ Erreur d’enregistrement : {e}")
540
612
  return 1
541
613
 
614
+
615
+ def parse_json_and_save_api(config_str: str) -> None:
616
+ raw = config_str.strip()
617
+
618
+ # 1️⃣ Parsing initial
619
+ try:
620
+ data = json.loads(raw)
621
+ except json.JSONDecodeError as e:
622
+ # 2️⃣ Cas très courant : quotes simples
623
+ if "double quotes" in e.msg.lower():
624
+ try:
625
+ normalized = _normalize_single_quotes_json(raw)
626
+ data = json.loads(normalized)
627
+ except json.JSONDecodeError:
628
+ raise ValueError(
629
+ "Invalid JSON: use double quotes "
630
+ '(example: {"service": "xxx"})'
631
+ ) from None
632
+ else:
633
+ raise ValueError(f"Invalid JSON syntax: {e.msg}") from None
634
+
635
+ # 3️⃣ Type attendu
636
+ if not isinstance(data, dict):
637
+ raise TypeError("JSON root must be an object")
638
+
639
+ # 4️⃣ Champs obligatoires
640
+ required_keys = ("service", "api_key")
641
+ missing = [k for k in required_keys if k not in data]
642
+ if missing:
643
+ raise ValueError(f"Missing required key(s): {', '.join(missing)}")
644
+
645
+ # 5️⃣ Validation stricte
646
+ for key in required_keys:
647
+ if not isinstance(data[key], str):
648
+ raise TypeError(f"'{key}' must be a string")
649
+ if not data[key].strip():
650
+ raise ValueError(f"'{key}' must be a non-empty string")
651
+
652
+ # 6️⃣ Champ optionnel
653
+ desc = data.get("description", "")
654
+ if not isinstance(desc, str):
655
+ raise TypeError("'description' must be a string")
656
+
657
+ # 7️⃣ Appel sécurisé
658
+ enregistrer_config_api_secure(
659
+ data["service"],
660
+ data["api_key"],
661
+ desc
662
+ )
663
+
664
+
665
+
666
+
542
667
  # Gestion clés API (HARD dossier aait_store/keys)
543
668
  # Enregistre un fichier JSON {service, api_key_encrypted, description}
544
669
  def enregistrer_config_api_secure(service_name, api_key, description=""):