IO4IT 4.0.7__tar.gz → 4.0.9__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 (110) hide show
  1. io4it-4.0.9/PKG-INFO +12 -0
  2. io4it-4.0.9/io4it.egg-info/PKG-INFO +12 -0
  3. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/toolViews/key_manager_ui.py +1 -1
  4. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/utils/keys_manager.py +29 -10
  5. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/utils/mail.py +54 -21
  6. io4it-4.0.9/orangecontrib/IO4IT/utils/pptx2jpg.py +102 -0
  7. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWInboxMailMonitoring.py +1 -1
  8. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWPipAuditor.py +68 -41
  9. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWXLSX_insert.py +134 -60
  10. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owinsertdatatoexcel.ui +27 -14
  11. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owpipauditor.ui +15 -2
  12. {io4it-4.0.7 → io4it-4.0.9}/setup.py +1 -1
  13. io4it-4.0.7/PKG-INFO +0 -30
  14. io4it-4.0.7/io4it.egg-info/PKG-INFO +0 -30
  15. io4it-4.0.7/orangecontrib/IO4IT/utils/pptx2jpg.py +0 -64
  16. {io4it-4.0.7 → io4it-4.0.9}/io4it.egg-info/SOURCES.txt +0 -0
  17. {io4it-4.0.7 → io4it-4.0.9}/io4it.egg-info/dependency_links.txt +0 -0
  18. {io4it-4.0.7 → io4it-4.0.9}/io4it.egg-info/entry_points.txt +0 -0
  19. {io4it-4.0.7 → io4it-4.0.9}/io4it.egg-info/namespace_packages.txt +0 -0
  20. {io4it-4.0.7 → io4it-4.0.9}/io4it.egg-info/requires.txt +0 -0
  21. {io4it-4.0.7 → io4it-4.0.9}/io4it.egg-info/top_level.txt +0 -0
  22. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/__init__.py +0 -0
  23. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/ocr_function/__init__.py +0 -0
  24. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/ocr_function/word_converter.py +0 -0
  25. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/toolViews/designer/key_manager_ui.ui +0 -0
  26. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/toolViews/designer/link_workflow_manager_ui.ui +0 -0
  27. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/toolViews/linkHTLMWorkflow_manager_ui.py +0 -0
  28. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/utils/__init__.py +0 -0
  29. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/utils/environment_collector.py +0 -0
  30. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/utils/pool_exec_utils.py +0 -0
  31. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/utils/secret_manager.py +0 -0
  32. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/utils/utils_md.py +0 -0
  33. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWChatGpt.py +0 -0
  34. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWDeep_Search.py +0 -0
  35. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWDoclingToMarkdown.py +0 -0
  36. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWExportMarkdown.py +0 -0
  37. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWExtractTablesDocxToXlsx.py +0 -0
  38. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWJsonToDataTable.py +0 -0
  39. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWMD2HTML.py +0 -0
  40. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWMarkdownLoader.py +0 -0
  41. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWMarkdownizer.py +0 -0
  42. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWOfficeNormalizer.py +0 -0
  43. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWPPTX2JPG.py +0 -0
  44. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWParserHTML.py +0 -0
  45. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWPdfType.py +0 -0
  46. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWProcessPoolExecutor.py +0 -0
  47. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWS3Uploader.py +0 -0
  48. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWS3downloader.py +0 -0
  49. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWS3list.py +0 -0
  50. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWWebSearch.py +0 -0
  51. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWmailLoader.py +0 -0
  52. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWmailSender.py +0 -0
  53. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/OWwordpdf2docx.py +0 -0
  54. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/__init__.py +0 -0
  55. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/__init__.py +0 -0
  56. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/nogui.ui +0 -0
  57. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/ow_extract_tables_docx_to_xlsx.ui +0 -0
  58. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/ow_file_ext_selector.ui +0 -0
  59. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/ow_json_to_data_table.ui +0 -0
  60. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owchatgpt.ui +0 -0
  61. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owdeepsearch.ui +0 -0
  62. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owdoclingasr.ui +0 -0
  63. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owdoclingtomarkdown.ui +0 -0
  64. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owexportmarkdown.ui +0 -0
  65. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owinboxmailmonitoring.ui +0 -0
  66. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owmailloader.ui +0 -0
  67. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owmailsender.ui +0 -0
  68. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owmarkdownizer.ui +0 -0
  69. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owmarkdownloader.ui +0 -0
  70. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owmd2html.ui +0 -0
  71. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owofficenormalizer.ui +0 -0
  72. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owparserhtml.ui +0 -0
  73. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owpdftype.ui +0 -0
  74. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owpptx2jpg.ui +0 -0
  75. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owprocesspoolexecutor.ui +0 -0
  76. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owspeechtotext.ui +0 -0
  77. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owvisualizationer.ui +0 -0
  78. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/owwebsearch.ui +0 -0
  79. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/designer/wordpdf2docx.ui +0 -0
  80. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/__init__.py +0 -0
  81. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/chatgpt.png +0 -0
  82. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/check_pdf.png +0 -0
  83. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/deepsearch.svg +0 -0
  84. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/dep_md_old.png +0 -0
  85. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/download.png +0 -0
  86. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/export_md.png +0 -0
  87. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/extract_table.png +0 -0
  88. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/file_extensor.png +0 -0
  89. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/html.png +0 -0
  90. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/json-file.png +0 -0
  91. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/list_aws.png +0 -0
  92. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/load_md.png +0 -0
  93. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/mail_loader.png +0 -0
  94. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/mail_writer.png +0 -0
  95. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/md.png +0 -0
  96. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/monitor-email.svg +0 -0
  97. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/office_normalizer.png +0 -0
  98. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/owmd2html.svg +0 -0
  99. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/pip_auditor.png +0 -0
  100. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/pptx2jpg.png +0 -0
  101. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/process_pool_executor.png +0 -0
  102. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/speech_to_text.png +0 -0
  103. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/upload.png +0 -0
  104. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/visualizationer.png +0 -0
  105. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/websearch.png +0 -0
  106. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/wordpdf2docx.png +0 -0
  107. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons/xlsx_insert.png +0 -0
  108. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/IO4IT/widgets/icons_dev/__init__.py +0 -0
  109. {io4it-4.0.7 → io4it-4.0.9}/orangecontrib/__init__.py +0 -0
  110. {io4it-4.0.7 → io4it-4.0.9}/setup.cfg +0 -0
io4it-4.0.9/PKG-INFO ADDED
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.1
2
+ Name: io4it
3
+ Version: 4.0.9
4
+ Summary: UNKNOWN
5
+ Home-page:
6
+ Author:
7
+ Author-email:
8
+ License: UNKNOWN
9
+ Keywords: orange3 add-on
10
+ Platform: UNKNOWN
11
+
12
+ UNKNOWN
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.1
2
+ Name: io4it
3
+ Version: 4.0.9
4
+ Summary: UNKNOWN
5
+ Home-page:
6
+ Author:
7
+ Author-email:
8
+ License: UNKNOWN
9
+ Keywords: orange3 add-on
10
+ Platform: UNKNOWN
11
+
12
+ UNKNOWN
@@ -155,7 +155,7 @@ class KeyManagerUI(QtWidgets.QDialog):
155
155
  if func_name=="Create / overwrite api key":
156
156
  self.textDetails.setText("{\n'service': 'service_name',\n'api_key': 'api_key',\n'description': 'this_is_a_description'\n}")
157
157
  elif func_name=="Create / overwrite imap4_ssl configuration":
158
- self.textDetails.setText("{\n'agent': 'service_name',\n'alias': 'alias_name',\n'domain': '@domain.com',\n'interval_second': 1,\n'password': 'password'\n}")
158
+ self.textDetails.setText("{\n'agent': 'service_name',\n'alias': 'alias_name',\n'domain': '@domain.com',\n'interval_second': 1,\n'password': 'password',\n'server_imap': 'imap.gmail.com',\n'port_imap': 993,\n'server_smtp': 'smtp.gmail.com',\n'port_smtp': 587\n}")
159
159
  elif func_name=="Create / overwrite nxp configuration":
160
160
  self.textDetails.setText("{\n'dossier_node_id': 'bode_key',\n'serveur': 'servor_adress',\n'username': 'my_username',\n'password': 'password',\n'description': 'this is a description'\n}")
161
161
  elif func_name=="Create / overwrite owa configuration":
@@ -35,7 +35,7 @@ def ask_secure():
35
35
  if resp in ("n", "no"):
36
36
  return False
37
37
  print("Please enter Y or N.")
38
- # FONCTIOSN D'OBFUSCATION GÉNÉRALES & CHEMIN
38
+ # FONCTIONS D'OBFUSCATION GÉNÉRALES & CHEMIN
39
39
  # Fonction pour générer une clé simple à partir du nom d'utilisateur
40
40
  def get_user_key():
41
41
  try:
@@ -115,7 +115,7 @@ def lire_list_email(chemin_fichier):
115
115
  return None
116
116
 
117
117
 
118
- def enregistrer_config_imap4_ssl(agent, my_domain, password, interval_second, alias=""):
118
+ def enregistrer_config_imap4_ssl(agent, my_domain, password, interval_second, alias="", server_imap="imap.gmail.com", port_imap=993, server_smtp="smtp.gmail.com", port_smtp=587):
119
119
  try:
120
120
  dossier = get_keys_dir("IMAP4_SSL")
121
121
  # Crée le dossier s'il n'existe pas
@@ -137,7 +137,11 @@ def enregistrer_config_imap4_ssl(agent, my_domain, password, interval_second, al
137
137
  "domain": my_domain,
138
138
  "interval_second": interval_second,
139
139
  "password_encrypted": mdp_chiffre,
140
- "alias": alias
140
+ "alias": alias,
141
+ "server_imap": server_imap,
142
+ "port_imap": port_imap,
143
+ "server_smtp": server_smtp,
144
+ "port_smtp": port_smtp
141
145
  }
142
146
 
143
147
  # Écriture du fichier
@@ -151,7 +155,7 @@ def enregistrer_config_imap4_ssl(agent, my_domain, password, interval_second, al
151
155
  print(f"❌ Erreur lors de l'enregistrement : {e}")
152
156
  return 1
153
157
 
154
- def enregistrer_config_imap4_ssl_secure(agent, my_domain, password, interval_second, alias=""):
158
+ def enregistrer_config_imap4_ssl_secure(agent, my_domain, password, interval_second, alias="", server_imap="imap.gmail.com", port_imap=993, server_smtp="smtp.gmail.com", port_smtp=587):
155
159
  try:
156
160
  dossier = get_keys_dir("IMAP4_SSL")
157
161
  # Crée le dossier s'il n'existe pas
@@ -171,7 +175,11 @@ def enregistrer_config_imap4_ssl_secure(agent, my_domain, password, interval_sec
171
175
  "domain": my_domain,
172
176
  "interval_second": interval_second,
173
177
  "password": password,
174
- "alias": alias
178
+ "alias": alias,
179
+ "server_imap": server_imap,
180
+ "port_imap": port_imap,
181
+ "server_smtp": server_smtp,
182
+ "port_smtp": port_smtp
175
183
  }
176
184
  sm = secret_manager.SecretManager(service_name)
177
185
  sm.store(contenu,overwrite=True)
@@ -326,7 +334,6 @@ def lire_config_imap4_ssl_dict_sec(chemin_fichier):
326
334
 
327
335
  # Fonction pour lire le fichier de configuration et déchiffrer le mot de passe
328
336
  def lire_config_imap4_ssl(chemin_fichier):
329
- # renvoie une liste =["agent","domain",mdp,"interval_second"]
330
337
  if len(chemin_fichier)<5:
331
338
  print(f"❌ Error path not correct {chemin_fichier}")
332
339
  return None
@@ -341,7 +348,11 @@ def lire_config_imap4_ssl(chemin_fichier):
341
348
  contenu["domain"],
342
349
  contenu["password"],
343
350
  int(contenu["interval_second"]),
344
- contenu.get("alias", "")
351
+ contenu.get("alias", ""),
352
+ contenu.get("server_imap", "imap.gmail.com"),
353
+ contenu.get("port_imap", 993),
354
+ contenu.get("server_smtp", "smtp.gmail.com"),
355
+ contenu.get("port_smtp", 587)
345
356
  ]
346
357
 
347
358
  except Exception as e:
@@ -363,7 +374,11 @@ def lire_config_imap4_ssl(chemin_fichier):
363
374
  contenu["domain"],
364
375
  mdp_dechiffre,
365
376
  int(contenu["interval_second"]),
366
- contenu.get("alias", "")
377
+ contenu.get("alias", ""),
378
+ contenu.get("server_imap", "imap.gmail.com"),
379
+ contenu.get("port_imap", 993),
380
+ contenu.get("server_smtp", "smtp.gmail.com"),
381
+ contenu.get("port_smtp", 587)
367
382
  ]
368
383
  except Exception as e:
369
384
  print(f"❌ Erreur lors de la lecture : {e}")
@@ -549,15 +564,19 @@ def enregistrer_config_cli_imap4_ssl():
549
564
  print("\n📝 Écriture d’un fichier de configuration :")
550
565
  agent = input("🤖 Nom de l’agent : ").strip()
551
566
  domaine = input("📨 @domain.com? : ").strip()
567
+ server_imap = input("📥 Serveur IMAP (ex: imap.nom.com) : ").strip()
568
+ port_imap = int(input("🔌 Port IMAP (ex: 993) : ").strip())
569
+ server_smtp = input("📤 Serveur SMTP (ex: smtp.nom.com) : ").strip()
570
+ port_smtp = int(input("🔌 Port SMTP (ex: 587) : ").strip())
552
571
  mdp = input("📨mot de passe? : ").strip()
553
572
  interval = int(input("⏱️ Intervalle en secondes : ").strip())
554
573
  alias = input("Nom de l'alias : ").strip()
555
574
  store = ask_secure()
556
575
  if not store:
557
- if 0 != enregistrer_config_imap4_ssl(agent, domaine, mdp, interval, alias):
576
+ if 0 != enregistrer_config_imap4_ssl(agent, domaine, mdp, interval, alias, server_imap, port_imap, server_smtp, port_smtp):
558
577
  print("erreur!")
559
578
  return
560
- if 0 != enregistrer_config_imap4_ssl_secure(agent, domaine, mdp, interval, alias):
579
+ if 0 != enregistrer_config_imap4_ssl_secure(agent, domaine, mdp, interval, alias, server_imap, port_imap, server_smtp, port_smtp):
561
580
  print("erreur!")
562
581
  return
563
582
 
@@ -29,7 +29,6 @@ else:
29
29
  from orangecontrib.AAIT.utils import MetManagement
30
30
  from orangecontrib.IO4IT.utils import keys_manager
31
31
 
32
-
33
32
  def clean_addresses(field,myemail):
34
33
  """Retourne une liste d'adresses nettoyées sans ton adresse"""
35
34
  if not field:
@@ -37,6 +36,13 @@ def clean_addresses(field,myemail):
37
36
  addresses = email.utils.getaddresses([field])
38
37
  return [addr for name, addr in addresses if addr.lower() != myemail.lower()]
39
38
 
39
+ def get_addresses(field):
40
+ """Retourne une liste d'adresses nettoyées sans ton adresse"""
41
+ if not field:
42
+ return []
43
+ addresses = email.utils.getaddresses([field])
44
+ return [addr for name, addr in addresses]
45
+
40
46
  def mail_in_folder(agent_name, type="in"):
41
47
  if agent_name is None or agent_name == "":
42
48
  print("agent_name doit etre renseigné")
@@ -74,12 +80,15 @@ def mark_as_read(item):
74
80
  return False
75
81
 
76
82
 
77
- def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
83
+ def check_new_emails(offusc_conf_agent,type_co,list_agent_email=[]):
78
84
  if type_co=="IMAP4_SSL":
79
85
  try:
80
- agent,my_domain,password,interl_seconds,alias=keys_manager.lire_config_imap4_ssl(offusc_conf_agent)
81
- myemail=agent + my_domain
82
- imap = imaplib.IMAP4_SSL("imap.gmail.com")
86
+ agent,my_domain,password,interl_seconds,alias,server_imap,port_imap,_,_=keys_manager.lire_config_imap4_ssl(offusc_conf_agent)
87
+ if(alias and alias != ""):
88
+ myemail=alias + my_domain
89
+ else:
90
+ myemail=agent + my_domain
91
+ imap = imaplib.IMAP4_SSL(server_imap,port_imap)
83
92
  imap.login(myemail, password)
84
93
  imap.select("inbox")
85
94
  status, messages = imap.search(None, 'UNSEEN')
@@ -110,16 +119,29 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
110
119
 
111
120
  # Expéditeur
112
121
  from_ = msg.get("From")
122
+
113
123
  # Destinataires
114
- to_emails = clean_addresses(msg.get("To", ""),myemail)
115
- cc_emails = clean_addresses(msg.get("Cc", ""),myemail)
116
- if (to_emails != [] or cc_emails != []) and alias == "":
117
- if myemail not in to_emails or myemail not in cc_emails:
118
- print(f"l'adresse de reception est un alias : {to_emails}")
119
- continue
120
- if (to_emails == [] and cc_emails == []) and alias != "":
121
- print(f"l'adresse de reception est un alias : {alias}")
124
+ # Je n'ai pas compris la logique
125
+ #to_emails = clean_addresses(msg.get("To", ""),myemail)
126
+ #cc_emails = clean_addresses(msg.get("Cc", ""),myemail)
127
+
128
+ #if (to_emails != [] or cc_emails != []) and alias == "":
129
+ # if myemail not in to_emails and myemail not in cc_emails:
130
+ # print(f"l'adresse de reception est un alias : {to_emails}")
131
+ # continue
132
+ #if (to_emails == [] and cc_emails == []) and alias != "":
133
+ # print(f"l'adresse de reception est un alias : {alias}")
134
+ # continue
135
+ to_emails = get_addresses(msg.get("To", ""))
136
+ cc_emails = get_addresses(msg.get("Cc", ""))
137
+ all_recipients = to_emails + cc_emails
138
+ myemail = myemail.lower().strip()
139
+ all_recipients = [x.lower().strip() for x in all_recipients]
140
+
141
+ if myemail not in all_recipients:
142
+ print(f"Le mail n'est pas destiné à {myemail}")
122
143
  continue
144
+
123
145
  ## passe en lu si ce n'est pas un alias
124
146
  imap.store(mail_id, '+FLAGS', '\\Seen')
125
147
  # Corps
@@ -634,20 +656,25 @@ def lire_message(chemin_fichier):
634
656
  return donnees
635
657
 
636
658
 
637
-
638
-
639
- def send_mail(expediteur, offusc_conf_agent, destinataire, sujet, contenu_html, piece_jointe_paths=None, serveur="smtp.gmail.com", port=587):
659
+ def send_mail(expediteur, offusc_conf_agent, destinataire, sujet, contenu_html, piece_jointe_paths=None, cc=None, serveur="smtp.gmail.com", port=587):
640
660
  msg = EmailMessage()
641
661
  msg['From'] = expediteur
642
662
  msg['To'] = destinataire
643
663
  msg['Subject'] = sujet
644
664
 
665
+ if cc:
666
+ # Si cc est une liste, on la transforme en chaîne séparée par des virgules
667
+ if isinstance(cc, list):
668
+ msg['Cc'] = ", ".join(cc)
669
+ else:
670
+ msg['Cc'] = cc
671
+
645
672
  # ✅ Définir le contenu HTML comme contenu alternatif
646
673
  msg.set_content("Votre client mail ne supporte pas le HTML.") # fallback texte brut
647
674
  msg.add_alternative(contenu_html, subtype='html')
648
675
 
649
676
  # ✅ Ajout d'une ou plusieurs pièces jointes si fournie
650
- if piece_jointe_paths:
677
+ if piece_jointe_paths and os.path.exists(piece_jointe_paths):
651
678
  piece_paths = [f for f in os.listdir(piece_jointe_paths) if os.path.isfile(os.path.join(piece_jointe_paths, f))]
652
679
  for piece_path in piece_paths:
653
680
  try:
@@ -660,7 +687,7 @@ def send_mail(expediteur, offusc_conf_agent, destinataire, sujet, contenu_html,
660
687
  except Exception as e:
661
688
  print(f"Erreur lors de l'ajout de la pièce jointe '{piece_path}': {e}")
662
689
  try:
663
- _, _, mot_de_passe, _, _ = keys_manager.lire_config_imap4_ssl(offusc_conf_agent)
690
+ _, _, mot_de_passe, _, _, _, _, _, _ = keys_manager.lire_config_imap4_ssl(offusc_conf_agent)
664
691
  with smtplib.SMTP(serveur, port) as smtp:
665
692
  smtp.starttls()
666
693
  smtp.login(expediteur, mot_de_passe)
@@ -705,8 +732,9 @@ def to_graph_recipients(champ):
705
732
 
706
733
  def check_send_new_emails(offusc_conf_agent, type_co):
707
734
  if type_co == "IMAP4_SSL":
708
- agent, domain, _, _, alias = keys_manager.lire_config_imap4_ssl(offusc_conf_agent)
735
+ agent, domain, _, _, alias, _, _, server_smtp, port_smtp = keys_manager.lire_config_imap4_ssl(offusc_conf_agent)
709
736
  mail = agent + domain
737
+
710
738
  if alias != "":
711
739
  agent = alias
712
740
  chemin_dossier_in, chemin_dossier_out = mail_in_folder(agent, "out")
@@ -725,14 +753,19 @@ def check_send_new_emails(offusc_conf_agent, type_co):
725
753
  print("Aucun destinataire trouvé dans 'eme'")
726
754
  continue
727
755
 
756
+ chemin_pj = chemin_dossier_out + "/" + contenu + "/pj"
757
+ pj_argument = chemin_pj if os.path.exists(chemin_pj) else None
758
+
728
759
  send_mail(
729
760
  mail,
730
761
  offusc_conf_agent,
731
762
  destinataires,
732
763
  infos["tit"],
733
764
  infos["txt"],
734
- #cc=copies,
735
- piece_jointe_paths=chemin_dossier_out + "/" + contenu + "/pj"
765
+ cc=copies,
766
+ piece_jointe_paths=pj_argument,
767
+ serveur=server_smtp,
768
+ port=port_smtp
736
769
  )
737
770
  MetManagement.reset_folder(chemin_dossier_in + contenu, recreate=False)
738
771
  MetManagement.reset_folder(chemin_dossier_out + contenu, recreate=False)
@@ -0,0 +1,102 @@
1
+ import sys
2
+ import time
3
+ import subprocess
4
+ import shutil
5
+ from pathlib import Path
6
+
7
+ def get_conversion_method():
8
+ """Determines the best available conversion method."""
9
+ # 1. Check for MS Office
10
+ if sys.platform.startswith("win"):
11
+ try:
12
+ import win32com.client
13
+ # Try to see if the COM object is registered
14
+ win32com.client.GetActiveObject("PowerPoint.Application")
15
+ return "office"
16
+ except:
17
+ try:
18
+ # If not running, try to see if it's dispatchable
19
+ win32com.client.Dispatch("PowerPoint.Application")
20
+ return "office"
21
+ except: pass
22
+ elif sys.platform == "darwin":
23
+ # Check if PowerPoint app exists on Mac
24
+ if Path("/Applications/Microsoft PowerPoint.app").exists():
25
+ return "office"
26
+
27
+ # 2. Check for LibreOffice (soffice)
28
+ if shutil.which("soffice"):
29
+ return "libreoffice"
30
+
31
+ # 3. Fallback to Aspose
32
+ return "aspose"
33
+
34
+ def convert_via_office(src: Path, pdf_path: Path):
35
+ if sys.platform.startswith("win"):
36
+ import win32com.client
37
+ powerpoint = win32com.client.Dispatch("PowerPoint.Application")
38
+ try:
39
+ presentation = powerpoint.Presentations.Open(str(src), WithWindow=False)
40
+ presentation.SaveAs(str(pdf_path), 32) # 32 = ppSaveAsPDF
41
+ presentation.Close()
42
+ finally:
43
+ # Note: We don't quit() powerpoint here to avoid killing other open docs
44
+ pass
45
+ elif sys.platform == "darwin":
46
+ script = f'tell application "Microsoft PowerPoint" to save (open POSIX file "{src}") in POSIX file "{pdf_path}" as PDF'
47
+ subprocess.run(["osascript", "-e", script], check=True)
48
+
49
+ def convert_via_libreoffice(src: Path, out_dir: Path):
50
+ subprocess.run([
51
+ "soffice", "--headless", "--convert-to", "pdf",
52
+ "--outdir", str(out_dir), str(src)
53
+ ], check=True, capture_output=True)
54
+ return src.with_suffix(".pdf")
55
+
56
+ def process_one_pptx(file_path_str: str, unique_folder: bool = True):
57
+ try:
58
+ import fitz # PyMuPDF
59
+ except ImportError:
60
+ return [file_path_str, "", "nok", "0.0", "Erreur: PyMuPDF non installé"]
61
+
62
+ t0 = time.time()
63
+ src = Path(file_path_str).resolve()
64
+ out_dir = src.parent / (f"images_{src.stem}" if unique_folder else "images")
65
+ out_dir.mkdir(parents=True, exist_ok=True)
66
+
67
+ method = get_conversion_method()
68
+ img_list = []
69
+
70
+ try:
71
+ # --- PHASE 1: GENERATE IMAGES ---
72
+ if method == "aspose":
73
+ # import aspose.slides as slides
74
+ # with slides.Presentation(str(src)) as pres:
75
+ # for i, slide in enumerate(pres.slides, start=1):
76
+ # img_path = out_dir / f"{src.stem}_slide_{i:03d}.jpg"
77
+ # slide.get_thumbnail(1.5, 1.5).save(str(img_path), slides.export.ImageFormat.JPEG)
78
+ # img_list.append(str(img_path))
79
+ print("converting slides without having libre office or office isn't possible for the moment")
80
+ else:
81
+ # Office or LibreOffice both generate a PDF first
82
+ pdf_path = out_dir / f"{src.stem}.pdf"
83
+ if method == "office":
84
+ convert_via_office(src, pdf_path)
85
+ else: # libreoffice
86
+ convert_via_libreoffice(src, out_dir)
87
+
88
+ # Convert PDF pages to JPG using PyMuPDF
89
+ doc = fitz.open(str(pdf_path))
90
+ for i, page in enumerate(doc, start=1):
91
+ pix = page.get_pixmap(dpi=150)
92
+ img_path = out_dir / f"{src.stem}_slide_{i:03d}.jpg"
93
+ pix.save(str(img_path))
94
+ img_list.append(str(img_path))
95
+ doc.close()
96
+ if pdf_path.exists(): pdf_path.unlink()
97
+
98
+ duration = time.time() - t0
99
+ return [str(src), "|".join(img_list), "ok", f"{duration:.2f}", f"{len(img_list)} slides ({method})"]
100
+
101
+ except Exception as e:
102
+ return [str(src), "", "nok", f"{time.time()-t0:.2f}", f"Method {method} failed: {str(e)}"]
@@ -139,7 +139,7 @@ class OWInboxMailMonitoring(widget.OWWidget):
139
139
  try:
140
140
  agent = ""
141
141
  if self.type_co == "IMAP4_SSL":
142
- agent, _, _, _, alias = keys_manager.lire_config_imap4_ssl(self.your_email_conf)
142
+ agent, _, _, _, alias, _, _, _, _ = keys_manager.lire_config_imap4_ssl(self.your_email_conf)
143
143
  if alias != "":
144
144
  agent = alias
145
145
  if self.type_co == "MICROSOFT_EXCHANGE_OWA":
@@ -5,9 +5,9 @@ from Orange.widgets import widget
5
5
  from Orange.data import Domain, StringVariable, Table
6
6
  from AnyQt.QtWidgets import QApplication
7
7
  from Orange.widgets.settings import Setting
8
- from Orange.widgets.utils.signals import Output
8
+ from Orange.widgets.utils.signals import Output, Input
9
9
  from AnyQt.QtCore import QTimer
10
-
10
+ from datetime import datetime
11
11
 
12
12
  # Importations conditionnelles selon l'architecture du projet
13
13
  if "site-packages/Orange/widgets" in os.path.dirname(os.path.abspath(__file__)).replace("\\", "/"):
@@ -54,8 +54,6 @@ def run_audit(saved_packages: dict) -> tuple:
54
54
  all_keys = set(saved_packages.keys()) | set(current_packages.keys())
55
55
 
56
56
  diff_rows = []
57
- current_rows = []
58
- previous_rows = []
59
57
 
60
58
  for pkg in sorted(all_keys):
61
59
  saved_v = saved_packages.get(pkg, "(Absent)")
@@ -71,32 +69,21 @@ def run_audit(saved_packages: dict) -> tuple:
71
69
  status = "✅ OK"
72
70
 
73
71
  # Table différences : 4 colonnes complètes
74
- #if status != "✅ OK":
75
72
  diff_rows.append([pkg, saved_v, current_v, status])
76
73
 
77
- # Table courante : uniquement Package + Version courante
78
- if current_v != "(Nouveau)":
79
- current_rows.append([pkg, current_v])
80
-
81
- # Table précédente : uniquement Package + Version sauvegardée
82
- if saved_v != "(Absent)":
83
- previous_rows.append([pkg, saved_v])
84
74
 
85
75
  diff_cols = ["Package", "Saved Version", "Current Version", "Status"]
86
- current_cols = ["Package", "Current Version"]
87
- previous_cols = ["Package", "Saved Version"]
76
+
88
77
 
89
78
  diff_table = _make_table(diff_rows, diff_cols) if diff_rows else None
90
- current_table = _make_table(current_rows, current_cols) if current_rows else None
91
- previous_table = _make_table(previous_rows, previous_cols) if previous_rows else None
92
-
93
- return diff_table, current_table, previous_table
79
+
80
+ return diff_table
94
81
 
95
82
 
96
83
  # ---------------------------------------------------------------------------
97
84
  # Widget
98
85
  # ---------------------------------------------------------------------------
99
-
86
+
100
87
  @apply_modification_from_python_file(filepath_original_widget=__file__)
101
88
  class OWPipAuditor(widget.OWWidget):
102
89
  name = "Pip Auditor"
@@ -115,16 +102,23 @@ class OWPipAuditor(widget.OWWidget):
115
102
  # ------------------------------------------------------------------
116
103
  # Settings persistants
117
104
  # ------------------------------------------------------------------
118
- saved_freeze: dict = Setting({}) # Snapshot sauvegardé (dict pkg→version)
105
+ saved_freeze = Setting(None, schema_only=True) # Snapshot sauvegardé (dict pkg→version)
106
+ snapshot_time = Setting(None)
119
107
  autorun: bool = Setting(False) # Checkbox "Lancer automatiquement au démarrage"
120
-
108
+ trigger_on_signal = Setting(False) # Checkbox "Run on signal"
109
+ # ------------------------------------------------------------------
110
+ # Entrées
111
+ # ------------------------------------------------------------------
112
+ class Inputs:
113
+ data = Input("Data", Orange.data.Table)
114
+
121
115
  # ------------------------------------------------------------------
122
116
  # Sorties
123
117
  # ------------------------------------------------------------------
124
118
  class Outputs:
125
- diff_table = Output("Différences", Orange.data.Table) # Packages avec écart
126
- current_table = Output("Actuels", Orange.data.Table) # Snapshot courant
127
- previous_table = Output("Précédents", Orange.data.Table) # Snapshot sauvegardé
119
+ diff_table = Output("Results", Orange.data.Table) # Comparaison packages
120
+ info_table = Output("Infos", Orange.data.Table)
121
+ data = Output("Data", Orange.data.Table) # Sortie "Passthrough"
128
122
 
129
123
  # ------------------------------------------------------------------
130
124
  # Initialisation
@@ -145,6 +139,9 @@ class OWPipAuditor(widget.OWWidget):
145
139
  # Checkbox autorun (doit être définie dans owpipauditor.ui avec le nom checkBox_autorun)
146
140
  self.checkBox_autorun.setChecked(self.autorun)
147
141
  self.checkBox_autorun.stateChanged.connect(self._on_autorun_changed)
142
+
143
+ self.checkBox_trigger.setChecked(self.trigger_on_signal)
144
+ self.checkBox_trigger.stateChanged.connect(self._on_trigger_changed)
148
145
 
149
146
  self.post_initialized()
150
147
  QTimer.singleShot(0, lambda: help_management.override_help_action(self))
@@ -152,6 +149,16 @@ class OWPipAuditor(widget.OWWidget):
152
149
  # Démarrage automatique si l'option est activée et qu'un snapshot existe
153
150
  if self.autorun and self.saved_freeze:
154
151
  QTimer.singleShot(100, self.run)
152
+
153
+ @Inputs.data
154
+ def set_data(self, data):
155
+ # On renvoie immédiatement la donnée en sortie (Passthrough)
156
+ self.Outputs.data.send(data)
157
+
158
+ # Si on reçoit une donnée non nulle et que l'option est activée
159
+ if data is not None and self.trigger_on_signal:
160
+ # On lance la comparaison
161
+ self.run()
155
162
 
156
163
  # ------------------------------------------------------------------
157
164
  # Slots
@@ -159,11 +166,17 @@ class OWPipAuditor(widget.OWWidget):
159
166
  def _on_autorun_changed(self, state: int):
160
167
  """Persistance de la checkbox autorun."""
161
168
  self.autorun = bool(state)
169
+
170
+ def _on_trigger_changed(self, state: int):
171
+ self.trigger_on_signal = bool(state)
162
172
 
163
173
  def take_snapshot(self):
164
174
  """Sauvegarde l'état pip courant dans le Setting."""
165
175
  try:
166
- self.saved_freeze = get_pip_freeze_dict()
176
+ self.saved_freeze = dict(get_pip_freeze_dict())
177
+ self.snapshot_time = datetime.now()
178
+ self.error("")
179
+ self.warning("")
167
180
  self.information(
168
181
  f"Snapshot réussi : {len(self.saved_freeze)} packages sauvegardés."
169
182
  )
@@ -175,8 +188,8 @@ class OWPipAuditor(widget.OWWidget):
175
188
  self.error("")
176
189
  self.warning("")
177
190
 
178
- if not self.saved_freeze:
179
- self.error("Aucun snapshot sauvegardé. Cliquez d'abord sur Snapshot.")
191
+ if self.saved_freeze is None:
192
+ self.error("Aucun snapshot sauvegardé.")
180
193
  return
181
194
 
182
195
  if self.thread is not None:
@@ -197,27 +210,41 @@ class OWPipAuditor(widget.OWWidget):
197
210
  self.progressBarSet(value)
198
211
 
199
212
  def handle_result(self, result):
200
- """
201
- result est un tuple (diff_table, current_table, previous_table).
202
- """
203
213
  try:
204
- diff_table, current_table, previous_table = result
205
- self._last_results = result
206
-
214
+ self.clear_messages()
215
+ diff_table = result
216
+
217
+ if diff_table is None:
218
+ return
219
+
220
+ ref_time = self.snapshot_time
221
+ now_time = datetime.now()
222
+
223
+ info_rows = [[
224
+ ref_time.strftime("%Y-%m-%d %H:%M:%S") if ref_time else "N/A",
225
+ now_time.strftime("%Y-%m-%d %H:%M:%S"),
226
+ ]]
227
+
228
+ info_table = _make_table(info_rows, ["Snapshot time", "Comparison time"])
229
+
207
230
  self.Outputs.diff_table.send(diff_table)
208
- self.Outputs.current_table.send(current_table)
209
- self.Outputs.previous_table.send(previous_table)
210
-
211
- n_diff = sum(1 for row in diff_table if str(row["Status"]) != "✅ OK")
212
- self.information(f"Audit terminé : {n_diff} différence(s) détectée(s) sur {len(diff_table)} package(s).")
231
+ self.Outputs.info_table.send(info_table)
232
+
233
+ status_idx = diff_table.domain.metas.index(diff_table.domain["Status"])
234
+ n_diff = sum(1 for row in diff_table.metas if str(row[status_idx]) != "✅ OK")
235
+
236
+ self.information(
237
+ f"Audit terminé : {n_diff} différence(s)."
238
+ )
239
+
213
240
  except Exception as e:
241
+ self.clear_messages()
214
242
  self.error(f"Erreur lors de l'envoi des tables: {e}")
215
- self.Outputs.diff_table.send(None)
216
- self.Outputs.current_table.send(None)
217
- self.Outputs.previous_table.send(None)
243
+
218
244
 
219
245
  def handle_finish(self):
220
246
  self.progressBarFinished()
247
+ self.thread = None
221
248
 
222
249
  # ------------------------------------------------------------------
223
250
  # Hook post-init (override si besoin dans une sous-classe)