nsarchive 3.0.0a6__tar.gz → 3.0.0a8__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.
- {nsarchive-3.0.0a6 → nsarchive-3.0.0a8}/PKG-INFO +3 -2
- nsarchive-3.0.0a8/nsarchive/__init__.py +30 -0
- {nsarchive-3.0.0a6/nsarchive/instances → nsarchive-3.0.0a8/nsarchive/interfaces}/_economy.py +15 -30
- nsarchive-3.0.0a8/nsarchive/interfaces/_entities.py +206 -0
- nsarchive-3.0.0a8/nsarchive/interfaces/_justice.py +50 -0
- nsarchive-3.0.0a8/nsarchive/interfaces/_state.py +142 -0
- nsarchive-3.0.0a8/nsarchive/mandate.py +50 -0
- {nsarchive-3.0.0a6/nsarchive/cls → nsarchive-3.0.0a8/nsarchive/models}/base.py +23 -5
- {nsarchive-3.0.0a6/nsarchive/cls → nsarchive-3.0.0a8/nsarchive/models}/economy.py +34 -13
- {nsarchive-3.0.0a6/nsarchive/cls → nsarchive-3.0.0a8/nsarchive/models}/entities.py +139 -72
- nsarchive-3.0.0a8/nsarchive/models/justice.py +108 -0
- nsarchive-3.0.0a8/nsarchive/models/republic.py +125 -0
- nsarchive-3.0.0a8/nsarchive/models/scale.py +23 -0
- nsarchive-3.0.0a8/nsarchive/models/state.py +59 -0
- {nsarchive-3.0.0a6 → nsarchive-3.0.0a8}/pyproject.toml +1 -1
- nsarchive-3.0.0a6/nsarchive/__init__.py +0 -25
- nsarchive-3.0.0a6/nsarchive/cls/archives.py +0 -93
- nsarchive-3.0.0a6/nsarchive/cls/republic.py +0 -149
- nsarchive-3.0.0a6/nsarchive/instances/_entities.py +0 -269
- nsarchive-3.0.0a6/nsarchive/instances/_republic.py +0 -339
- {nsarchive-3.0.0a6 → nsarchive-3.0.0a8}/LICENSE +0 -0
- {nsarchive-3.0.0a6 → nsarchive-3.0.0a8}/README.md +0 -0
- {nsarchive-3.0.0a6 → nsarchive-3.0.0a8}/nsarchive/assets/default_avatar.png +0 -0
- {nsarchive-3.0.0a6 → nsarchive-3.0.0a8}/nsarchive/utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: nsarchive
|
3
|
-
Version: 3.0.
|
3
|
+
Version: 3.0.0a8
|
4
4
|
Summary: API-wrapper pour récupérer des données liées à Nation
|
5
5
|
License: GPL-3.0
|
6
6
|
Author: happex
|
@@ -11,6 +11,7 @@ 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
|
+
Classifier: Programming Language :: Python :: 3.13
|
14
15
|
Requires-Dist: pillow (>=10.4,<11.0)
|
15
16
|
Requires-Dist: requests (>=2.31,<3.0)
|
16
17
|
Description-Content-Type: text/markdown
|
@@ -0,0 +1,30 @@
|
|
1
|
+
"""
|
2
|
+
nsarchive - API-wrapper pour récupérer des données liées à Nation.
|
3
|
+
|
4
|
+
Version: 3.0.0-alpha.8
|
5
|
+
Date de sortie: 2025-08-04
|
6
|
+
License: GPL-3.0
|
7
|
+
Auteur : happex <110610727+okayhappex@users.noreply.github.com>
|
8
|
+
|
9
|
+
Dependencies:
|
10
|
+
- Python ^3.10
|
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
|
17
|
+
from .models.base import NSID
|
18
|
+
from .models.entities import *
|
19
|
+
from .models.economy import *
|
20
|
+
|
21
|
+
from .models.republic import *
|
22
|
+
from .models.state import *
|
23
|
+
from .models.justice import *
|
24
|
+
|
25
|
+
# Import des interfaces
|
26
|
+
from .models.base import Interface
|
27
|
+
from .interfaces._entities import EntityInterface
|
28
|
+
from .interfaces._economy import EconomyInterface
|
29
|
+
from .interfaces._state import StateInterface
|
30
|
+
from .interfaces._justice import JusticeInterface
|
{nsarchive-3.0.0a6/nsarchive/instances → nsarchive-3.0.0a8/nsarchive/interfaces}/_economy.py
RENAMED
@@ -1,13 +1,12 @@
|
|
1
1
|
import time
|
2
2
|
|
3
|
-
from ..
|
4
|
-
from ..
|
5
|
-
from ..cls.economy import *
|
3
|
+
from ..models.base import *
|
4
|
+
from ..models.economy import *
|
6
5
|
|
7
|
-
from ..
|
6
|
+
from ..models import economy # Pour les default_headers
|
8
7
|
|
9
|
-
class
|
10
|
-
"""
|
8
|
+
class EconomyInterface(Interface):
|
9
|
+
"""Interface qui vous permettra d'interagir avec les comptes en banque et les transactions économiques."""
|
11
10
|
|
12
11
|
def __init__(self, url: str, token: str) -> None:
|
13
12
|
super().__init__(url, token)
|
@@ -43,9 +42,7 @@ class EconomyInstance(Instance):
|
|
43
42
|
return None
|
44
43
|
|
45
44
|
account = BankAccount(id)
|
46
|
-
account.
|
47
|
-
|
48
|
-
account._load(_data)
|
45
|
+
account._load(_data, self.url, self.default_headers)
|
49
46
|
|
50
47
|
return account
|
51
48
|
|
@@ -107,9 +104,7 @@ class EconomyInstance(Instance):
|
|
107
104
|
account = BankAccount(_acc["owner_id"])
|
108
105
|
|
109
106
|
account.id = NSID(_acc['id'])
|
110
|
-
account.
|
111
|
-
|
112
|
-
account._load(_acc)
|
107
|
+
account._load(_acc, self.url, self.default_headers)
|
113
108
|
|
114
109
|
res.append(account)
|
115
110
|
|
@@ -144,9 +139,7 @@ class EconomyInstance(Instance):
|
|
144
139
|
return None
|
145
140
|
|
146
141
|
inventory = Inventory(id)
|
147
|
-
inventory.
|
148
|
-
|
149
|
-
inventory._load(_data)
|
142
|
+
inventory._load(_data, self.url, self.default_headers)
|
150
143
|
|
151
144
|
return inventory
|
152
145
|
|
@@ -201,9 +194,7 @@ class EconomyInstance(Instance):
|
|
201
194
|
inventory = Inventory(_inv["owner_id"])
|
202
195
|
|
203
196
|
inventory.id = NSID(_inv['id'])
|
204
|
-
inventory.
|
205
|
-
|
206
|
-
inventory._load(_inv)
|
197
|
+
inventory._load(_inv, self.url, self.default_headers)
|
207
198
|
|
208
199
|
res.append(inventory)
|
209
200
|
|
@@ -238,10 +229,9 @@ class EconomyInstance(Instance):
|
|
238
229
|
return None
|
239
230
|
|
240
231
|
item = Item()
|
241
|
-
item.id = id
|
242
|
-
item._url = f"{self.url}/marketplace/items/{item.id}"
|
243
232
|
|
244
|
-
item.
|
233
|
+
item.id = id
|
234
|
+
item._load(_data, self.url, self.default_headers)
|
245
235
|
|
246
236
|
return item
|
247
237
|
|
@@ -294,9 +284,7 @@ class EconomyInstance(Instance):
|
|
294
284
|
item = Item()
|
295
285
|
|
296
286
|
item.id = NSID(_item['id'])
|
297
|
-
item.
|
298
|
-
|
299
|
-
item._load(_item)
|
287
|
+
item._load(_item, self.url, self.default_headers)
|
300
288
|
|
301
289
|
res.append(item)
|
302
290
|
|
@@ -332,10 +320,9 @@ class EconomyInstance(Instance):
|
|
332
320
|
return None
|
333
321
|
|
334
322
|
sale = Sale()
|
335
|
-
sale.id = id
|
336
|
-
sale._url = f"{self.url}/marketplace/sales/{sale.id}"
|
337
323
|
|
338
|
-
sale.
|
324
|
+
sale.id = id
|
325
|
+
sale._load(_data, self.url, self.default_headers)
|
339
326
|
|
340
327
|
return sale
|
341
328
|
|
@@ -369,9 +356,7 @@ class EconomyInstance(Instance):
|
|
369
356
|
sale = Sale()
|
370
357
|
|
371
358
|
sale.id = NSID(_sale['id'])
|
372
|
-
sale.
|
373
|
-
|
374
|
-
sale._load(_sale)
|
359
|
+
sale._load(_sale, self.url, self.default_headers)
|
375
360
|
|
376
361
|
res.append(sale)
|
377
362
|
|
@@ -0,0 +1,206 @@
|
|
1
|
+
from ..models.base import *
|
2
|
+
from ..models.entities import *
|
3
|
+
|
4
|
+
from ..models import entities # Pour les default_headers
|
5
|
+
|
6
|
+
class EntityInterface(Interface):
|
7
|
+
"""
|
8
|
+
Interface qui vous permettra d'interagir avec les profils des membres ainsi que les différents métiers et secteurs d'activité.
|
9
|
+
|
10
|
+
## Informations disponibles
|
11
|
+
- Profil des membres et des entreprises: `.User | .Organization | .Entity`
|
12
|
+
- Participation d'un membre à différent votes: `.User | .Organization | .Entity`
|
13
|
+
- Appartenance et permissions d'un membre dans un groupe: `.GroupMember.MemberPermissions`
|
14
|
+
- Position légale et permissions d'une entité: `.Position.Permissions`
|
15
|
+
- Sanctions et modifications d'une entité: `.Action[ .AdminAction | .Sanction ]`
|
16
|
+
"""
|
17
|
+
|
18
|
+
def __init__(self, url: str, token: str = None) -> None:
|
19
|
+
super().__init__(url, token)
|
20
|
+
|
21
|
+
"""
|
22
|
+
---- ENTITÉS ----
|
23
|
+
"""
|
24
|
+
|
25
|
+
def get_entity(self, id: NSID, _class: str = None) -> User | Organization | Entity:
|
26
|
+
"""
|
27
|
+
Fonction permettant de récupérer le profil public d'une entité.\n
|
28
|
+
|
29
|
+
## Paramètres
|
30
|
+
id: `NSID`
|
31
|
+
ID héxadécimal de l'entité à récupérer
|
32
|
+
_class: `str`
|
33
|
+
Classe du modèle à prendre (`.User` ou `.Organization`)
|
34
|
+
|
35
|
+
## Renvoie
|
36
|
+
- `.User` dans le cas où l'entité choisie est un membre
|
37
|
+
- `.Organization` dans le cas où c'est un groupe
|
38
|
+
- `.Entity` dans le cas où c'est indéterminé
|
39
|
+
"""
|
40
|
+
|
41
|
+
id = NSID(id)
|
42
|
+
|
43
|
+
if _class == "user":
|
44
|
+
_data = self._get_by_ID('individuals', id)
|
45
|
+
elif _class == "group":
|
46
|
+
_data = self._get_by_ID('organizations', id)
|
47
|
+
else:
|
48
|
+
_data = self._get_by_ID('entities', id)
|
49
|
+
|
50
|
+
if _data is None: # ID inexistant chez les entités
|
51
|
+
return None
|
52
|
+
|
53
|
+
if _data['_class'] == 'individuals':
|
54
|
+
entity = User(id)
|
55
|
+
elif _data['_class'] == 'organizations':
|
56
|
+
entity = Organization(id)
|
57
|
+
else:
|
58
|
+
entity = Entity(id)
|
59
|
+
|
60
|
+
entity._load(_data, self.url, self.default_headers)
|
61
|
+
|
62
|
+
return entity
|
63
|
+
|
64
|
+
def create_entity(self, id: NSID, name: str, _class: str, position: str = 'membre', zone: int = 10):
|
65
|
+
"""
|
66
|
+
Fonction permettant de créer ou modifier une entité.
|
67
|
+
|
68
|
+
## Paramètres
|
69
|
+
- id (`NSID`): Identifiant NSID
|
70
|
+
- name (`str`): Nom d'usage
|
71
|
+
- _class (`"user"` ou `"group"`): Type de l'entité
|
72
|
+
- position (`str`, optionnel): ID de la position civile
|
73
|
+
- zone (`int`, optionnel): ID de la zone civile
|
74
|
+
"""
|
75
|
+
|
76
|
+
id = NSID(id)
|
77
|
+
|
78
|
+
if _class in ('group', 'organization'):
|
79
|
+
_class = 'organizations'
|
80
|
+
elif _class in ('user', 'individual'):
|
81
|
+
_class = 'individuals'
|
82
|
+
else:
|
83
|
+
return
|
84
|
+
|
85
|
+
self._put_in_db(
|
86
|
+
f"/new_model/{_class}?id={urllib.parse.quote(id)}&name={urllib.parse.quote(name)}&position={urllib.parse.quote(position)}&zone={urllib.parse.quote(zone)}",
|
87
|
+
headers = self.default_headers,
|
88
|
+
use_PUT = True
|
89
|
+
)
|
90
|
+
|
91
|
+
entity = self.get_entity(id)
|
92
|
+
|
93
|
+
if _class == "individuals":
|
94
|
+
entity._url = f"{self.url}/model/individuals/{id}"
|
95
|
+
elif isinstance(entity, Organization):
|
96
|
+
entity._url = f"{self.url}/model/organizations/{id}"
|
97
|
+
entity.avatar_url = f"{entity._url}/avatar"
|
98
|
+
else:
|
99
|
+
entity._url = f"{self.url}/model/entities/{id}"
|
100
|
+
|
101
|
+
return entity
|
102
|
+
|
103
|
+
|
104
|
+
def delete_entity(self, entity: Entity):
|
105
|
+
"""
|
106
|
+
Fonction permettant de supprimer le profil d'une entité
|
107
|
+
|
108
|
+
## Paramètres
|
109
|
+
entity: `.Entity`\n
|
110
|
+
L'entité à supprimer
|
111
|
+
"""
|
112
|
+
|
113
|
+
res = requests.post(f"{entity._url}/delete", headers = self.default_headers,)
|
114
|
+
|
115
|
+
if res.status_code != 200:
|
116
|
+
res.raise_for_status()
|
117
|
+
|
118
|
+
def fetch_entities(self, **query: typing.Any) -> list[ Entity | User | Organization ]:
|
119
|
+
"""
|
120
|
+
Récupère une liste d'entités en fonction d'une requête.
|
121
|
+
|
122
|
+
## Paramètres
|
123
|
+
query: `**dict`\n
|
124
|
+
La requête pour filtrer les entités.
|
125
|
+
|
126
|
+
## Renvoie
|
127
|
+
- `list[.Entity | .User | .Organization]`
|
128
|
+
"""
|
129
|
+
|
130
|
+
if "_class" in query.keys():
|
131
|
+
if query["_class"] == "individuals":
|
132
|
+
del query["_class"]
|
133
|
+
_res = self.fetch('individuals', **query)
|
134
|
+
elif query["_class"] == "organizations":
|
135
|
+
del query["_class"]
|
136
|
+
_res = self.fetch('organizations', **query)
|
137
|
+
else:
|
138
|
+
del query["_class"]
|
139
|
+
_res = self.fetch('entities', **query)
|
140
|
+
else:
|
141
|
+
_res = self.fetch('entities', **query)
|
142
|
+
|
143
|
+
res = []
|
144
|
+
|
145
|
+
for _entity in _res:
|
146
|
+
if _entity is None: continue
|
147
|
+
|
148
|
+
if _entity['_class'] == 'individuals':
|
149
|
+
entity = User(_entity["id"])
|
150
|
+
elif _entity['_class'] == 'organizations':
|
151
|
+
entity = Organization(_entity["id"])
|
152
|
+
else:
|
153
|
+
entity = Entity(_entity["id"])
|
154
|
+
|
155
|
+
entity._load(_entity, self.url, self.default_headers)
|
156
|
+
|
157
|
+
res.append(entity)
|
158
|
+
|
159
|
+
return res
|
160
|
+
|
161
|
+
|
162
|
+
|
163
|
+
def get_position(self, id: str) -> Position:
|
164
|
+
"""
|
165
|
+
Récupère une position légale (métier, domaine professionnel).
|
166
|
+
|
167
|
+
## Paramètres
|
168
|
+
id: `str`\n
|
169
|
+
ID de la position (SENSIBLE À LA CASSE !)
|
170
|
+
|
171
|
+
## Renvoie
|
172
|
+
- `.Position`
|
173
|
+
"""
|
174
|
+
|
175
|
+
_data = self._get_by_ID('positions', id)
|
176
|
+
|
177
|
+
if _data is None:
|
178
|
+
return None
|
179
|
+
|
180
|
+
position = Position(id)
|
181
|
+
position._load(_data, self.url, self.default_headers)
|
182
|
+
|
183
|
+
return position
|
184
|
+
|
185
|
+
def fetch_positions(self, **query: typing.Any) -> list[Position]:
|
186
|
+
"""
|
187
|
+
Récupère une liste de positions en fonction d'une requête.
|
188
|
+
|
189
|
+
## Paramètres
|
190
|
+
query: `**dict`\n
|
191
|
+
La requête pour filtrer les positions.
|
192
|
+
|
193
|
+
## Renvoie
|
194
|
+
- `list[.Position]`
|
195
|
+
"""
|
196
|
+
|
197
|
+
_res = self.fetch('positions', **query)
|
198
|
+
res = []
|
199
|
+
|
200
|
+
for _data in _res:
|
201
|
+
pos = Position()
|
202
|
+
pos._load(_data, self.url, self.default_headers)
|
203
|
+
|
204
|
+
res.append(pos)
|
205
|
+
|
206
|
+
return res
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import requests
|
2
|
+
import time
|
3
|
+
|
4
|
+
from ..models.base import *
|
5
|
+
from ..models.justice import *
|
6
|
+
|
7
|
+
class JusticeInterface(Interface):
|
8
|
+
"""
|
9
|
+
Gère les procès, sanctions et signalements.
|
10
|
+
"""
|
11
|
+
|
12
|
+
def __init__(self, url: str, token: str) -> None:
|
13
|
+
super().__init__(url, token)
|
14
|
+
|
15
|
+
"""
|
16
|
+
SIGNALEMENTS
|
17
|
+
"""
|
18
|
+
|
19
|
+
def get_report(self, id: NSID) -> Report:
|
20
|
+
res = requests.get(
|
21
|
+
f"{self.url}/justice/reports/{id}",
|
22
|
+
headers = self.default_headers,
|
23
|
+
)
|
24
|
+
|
25
|
+
if res.status_code != 200:
|
26
|
+
res.raise_for_status()
|
27
|
+
|
28
|
+
report = Report(id)
|
29
|
+
report._load(res.json(), f"{self.url}/justice/reports/{id}", self.default_headers)
|
30
|
+
|
31
|
+
return report
|
32
|
+
|
33
|
+
def submit_report(self, target: NSID, reason: str = None, details: str = None) -> Report:
|
34
|
+
payload = {}
|
35
|
+
if reason: payload['reason'] = reason
|
36
|
+
if details: payload['details'] = details
|
37
|
+
|
38
|
+
res = requests.put(
|
39
|
+
f"{self.url}/justice/submit_report?target={target}",
|
40
|
+
headers = self.default_headers,
|
41
|
+
json = payload
|
42
|
+
)
|
43
|
+
|
44
|
+
if res.status_code != 200:
|
45
|
+
res.raise_for_status()
|
46
|
+
|
47
|
+
report = Report(NSID(res.json()['id']))
|
48
|
+
report._load(res.json(), f"{self.url}/justice/reports/{report.id}", self.default_headers)
|
49
|
+
|
50
|
+
return report
|
@@ -0,0 +1,142 @@
|
|
1
|
+
import time
|
2
|
+
|
3
|
+
from ..models.base import *
|
4
|
+
from ..models.republic import *
|
5
|
+
from ..models.state import *
|
6
|
+
from ..models.scale import *
|
7
|
+
|
8
|
+
class StateInterface(Interface):
|
9
|
+
"""
|
10
|
+
Gère les interactions avec les votes et les officiers.
|
11
|
+
|
12
|
+
## Informations
|
13
|
+
- Liste des partis enregistrés: `.Party`
|
14
|
+
- Liste des élections: `.Election`
|
15
|
+
- Liste des officiers et candidats: `.Officer | .Candidate`
|
16
|
+
- Résultats des votes: `.Vote`
|
17
|
+
"""
|
18
|
+
|
19
|
+
def __init__(self, url: str, token: str) -> None:
|
20
|
+
super().__init__(url, token)
|
21
|
+
|
22
|
+
"""
|
23
|
+
---- VOTES ----
|
24
|
+
"""
|
25
|
+
|
26
|
+
def get_vote(self, id: NSID) -> Vote:
|
27
|
+
"""
|
28
|
+
Récupère un vote.
|
29
|
+
|
30
|
+
## Paramètres
|
31
|
+
id: `NSID`\n
|
32
|
+
ID du vote.
|
33
|
+
|
34
|
+
## Renvoie
|
35
|
+
- `.Vote`
|
36
|
+
"""
|
37
|
+
|
38
|
+
id = NSID(id)
|
39
|
+
res = requests.get(f"{self.url}/votes/{id}", headers = self.default_headers)
|
40
|
+
|
41
|
+
if not res:
|
42
|
+
return None
|
43
|
+
|
44
|
+
_data = res.json()
|
45
|
+
|
46
|
+
vote = Vote(id, _data['title'])
|
47
|
+
vote._load(_data, url = f"{self.url}/votes/{id}", headers = self.default_headers)
|
48
|
+
|
49
|
+
return vote
|
50
|
+
|
51
|
+
def open_vote(self, title: str = None, options: list[dict] = [], end: int = 0) -> Vote:
|
52
|
+
"""
|
53
|
+
Déclenche un vote dans la base de données.
|
54
|
+
|
55
|
+
## Paramètres
|
56
|
+
- title: `str`\n
|
57
|
+
Titre du vote
|
58
|
+
- options: list[dict]\n
|
59
|
+
Liste des choix disponibles
|
60
|
+
- end: `int`\n
|
61
|
+
Fin du vote (timestamp)
|
62
|
+
"""
|
63
|
+
|
64
|
+
payload = {
|
65
|
+
"options": options,
|
66
|
+
"end_date": end
|
67
|
+
}
|
68
|
+
|
69
|
+
if title:
|
70
|
+
payload['title'] = title
|
71
|
+
|
72
|
+
res = requests.put(f"{self.url}/open_vote", headers = self.default_headers, json = _data)
|
73
|
+
|
74
|
+
if res.status_code == 200:
|
75
|
+
_data = res.json()
|
76
|
+
|
77
|
+
vote = Vote()
|
78
|
+
vote._load(_data, url = f"{self.url}/votes/{_data['id']}", headers = self.default_headers)
|
79
|
+
else:
|
80
|
+
res.raise_for_status()
|
81
|
+
|
82
|
+
# Aucune possibilité de supprimer un vote
|
83
|
+
|
84
|
+
"""
|
85
|
+
PARTIS
|
86
|
+
"""
|
87
|
+
|
88
|
+
def get_party(self, id: NSID) -> Party:
|
89
|
+
"""
|
90
|
+
Récupère un parti politique.
|
91
|
+
|
92
|
+
## Paramètres
|
93
|
+
id: `NSID`\n
|
94
|
+
ID du parti.
|
95
|
+
|
96
|
+
## Renvoie
|
97
|
+
- `.Party`
|
98
|
+
"""
|
99
|
+
|
100
|
+
id = NSID(id)
|
101
|
+
res = requests.get(f"{self.url}/parties/{id}", headers = self.default_headers)
|
102
|
+
|
103
|
+
if not res:
|
104
|
+
return None
|
105
|
+
|
106
|
+
_data = res.json()
|
107
|
+
|
108
|
+
party = Party(id)
|
109
|
+
party._load(_data, url = f"{self.url}/parties/{id}", headers = self.default_headers)
|
110
|
+
|
111
|
+
return party
|
112
|
+
|
113
|
+
def register_party(self, id: NSID, color: int, motto: str = None, scale: dict | Scale = {}) -> Party:
|
114
|
+
"""
|
115
|
+
Enregistre un nouveau parti pour que ses députés puissent s'y présenter.
|
116
|
+
|
117
|
+
## Paramètres
|
118
|
+
- id: `NSID`\n
|
119
|
+
ID de l'entreprise à laquelle correspond le parti
|
120
|
+
- color: `int`\n
|
121
|
+
Couleur du parti
|
122
|
+
- motto: `str, optional`\n
|
123
|
+
Devise du parti
|
124
|
+
- politiscales: `.Scale`\n
|
125
|
+
Résultats du parti au test Politiscales
|
126
|
+
"""
|
127
|
+
|
128
|
+
payload = {
|
129
|
+
"color": color,
|
130
|
+
"motto": motto,
|
131
|
+
"scale": scale
|
132
|
+
}
|
133
|
+
|
134
|
+
res = requests.put(f"{self.url}/register_party?candidate={id}", headers = self.default_headers, json = _data)
|
135
|
+
|
136
|
+
if res.status_code == 200:
|
137
|
+
_data = res.json()
|
138
|
+
|
139
|
+
vote = Vote()
|
140
|
+
vote._load(_data, url = f"{self.url}/votes/{_data['id']}", headers = self.default_headers)
|
141
|
+
else:
|
142
|
+
res.raise_for_status()
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import math
|
2
|
+
import time
|
3
|
+
|
4
|
+
EPOCH = 1577833200 # 1er Janvier 2020
|
5
|
+
PATIENTAGE_DATE = 1725141600 # 1er Septembre 2024
|
6
|
+
OPEN_DATE = 1756677600 # 1er Septembre 2025
|
7
|
+
|
8
|
+
MANDATE_DURATION = 2419200
|
9
|
+
|
10
|
+
def get_cycle(ts: int = round(time.time())):
|
11
|
+
if EPOCH <= ts < PATIENTAGE_DATE:
|
12
|
+
return 0
|
13
|
+
elif PATIENTAGE_DATE <= ts < OPEN_DATE:
|
14
|
+
return 1
|
15
|
+
elif OPEN_DATE <= ts:
|
16
|
+
return math.floor((ts - OPEN_DATE) / MANDATE_DURATION) + 2
|
17
|
+
else:
|
18
|
+
raise ValueError(f"Timestamp {ts} is out of range (must be greater than or equal to {EPOCH}).")
|
19
|
+
|
20
|
+
def get_day(ts: int = round(time.time())) -> int:
|
21
|
+
cycle = get_cycle(ts)
|
22
|
+
|
23
|
+
if cycle == 0:
|
24
|
+
return math.floor((ts - EPOCH) / 86400)
|
25
|
+
elif cycle == 1:
|
26
|
+
return math.floor((ts - PATIENTAGE_DATE) / 86400)
|
27
|
+
else:
|
28
|
+
return math.floor(((ts - OPEN_DATE) % MANDATE_DURATION) / 86400)
|
29
|
+
|
30
|
+
def get_phase(ts: int = round(time.time())) -> str:
|
31
|
+
cycle = get_cycle(ts)
|
32
|
+
|
33
|
+
if cycle < 2: # Les deux premiers cycles durent (beaucoup) plus longtemps qu'un cycle normal.
|
34
|
+
return 'undefined'
|
35
|
+
|
36
|
+
day = get_day(ts)
|
37
|
+
|
38
|
+
if day == 0:
|
39
|
+
return 'investiture' # Investiture du PR
|
40
|
+
elif 1 <= day < 24:
|
41
|
+
return 'paix' # Rien du tout
|
42
|
+
elif 24 <= day < 28:
|
43
|
+
return 'partials' # Élections législatives
|
44
|
+
elif 28 <= day < 52:
|
45
|
+
return 'paix' # Toujours rien
|
46
|
+
elif 52 <= day < 56:
|
47
|
+
return 'elections' # Élections législatives et présidentielles
|
48
|
+
|
49
|
+
else:
|
50
|
+
raise ValueError(f"Idk what happened but it seems that {day} is greater than 55...")
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import io
|
2
1
|
import json
|
3
2
|
import requests
|
4
3
|
import typing
|
@@ -40,17 +39,18 @@ class NSID(str):
|
|
40
39
|
if value.startswith("0x"):
|
41
40
|
value = value[2:]
|
42
41
|
|
43
|
-
|
44
|
-
return
|
42
|
+
interface = super(NSID, cls).__new__(cls, value.upper())
|
43
|
+
return interface
|
45
44
|
|
46
|
-
class
|
45
|
+
class Interface:
|
47
46
|
"""
|
48
|
-
Instance qui servira de base à toutes les
|
47
|
+
Instance qui servira de base à toutes les interfaces.
|
49
48
|
"""
|
50
49
|
|
51
50
|
def __init__(self, url: str, token: str = None):
|
52
51
|
self.url = url
|
53
52
|
self.token = token
|
53
|
+
self.zone = 20 # 10 = Serveur test, 20 = Serveur principal, 30 = Serveur de patientage, 40 = Scratch World
|
54
54
|
|
55
55
|
self.default_headers = {
|
56
56
|
"Authorization": f"Bearer {self.token}",
|
@@ -71,6 +71,24 @@ class Instance:
|
|
71
71
|
except:
|
72
72
|
utils.warn("NationDB is not responding.")
|
73
73
|
|
74
|
+
def alias(self, alias: NSID) -> typing.Self:
|
75
|
+
"""
|
76
|
+
Duplique l'interface en se faisant passer pour une autre entité. Aucune erreur ne sera levée si l'entité n'existe pas (hormis les éventuels 401 ou 404 renvoyés par le serveur).
|
77
|
+
|
78
|
+
## Paramètres
|
79
|
+
alias: `NSID`\n
|
80
|
+
ID de l'entité à simuler
|
81
|
+
|
82
|
+
## Renvoie
|
83
|
+
- `self` avec le token de l'alias
|
84
|
+
"""
|
85
|
+
|
86
|
+
alias = NSID(alias)
|
87
|
+
|
88
|
+
token = self.token + ':' + str(alias)
|
89
|
+
|
90
|
+
return self.__class__(self.url, token)
|
91
|
+
|
74
92
|
def request_token(self, username: str, password: str) -> str | None:
|
75
93
|
res = requests.post(f"{self.url}/auth/login", json = {
|
76
94
|
"username": username,
|