@tricoteuses/senat 2.22.3 → 2.22.5

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 (258) hide show
  1. package/lib/aggregates.d.ts +52 -0
  2. package/lib/aggregates.js +930 -0
  3. package/lib/aggregates.mjs +713 -0
  4. package/lib/aggregates.ts +833 -0
  5. package/lib/config.d.ts +10 -0
  6. package/lib/config.js +16 -0
  7. package/lib/config.mjs +16 -0
  8. package/lib/config.ts +26 -0
  9. package/lib/databases.d.ts +2 -0
  10. package/lib/databases.js +26 -0
  11. package/lib/databases.mjs +57 -0
  12. package/lib/databases.ts +71 -0
  13. package/lib/datasets.d.ts +34 -0
  14. package/lib/datasets.js +233 -0
  15. package/lib/datasets.mjs +78 -0
  16. package/lib/datasets.ts +118 -0
  17. package/lib/fields.d.ts +10 -0
  18. package/lib/fields.js +68 -0
  19. package/lib/fields.mjs +22 -0
  20. package/lib/fields.ts +29 -0
  21. package/lib/git.d.ts +26 -0
  22. package/lib/git.js +167 -0
  23. package/lib/index.d.ts +13 -0
  24. package/lib/index.js +1 -0
  25. package/lib/index.mjs +7 -0
  26. package/lib/index.ts +64 -0
  27. package/lib/inserters.d.ts +98 -0
  28. package/lib/inserters.js +500 -0
  29. package/lib/inserters.mjs +360 -0
  30. package/lib/inserters.ts +521 -0
  31. package/lib/legislatures.json +38 -0
  32. package/lib/loaders.d.ts +58 -0
  33. package/lib/loaders.js +286 -0
  34. package/lib/loaders.mjs +158 -0
  35. package/lib/loaders.ts +271 -0
  36. package/lib/model/agenda.d.ts +6 -0
  37. package/lib/model/agenda.js +148 -0
  38. package/lib/model/ameli.d.ts +51 -0
  39. package/lib/model/ameli.js +149 -0
  40. package/lib/model/ameli.mjs +84 -0
  41. package/lib/model/ameli.ts +100 -0
  42. package/lib/model/commission.d.ts +18 -0
  43. package/lib/model/commission.js +269 -0
  44. package/lib/model/debats.d.ts +67 -0
  45. package/lib/model/debats.js +95 -0
  46. package/lib/model/debats.mjs +43 -0
  47. package/lib/model/debats.ts +68 -0
  48. package/lib/model/documents.d.ts +12 -0
  49. package/lib/model/documents.js +151 -0
  50. package/lib/model/dosleg.d.ts +7 -0
  51. package/lib/model/dosleg.js +326 -0
  52. package/lib/model/dosleg.mjs +196 -0
  53. package/lib/model/dosleg.ts +240 -0
  54. package/lib/model/index.d.ts +7 -0
  55. package/lib/model/index.js +7 -0
  56. package/lib/model/index.mjs +5 -0
  57. package/lib/model/index.ts +15 -0
  58. package/lib/model/questions.d.ts +45 -0
  59. package/lib/model/questions.js +89 -0
  60. package/lib/model/questions.mjs +71 -0
  61. package/lib/model/questions.ts +93 -0
  62. package/lib/model/scrutins.d.ts +13 -0
  63. package/lib/model/scrutins.js +114 -0
  64. package/lib/model/seance.d.ts +3 -0
  65. package/lib/model/seance.js +267 -0
  66. package/lib/model/sens.d.ts +146 -0
  67. package/lib/model/sens.js +454 -0
  68. package/lib/model/sens.mjs +415 -0
  69. package/lib/model/sens.ts +516 -0
  70. package/lib/model/texte.d.ts +7 -0
  71. package/lib/model/texte.js +256 -0
  72. package/lib/model/texte.mjs +208 -0
  73. package/lib/model/texte.ts +229 -0
  74. package/lib/model/util.d.ts +9 -0
  75. package/lib/model/util.js +38 -0
  76. package/lib/model/util.mjs +19 -0
  77. package/lib/model/util.ts +32 -0
  78. package/lib/parsers/texte.d.ts +7 -0
  79. package/lib/parsers/texte.js +228 -0
  80. package/lib/raw_types/ameli.d.ts +914 -0
  81. package/lib/raw_types/ameli.js +5 -0
  82. package/lib/raw_types/ameli.mjs +163 -0
  83. package/lib/raw_types/debats.d.ts +207 -0
  84. package/lib/raw_types/debats.js +5 -0
  85. package/lib/raw_types/debats.mjs +58 -0
  86. package/lib/raw_types/dosleg.d.ts +1619 -0
  87. package/lib/raw_types/dosleg.js +5 -0
  88. package/lib/raw_types/dosleg.mjs +438 -0
  89. package/lib/raw_types/questions.d.ts +419 -0
  90. package/lib/raw_types/questions.js +5 -0
  91. package/lib/raw_types/questions.mjs +11 -0
  92. package/lib/raw_types/senat.d.ts +11368 -0
  93. package/lib/raw_types/senat.js +5 -0
  94. package/lib/raw_types/sens.d.ts +8248 -0
  95. package/lib/raw_types/sens.js +5 -0
  96. package/lib/raw_types/sens.mjs +508 -0
  97. package/lib/raw_types_kysely/ameli.d.ts +915 -0
  98. package/lib/raw_types_kysely/ameli.js +7 -0
  99. package/lib/raw_types_kysely/ameli.mjs +5 -0
  100. package/lib/raw_types_kysely/ameli.ts +951 -0
  101. package/lib/raw_types_kysely/debats.d.ts +207 -0
  102. package/lib/raw_types_kysely/debats.js +7 -0
  103. package/lib/raw_types_kysely/debats.mjs +5 -0
  104. package/lib/raw_types_kysely/debats.ts +222 -0
  105. package/lib/raw_types_kysely/dosleg.d.ts +3532 -0
  106. package/lib/raw_types_kysely/dosleg.js +7 -0
  107. package/lib/raw_types_kysely/dosleg.mjs +5 -0
  108. package/lib/raw_types_kysely/dosleg.ts +3621 -0
  109. package/lib/raw_types_kysely/questions.d.ts +414 -0
  110. package/lib/raw_types_kysely/questions.js +7 -0
  111. package/lib/raw_types_kysely/questions.mjs +5 -0
  112. package/lib/raw_types_kysely/questions.ts +426 -0
  113. package/lib/raw_types_kysely/sens.d.ts +4394 -0
  114. package/lib/raw_types_kysely/sens.js +7 -0
  115. package/lib/raw_types_kysely/sens.mjs +5 -0
  116. package/lib/raw_types_kysely/sens.ts +4499 -0
  117. package/lib/raw_types_schemats/ameli.d.ts +539 -0
  118. package/lib/raw_types_schemats/ameli.js +2 -0
  119. package/lib/raw_types_schemats/ameli.mjs +2 -0
  120. package/lib/raw_types_schemats/ameli.ts +601 -0
  121. package/lib/raw_types_schemats/debats.d.ts +127 -0
  122. package/lib/raw_types_schemats/debats.js +2 -0
  123. package/lib/raw_types_schemats/debats.mjs +2 -0
  124. package/lib/raw_types_schemats/debats.ts +145 -0
  125. package/lib/raw_types_schemats/dosleg.d.ts +977 -0
  126. package/lib/raw_types_schemats/dosleg.js +2 -0
  127. package/lib/raw_types_schemats/dosleg.mjs +2 -0
  128. package/lib/raw_types_schemats/dosleg.ts +2193 -0
  129. package/lib/raw_types_schemats/questions.d.ts +235 -0
  130. package/lib/raw_types_schemats/questions.js +2 -0
  131. package/lib/raw_types_schemats/questions.mjs +2 -0
  132. package/lib/raw_types_schemats/questions.ts +249 -0
  133. package/lib/raw_types_schemats/sens.d.ts +6915 -0
  134. package/lib/raw_types_schemats/sens.js +2 -0
  135. package/lib/raw_types_schemats/sens.mjs +2 -0
  136. package/lib/raw_types_schemats/sens.ts +2907 -0
  137. package/lib/scripts/convert_data.d.ts +1 -0
  138. package/lib/scripts/convert_data.js +354 -0
  139. package/lib/scripts/convert_data.mjs +181 -0
  140. package/lib/scripts/convert_data.ts +243 -0
  141. package/lib/scripts/data-download.d.ts +1 -0
  142. package/lib/scripts/data-download.js +12 -0
  143. package/lib/scripts/datautil.d.ts +8 -0
  144. package/lib/scripts/datautil.js +34 -0
  145. package/lib/scripts/datautil.mjs +16 -0
  146. package/lib/scripts/datautil.ts +19 -0
  147. package/lib/scripts/images/transparent_150x192.jpg +0 -0
  148. package/lib/scripts/images/transparent_155x225.jpg +0 -0
  149. package/lib/scripts/parse_textes.d.ts +1 -0
  150. package/lib/scripts/parse_textes.js +44 -0
  151. package/lib/scripts/parse_textes.mjs +46 -0
  152. package/lib/scripts/parse_textes.ts +65 -0
  153. package/lib/scripts/retrieve_agenda.d.ts +1 -0
  154. package/lib/scripts/retrieve_agenda.js +132 -0
  155. package/lib/scripts/retrieve_cr_commission.d.ts +1 -0
  156. package/lib/scripts/retrieve_cr_commission.js +364 -0
  157. package/lib/scripts/retrieve_cr_seance.d.ts +6 -0
  158. package/lib/scripts/retrieve_cr_seance.js +347 -0
  159. package/lib/scripts/retrieve_documents.d.ts +3 -0
  160. package/lib/scripts/retrieve_documents.js +219 -0
  161. package/lib/scripts/retrieve_documents.mjs +249 -0
  162. package/lib/scripts/retrieve_documents.ts +298 -0
  163. package/lib/scripts/retrieve_open_data.d.ts +1 -0
  164. package/lib/scripts/retrieve_open_data.js +315 -0
  165. package/lib/scripts/retrieve_open_data.mjs +217 -0
  166. package/lib/scripts/retrieve_open_data.ts +268 -0
  167. package/lib/scripts/retrieve_senateurs_photos.d.ts +1 -0
  168. package/lib/scripts/retrieve_senateurs_photos.js +147 -0
  169. package/lib/scripts/retrieve_senateurs_photos.mjs +147 -0
  170. package/lib/scripts/retrieve_senateurs_photos.ts +177 -0
  171. package/lib/scripts/retrieve_videos.d.ts +1 -0
  172. package/lib/scripts/retrieve_videos.js +461 -0
  173. package/lib/scripts/shared/cli_helpers.d.ts +95 -0
  174. package/lib/scripts/shared/cli_helpers.js +91 -0
  175. package/lib/scripts/shared/cli_helpers.ts +36 -0
  176. package/lib/scripts/shared/util.d.ts +4 -0
  177. package/lib/scripts/shared/util.js +35 -0
  178. package/lib/scripts/shared/util.ts +33 -0
  179. package/lib/scripts/test_iter_load.d.ts +1 -0
  180. package/lib/scripts/test_iter_load.js +12 -0
  181. package/lib/src/conversion_textes.js +10 -1
  182. package/lib/src/index.d.ts +1 -1
  183. package/lib/src/index.js +1 -1
  184. package/lib/src/loaders.d.ts +1 -0
  185. package/lib/src/loaders.js +1 -0
  186. package/lib/src/model/ameli.js +1 -0
  187. package/lib/src/parsers/texte.js +2 -2
  188. package/lib/src/scripts/convert_data.js +11 -10
  189. package/lib/src/scripts/retrieve_documents.d.ts +1 -1
  190. package/lib/src/scripts/retrieve_documents.js +25 -10
  191. package/lib/src/scripts/retrieve_open_data.js +1 -1
  192. package/lib/src/types/sessions.d.ts +5 -4
  193. package/lib/src/types/sessions.js +10 -75
  194. package/lib/src/types/texte.d.ts +2 -0
  195. package/lib/strings.d.ts +1 -0
  196. package/lib/strings.js +18 -0
  197. package/lib/strings.mjs +18 -0
  198. package/lib/strings.ts +26 -0
  199. package/lib/types/agenda.d.ts +44 -0
  200. package/lib/types/agenda.js +1 -0
  201. package/lib/types/ameli.d.ts +5 -0
  202. package/lib/types/ameli.js +1 -0
  203. package/lib/types/ameli.mjs +13 -0
  204. package/lib/types/ameli.ts +21 -0
  205. package/lib/types/compte_rendu.d.ts +83 -0
  206. package/lib/types/compte_rendu.js +1 -0
  207. package/lib/types/debats.d.ts +2 -0
  208. package/lib/types/debats.js +1 -0
  209. package/lib/types/debats.mjs +2 -0
  210. package/lib/types/debats.ts +6 -0
  211. package/lib/types/dosleg.d.ts +70 -0
  212. package/lib/types/dosleg.js +1 -0
  213. package/lib/types/dosleg.mjs +151 -0
  214. package/lib/types/dosleg.ts +284 -0
  215. package/lib/types/questions.d.ts +2 -0
  216. package/lib/types/questions.js +1 -0
  217. package/lib/types/questions.mjs +1 -0
  218. package/lib/types/questions.ts +3 -0
  219. package/lib/types/sens.d.ts +10 -0
  220. package/lib/types/sens.js +1 -0
  221. package/lib/types/sens.mjs +1 -0
  222. package/lib/types/sens.ts +12 -0
  223. package/lib/types/sessions.d.ts +5 -0
  224. package/lib/types/sessions.js +84 -0
  225. package/lib/types/sessions.mjs +43 -0
  226. package/lib/types/sessions.ts +42 -0
  227. package/lib/types/texte.d.ts +74 -0
  228. package/lib/types/texte.js +16 -0
  229. package/lib/types/texte.mjs +16 -0
  230. package/lib/types/texte.ts +76 -0
  231. package/lib/typings/windows-1252.d.js +2 -0
  232. package/lib/typings/windows-1252.d.mjs +2 -0
  233. package/lib/typings/windows-1252.d.ts +11 -0
  234. package/lib/utils/cr_spliting.d.ts +28 -0
  235. package/lib/utils/cr_spliting.js +265 -0
  236. package/lib/utils/date.d.ts +10 -0
  237. package/lib/utils/date.js +100 -0
  238. package/lib/utils/nvs-timecode.d.ts +7 -0
  239. package/lib/utils/nvs-timecode.js +79 -0
  240. package/lib/utils/reunion_grouping.d.ts +9 -0
  241. package/lib/utils/reunion_grouping.js +361 -0
  242. package/lib/utils/reunion_odj_building.d.ts +5 -0
  243. package/lib/utils/reunion_odj_building.js +154 -0
  244. package/lib/utils/reunion_parsing.d.ts +23 -0
  245. package/lib/utils/reunion_parsing.js +209 -0
  246. package/lib/utils/scoring.d.ts +14 -0
  247. package/lib/utils/scoring.js +147 -0
  248. package/lib/utils/string_cleaning.d.ts +7 -0
  249. package/lib/utils/string_cleaning.js +57 -0
  250. package/lib/validators/config.d.ts +9 -0
  251. package/lib/validators/config.js +10 -0
  252. package/lib/validators/config.mjs +54 -0
  253. package/lib/validators/config.ts +79 -0
  254. package/lib/validators/senat.d.ts +0 -0
  255. package/lib/validators/senat.js +28 -0
  256. package/lib/validators/senat.mjs +24 -0
  257. package/lib/validators/senat.ts +26 -0
  258. package/package.json +5 -5
@@ -0,0 +1,84 @@
1
+ import { jsonArrayFrom } from "kysely/helpers/postgres";
2
+ import { dbAmeli } from "../databases";
3
+ import { concat, toDateString } from "./util";
4
+ function auteurs(amendementId) {
5
+ return jsonArrayFrom(dbAmeli.selectFrom("amdsen")
6
+ .leftJoin("sen_ameli", "amdsen.senid", "sen_ameli.entid")
7
+ .where("amdsen.amdid", "=", amendementId)
8
+ .select([
9
+ "amdsen.prenomuse as prenom",
10
+ "amdsen.nomuse as nom",
11
+ "sen_ameli.mat as matricule",
12
+ ])
13
+ .orderBy("amdsen.rng asc"));
14
+ }
15
+ const findAllQuery = dbAmeli
16
+ .selectFrom("amd")
17
+ .leftJoin("sub", "amd.subid", "sub.id")
18
+ .leftJoin("typsub", "sub.typid", "typsub.id")
19
+ .leftJoin("txt_ameli", "amd.txtid", "txt_ameli.id")
20
+ .leftJoin("ses", "txt_ameli.sesdepid", "ses.id")
21
+ .leftJoin("nat", "txt_ameli.natid", "nat.id")
22
+ .leftJoin("lec_ameli", "txt_ameli.lecid", "lec_ameli.id")
23
+ .leftJoin("avicom", "amd.avcid", "avicom.id")
24
+ .leftJoin("avigvt", "amd.avgid", "avigvt.id")
25
+ .leftJoin("sor", "amd.sorid", "sor.id")
26
+ .leftJoin("irr", "amd.irrid", "irr.id")
27
+ .leftJoin("grppol_ameli", "amd.nomentid", "grppol_ameli.entid")
28
+ .leftJoin("com_ameli", "amd.nomentid", "com_ameli.entid")
29
+ .leftJoin("cab", "amd.nomentid", "cab.entid")
30
+ .select(({ eb, ref, val }) => [
31
+ "ses.ann as session",
32
+ "txt_ameli.doslegsignet as signet_dossier_legislatif",
33
+ "nat.libcourt as nature_texte",
34
+ "txt_ameli.numabs as numero_texte",
35
+ "txt_ameli.int as intitule_texte",
36
+ "lec_ameli.lib as lecture",
37
+ eb.case()
38
+ .when("amd.typ", "=", "A")
39
+ .then(val("Amendement"))
40
+ .when("amd.typ", "=", "M")
41
+ .then(val("Motion"))
42
+ .when("amd.typ", "=", "S")
43
+ .then(val("Sous-amendement"))
44
+ .else("'")
45
+ .end()
46
+ .as("nature"),
47
+ "amd.id as id",
48
+ "amd.amdperid as parent_id",
49
+ "amd.num as numero",
50
+ "amd.numabs as numero_absolu",
51
+ "amd.ord as ordre",
52
+ "sub.lib as subdivision_libelle",
53
+ "sub.lic as subdivision_libelle_court",
54
+ "typsub.lib as subdivision_type",
55
+ "amd.alinea as alinea",
56
+ toDateString(ref("amd.datdep")).as("date_depot"),
57
+ eb.case()
58
+ .when("amd.etaid", "=", 8)
59
+ .then(val("Cet amendement a été retiré avant séance."))
60
+ .else(ref("amd.dis"))
61
+ .end()
62
+ .as("dispositif"),
63
+ "amd.obj as objet",
64
+ "amd.etaid as etat_id",
65
+ "avicom.lib as avis_commission",
66
+ "avigvt.lib as avis_gouvernement",
67
+ eb.fn.coalesce("sor.lib", "irr.libirr").as("sort"),
68
+ "amd.rev as revision",
69
+ concat(val("https://www.senat.fr/amendements/"), ref("ses.lil"), val("/"), ref("txt_ameli.numabs"), val("/Amdt_"), ref("amd.numabs"), val(".html")).as("url"),
70
+ "grppol_ameli.lilcou as au_nom_de_groupe_politique",
71
+ "com_ameli.lil as au_nom_de_commission",
72
+ eb.case()
73
+ .when("cab.entid", "is not", null)
74
+ .then(true)
75
+ .else(false)
76
+ .end()
77
+ .as("auteur_est_gouvernement"),
78
+ ])
79
+ .select(({ ref }) => [
80
+ auteurs(ref("amd.id")).as("auteurs"),
81
+ ]);
82
+ export function findAll() {
83
+ return findAllQuery.stream();
84
+ }
@@ -0,0 +1,100 @@
1
+ import { Expression, InferResult } from "kysely"
2
+ import { jsonArrayFrom } from "kysely/helpers/postgres"
3
+ import { dbAmeli } from "../databases"
4
+ import { concat, toDateString } from "./util"
5
+
6
+ function auteurs (amendementId: Expression<number>) {
7
+ return jsonArrayFrom(
8
+ dbAmeli.selectFrom("amdsen")
9
+ .leftJoin("sen_ameli", "amdsen.senid", "sen_ameli.entid")
10
+ .where("amdsen.amdid", "=", amendementId)
11
+ .select([
12
+ "amdsen.prenomuse as prenom",
13
+ "amdsen.nomuse as nom",
14
+ "sen_ameli.mat as matricule",
15
+ ])
16
+ .orderBy("amdsen.rng asc"),
17
+ )
18
+ }
19
+
20
+ const findAllQuery = dbAmeli
21
+ .selectFrom("amd")
22
+ .leftJoin("sub", "amd.subid", "sub.id")
23
+ .leftJoin("typsub", "sub.typid", "typsub.id")
24
+ .leftJoin("txt_ameli", "amd.txtid", "txt_ameli.id")
25
+ .leftJoin("ses", "txt_ameli.sesdepid", "ses.id")
26
+ .leftJoin("nat", "txt_ameli.natid", "nat.id")
27
+ .leftJoin("lec_ameli", "txt_ameli.lecid", "lec_ameli.id")
28
+ .leftJoin("avicom", "amd.avcid", "avicom.id")
29
+ .leftJoin("avigvt", "amd.avgid", "avigvt.id")
30
+ .leftJoin("sor", "amd.sorid", "sor.id")
31
+ .leftJoin("irr", "amd.irrid", "irr.id")
32
+ .leftJoin("grppol_ameli", "amd.nomentid", "grppol_ameli.entid")
33
+ .leftJoin("com_ameli", "amd.nomentid", "com_ameli.entid")
34
+ .leftJoin("cab", "amd.nomentid", "cab.entid")
35
+ .select(({ eb, ref, val }) => [
36
+ "ses.ann as session",
37
+ "txt_ameli.doslegsignet as signet_dossier_legislatif",
38
+ "nat.libcourt as nature_texte",
39
+ "txt_ameli.numabs as numero_texte",
40
+ "txt_ameli.int as intitule_texte",
41
+ "lec_ameli.lib as lecture",
42
+ eb.case()
43
+ .when("amd.typ", "=", "A")
44
+ .then(val("Amendement"))
45
+ .when("amd.typ", "=", "M")
46
+ .then(val("Motion"))
47
+ .when("amd.typ", "=", "S")
48
+ .then(val("Sous-amendement"))
49
+ .else("'")
50
+ .end()
51
+ .as("nature"),
52
+ "amd.id as id",
53
+ "amd.amdperid as parent_id",
54
+ "amd.num as numero",
55
+ "amd.numabs as numero_absolu",
56
+ "amd.ord as ordre",
57
+ "sub.lib as subdivision_libelle",
58
+ "sub.lic as subdivision_libelle_court",
59
+ "typsub.lib as subdivision_type",
60
+ "amd.alinea as alinea",
61
+ toDateString(ref("amd.datdep")).as("date_depot"),
62
+ eb.case()
63
+ .when("amd.etaid", "=", 8)
64
+ .then(val("Cet amendement a été retiré avant séance."))
65
+ .else(ref("amd.dis"))
66
+ .end()
67
+ .as("dispositif"),
68
+ "amd.obj as objet",
69
+ "amd.etaid as etat_id",
70
+ "avicom.lib as avis_commission",
71
+ "avigvt.lib as avis_gouvernement",
72
+ eb.fn.coalesce("sor.lib", "irr.libirr").as("sort"),
73
+ "amd.rev as revision",
74
+ concat(
75
+ val("https://www.senat.fr/amendements/"),
76
+ ref("ses.lil"),
77
+ val("/"),
78
+ ref("txt_ameli.numabs"),
79
+ val("/Amdt_"),
80
+ ref("amd.numabs"),
81
+ val(".html")
82
+ ).as("url"),
83
+ "grppol_ameli.lilcou as au_nom_de_groupe_politique",
84
+ "com_ameli.lil as au_nom_de_commission",
85
+ eb.case()
86
+ .when("cab.entid", "is not", null)
87
+ .then(true)
88
+ .else(false)
89
+ .end()
90
+ .as("auteur_est_gouvernement"),
91
+ ])
92
+ .select(({ ref }) => [
93
+ auteurs(ref("amd.id")).as("auteurs"),
94
+ ])
95
+
96
+ export type AmendementResult = InferResult<typeof findAllQuery>[0]
97
+
98
+ export function findAll () {
99
+ return findAllQuery.stream()
100
+ }
@@ -0,0 +1,18 @@
1
+ import * as cheerio from "cheerio";
2
+ import { CompteRendu } from "../types/compte_rendu";
3
+ import { Reunion } from "../types/agenda";
4
+ export declare function getRemainingTextAfterSpeakerHeader($: cheerio.CheerioAPI, $p: cheerio.Cheerio<any>): string;
5
+ export type DaySection = {
6
+ title: string;
7
+ $start: cheerio.Cheerio<any>;
8
+ time?: string;
9
+ };
10
+ export declare function cleanTitle(t: string): string;
11
+ export declare function extractDayH3Sections($: cheerio.CheerioAPI, dateISO: string): DaySection[];
12
+ export declare function parseCommissionCRSectionFromDom($: cheerio.CheerioAPI, htmlFilePath: string, opts: {
13
+ dateISO: string;
14
+ hourShort: string | null;
15
+ organe?: string | null;
16
+ section: DaySection;
17
+ matched?: Reunion;
18
+ }): CompteRendu | null;
@@ -0,0 +1,269 @@
1
+ import * as cheerio from "cheerio";
2
+ import path from "path";
3
+ import { makeReunionUid } from "../utils/reunion_parsing";
4
+ import { norm } from "../utils/string_cleaning";
5
+ import { frDateToISO, hourShortToStartTime } from "../utils/date";
6
+ import { toCRDate } from "./util";
7
+ const PARA_h3_SEL = "p.sh_justify, p.sh_center, p.sh_marge, p[align], li, h3";
8
+ function findDayRoot($, targetISO) {
9
+ let $root = $();
10
+ $("h2").each((_, el) => {
11
+ const txt = norm($(el).text());
12
+ const m = txt.match(/(?:Lundi|Mardi|Mercredi|Jeudi|Vendredi|Samedi|Dimanche)\s+(.+)$/i);
13
+ const iso = m ? frDateToISO(m[1]) : undefined;
14
+ if (iso === targetISO && $root.length === 0)
15
+ $root = $(el);
16
+ });
17
+ return $root;
18
+ }
19
+ function normalizeSpaces(s) {
20
+ return s.replace(/[\u00A0\u202F\u2009]/g, " ");
21
+ }
22
+ function stripIntroPunct(s) {
23
+ return s.replace(/^[\s]*[.:;]?\s*(?:[–—-]\s*)+/u, "");
24
+ }
25
+ function collectLeadingHeaderStrongEls($, $clone) {
26
+ const els = [];
27
+ const nodes = $clone.contents().toArray();
28
+ for (const node of nodes) {
29
+ if (node.type === "text") {
30
+ if (norm(node.data || ""))
31
+ break;
32
+ continue;
33
+ }
34
+ if (node.type === "tag") {
35
+ const $n = $(node);
36
+ if ($n.is("strong, b")) {
37
+ els.push(node);
38
+ continue;
39
+ }
40
+ if ($n.is("a") && $n.children("strong, b").length) {
41
+ $n.children("strong, b").each((_, el) => {
42
+ els.push($(el));
43
+ });
44
+ continue;
45
+ }
46
+ break;
47
+ }
48
+ }
49
+ return els;
50
+ }
51
+ // Remove orateur's name from text and clean intro punct
52
+ export function getRemainingTextAfterSpeakerHeader($, $p) {
53
+ const $clone = $p.clone();
54
+ // 1) Remove <strong> at start
55
+ const headerStrongEls = collectLeadingHeaderStrongEls($, $clone);
56
+ for (const el of headerStrongEls)
57
+ $(el).remove();
58
+ // 2) normalize + clean intro punct
59
+ let remainingHtml = $clone.html() || "";
60
+ remainingHtml = normalizeSpaces(cheerio.load(remainingHtml).text());
61
+ remainingHtml = stripIntroPunct(remainingHtml);
62
+ const remainingText = norm(remainingHtml || "");
63
+ return remainingText;
64
+ }
65
+ function buildPointsFromParagraphs($, paras) {
66
+ const points = [];
67
+ let ordreAbsoluSeance = 0;
68
+ const normSpeaker = (s) => s
69
+ .normalize("NFKC")
70
+ .replace(/\s+/g, " ")
71
+ .replace(/[:\.]\s*$/, "")
72
+ .trim();
73
+ const normQual = (s) => s
74
+ .normalize("NFKC")
75
+ .replace(/\s+/g, " ")
76
+ .replace(/^\s*,\s*|\s+$/g, "")
77
+ .replace(/[\s\u00A0]*[.,;:–—-]+$/u, "")
78
+ .trim();
79
+ let currentOrateur = null;
80
+ let currentQualite = "";
81
+ let currentTexte = "";
82
+ function isPresidentQual(qual) {
83
+ return /\bprésident(e)?\b/i.test(qual);
84
+ }
85
+ // Flush the buffered speaker’s text into points[] if any.
86
+ function flush() {
87
+ if (!currentOrateur || !currentTexte.trim())
88
+ return;
89
+ ordreAbsoluSeance++;
90
+ points.push({
91
+ code_grammaire: "PAROLE_GENERIQUE",
92
+ roledebat: isPresidentQual(currentQualite) ? "président" : "",
93
+ ordre_absolu_seance: String(ordreAbsoluSeance),
94
+ orateurs: { orateur: { nom: currentOrateur, id: "", qualite: currentQualite || "" } },
95
+ texte: { _: currentTexte.trim() },
96
+ });
97
+ currentOrateur = null;
98
+ currentQualite = "";
99
+ currentTexte = "";
100
+ }
101
+ function addPoint(payload) {
102
+ ordreAbsoluSeance++;
103
+ points.push({ ...payload, ordre_absolu_seance: String(ordreAbsoluSeance) });
104
+ }
105
+ for (const $p of paras) {
106
+ if ($p.closest("table").length)
107
+ continue;
108
+ const tagName = ($p.prop("tagName") || "").toString().toLowerCase();
109
+ const rawText = ($p.text() || "").replace(/\u00a0/g, " ").trim();
110
+ const text = norm(rawText);
111
+ if (!text || text.length <= 3)
112
+ continue;
113
+ const html = ($p.html() || "").trim();
114
+ const italicSpans = $p.find("i, em, span[style*='italic']");
115
+ const firstItalicOuter = italicSpans.length ? $(italicSpans[0]).prop("outerHTML") || "" : "";
116
+ const htmlBeforeFirstItalic = firstItalicOuter ? html.split(firstItalicOuter)[0].trim() : "";
117
+ const isPureItalic = italicSpans.length > 0 && italicSpans.length === $p.find("span,i,em").length && htmlBeforeFirstItalic === "";
118
+ if (tagName === "h3") {
119
+ flush();
120
+ addPoint({
121
+ code_style: "Titre",
122
+ code_grammaire: "TITRE_TEXTE_DISCUSSION",
123
+ texte: { _: text },
124
+ });
125
+ continue;
126
+ }
127
+ const boldSpans = $p.find("strong, b");
128
+ const joinedBold = norm(boldSpans
129
+ .map((_, el) => $(el).text() || "")
130
+ .get()
131
+ .join(""));
132
+ const [namePartRaw, qualPartRaw] = joinedBold.split(/\s*,\s+/, 2);
133
+ const namePart = namePartRaw ? normSpeaker(namePartRaw) : "";
134
+ const qualPart = qualPartRaw ? normQual(qualPartRaw) : "";
135
+ const looksLikeName = namePart.length > 3 && /^(M\.|Mme)[\s\u00A0\u202F]+/i.test(namePart);
136
+ const startsWithName = namePart && text.startsWith(namePart);
137
+ const isNewSpeaker = looksLikeName && startsWithName && namePart !== currentOrateur;
138
+ if (isNewSpeaker) {
139
+ flush();
140
+ currentOrateur = namePart;
141
+ currentQualite = qualPart;
142
+ const remainingText = getRemainingTextAfterSpeakerHeader($, $p);
143
+ currentTexte = remainingText;
144
+ continue;
145
+ }
146
+ if (isPureItalic || (!joinedBold && !currentOrateur && text)) {
147
+ flush();
148
+ addPoint({
149
+ code_style: "Info Italiques",
150
+ code_grammaire: "PAROLE_GENERIQUE",
151
+ texte: { _: "<i>" + text + "</i>" },
152
+ });
153
+ continue;
154
+ }
155
+ // concat text because same orateur
156
+ if (currentOrateur) {
157
+ const removeOrateurFromText = getRemainingTextAfterSpeakerHeader($, $p);
158
+ currentTexte += (currentTexte ? "<br/><br/>" : "") + removeOrateurFromText;
159
+ continue;
160
+ }
161
+ }
162
+ flush();
163
+ return points;
164
+ }
165
+ const TIME_RE = /(?:\b[àa]\s*)?(\d{1,2})\s*(?:h|heures?)\s*(?:([0-5]\d))?/i;
166
+ export function cleanTitle(t) {
167
+ return (t || "").replace(/\s+/g, " ").trim();
168
+ }
169
+ function parseTimeToHHmm(text) {
170
+ const m = normalizeSpaces(text).match(TIME_RE);
171
+ if (!m)
172
+ return undefined;
173
+ const hh = m[1]?.padStart(2, "0");
174
+ const mm = (m[2] ?? "00").padStart(2, "0");
175
+ const h = Number(hh);
176
+ if (h >= 0 && h <= 23)
177
+ return `${hh}:${mm}`;
178
+ return undefined;
179
+ }
180
+ function findNearbyTime($, $h3) {
181
+ let cur = $h3.prev();
182
+ for (let i = 0; i < 3 && cur.length; i++, cur = cur.prev()) {
183
+ const direct = parseTimeToHHmm(cur.text());
184
+ if (direct)
185
+ return direct;
186
+ const italic = parseTimeToHHmm(cur.find("i, em").first().text());
187
+ if (italic)
188
+ return italic;
189
+ }
190
+ return undefined;
191
+ }
192
+ export function extractDayH3Sections($, dateISO) {
193
+ const sections = [];
194
+ const $dayRoot = findDayRoot($, dateISO);
195
+ if ($dayRoot.length === 0)
196
+ return sections;
197
+ const $range = $dayRoot.nextUntil("h2");
198
+ const $h3s = $range.filter("h3").add($range.find("h3"));
199
+ $h3s.each((_, el) => {
200
+ const $h3 = $(el);
201
+ const title = cleanTitle($h3.text());
202
+ if (!title)
203
+ return;
204
+ const time = findNearbyTime($, $h3);
205
+ sections.push({ title, $start: $h3, time });
206
+ });
207
+ return sections;
208
+ }
209
+ export function parseCommissionCRSectionFromDom($, htmlFilePath, opts) {
210
+ try {
211
+ const { dateISO, hourShort, organe, section, matched } = opts;
212
+ const seanceRef = matched?.uid ?? makeReunionUid(dateISO, "COM", matched?.events[0].id ?? hourShort ?? "", organe ?? undefined);
213
+ const uid = seanceRef.replace(/^RU/, "CRC");
214
+ const dateSeance = toCRDate(dateISO, matched?.startTime ?? hourShortToStartTime(hourShort));
215
+ const $dayRoot = findDayRoot($, dateISO);
216
+ if ($dayRoot.length === 0) {
217
+ console.warn(`[COM-CR][parse] day root not found for ${dateISO} in ${path.basename(htmlFilePath)}`);
218
+ return null;
219
+ }
220
+ const paras = [];
221
+ let $cursor = section.$start;
222
+ // Jump title if we do not want to add it to paragraphes
223
+ $cursor = $cursor.next();
224
+ while ($cursor.length && !$cursor.is("h2") && !$cursor.is("h3")) {
225
+ if ($cursor.is(PARA_h3_SEL)) {
226
+ paras.push($cursor);
227
+ }
228
+ else {
229
+ const $ps = $cursor.find(PARA_h3_SEL);
230
+ if ($ps.length)
231
+ $ps.each((_, p) => {
232
+ paras.push($(p));
233
+ });
234
+ }
235
+ $cursor = $cursor.next();
236
+ }
237
+ const points = buildPointsFromParagraphs($, paras);
238
+ if (points.length < 4 || !points.some((pt) => pt.code_grammaire === "PAROLE_GENERIQUE" && pt.orateurs)) {
239
+ console.warn(`[COM-CR][parse] Insufficient points or no interventions found for a section in ${path.basename(htmlFilePath)}`);
240
+ return null;
241
+ }
242
+ const session = dateISO.slice(5, 7) >= "10" ? `${dateISO.slice(0, 4)}` : `${Number(dateISO.slice(0, 4)) - 1}`;
243
+ const contenu = {
244
+ quantiemes: { journee: dateISO, session },
245
+ point: points,
246
+ };
247
+ const metadonnees = {
248
+ dateSeance,
249
+ dateSeanceJour: dateISO,
250
+ numSeanceJour: "",
251
+ numSeance: "",
252
+ typeAssemblee: "SN",
253
+ legislature: "",
254
+ session,
255
+ nomFichierJo: path.basename(htmlFilePath),
256
+ validite: "non-certifie",
257
+ etat: "definitif",
258
+ diffusion: "publique",
259
+ version: "1",
260
+ environnement: "prod",
261
+ heureGeneration: new Date(),
262
+ };
263
+ return { uid, seanceRef, sessionRef: session, metadonnees, contenu };
264
+ }
265
+ catch (e) {
266
+ console.error(`[COM-CR][parse] error section file=${path.basename(htmlFilePath)}:`, e);
267
+ return null;
268
+ }
269
+ }
@@ -0,0 +1,67 @@
1
+ import { InferResult } from "kysely";
2
+ export type DebatResult = InferResult<typeof findAllQuery>[0];
3
+ declare const findAllQuery: import("kysely").SelectQueryBuilder<any, "debats.debats", {
4
+ [x: string]: any;
5
+ id: string;
6
+ date_seance: string;
7
+ sections: {
8
+ [x: string]: any;
9
+ interventions: {
10
+ [x: string]: any;
11
+ auteur: {
12
+ code: any;
13
+ nom: any;
14
+ prenom: any;
15
+ matricule: any;
16
+ };
17
+ }[];
18
+ }[];
19
+ sections_divers: {
20
+ [x: string]: any;
21
+ interventions: {
22
+ [x: string]: any;
23
+ auteur: {
24
+ code: any;
25
+ nom: any;
26
+ prenom: any;
27
+ matricule: any;
28
+ };
29
+ }[];
30
+ }[];
31
+ lectures: {
32
+ id: any;
33
+ }[];
34
+ }>;
35
+ export declare function findAll(fromSession?: number): AsyncIterableIterator<{
36
+ [x: string]: any;
37
+ id: string;
38
+ date_seance: string;
39
+ sections: {
40
+ [x: string]: any;
41
+ interventions: {
42
+ [x: string]: any;
43
+ auteur: {
44
+ code: any;
45
+ nom: any;
46
+ prenom: any;
47
+ matricule: any;
48
+ };
49
+ }[];
50
+ }[];
51
+ sections_divers: {
52
+ [x: string]: any;
53
+ interventions: {
54
+ [x: string]: any;
55
+ auteur: {
56
+ code: any;
57
+ nom: any;
58
+ prenom: any;
59
+ matricule: any;
60
+ };
61
+ }[];
62
+ }[];
63
+ lectures: {
64
+ id: any;
65
+ }[];
66
+ }>;
67
+ export {};
@@ -0,0 +1,95 @@
1
+ import { jsonArrayFrom, jsonBuildObject } from "kysely/helpers/postgres";
2
+ import { dbSenat } from "../databases";
3
+ import { ID_DATE_FORMAT } from "../scripts/datautil";
4
+ import { toDateString } from "./util";
5
+ function sectionsLegislatives(dateSeance) {
6
+ return jsonArrayFrom(dbSenat
7
+ .selectFrom("debats.secdis")
8
+ .leftJoin("debats.typsec", "debats.secdis.typseccod", "debats.typsec.typseccod")
9
+ .where("debats.secdis.datsea", "=", dateSeance)
10
+ .select(({ ref }) => [
11
+ "debats.secdis.secdisordid as id",
12
+ "debats.secdis.secdisnum as numero",
13
+ "debats.secdis.secdisobj as objet",
14
+ "debats.secdis.secdisurl as url",
15
+ "debats.typsec.typseclib as type",
16
+ "debats.typsec.typseccat as categorie",
17
+ interventionsLegislatives(ref("debats.secdis.secdiscle")).as("interventions"),
18
+ "debats.secdis.lecassidt as lecture_id",
19
+ ])
20
+ .orderBy("debats.secdis.secdisordid", "asc"));
21
+ }
22
+ function interventionsLegislatives(sectionId) {
23
+ return jsonArrayFrom(dbSenat
24
+ .selectFrom("debats.intpjl")
25
+ .leftJoin("dosleg.auteur", "debats.intpjl.autcod", "dosleg.auteur.autcod")
26
+ .where("debats.intpjl.secdiscle", "=", sectionId)
27
+ .select(({ ref, val, fn }) => [
28
+ "debats.intpjl.intordid as id",
29
+ "debats.intpjl.autcod as auteur_code",
30
+ "debats.intpjl.intfon as fonction_intervenant",
31
+ "debats.intpjl.inturl as url",
32
+ "debats.intpjl.intana as analyse",
33
+ jsonBuildObject({
34
+ code: ref("dosleg.auteur.autcod"),
35
+ nom: ref("dosleg.auteur.nomuse"),
36
+ prenom: ref("dosleg.auteur.prenom"),
37
+ matricule: ref("dosleg.auteur.autmat"),
38
+ }).as("auteur"),
39
+ ])
40
+ .orderBy("debats.intpjl.intordid", "asc"));
41
+ }
42
+ function sectionsNonLegislatives(dateSeance) {
43
+ return jsonArrayFrom(dbSenat
44
+ .selectFrom("debats.secdivers")
45
+ .leftJoin("debats.typsec", "debats.secdivers.typseccod", "debats.typsec.typseccod")
46
+ .where("debats.secdivers.datsea", "=", dateSeance)
47
+ .select(({ ref }) => [
48
+ "debats.secdivers.secdiverslibelle as libelle",
49
+ "debats.secdivers.secdiversobj as objet",
50
+ "debats.typsec.typseclib as type",
51
+ "debats.typsec.typseccat as categorie",
52
+ interventionsNonLegislatives(ref("debats.secdivers.secdiverscle")).as("interventions"),
53
+ ]));
54
+ }
55
+ function interventionsNonLegislatives(sectionId) {
56
+ return jsonArrayFrom(dbSenat
57
+ .selectFrom("debats.intdivers")
58
+ .leftJoin("dosleg.auteur", "debats.intdivers.autcod", "dosleg.auteur.autcod")
59
+ .where("debats.intdivers.intdiverscle", "=", sectionId)
60
+ .select(({ ref, val }) => [
61
+ "debats.intdivers.intdiversordid as id",
62
+ "debats.intdivers.autcod as auteur_code",
63
+ "debats.intdivers.intfon as fonction_intervenant",
64
+ "debats.intdivers.inturl as url",
65
+ "debats.intdivers.intana as analyse",
66
+ jsonBuildObject({
67
+ code: ref("dosleg.auteur.autcod"),
68
+ nom: ref("dosleg.auteur.nomuse"),
69
+ prenom: ref("dosleg.auteur.prenom"),
70
+ matricule: ref("dosleg.auteur.autmat"),
71
+ }).as("auteur"),
72
+ ])
73
+ .orderBy("debats.intdivers.intdiversordid", "asc"));
74
+ }
75
+ function lecturesAssemblee(dateSeance) {
76
+ return jsonArrayFrom(dbSenat
77
+ .selectFrom("debats.lecassdeb")
78
+ .where("debats.lecassdeb.datsea", "=", dateSeance)
79
+ .select("debats.lecassdeb.lecassidt as id"));
80
+ }
81
+ const findAllQuery = dbSenat
82
+ .selectFrom("debats.debats")
83
+ .select(({ ref, val }) => [
84
+ toDateString(ref("debats.debats.datsea"), val(ID_DATE_FORMAT)).as("id"),
85
+ toDateString(ref("debats.debats.datsea")).as("date_seance"),
86
+ "debats.debats.numero as numero",
87
+ "debats.debats.deburl as url",
88
+ "debats.debats.debsyn as etat_synchronisation",
89
+ sectionsLegislatives(ref("debats.debats.datsea")).as("sections"),
90
+ sectionsNonLegislatives(ref("debats.debats.datsea")).as("sections_divers"),
91
+ lecturesAssemblee(ref("debats.debats.datsea")).as("lectures"),
92
+ ]);
93
+ export function findAll(fromSession) {
94
+ return findAllQuery.stream();
95
+ }
@@ -0,0 +1,43 @@
1
+ import { debatsFieldsToTrim, lecassdebFieldsToTrim, } from "../types/debats";
2
+ import { dbByName } from "../databases";
3
+ import { trimFieldsRight } from "../fields";
4
+ export const getDebats = async (ids) => {
5
+ if (ids.length === 0) {
6
+ return [];
7
+ }
8
+ return (await dbByName.debats.any(`
9
+ SELECT *
10
+ FROM debats
11
+ WHERE datsea IN ($<ids:list>)
12
+ `, {
13
+ ids,
14
+ })).map((debat) => trimFieldsRight(debatsFieldsToTrim, debat));
15
+ };
16
+ export const getDebatsFromLecassidts = async (ids) => {
17
+ if (ids.length === 0) {
18
+ return [];
19
+ }
20
+ return (await dbByName.debats.any(`
21
+ SELECT *
22
+ FROM debats
23
+ WHERE datsea IN (
24
+ SELECT datsea
25
+ FROM lecassdeb
26
+ WHERE lecassidt IN ($<ids:list>)
27
+ )
28
+ `, {
29
+ ids,
30
+ })).map((debat) => trimFieldsRight(debatsFieldsToTrim, debat));
31
+ };
32
+ export const getLecAssDebsFromDatseas = async (ids) => {
33
+ if (ids.length === 0) {
34
+ return [];
35
+ }
36
+ return (await dbByName.debats.any(`
37
+ SELECT *
38
+ FROM lecassdeb
39
+ WHERE datsea IN ($<ids:list>)
40
+ `, {
41
+ ids,
42
+ })).map((lecassdeb) => trimFieldsRight(lecassdebFieldsToTrim, lecassdeb));
43
+ };