nsarchive 1.4.0__py3-none-any.whl → 2.0.0a2__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 +20 -820
- nsarchive/cls/archives.py +35 -29
- nsarchive/cls/base.py +110 -14
- nsarchive/cls/economy.py +3 -4
- nsarchive/cls/entities.py +27 -25
- nsarchive/cls/republic.py +25 -8
- nsarchive/instances/_economy.py +248 -0
- nsarchive/instances/_entities.py +299 -0
- nsarchive/instances/_republic.py +278 -0
- nsarchive/utils/assets.py +1 -1
- {nsarchive-1.4.0.dist-info → nsarchive-2.0.0a2.dist-info}/METADATA +3 -3
- nsarchive-2.0.0a2.dist-info/RECORD +16 -0
- nsarchive-1.4.0.dist-info/RECORD +0 -13
- {nsarchive-1.4.0.dist-info → nsarchive-2.0.0a2.dist-info}/LICENSE +0 -0
- {nsarchive-1.4.0.dist-info → nsarchive-2.0.0a2.dist-info}/WHEEL +0 -0
nsarchive/__init__.py
CHANGED
@@ -1,827 +1,27 @@
|
|
1
|
-
|
1
|
+
"""
|
2
|
+
nsarchive - API-wrapper pour récupérer des données liées à Nation.
|
2
3
|
|
3
|
-
|
4
|
+
Version: 2.0.0
|
5
|
+
License: GPL-3.0
|
6
|
+
Auteur : happex <110610727+okayhappex@users.noreply.github.com>
|
4
7
|
|
5
|
-
|
6
|
-
|
8
|
+
Dependencies:
|
9
|
+
- Python ^3.10
|
10
|
+
- supabase ^2.9.1
|
11
|
+
- pillow ^10.4
|
12
|
+
|
13
|
+
Le fichier README.md fournit des détails supplémentaires pour l'utilisation.
|
14
|
+
"""
|
15
|
+
|
16
|
+
# Import des types et des exceptions
|
17
|
+
from .cls.base import NSID
|
7
18
|
from .cls.archives import *
|
19
|
+
from .cls.entities import *
|
8
20
|
from .cls.republic import *
|
9
|
-
from .cls.economy import *
|
10
21
|
|
11
22
|
from .cls.exceptions import *
|
12
23
|
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
25
|
-
def __init__(self, token: str) -> None:
|
26
|
-
self.db = deta.Deta(token)
|
27
|
-
self.base = self.db.Base('entities')
|
28
|
-
self.electors = self.db.Base('electors')
|
29
|
-
self.archives = self.db.Base('archives')
|
30
|
-
self.avatars = self.db.Drive('avatars')
|
31
|
-
self.positions = self.db.Base('positions') # Liste des métiers
|
32
|
-
|
33
|
-
def get_entity(self, id: str | NSID) -> User | Organization | Entity:
|
34
|
-
"""
|
35
|
-
Fonction permettant de récupérer le profil public d'une entité.\n
|
36
|
-
|
37
|
-
## Paramètres
|
38
|
-
id: `NSID`\n
|
39
|
-
ID héxadécimal de l'entité à récupérer
|
40
|
-
|
41
|
-
## Renvoie
|
42
|
-
- `.User` dans le cas où l'entité choisie est un membre
|
43
|
-
- `.Organization` dans le cas où c'est un groupe
|
44
|
-
- `.Entity` dans le cas où c'est indéterminé
|
45
|
-
"""
|
46
|
-
|
47
|
-
id = NSID(id)
|
48
|
-
_data = self.base.get(id)
|
49
|
-
_votes = self.electors.get(id)
|
50
|
-
|
51
|
-
if _data is None:
|
52
|
-
return None
|
53
|
-
|
54
|
-
if _data['_type'] == 'user':
|
55
|
-
entity = User(id)
|
56
|
-
|
57
|
-
entity.xp = _data['xp']
|
58
|
-
entity.boosts = _data['boosts']
|
59
|
-
|
60
|
-
if _votes is None:
|
61
|
-
entity.votes = []
|
62
|
-
else:
|
63
|
-
entity.votes = [ NSID(vote) for vote in _votes['votes'] ]
|
64
|
-
elif _data['_type'] == 'organization':
|
65
|
-
entity = Organization(id)
|
66
|
-
|
67
|
-
entity.owner = self.get_entity(NSID(_data['owner_id']))
|
68
|
-
|
69
|
-
for _member in _data['members']:
|
70
|
-
member = GroupMember(_member['id'])
|
71
|
-
member.group_permissions.__dict__ = _member['permissions']
|
72
|
-
|
73
|
-
_member_profile = self.get_entity(member.id)
|
74
|
-
|
75
|
-
member.set_name(_member_profile.name)
|
76
|
-
member.legalPosition = _member_profile.legalPosition
|
77
|
-
member.registerDate = _member_profile.registerDate
|
78
|
-
|
79
|
-
member.xp = _member_profile.xp
|
80
|
-
member.boosts = _member_profile.boosts
|
81
|
-
|
82
|
-
member.permissions = _member_profile.permissions
|
83
|
-
member.votes = _member_profile.votes
|
84
|
-
|
85
|
-
entity.append(member)
|
86
|
-
|
87
|
-
try:
|
88
|
-
entity.avatar = self.avatars.get(id).read()
|
89
|
-
except:
|
90
|
-
entity.avatar = None
|
91
|
-
|
92
|
-
entity.certifications = _data['certifications']
|
93
|
-
else:
|
94
|
-
entity = Entity(id)
|
95
|
-
|
96
|
-
entity.name = _data['name']
|
97
|
-
entity.legalPosition = _data['legalPosition'] # Métier si c'est un utilisateur, domaine professionnel si c'est un collectif
|
98
|
-
entity.registerDate = _data['registerDate']
|
99
|
-
|
100
|
-
for key, value in _data.get('additional', {}):
|
101
|
-
if isinstance(value, str) and value.startswith('\n'):
|
102
|
-
entity.add_link(key, int(value[1:]))
|
103
|
-
else:
|
104
|
-
entity.add_link(key, value)
|
105
|
-
|
106
|
-
return entity
|
107
|
-
|
108
|
-
def save_entity(self, entity: Entity) -> None:
|
109
|
-
"""
|
110
|
-
Fonction permettant de créer ou modifier une entité.
|
111
|
-
|
112
|
-
## Paramètres
|
113
|
-
entity: `.Entity` ( `.User | .Organization` )
|
114
|
-
L'entité à sauvegarder
|
115
|
-
"""
|
116
|
-
|
117
|
-
entity.id = NSID(entity.id)
|
118
|
-
|
119
|
-
_base = self.base
|
120
|
-
_data = {
|
121
|
-
'_type': 'user' if type(entity) == User else 'organization' if type(entity) == Organization else 'unknown',
|
122
|
-
'name': entity.name,
|
123
|
-
'legalPosition': entity.legalPosition,
|
124
|
-
'registerDate': entity.registerDate,
|
125
|
-
'additional': {}
|
126
|
-
}
|
127
|
-
|
128
|
-
for key, value in entity.additional.items():
|
129
|
-
if isinstance(value, int) and len(str(int)) >= 15:
|
130
|
-
_data['additional'][key] = '\n' + str(value)
|
131
|
-
elif type(value) in (str, int):
|
132
|
-
_data['additional'][key] = value
|
133
|
-
|
134
|
-
if type(entity) == Organization:
|
135
|
-
_data['owner_id'] = NSID(entity.owner.id) if entity.owner else NSID("0")
|
136
|
-
_data['members'] = []
|
137
|
-
_data['certifications'] = entity.certifications
|
138
|
-
|
139
|
-
for member in entity.members:
|
140
|
-
_member = {
|
141
|
-
'id': NSID(member.id),
|
142
|
-
'permissions': member.group_permissions.__dict__.copy()
|
143
|
-
}
|
144
|
-
|
145
|
-
_data['members'] += [_member]
|
146
|
-
|
147
|
-
self.avatars.put(name = entity.id, data = entity.avatar)
|
148
|
-
elif type(entity) == User:
|
149
|
-
_data['xp'] = entity.xp
|
150
|
-
_data['boosts'] = entity.boosts
|
151
|
-
|
152
|
-
_votes = []
|
153
|
-
for vote in entity.votes:
|
154
|
-
_votes.append(NSID(vote))
|
155
|
-
|
156
|
-
self.electors.put({ "votes": _votes }, entity.id, expire_in = 112 * 84600) # Données supprimées après 16 semaines d'inactivité
|
157
|
-
|
158
|
-
_base.put(_data, entity.id, expire_in = 3 * 31536000) # Pareil après 3 ans
|
159
|
-
|
160
|
-
def delete_entity(self, entity: Entity) -> None:
|
161
|
-
"""
|
162
|
-
Fonction permettant de supprimer le profil d'une entité
|
163
|
-
|
164
|
-
## Paramètres
|
165
|
-
entity: `.Entity` ( `.User | .Organization` )
|
166
|
-
L'entité à supprimer
|
167
|
-
"""
|
168
|
-
|
169
|
-
self.base.delete(NSID(entity.id))
|
170
|
-
|
171
|
-
if type(entity) == Organization:
|
172
|
-
self.avatars.delete(NSID(entity.id))
|
173
|
-
|
174
|
-
def fetch_entities(self, query: dict = None, listquery: dict | None = None) -> list[ Entity | User | Organization ]:
|
175
|
-
"""
|
176
|
-
Récupère une liste d'entités en fonction d'une requête.
|
177
|
-
|
178
|
-
## Paramètres
|
179
|
-
query: `dict`
|
180
|
-
La requête pour filtrer les entités.
|
181
|
-
listquery: `dict | None`
|
182
|
-
OBSOLÈTE
|
183
|
-
|
184
|
-
## Renvoie
|
185
|
-
- `list[Entity | User | Organization]`
|
186
|
-
"""
|
187
|
-
|
188
|
-
_res = self.base.fetch(query).items
|
189
|
-
|
190
|
-
if listquery:
|
191
|
-
print("\033[1;33mAvertissement\033[0m Listquery n'est plus pris en charge et sera retiré en version 1.3.0")
|
192
|
-
|
193
|
-
return [ self.get_entity(NSID(entity['key'])) for entity in _res if entity is not None ]
|
194
|
-
|
195
|
-
def get_entity_groups(self, id: str | NSID) -> list[Organization]:
|
196
|
-
"""
|
197
|
-
Récupère les groupes auxquels appartient une entité.
|
198
|
-
|
199
|
-
## Paramètres
|
200
|
-
id: `str | NSID`
|
201
|
-
ID de l'entité.
|
202
|
-
|
203
|
-
## Renvoie
|
204
|
-
- `list[Organization]`
|
205
|
-
"""
|
206
|
-
|
207
|
-
id = NSID(id)
|
208
|
-
groups = self.fetch_entities({'_type': 'organization'})
|
209
|
-
groups.extend(self.fetch_entities({'_type': 'organization', 'owner_id': id}))
|
210
|
-
|
211
|
-
for group in groups:
|
212
|
-
if group is None:
|
213
|
-
groups.remove(group)
|
214
|
-
continue
|
215
|
-
|
216
|
-
if group.owner.id == id:
|
217
|
-
continue
|
218
|
-
|
219
|
-
for member in group.members:
|
220
|
-
if member.id == id:
|
221
|
-
break
|
222
|
-
else:
|
223
|
-
groups.remove(group)
|
224
|
-
|
225
|
-
return [ group for group in groups if group is not None ]
|
226
|
-
|
227
|
-
def get_position(self, id: str) -> Position:
|
228
|
-
"""
|
229
|
-
Récupère une position légale (métier, domaine professionnel).
|
230
|
-
|
231
|
-
## Paramètres
|
232
|
-
id: `str`
|
233
|
-
ID de la position (SENSIBLE À LA CASSE !)
|
234
|
-
|
235
|
-
## Renvoie
|
236
|
-
- `.Position`
|
237
|
-
"""
|
238
|
-
|
239
|
-
_data = self.positions.get(id)
|
240
|
-
|
241
|
-
if _data is None:
|
242
|
-
return None
|
243
|
-
|
244
|
-
position = Position(id)
|
245
|
-
position.name = _data['name']
|
246
|
-
|
247
|
-
for _permission in _data['permissions']:
|
248
|
-
position.permissions.__setattr__(_permission, True)
|
249
|
-
|
250
|
-
return position
|
251
|
-
|
252
|
-
def _add_archive(self, archive: Action) -> None:
|
253
|
-
"""
|
254
|
-
Ajoute une archive d'une action (modification au sein d'un groupe ou sanction) dans la base de données.
|
255
|
-
"""
|
256
|
-
|
257
|
-
archive.id = NSID(archive.id)
|
258
|
-
archive.author = NSID(archive.author)
|
259
|
-
archive.target = NSID(archive.target)
|
260
|
-
|
261
|
-
_data = archive.__dict__.copy()
|
262
|
-
|
263
|
-
if type(archive) == Sanction:
|
264
|
-
_data['type'] = "sanction"
|
265
|
-
elif type(archive) == AdminAction:
|
266
|
-
_data['type'] = "adminaction"
|
267
|
-
elif type(archive) == Report:
|
268
|
-
_data['type'] = "report"
|
269
|
-
else:
|
270
|
-
_data['type'] = "unknown"
|
271
|
-
|
272
|
-
self.archives.put(key = archive.id, data = _data)
|
273
|
-
|
274
|
-
def _get_archive(self, id: str | NSID) -> Action | Sanction | AdminAction:
|
275
|
-
"""
|
276
|
-
Récupère une archive spécifique.
|
277
|
-
|
278
|
-
## Paramètres
|
279
|
-
id: `str | NSID`
|
280
|
-
ID de l'archive.
|
281
|
-
|
282
|
-
## Renvoie
|
283
|
-
- `.Action | .Sanction | .AdminAction`
|
284
|
-
"""
|
285
|
-
|
286
|
-
id = NSID(id)
|
287
|
-
_data = self.archives.get(id)
|
288
|
-
|
289
|
-
if _data is None:
|
290
|
-
return None
|
291
|
-
|
292
|
-
if _data['type'] == "sanction": # Mute, ban, GAV, kick, détention, prune (xp seulement)
|
293
|
-
archive = Sanction(_data['author'], _data['target'])
|
294
|
-
|
295
|
-
archive.details = _data['details']
|
296
|
-
archive.major = _data['major']
|
297
|
-
archive.duration = _data['duration']
|
298
|
-
elif _data['type'] == "adminaction": # Renommage, promotion, démotion (au niveau de l'état)
|
299
|
-
archive = AdminAction(_data['author'], _data['target'])
|
300
|
-
|
301
|
-
archive.details = _data['details']
|
302
|
-
archive.new_state = _data['new_state']
|
303
|
-
elif _data['type'] == "report": # Plainte
|
304
|
-
archive = Report(_data['author'], _data['target'])
|
305
|
-
|
306
|
-
archive.details = _data['details']
|
307
|
-
else:
|
308
|
-
archive = Action(_data['author'], _data['target'])
|
309
|
-
|
310
|
-
archive.id = id
|
311
|
-
archive.action = _data['action']
|
312
|
-
archive.date = _data['date']
|
313
|
-
|
314
|
-
return archive
|
315
|
-
|
316
|
-
def _fetch_archives(self, **query) -> list[ Action | Sanction | AdminAction ]:
|
317
|
-
"""
|
318
|
-
Récupère une liste d'archives correspondant à la requête.
|
319
|
-
|
320
|
-
## Paramètres
|
321
|
-
query: `dict`
|
322
|
-
Requête pour filtrer les archives.
|
323
|
-
|
324
|
-
## Renvoie
|
325
|
-
- `list[Action | Sanction | AdminAction]`
|
326
|
-
"""
|
327
|
-
|
328
|
-
_res = self.archives.fetch(query).items
|
329
|
-
|
330
|
-
return [ self._get_archive(archive['key']) for archive in _res ]
|
331
|
-
|
332
|
-
class RepublicInstance:
|
333
|
-
"""
|
334
|
-
Gère les interactions avec les votes, les archives de la république, et les fonctionnaires.
|
335
|
-
|
336
|
-
## Informations
|
337
|
-
- Résultats des votes: `.Vote | .ClosedVote`
|
338
|
-
- Différentes institutions: `.Institutions | .Administration | .Government | .Assembly | .Court | .PoliceForces`
|
339
|
-
- Occupants des différents rôles et historique de leurs actions: `.Official`
|
340
|
-
"""
|
341
|
-
|
342
|
-
def __init__(self, token: str) -> None:
|
343
|
-
"""Initialise une nouvelle RepublicInstance avec un token Deta."""
|
344
|
-
|
345
|
-
self.db = deta.Deta(token)
|
346
|
-
self.votes = self.db.Base('votes')
|
347
|
-
self.archives = self.db.Base('archives')
|
348
|
-
self.mandate = self.db.Base('mandate')
|
349
|
-
self.functions = self.db.Base('functions') # Liste des fonctionnaires
|
350
|
-
|
351
|
-
def get_vote(self, id: str | NSID) -> Vote | ClosedVote | Lawsuit:
|
352
|
-
"""
|
353
|
-
Récupère un vote spécifique.
|
354
|
-
|
355
|
-
## Paramètres
|
356
|
-
id: `str | NSID`
|
357
|
-
ID du vote.
|
358
|
-
|
359
|
-
## Renvoie
|
360
|
-
- `.Vote | .ClosedVote`
|
361
|
-
"""
|
362
|
-
|
363
|
-
id = NSID(id)
|
364
|
-
_data = self.votes.get(id)
|
365
|
-
|
366
|
-
if _data is None:
|
367
|
-
return None
|
368
|
-
|
369
|
-
if _data['_type'] == 'open':
|
370
|
-
vote = Vote(id, _data['title'], tuple(_data['choices'].keys()))
|
371
|
-
elif _data['_type'] == 'closed':
|
372
|
-
vote = ClosedVote(id, _data['title'])
|
373
|
-
elif _data['_type'] == 'lawsuit':
|
374
|
-
vote = Lawsuit(id, _data['title'])
|
375
|
-
else:
|
376
|
-
vote = Vote('0', 'Unknown Vote', ())
|
377
|
-
|
378
|
-
vote.author = _data['author']
|
379
|
-
vote.startDate = _data['startDate']
|
380
|
-
vote.endDate = _data['endDate']
|
381
|
-
vote.choices = _data['choices']
|
382
|
-
|
383
|
-
return vote
|
384
|
-
|
385
|
-
def save_vote(self, vote: Vote | ClosedVote) -> None:
|
386
|
-
"""Sauvegarde un vote dans la base de données."""
|
387
|
-
|
388
|
-
vote.id = NSID(vote.id)
|
389
|
-
|
390
|
-
_data = {
|
391
|
-
'_type':'open' if type(vote) == Vote else\
|
392
|
-
'closed' if type(vote) == ClosedVote else\
|
393
|
-
'lawsuit' if type(vote) == Lawsuit else\
|
394
|
-
'unknown',
|
395
|
-
'title': vote.title,
|
396
|
-
'author': NSID(vote.author),
|
397
|
-
'startDate': vote.startDate,
|
398
|
-
'endDate': vote.endDate,
|
399
|
-
'choices': vote.choices
|
400
|
-
}
|
401
|
-
|
402
|
-
self.votes.put(_data, vote.id)
|
403
|
-
|
404
|
-
def get_official(self, id: str | NSID, current_mandate: bool = True) -> Official:
|
405
|
-
"""
|
406
|
-
Récupère les informations d'un fonctionnaire (mandats, contributions).
|
407
|
-
|
408
|
-
## Paramètres
|
409
|
-
id: `str | NSID`
|
410
|
-
ID du fonctionnaire.
|
411
|
-
current_mandate: `bool`
|
412
|
-
Indique si l'on doit récupérer le mandat actuel ou les anciens mandats.
|
413
|
-
|
414
|
-
## Renvoie
|
415
|
-
- `.Official`
|
416
|
-
"""
|
417
|
-
|
418
|
-
id = NSID(id)
|
419
|
-
|
420
|
-
archives = self.mandate if current_mandate else self.archives
|
421
|
-
|
422
|
-
_contributions = archives.fetch({'author': id, 'type': 'contrib'}).items
|
423
|
-
_mandates = archives.fetch({'target': id, 'type': 'election'}).items\
|
424
|
-
+ archives.fetch({'target': id, 'type': 'promotion'}).items
|
425
|
-
|
426
|
-
user = Official(id)
|
427
|
-
for mandate in _mandates:
|
428
|
-
if mandate['position'].startswith('MIN'):
|
429
|
-
mandate['position'] = 'MIN'
|
430
|
-
|
431
|
-
try:
|
432
|
-
user.mandates[mandate['position']] += 1
|
433
|
-
except KeyError:
|
434
|
-
user.mandates[mandate['position']] = 1
|
435
|
-
|
436
|
-
for contrib in _contributions:
|
437
|
-
try:
|
438
|
-
user.contributions[contrib['action']] += 1
|
439
|
-
except KeyError:
|
440
|
-
user.contributions[contrib['action']] = 1
|
441
|
-
|
442
|
-
return user
|
443
|
-
|
444
|
-
def get_institutions(self) -> Organization:
|
445
|
-
"""Récupère l'état actuel des institutions de la république."""
|
446
|
-
|
447
|
-
admin = Administration()
|
448
|
-
gov = Government(Official('0'))
|
449
|
-
assembly = Assembly()
|
450
|
-
court = Court()
|
451
|
-
police_forces = PoliceForces()
|
452
|
-
|
453
|
-
_admins = self.functions.get('ADMIN')
|
454
|
-
admin.members = [ self.get_official(user) for user in _admins['users'] ]
|
455
|
-
admin.president = self.get_official('F7DB60DD1C4300A') # happex (remplace Kheops pour l'instant)
|
456
|
-
|
457
|
-
gov.president = self.get_official(self.functions.get('PRE_REP')['users'][0])
|
458
|
-
|
459
|
-
minister = lambda code : self.get_official(self.functions.get(f'MIN_{code}')['users'][0])
|
460
|
-
gov.prime_minister = minister('PRIM')
|
461
|
-
gov.economy_minister = minister('ECO')
|
462
|
-
gov.inner_minister = minister('INN')
|
463
|
-
gov.press_minister = minister('AUD')
|
464
|
-
gov.justice_minister = minister('JUS')
|
465
|
-
gov.outer_minister = minister('OUT')
|
466
|
-
|
467
|
-
assembly.president = self.get_official(self.functions.get('PRE_AS')['users'][0])
|
468
|
-
assembly.members = [ self.get_official(id) for id in self.functions.get('REPR')['users'] ]
|
469
|
-
|
470
|
-
court.president = gov.justice_minister
|
471
|
-
court.members = [ self.get_official(id) for id in self.functions.get('JUDGE')['users'] ]
|
472
|
-
|
473
|
-
police_forces.president = gov.inner_minister
|
474
|
-
police_forces.members = [ self.get_official(id) for id in self.functions.get('POLICE')['users'] ]
|
475
|
-
|
476
|
-
instits = Institutions()
|
477
|
-
instits.administration = admin
|
478
|
-
instits.government = gov
|
479
|
-
instits.court = court
|
480
|
-
instits.assembly = assembly
|
481
|
-
instits.police = police_forces
|
482
|
-
|
483
|
-
return instits
|
484
|
-
|
485
|
-
def update_institutions(self, institutions: Institutions):
|
486
|
-
"""
|
487
|
-
Fonction communément appelée après un vote législatif ou une nomination.\n
|
488
|
-
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
|
489
|
-
|
490
|
-
## Paramètres
|
491
|
-
institutions: `.Institutions`\n
|
492
|
-
Le nouvel état des institutions, à sauvegarder.
|
493
|
-
"""
|
494
|
-
|
495
|
-
get_ids = lambda institution : [ member.id for member in institutions.__getattribute__(institution).members ]
|
496
|
-
|
497
|
-
self.functions.put(key = 'ADMIN', data = { 'users': get_ids('administration') })
|
498
|
-
self.functions.put(key = 'REPR', data = { 'users': get_ids('assembly') })
|
499
|
-
self.functions.put(key = 'JUDGE', data = { 'users': get_ids('court') })
|
500
|
-
self.functions.put(key = 'POLICE', data = { 'users': get_ids('police') })
|
501
|
-
|
502
|
-
self.functions.put(key = 'PRE_AS', data = { 'users': [ institutions.assembly.president.id ] })
|
503
|
-
self.functions.put(key = 'PRE_REP', data = { 'users': [ institutions.government.president.id ] })
|
504
|
-
|
505
|
-
self.functions.put(key = 'MIN_PRIM', data = { 'users': [ institutions.government.prime_minister.id ] })
|
506
|
-
self.functions.put(key = 'MIN_INN', data = { 'users': [ institutions.government.inner_minister.id ] })
|
507
|
-
self.functions.put(key = 'MIN_JUS', data = { 'users': [ institutions.government.justice_minister.id ] })
|
508
|
-
self.functions.put(key = 'MIN_ECO', data = { 'users': [ institutions.government.economy_minister.id ] })
|
509
|
-
self.functions.put(key = 'MIN_AUD', data = { 'users': [ institutions.government.press_minister.id ] })
|
510
|
-
self.functions.put(key = 'MIN_OUT', data = { 'users': [ institutions.government.outer_minister.id ] })
|
511
|
-
|
512
|
-
def new_mandate(self, institutions: Institutions, weeks: int = 4) -> None:
|
513
|
-
"""
|
514
|
-
Fonction qui amène à supprimer toutes les archives du mandat précédent
|
515
|
-
"""
|
516
|
-
|
517
|
-
for item in self.mandate.fetch().items:
|
518
|
-
if item['date'] >= round(time.time()) - weeks * 604800: # On évite de supprimer les informations écrites lors de la période définie
|
519
|
-
self.mandate.delete(item['id'])
|
520
|
-
|
521
|
-
self.update_institutions(institutions)
|
522
|
-
|
523
|
-
def _add_archive(self, archive: Action) -> None:
|
524
|
-
"""Ajoute une archive d'une action (élection, promotion, ou rétrogradation) dans la base de données."""
|
525
|
-
|
526
|
-
archive.id = NSID(archive.id)
|
527
|
-
_data = archive.__dict__.copy()
|
528
|
-
|
529
|
-
if type(archive) == Election:
|
530
|
-
_data['type'] = "election"
|
531
|
-
elif type(archive) == Promotion:
|
532
|
-
_data['type'] = "promotion"
|
533
|
-
elif type(archive) == Demotion:
|
534
|
-
_data['type'] = "demotion"
|
535
|
-
else:
|
536
|
-
_data['type'] = "unknown"
|
537
|
-
|
538
|
-
self.archives.put(key = archive.id, data = _data)
|
539
|
-
self.mandate.put(key = archive.id, data = _data) # Ajouter les archives à celle du mandat actuel
|
540
|
-
|
541
|
-
def _get_archive(self, id: str | NSID) -> Action | Election | Promotion | Demotion:
|
542
|
-
"""
|
543
|
-
Récupère une archive spécifique.
|
544
|
-
|
545
|
-
## Paramètres
|
546
|
-
id: `str | NSID`
|
547
|
-
ID de l'archive.
|
548
|
-
|
549
|
-
## Renvoie
|
550
|
-
- `.Action | .Election | .Promotion | .Demotion`
|
551
|
-
"""
|
552
|
-
|
553
|
-
id = NSID(id)
|
554
|
-
_data = self.archives.get(id)
|
555
|
-
|
556
|
-
if _data is None:
|
557
|
-
return None
|
558
|
-
|
559
|
-
if _data['type'] == "election":
|
560
|
-
archive = Election(_data['author'], _data['target'], _data['position'])
|
561
|
-
|
562
|
-
archive.positive_votes = _data['positive_votes']
|
563
|
-
archive.total_votes = _data['total_votes']
|
564
|
-
elif _data['type'] == "promotion":
|
565
|
-
archive = Promotion(_data['author'], _data['target'], _data['position'])
|
566
|
-
elif _data['type'] == "demotion":
|
567
|
-
archive = Demotion(_data['author'], _data['target'])
|
568
|
-
|
569
|
-
archive.reason = _data['reason']
|
570
|
-
else:
|
571
|
-
archive = Action(_data['author'], _data['target'])
|
572
|
-
|
573
|
-
archive.id = id
|
574
|
-
archive.action = _data['action']
|
575
|
-
archive.date = _data['date']
|
576
|
-
|
577
|
-
return archive
|
578
|
-
|
579
|
-
def _fetch_archives(self, **query) -> list[ Action | Election | Promotion | Demotion ]:
|
580
|
-
"""
|
581
|
-
Récupère une liste d'archives correspondant à la requête.
|
582
|
-
|
583
|
-
## Paramètres
|
584
|
-
query: `dict`
|
585
|
-
Requête pour filtrer les archives.
|
586
|
-
|
587
|
-
## Renvoie
|
588
|
-
- `list[Action | Election | Promotion | Demotion]`
|
589
|
-
"""
|
590
|
-
|
591
|
-
_res = self.archives.fetch(query).items
|
592
|
-
|
593
|
-
return [ self._get_archive(archive['key']) for archive in _res ]
|
594
|
-
|
595
|
-
class BankInstance:
|
596
|
-
"""Gère les interactions avec les comptes bancaires, les transactions, et le marché."""
|
597
|
-
|
598
|
-
def __init__(self, token: str) -> None:
|
599
|
-
self.db = deta.Deta(token)
|
600
|
-
self.archives = self.db.Base('archives')
|
601
|
-
self.accounts = self.db.Base('accounts')
|
602
|
-
self.registry = self.db.Base('banks')
|
603
|
-
self.marketplace = self.db.Base('shop')
|
604
|
-
self.inventories = self.db.Base('inventories')
|
605
|
-
|
606
|
-
def get_account(self, id: str | NSID) -> BankAccount:
|
607
|
-
"""
|
608
|
-
Récupère les informations d'un compte bancaire.
|
609
|
-
|
610
|
-
## Paramètres
|
611
|
-
id: `str | NSID`
|
612
|
-
ID du compte.
|
613
|
-
|
614
|
-
## Renvoie
|
615
|
-
- `.BankAccount`
|
616
|
-
"""
|
617
|
-
|
618
|
-
id = NSID(id)
|
619
|
-
_data = self.accounts.get(id)
|
620
|
-
|
621
|
-
if _data is None:
|
622
|
-
return None
|
623
|
-
|
624
|
-
account = BankAccount(id)
|
625
|
-
account.amount = _data['amount']
|
626
|
-
account.locked = _data['locked']
|
627
|
-
account.owner = _data['owner_id']
|
628
|
-
account.bank = _data['bank']
|
629
|
-
|
630
|
-
return account
|
631
|
-
|
632
|
-
def save_account(self, account: BankAccount):
|
633
|
-
"""Sauvegarde un compte bancaire dans la base de données."""
|
634
|
-
|
635
|
-
_data = {
|
636
|
-
'amount': account.amount,
|
637
|
-
'locked': account.locked,
|
638
|
-
'owner_id': account.owner,
|
639
|
-
'bank': account.bank
|
640
|
-
}
|
641
|
-
|
642
|
-
self.accounts.put(_data, NSID(account.id))
|
643
|
-
|
644
|
-
def lock_account(self, account: BankAccount):
|
645
|
-
"""Verrouille un compte bancaire pour empêcher toute transaction."""
|
646
|
-
|
647
|
-
account.id = account.id.upper()
|
648
|
-
account.locked = True
|
649
|
-
|
650
|
-
self.save_account(account)
|
651
|
-
|
652
|
-
def get_sale(self, id: str | NSID) -> Sale | None:
|
653
|
-
"""
|
654
|
-
Récupère une vente disponible sur le marketplace.
|
655
|
-
|
656
|
-
## Paramètres
|
657
|
-
id: `str | NSID`
|
658
|
-
ID de l'item.
|
659
|
-
|
660
|
-
## Renvoie
|
661
|
-
- `.Item | None`
|
662
|
-
"""
|
663
|
-
|
664
|
-
id = NSID(id)
|
665
|
-
|
666
|
-
_data = self.marketplace.get(id)
|
667
|
-
|
668
|
-
if _data is None:
|
669
|
-
return None
|
670
|
-
|
671
|
-
sale = Sale(NSID(id))
|
672
|
-
|
673
|
-
del _data['key']
|
674
|
-
sale.__dict__ = _data
|
675
|
-
|
676
|
-
return sale
|
677
|
-
|
678
|
-
def sell_item(self, item: Item, quantity: int, price: int, seller: NSID) -> None:
|
679
|
-
"""
|
680
|
-
Vend un item sur le marché.
|
681
|
-
|
682
|
-
## Paramètres
|
683
|
-
item: `.Item`
|
684
|
-
Item à vendre
|
685
|
-
quantity: `int`
|
686
|
-
Nombre d'items à vendre
|
687
|
-
price: `int`
|
688
|
-
Prix à l'unité de chaque objet
|
689
|
-
seller: `NSID`
|
690
|
-
ID de l'auteur de la vente
|
691
|
-
"""
|
692
|
-
|
693
|
-
sale = Sale(NSID(round(time.time()) * 16 ** 3), item)
|
694
|
-
sale.quantity = quantity
|
695
|
-
sale.price = price
|
696
|
-
sale.seller_id = seller
|
697
|
-
|
698
|
-
_data = sale.__dict__.copy()
|
699
|
-
del _data['id']
|
700
|
-
|
701
|
-
self.marketplace.put(key = sale.id, data = _data)
|
702
|
-
|
703
|
-
def delete_sale(self, sale: Sale) -> None:
|
704
|
-
"""Annule une vente sur le marketplace."""
|
705
|
-
|
706
|
-
sale.id = NSID(sale.id)
|
707
|
-
self.marketplace.delete(sale.id)
|
708
|
-
|
709
|
-
def get_inventory(self, id: NSID) -> Inventory | None:
|
710
|
-
"""
|
711
|
-
Récupérer un inventaire dans la base des inventaires.
|
712
|
-
|
713
|
-
## Paramètres
|
714
|
-
id: `NSID`
|
715
|
-
ID du propriétaire de l'inventaire
|
716
|
-
|
717
|
-
## Retourne
|
718
|
-
- `.Inventory | None`
|
719
|
-
"""
|
720
|
-
_data = self.inventories.get(id)
|
721
|
-
|
722
|
-
if _data is None:
|
723
|
-
return None
|
724
|
-
|
725
|
-
inventory = Inventory(id)
|
726
|
-
|
727
|
-
del _data['key']
|
728
|
-
|
729
|
-
for _item in _data['objects']:
|
730
|
-
item = Item(_item['id'])
|
731
|
-
item.__dict__ = _item
|
732
|
-
|
733
|
-
inventory.objects.append(item)
|
734
|
-
|
735
|
-
return inventory
|
736
|
-
|
737
|
-
def save_inventory(self, inventory: Inventory) -> None:
|
738
|
-
"""
|
739
|
-
Sauvegarder un inventaire
|
740
|
-
|
741
|
-
## Paramètres
|
742
|
-
inventory: `.Inventory`
|
743
|
-
Inventaire à sauvegarder
|
744
|
-
"""
|
745
|
-
|
746
|
-
_data = {
|
747
|
-
"owner_id": inventory.owner_id,
|
748
|
-
"objects": [ object.__dict__ for object in inventory.objects ]
|
749
|
-
}
|
750
|
-
|
751
|
-
self.inventories.put(key = inventory.owner_id, data = _data)
|
752
|
-
|
753
|
-
def delete_inventory(self, inventory: Inventory) -> None:
|
754
|
-
"""
|
755
|
-
Supprime un inventaire
|
756
|
-
|
757
|
-
## Paramètres
|
758
|
-
inventory: `.Inventory`
|
759
|
-
Inventaire à supprimer
|
760
|
-
"""
|
761
|
-
|
762
|
-
self.inventories.delete(inventory.id)
|
763
|
-
|
764
|
-
def _add_archive(self, archive: Action):
|
765
|
-
"""Ajoute une archive d'une transaction ou d'une vente dans la base de données."""
|
766
|
-
|
767
|
-
archive.id = NSID(archive.id)
|
768
|
-
archive.author = NSID(archive.author)
|
769
|
-
archive.target = NSID(archive.target)
|
770
|
-
|
771
|
-
_data = archive.__dict__.copy()
|
772
|
-
|
773
|
-
if type(archive) == Transaction:
|
774
|
-
_data['type'] = "transaction"
|
775
|
-
archive.currency = archive.currency.upper()
|
776
|
-
else:
|
777
|
-
_data['type'] = "unknown"
|
778
|
-
|
779
|
-
self.archives.put(key = archive.id, data = _data)
|
780
|
-
|
781
|
-
def _get_archive(self, id: str | NSID) -> Action | Transaction:
|
782
|
-
"""
|
783
|
-
Récupère une archive spécifique.
|
784
|
-
|
785
|
-
## Paramètres
|
786
|
-
id: `str | NSID`
|
787
|
-
ID de l'archive.
|
788
|
-
|
789
|
-
## Renvoie
|
790
|
-
- `.Action | .Transaction`
|
791
|
-
"""
|
792
|
-
|
793
|
-
id = NSID(id)
|
794
|
-
_data = self.archives.get(id)
|
795
|
-
|
796
|
-
if _data is None:
|
797
|
-
return None
|
798
|
-
|
799
|
-
if _data['type'] == "transaction":
|
800
|
-
archive = Transaction(_data['author'], _data['target'], _data['amount'])
|
801
|
-
|
802
|
-
archive.reason = _data['reason']
|
803
|
-
archive.currency = _data['currency']
|
804
|
-
else:
|
805
|
-
archive = Action(_data['author'], _data['target'])
|
806
|
-
|
807
|
-
archive.id = id
|
808
|
-
archive.action = _data['action']
|
809
|
-
archive.date = _data['date']
|
810
|
-
|
811
|
-
return archive
|
812
|
-
|
813
|
-
def _fetch_archives(self, **query) -> list[ Action | Transaction ]:
|
814
|
-
"""
|
815
|
-
Récupère une liste d'archives correspondant à la requête.
|
816
|
-
|
817
|
-
## Paramètres
|
818
|
-
query: `dict`
|
819
|
-
Requête pour filtrer les archives.
|
820
|
-
|
821
|
-
## Renvoie
|
822
|
-
- `list[Action | Transaction]`
|
823
|
-
"""
|
824
|
-
|
825
|
-
_res = self.archives.fetch(query).items
|
826
|
-
|
827
|
-
return [ self._get_archive(archive['key']) for archive in _res ]
|
24
|
+
# Import des instances
|
25
|
+
from .instances._economy import EconomyInstance
|
26
|
+
from .instances._entities import EntityInstance
|
27
|
+
from .instances._republic import RepublicInstance
|