nsarchive 0.1b3__tar.gz → 1.0.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nsarchive
3
- Version: 0.1b3
3
+ Version: 1.0.0
4
4
  Summary:
5
5
  License: GPL-3.0
6
6
  Author: happex
@@ -0,0 +1,700 @@
1
+ import time
2
+
3
+ import deta
4
+
5
+ from .cls.base import *
6
+ from .cls.entities import *
7
+ from .cls.archives import *
8
+ from .cls.republic import *
9
+ from .cls.economy import *
10
+
11
+ from .cls.exceptions import *
12
+
13
+ class EntityInstance:
14
+ """
15
+ Instance qui vous permettra d'interagir avec les profils des membres ainsi que les différents métiers et secteurs d'activité.
16
+
17
+ ## Informations disponibles
18
+ - Profil des membres et des entreprises: `.User | .Organization | .Entity`
19
+ - Participation d'un membre à différent votes: `.User | .Organization | .Entity`
20
+ - Appartenance et permissions d'un membre dans un groupe: `.GroupMember.MemberPermissions`
21
+ - Position légale et permissions d'une entité: `.Position.Permissions`
22
+ - Sanctions et modifications d'une entité: `.Action[ .AdminAction | .Sanction ]`
23
+ """
24
+ def __init__(self, token: str) -> None:
25
+ self.db = deta.Deta(token)
26
+ self.base = self.db.Base('entities')
27
+ self.electors = self.db.Base('electors')
28
+ self.archives = self.db.Base('archives')
29
+ self.avatars = self.db.Drive('avatars')
30
+ self.positions = self.db.Base('positions') # Liste des métiers
31
+
32
+ def get_entity(self, id: str | NSID) -> User | Organization | Entity:
33
+ """
34
+ Fonction permettant de récupérer le profil public d'une entité.\n
35
+
36
+ ## Paramètres
37
+ id: `NSID`\n
38
+ ID héxadécimal de l'entité à récupérer
39
+
40
+ ## Renvoie
41
+ - `.User` dans le cas où l'entité choisie est un membre
42
+ - `.Organization` dans le cas où c'est un groupe
43
+ - `.Entity` dans le cas où c'est indéterminé
44
+ """
45
+
46
+ id = NSID(id)
47
+ _data = self.base.get(id)
48
+ _votes = self.electors.get(id)
49
+
50
+ if _data is None:
51
+ return Entity("0")
52
+
53
+ if _data['_type'] == 'user':
54
+ entity = User(id)
55
+
56
+ entity.xp = _data['xp']
57
+ entity.boosts = _data['boosts']
58
+ entity.votes = [ NSID(vote) for vote in _votes['votes'] ]
59
+ elif _data['_type'] == 'organization':
60
+ entity = Organization(id)
61
+
62
+ entity.owner = self.get_entity(NSID(_data['owner_id']))
63
+
64
+ for _member in _data['members']:
65
+ member = GroupMember(_member['id'])
66
+ member.permissions.__dict__ = _member['permissions']
67
+
68
+ try:
69
+ entity.avatar = self.avatars.get(id).read()
70
+ except:
71
+ entity.avatar = None
72
+
73
+ entity.certifications = _data['certifications']
74
+ else:
75
+ entity = Entity(id)
76
+
77
+ entity.name = _data['name']
78
+ entity.legalPosition = _data['legalPosition'] # Métier si c'est un utilisateur, domaine professionnel si c'est un collectif
79
+ entity.registerDate = _data['registerDate']
80
+
81
+ return entity
82
+
83
+ def save_entity(self, entity: Entity) -> None:
84
+ """
85
+ Fonction permettant de créer ou modifier une entité.
86
+
87
+ ## Paramètres
88
+ entity: `.Entity` ( `.User | .Organization` )
89
+ L'entité à sauvegarder
90
+ """
91
+
92
+ entity.id = NSID(entity.id)
93
+
94
+ _base = self.base
95
+ _data = {
96
+ '_type': 'user' if type(entity) == User else 'organization' if type(entity) == Organization else 'unknown',
97
+ 'name': entity.name,
98
+ 'legalPosition': entity.legalPosition,
99
+ 'registerDate': entity.registerDate
100
+ }
101
+
102
+ if type(entity) == Organization:
103
+ _data['owner_id'] = NSID(entity.owner.id) if entity.owner else NSID("0")
104
+ _data['members'] = []
105
+ _data['certifications'] = entity.certifications
106
+
107
+ for member in entity.members:
108
+ _member = {
109
+ 'id': NSID(member.id),
110
+ 'permissions': member.permissions.__dict__.copy()
111
+ }
112
+
113
+ _data['members'] += _member
114
+
115
+ self.avatars.put(name = entity.id, data = entity.avatar)
116
+ elif type(entity) == User:
117
+ _data['xp'] = entity.xp
118
+ _data['boosts'] = entity.boosts
119
+
120
+ _base.put(_data, entity.id, expire_in = 3 * 31536000) # Données supprimées tous les trois ans
121
+
122
+ def delete_entity(self, entity: Entity) -> None:
123
+ """
124
+ Fonction permettant de supprimer le profil d'une entité
125
+
126
+ ## Paramètres
127
+ entity: `.Entity` ( `.User | .Organization` )
128
+ L'entité à supprimer
129
+ """
130
+
131
+ self.base.delete(NSID(entity.id))
132
+
133
+ if type(entity) == Organization:
134
+ self.avatars.delete(NSID(entity.id))
135
+
136
+ def fetch_entities(self, query: dict = None, listquery: dict | None = None) -> list[ Entity | User | Organization ]:
137
+ """
138
+ Récupère une liste d'entités en fonction d'une requête.
139
+
140
+ ## Paramètres
141
+ query: `dict`
142
+ La requête pour filtrer les entités.
143
+ listquery: `dict | None`
144
+ Requête secondaire pour n'afficher que les listes contenant un certain élément.
145
+
146
+ ## Renvoie
147
+ - `list[Entity | User | Organization]`
148
+ """
149
+ _res = self.base.fetch(query).items
150
+
151
+ if listquery is not None:
152
+ for item in _res:
153
+ for target, value in listquery.items():
154
+ if value not in item[target]:
155
+ _res.remove(item)
156
+
157
+ return [ self.get_entity(NSID(entity['key'])) for entity in _res ]
158
+
159
+ def get_entity_groups(self, id: str | NSID) -> list[Organization]:
160
+ """
161
+ Récupère les groupes auxquels appartient une entité.
162
+
163
+ ## Paramètres
164
+ id: `str | NSID`
165
+ ID de l'entité.
166
+
167
+ ## Renvoie
168
+ - `list[Organization]`
169
+ """
170
+
171
+ id = NSID(id)
172
+ groups = self.fetch_entities({'_type': 'organization'}, {'members': id})
173
+
174
+ return groups
175
+
176
+ def get_position(self, id: str) -> Position:
177
+ """
178
+ Récupère une position légale (métier, domaine professionnel).
179
+
180
+ ## Paramètres
181
+ id: `str`
182
+ ID de la position (SENSIBLE À LA CASSE !)
183
+
184
+ ## Renvoie
185
+ - `.Position`
186
+ """
187
+
188
+ _data = self.positions.get(id)
189
+
190
+ if _data is None:
191
+ raise RessourceNotFoundError(f"No position with ID {id}")
192
+
193
+ position = Position(id)
194
+ position.name = _data['name']
195
+
196
+ for _permission in _data['permissions']:
197
+ position.permissions.__setattr__(_permission, True)
198
+
199
+ return position
200
+
201
+ def _add_archive(self, archive: Action) -> None:
202
+ """
203
+ Ajoute une archive d'une action (modification au sein d'un groupe ou sanction) dans la base de données.
204
+ """
205
+
206
+ archive.id = NSID(archive.id)
207
+ archive.author = NSID(archive.author)
208
+ archive.target = NSID(archive.target)
209
+
210
+ _data = archive.__dict__.copy()
211
+
212
+ if type(archive) == Sanction:
213
+ _data['type'] = "sanction"
214
+ elif type(archive) == AdminAction:
215
+ _data['type'] = "adminaction"
216
+ else:
217
+ _data['type'] = "unknown"
218
+
219
+ self.archives.put(key = archive.id, data = _data)
220
+
221
+ def _get_archive(self, id: str | NSID) -> Action | Sanction | AdminAction:
222
+ """
223
+ Récupère une archive spécifique.
224
+
225
+ ## Paramètres
226
+ id: `str | NSID`
227
+ ID de l'archive.
228
+
229
+ ## Renvoie
230
+ - `.Action | .Sanction | .AdminAction`
231
+ """
232
+
233
+ id = NSID(id)
234
+ _data = self.archives.get(id)
235
+
236
+ if _data is None:
237
+ return None
238
+
239
+ if _data['type'] == "sanction": # Mute, ban, GAV, kick, détention, prune (xp seulement)
240
+ archive = Sanction(_data['author'], _data['target'])
241
+
242
+ archive.details = _data['details']
243
+ archive.major = _data['major']
244
+ archive.duration = _data['duration']
245
+ elif _data['type'] == "adminaction": # Renommage, promotion, démotion (au niveau de l'état)
246
+ archive = AdminAction(_data['author'], _data['target'])
247
+
248
+ archive.details = _data['details']
249
+ archive.new_state = _data['new_state']
250
+ else:
251
+ archive = Action(_data['author'], _data['target'])
252
+
253
+ archive.id = id
254
+ archive.action = _data['action']
255
+ archive.date = _data['date']
256
+
257
+ return archive
258
+
259
+ def _fetch_archives(self, **query) -> list[ Action | Sanction | AdminAction ]:
260
+ """
261
+ Récupère une liste d'archives correspondant à la requête.
262
+
263
+ ## Paramètres
264
+ query: `dict`
265
+ Requête pour filtrer les archives.
266
+
267
+ ## Renvoie
268
+ - `list[Action | Sanction | AdminAction]`
269
+ """
270
+
271
+ _res = self.archives.fetch(query).items
272
+
273
+ return [ self._get_archive(archive['key']) for archive in _res ]
274
+
275
+ class RepublicInstance:
276
+ """
277
+ Gère les interactions avec les votes, les archives de la république, et les fonctionnaires.
278
+
279
+ ## Informations
280
+ - Résultats des votes: `.Vote | .ClosedVote`
281
+ - Différentes institutions: `.Institutions | .Administration | .Government | .Assembly | .Court | .PoliceForces`
282
+ - Occupants des différents rôles et historique de leurs actions: `.Official`
283
+ """
284
+
285
+ def __init__(self, token: str) -> None:
286
+ """Initialise une nouvelle RepublicInstance avec un token Deta."""
287
+
288
+ self.db = deta.Deta(token)
289
+ self.votes = self.db.Base('votes')
290
+ self.archives = self.db.Base('archives')
291
+ self.mandate = self.db.Base('mandate')
292
+ self.functions = self.db.Base('functions') # Liste des fonctionnaires
293
+
294
+ def get_vote(self, id: str | NSID) -> Vote | ClosedVote:
295
+ """
296
+ Récupère un vote spécifique.
297
+
298
+ ## Paramètres
299
+ id: `str | NSID`
300
+ ID du vote.
301
+
302
+ ## Renvoie
303
+ - `.Vote | .ClosedVote`
304
+ """
305
+
306
+ id = NSID(id)
307
+ _data = self.votes.get(id)
308
+
309
+ if _data is None:
310
+ raise RessourceNotFoundError(f"The vote #{id} does not exist.")
311
+
312
+ if _data['_type'] == 'open':
313
+ vote = Vote(id, _data['title'], tuple(_data['choices'].keys()))
314
+ elif _data['_type'] == 'closed':
315
+ vote = ClosedVote(id, _data['title'])
316
+ else:
317
+ vote = Vote('0', 'Unknown Vote', ())
318
+
319
+ vote.author = _data['author']
320
+ vote.startDate = _data['startDate']
321
+ vote.endDate = _data['endDate']
322
+ vote.choices = _data['choices']
323
+
324
+ return vote
325
+
326
+ def save_vote(self, vote: Vote | ClosedVote) -> None:
327
+ """Sauvegarde un vote dans la base de données."""
328
+
329
+ vote.id = NSID(vote.id)
330
+
331
+ _data = {
332
+ '_type': 'open' if type(vote) == Vote else 'closed' if type(vote) == ClosedVote else 'unknown',
333
+ 'title': vote.title,
334
+ 'author': NSID(vote.author),
335
+ 'startDate': vote.startDate,
336
+ 'endDate': vote.endDate,
337
+ 'choices': vote.choices
338
+ }
339
+
340
+ self.votes.put(_data, vote.id)
341
+
342
+ def get_official(self, id: str | NSID, current_mandate: bool = True) -> Official:
343
+ """
344
+ Récupère les informations d'un fonctionnaire (mandats, contributions).
345
+
346
+ ## Paramètres
347
+ id: `str | NSID`
348
+ ID du fonctionnaire.
349
+ current_mandate: `bool`
350
+ Indique si l'on doit récupérer le mandat actuel ou les anciens mandats.
351
+
352
+ ## Renvoie
353
+ - `.Official`
354
+ """
355
+
356
+ id = NSID(id)
357
+
358
+ archives = self.mandate if current_mandate else self.archives
359
+
360
+ _contributions = archives.fetch({'author': id, 'type': 'contrib'}).items
361
+ _mandates = archives.fetch({'target': id, 'type': 'election'}).items\
362
+ + archives.fetch({'target': id, 'type': 'promotion'}).items
363
+
364
+ user = Official(id)
365
+ for mandate in _mandates:
366
+ if mandate['position'].startswith('MIN'):
367
+ mandate['position'] = 'MIN'
368
+
369
+ try:
370
+ user.mandates[mandate['position']] += 1
371
+ except KeyError:
372
+ user.mandates[mandate['position']] = 1
373
+
374
+ for contrib in _contributions:
375
+ try:
376
+ user.contributions[contrib['action']] += 1
377
+ except KeyError:
378
+ user.contributions[contrib['action']] = 1
379
+
380
+ return user
381
+
382
+ def get_institutions(self) -> Organization:
383
+ """Récupère l'état actuel des institutions de la république."""
384
+
385
+ admin = Administration()
386
+ gov = Government(Official('0'))
387
+ assembly = Assembly()
388
+ court = Court()
389
+ police_forces = PoliceForces()
390
+
391
+ _admins = self.functions.get('ADMIN')
392
+ admin.members = [ self.get_official(user) for user in _admins['users'] ]
393
+ admin.president = self.get_official('F7DB60DD1C4300A') # happex (remplace Kheops pour l'instant)
394
+
395
+ gov.president = self.get_official(self.functions.get('PRE_REP')['users'][0])
396
+
397
+ minister = lambda code : self.get_official(self.functions.get(f'MIN_{code}')['users'][0])
398
+ gov.prime_minister = minister('PRIM')
399
+ gov.economy_minister = minister('ECO')
400
+ gov.inner_minister = minister('INN')
401
+ gov.press_minister = minister('AUD')
402
+ gov.justice_minister = minister('JUS')
403
+ gov.outer_minister = minister('OUT')
404
+
405
+ assembly.president = self.get_official(self.functions.get('PRE_AS')['users'][0])
406
+ assembly.members = [ self.get_official(id) for id in self.functions.get('REPR')['users'] ]
407
+
408
+ court.president = gov.justice_minister
409
+ court.members = [ self.get_official(id) for id in self.functions.get('JUDGE')['users'] ]
410
+
411
+ police_forces.president = gov.inner_minister
412
+ police_forces.members = [ self.get_official(id) for id in self.functions.get('POLICE')['users'] ]
413
+
414
+ instits = Institutions()
415
+ instits.administration = admin
416
+ instits.government = gov
417
+ instits.court = court
418
+ instits.assembly = assembly
419
+ instits.police = police_forces
420
+
421
+ return instits
422
+
423
+ def update_institutions(self, institutions: Institutions):
424
+ """
425
+ Fonction communément appelée après un vote législatif ou une nomination.\n
426
+ Celle-ci met à jour: Le gouvernement (président, ministres), les différents députés et leur président, les différents juges, les différents policiers.\n
427
+
428
+ ## Paramètres
429
+ institutions: `.Institutions`\n
430
+ Le nouvel état des institutions, à sauvegarder.
431
+ """
432
+
433
+ get_ids = lambda institution : [ member.id for member in institutions.__getattribute__(institution).members ]
434
+
435
+ self.functions.put(key = 'ADMIN', data = { 'users': get_ids('administration') })
436
+ self.functions.put(key = 'REPR', data = { 'users': get_ids('assembly') })
437
+ self.functions.put(key = 'JUDGE', data = { 'users': get_ids('court') })
438
+ self.functions.put(key = 'POLICE', data = { 'users': get_ids('police') })
439
+
440
+ self.functions.put(key = 'PRE_AS', data = { 'users': [ institutions.assembly.president.id ] })
441
+ self.functions.put(key = 'PRE_REP', data = { 'users': [ institutions.government.president.id ] })
442
+
443
+ self.functions.put(key = 'MIN_PRIM', data = { 'users': [ institutions.government.prime_minister.id ] })
444
+ self.functions.put(key = 'MIN_INN', data = { 'users': [ institutions.government.inner_minister.id ] })
445
+ self.functions.put(key = 'MIN_JUS', data = { 'users': [ institutions.government.justice_minister.id ] })
446
+ self.functions.put(key = 'MIN_ECO', data = { 'users': [ institutions.government.economy_minister.id ] })
447
+ self.functions.put(key = 'MIN_AUD', data = { 'users': [ institutions.government.press_minister.id ] })
448
+ self.functions.put(key = 'MIN_OUT', data = { 'users': [ institutions.government.outer_minister.id ] })
449
+
450
+ def new_mandate(self, institutions: Institutions, weeks: int = 4) -> None:
451
+ """
452
+ Fonction qui amène à supprimer toutes les archives du mandat précédent
453
+ """
454
+
455
+ for item in self.mandate.fetch().items:
456
+ if item['date'] >= round(time.time()) - weeks * 604800: # On évite de supprimer les informations écrites lors de la période définie
457
+ self.mandate.delete(item['id'])
458
+
459
+ self.update_institutions(institutions)
460
+
461
+ def _add_archive(self, archive: Action) -> None:
462
+ """Ajoute une archive d'une action (élection, promotion, ou rétrogradation) dans la base de données."""
463
+
464
+ archive.id = NSID(archive.id)
465
+ _data = archive.__dict__.copy()
466
+
467
+ if type(archive) == Election:
468
+ _data['type'] = "election"
469
+ elif type(archive) == Promotion:
470
+ _data['type'] = "promotion"
471
+ elif type(archive) == Demotion:
472
+ _data['type'] = "demotion"
473
+ else:
474
+ _data['type'] = "unknown"
475
+
476
+ self.archives.put(key = archive.id, data = _data)
477
+ self.mandate.put(key = archive.id, data = _data) # Ajouter les archives à celle du mandat actuel
478
+
479
+ def _get_archive(self, id: str | NSID) -> Action | Election | Promotion | Demotion:
480
+ """
481
+ Récupère une archive spécifique.
482
+
483
+ ## Paramètres
484
+ id: `str | NSID`
485
+ ID de l'archive.
486
+
487
+ ## Renvoie
488
+ - `.Action | .Election | .Promotion | .Demotion`
489
+ """
490
+
491
+ id = NSID(id)
492
+ _data = self.archives.get(id)
493
+
494
+ if _data is None:
495
+ return None
496
+
497
+ if _data['type'] == "election":
498
+ archive = Election(_data['author'], _data['target'], _data['position'])
499
+
500
+ archive.positive_votes = _data['positive_votes']
501
+ archive.total_votes = _data['total_votes']
502
+ elif _data['type'] == "promotion":
503
+ archive = Promotion(_data['author'], _data['target'], _data['position'])
504
+ elif _data['type'] == "demotion":
505
+ archive = Demotion(_data['author'], _data['target'])
506
+
507
+ archive.reason = _data['reason']
508
+ else:
509
+ archive = Action(_data['author'], _data['target'])
510
+
511
+ archive.id = id
512
+ archive.action = _data['action']
513
+ archive.date = _data['date']
514
+
515
+ return archive
516
+
517
+ def _fetch_archives(self, **query) -> list[ Action | Election | Promotion | Demotion ]:
518
+ """
519
+ Récupère une liste d'archives correspondant à la requête.
520
+
521
+ ## Paramètres
522
+ query: `dict`
523
+ Requête pour filtrer les archives.
524
+
525
+ ## Renvoie
526
+ - `list[Action | Election | Promotion | Demotion]`
527
+ """
528
+
529
+ _res = self.archives.fetch(query).items
530
+
531
+ return [ self._get_archive(archive['key']) for archive in _res ]
532
+
533
+ class BankInstance:
534
+ """Gère les interactions avec les comptes bancaires, les transactions, et le marché."""
535
+
536
+ def __init__(self, token: str) -> None:
537
+ self.db = deta.Deta(token)
538
+ self.archives = self.db.Base('archives')
539
+ self.accounts = self.db.Base('accounts')
540
+ self.registry = self.db.Base('banks')
541
+ self.marketplace = self.db.Base('shop')
542
+
543
+ def get_account(self, id: str | NSID) -> BankAccount:
544
+ """
545
+ Récupère les informations d'un compte bancaire.
546
+
547
+ ## Paramètres
548
+ id: `str | NSID`
549
+ ID du compte.
550
+
551
+ ## Renvoie
552
+ - `.BankAccount`
553
+ """
554
+
555
+ id = NSID(id)
556
+ _data = self.accounts.get(id)
557
+
558
+ if _data is None:
559
+ return None
560
+
561
+ account = BankAccount(id)
562
+ account.amount = _data['amount']
563
+ account.locked = _data['locked']
564
+ account.owner = _data['owner_id']
565
+ account.bank = _data['bank']
566
+
567
+ return account
568
+
569
+ def save_account(self, account: BankAccount):
570
+ """Sauvegarde un compte bancaire dans la base de données."""
571
+
572
+ _data = {
573
+ 'amount': account.amount,
574
+ 'locked': account.locked,
575
+ 'owner_id': account.owner,
576
+ 'bank': account.bank
577
+ }
578
+
579
+ self.accounts.put(_data, NSID(account.id))
580
+
581
+ def lock_account(self, account: BankAccount):
582
+ """Verrouille un compte bancaire pour empêcher toute transaction."""
583
+
584
+ account.id = account.id.upper()
585
+ account.locked = True
586
+
587
+ self.save_account(account)
588
+
589
+ def get_item(self, id: str | NSID) -> Item | None:
590
+ """
591
+ Récupère un item du marché.
592
+
593
+ ## Paramètres
594
+ id: `str | NSID`
595
+ ID de l'item.
596
+
597
+ ## Renvoie
598
+ - `.Item | None`
599
+ """
600
+
601
+ id = NSID(id)
602
+
603
+ _data = self.marketplace.get(id)
604
+
605
+ if _data is None:
606
+ return None
607
+
608
+ item = Item(id)
609
+ item.title = _data['title']
610
+ item.emoji = _data['emoji']
611
+ item.seller_id = _data['seller']
612
+ item.price = _data['price']
613
+
614
+ return item
615
+
616
+ def save_item(self, item: Item) -> None:
617
+ """Sauvegarde un item dans la base de données du marché."""
618
+
619
+ item.id = NSID(item.id)
620
+
621
+ _data = item.__dict__.copy()
622
+
623
+ self.marketplace.put(key = item.id, data = _data)
624
+
625
+ def delete_item(self, item: Item) -> None:
626
+ """Supprime un item du marché."""
627
+
628
+ item.id = NSID(item.id)
629
+ self.marketplace.delete(item.id)
630
+
631
+ def _add_archive(self, archive: Action):
632
+ """Ajoute une archive d'une transaction ou d'une vente dans la base de données."""
633
+
634
+ archive.id = NSID(archive.id)
635
+ archive.author = NSID(archive.author)
636
+ archive.target = NSID(archive.target)
637
+
638
+ _data = archive.__dict__.copy()
639
+
640
+ if type(archive) == Transaction:
641
+ _data['type'] = "transaction"
642
+ archive.currency = archive.currency.upper()
643
+ elif type(archive) == Sale:
644
+ _data['type'] = "sale"
645
+ else:
646
+ _data['type'] = "unknown"
647
+
648
+ self.archives.put(key = archive.id, data = _data)
649
+
650
+ def _get_archive(self, id: str | NSID) -> Action | Transaction:
651
+ """
652
+ Récupère une archive spécifique.
653
+
654
+ ## Paramètres
655
+ id: `str | NSID`
656
+ ID de l'archive.
657
+
658
+ ## Renvoie
659
+ - `.Action | .Transaction`
660
+ """
661
+
662
+ id = NSID(id)
663
+ _data = self.archives.get(id)
664
+
665
+ if _data is None:
666
+ return None
667
+
668
+ if _data['type'] == "transaction":
669
+ archive = Transaction(_data['author'], _data['target'], _data['amount'])
670
+
671
+ archive.reason = _data['reason']
672
+ archive.currency = _data['currency']
673
+ elif _data['type'] == "sale":
674
+ archive = Sale(_data['author'], _data['target'])
675
+
676
+ archive.price = _data['price']
677
+ else:
678
+ archive = Action(_data['author'], _data['target'])
679
+
680
+ archive.id = id
681
+ archive.action = _data['action']
682
+ archive.date = _data['date']
683
+
684
+ return archive
685
+
686
+ def _fetch_archives(self, **query) -> list[ Action | Transaction ]:
687
+ """
688
+ Récupère une liste d'archives correspondant à la requête.
689
+
690
+ ## Paramètres
691
+ query: `dict`
692
+ Requête pour filtrer les archives.
693
+
694
+ ## Renvoie
695
+ - `list[Action | Transaction]`
696
+ """
697
+
698
+ _res = self.archives.fetch(query).items
699
+
700
+ return [ self._get_archive(archive['key']) for archive in _res ]