nsarchive 0.1b3__py3-none-any.whl → 1.0.0__py3-none-any.whl

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.
nsarchive/__init__.py CHANGED
@@ -2,24 +2,50 @@ import time
2
2
 
3
3
  import deta
4
4
 
5
+ from .cls.base import *
5
6
  from .cls.entities import *
6
7
  from .cls.archives import *
7
8
  from .cls.republic import *
8
- from .cls.bank import *
9
+ from .cls.economy import *
9
10
 
10
11
  from .cls.exceptions import *
11
12
 
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
+ """
13
24
  def __init__(self, token: str) -> None:
14
25
  self.db = deta.Deta(token)
15
26
  self.base = self.db.Base('entities')
16
27
  self.electors = self.db.Base('electors')
17
28
  self.archives = self.db.Base('archives')
18
29
  self.avatars = self.db.Drive('avatars')
30
+ self.positions = self.db.Base('positions') # Liste des métiers
19
31
 
20
- def get_entity(self, id: str) -> User | Organization | Entity:
21
- id = id.upper()
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)
22
47
  _data = self.base.get(id)
48
+ _votes = self.electors.get(id)
23
49
 
24
50
  if _data is None:
25
51
  return Entity("0")
@@ -29,16 +55,20 @@ class EntityInstance:
29
55
 
30
56
  entity.xp = _data['xp']
31
57
  entity.boosts = _data['boosts']
58
+ entity.votes = [ NSID(vote) for vote in _votes['votes'] ]
32
59
  elif _data['_type'] == 'organization':
33
60
  entity = Organization(id)
34
61
 
35
- entity.owner = self.get_entity(_data['owner_id'].upper())
62
+ entity.owner = self.get_entity(NSID(_data['owner_id']))
36
63
 
37
64
  for _member in _data['members']:
38
65
  member = GroupMember(_member['id'])
39
66
  member.permissions.__dict__ = _member['permissions']
40
67
 
41
- entity.avatar = self.avatars.get(id).read()
68
+ try:
69
+ entity.avatar = self.avatars.get(id).read()
70
+ except:
71
+ entity.avatar = None
42
72
 
43
73
  entity.certifications = _data['certifications']
44
74
  else:
@@ -51,6 +81,16 @@ class EntityInstance:
51
81
  return entity
52
82
 
53
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
+
54
94
  _base = self.base
55
95
  _data = {
56
96
  '_type': 'user' if type(entity) == User else 'organization' if type(entity) == Organization else 'unknown',
@@ -60,13 +100,13 @@ class EntityInstance:
60
100
  }
61
101
 
62
102
  if type(entity) == Organization:
63
- _data['owner_id'] = entity.owner.id.upper() if entity.owner else "0"
103
+ _data['owner_id'] = NSID(entity.owner.id) if entity.owner else NSID("0")
64
104
  _data['members'] = []
65
105
  _data['certifications'] = entity.certifications
66
106
 
67
107
  for member in entity.members:
68
108
  _member = {
69
- 'id': member.id,
109
+ 'id': NSID(member.id),
70
110
  'permissions': member.permissions.__dict__.copy()
71
111
  }
72
112
 
@@ -77,38 +117,35 @@ class EntityInstance:
77
117
  _data['xp'] = entity.xp
78
118
  _data['boosts'] = entity.boosts
79
119
 
80
- _base.put(_data, entity.id.upper(), expire_in = 3 * 31536000) # Données supprimées tous les trois ans
81
-
82
- def delete_entity(self, entity: Entity) -> None:
83
- self.base.delete(entity.id.upper())
120
+ _base.put(_data, entity.id, expire_in = 3 * 31536000) # Données supprimées tous les trois ans
84
121
 
85
- if type(entity) == Organization:
86
- self.avatars.delete(entity.id.upper())
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
+ """
87
130
 
88
- def get_elector(self, id: str) -> Elector:
89
- id = id.upper()
90
- _data = self.electors.get(id)
131
+ self.base.delete(NSID(entity.id))
91
132
 
92
- if _data is None:
93
- self.save_elector(Elector(id))
94
- return Elector(id)
95
-
96
- elector = Elector(id)
97
- elector.votes = _data['votes']
98
-
99
- return elector
133
+ if type(entity) == Organization:
134
+ self.avatars.delete(NSID(entity.id))
100
135
 
101
- def save_elector(self, elector: Elector):
102
- _data = {
103
- "votes": elector.votes
104
- }
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.
105
139
 
106
- self.electors.put(_data, elector.id.upper())
107
-
108
- # Les archives ne permettent pas de garder une trace des votes
109
- # Donc je préfère aucune fonction permettant de les supprimer
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.
110
145
 
111
- def fetch_entities(self, query = None, listquery: dict | None = None) -> list[Entity | User | Organization]:
146
+ ## Renvoie
147
+ - `list[Entity | User | Organization]`
148
+ """
112
149
  _res = self.base.fetch(query).items
113
150
 
114
151
  if listquery is not None:
@@ -116,15 +153,60 @@ class EntityInstance:
116
153
  for target, value in listquery.items():
117
154
  if value not in item[target]:
118
155
  _res.remove(item)
119
-
120
- return [ self.get_entity(entity['key']) for entity in _res ]
121
156
 
122
- def get_entity_groups(self, id: str) -> list[Organization]:
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)
123
172
  groups = self.fetch_entities({'_type': 'organization'}, {'members': id})
124
173
 
125
174
  return groups
126
-
127
- def _add_archive(self, archive: Action):
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
+
128
210
  _data = archive.__dict__.copy()
129
211
 
130
212
  if type(archive) == Sanction:
@@ -134,11 +216,21 @@ class EntityInstance:
134
216
  else:
135
217
  _data['type'] = "unknown"
136
218
 
137
- del _data['id']
138
-
139
219
  self.archives.put(key = archive.id, data = _data)
140
220
 
141
- def _get_archive(self, id: str) -> Action | Sanction | AdminAction:
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)
142
234
  _data = self.archives.get(id)
143
235
 
144
236
  if _data is None:
@@ -163,84 +255,139 @@ class EntityInstance:
163
255
  archive.date = _data['date']
164
256
 
165
257
  return archive
166
-
258
+
167
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
+
168
271
  _res = self.archives.fetch(query).items
169
272
 
170
273
  return [ self._get_archive(archive['key']) for archive in _res ]
171
-
274
+
172
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
+
173
285
  def __init__(self, token: str) -> None:
286
+ """Initialise une nouvelle RepublicInstance avec un token Deta."""
287
+
174
288
  self.db = deta.Deta(token)
175
289
  self.votes = self.db.Base('votes')
176
290
  self.archives = self.db.Base('archives')
177
291
  self.mandate = self.db.Base('mandate')
178
292
  self.functions = self.db.Base('functions') # Liste des fonctionnaires
179
293
 
180
- def get_vote(self, id: str) -> Vote | ClosedVote:
181
- id = id.upper()
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)
182
307
  _data = self.votes.get(id)
183
308
 
184
309
  if _data is None:
185
- return None
186
-
310
+ raise RessourceNotFoundError(f"The vote #{id} does not exist.")
311
+
187
312
  if _data['_type'] == 'open':
188
313
  vote = Vote(id, _data['title'], tuple(_data['choices'].keys()))
189
314
  elif _data['_type'] == 'closed':
190
315
  vote = ClosedVote(id, _data['title'])
191
316
  else:
192
317
  vote = Vote('0', 'Unknown Vote', ())
193
-
318
+
194
319
  vote.author = _data['author']
195
320
  vote.startDate = _data['startDate']
196
321
  vote.endDate = _data['endDate']
197
322
  vote.choices = _data['choices']
198
-
323
+
199
324
  return vote
200
325
 
201
- def save_vote(self, vote: Vote | ClosedVote):
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
+
202
331
  _data = {
203
332
  '_type': 'open' if type(vote) == Vote else 'closed' if type(vote) == ClosedVote else 'unknown',
204
333
  'title': vote.title,
205
- 'author': vote.author,
334
+ 'author': NSID(vote.author),
206
335
  'startDate': vote.startDate,
207
336
  'endDate': vote.endDate,
208
337
  'choices': vote.choices
209
338
  }
210
339
 
211
- self.votes.put(_data, vote.id.upper())
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)
212
357
 
213
- def get_official(self, id: str, current_mandate: bool = True) -> FunctionalUser:
214
358
  archives = self.mandate if current_mandate else self.archives
215
359
 
216
360
  _contributions = archives.fetch({'author': id, 'type': 'contrib'}).items
217
361
  _mandates = archives.fetch({'target': id, 'type': 'election'}).items\
218
362
  + archives.fetch({'target': id, 'type': 'promotion'}).items
219
363
 
220
- user = FunctionalUser(id)
364
+ user = Official(id)
221
365
  for mandate in _mandates:
222
- if mandate['position'].startswith('MIN'): mandate['position'] = 'MIN'
366
+ if mandate['position'].startswith('MIN'):
367
+ mandate['position'] = 'MIN'
223
368
 
224
369
  try:
225
370
  user.mandates[mandate['position']] += 1
226
371
  except KeyError:
227
372
  user.mandates[mandate['position']] = 1
228
-
373
+
229
374
  for contrib in _contributions:
230
375
  try:
231
376
  user.contributions[contrib['action']] += 1
232
377
  except KeyError:
233
378
  user.contributions[contrib['action']] = 1
234
-
379
+
235
380
  return user
236
381
 
237
382
  def get_institutions(self) -> Organization:
383
+ """Récupère l'état actuel des institutions de la république."""
384
+
238
385
  admin = Administration()
239
- gov = Government(FunctionalUser('0'))
386
+ gov = Government(Official('0'))
240
387
  assembly = Assembly()
241
388
  court = Court()
242
389
  police_forces = PoliceForces()
243
-
390
+
244
391
  _admins = self.functions.get('ADMIN')
245
392
  admin.members = [ self.get_official(user) for user in _admins['users'] ]
246
393
  admin.president = self.get_official('F7DB60DD1C4300A') # happex (remplace Kheops pour l'instant)
@@ -272,8 +419,17 @@ class RepublicInstance:
272
419
  instits.police = police_forces
273
420
 
274
421
  return instits
275
-
422
+
276
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
+
277
433
  get_ids = lambda institution : [ member.id for member in institutions.__getattribute__(institution).members ]
278
434
 
279
435
  self.functions.put(key = 'ADMIN', data = { 'users': get_ids('administration') })
@@ -291,14 +447,21 @@ class RepublicInstance:
291
447
  self.functions.put(key = 'MIN_AUD', data = { 'users': [ institutions.government.press_minister.id ] })
292
448
  self.functions.put(key = 'MIN_OUT', data = { 'users': [ institutions.government.outer_minister.id ] })
293
449
 
294
- def new_mandate(self, institutions: Institutions, weeks: int = 4):
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
+
295
455
  for item in self.mandate.fetch().items:
296
- if item['date'] >= round(time.time()) - weeks * 604800:
456
+ if item['date'] >= round(time.time()) - weeks * 604800: # On évite de supprimer les informations écrites lors de la période définie
297
457
  self.mandate.delete(item['id'])
298
-
458
+
299
459
  self.update_institutions(institutions)
300
460
 
301
- def _add_archive(self, archive: Action):
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)
302
465
  _data = archive.__dict__.copy()
303
466
 
304
467
  if type(archive) == Election:
@@ -309,17 +472,28 @@ class RepublicInstance:
309
472
  _data['type'] = "demotion"
310
473
  else:
311
474
  _data['type'] = "unknown"
312
-
313
- del _data['id']
314
475
 
315
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.
316
486
 
317
- def _get_archive(self, id: str) -> Action | Election | Promotion | Demotion:
487
+ ## Renvoie
488
+ - `.Action | .Election | .Promotion | .Demotion`
489
+ """
490
+
491
+ id = NSID(id)
318
492
  _data = self.archives.get(id)
319
493
 
320
494
  if _data is None:
321
495
  return None
322
-
496
+
323
497
  if _data['type'] == "election":
324
498
  archive = Election(_data['author'], _data['target'], _data['position'])
325
499
 
@@ -333,88 +507,194 @@ class RepublicInstance:
333
507
  archive.reason = _data['reason']
334
508
  else:
335
509
  archive = Action(_data['author'], _data['target'])
336
-
510
+
337
511
  archive.id = id
338
512
  archive.action = _data['action']
339
513
  archive.date = _data['date']
340
514
 
341
515
  return archive
342
-
516
+
343
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
+
344
529
  _res = self.archives.fetch(query).items
345
530
 
346
531
  return [ self._get_archive(archive['key']) for archive in _res ]
347
532
 
348
533
  class BankInstance:
534
+ """Gère les interactions avec les comptes bancaires, les transactions, et le marché."""
535
+
349
536
  def __init__(self, token: str) -> None:
350
537
  self.db = deta.Deta(token)
351
538
  self.archives = self.db.Base('archives')
352
539
  self.accounts = self.db.Base('accounts')
353
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
+ """
354
554
 
355
- def get_account(self, id: str) -> BankAccount:
356
- id = id.upper()
555
+ id = NSID(id)
357
556
  _data = self.accounts.get(id)
358
557
 
359
558
  if _data is None:
360
559
  return None
361
-
362
- acc = BankAccount(id)
363
- acc.amount = _data['amount']
364
- acc.locked = _data['locked']
365
- acc.owner = _data['owner_id']
366
- acc.bank = _data['bank']
367
560
 
368
- return acc
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."""
369
571
 
370
- def save_account(self, acc: BankAccount):
371
572
  _data = {
372
- 'amount': acc.amount,
373
- 'locked': acc.locked,
374
- 'owner_id': acc.owner,
375
- 'bank': acc.bank
573
+ 'amount': account.amount,
574
+ 'locked': account.locked,
575
+ 'owner_id': account.owner,
576
+ 'bank': account.bank
376
577
  }
377
578
 
378
- self.accounts.put(_data, acc.id.upper())
379
-
380
- def lock_account(self, acc: BankAccount):
381
- acc.locked = True
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.
382
596
 
383
- self.save_account(acc)
597
+ ## Renvoie
598
+ - `.Item | None`
599
+ """
384
600
 
385
- def _add_archive(self, _archive: Action):
386
- _data = _archive.__dict__.copy()
601
+ id = NSID(id)
387
602
 
388
- if type(_archive) == Transaction:
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:
389
641
  _data['type'] = "transaction"
642
+ archive.currency = archive.currency.upper()
643
+ elif type(archive) == Sale:
644
+ _data['type'] = "sale"
390
645
  else:
391
646
  _data['type'] = "unknown"
392
-
393
- del _data['id']
394
647
 
395
- self.archives.put(key = _archive.id, data = _data)
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.
396
657
 
397
- def _get_archive(self, id: str) -> Action | Transaction:
658
+ ## Renvoie
659
+ - `.Action | .Transaction`
660
+ """
661
+
662
+ id = NSID(id)
398
663
  _data = self.archives.get(id)
399
664
 
400
665
  if _data is None:
401
666
  return None
402
-
667
+
403
668
  if _data['type'] == "transaction":
404
669
  archive = Transaction(_data['author'], _data['target'], _data['amount'])
405
670
 
406
671
  archive.reason = _data['reason']
407
672
  archive.currency = _data['currency']
673
+ elif _data['type'] == "sale":
674
+ archive = Sale(_data['author'], _data['target'])
675
+
676
+ archive.price = _data['price']
408
677
  else:
409
678
  archive = Action(_data['author'], _data['target'])
410
-
679
+
411
680
  archive.id = id
412
681
  archive.action = _data['action']
413
682
  archive.date = _data['date']
414
683
 
415
684
  return archive
416
-
685
+
417
686
  def _fetch_archives(self, **query) -> list[ Action | Transaction ]:
418
- _res = self.archives.fetch(query).items
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
+ """
419
697
 
698
+ _res = self.archives.fetch(query).items
699
+
420
700
  return [ self._get_archive(archive['key']) for archive in _res ]
nsarchive/cls/archives.py CHANGED
@@ -1,18 +1,21 @@
1
1
  import time
2
2
 
3
+ from .base import *
4
+
3
5
  class Action:
4
- def __init__(self, author: str = '11625D9061021010', target: str = '0') -> None:
5
- self.id: str = hex(round(time.time()))[2:].upper()
6
- self.date: int = int(self.id, 16)
6
+ def __init__(self, author: str | NSID = '0', target: str | NSID = '0') -> None:
7
+ self.date: int = round(time.time())
8
+
9
+ self.id: NSID = NSID(self.date)
7
10
  self.action: str = ""
8
- self.author: str = author
9
- self.target: str = target
11
+ self.author: NSID = NSID(author)
12
+ self.target: NSID = NSID(target)
10
13
 
11
14
 
12
15
  # Entities
13
16
 
14
17
  class Sanction(Action):
15
- def __init__(self, author: str, target: str) -> None:
18
+ def __init__(self, author: str | NSID, target: str | NSID) -> None:
16
19
  super().__init__(author, target)
17
20
 
18
21
  self.details: str = ""
@@ -20,7 +23,7 @@ class Sanction(Action):
20
23
  self.duration: int = 0 # Durée en secondes, 0 = définitif
21
24
 
22
25
  class AdminAction(Action):
23
- def __init__(self, author: str, target: str) -> None:
26
+ def __init__(self, author: str | NSID, target: str | NSID) -> None:
24
27
  super().__init__(author, target)
25
28
 
26
29
  self.details: str = ""
@@ -30,7 +33,7 @@ class AdminAction(Action):
30
33
  # Community
31
34
 
32
35
  class Election(Action):
33
- def __init__(self, author: str, target: str, position: str) -> None:
36
+ def __init__(self, author: str | NSID, target: str | NSID, position: str) -> None:
34
37
  super().__init__(author, target)
35
38
 
36
39
  self.position: str = position
@@ -38,23 +41,30 @@ class Election(Action):
38
41
  self.total_votes: int = 0
39
42
 
40
43
  class Promotion(Action):
41
- def __init__(self, author: str, target: str, position: str) -> None:
44
+ def __init__(self, author: str | NSID, target: str | NSID, position: str) -> None:
42
45
  super().__init__(author, target)
43
46
 
44
47
  self.position: str = position
45
48
 
46
49
  class Demotion(Action):
47
- def __init__(self, author: str, target: str) -> None:
50
+ def __init__(self, author: str | NSID, target: str | NSID) -> None:
48
51
  super().__init__(author, target)
49
52
 
50
53
  self.reason: str = None
51
54
 
55
+
52
56
  # Bank
53
57
 
54
58
  class Transaction(Action):
55
- def __init__(self, author: str, target: str, amount: int) -> None:
59
+ def __init__(self, author: str | NSID, target: str | NSID, amount: int) -> None:
56
60
  super().__init__(author, target)
57
61
 
58
62
  self.amount: int = amount
59
63
  self.currency: str = 'HC'
60
- self.reason: str = None
64
+ self.reason: str = None
65
+
66
+ class Sale(Action):
67
+ def __init__(self, author: str | NSID = '0', target: str | NSID = '0') -> None:
68
+ super().__init__(author, target)
69
+
70
+ self.price: int = 0
nsarchive/cls/base.py ADDED
@@ -0,0 +1,30 @@
1
+ class NSID(str):
2
+ unknown = "0"
3
+ admin = "01"
4
+ gov = "02"
5
+ assembly = "03"
6
+ court = "04"
7
+ office = "05"
8
+ hexabank = "06"
9
+ archives = "07"
10
+
11
+ maintenance_committee = "101"
12
+ audiovisual_department = "102"
13
+ interior_department = "103"
14
+
15
+ def __new__(cls, value):
16
+ instance = super(NSID, cls).__new__(cls, value)
17
+ return instance
18
+
19
+ def __init__(self, value: str | int = ""):
20
+ if type(value) == int:
21
+ value = hex(value)
22
+ elif type(value) in (str, NSID):
23
+ value = hex(int(value, 16))
24
+ else:
25
+ return TypeError(f"<{value}> is not NSID serializable")
26
+
27
+ if value.startswith("0x"):
28
+ value = value[2:]
29
+
30
+ self.value = value.upper()
@@ -0,0 +1,20 @@
1
+ from .base import *
2
+
3
+ class BankAccount:
4
+ def __init__(self, id: str | NSID) -> None:
5
+ self.id: NSID = NSID(id)
6
+ self.owner: NSID = NSID(0)
7
+ self.amount: int = 0
8
+ self.locked: bool = False
9
+ self.bank: str = "HexaBank"
10
+
11
+ self.income: int = 0
12
+
13
+ class Item:
14
+ def __init__(self, id: str | NSID) -> None:
15
+ self.id: NSID = NSID(id)
16
+ self.title: str = "Unknown Object"
17
+ self.emoji: str = ":light_bulb:"
18
+
19
+ self.seller_id: NSID = NSID(0)
20
+ self.price: int = 0
nsarchive/cls/entities.py CHANGED
@@ -2,31 +2,68 @@ import io
2
2
  import time
3
3
 
4
4
  from .exceptions import *
5
+ from .base import *
5
6
 
6
7
  from ..utils import assets
7
8
 
9
+ class PositionPermissions:
10
+ """
11
+ Permissions d'une position à l'échelle du serveur. Certaines sont attribuées selon l'appartenance à divers groupes ayant une position précise
12
+ """
13
+
14
+ def __init__(self) -> None:
15
+ # Membres
16
+ self.approve_laws = False # Approuver ou désapprouver les lois proposées (vaut aussi pour la Constitution)
17
+ self.buy_items = False # Acheter des items depuis le marketplace
18
+ self.create_organizations = False # Créer une organisation
19
+ self.edit_constitution = False # Proposer une modification de la Constitution
20
+ self.edit_laws = False # Proposer une modification des différents textes de loi
21
+ self.manage_entities = False # Gérer les membres et les organisations
22
+ self.manage_national_channel = False # Prendre la parole sur la chaîne nationale et avoir une priorité de passage sur les autres chaînes
23
+ self.manage_state_budgets = False # Gérer les différents budgets de l'État
24
+ self.moderate_members = False # Envoyer des membres en garde à vue, en détention ou toute autre sanction non présente sur le client Discord
25
+ self.propose_new_laws = self.edit_constitution # Proposer un nouveau texte de loi pris en charge par la Constitution
26
+ self.publish_official_messages = False # Publier un message sous l'identité du bot Serveur
27
+ self.sell_items = False # Vendre des objets ou services sur le marketplace
28
+ self.vote_president = False # Participer aux élections présidentielles
29
+ self.vote_representatives = False # Participer aux élections législatives
30
+
31
+ def edit(self, **permissions: bool) -> None:
32
+ for perm in permissions.values():
33
+ self.__setattr__(*perm)
34
+
35
+ class Position:
36
+ def __init__(self, id: str = 'inconnu') -> None:
37
+ self.name: str = "Inconnue"
38
+ self.id = id
39
+ self.permissions: PositionPermissions = PositionPermissions()
8
40
  class Entity:
9
- def __init__(self, id: str) -> None:
10
- self.id: str = id # ID hexadécimal de l'entité (ou nom dans le cas de l'entreprise)
41
+ def __init__(self, id: str | NSID) -> None:
42
+ self.id: NSID = NSID(id) # ID hexadécimal de l'entité (ou nom dans le cas de l'entreprise)
11
43
  self.name: str = "Entité Inconnue"
12
44
  self.registerDate: int = 0
13
- self.legalPosition: str = 'Membre'
14
-
45
+ self.legalPosition: Position = Position()
46
+
15
47
  def set_name(self, new_name: str) -> None:
16
48
  if len(new_name) > 32:
17
49
  raise NameTooLongError(f"Name length mustn't exceed 32 characters.")
18
-
50
+
19
51
  self.name = new_name
20
-
52
+
21
53
  def set_position(self, position: str) -> None:
22
54
  self.legalPosition = position
23
55
 
24
56
  class User(Entity):
25
- def __init__(self, id: str) -> None:
26
- super().__init__(id)
57
+ def __init__(self, id: str | NSID) -> None:
58
+ super().__init__(NSID(id))
27
59
 
28
60
  self.xp: int = 0
29
61
  self.boosts: dict[str, int] = {}
62
+ self.permissions: PositionPermissions = PositionPermissions() # Elles seront définies en récupérant les permissions de sa position
63
+ self.votes: list[str] = []
64
+
65
+ def add_vote(self, id: str | NSID):
66
+ self.votes.append(NSID(id))
30
67
 
31
68
  def get_level(self) -> None:
32
69
  i = 0
@@ -34,7 +71,7 @@ class User(Entity):
34
71
  i += 1
35
72
 
36
73
  return i
37
-
74
+
38
75
  def add_xp(self, amount: int) -> None:
39
76
  boost = 0 if 0 in self.boosts.values() else max(list(self.boosts.values()) + [ 1 ])
40
77
 
@@ -47,24 +84,28 @@ class User(Entity):
47
84
  del self.boosts[name]
48
85
 
49
86
  class MemberPermissions:
87
+ """
88
+ Permissions d'un utilisateur à l'échelle d'un groupe
89
+ """
90
+
50
91
  def __init__(self) -> None:
51
92
  self.manage_organization = False # Renommer ou changer le logo
52
93
  self.manage_members = False # Virer quelqu'un d'une entreprise, l'y inviter, changer ses rôles
53
94
  self.manage_roles = False # Promouvoir ou rétrograder les membres
54
-
95
+
55
96
  def edit(self, **permissions: bool) -> None:
56
97
  for perm in permissions.values():
57
98
  self.__setattr__(*perm)
58
99
 
59
100
  class GroupMember():
60
- def __init__(self, id: str) -> None:
61
- self.id = id
101
+ def __init__(self, id: str | NSID) -> None:
102
+ self.id: NSID = NSID(id)
62
103
  self.permissions: MemberPermissions = MemberPermissions()
63
104
  self.position: str = 'membre'
64
105
 
65
- class FunctionalUser:
66
- def __init__(self, id: str) -> None:
67
- self.id: str = id
106
+ class Official:
107
+ def __init__(self, id: str | NSID) -> None:
108
+ self.id: NSID = NSID(id)
68
109
 
69
110
  self.mandates: int = {
70
111
  'PRE_REP': 0, # Président de la République
@@ -82,8 +123,8 @@ class FunctionalUser:
82
123
  }
83
124
 
84
125
  class Organization(Entity):
85
- def __init__(self, id: str) -> None:
86
- super().__init__(id)
126
+ def __init__(self, id: str | NSID) -> None:
127
+ super().__init__(NSID(id))
87
128
 
88
129
  self.owner: Entity
89
130
  self.certifications: dict = {}
@@ -92,21 +133,16 @@ class Organization(Entity):
92
133
 
93
134
  def add_certification(self, certif: str) -> None:
94
135
  self.certifications[certif] = round(time.time())
95
-
136
+
96
137
  def add_member(self, member: GroupMember) -> None:
97
138
  self.members.append(member)
98
-
99
- def remove_member(self, member: User) -> None:
139
+
140
+ def remove_member(self, member: GroupMember) -> None:
100
141
  if member in self.members:
101
142
  self.members.remove(member)
102
-
143
+
103
144
  def set_owner(self, member: User) -> None:
104
145
  self.owner = member
105
146
 
106
147
  def get_member_id(self) -> list[str]:
107
- return [ member.id for member in self.members ]
108
-
109
- class Elector(User):
110
- def __init__(self, id: str) -> None:
111
- super().__init__(id)
112
- self.votes: list[str] = []
148
+ return [ member.id for member in self.members ]
@@ -15,5 +15,11 @@ class AvatarTooLongError(Exception):
15
15
  # Exceptions pour le vote
16
16
 
17
17
  class AlreadyVotedError(Exception):
18
+ def __init__(self, *args: object) -> None:
19
+ super().__init__(*args)
20
+
21
+ # Ressource pas trouvée
22
+
23
+ class RessourceNotFoundError(Exception):
18
24
  def __init__(self, *args: object) -> None:
19
25
  super().__init__(*args)
nsarchive/cls/republic.py CHANGED
@@ -3,8 +3,8 @@ from .entities import *
3
3
  # Votes
4
4
 
5
5
  class Vote:
6
- def __init__(self, id: str, title: str, choices: tuple[str]) -> None:
7
- self.id: str = id
6
+ def __init__(self, id: str | NSID, title: str, choices: tuple[str]) -> None:
7
+ self.id: NSID = NSID(id)
8
8
  self.title: str = title
9
9
  self.choices = { choice : 0 for choice in choices }
10
10
  self.author: str = '0'
@@ -12,7 +12,7 @@ class Vote:
12
12
  self.endDate: int = 0
13
13
 
14
14
  class ClosedVote(Vote):
15
- def __init__(self, id: str, title: str) -> None:
15
+ def __init__(self, id: str | NSID, title: str) -> None:
16
16
  super().__init__(id, title, ('yes', 'no', 'blank'))
17
17
 
18
18
 
@@ -20,35 +20,35 @@ class ClosedVote(Vote):
20
20
 
21
21
  class Administration:
22
22
  def __init__(self) -> None:
23
- self.president: FunctionalUser
24
- self.members: list[FunctionalUser]
23
+ self.president: Official
24
+ self.members: list[Official]
25
25
 
26
26
  class Government:
27
- def __init__(self, president: FunctionalUser) -> None:
28
- self.president: FunctionalUser = president
29
- self.prime_minister: FunctionalUser
27
+ def __init__(self, president: Official) -> None:
28
+ self.president: Official = president
29
+ self.prime_minister: Official
30
30
 
31
- self.inner_minister: FunctionalUser
32
- self.economy_minister: FunctionalUser
33
- self.justice_minister: FunctionalUser
34
- self.press_minister: FunctionalUser
35
- self.outer_minister: FunctionalUser
31
+ self.inner_minister: Official
32
+ self.economy_minister: Official
33
+ self.justice_minister: Official
34
+ self.press_minister: Official
35
+ self.outer_minister: Official
36
36
 
37
37
  class Assembly:
38
38
  def __init__(self) -> None:
39
- self.president: FunctionalUser
40
- self.members: list[FunctionalUser]
39
+ self.president: Official
40
+ self.members: list[Official]
41
41
 
42
42
  class Court:
43
43
  def __init__(self) -> None:
44
- self.president: FunctionalUser
44
+ self.president: Official
45
45
  # On discutera de la mise en place d'un potentiel président. Pour l'instant c'est le Ministre de la Justice
46
- self.members: list[FunctionalUser]
46
+ self.members: list[Official]
47
47
 
48
48
  class PoliceForces:
49
49
  def __init__(self) -> None:
50
- self.president: FunctionalUser
51
- self.members: list[FunctionalUser]
50
+ self.president: Official
51
+ self.members: list[Official]
52
52
 
53
53
  class Institutions:
54
54
  def __init__(self) -> None:
@@ -56,4 +56,5 @@ class Institutions:
56
56
  self.government: Government
57
57
  self.court: Court
58
58
  self.assembly: Assembly
59
- self.police: PoliceForces
59
+ self.police: PoliceForces
60
+
@@ -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,13 @@
1
+ nsarchive/__init__.py,sha256=WAGTyFj-bQEgkz7tW8KTCIYqEMKq6RvjP6sp-9RaGp0,23899
2
+ nsarchive/assets/default_avatar.png,sha256=n-4vG_WPke8LvbY3ZU6oA-H-OtRoIu7woKnRq9DCIlI,51764
3
+ nsarchive/cls/archives.py,sha256=P3xOg7D7og-Vnf3VQWeIwmJRD9g7dVQBYChvMIMM6i8,2008
4
+ nsarchive/cls/base.py,sha256=1B1BpDuQhQAU2gzpme_SmQcfT-xBiii08Fd4bv73_8E,777
5
+ nsarchive/cls/economy.py,sha256=RjFu3VzNunazslbd4Ia5p1Jr-jJP5CvIcbVOzkDTwTU,549
6
+ nsarchive/cls/entities.py,sha256=zz0JTphgtXpCIVH8dgb3hxc55nxwvXF3m2yIXgp_Q9k,5743
7
+ nsarchive/cls/exceptions.py,sha256=QN6Qn7cxTkGoC4lO50hBAq4gZCgo7scQvCkb-xKl6Xs,692
8
+ nsarchive/cls/republic.py,sha256=FphoO9TBE9hyfdjcePjQHqBw7NFT74f-avE9T5qTTuE,1750
9
+ nsarchive/utils/assets.py,sha256=hd0STSpa0yT-OJlUyI_wCYXJqcBiUMQds2pZTXNNg9c,382
10
+ nsarchive-1.0.0.dist-info/LICENSE,sha256=aFLFZg6LEJFpTlNQ8su3__jw4GfV-xWBmC1cePkKZVw,35802
11
+ nsarchive-1.0.0.dist-info/METADATA,sha256=iHeEWqCHHmMSOrjN7qofN3bkqPPwLL7ZFPu2Xfz8bUk,5629
12
+ nsarchive-1.0.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
13
+ nsarchive-1.0.0.dist-info/RECORD,,
nsarchive/cls/bank.py DELETED
@@ -1,7 +0,0 @@
1
- class BankAccount:
2
- def __init__(self, id: str) -> None:
3
- self.id: str = id
4
- self.owner: str = '0'
5
- self.amount: int = 0
6
- self.locked: bool = False
7
- self.bank: str = "HexaBank"
@@ -1,12 +0,0 @@
1
- nsarchive/__init__.py,sha256=2wELlOApcaP3RPByj_xr3JwQ8ngLSDWBzQIDp117HsM,15481
2
- nsarchive/assets/default_avatar.png,sha256=n-4vG_WPke8LvbY3ZU6oA-H-OtRoIu7woKnRq9DCIlI,51764
3
- nsarchive/cls/archives.py,sha256=5C66pXuXAANRXNDqNTvIepRtUrXIWOL7ymmYiBHsHAY,1720
4
- nsarchive/cls/bank.py,sha256=OactEpRn8PGv7BwnBUbMpzgHqrvv4yx526AMzh9uBO8,220
5
- nsarchive/cls/entities.py,sha256=Gv6nNEmLXyUokQfoQgNUIjq0kLTTlPT0Wmdpw83z7gY,3499
6
- nsarchive/cls/exceptions.py,sha256=UZ7G7AFUN5OkKAGpNl1OT7jauF1jC7WW8wWXVFt5sMs,539
7
- nsarchive/cls/republic.py,sha256=aY79B5PZF5IErwzEjn9ito6T8gXA4trm6LmIeYu6XLM,1821
8
- nsarchive/utils/assets.py,sha256=hd0STSpa0yT-OJlUyI_wCYXJqcBiUMQds2pZTXNNg9c,382
9
- nsarchive-0.1b3.dist-info/LICENSE,sha256=aFLFZg6LEJFpTlNQ8su3__jw4GfV-xWBmC1cePkKZVw,35802
10
- nsarchive-0.1b3.dist-info/METADATA,sha256=1KcsUxL-6mWvF4VJ42jYnNnL-wkkI8pBqYOtiZxscDI,5629
11
- nsarchive-0.1b3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
12
- nsarchive-0.1b3.dist-info/RECORD,,