nsarchive 2.0.0b2__tar.gz → 3.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.
@@ -0,0 +1,19 @@
1
+ Metadata-Version: 2.1
2
+ Name: nsarchive
3
+ Version: 3.0.0a2
4
+ Summary: API-wrapper pour récupérer des données liées à Nation
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
+ Requires-Dist: pillow (>=10.4,<11.0)
15
+ Description-Content-Type: text/markdown
16
+
17
+ # NSArchive
18
+
19
+ Documentation pas disponible pour l'instant
@@ -0,0 +1,3 @@
1
+ # NSArchive
2
+
3
+ Documentation pas disponible pour l'instant
@@ -1,27 +1,24 @@
1
1
  """
2
2
  nsarchive - API-wrapper pour récupérer des données liées à Nation.
3
3
 
4
- Version: 2.0.0
4
+ Version: 3.0.0a2
5
5
  License: GPL-3.0
6
6
  Auteur : happex <110610727+okayhappex@users.noreply.github.com>
7
7
 
8
8
  Dependencies:
9
9
  - Python ^3.10
10
- - supabase ^2.9.1
11
10
  - pillow ^10.4
12
11
 
13
12
  Le fichier README.md fournit des détails supplémentaires pour l'utilisation.
14
13
  """
15
14
 
16
- # Import des types et des exceptions
15
+ # Import des types
17
16
  from .cls.base import NSID
18
17
  from .cls.archives import *
19
18
  from .cls.entities import *
20
19
  from .cls.republic import *
21
20
  from .cls.economy import *
22
21
 
23
- from .cls.exceptions import *
24
-
25
22
  # Import des instances
26
23
  from .instances._economy import EconomyInstance
27
24
  from .instances._entities import EntityInstance
@@ -3,7 +3,24 @@ import time
3
3
  from .base import *
4
4
 
5
5
  class Archive:
6
- def __init__(self, author: str | NSID = '0', target: str | NSID = '0') -> None:
6
+ def __init__(self, author: NSID = '0', target: NSID = '0'):
7
+ """
8
+ Classe de référence pour toutes les archives.
9
+
10
+ ## Attributs de base
11
+ - date: `int`\n
12
+ Date (timestamp) de l'exécution de l'archive
13
+ - id: `NSID`\n
14
+ Clé d'identification des archives (basée sur la date)
15
+ - author: `NSID`\n
16
+ ID de l'auteur de l'action
17
+ - target: `NSID`:
18
+ ID de la cible de l'action
19
+ - action: `str`:\n
20
+ Action effectuée
21
+ - details: `dict`\n
22
+ Ensemble de détails que les différents bots peuvent utiliser
23
+ """
7
24
  self.date: int = round(time.time())
8
25
 
9
26
  self.id: NSID = NSID(self.date)
@@ -19,7 +36,7 @@ class Archive:
19
36
  # Entities
20
37
 
21
38
  class Sanction(Archive):
22
- def __init__(self, author: str | NSID, target: str | NSID) -> None:
39
+ def __init__(self, author: NSID, target: NSID) -> None:
23
40
  super().__init__(author, target)
24
41
 
25
42
  self.details: dict = {
@@ -29,7 +46,7 @@ class Sanction(Archive):
29
46
  }
30
47
 
31
48
  class Report(Archive):
32
- def __init__(self, author: str | NSID, target: str | NSID) -> None:
49
+ def __init__(self, author: NSID, target: NSID) -> None:
33
50
  super().__init__(author, target)
34
51
 
35
52
  self.details: dict = {
@@ -41,7 +58,7 @@ class Report(Archive):
41
58
  # Community
42
59
 
43
60
  class Election(Archive):
44
- def __init__(self, author: str | NSID, target: str | NSID, position: str) -> None:
61
+ def __init__(self, author: NSID, target: NSID, position: str) -> None:
45
62
  super().__init__(author, target)
46
63
 
47
64
  self.details = {
@@ -51,7 +68,7 @@ class Election(Archive):
51
68
  }
52
69
 
53
70
  class Promotion(Archive):
54
- def __init__(self, author: str | NSID, target: str | NSID, position: str) -> None:
71
+ def __init__(self, author: NSID, target: NSID, position: str) -> None:
55
72
  super().__init__(author, target)
56
73
 
57
74
  self.details = {
@@ -59,14 +76,14 @@ class Promotion(Archive):
59
76
  }
60
77
 
61
78
  class Demotion(Archive):
62
- def __init__(self, author: str | NSID, target: str | NSID) -> None:
79
+ def __init__(self, author: NSID, target: NSID) -> None:
63
80
  super().__init__(author, target)
64
81
 
65
82
 
66
83
  # Bank
67
84
 
68
85
  class Transaction(Archive):
69
- def __init__(self, author: str | NSID, target: str | NSID) -> None:
86
+ def __init__(self, author: NSID, target: NSID) -> None:
70
87
  super().__init__(author, target)
71
88
 
72
89
  self.details = {
@@ -0,0 +1,237 @@
1
+ import io
2
+ import json
3
+ import requests
4
+ import typing
5
+ import warnings
6
+
7
+ class NSID(str):
8
+ """
9
+ Nation Server ID
10
+
11
+ ID unique et universel pour l'ensemble des entités et évènements. Il prend les `int`, les `str` et les autres instances `NSID` pour les convertir en un identifiant hexadécimal.
12
+ """
13
+ unknown = "0"
14
+ admin = "1"
15
+ gov = "2"
16
+ court = "3"
17
+ assembly = "4"
18
+ office = "5"
19
+ hexabank = "6"
20
+ archives = "7"
21
+
22
+ maintenance_com = "101"
23
+ audiovisual_dept = "102"
24
+ interior_dept = "103"
25
+ justice_dept = "104"
26
+ egalitary_com = "105"
27
+ antifraud_dept = "106"
28
+
29
+ def __new__(cls, value):
30
+ if type(value) == int:
31
+ value = hex(value)
32
+ elif type(value) in (str, NSID):
33
+ value = hex(int(value, 16))
34
+ else:
35
+ raise TypeError(f"<{value}> is not NSID serializable")
36
+
37
+ if value.startswith("0x"):
38
+ value = value[2:]
39
+
40
+ instance = super(NSID, cls).__new__(cls, value.upper())
41
+ return instance
42
+
43
+ class Instance:
44
+ """
45
+ Instance qui servira de base à toutes les instances.
46
+ """
47
+
48
+ def __init__(self, url: str, token: str = None):
49
+ self.url = url
50
+ self.token = token
51
+
52
+ self.default_headers = {
53
+ "Authorization": f"Bearer {self.token}",
54
+ "Content-Type": "application/json",
55
+ }
56
+
57
+ def request_token(self, username: str, password: str) -> str | None:
58
+ res = requests.post(f"{self.url}/auth/login", json = {
59
+ "username": username,
60
+ "password": password
61
+ })
62
+
63
+ if res.status_code == 200:
64
+ return res.json()["token"]
65
+ elif res.status_code in (401, 403):
66
+ raise PermissionError(res.json()['message'])
67
+ else:
68
+ raise Exception(f"Error {res.status_code}: {res.json()['message']}")
69
+
70
+ def _get_item(self, endpoint: str, body: dict = None, headers: dict = None) -> dict:
71
+ """
72
+ Récupère des données JSON depuis l'API
73
+
74
+ ## Paramètres
75
+ endpoint: `str`:
76
+ Endpoint de l'URL
77
+ headers: `dict` (optional)
78
+ Headers à envoyer
79
+ body: `dict` (optional)
80
+ Données à envoyer
81
+
82
+ ## Renvoie
83
+ - `list` de tous les élements correspondants
84
+ - `None` si aucune donnée n'est trouvée
85
+ """
86
+
87
+ if not headers:
88
+ headers = self.default_headers
89
+
90
+ res = requests.get(f"{self.url}/{endpoint}", headers = headers, json = body, timeout = 5)
91
+
92
+ if 200 <= res.status_code < 300:
93
+ return res.json()
94
+ elif res.status_code == 404:
95
+ return
96
+ elif res.status_code in (403, 401):
97
+ raise PermissionError(res.json()['message'])
98
+ else:
99
+ raise Exception(f"Error {res.status_code}: {res.json()['message']}")
100
+
101
+ def _get_by_ID(self, _class: str, id: NSID) -> dict:
102
+ _data = self._get_item(f"/model/{_class}/{id}")
103
+
104
+ return _data
105
+
106
+ def _put_in_db(self, endpoint: str, body: dict, headers: dict = None, use_PUT: bool = False) -> None:
107
+ """
108
+ Publie des données JSON dans une table nation-db.
109
+
110
+ ## Paramètres
111
+ endpoint: `str`
112
+ Endpoint de l'URL
113
+ body: `dict`
114
+ Données à envoyer
115
+ headers: `dict` (optionnel)
116
+ Headers à envoyer
117
+ """
118
+
119
+ if not headers:
120
+ headers = headers
121
+
122
+ if use_PUT:
123
+ res = requests.put(f"{self.url}/{endpoint}", headers = headers, json = body)
124
+ else:
125
+ res = requests.post(f"{self.url}/{endpoint}", headers = headers, json = body)
126
+
127
+ if 200 <= res.status_code < 300:
128
+ return res.json()
129
+ else:
130
+ print(res.text)
131
+ res.raise_for_status()
132
+
133
+ def _delete(self, _class: str, ids: list[NSID]) -> None:
134
+ """
135
+ Supprime des données JSON dans une table nation-db.
136
+
137
+ ## Paramètres
138
+ _class: `str`
139
+ Classe des entités à supprimer
140
+ ids: `list[NSID]`
141
+ ID des entités à supprimer
142
+ """
143
+
144
+ res = requests.post(f"{self.url}/delete_{_class}", json = { "ids": ids })
145
+
146
+ if 200 <= res.status_code < 300:
147
+ return res.json()
148
+ elif res.status_code in (403, 401):
149
+ raise PermissionError(res.json()['message'])
150
+ else:
151
+ raise Exception(f"Error {res.status_code}: {res.json()['message']}")
152
+
153
+ def _delete_by_ID(self, _class: str, id: NSID):
154
+ warnings.showwarning("Method '_delete_by_id' is deprecated. Use '_delete' instead.")
155
+ self._delete(_class, id)
156
+
157
+ def fetch(self, _class: str, **query: typing.Any) -> list:
158
+ res = requests.get(f"{self.url}/fetch/{_class}", params = query)
159
+
160
+ if res.status_code == 200:
161
+ matches = res.json()
162
+ elif res.status_code in (401, 403):
163
+ matches = []
164
+ else:
165
+ res.raise_for_status()
166
+
167
+ return matches
168
+
169
+
170
+ def _upload_file(self, bucket: str, name: str, data: bytes, overwrite: bool = False, headers: dict = None) -> dict:
171
+ """
172
+ Envoie un fichier dans un bucket nation-db.
173
+
174
+ ## Paramètres
175
+ bucket: `str`
176
+ Nom du bucket où le fichier sera stocké
177
+ name: `str`
178
+ Nom du fichier dans le drive
179
+ data: `bytes`
180
+ Données à uploader
181
+ overwrite: `bool` (optional)
182
+ Overwrite ou non
183
+ headers: `dict` (optional)
184
+ Headers à envoyer
185
+
186
+ ## Renvoie
187
+ - `dict` contenant les informations de l'upload si réussi
188
+ - `None` en cas d'échec
189
+ """
190
+
191
+ if not headers:
192
+ headers = self.default_headers
193
+ headers['Content-Type'] = 'image/png'
194
+
195
+ body = {
196
+ "name": name,
197
+ "overwrite": json.dumps(overwrite)
198
+ }
199
+
200
+ file = ("file", "image/png", data)
201
+
202
+ res = requests.put(f"{self.url}/upload_file/{bucket}", headers = headers, json = body, files = [ file ])
203
+
204
+ if res.status_code == 200:
205
+ return res.json()
206
+ elif res.status_code in (403, 401):
207
+ raise PermissionError(res.json()['message'])
208
+ elif res.status_code == 409:
209
+ raise FileExistsError(res.json()['message'])
210
+ else:
211
+ raise Exception(f"Error {res.status_code}: {res.json()['message']}")
212
+
213
+ def _download_from_storage(self, bucket: str, path: str, headers: dict = None) -> bytes:
214
+ """
215
+ Télécharge un fichier depuis le stockage nation-db.
216
+
217
+ ## Paramètres
218
+ bucket: `str`\n
219
+ Nom du bucket où il faut chercher le fichier
220
+ path: `str`\n
221
+ Chemin du fichier dans le bucket
222
+
223
+ ## Renvoie
224
+ - Le fichier demandé en `bytes`
225
+ """
226
+
227
+ if not headers:
228
+ headers = self.default_headers
229
+
230
+ res = requests.get(f"{self.url}/drive/{bucket}/{path}", headers = headers)
231
+
232
+ if res.status_code == 200:
233
+ return res.json()
234
+ elif res.status_code in (403, 401):
235
+ raise PermissionError(res.json()['message'])
236
+ else:
237
+ raise Exception(f"Error {res.status_code}: {res.json()['message']}")
@@ -0,0 +1,100 @@
1
+ from .base import NSID
2
+
3
+ class BankAccount:
4
+ """
5
+ Compte en banque d'une entité, individuelle ou collective.
6
+
7
+ ## Attributs
8
+ - id: `NSID`\n
9
+ Identifiant du compte
10
+ - owner: `NSID`\n
11
+ Identifiant du titulaire du compte
12
+ - amount: `int`\n
13
+ Somme d'argent totale sur le compte
14
+ - frozen: `bool`\n
15
+ État gelé ou non du compte
16
+ - bank: `NSID`\n
17
+ Identifiant de la banque qui détient le compte
18
+ - income: `int`\n
19
+ Somme entrante sur le compte depuis la dernière réinitialisation (tous les ~ 28 jours)
20
+ """
21
+
22
+ def __init__(self, id: NSID) -> None:
23
+ self.id: NSID = NSID(id)
24
+ self.owner: NSID = NSID(0)
25
+ self.amount: int = 0
26
+ self.frozen: bool = False
27
+ self.bank: NSID = NSID("6")
28
+
29
+ self.income: int = 0
30
+
31
+ class Item:
32
+ """
33
+ Article d'inventaire qui peut circuler sur le serveur
34
+
35
+ ## Attributs
36
+ - id: `NSID`\n
37
+ Identifiant de l'objet
38
+ - title: `str`\n
39
+ Nom de l'objet
40
+ - emoji: `str`\n
41
+ Emoji lié à l'objet
42
+ """
43
+
44
+ def __init__(self, id: NSID) -> None:
45
+ self.id: NSID = NSID(id)
46
+ self.title: str = "Unknown Object"
47
+ self.emoji: str = ":light_bulb:"
48
+
49
+ class Inventory:
50
+ """
51
+ Inventaire d'un membre
52
+
53
+ ## Attributs
54
+ - owner_id: `NSID`\n
55
+ ID du propriétaire de l'inventaire
56
+ - objects: `dict[str, NSID]`\n
57
+ Collection d'objets et leur quantité
58
+ """
59
+
60
+ def __init__(self, owner_id: NSID) -> None:
61
+ self.owner_id: NSID = NSID(owner_id)
62
+ self.objects: dict[str, NSID] = {}
63
+
64
+ def append(self, item: Item, quantity: int = 1):
65
+ if item.id in self.objects.keys():
66
+ self.objects[item.id] += quantity
67
+ else:
68
+ self.objects[item.id] = quantity
69
+
70
+ def throw(self, item: Item, quantity: int = 1):
71
+ if item.id in self.objects.keys():
72
+ if self.objects[item.id] > quantity:
73
+ self.objects[item.id] -= quantity
74
+ else:
75
+ self.objects[item.id] = 0
76
+
77
+ class Sale:
78
+ """
79
+ Vente mettant en jeu un objet
80
+
81
+ ## Attributs
82
+ - id: `NSID`\n
83
+ Identifiant de la vente
84
+ - item: `NSID`\n
85
+ Identifiant de l'objet mis en vente
86
+ - quantity: `int`\n
87
+ Quantité d'objets mis en vente
88
+ - price: `int`\n
89
+ Prix total du lot
90
+ - seller_id: `NSID`\n
91
+ Identifiant du vendeur
92
+ """
93
+
94
+ def __init__(self, id: NSID, item: Item) -> None:
95
+ self.id: NSID = NSID(id)
96
+ self.item: NSID = NSID(item.id)
97
+ self.quantity: int = 1
98
+
99
+ self.price: int = 0
100
+ self.seller_id: NSID = NSID('0')