nsarchive 1.3.0__py3-none-any.whl → 2.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.
@@ -0,0 +1,313 @@
1
+ import time
2
+
3
+ from supabase import create_client
4
+
5
+ from ..cls.base import *
6
+ from ..cls.archives import *
7
+ from ..cls.economy import *
8
+
9
+ from ..cls.exceptions import *
10
+
11
+ class EconomyInstance(Instance):
12
+ """Gère les interactions avec les comptes bancaires, les transactions, et le marché."""
13
+
14
+ def __init__(self, id: str, token: str) -> None:
15
+ super().__init__(create_client(f"https://{id}.supabase.co", token))
16
+
17
+ """
18
+ ---- COMPTES EN BANQUE ----
19
+ """
20
+
21
+ def get_account(self, id: NSID) -> BankAccount:
22
+ """
23
+ Récupère les informations d'un compte bancaire.
24
+
25
+ ## Paramètres
26
+ id: `NSID`\n
27
+ ID du compte.
28
+
29
+ ## Renvoie
30
+ - `.BankAccount`
31
+ """
32
+
33
+ id = NSID(id)
34
+ _data = self._get_by_ID('accounts', id)
35
+
36
+ if _data is None:
37
+ return None
38
+
39
+ account = BankAccount(id)
40
+ account.amount = _data['amount']
41
+ account.frozen = _data['frozen']
42
+ account.owner = NSID(_data['owner_id'])
43
+ account.bank = _data['bank']
44
+ account.income = _data['income']
45
+
46
+ return account
47
+
48
+ def save_account(self, account: BankAccount):
49
+ """
50
+ Sauvegarde un compte bancaire dans la base de données.
51
+
52
+ ## Paramètres
53
+ - account: `.BankAccount`\n
54
+ Compte à sauvegarder
55
+ """
56
+
57
+ _data = {
58
+ 'id': NSID(account.id),
59
+ 'amount': account.amount,
60
+ 'frozen': account.frozen,
61
+ 'owner_id': account.owner,
62
+ 'bank': account.bank,
63
+ 'income': account.income
64
+ }
65
+
66
+ self._put_in_db('accounts', _data)
67
+
68
+ def freeze_account(self, account: BankAccount):
69
+ """
70
+ Gèle un compte bancaire pour empêcher toute transaction.
71
+
72
+ ## Paramètres
73
+ - account: `.BankAccount`\n
74
+ Compte à geler
75
+ """
76
+
77
+ account.id = NSID(account.id)
78
+ account.frozen = True
79
+
80
+ self.save_account(account)
81
+
82
+ """
83
+ ---- OBJETS & VENTES ----
84
+ """
85
+
86
+ def save_item(self, item: Item):
87
+ """
88
+ Sauvegarde des infos à propos d'un item.
89
+
90
+ ## Paramètres
91
+ item: `.Item`\n
92
+ Article à sauvegarder
93
+ """
94
+
95
+ _item = item.__dict__
96
+ self._put_in_db('items', _item)
97
+
98
+ def get_item(self, id: NSID) -> Item | None:
99
+ """
100
+ Récupère des informations à propos d'un item.
101
+
102
+ ## Paramètres
103
+ id: `NSID`\n
104
+ ID de l'item
105
+
106
+ ## Retourne
107
+ - `.Item` si quelque chose est trouvé, sinon
108
+ - `None`
109
+ """
110
+
111
+ _item = self._get_by_ID('items', id)
112
+
113
+ if _item is None:
114
+ return
115
+
116
+ item = Item(id)
117
+ item.title = _item['title']
118
+ item.emoji = _item['emoji']
119
+
120
+ return item
121
+
122
+ def delete_item(self, item: Item):
123
+ """
124
+ Annule le référencement d'un item.
125
+
126
+ ## Paramètres
127
+ item: `.Item`\n
128
+ Item à supprimer
129
+ """
130
+
131
+ self._delete_by_ID('items', item.id)
132
+
133
+ def get_sale(self, id: NSID) -> Sale | None:
134
+ """
135
+ Récupère une vente disponible sur le marketplace.
136
+
137
+ ## Paramètres
138
+ id: `NSID`\n
139
+ ID de la vente.
140
+
141
+ ## Renvoie
142
+ - `.Sale | None`: Le résultat de la vente
143
+ """
144
+
145
+ id = NSID(id)
146
+
147
+ _data = self._get_by_ID('market', id)
148
+
149
+ if _data is None:
150
+ return None
151
+
152
+ item = self.get_item(_data['id'])
153
+
154
+ sale = Sale(NSID(id), Item(_data['id']) if item is None else item)
155
+ sale.__dict__ = _data
156
+
157
+ return sale
158
+
159
+ def sell_item(self, item: Item, quantity: int, price: int, seller: NSID):
160
+ """
161
+ Vend un item sur le marché.
162
+
163
+ ## Paramètres
164
+ item: `.Item`\n
165
+ Item à vendre
166
+ quantity: `int`\n
167
+ Nombre d'items à vendre
168
+ price: `int`\n
169
+ Prix à l'unité de chaque objet
170
+ seller: `NSID`\n
171
+ ID de l'auteur de la vente
172
+ """
173
+
174
+ sale = Sale(NSID(round(time.time()) * 16 ** 3), item)
175
+ sale.quantity = quantity
176
+ sale.price = price
177
+ sale.seller_id = seller
178
+
179
+ _data = sale.__dict__.copy()
180
+
181
+ self._put_in_db('market', _data)
182
+
183
+ def delete_sale(self, sale: Sale) -> None:
184
+ """Annule une vente sur le marketplace."""
185
+
186
+ sale.id = NSID(sale.id)
187
+ self._delete_by_ID('market', NSID(sale.id))
188
+
189
+ """
190
+ ---- INVENTAIRES ----
191
+ """
192
+
193
+ def get_inventory(self, id: NSID) -> Inventory | None:
194
+ """
195
+ Récupérer un inventaire dans la base des inventaires.
196
+
197
+ ## Paramètres
198
+ id: `NSID`\n
199
+ ID du propriétaire de l'inventaire
200
+
201
+ ## Retourne
202
+ - `.Inventory | None`: L'inventaire s'il a été trouvé
203
+ """
204
+
205
+ _data = self._get_by_ID('inventories', id)
206
+
207
+ if _data is None:
208
+ return None
209
+
210
+ inventory = Inventory(id)
211
+
212
+ for _item in _data['objects']:
213
+ item = self.get_item(_item)
214
+
215
+ inventory.objects.append(item)
216
+
217
+ return inventory
218
+
219
+ def save_inventory(self, inventory: Inventory):
220
+ """
221
+ Sauvegarder un inventaire
222
+
223
+ ## Paramètres
224
+ inventory: `.Inventory`\n
225
+ Inventaire à sauvegarder
226
+ """
227
+
228
+ _data = inventory.__dict__
229
+
230
+ self._put_in_db('inventories', _data)
231
+
232
+ def delete_inventory(self, inventory: Inventory):
233
+ """
234
+ Supprime un inventaire
235
+
236
+ ## Paramètres
237
+ inventory: `.Inventory`
238
+ Inventaire à supprimer
239
+ """
240
+
241
+ self._delete_by_ID('inventories', inventory.owner_id)
242
+
243
+ """
244
+ ---- ARCHIVES ----
245
+ """
246
+
247
+ def _add_archive(self, archive: Archive):
248
+ """
249
+ Ajoute une archive d'une transaction ou d'une vente dans la base de données.
250
+
251
+ ## Paramètres
252
+ - archive: `.Archive`\n
253
+ Archive à ajouter
254
+ """
255
+
256
+ archive.id = NSID(archive.id)
257
+ archive.author = NSID(archive.author)
258
+ archive.target = NSID(archive.target)
259
+
260
+ _data = archive.__dict__.copy()
261
+
262
+ if type(archive) == Transaction:
263
+ _data['_type'] = "transaction"
264
+ else:
265
+ _data['_type'] = "action"
266
+
267
+ self._put_in_db('archives', _data)
268
+
269
+ def _get_archive(self, id: NSID) -> Archive | Transaction:
270
+ """
271
+ Récupère une archive spécifique.
272
+
273
+ ## Paramètres
274
+ id: `NSID`\n
275
+ ID de l'archive.
276
+
277
+ ## Renvoie
278
+ - `.Archive | .Transaction`
279
+ """
280
+
281
+ id = NSID(id)
282
+ _data = self._get_by_ID('archives', id)
283
+
284
+ if _data is None:
285
+ return None
286
+
287
+ if _data['_type'] == "transaction":
288
+ archive = Transaction(_data['author'], _data['target'])
289
+ else:
290
+ archive = Archive(_data['author'], _data['target'])
291
+
292
+ archive.id = id
293
+ archive.action = _data['action']
294
+ archive.date = _data['date']
295
+ archive.details = _data['details']
296
+
297
+ return archive
298
+
299
+ def _fetch_archives(self, **query) -> list[ Archive | Transaction ]:
300
+ """
301
+ Récupère une liste d'archives correspondant à la requête.
302
+
303
+ ## Paramètres
304
+ query: `dict`\n
305
+ Requête pour filtrer les archives.
306
+
307
+ ## Renvoie
308
+ - `list[.Archive | .Transaction]`
309
+ """
310
+
311
+ _res = self.fetch('archives', **query)
312
+
313
+ return [ self._get_archive(archive['id']) for archive in _res ]
@@ -0,0 +1,321 @@
1
+ from supabase import create_client
2
+
3
+ from ..cls.base import *
4
+ from ..cls.entities import *
5
+ from ..cls.archives import *
6
+
7
+ from ..cls.exceptions import *
8
+
9
+ class EntityInstance(Instance):
10
+ """
11
+ Instance qui vous permettra d'interagir avec les profils des membres ainsi que les différents métiers et secteurs d'activité.
12
+
13
+ ## Informations disponibles
14
+ - Profil des membres et des entreprises: `.User | .Organization | .Entity`
15
+ - Participation d'un membre à différent votes: `.User | .Organization | .Entity`
16
+ - Appartenance et permissions d'un membre dans un groupe: `.GroupMember.MemberPermissions`
17
+ - Position légale et permissions d'une entité: `.Position.Permissions`
18
+ - Sanctions et modifications d'une entité: `.Action[ .AdminAction | .Sanction ]`
19
+ """
20
+
21
+ def __init__(self, id: str, token: str) -> None:
22
+ super().__init__(create_client(f"https://{id}.supabase.co", token))
23
+
24
+ """
25
+ ---- ENTITÉS ----
26
+ """
27
+
28
+ def get_entity(self, id: NSID) -> User | Organization | Entity:
29
+ """
30
+ Fonction permettant de récupérer le profil public d'une entité.\n
31
+
32
+ ## Paramètres
33
+ id: `NSID`\n
34
+ ID héxadécimal de l'entité à récupérer
35
+
36
+ ## Renvoie
37
+ - `.User` dans le cas où l'entité choisie est un membre
38
+ - `.Organization` dans le cas où c'est un groupe
39
+ - `.Entity` dans le cas où c'est indéterminé
40
+ """
41
+
42
+ id = NSID(id)
43
+
44
+ _data = self._get_by_ID('individuals', id)
45
+
46
+ if _data is None: # Aucune entité individuelle sous cet ID
47
+ _data = self._get_by_ID('organizations', id) # On cherche du côté des groupes
48
+ else:
49
+ _data['_type'] = 'user'
50
+
51
+ if _data is None: # ID inexistant chez les entités
52
+ return None
53
+ elif '_type' not in _data.keys(): # S'il existe chez les organisations, clé '_type' pas encore initialisée
54
+ _data['_type'] = 'organization'
55
+
56
+ if _data['_type'] == 'user':
57
+ entity = User(id)
58
+
59
+ entity.xp = _data['xp']
60
+ entity.boosts = _data['boosts']
61
+
62
+ entity.votes = [ NSID(vote) for vote in _data['votes'] ]
63
+ elif _data['_type'] == 'organization':
64
+ entity = Organization(id)
65
+
66
+ entity.owner = self.get_entity(NSID(_data['owner_id']))
67
+
68
+ for _member in _data['members']:
69
+ member = GroupMember(_member['id'])
70
+ member.permission_level = _member['position']
71
+
72
+ _member_profile = self.get_entity(member.id)
73
+
74
+ member.set_name(_member_profile.name)
75
+ member.position = _member_profile.position
76
+ member.registerDate = _member_profile.registerDate
77
+
78
+ member.xp = _member_profile.xp
79
+ member.boosts = _member_profile.boosts
80
+
81
+ member.permissions = _member_profile.permissions
82
+ member.votes = _member_profile.votes
83
+
84
+ entity.append(member)
85
+
86
+ entity.parts = []
87
+
88
+ for owner, attrs in _data['parts'].items():
89
+ entity.parts.extend(attrs['count'] * [ Share(NSID(owner), attrs['worth'] // attrs['count']) ])
90
+
91
+ entity.certifications = _data['certifications']
92
+ entity.avatar = self._download_from_storage('organizations', f"avatars/{entity.id}")
93
+ else:
94
+ entity = Entity(id)
95
+
96
+ entity.name = _data['name']
97
+ entity.position = self.get_position(_data['position']) # Métier si c'est un utilisateur, domaine professionnel si c'est un collectif
98
+ entity.registerDate = _data['register_date']
99
+
100
+ for key, value in _data.get('additional', {}).items():
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):
109
+ """
110
+ Fonction permettant de créer ou modifier une entité.
111
+
112
+ ## Paramètres
113
+ entity: `.Entity`\n
114
+ L'entité à sauvegarder
115
+ """
116
+
117
+ entity.id = NSID(entity.id)
118
+
119
+ _data = {
120
+ 'id': entity.id,
121
+ 'name': entity.name,
122
+ 'position': entity.position.id,
123
+ 'register_date': entity.registerDate,
124
+ 'additional': {},
125
+ }
126
+
127
+ for key, value in entity.additional.items():
128
+ if isinstance(value, int) and len(str(int)) >= 15:
129
+ _data['additional'][key] = '\n' + str(value)
130
+ elif type(value) in (str, int):
131
+ _data['additional'][key] = value
132
+
133
+ if type(entity) == Organization:
134
+ _data['owner_id'] = NSID(entity.owner.id) if entity.owner else NSID("0")
135
+ _data['members'] = []
136
+ _data['certifications'] = entity.certifications
137
+ _data['parts'] = entity.get_shares(True)
138
+
139
+ for member in entity.members:
140
+ _member = {
141
+ 'id': NSID(member.id),
142
+ 'position': member.permission_level
143
+ }
144
+
145
+ _data['members'] += [_member]
146
+
147
+ self._upload_to_storage('organizations', entity.avatar, f'/avatars/{entity.id}', overwrite = True)
148
+ elif type(entity) == User:
149
+ _data['xp'] = entity.xp
150
+ _data['boosts'] = entity.boosts
151
+ _data['votes'] = [ NSID(vote) for vote in entity.votes]
152
+
153
+ self._put_in_db('individuals' if isinstance(entity, User) else 'organizations', _data)
154
+
155
+ def delete_entity(self, entity: Entity):
156
+ """
157
+ Fonction permettant de supprimer le profil d'une entité
158
+
159
+ ## Paramètres
160
+ entity: `.Entity`\n
161
+ L'entité à supprimer
162
+ """
163
+
164
+ self._delete_by_ID('individuals' if isinstance(entity, User) else 'organizations', NSID(entity.id))
165
+
166
+ def fetch_entities(self, **query: typing.Any) -> list[ Entity | User | Organization ]:
167
+ """
168
+ Récupère une liste d'entités en fonction d'une requête.
169
+
170
+ ## Paramètres
171
+ query: `dict`\n
172
+ La requête pour filtrer les entités.
173
+
174
+ ## Renvoie
175
+ - `list[.Entity | .User | .Organization]`
176
+ """
177
+
178
+ if "_type" in query.keys():
179
+ if query["_type"] == "individual":
180
+ del query["_type"]
181
+ _res = self.fetch('individuals', **query)
182
+ elif query["_type"] == "organization":
183
+ del query["_type"]
184
+ _res = self.fetch('organizations', **query)
185
+ else:
186
+ del query["_type"]
187
+ _res = self.fetch('individuals', **query)
188
+ _res.extend(self.fetch('organizations', **query))
189
+ else:
190
+ _res = self.fetch('individuals', **query)
191
+ _res.extend(self.fetch('organizations', **query))
192
+
193
+ return [ self.get_entity(NSID(entity['id'])) for entity in _res if entity is not None ]
194
+
195
+ def get_entity_groups(self, id: NSID) -> list[Organization]:
196
+ """
197
+ Récupère les groupes auxquels appartient une entité.
198
+
199
+ ## Paramètres
200
+ id: `NSID`\n
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 = []
210
+
211
+ for group in _groups:
212
+ if group is None:
213
+ continue
214
+
215
+ if group.owner.id == id:
216
+ groups.append(group)
217
+
218
+ for member in group.members:
219
+ if member.id == id:
220
+ groups.append(group)
221
+
222
+ return [ group for group in groups ]
223
+
224
+ def get_position(self, id: str) -> Position:
225
+ """
226
+ Récupère une position légale (métier, domaine professionnel).
227
+
228
+ ## Paramètres
229
+ id: `str`\n
230
+ ID de la position (SENSIBLE À LA CASSE !)
231
+
232
+ ## Renvoie
233
+ - `.Position`
234
+ """
235
+
236
+ _data = self._get_by_ID('positions', id)
237
+
238
+ if _data is None:
239
+ return None
240
+
241
+ position = Position(id)
242
+ position.name = _data['title']
243
+ position.permissions.edit(**{ p: True for p in _data['permissions'] })
244
+
245
+ return position
246
+
247
+ """
248
+ ---- ARCHIVES --
249
+ """
250
+
251
+ def _add_archive(self, archive: Archive):
252
+ """
253
+ Ajoute une archive d'une action (modification au sein d'un groupe ou sanction) dans la base de données.
254
+
255
+ ## Paramètres
256
+ - archive: `.Archive`\n
257
+ Archive à ajouter
258
+ """
259
+
260
+ archive.id = NSID(archive.id)
261
+ archive.author = NSID(archive.author)
262
+ archive.target = NSID(archive.target)
263
+
264
+ _data = archive.__dict__.copy()
265
+
266
+ if type(archive) == Sanction:
267
+ _data['_type'] = "sanction"
268
+ elif type(archive) == Report:
269
+ _data['_type'] = "report"
270
+ else:
271
+ _data['_type'] = "action"
272
+
273
+ self._put_in_db('archives', _data)
274
+
275
+ def _get_archive(self, id: NSID) -> Archive | Sanction:
276
+ """
277
+ Récupère une archive spécifique.
278
+
279
+ ## Paramètres
280
+ id: `NSID`\n
281
+ ID de l'archive.
282
+
283
+ ## Renvoie
284
+ - `.Archive | .Sanction `
285
+ """
286
+
287
+ id = NSID(id)
288
+ _data = self._get_by_ID('archives', id)
289
+
290
+ if _data is None:
291
+ return None
292
+
293
+ if _data['_type'] == "sanction": # Mute, ban, GAV, kick, détention, prune (xp seulement)
294
+ archive = Sanction(_data['author'], _data['target'])
295
+ elif _data['_type'] == "report": # Plainte
296
+ archive = Report(_data['author'], _data['target'])
297
+ else:
298
+ archive = Archive(_data['author'], _data['target'])
299
+
300
+ archive.id = id
301
+ archive.date = _data['date']
302
+ archive.action = _data['action']
303
+ archive.details = _data['details']
304
+
305
+ return archive
306
+
307
+ def _fetch_archives(self, **query) -> list[ Archive | Sanction ]:
308
+ """
309
+ Récupère une liste d'archives correspondant à la requête.
310
+
311
+ ## Paramètres
312
+ query: `dict`\n
313
+ Requête pour filtrer les archives.
314
+
315
+ ## Renvoie
316
+ - `list[.Archive | .Sanction]`
317
+ """
318
+
319
+ _res = self.fetch('archives', **query)
320
+
321
+ return [ self._get_archive(archive['id']) for archive in _res ]