nsarchive 1.4.0__tar.gz → 2.0.0a2__tar.gz

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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nsarchive
3
- Version: 1.4.0
4
- Summary:
3
+ Version: 2.0.0a2
4
+ Summary: API-wrapper pour récupérer des données liées à Nation
5
5
  License: GPL-3.0
6
6
  Author: happex
7
7
  Author-email: 110610727+okayhappex@users.noreply.github.com
@@ -11,8 +11,8 @@ Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
- Requires-Dist: deta (>=1.2,<2.0)
15
14
  Requires-Dist: pillow (>=10.4,<11.0)
15
+ Requires-Dist: supabase (>=2.9.1,<3.0.0)
16
16
  Description-Content-Type: text/markdown
17
17
 
18
18
  # nsarchive
@@ -0,0 +1,27 @@
1
+ """
2
+ nsarchive - API-wrapper pour récupérer des données liées à Nation.
3
+
4
+ Version: 2.0.0
5
+ License: GPL-3.0
6
+ Auteur : happex <110610727+okayhappex@users.noreply.github.com>
7
+
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
18
+ from .cls.archives import *
19
+ from .cls.entities import *
20
+ from .cls.republic import *
21
+
22
+ from .cls.exceptions import *
23
+
24
+ # Import des instances
25
+ from .instances._economy import EconomyInstance
26
+ from .instances._entities import EntityInstance
27
+ from .instances._republic import RepublicInstance
@@ -2,69 +2,75 @@ import time
2
2
 
3
3
  from .base import *
4
4
 
5
- class Action:
5
+ class Archive:
6
6
  def __init__(self, author: str | NSID = '0', target: str | NSID = '0') -> None:
7
7
  self.date: int = round(time.time())
8
8
 
9
9
  self.id: NSID = NSID(self.date)
10
- self.action: str = ""
11
10
  self.author: NSID = NSID(author)
12
11
  self.target: NSID = NSID(target)
13
12
 
13
+ self.action: str = ""
14
+ self.details: dict = {
15
+ "reason": None
16
+ }
14
17
 
15
- # Entities
16
18
 
17
- class Sanction(Action):
18
- def __init__(self, author: str | NSID, target: str | NSID) -> None:
19
- super().__init__(author, target)
20
-
21
- self.details: str = ""
22
- self.major: bool = False # Sanction majeure ou non
23
- self.duration: int = 0 # Durée en secondes, 0 = définitif
19
+ # Entities
24
20
 
25
- class AdminAction(Action):
21
+ class Sanction(Archive):
26
22
  def __init__(self, author: str | NSID, target: str | NSID) -> None:
27
23
  super().__init__(author, target)
28
24
 
29
- self.details: str = ""
30
- self.new_state: str | int | bool = None
25
+ self.details: dict = {
26
+ "reason": None,
27
+ "major": False, # Sanction majeure ou non
28
+ "duration": 0 # Durée en secondes , 0 = définitif
29
+ }
31
30
 
32
- class Report(Action):
31
+ class Report(Archive):
33
32
  def __init__(self, author: str | NSID, target: str | NSID) -> None:
34
33
  super().__init__(author, target)
35
34
 
36
- self.details: str = ""
35
+ self.details: dict = {
36
+ "reason": None,
37
+ "elements": [] # Liste des pièces jointes
38
+ }
37
39
 
38
40
 
39
41
  # Community
40
42
 
41
- class Election(Action):
43
+ class Election(Archive):
42
44
  def __init__(self, author: str | NSID, target: str | NSID, position: str) -> None:
43
45
  super().__init__(author, target)
44
46
 
45
- self.position: str = position
46
- self.positive_votes: int = 0
47
- self.total_votes: int = 0
47
+ self.details = {
48
+ "position": position,
49
+ "positive_votes": 0,
50
+ "total_votes": 0
51
+ }
48
52
 
49
- class Promotion(Action):
53
+ class Promotion(Archive):
50
54
  def __init__(self, author: str | NSID, target: str | NSID, position: str) -> None:
51
55
  super().__init__(author, target)
52
56
 
53
- self.position: str = position
57
+ self.details = {
58
+ "position": position
59
+ }
54
60
 
55
- class Demotion(Action):
61
+ class Demotion(Archive):
56
62
  def __init__(self, author: str | NSID, target: str | NSID) -> None:
57
63
  super().__init__(author, target)
58
64
 
59
- self.reason: str = None
60
-
61
65
 
62
66
  # Bank
63
67
 
64
- class Transaction(Action):
65
- def __init__(self, author: str | NSID, target: str | NSID, amount: int) -> None:
68
+ class Transaction(Archive):
69
+ def __init__(self, author: str | NSID, target: str | NSID) -> None:
66
70
  super().__init__(author, target)
67
71
 
68
- self.amount: int = amount
69
- self.currency: str = 'HC'
70
- self.reason: str = None
72
+ self.details = {
73
+ "amount": 0,
74
+ "currency": "HC",
75
+ "reason": None
76
+ }
@@ -0,0 +1,123 @@
1
+ import typing
2
+
3
+ from supabase import Client
4
+
5
+ class NSID(str):
6
+ unknown = "0"
7
+ admin = "1"
8
+ gov = "2"
9
+ court = "3"
10
+ assembly = "4"
11
+ office = "5"
12
+ hexabank = "6"
13
+ archives = "7"
14
+
15
+ maintenance_com = "101"
16
+ audiovisual_dept = "102"
17
+ interior_dept = "103"
18
+ justice_dept = "104"
19
+ egalitary_com = "105"
20
+ antifraud_dept = "106"
21
+
22
+ def __new__(cls, value):
23
+ if type(value) == int:
24
+ value = hex(value)
25
+ elif type(value) in (str, NSID):
26
+ value = hex(int(value, 16))
27
+ else:
28
+ raise TypeError(f"<{value}> is not NSID serializable")
29
+
30
+ if value.startswith("0x"):
31
+ value = value[2:]
32
+
33
+ instance = super(NSID, cls).__new__(cls, value.upper())
34
+ return instance
35
+
36
+ class Instance:
37
+ def __init__(self, client: Client):
38
+ self.db = client
39
+
40
+ def _select_from_db(self, table: str, key: str, value: str) -> dict:
41
+ """
42
+ Récupère des données JSON d'une table Supabase en fonction de l'ID.
43
+
44
+ ## Paramètres
45
+ table: `str`:\n
46
+ Nom de la base
47
+ key: `str`\n
48
+ Clé à vérifier
49
+ value: `str`\n
50
+ Valeur de la clé à vérifier
51
+
52
+ ## Renvoie
53
+ - `list` de tous les élements correspondants
54
+ - `None` si aucune donnée n'est trouvée
55
+ """
56
+
57
+ res = self.db.from_(table).select("*").eq(key, value).execute()
58
+
59
+ if res.data:
60
+ return res.data
61
+ else:
62
+ return None
63
+
64
+ def _get_by_ID(self, table: str, id: NSID) -> dict:
65
+ _data = self._select_from_db(table, 'id', id)
66
+
67
+ if _data is not None:
68
+ _data = _data[0]
69
+
70
+ return _data
71
+
72
+ def _put_in_db(self, table: str, data: dict) -> None:
73
+ """
74
+ Publie des données JSON dans une table Supabase en utilisant le client Supabase.
75
+
76
+ :param table: Nom de la table dans laquelle les données doivent être insérées
77
+ :param data: Dictionnaire contenant les données à publier
78
+ :return: Résultat de l'insertion
79
+ """
80
+
81
+ res = self.db.from_(table).upsert(data).execute()
82
+
83
+ return res
84
+
85
+ def _delete_from_db(self, table: str, key: str, value: str):
86
+ """
87
+ Supprime un enregistrement d'une table Supabase en fonction d'une clé et de sa valeur.
88
+
89
+ ## Paramètres
90
+ table: `str`
91
+ Nom de la table dans laquelle les données doivent être supprimées
92
+ key: `str`
93
+ Clé à vérifier (par exemple "id" ou autre clé unique)
94
+ value: `str`
95
+ Valeur de la clé à vérifier pour trouver l'enregistrement à supprimer
96
+
97
+ ## Renvoie
98
+ - `True` si la suppression a réussi
99
+ - `False` si aucune donnée n'a été trouvée ou si la suppression a échoué
100
+ """
101
+
102
+ res = self.db.from_(table).delete().eq(key, value).execute()
103
+
104
+ return res
105
+
106
+ def _delete_by_ID(self, table: str, id: NSID):
107
+ res = self._delete_from_db(table, 'id', id)
108
+
109
+ return res
110
+
111
+ def fetch(self, table: str, **query: typing.Any) -> list:
112
+ matches = []
113
+
114
+ for key, value in query.items():
115
+ matches.append(self._select_from_db(table, key, value))
116
+
117
+ _res = []
118
+
119
+ for item in matches[0]:
120
+ if all(item in sublist for sublist in matches[1:]):
121
+ _res.append(item)
122
+
123
+ return _res
@@ -1,12 +1,11 @@
1
- from nsarchive.cls.base import NSID
2
- from .base import *
1
+ from .base import NSID
3
2
 
4
3
  class BankAccount:
5
4
  def __init__(self, id: str | NSID) -> None:
6
5
  self.id: NSID = NSID(id)
7
6
  self.owner: NSID = NSID(0)
8
7
  self.amount: int = 0
9
- self.locked: bool = False
8
+ self.frozen: bool = False
10
9
  self.bank: str = "HexaBank"
11
10
 
12
11
  self.income: int = 0
@@ -23,7 +22,7 @@ class Inventory:
23
22
  self.objects: list[Item] = []
24
23
 
25
24
  def append(self, item: Item, quantity: int = 1):
26
- self.objects.extend(quantity * [item])
25
+ self.objects.extend(quantity * [ item ])
27
26
 
28
27
  def throw(self, item: Item, quantity: int = 1):
29
28
  if quantity > self.objects.count(item):
@@ -1,8 +1,7 @@
1
- import io
2
1
  import time
3
2
 
4
3
  from .exceptions import *
5
- from .base import *
4
+ from .base import NSID
6
5
 
7
6
  from ..utils import assets
8
7
 
@@ -99,9 +98,10 @@ class MemberPermissions:
99
98
  """
100
99
 
101
100
  def __init__(self) -> None:
102
- self.manage_organization = False # Renommer ou changer le logo
103
- self.manage_members = False # Virer quelqu'un d'une entreprise, l'y inviter, changer ses rôles
104
- self.manage_roles = False # Promouvoir ou rétrograder les membres
101
+ self.manage_organization = False # Renommer l'organisation, changer le logo
102
+ self.manage_roles = False # Changer les rôles des membres
103
+ self.manage_shares = False # Revaloriser les actions
104
+ self.manage_members = False # Virer quelqu'un d'une entreprise, l'y inviter
105
105
 
106
106
  def edit(self, **permissions: bool) -> None:
107
107
  for perm in permissions.values():
@@ -111,36 +111,38 @@ class GroupMember(User):
111
111
  def __init__(self, id: str | NSID) -> None:
112
112
  super().__init__(id)
113
113
 
114
- self.group_permissions: MemberPermissions = MemberPermissions()
115
- self.group_position: str = 'membre'
114
+ self.permission_level: int = 0
116
115
 
117
- class Official:
118
- def __init__(self, id: str | NSID) -> None:
119
- self.id: NSID = NSID(id)
120
-
121
- self.mandates: int = {
122
- 'PRE_REP': 0, # Président de la République
123
- 'MIN': 0, # Différents ministres
124
- 'PRE_AS': 0, # Président de l'Assemblée Nationale
125
- 'JUDGE': 0, # Juge
126
- 'REPR': 0 # Député
127
- }
116
+ def group_permissions(self) -> MemberPermissions:
117
+ p = MemberPermissions()
128
118
 
129
- self.contributions: dict = {
130
- 'project': 0,
131
- 'approved_project': 0,
132
- 'admin_action': 0,
133
- 'law_vote': 0
134
- }
119
+ if self.permission_level >= 1:
120
+ p.manage_members = True
121
+
122
+ if self.permission_level >= 2:
123
+ p.manage_shares = True
124
+
125
+ if self.permission_level >= 3:
126
+ p.manage_roles = True
127
+
128
+ if self.permission_level >= 4:
129
+ p.manage_organization = True
130
+
131
+ return p
135
132
 
136
133
  class Organization(Entity):
137
134
  def __init__(self, id: str | NSID) -> None:
138
135
  super().__init__(NSID(id))
139
136
 
140
137
  self.owner: Entity
138
+ self.avatar: bytes = assets.open('default_avatar.png')
139
+
141
140
  self.certifications: dict = {}
142
141
  self.members: list[GroupMember] = []
143
- self.avatar: bytes = assets.open('default_avatar.png')
142
+
143
+ self.parts: dict[NSID, int] = {
144
+ self.owner.id: 1
145
+ }
144
146
 
145
147
  def add_certification(self, certification: str) -> None:
146
148
  self.certifications[certification] = round(time.time())
@@ -1,5 +1,4 @@
1
- from nsarchive.cls.entities import NSID
2
- from .entities import *
1
+ from nsarchive.cls.base import NSID
3
2
 
4
3
  # Votes
5
4
 
@@ -23,6 +22,25 @@ class Lawsuit(Vote):
23
22
 
24
23
  # Institutions (defs)
25
24
 
25
+ class Official:
26
+ def __init__(self, id: str | NSID) -> None:
27
+ self.id: NSID = NSID(id)
28
+
29
+ self.mandates: int = {
30
+ 'PRE_REP': 0, # Président de la République
31
+ 'MIN': 0, # Différents ministres
32
+ 'PRE_AS': 0, # Président de l'Assemblée Nationale
33
+ 'JUDGE': 0, # Juge
34
+ 'REPR': 0 # Député
35
+ }
36
+
37
+ self.contributions: dict = {
38
+ 'project': 0,
39
+ 'approved_project': 0,
40
+ 'admin_action': 0,
41
+ 'law_vote': 0
42
+ }
43
+
26
44
  class Administration:
27
45
  def __init__(self) -> None:
28
46
  self.president: Official
@@ -39,15 +57,15 @@ class Government:
39
57
  self.press_minister: Official
40
58
  self.outer_minister: Official
41
59
 
42
- class Assembly:
60
+ class Court:
43
61
  def __init__(self) -> None:
44
62
  self.president: Official
63
+ # On discutera de la mise en place d'un potentiel président. Pour l'instant c'est le Ministre de la Justice
45
64
  self.members: list[Official]
46
65
 
47
- class Court:
66
+ class Assembly:
48
67
  def __init__(self) -> None:
49
68
  self.president: Official
50
- # On discutera de la mise en place d'un potentiel président. Pour l'instant c'est le Ministre de la Justice
51
69
  self.members: list[Official]
52
70
 
53
71
  class PoliceForces:
@@ -55,11 +73,10 @@ class PoliceForces:
55
73
  self.president: Official
56
74
  self.members: list[Official]
57
75
 
58
- class Institutions:
76
+ class State:
59
77
  def __init__(self) -> None:
60
78
  self.administration: Administration
61
79
  self.government: Government
62
80
  self.court: Court
63
81
  self.assembly: Assembly
64
- self.police: PoliceForces
65
-
82
+ self.police: PoliceForces
@@ -0,0 +1,248 @@
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: str | NSID) -> BankAccount:
22
+ """
23
+ Récupère les informations d'un compte bancaire.
24
+
25
+ ## Paramètres
26
+ id: `str | 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 = _data['owner_id']
43
+ account.bank = _data['bank']
44
+
45
+ return account
46
+
47
+ def save_account(self, account: BankAccount):
48
+ """Sauvegarde un compte bancaire dans la base de données."""
49
+
50
+ _data = {
51
+ 'id': NSID(account.id),
52
+ 'amount': account.amount,
53
+ 'frozen': account.frozen,
54
+ 'owner_id': account.owner,
55
+ 'bank': account.bank
56
+ }
57
+
58
+ self._put_in_db('accounts', _data)
59
+
60
+ def freeze_account(self, account: BankAccount):
61
+ """Gèle un compte bancaire pour empêcher toute transaction."""
62
+
63
+ account.id = NSID(account.id)
64
+ account.frozen = True
65
+
66
+ self.save_account(account)
67
+
68
+ """
69
+ ---- VENTES ----
70
+ """
71
+
72
+ def get_sale(self, id: str | NSID) -> Sale | None:
73
+ """
74
+ Récupère une vente disponible sur le marketplace.
75
+
76
+ ## Paramètres
77
+ id: `str | NSID`\n
78
+ ID de l'item.
79
+
80
+ ## Renvoie
81
+ - `.Item | None`
82
+ """
83
+
84
+ id = NSID(id)
85
+
86
+ _data = self._get_by_ID('market', id)
87
+
88
+ if _data is None:
89
+ return None
90
+
91
+ sale = Sale(NSID(id))
92
+ sale.__dict__ = _data
93
+
94
+ return sale
95
+
96
+ def sell_item(self, item: Item, quantity: int, price: int, seller: NSID) -> None:
97
+ """
98
+ Vend un item sur le marché.
99
+
100
+ ## Paramètres
101
+ item: `.Item`\n
102
+ Item à vendre
103
+ quantity: `int`\n
104
+ Nombre d'items à vendre
105
+ price: `int`\n
106
+ Prix à l'unité de chaque objet
107
+ seller: `NSID`\n
108
+ ID de l'auteur de la vente
109
+ """
110
+
111
+ sale = Sale(NSID(round(time.time()) * 16 ** 3), item)
112
+ sale.quantity = quantity
113
+ sale.price = price
114
+ sale.seller_id = seller
115
+
116
+ _data = sale.__dict__.copy()
117
+
118
+ self._put_in_db('market', _data)
119
+
120
+ def delete_sale(self, sale: Sale) -> None:
121
+ """Annule une vente sur le marketplace."""
122
+
123
+ sale.id = NSID(sale.id)
124
+ self._delete_by_ID('market', NSID(sale.id))
125
+
126
+ """
127
+ ---- INVENTAIRES ----
128
+ """
129
+
130
+ def get_inventory(self, id: NSID) -> Inventory | None:
131
+ """
132
+ Récupérer un inventaire dans la base des inventaires.
133
+
134
+ ## Paramètres
135
+ id: `NSID`\n
136
+ ID du propriétaire de l'inventaire
137
+
138
+ ## Retourne
139
+ - `.Inventory | None`
140
+ """
141
+
142
+ _data = self._get_by_ID('inventories', id)
143
+
144
+ if _data is None:
145
+ return None
146
+
147
+ inventory = Inventory(id)
148
+
149
+ for _item in _data['objects']:
150
+ item = Item(_item['id'])
151
+ item.__dict__ = _item
152
+
153
+ inventory.objects.append(item)
154
+
155
+ return inventory
156
+
157
+ def save_inventory(self, inventory: Inventory) -> None:
158
+ """
159
+ Sauvegarder un inventaire
160
+
161
+ ## Paramètres
162
+ inventory: `.Inventory`\n
163
+ Inventaire à sauvegarder
164
+ """
165
+
166
+ _data = {
167
+ "owner_id": inventory.owner_id,
168
+ "objects": [ object.__dict__ for object in inventory.objects ]
169
+ }
170
+
171
+ self._put_in_db('inventories', _data)
172
+
173
+ def delete_inventory(self, inventory: Inventory) -> None:
174
+ """
175
+ Supprime un inventaire
176
+
177
+ ## Paramètres
178
+ inventory: `.Inventory`
179
+ Inventaire à supprimer
180
+ """
181
+
182
+ self._delete_by_ID('inventories', inventory.owner_id)
183
+
184
+ """
185
+ ---- ARCHIVES ----
186
+ """
187
+
188
+ def _add_archive(self, archive: Archive):
189
+ """Ajoute une archive d'une transaction ou d'une vente dans la base de données."""
190
+
191
+ archive.id = NSID(archive.id)
192
+ archive.author = NSID(archive.author)
193
+ archive.target = NSID(archive.target)
194
+
195
+ _data = archive.__dict__.copy()
196
+
197
+ if type(archive) == Transaction:
198
+ _data['_type'] = "transaction"
199
+ else:
200
+ _data['_type'] = "unknown"
201
+
202
+ self._put_in_db('archives', _data)
203
+
204
+ def _get_archive(self, id: str | NSID) -> Archive | Transaction:
205
+ """
206
+ Récupère une archive spécifique.
207
+
208
+ ## Paramètres
209
+ id: `str | NSID`\n
210
+ ID de l'archive.
211
+
212
+ ## Renvoie
213
+ - `.Archive | .Transaction`
214
+ """
215
+
216
+ id = NSID(id)
217
+ _data = self._get_by_ID('archives', id)
218
+
219
+ if _data is None:
220
+ return None
221
+
222
+ if _data['_type'] == "transaction":
223
+ archive = Transaction(_data['author'], _data['target'])
224
+ else:
225
+ archive = Archive(_data['author'], _data['target'])
226
+
227
+ archive.id = id
228
+ archive.action = _data['action']
229
+ archive.date = _data['date']
230
+ archive.details = _data['details']
231
+
232
+ return archive
233
+
234
+ def _fetch_archives(self, **query) -> list[ Archive | Transaction ]:
235
+ """
236
+ Récupère une liste d'archives correspondant à la requête.
237
+
238
+ ## Paramètres
239
+ query: `dict`\n
240
+ Requête pour filtrer les archives.
241
+
242
+ ## Renvoie
243
+ - `list[.Archive | .Transaction]`
244
+ """
245
+
246
+ _res = self.fetch('archives', **query)
247
+
248
+ return [ self._get_archive(archive['id']) for archive in _res ]