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/cls/archives.py CHANGED
@@ -2,69 +2,92 @@ import time
2
2
 
3
3
  from .base import *
4
4
 
5
- class Action:
6
- def __init__(self, author: str | NSID = '0', target: str | NSID = '0') -> None:
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
- 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
36
+ # Entities
24
37
 
25
- class AdminAction(Action):
26
- def __init__(self, author: str | NSID, target: str | NSID) -> None:
38
+ class Sanction(Archive):
39
+ def __init__(self, author: NSID, target: NSID) -> None:
27
40
  super().__init__(author, target)
28
41
 
29
- self.details: str = ""
30
- self.new_state: str | int | bool = None
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(Action):
33
- def __init__(self, author: str | NSID, target: str | NSID) -> None:
48
+ class Report(Archive):
49
+ def __init__(self, author: NSID, target: NSID) -> None:
34
50
  super().__init__(author, target)
35
51
 
36
- self.details: str = ""
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(Action):
42
- def __init__(self, author: str | NSID, target: str | NSID, position: str) -> None:
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.position: str = position
46
- self.positive_votes: int = 0
47
- self.total_votes: int = 0
64
+ self.details = {
65
+ "position": position,
66
+ "positive_votes": 0,
67
+ "total_votes": 0
68
+ }
48
69
 
49
- class Promotion(Action):
50
- def __init__(self, author: str | NSID, target: str | NSID, position: str) -> None:
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.position: str = position
74
+ self.details = {
75
+ "position": position
76
+ }
54
77
 
55
- class Demotion(Action):
56
- def __init__(self, author: str | NSID, target: str | NSID) -> None:
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(Action):
65
- def __init__(self, author: str | NSID, target: str | NSID, amount: int) -> None:
85
+ class Transaction(Archive):
86
+ def __init__(self, author: NSID, target: NSID) -> None:
66
87
  super().__init__(author, target)
67
88
 
68
- self.amount: int = amount
69
- self.currency: str = 'HC'
70
- self.reason: str = None
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 = "01"
4
- gov = "02"
5
- assembly = "03"
6
- court = "04"
7
- office = "05"
8
- hexabank = "06"
9
- archives = "07"
10
-
11
- maintenance_committee = "101"
12
- audiovisual_department = "102"
13
- interior_department = "103"
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 nsarchive.cls.base import NSID
2
- from .base import *
1
+ from .base import NSID
3
2
 
4
3
  class BankAccount:
5
- def __init__(self, id: str | NSID) -> None:
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.locked: bool = False
10
- self.bank: str = "HexaBank"
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
- def __init__(self, id: str | NSID) -> None:
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: list[Item] = []
62
+ self.objects: dict[str, NSID] = {}
24
63
 
25
64
  def append(self, item: Item, quantity: int = 1):
26
- self.objects.extend(quantity * [item])
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 quantity > self.objects.count(item):
30
- quantity = self.objects.count(item)
31
-
32
- for i in range(quantity):
33
- self.objects.remove(item)
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)