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 +380 -100
- nsarchive/cls/archives.py +22 -12
- nsarchive/cls/base.py +30 -0
- nsarchive/cls/economy.py +20 -0
- nsarchive/cls/entities.py +63 -27
- nsarchive/cls/exceptions.py +6 -0
- nsarchive/cls/republic.py +21 -20
- {nsarchive-0.1b3.dist-info → nsarchive-1.0.0.dist-info}/METADATA +1 -1
- nsarchive-1.0.0.dist-info/RECORD +13 -0
- nsarchive/cls/bank.py +0 -7
- nsarchive-0.1b3.dist-info/RECORD +0 -12
- {nsarchive-0.1b3.dist-info → nsarchive-1.0.0.dist-info}/LICENSE +0 -0
- {nsarchive-0.1b3.dist-info → nsarchive-1.0.0.dist-info}/WHEEL +0 -0
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.
|
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
|
-
|
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']
|
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
|
-
|
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
|
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
|
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
|
-
|
86
|
-
|
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
|
-
|
89
|
-
id = id.upper()
|
90
|
-
_data = self.electors.get(id)
|
131
|
+
self.base.delete(NSID(entity.id))
|
91
132
|
|
92
|
-
if
|
93
|
-
self.
|
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
|
102
|
-
|
103
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
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 =
|
364
|
+
user = Official(id)
|
221
365
|
for mandate in _mandates:
|
222
|
-
if mandate['position'].startswith('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(
|
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
|
-
|
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
|
-
|
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
|
-
|
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':
|
373
|
-
'locked':
|
374
|
-
'owner_id':
|
375
|
-
'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,
|
379
|
-
|
380
|
-
def lock_account(self,
|
381
|
-
|
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
|
-
|
597
|
+
## Renvoie
|
598
|
+
- `.Item | None`
|
599
|
+
"""
|
384
600
|
|
385
|
-
|
386
|
-
_data = _archive.__dict__.copy()
|
601
|
+
id = NSID(id)
|
387
602
|
|
388
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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 = '
|
5
|
-
self.
|
6
|
-
|
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:
|
9
|
-
self.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()
|
nsarchive/cls/economy.py
ADDED
@@ -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:
|
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:
|
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
|
66
|
-
def __init__(self, id: str) -> None:
|
67
|
-
self.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:
|
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 ]
|
nsarchive/cls/exceptions.py
CHANGED
@@ -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:
|
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:
|
24
|
-
self.members: list[
|
23
|
+
self.president: Official
|
24
|
+
self.members: list[Official]
|
25
25
|
|
26
26
|
class Government:
|
27
|
-
def __init__(self, president:
|
28
|
-
self.president:
|
29
|
-
self.prime_minister:
|
27
|
+
def __init__(self, president: Official) -> None:
|
28
|
+
self.president: Official = president
|
29
|
+
self.prime_minister: Official
|
30
30
|
|
31
|
-
self.inner_minister:
|
32
|
-
self.economy_minister:
|
33
|
-
self.justice_minister:
|
34
|
-
self.press_minister:
|
35
|
-
self.outer_minister:
|
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:
|
40
|
-
self.members: list[
|
39
|
+
self.president: Official
|
40
|
+
self.members: list[Official]
|
41
41
|
|
42
42
|
class Court:
|
43
43
|
def __init__(self) -> None:
|
44
|
-
self.president:
|
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[
|
46
|
+
self.members: list[Official]
|
47
47
|
|
48
48
|
class PoliceForces:
|
49
49
|
def __init__(self) -> None:
|
50
|
-
self.president:
|
51
|
-
self.members: list[
|
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
|
+
|
@@ -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
nsarchive-0.1b3.dist-info/RECORD
DELETED
@@ -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,,
|
File without changes
|
File without changes
|