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.
- nsarchive/__init__.py +20 -806
- nsarchive/cls/archives.py +58 -35
- nsarchive/cls/base.py +174 -14
- nsarchive/cls/economy.py +71 -13
- nsarchive/cls/entities.py +176 -38
- nsarchive/cls/republic.py +104 -20
- nsarchive/instances/_economy.py +313 -0
- nsarchive/instances/_entities.py +321 -0
- nsarchive/instances/_republic.py +313 -0
- nsarchive/utils.py +26 -0
- nsarchive-2.0.0.dist-info/METADATA +20 -0
- nsarchive-2.0.0.dist-info/RECORD +16 -0
- nsarchive/utils/assets.py +0 -15
- nsarchive-1.3.0.dist-info/METADATA +0 -177
- nsarchive-1.3.0.dist-info/RECORD +0 -13
- {nsarchive-1.3.0.dist-info → nsarchive-2.0.0.dist-info}/LICENSE +0 -0
- {nsarchive-1.3.0.dist-info → nsarchive-2.0.0.dist-info}/WHEEL +0 -0
nsarchive/cls/archives.py
CHANGED
@@ -2,69 +2,92 @@ import time
|
|
2
2
|
|
3
3
|
from .base import *
|
4
4
|
|
5
|
-
class
|
6
|
-
def __init__(self, author:
|
5
|
+
class Archive:
|
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)
|
10
|
-
self.action: str = ""
|
11
27
|
self.author: NSID = NSID(author)
|
12
28
|
self.target: NSID = NSID(target)
|
13
29
|
|
30
|
+
self.action: str = ""
|
31
|
+
self.details: dict = {
|
32
|
+
"reason": None
|
33
|
+
}
|
14
34
|
|
15
|
-
# Entities
|
16
35
|
|
17
|
-
|
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
|
36
|
+
# Entities
|
24
37
|
|
25
|
-
class
|
26
|
-
def __init__(self, author:
|
38
|
+
class Sanction(Archive):
|
39
|
+
def __init__(self, author: NSID, target: NSID) -> None:
|
27
40
|
super().__init__(author, target)
|
28
41
|
|
29
|
-
self.details:
|
30
|
-
|
42
|
+
self.details: dict = {
|
43
|
+
"reason": None,
|
44
|
+
"major": False, # Sanction majeure ou non
|
45
|
+
"duration": 0 # Durée en secondes , 0 = définitif
|
46
|
+
}
|
31
47
|
|
32
|
-
class Report(
|
33
|
-
def __init__(self, author:
|
48
|
+
class Report(Archive):
|
49
|
+
def __init__(self, author: NSID, target: NSID) -> None:
|
34
50
|
super().__init__(author, target)
|
35
51
|
|
36
|
-
self.details:
|
52
|
+
self.details: dict = {
|
53
|
+
"reason": None,
|
54
|
+
"elements": [] # Liste des pièces jointes
|
55
|
+
}
|
37
56
|
|
38
57
|
|
39
58
|
# Community
|
40
59
|
|
41
|
-
class Election(
|
42
|
-
def __init__(self, author:
|
60
|
+
class Election(Archive):
|
61
|
+
def __init__(self, author: NSID, target: NSID, position: str) -> None:
|
43
62
|
super().__init__(author, target)
|
44
63
|
|
45
|
-
self.
|
46
|
-
|
47
|
-
|
64
|
+
self.details = {
|
65
|
+
"position": position,
|
66
|
+
"positive_votes": 0,
|
67
|
+
"total_votes": 0
|
68
|
+
}
|
48
69
|
|
49
|
-
class Promotion(
|
50
|
-
def __init__(self, author:
|
70
|
+
class Promotion(Archive):
|
71
|
+
def __init__(self, author: NSID, target: NSID, position: str) -> None:
|
51
72
|
super().__init__(author, target)
|
52
73
|
|
53
|
-
self.
|
74
|
+
self.details = {
|
75
|
+
"position": position
|
76
|
+
}
|
54
77
|
|
55
|
-
class Demotion(
|
56
|
-
def __init__(self, author:
|
78
|
+
class Demotion(Archive):
|
79
|
+
def __init__(self, author: NSID, target: NSID) -> None:
|
57
80
|
super().__init__(author, target)
|
58
81
|
|
59
|
-
self.reason: str = None
|
60
|
-
|
61
82
|
|
62
83
|
# Bank
|
63
84
|
|
64
|
-
class Transaction(
|
65
|
-
def __init__(self, author:
|
85
|
+
class Transaction(Archive):
|
86
|
+
def __init__(self, author: NSID, target: NSID) -> None:
|
66
87
|
super().__init__(author, target)
|
67
88
|
|
68
|
-
self.
|
69
|
-
|
70
|
-
|
89
|
+
self.details = {
|
90
|
+
"amount": 0,
|
91
|
+
"currency": "HC",
|
92
|
+
"reason": None
|
93
|
+
}
|
nsarchive/cls/base.py
CHANGED
@@ -1,16 +1,29 @@
|
|
1
|
+
import json
|
2
|
+
import typing
|
3
|
+
|
4
|
+
from supabase import Client
|
5
|
+
|
1
6
|
class NSID(str):
|
7
|
+
"""
|
8
|
+
Nation Server ID
|
9
|
+
|
10
|
+
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.
|
11
|
+
"""
|
2
12
|
unknown = "0"
|
3
|
-
admin = "
|
4
|
-
gov = "
|
5
|
-
|
6
|
-
|
7
|
-
office = "
|
8
|
-
hexabank = "
|
9
|
-
archives = "
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
admin = "1"
|
14
|
+
gov = "2"
|
15
|
+
court = "3"
|
16
|
+
assembly = "4"
|
17
|
+
office = "5"
|
18
|
+
hexabank = "6"
|
19
|
+
archives = "7"
|
20
|
+
|
21
|
+
maintenance_com = "101"
|
22
|
+
audiovisual_dept = "102"
|
23
|
+
interior_dept = "103"
|
24
|
+
justice_dept = "104"
|
25
|
+
egalitary_com = "105"
|
26
|
+
antifraud_dept = "106"
|
14
27
|
|
15
28
|
def __new__(cls, value):
|
16
29
|
if type(value) == int:
|
@@ -19,9 +32,156 @@ class NSID(str):
|
|
19
32
|
value = hex(int(value, 16))
|
20
33
|
else:
|
21
34
|
raise TypeError(f"<{value}> is not NSID serializable")
|
22
|
-
|
35
|
+
|
23
36
|
if value.startswith("0x"):
|
24
37
|
value = value[2:]
|
25
|
-
|
38
|
+
|
26
39
|
instance = super(NSID, cls).__new__(cls, value.upper())
|
27
|
-
return instance
|
40
|
+
return instance
|
41
|
+
|
42
|
+
class Instance:
|
43
|
+
"""
|
44
|
+
Instance qui servira de base à toutes les instances.
|
45
|
+
"""
|
46
|
+
def __init__(self, client: Client):
|
47
|
+
self.db = client
|
48
|
+
|
49
|
+
def _select_from_db(self, table: str, key: str = None, value: str = None) -> list:
|
50
|
+
"""
|
51
|
+
Récupère des données JSON d'une table Supabase en fonction de l'ID.
|
52
|
+
|
53
|
+
## Paramètres
|
54
|
+
table: `str`:\n
|
55
|
+
Nom de la base
|
56
|
+
key: `str`\n
|
57
|
+
Clé à vérifier
|
58
|
+
value: `str`\n
|
59
|
+
Valeur de la clé à vérifier
|
60
|
+
|
61
|
+
## Renvoie
|
62
|
+
- `list` de tous les élements correspondants
|
63
|
+
- `None` si aucune donnée n'est trouvée
|
64
|
+
"""
|
65
|
+
|
66
|
+
if key and value:
|
67
|
+
res = self.db.from_(table).select("*").eq(key, value).execute()
|
68
|
+
else:
|
69
|
+
res = self.db.from_(table).select("*").execute()
|
70
|
+
|
71
|
+
if res.data:
|
72
|
+
return res.data
|
73
|
+
else:
|
74
|
+
return None
|
75
|
+
|
76
|
+
def _get_by_ID(self, table: str, id: NSID) -> dict:
|
77
|
+
_data = self._select_from_db(table, 'id', id)
|
78
|
+
|
79
|
+
if _data is not None:
|
80
|
+
_data = _data[0]
|
81
|
+
|
82
|
+
return _data
|
83
|
+
|
84
|
+
def _put_in_db(self, table: str, data: dict) -> None:
|
85
|
+
"""
|
86
|
+
Publie des données JSON dans une table Supabase en utilisant le client Supabase.
|
87
|
+
|
88
|
+
:param table: Nom de la table dans laquelle les données doivent être insérées
|
89
|
+
:param data: Dictionnaire contenant les données à publier
|
90
|
+
:return: Résultat de l'insertion
|
91
|
+
"""
|
92
|
+
|
93
|
+
res = self.db.from_(table).upsert(data).execute()
|
94
|
+
|
95
|
+
return res
|
96
|
+
|
97
|
+
def _delete_from_db(self, table: str, key: str, value: str):
|
98
|
+
"""
|
99
|
+
Supprime un enregistrement d'une table Supabase en fonction d'une clé et de sa valeur.
|
100
|
+
|
101
|
+
## Paramètres
|
102
|
+
table: `str`
|
103
|
+
Nom de la table dans laquelle les données doivent être supprimées
|
104
|
+
key: `str`
|
105
|
+
Clé à vérifier (par exemple "id" ou autre clé unique)
|
106
|
+
value: `str`
|
107
|
+
Valeur de la clé à vérifier pour trouver l'enregistrement à supprimer
|
108
|
+
|
109
|
+
## Renvoie
|
110
|
+
- `True` si la suppression a réussi
|
111
|
+
- `False` si aucune donnée n'a été trouvée ou si la suppression a échoué
|
112
|
+
"""
|
113
|
+
|
114
|
+
res = self.db.from_(table).delete().eq(key, value).execute()
|
115
|
+
|
116
|
+
return res
|
117
|
+
|
118
|
+
def _delete_by_ID(self, table: str, id: NSID):
|
119
|
+
res = self._delete_from_db(table, 'id', id)
|
120
|
+
|
121
|
+
return res
|
122
|
+
|
123
|
+
def fetch(self, table: str, **query: typing.Any) -> list:
|
124
|
+
matches = []
|
125
|
+
|
126
|
+
for key, value in query.items():
|
127
|
+
entity = self._select_from_db(table, key, value)
|
128
|
+
|
129
|
+
if entity is not None:
|
130
|
+
matches.append(entity)
|
131
|
+
|
132
|
+
if query == {}:
|
133
|
+
matches = [ self._select_from_db(table) ]
|
134
|
+
|
135
|
+
if not matches or (len(matches) != len(query) and query != {}):
|
136
|
+
return []
|
137
|
+
|
138
|
+
_res = [ item for item in matches[0] if all(item in match for match in matches[1:]) ]
|
139
|
+
|
140
|
+
return _res
|
141
|
+
|
142
|
+
def _upload_to_storage(self, bucket: str, data: bytes, path: str, overwrite: bool = False, options: dict = {'content-type': 'image/png'}) -> dict:
|
143
|
+
"""
|
144
|
+
Envoie un fichier dans un bucket Supabase.
|
145
|
+
|
146
|
+
## Paramètres
|
147
|
+
bucket: `str`\n
|
148
|
+
Nom du bucket où le fichier sera stocké
|
149
|
+
data: `bytes`\n
|
150
|
+
Données à uploader
|
151
|
+
path: `str`\n
|
152
|
+
Chemin dans le bucket où le fichier sera stocké
|
153
|
+
|
154
|
+
## Renvoie
|
155
|
+
- `dict` contenant les informations de l'upload si réussi
|
156
|
+
- `None` en cas d'échec
|
157
|
+
"""
|
158
|
+
|
159
|
+
options["upsert"] = json.dumps(overwrite)
|
160
|
+
|
161
|
+
if len(data) > 5 * 1000 ** 3:
|
162
|
+
raise ValueError("La limite d'un fichier à upload est de 1Mo")
|
163
|
+
|
164
|
+
res = self.db.storage.from_(bucket).upload(path, data, options)
|
165
|
+
|
166
|
+
if res.json().get("error"):
|
167
|
+
print("Erreur lors de l'upload:", res["error"])
|
168
|
+
|
169
|
+
return res
|
170
|
+
|
171
|
+
def _download_from_storage(self, bucket: str, path: str) -> bytes:
|
172
|
+
"""
|
173
|
+
Télécharge un fichier depuis le stockage Supabase.
|
174
|
+
|
175
|
+
## Paramètres
|
176
|
+
bucket: `str`\n
|
177
|
+
Nom du bucket où il faut chercher le fichier
|
178
|
+
path: `str`\n
|
179
|
+
Chemin du fichier dans le bucket
|
180
|
+
|
181
|
+
## Renvoie
|
182
|
+
- Le fichier demandé en `bytes`
|
183
|
+
"""
|
184
|
+
|
185
|
+
res = self.db.storage.from_(bucket).download(path)
|
186
|
+
|
187
|
+
return res
|
nsarchive/cls/economy.py
CHANGED
@@ -1,38 +1,96 @@
|
|
1
|
-
from
|
2
|
-
from .base import *
|
1
|
+
from .base import NSID
|
3
2
|
|
4
3
|
class BankAccount:
|
5
|
-
|
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:
|
6
23
|
self.id: NSID = NSID(id)
|
7
24
|
self.owner: NSID = NSID(0)
|
8
25
|
self.amount: int = 0
|
9
|
-
self.
|
10
|
-
self.bank:
|
26
|
+
self.frozen: bool = False
|
27
|
+
self.bank: NSID = NSID("6")
|
11
28
|
|
12
29
|
self.income: int = 0
|
13
30
|
|
14
31
|
class Item:
|
15
|
-
|
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:
|
16
45
|
self.id: NSID = NSID(id)
|
17
46
|
self.title: str = "Unknown Object"
|
18
47
|
self.emoji: str = ":light_bulb:"
|
19
48
|
|
20
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
|
+
|
21
60
|
def __init__(self, owner_id: NSID) -> None:
|
22
61
|
self.owner_id: NSID = NSID(owner_id)
|
23
|
-
self.objects:
|
62
|
+
self.objects: dict[str, NSID] = {}
|
24
63
|
|
25
64
|
def append(self, item: Item, quantity: int = 1):
|
26
|
-
self.objects.
|
65
|
+
if item.id in self.objects.keys():
|
66
|
+
self.objects[item.id] += quantity
|
67
|
+
else:
|
68
|
+
self.objects[item.id] = quantity
|
27
69
|
|
28
70
|
def throw(self, item: Item, quantity: int = 1):
|
29
|
-
if
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
34
76
|
|
35
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
|
+
|
36
94
|
def __init__(self, id: NSID, item: Item) -> None:
|
37
95
|
self.id: NSID = NSID(id)
|
38
96
|
self.item: NSID = NSID(item.id)
|