nsarchive 0.1a0__py3-none-any.whl → 0.1b0__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
@@ -3,75 +3,409 @@ import time
3
3
  import deta
4
4
 
5
5
  from .cls.entities import *
6
+ from .cls.archives import *
7
+ from .cls.republic import *
8
+ from .cls.bank import *
9
+
6
10
  from .cls.exceptions import *
7
11
 
8
12
  class EntityInstance:
9
13
  def __init__(self, token: str) -> None:
10
14
  self.db = deta.Deta(token)
11
15
  self.base = self.db.Base('entities')
16
+ self.electors = self.db.Base('electors')
17
+ self.archives = self.db.Base('archives')
18
+ self.avatars = self.db.Drive('avatars')
12
19
 
13
20
  def get_entity(self, id: str) -> User | Organization | Entity:
14
- _base = self.base
15
- _data = _base.get(id)
21
+ id = id.upper()
22
+ _data = self.base.get(id)
16
23
 
17
24
  if _data is None:
18
25
  return Entity("0")
19
26
 
20
27
  if _data['_type'] == 'user':
21
28
  entity = User(id)
29
+
30
+ entity.xp = _data['xp']
31
+ entity.boosts = _data['boosts']
22
32
  elif _data['_type'] == 'organization':
23
33
  entity = Organization(id)
34
+
35
+ entity.owner = self.get_entity(_data['owner_id'].upper())
36
+ entity.members = [
37
+ self.get_entity(_id) for _id in _data['members']
38
+ ]
39
+
40
+ entity.avatar = self.avatars.get(id).read()
41
+
42
+ entity.certifications = _data['certifications']
24
43
  else:
25
44
  entity = Entity(id)
26
45
 
27
46
  entity.name = _data['name']
28
47
  entity.legalPosition = _data['legalPosition'] # Métier si c'est un utilisateur, domaine professionnel si c'est un collectif
29
48
  entity.registerDate = _data['registerDate']
30
- entity.xp = _data['xp']
31
-
32
- if type(entity) == Organization:
33
- entity.owner = self.get_entity(_data['owner_id'])
34
- entity.members = [
35
- self.get_entity(_id) for _id in _data['members']
36
- ]
37
49
 
38
- entity.certifications = _data['certifications']
39
- elif type(entity) == User:
40
- entity.boosts = _data['boosts']
41
-
42
50
  return entity
43
-
51
+
44
52
  def save_entity(self, entity: Entity) -> None:
45
53
  _base = self.base
46
54
  _data = {
47
55
  '_type': 'user' if type(entity) == User else 'organization' if type(entity) == Organization else 'unknown',
48
56
  'name': entity.name,
49
57
  'legalPosition': entity.legalPosition,
50
- 'registerDate': entity.registerDate,
51
- 'xp': entity.xp
58
+ 'registerDate': entity.registerDate
52
59
  }
53
60
 
54
61
  if type(entity) == Organization:
55
- _data['owner_id'] = entity.owner.id if entity.owner else Entity(0)
56
- _data['members'] = [ member.id for member in entity.members ] if entity.members else []
62
+ _data['owner_id'] = entity.owner.id.upper() if entity.owner else "0"
63
+ _data['members'] = [ member.id.upper() for member in entity.members ] if entity.members else []
57
64
  _data['certifications'] = entity.certifications
65
+
66
+ self.avatars.put(name = entity.id, data = entity.avatar)
58
67
  elif type(entity) == User:
68
+ _data['xp'] = entity.xp
59
69
  _data['boosts'] = entity.boosts
60
70
 
61
- _base.put(_data, entity.id, expire_in = 3 * 31536000) # Données supprimées tous les trois ans
71
+ _base.put(_data, entity.id.upper(), expire_in = 3 * 31536000) # Données supprimées tous les trois ans
72
+
73
+ def delete_entity(self, entity: Entity) -> None:
74
+ self.base.delete(entity.id.upper())
75
+
76
+ if type(entity) == Organization:
77
+ self.avatars.delete(entity.id.upper())
78
+
79
+ def get_elector(self, id: str) -> Elector:
80
+ id = id.upper()
81
+ _data = self.electors.get(id)
82
+
83
+ if _data is None:
84
+ self.save_elector(Elector(id))
85
+ return Elector(id)
86
+
87
+ elector = Elector(id)
88
+ elector.votes = _data['votes']
89
+
90
+ return elector
91
+
92
+ def save_elector(self, elector: Elector):
93
+ _data = {
94
+ "votes": elector.votes
95
+ }
96
+
97
+ self.electors.put(_data, elector.id.upper())
98
+
99
+ # Les archives ne permettent pas de garder une trace des votes
100
+ # Donc je préfère aucune fonction permettant de les supprimer
62
101
 
63
- def fetch(self, query = None, listquery: dict | None = None) -> list:
102
+ def fetch_entities(self, query = None, listquery: dict | None = None) -> list[Entity | User | Organization]:
64
103
  _res = self.base.fetch(query).items
65
104
 
66
105
  if listquery is not None:
67
106
  for item in _res:
68
- for target, value in listquery:
107
+ for target, value in listquery.items():
69
108
  if value not in item[target]:
70
109
  _res.remove(item)
71
110
 
72
- return _res
111
+ return [ self.get_entity(entity['key']) for entity in _res ]
112
+
113
+ def get_entity_groups(self, id: str) -> list[Organization]:
114
+ groups = self.fetch_entities({'_type': 'organization'}, {'members': id})
115
+
116
+ return [ self.get_entity(group['key']) for group in groups ]
117
+
118
+ def _add_archive(self, archive: Action):
119
+ _data = archive.__dict__.copy()
120
+
121
+ if type(archive) == Sanction:
122
+ _data['type'] = "sanction"
123
+ elif type(archive) == AdminAction:
124
+ _data['type'] = "adminaction"
125
+ else:
126
+ _data['type'] = "unknown"
127
+
128
+ del _data['id']
129
+
130
+ self.archives.put(key = archive.id, data = _data)
131
+
132
+ def _get_archive(self, id: str) -> Action | Sanction | AdminAction:
133
+ _data = self.archives.get(id)
134
+
135
+ if _data is None:
136
+ return None
137
+
138
+ if _data['type'] == "sanction": # Mute, ban, GAV, kick, détention, prune (xp seulement)
139
+ archive = Sanction(_data['author'], _data['target'])
140
+
141
+ archive.details = _data['details']
142
+ archive.major = _data['major']
143
+ archive.duration = _data['duration']
144
+ elif _data['type'] == "adminaction": # Renommage, promotion, démotion (au niveau de l'état)
145
+ archive = AdminAction(_data['author'], _data['target'])
146
+
147
+ archive.details = _data['details']
148
+ archive.new_state = _data['new_state']
149
+ else:
150
+ archive = Action(_data['author'], _data['target'])
151
+
152
+ archive.id = id
153
+ archive.action = _data['action']
154
+ archive.date = _data['date']
155
+
156
+ return archive
157
+
158
+ def _fetch_archives(self, **query) -> list[ Action | Sanction | AdminAction ]:
159
+ _res = self.archives.fetch(query).items
160
+
161
+ return [ self._get_archive(archive['key']) for archive in _res ]
162
+
163
+ class RepublicInstance:
164
+ def __init__(self, token: str) -> None:
165
+ self.db = deta.Deta(token)
166
+ self.votes = self.db.Base('votes')
167
+ self.archives = self.db.Base('archives')
168
+ self.mandate = self.db.Base('mandate')
169
+ self.functions = self.db.Base('functions') # Liste des fonctionnaires
170
+
171
+ def get_vote(self, id: str) -> Vote | ClosedVote:
172
+ id = id.upper()
173
+ _data = self.votes.get(id)
174
+
175
+ if _data is None:
176
+ return None
177
+
178
+ if _data['_type'] == 'open':
179
+ vote = Vote(id, _data['title'], tuple(_data['choices'].keys()))
180
+ elif _data['_type'] == 'closed':
181
+ vote = ClosedVote(id, _data['title'])
182
+ else:
183
+ vote = Vote('0', 'Unknown Vote', ())
184
+
185
+ vote.author = _data['author']
186
+ vote.startDate = _data['startDate']
187
+ vote.endDate = _data['endDate']
188
+ vote.choices = _data['choices']
189
+
190
+ return vote
191
+
192
+ def save_vote(self, vote: Vote | ClosedVote):
193
+ _data = {
194
+ '_type': 'open' if type(vote) == Vote else 'closed' if type(vote) == ClosedVote else 'unknown',
195
+ 'title': vote.title,
196
+ 'author': vote.author,
197
+ 'startDate': vote.startDate,
198
+ 'endDate': vote.endDate,
199
+ 'choices': vote.choices
200
+ }
201
+
202
+ self.votes.put(_data, vote.id.upper())
203
+
204
+ def get_official(self, id: str, current_mandate: bool = True) -> FunctionalUser:
205
+ archives = self.mandate if current_mandate else self.archives
206
+
207
+ _contributions = archives.fetch({'author': id, 'type': 'contrib'}).items
208
+ _mandates = archives.fetch({'target': id, 'type': 'election'}).items()\
209
+ + archives.fetch({'target': id, 'type': 'promotion'}).items()
210
+
211
+ user = FunctionalUser(id)
212
+ for mandate in _mandates:
213
+ if mandate['position'].startswith('MIN'): mandate['position'] = 'MIN'
214
+
215
+ try:
216
+ user.mandates[mandate['position']] += 1
217
+ except KeyError:
218
+ user.mandates[mandate['position']] = 1
219
+
220
+ for contrib in _contributions:
221
+ try:
222
+ user.contributions[contrib['action']] += 1
223
+ except KeyError:
224
+ user.contributions[contrib['action']] = 1
225
+
226
+ return user
227
+
228
+ def get_institutions(self) -> Organization:
229
+ admin = Administration()
230
+ gov = Government(FunctionalUser('0'))
231
+ assembly = Assembly()
232
+ court = Court()
233
+ police_forces = PoliceForces()
234
+
235
+ _admins = self.functions.get('ADMIN')
236
+ admin.members = [ self.get_official(user) for user in _admins['users'] ]
237
+ admin.president = self.get_official('F7DB60DD1C4300A') # happex (remplace Kheops pour l'instant)
238
+
239
+ gov.president = self.get_official(self.functions.get('PRE_REP')['users'][0])
240
+
241
+ minister = lambda code : self.get_official(self.functions.get(f'MIN_{code}')['users'][0])
242
+ gov.prime_minister = minister('PRIM')
243
+ gov.economy_minister = minister('ECO')
244
+ gov.inner_minister = minister('INN')
245
+ gov.press_minister = minister('AUD')
246
+ gov.justice_minister = minister('JUS')
247
+ gov.outer_minister = minister('OUT')
248
+
249
+ assembly.president = self.get_official(self.functions.get('PRE_AS')['users'][0])
250
+ assembly.members = [ self.get_official(id) for id in self.functions.get('REPR')['users'] ]
251
+
252
+ court.president = gov.justice_minister
253
+ court.members = [ self.get_official(id) for id in self.functions.get('JUDGE')['users'] ]
254
+
255
+ police_forces.president = gov.inner_minister
256
+ police_forces.members = [ self.get_official(id) for id in self.functions.get('POLICE')['users'] ]
257
+
258
+ instits = Institutions()
259
+ instits.administration = admin
260
+ instits.government = gov
261
+ instits.court = court
262
+ instits.assembly = assembly
263
+ instits.police = police_forces
264
+
265
+ return instits
266
+
267
+ def update_institutions(self, institutions: Institutions):
268
+ get_ids = lambda institution : [ member.id for member in institutions.__getattribute__(institution).members ]
269
+
270
+ self.functions.put(key = 'ADMIN', data = { 'users': get_ids('administration') })
271
+ self.functions.put(key = 'REPR', data = { 'users': get_ids('assembly') })
272
+ self.functions.put(key = 'JUDGE', data = { 'users': get_ids('court') })
273
+ self.functions.put(key = 'POLICE', data = { 'users': get_ids('police') })
274
+
275
+ self.functions.put(key = 'PRE_AS', data = { 'users': [ institutions.assembly.president.id ] })
276
+ self.functions.put(key = 'PRE_REP', data = { 'users': [ institutions.government.president.id ] })
277
+
278
+ self.functions.put(key = 'MIN_PRIM', data = { 'users': [ institutions.government.prime_minister.id ] })
279
+ self.functions.put(key = 'MIN_INN', data = { 'users': [ institutions.government.inner_minister.id ] })
280
+ self.functions.put(key = 'MIN_JUS', data = { 'users': [ institutions.government.justice_minister.id ] })
281
+ self.functions.put(key = 'MIN_ECO', data = { 'users': [ institutions.government.economy_minister.id ] })
282
+ self.functions.put(key = 'MIN_AUD', data = { 'users': [ institutions.government.press_minister.id ] })
283
+ self.functions.put(key = 'MIN_OUT', data = { 'users': [ institutions.government.outer_minister.id ] })
284
+
285
+ def new_mandate(self, institutions: Institutions, weeks: int = 4):
286
+ for item in self.mandate.fetch().items():
287
+ if item['date'] >= round(time.time()) - weeks * 604800:
288
+ self.mandate.delete(item['id'])
289
+
290
+ self.update_institutions(institutions)
291
+
292
+ def _add_archive(self, archive: Action):
293
+ _data = archive.__dict__.copy()
294
+
295
+ if type(archive) == Election:
296
+ _data['type'] = "election"
297
+ elif type(archive) == Promotion:
298
+ _data['type'] = "promotion"
299
+ elif type(archive) == Demotion:
300
+ _data['type'] = "demotion"
301
+ else:
302
+ _data['type'] = "unknown"
303
+
304
+ del _data['id']
305
+
306
+ self.archives.put(key = archive.id, data = _data)
307
+
308
+ def _get_archive(self, id: str) -> Action | Election | Promotion | Demotion:
309
+ _data = self.archives.get(id)
310
+
311
+ if _data is None:
312
+ return None
313
+
314
+ if _data['type'] == "election":
315
+ archive = Election(_data['author'], _data['target'], _data['position'])
316
+
317
+ archive.positive_votes = _data['positive_votes']
318
+ archive.total_votes = _data['total_votes']
319
+ elif _data['type'] == "promotion":
320
+ archive = Promotion(_data['author'], _data['target'], _data['position'])
321
+ elif _data['type'] == "demotion":
322
+ archive = Demotion(_data['author'], _data['target'])
323
+
324
+ archive.reason = _data['reason']
325
+ else:
326
+ archive = Action(_data['author'], _data['target'])
327
+
328
+ archive.id = id
329
+ archive.action = _data['action']
330
+ archive.date = _data['date']
331
+
332
+ return archive
333
+
334
+ def _fetch_archives(self, **query) -> list[ Action | Election | Promotion | Demotion ]:
335
+ _res = self.archives.fetch(query).items
336
+
337
+ return [ self._get_archive(archive['key']) for archive in _res ]
338
+
339
+ class BankInstance:
340
+ def __init__(self, token: str) -> None:
341
+ self.db = deta.Deta(token)
342
+ self.archives = self.db.Base('archives')
343
+ self.accounts = self.db.Base('accounts')
344
+ self.registry = self.db.Base('banks')
345
+
346
+ def get_account(self, id: str) -> BankAccount:
347
+ id = id.upper()
348
+ _data = self.accounts.get(id)
349
+
350
+ if _data is None:
351
+ return None
352
+
353
+ acc = BankAccount(id)
354
+ acc.amount = _data['amount']
355
+ acc.locked = _data['locked']
356
+ acc.owner = _data['owner_id']
357
+ acc.bank = _data['bank']
358
+
359
+ return acc
360
+
361
+ def save_account(self, acc: BankAccount):
362
+ _data = {
363
+ 'amount': acc.amount,
364
+ 'locked': acc.locked,
365
+ 'owner_id': acc.owner,
366
+ 'bank': acc.bank
367
+ }
368
+
369
+ self.accounts.put(_data, acc.id.upper())
370
+
371
+ def lock_account(self, acc: BankAccount):
372
+ acc.locked = True
373
+
374
+ self.save_account(acc)
375
+
376
+ def _add_archive(self, _archive: Action):
377
+ _data = _archive.__dict__.copy()
378
+
379
+ if type(_archive) == Transaction:
380
+ _data['type'] = "transaction"
381
+ else:
382
+ _data['type'] = "unknown"
383
+
384
+ del _data['id']
385
+
386
+ self.archives.put(key = _archive.id, data = _data)
387
+
388
+ def _get_archive(self, id: str) -> Action | Transaction:
389
+ _data = self.archives.get(id)
390
+
391
+ if _data is None:
392
+ return None
393
+
394
+ if _data['type'] == "transaction":
395
+ archive = Transaction(_data['author'], _data['target'], _data['amount'])
396
+
397
+ archive.reason = _data['reason']
398
+ archive.currency = _data['currency']
399
+ else:
400
+ archive = Action(_data['author'], _data['target'])
401
+
402
+ archive.id = id
403
+ archive.action = _data['action']
404
+ archive.date = _data['date']
405
+
406
+ return archive
73
407
 
74
- def get_entity_groups(self, id: int) -> list[Organization]:
75
- groups = self.fetch({'_type': 'organization'}, {'members': str(id)})
408
+ def _fetch_archives(self, **query) -> list[ Action | Transaction ]:
409
+ _res = self.archives.fetch(query).items
76
410
 
77
- return [ self.get_entity(int(group['id'], 16)) for group in groups ]
411
+ return [ self._get_archive(archive['key']) for archive in _res ]
Binary file
@@ -0,0 +1,60 @@
1
+ import time
2
+
3
+ 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)
7
+ self.action: str = ""
8
+ self.author: str = author
9
+ self.target: str = target
10
+
11
+
12
+ # Entities
13
+
14
+ class Sanction(Action):
15
+ def __init__(self, author: str, target: str) -> None:
16
+ super().__init__(author, target)
17
+
18
+ self.details: str = ""
19
+ self.major: bool = False # Sanction majeure ou non
20
+ self.duration: int = 0 # Durée en secondes, 0 = définitif
21
+
22
+ class AdminAction(Action):
23
+ def __init__(self, author: str, target: str) -> None:
24
+ super().__init__(author, target)
25
+
26
+ self.details: str = ""
27
+ self.new_state: str | int | bool = None
28
+
29
+
30
+ # Community
31
+
32
+ class Election(Action):
33
+ def __init__(self, author: str, target: str, position: str) -> None:
34
+ super().__init__(author, target)
35
+
36
+ self.position: str = position
37
+ self.positive_votes: int = 0
38
+ self.total_votes: int = 0
39
+
40
+ class Promotion(Action):
41
+ def __init__(self, author: str, target: str, position: str) -> None:
42
+ super().__init__(author, target)
43
+
44
+ self.position: str = position
45
+
46
+ class Demotion(Action):
47
+ def __init__(self, author: str, target: str) -> None:
48
+ super().__init__(author, target)
49
+
50
+ self.reason: str = None
51
+
52
+ # Bank
53
+
54
+ class Transaction(Action):
55
+ def __init__(self, author: str, target: str, amount: int) -> None:
56
+ super().__init__(author, target)
57
+
58
+ self.amount: int = amount
59
+ self.currency: str = 'HC'
60
+ self.reason: str = None
nsarchive/cls/bank.py ADDED
@@ -0,0 +1,7 @@
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"
nsarchive/cls/entities.py CHANGED
@@ -1,23 +1,18 @@
1
+ import io
1
2
  import time
2
3
 
3
4
  from .exceptions import *
4
5
 
6
+ from ..utils import assets
7
+
5
8
  class Entity:
6
- def __init__(self, id: str):
7
- self.id: str = id # ID hexadécimal de l'entité
8
- self.name: str = 'Entité Inconnue'
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)
11
+ self.name: str = "Entité Inconnue"
9
12
  self.registerDate: int = 0
10
- self.legalPosition: int = 'Normal'
11
- self.xp: int = 0
12
-
13
- def get_level(self) -> None:
14
- i = 0
15
- while self.xp > int(round(25 * (i * 2.5) ** 2, -2)):
16
- i += 1
17
-
18
- return i
13
+ self.legalPosition: str = 'Membre'
19
14
 
20
- def rename(self, new_name: str) -> None:
15
+ def set_name(self, new_name: str) -> None:
21
16
  if len(new_name) > 32:
22
17
  raise NameTooLongError(f"Name length mustn't exceed 32 characters.")
23
18
 
@@ -25,36 +20,80 @@ class Entity:
25
20
 
26
21
  def set_position(self, position: str) -> None:
27
22
  self.legalPosition = position
28
-
29
- def add_xp(self, amount: int) -> None:
30
- boost = 0 if 0 in self.boosts.values() else max(list(self.boosts.values()) + [ 1 ])
31
23
 
32
- self.xp += amount * boost
33
-
34
24
  class User(Entity):
35
- def __init__(self, id: str):
25
+ def __init__(self, id: str) -> None:
36
26
  super().__init__(id)
37
27
 
28
+ self.xp: int = 0
38
29
  self.boosts: dict[str, int] = {}
30
+
31
+ def get_level(self) -> None:
32
+ i = 0
33
+ while self.xp > int(round(25 * (i * 2.5) ** 2, -2)):
34
+ i += 1
35
+
36
+ return i
39
37
 
38
+ def add_xp(self, amount: int) -> None:
39
+ boost = 0 if 0 in self.boosts.values() else max(list(self.boosts.values()) + [ 1 ])
40
+
41
+ self.xp += amount * boost
42
+
40
43
  def edit_boost(self, name: str, multiplier: int = -1) -> None:
41
44
  if multiplier >= 0:
42
45
  self.boosts[name] = multiplier
43
46
  else:
44
47
  del self.boosts[name]
45
48
 
49
+ class MemberPermissions:
50
+ def __init__(self) -> None:
51
+ self.manage_organization = False # Renommer ou changer le logo
52
+ self.manage_members = False # Virer quelqu'un d'une entreprise, l'y inviter, changer ses rôles
53
+ self.manage_roles = False # Promouvoir ou rétrograder les membres
54
+
55
+ def edit(self, **permissions: bool) -> None:
56
+ for perm in permissions.values():
57
+ self.__setattr__(*perm)
58
+
59
+ class GroupMember(User):
60
+ def __init__(self, id: str) -> None:
61
+ super().__init__(id)
62
+
63
+ self.permissions: MemberPermissions = MemberPermissions()
64
+
65
+ class FunctionalUser:
66
+ def __init__(self, id: str) -> None:
67
+ self.id: str = id
68
+
69
+ self.mandates: int = {
70
+ 'PRE_REP': 0, # Président de la République
71
+ 'MIN': 0, # Différents ministres
72
+ 'PRE_AS': 0, # Président de l'Assemblée Nationale
73
+ 'JUDGE': 0, # Juge
74
+ 'REPR': 0 # Député
75
+ }
76
+
77
+ self.contributions: dict = {
78
+ 'project': 0,
79
+ 'approved_project': 0,
80
+ 'admin_action': 0,
81
+ 'law_vote': 0
82
+ }
83
+
46
84
  class Organization(Entity):
47
- def __init__(self, id: str):
85
+ def __init__(self, id: str) -> None:
48
86
  super().__init__(id)
49
87
 
50
88
  self.owner: Entity
51
89
  self.certifications: dict = {}
52
- self.members: list = []
53
-
90
+ self.members: list[GroupMember] = []
91
+ self.avatar: bytes = assets.open('default_avatar.png')
92
+
54
93
  def add_certification(self, certif: str) -> None:
55
94
  self.certifications[certif] = round(time.time())
56
95
 
57
- def add_member(self, member: User) -> None:
96
+ def add_member(self, member: GroupMember) -> None:
58
97
  self.members.append(member)
59
98
 
60
99
  def remove_member(self, member: User) -> None:
@@ -62,4 +101,12 @@ class Organization(Entity):
62
101
  self.members.remove(member)
63
102
 
64
103
  def set_owner(self, member: User) -> None:
65
- self.owner = member
104
+ self.owner = member
105
+
106
+ 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] = []
@@ -8,6 +8,9 @@ class EntityTypeError(Exception):
8
8
  def __init__(self, *args: object) -> None:
9
9
  super().__init__(*args)
10
10
 
11
+ class AvatarTooLongError(Exception):
12
+ def __init__(self, *args: object) -> None:
13
+ super().__init__(*args)
11
14
 
12
15
  # Exceptions pour le vote
13
16
 
@@ -0,0 +1,59 @@
1
+ from .entities import *
2
+
3
+ # Votes
4
+
5
+ class Vote:
6
+ def __init__(self, id: str, title: str, choices: tuple[str]) -> None:
7
+ self.id: str = id
8
+ self.title: str = title
9
+ self.choices = { choice : 0 for choice in choices }
10
+ self.author: str = '0'
11
+ self.startDate: int = 0
12
+ self.endDate: int = 0
13
+
14
+ class ClosedVote(Vote):
15
+ def __init__(self, id: str, title: str) -> None:
16
+ super().__init__(id, title, ('yes', 'no', 'blank'))
17
+
18
+
19
+ # Institutions (defs)
20
+
21
+ class Administration:
22
+ def __init__(self) -> None:
23
+ self.president: FunctionalUser
24
+ self.members: list[FunctionalUser]
25
+
26
+ class Government:
27
+ def __init__(self, president: FunctionalUser) -> None:
28
+ self.president: FunctionalUser = president
29
+ self.prime_minister: FunctionalUser
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
36
+
37
+ class Assembly:
38
+ def __init__(self) -> None:
39
+ self.president: FunctionalUser
40
+ self.members: list[FunctionalUser]
41
+
42
+ class Court:
43
+ def __init__(self) -> None:
44
+ self.president: FunctionalUser
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]
47
+
48
+ class PoliceForces:
49
+ def __init__(self) -> None:
50
+ self.president: FunctionalUser
51
+ self.members: list[FunctionalUser]
52
+
53
+ class Institutions:
54
+ def __init__(self) -> None:
55
+ self.administration: Administration
56
+ self.government: Government
57
+ self.court: Court
58
+ self.assembly: Assembly
59
+ self.police: PoliceForces
@@ -0,0 +1,15 @@
1
+ import io
2
+ import os
3
+ from PIL import Image
4
+
5
+ def open(path: str) -> Image:
6
+ curr_dir = os.path.dirname(os.path.abspath(os.path.join(__file__)))
7
+ parent_dir = os.path.dirname(curr_dir)
8
+ asset_path = os.path.join(parent_dir, 'assets', path)
9
+
10
+ image = Image.open(asset_path)
11
+ val = io.BytesIO()
12
+
13
+ image.save(val, format = 'PNG')
14
+
15
+ return val.getvalue()
@@ -0,0 +1,175 @@
1
+ Metadata-Version: 2.1
2
+ Name: nsarchive
3
+ Version: 0.1b0
4
+ Summary:
5
+ License: GPL-3.0
6
+ Author: happex
7
+ Author-email: 110610727+okayhappex@users.noreply.github.com
8
+ Requires-Python: >=3.10,<4.0
9
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Description-Content-Type: text/markdown
15
+
16
+ # nsarchive
17
+
18
+ `nsarchive` est un module Python pour la gestion des entités (utilisateurs et organisations) à l'aide de la base de données Deta. Ce module permet de créer, récupérer, sauvegarder et gérer des entités et leurs attributs spécifiques.
19
+
20
+ ## Pré-requis
21
+
22
+ Listes des choses à avoir afin de pouvoir utiliser le module correctement:
23
+ - [Python 3.10](https://www.python.org/downloads/) ou supérieur
24
+ - Un token [Deta](https://deta.space), donné par un administrateur ou pour votre collection personnelle
25
+ - Un bon capuccino, pour commencer la programmation en bons termes
26
+
27
+ > **Note:** Il vous faudra un token différent pour accéder aux différentes parties de la base de données. Vos tokens n'expireront pas à moins que l'ordre en aura été donné
28
+
29
+ ## Installation
30
+
31
+ Vous pouvez installer ce module via pip :
32
+
33
+ ```sh
34
+ pip install nsarchive
35
+ ```
36
+
37
+ ## Utilisation
38
+
39
+ ### Importation et Initialisation
40
+
41
+ Pour utiliser `nsarchive`, commencez par importer le module et initialiser une instance d'`EntityInstance` avec votre token Deta.
42
+
43
+ ```python
44
+ from nsarchive import EntityInstance
45
+
46
+ # Remplacez 'your_deta_token' par votre véritable token Deta
47
+ entity_instance = EntityInstance(token = 'your_deta_token')
48
+ ```
49
+
50
+ ### Récupérer une Entité
51
+
52
+ Vous pouvez récupérer une entité (Utilisateur ou Organisation) à l'aide de son ID.
53
+
54
+ ```python
55
+ entity = entity_instance.get_entity(id = 'entity_id')
56
+ print(entity.name)
57
+ ```
58
+
59
+ **ATTENTION: Les entités sont identifiées sous une forme hexadécimale. Pour les avoir, vous devez convertir leur ID Discord en hexadécimale puis enlever le préfixe `0x`.**
60
+
61
+ Pour les organisations, l'ID Discord correspondra à la formule suivante: `ID fondateur // 100000`.
62
+
63
+ N'oubliez pas de toujours utiliser un `str` dans les ID pour interagir avec la base de données.
64
+
65
+ ### Sauvegarder une Entité
66
+
67
+ Après avoir modifié une entité, vous pouvez la sauvegarder dans la base de données.
68
+
69
+ ```python
70
+ entity.rename("Nouveau Nom")
71
+ entity_instance.save_entity(entity)
72
+ ```
73
+
74
+ ### Rechercher des Entités
75
+
76
+ Vous pouvez rechercher des entités avec des critères spécifiques.
77
+
78
+ ```python
79
+ entities = entity_instance.fetch_entity(query = {'name': 'Alice'})
80
+ for entity in entities:
81
+ print(entity['name'])
82
+ ```
83
+
84
+ ### Gérer les Organisations
85
+
86
+ Les organisations peuvent avoir des membres et des certifications. Voici comment ajouter un membre ou une certification.
87
+
88
+ ```python
89
+ organization = entity_instance.get_entity(id = 'org_id')
90
+ user = entity_instance.get_entity(id = 'user_id')
91
+
92
+ # Ajouter un membre
93
+ organization.add_member(user)
94
+ entity_instance.save_entity(organization)
95
+
96
+ # Ajouter une certification
97
+ organization.add_certification('Certification Example')
98
+ entity_instance.save_entity(organization)
99
+ ```
100
+
101
+ Les certifications pourront être utilisées pour vérifier l'officialité d'une organisation, mais également pour déterminer si l'on peut accorder (ou non) des permissions à ses membres.
102
+
103
+ ### Exemples de Classes
104
+
105
+ #### `Entity`
106
+
107
+ Classe parente des classes `User` et `Organization`, elle est utilisée lorsque le module ne peut pas déterminer l'appartenance d'une identité à l'une de ces deux classes ou à l'autre.
108
+
109
+ ```python
110
+ from nsarchive.cls.entities import Entity
111
+
112
+ entity = Entity(id='entity_id')
113
+ entity.rename('New Name')
114
+ entity.add_xp(100)
115
+ print(entity.get_level())
116
+ ```
117
+
118
+ #### `User`
119
+
120
+ ```python
121
+ from nsarchive.cls.entities import User
122
+
123
+ user = User(id = 'user_id')
124
+ user.edit_boost(name = 'admin', multiplier = 5) # Négliger le paramètre <multiplier> ou le fixer à un nombre négatif reviendrait à supprimer le boost.
125
+ print(user.boosts)
126
+ ```
127
+
128
+ > **Note:** Lorsqu'on ajoute de l'expérience à un utilisateur via la méthode `add_xp`, le nombre de points ajoutés est automatiquement multiplié par le bonus le plus important dont l'utilisateur bénéficie.
129
+
130
+ #### `Organization`
131
+
132
+ ```python
133
+ from nsarchive.cls.entities import Organization
134
+
135
+ organization = Organization(id = 'org_id')
136
+ organization.set_owner(user)
137
+ organization.add_member(user)
138
+ print(organization.members)
139
+ ```
140
+
141
+ > **Note:** Les attributs `owner` et `members` sont indépendants. L'owner peut être n'importe quelle personne faisant ou non partie des `members`.
142
+
143
+ ## Gestion des Exceptions
144
+
145
+ `nsarchive` fournit des exceptions spécifiques pour gérer les erreurs courantes.
146
+
147
+ #### `NameTooLongError`
148
+
149
+ Lancé lorsque le nom d'une entité dépasse la longueur maximale autorisée (32 caractères).
150
+
151
+ ```python
152
+ from nsarchive.cls.exceptions import NameTooLongError
153
+
154
+ try:
155
+ entity.rename('Ce nom est long, voire même très long, je dirais même extrêmement long')
156
+ except NameTooLongError as e:
157
+ print(e)
158
+ ```
159
+
160
+ #### `EntityTypeError`
161
+
162
+ Lancé lorsque le type d'entité est incorrect. Vous ne devriez normalement pas la rencontrer en utilisant le module, mais elle pourrait vous être utile.
163
+
164
+ ```python
165
+ from nsarchive.cls.exceptions import EntityTypeError
166
+
167
+ try:
168
+ # Code qui peut lancer une EntityTypeError
169
+ except EntityTypeError as e:
170
+ print(e)
171
+ ```
172
+
173
+ ## License
174
+
175
+ Ce projet est sous licence GNU GPL-3.0 - Voir le fichier [LICENSE](LICENSE) pour plus de détails.
@@ -0,0 +1,12 @@
1
+ nsarchive/__init__.py,sha256=Y-I47MuPc8FIHIhvt8RZ-t5TXAi7APD0XlfEjqevfjk,15273
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=u5u46HzHJp2H_DngLALLgedHaLXlJpjhmxU_Ggozp3Q,3474
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.1b0.dist-info/LICENSE,sha256=aFLFZg6LEJFpTlNQ8su3__jw4GfV-xWBmC1cePkKZVw,35802
10
+ nsarchive-0.1b0.dist-info/METADATA,sha256=rvpiq-iES71BGQ2r4pUmSPeItUkt0KW6u-XqZExWNXk,5559
11
+ nsarchive-0.1b0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
12
+ nsarchive-0.1b0.dist-info/RECORD,,
nsarchive/cls/votes.py DELETED
@@ -1,7 +0,0 @@
1
- import time
2
-
3
- class Vote:
4
- def __init__(self, id: int, title: str, choices: list[str]) -> None:
5
- self.id: int = id
6
- self.title: str = title
7
- self.choices = { choice : 0 for choice in choices }
@@ -1,17 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: nsarchive
3
- Version: 0.1a0
4
- Summary:
5
- License: GPL-3.0
6
- Author: happex
7
- Author-email: 110610727+okayhappex@users.noreply.github.com
8
- Requires-Python: >=3.10,<4.0
9
- Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
- Description-Content-Type: text/markdown
15
-
16
- # 1ns-archive
17
-
@@ -1,8 +0,0 @@
1
- nsarchive/__init__.py,sha256=cWlY3WvOeAmzwU0TC6VH0V2NfZeL4dbi_7ocneQ5els,2767
2
- nsarchive/cls/entities.py,sha256=IrQSciTyb1fS-AumcGxyD35ONfvNa49CwfTQNDrFEkA,1895
3
- nsarchive/cls/exceptions.py,sha256=TrH9PvHhVZi7wap9ZfBLGRWJY3OBCYgWAMnco5uadYY,420
4
- nsarchive/cls/votes.py,sha256=p5QnvQQTaKkZDjfZa2qDgGrpCmu4vQV8-9drPayZ0oE,221
5
- nsarchive-0.1a0.dist-info/LICENSE,sha256=aFLFZg6LEJFpTlNQ8su3__jw4GfV-xWBmC1cePkKZVw,35802
6
- nsarchive-0.1a0.dist-info/METADATA,sha256=Kn6vtRhpgpk091l-IlmMpfUGVf8bbnfig0eA63c93cw,518
7
- nsarchive-0.1a0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
8
- nsarchive-0.1a0.dist-info/RECORD,,