From aa05f5aaa7a5fba07152e0c57e53221f6a328a0d Mon Sep 17 00:00:00 2001 From: ValDesign Date: Wed, 23 Apr 2025 18:07:10 +0200 Subject: [PATCH 01/17] fix: Update documentation link for bot registration --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c77a805..fabfe5d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ pip install discordanalytics ## Usage -> **Note:** To use Discord Analytics, you need to have an API token. Check the docs for more informations : https://docs.discordanalytics.xyz/get-started/bot-registration +> **Note:** To use Discord Analytics, you need to have an API token. Check the docs for more informations : https://discordanalytics.xyz/docs/main/get-started/bot-registration ```python import discord From 4465b001677e1b15c26fef2affd3b50121574489 Mon Sep 17 00:00:00 2001 From: ValDesign Date: Wed, 23 Apr 2025 18:25:41 +0200 Subject: [PATCH 02/17] chore: Bump version to 3.2.0 and add custom event handling --- discordanalytics/__init__.py | 2 +- discordanalytics/client.py | 40 ++++++++++++++++++++++++++++++++++-- pyproject.toml | 2 +- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/discordanalytics/__init__.py b/discordanalytics/__init__.py index 25bc051..660e53b 100644 --- a/discordanalytics/__init__.py +++ b/discordanalytics/__init__.py @@ -1,6 +1,6 @@ __title__ = 'discordanalytics' __author__ = "ValDesign" __license__ = "MIT" -__version__ = "3.1.6" +__version__ = "3.2.0" from .client import * diff --git a/discordanalytics/client.py b/discordanalytics/client.py index 07a8275..107581b 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -22,6 +22,32 @@ class ErrorCodes: SUSPENDED_BOT = "Your bot has been suspended, please check your mailbox for more information." INVALID_EVENTS_COUNT = "invalid events count" +class Event: + def __init__(self, analytics, event_key: str): + self.analytics = analytics + self.event_key = event_key + + def increment(self, count: int = 1): + if self.analytics.debug: + print(f"[DISCORDANALYTICS] Incrementing event {self.event_key} by {count}") + if not isinstance(count, int) or count < 0: + raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) + self.analytics.stats["custom_events"][self.event_key] += count + + def decrement(self, count: int = 1): + if self.analytics.debug: + print(f"[DISCORDANALYTICS] Decrementing event {self.event_key} by {count}") + if not isinstance(count, int) or count < 0: + raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) + self.analytics.stats["custom_events"][self.event_key] -= count + + def set(self, value: int): + if self.analytics.debug: + print(f"[DISCORDANALYTICS] Setting event {self.event_key} to {value}") + if not isinstance(value, int) or value < 0: + raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) + self.analytics.stats["custom_events"][self.event_key] = value + class DiscordAnalytics(): def __init__(self, client: discord.Client, api_key: str, debug: bool = False, chunk_guilds_at_startup: bool = True): self.client = client @@ -54,7 +80,8 @@ def __init__(self, client: discord.Client, api_key: str, debug: bool = False, ch "new_member": 0, "other": 0, "private_message": 0 - } + }, + "custom_events": {}, # {[event_key:str]: int} } def track_events(self): @@ -314,4 +341,13 @@ def trackGuilds(self, guild: discord.Guild, type: Literal["create", "delete"]): if type == "create": self.stats["addedGuilds"] += 1 elif type == "delete": - self.stats["removedGuilds"] += 1 \ No newline at end of file + self.stats["removedGuilds"] += 1 + + def events(self, event_key: str): + if self.debug: + print(f"[DISCORDANALYTICS] Event {event_key} triggered") + if not self.client.is_ready(): + raise ValueError(ErrorCodes.CLIENT_NOT_READY) + if event_key not in self.stats["custom_events"]: + self.stats["custom_events"][event_key] = 0 + return Event(self, event_key) diff --git a/pyproject.toml b/pyproject.toml index 5f08eb3..cdd6135 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "discordanalytics" description = "A Python package for interacting with Discord Analytics API" -version = "3.1.6" +version = "3.2.0" authors = [{ name = "ValDesign", email = "valdesign.dev@gmail.com" }] requires-python = ">=3.8" readme = "README.md" From 0dd3f2888688a41d7488332111ab3e044ccff9df Mon Sep 17 00:00:00 2001 From: ValDesign Date: Wed, 23 Apr 2025 18:33:25 +0200 Subject: [PATCH 03/17] fix: Added custom_events reset after stats are sent --- discordanalytics/client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/discordanalytics/client.py b/discordanalytics/client.py index 107581b..f018c05 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -220,7 +220,8 @@ async def send_stats(self): "new_member": 0, "other": 0, "private_message": 0 - } + }, + "custom_events": {}, } await asyncio.sleep(30 if "--dev" in sys.argv else 300) From 41ec38622c648ddcef0135c4600af483af3ebf31 Mon Sep 17 00:00:00 2001 From: ValDesign Date: Wed, 23 Apr 2025 18:48:06 +0200 Subject: [PATCH 04/17] fix: Update error handling for invalid value types in Event methods --- discordanalytics/client.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/discordanalytics/client.py b/discordanalytics/client.py index f018c05..ed7cae6 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -21,6 +21,7 @@ class ErrorCodes: DATA_NOT_SENT = "Data cannot be sent to the API, I will try again in a minute." SUSPENDED_BOT = "Your bot has been suspended, please check your mailbox for more information." INVALID_EVENTS_COUNT = "invalid events count" + INVALID_VALUE_TYPE = "invalid value type" class Event: def __init__(self, analytics, event_key: str): @@ -31,21 +32,21 @@ def increment(self, count: int = 1): if self.analytics.debug: print(f"[DISCORDANALYTICS] Incrementing event {self.event_key} by {count}") if not isinstance(count, int) or count < 0: - raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) + raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) self.analytics.stats["custom_events"][self.event_key] += count def decrement(self, count: int = 1): if self.analytics.debug: print(f"[DISCORDANALYTICS] Decrementing event {self.event_key} by {count}") if not isinstance(count, int) or count < 0: - raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) + raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) self.analytics.stats["custom_events"][self.event_key] -= count def set(self, value: int): if self.analytics.debug: print(f"[DISCORDANALYTICS] Setting event {self.event_key} to {value}") if not isinstance(value, int) or value < 0: - raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) + raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) self.analytics.stats["custom_events"][self.event_key] = value class DiscordAnalytics(): From d8c69d16d627e638998f8db95c06985686305ab9 Mon Sep 17 00:00:00 2001 From: ValDesign Date: Wed, 23 Apr 2025 18:51:44 +0200 Subject: [PATCH 05/17] fix: Add event existence check in Event methods and improve error handling --- discordanalytics/client.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/discordanalytics/client.py b/discordanalytics/client.py index ed7cae6..122ebb0 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -28,11 +28,20 @@ def __init__(self, analytics, event_key: str): self.analytics = analytics self.event_key = event_key + def ensure(self): + if self.analytics.debug: + print(f"[DISCORDANALYTICS] Ensuring event {self.event_key} exists") + if not isinstance(self.event_key, str) or len(self.event_key) < 1 or len(self.event_key) > 50: + raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) + if self.event_key not in self.analytics.stats["custom_events"]: + self.analytics.stats["custom_events"][self.event_key] = 0 + def increment(self, count: int = 1): if self.analytics.debug: print(f"[DISCORDANALYTICS] Incrementing event {self.event_key} by {count}") if not isinstance(count, int) or count < 0: raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) + self.ensure() self.analytics.stats["custom_events"][self.event_key] += count def decrement(self, count: int = 1): @@ -40,6 +49,7 @@ def decrement(self, count: int = 1): print(f"[DISCORDANALYTICS] Decrementing event {self.event_key} by {count}") if not isinstance(count, int) or count < 0: raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) + self.ensure() self.analytics.stats["custom_events"][self.event_key] -= count def set(self, value: int): @@ -47,6 +57,7 @@ def set(self, value: int): print(f"[DISCORDANALYTICS] Setting event {self.event_key} to {value}") if not isinstance(value, int) or value < 0: raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) + self.ensure() self.analytics.stats["custom_events"][self.event_key] = value class DiscordAnalytics(): From 59f199b54a622c34d6e460fa8fd51c8fe82ee67f Mon Sep 17 00:00:00 2001 From: ValDesign Date: Thu, 24 Apr 2025 10:59:20 +0200 Subject: [PATCH 06/17] refactor: Simplify guild members repartition calculation using Counter and threshold functions --- discordanalytics/client.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/discordanalytics/client.py b/discordanalytics/client.py index 122ebb0..d8e1aee 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -1,4 +1,5 @@ import asyncio +from collections import Counter from datetime import datetime from typing import Literal import discord @@ -239,24 +240,21 @@ async def send_stats(self): await asyncio.sleep(30 if "--dev" in sys.argv else 300) def calculate_guild_members_repartition(self): - result = { - "little": 0, - "medium": 0, - "big": 0, - "huge": 0 + tresholds = { + "little": lambda count: count <= 100, + "medium": lambda count: 100 < count <= 500, + "big": lambda count: 500 < count <= 1500, + "huge": lambda count: count > 1500 } - for guild in self.client.guilds: - if guild.member_count <= 100: - result["little"] += 1 - elif 100 < guild.member_count <= 500: - result["medium"] += 1 - elif 500 < guild.member_count <= 1500: - result["big"] += 1 - else: - result["huge"] += 1 + counter = Counter() - return result + for guild in self.client.guilds: + for key, condition in tresholds.items(): + if condition(guild.member_count): + counter[key] += 1 + break + return dict(counter) def track_interactions(self, interaction: discord.Interaction): if self.debug: From 3691a4b5f3e4b07c470f8fbf7f173c17caab90cb Mon Sep 17 00:00:00 2001 From: ValDesign Date: Thu, 24 Apr 2025 10:59:52 +0200 Subject: [PATCH 07/17] fix: Correct typo in variable name from 'tresholds' to 'thresholds' in calculate_guild_members_repartition method --- discordanalytics/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discordanalytics/client.py b/discordanalytics/client.py index d8e1aee..40eb8dd 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -240,7 +240,7 @@ async def send_stats(self): await asyncio.sleep(30 if "--dev" in sys.argv else 300) def calculate_guild_members_repartition(self): - tresholds = { + thresholds = { "little": lambda count: count <= 100, "medium": lambda count: 100 < count <= 500, "big": lambda count: 500 < count <= 1500, @@ -250,7 +250,7 @@ def calculate_guild_members_repartition(self): counter = Counter() for guild in self.client.guilds: - for key, condition in tresholds.items(): + for key, condition in thresholds.items(): if condition(guild.member_count): counter[key] += 1 break From a05c5b838f97a8dcacdb8e91442f0ab098b4fc05 Mon Sep 17 00:00:00 2001 From: ValDesign Date: Thu, 24 Apr 2025 11:09:08 +0200 Subject: [PATCH 08/17] chore: Update version number to 3.5.0 in __init__.py and pyproject.toml --- discordanalytics/__init__.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/discordanalytics/__init__.py b/discordanalytics/__init__.py index 660e53b..5a751e3 100644 --- a/discordanalytics/__init__.py +++ b/discordanalytics/__init__.py @@ -1,6 +1,6 @@ __title__ = 'discordanalytics' __author__ = "ValDesign" __license__ = "MIT" -__version__ = "3.2.0" +__version__ = "3.5.0" from .client import * diff --git a/pyproject.toml b/pyproject.toml index cdd6135..ea20143 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "discordanalytics" description = "A Python package for interacting with Discord Analytics API" -version = "3.2.0" +version = "3.5.0" authors = [{ name = "ValDesign", email = "valdesign.dev@gmail.com" }] requires-python = ">=3.8" readme = "README.md" From e4b6853d398d61cd974d0a7aa7c396b952c132db Mon Sep 17 00:00:00 2001 From: ValDesign Date: Thu, 24 Apr 2025 13:02:26 +0200 Subject: [PATCH 09/17] feat: Add event URL and enhance event validation in Event class --- discordanalytics/client.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/discordanalytics/client.py b/discordanalytics/client.py index 40eb8dd..ff9274d 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -13,6 +13,7 @@ class ApiEndpoints: BASE_URL = "https://discordanalytics.xyz/api" BOT_URL = f"{BASE_URL}/bots/:id" STATS_URL = f"{BASE_URL}/bots/:id/stats" + EVENT_URL = f"{BASE_URL}/bots/:id/events/:event_key" class ErrorCodes: INVALID_CLIENT_TYPE = "Invalid client type, please use a valid client." @@ -23,20 +24,32 @@ class ErrorCodes: SUSPENDED_BOT = "Your bot has been suspended, please check your mailbox for more information." INVALID_EVENTS_COUNT = "invalid events count" INVALID_VALUE_TYPE = "invalid value type" + INVALID_EVENT_KEY = "invalid event key" class Event: def __init__(self, analytics, event_key: str): self.analytics = analytics self.event_key = event_key + self.ensure() + def ensure(self): if self.analytics.debug: print(f"[DISCORDANALYTICS] Ensuring event {self.event_key} exists") if not isinstance(self.event_key, str) or len(self.event_key) < 1 or len(self.event_key) > 50: raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) + + url = ApiEndpoints.EVENT_URL.replace(":id", str(self.analytics.client.user.id)).replace(":event_key", self.event_key) + body = { "event": self.event_key, "count": 0 } + + self.analytics.api_call_with_retries("POST", url, self.analytics.headers, body) + if self.event_key not in self.analytics.stats["custom_events"]: self.analytics.stats["custom_events"][self.event_key] = 0 + if self.analytics.debug: + print(f"[DISCORDANALYTICS] Event {self.event_key} ensured") + def increment(self, count: int = 1): if self.analytics.debug: print(f"[DISCORDANALYTICS] Incrementing event {self.event_key} by {count}") @@ -61,6 +74,14 @@ def set(self, value: int): self.ensure() self.analytics.stats["custom_events"][self.event_key] = value + def get(self): + if self.analytics.debug: + print(f"[DISCORDANALYTICS] Getting event {self.event_key}") + if not isinstance(self.event_key, str) or len(self.event_key) < 1 or len(self.event_key) > 50: + raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) + self.ensure() + return self.analytics.stats["custom_events"][self.event_key] + class DiscordAnalytics(): def __init__(self, client: discord.Client, api_key: str, debug: bool = False, chunk_guilds_at_startup: bool = True): self.client = client @@ -129,6 +150,8 @@ async def api_call_with_retries(self, method, url, headers, json, max_retries=5, raise ValueError(ErrorCodes.INVALID_API_TOKEN) elif response.status == 423: raise ValueError(ErrorCodes.SUSPENDED_BOT) + elif response.status == 404 and "events" in url: + raise ValueError(ErrorCodes.INVALID_EVENT_KEY) else: raise ValueError(ErrorCodes.INVALID_RESPONSE) except (aiohttp.ClientError, ValueError) as e: From 5d41bbc4f6479cf2415b1f8f2a030fa1cbe13c78 Mon Sep 17 00:00:00 2001 From: ValDesign Date: Fri, 25 Apr 2025 11:33:24 +0200 Subject: [PATCH 10/17] fix: Remove redundant ensure() calls in Event methods to streamline event handling --- discordanalytics/client.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/discordanalytics/client.py b/discordanalytics/client.py index ff9274d..6830f2b 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -55,7 +55,6 @@ def increment(self, count: int = 1): print(f"[DISCORDANALYTICS] Incrementing event {self.event_key} by {count}") if not isinstance(count, int) or count < 0: raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) - self.ensure() self.analytics.stats["custom_events"][self.event_key] += count def decrement(self, count: int = 1): @@ -63,7 +62,6 @@ def decrement(self, count: int = 1): print(f"[DISCORDANALYTICS] Decrementing event {self.event_key} by {count}") if not isinstance(count, int) or count < 0: raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) - self.ensure() self.analytics.stats["custom_events"][self.event_key] -= count def set(self, value: int): @@ -71,7 +69,6 @@ def set(self, value: int): print(f"[DISCORDANALYTICS] Setting event {self.event_key} to {value}") if not isinstance(value, int) or value < 0: raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) - self.ensure() self.analytics.stats["custom_events"][self.event_key] = value def get(self): @@ -79,7 +76,6 @@ def get(self): print(f"[DISCORDANALYTICS] Getting event {self.event_key}") if not isinstance(self.event_key, str) or len(self.event_key) < 1 or len(self.event_key) > 50: raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) - self.ensure() return self.analytics.stats["custom_events"][self.event_key] class DiscordAnalytics(): From 1558d867c3d348dbf2334a2c062c90d8a20cbd7c Mon Sep 17 00:00:00 2001 From: ValDesign Date: Fri, 25 Apr 2025 18:09:38 +0200 Subject: [PATCH 11/17] refactor: Change event API call from POST to GET in Event class to align with API specifications --- discordanalytics/client.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/discordanalytics/client.py b/discordanalytics/client.py index 6830f2b..746c6d5 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -40,9 +40,8 @@ def ensure(self): raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) url = ApiEndpoints.EVENT_URL.replace(":id", str(self.analytics.client.user.id)).replace(":event_key", self.event_key) - body = { "event": self.event_key, "count": 0 } - self.analytics.api_call_with_retries("POST", url, self.analytics.headers, body) + self.analytics.api_call_with_retries("GET", url, self.analytics.headers) if self.event_key not in self.analytics.stats["custom_events"]: self.analytics.stats["custom_events"][self.event_key] = 0 From 8c969293e889ac2073a5cb11b127fe3948472803 Mon Sep 17 00:00:00 2001 From: ValDesign Date: Sun, 27 Apr 2025 16:46:50 +0200 Subject: [PATCH 12/17] chore: Update package versions in requirements.txt to latest stable releases --- requirements.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index b6f09b0..b1f0f9b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -discord.py==2.4.0 -aiohttp==3.10.10 -setuptools==75.2.0 -wheel==0.44.0 \ No newline at end of file +discord.py==2.5.2 +aiohttp==3.11.18 +setuptools==79.0.1 +wheel==0.46.1 \ No newline at end of file From 63e5ef2c456fe8a88d2b5253fb3d5d97c1867356 Mon Sep 17 00:00:00 2001 From: ValDesign22 Date: Wed, 30 Apr 2025 10:12:45 +0200 Subject: [PATCH 13/17] fix: Fixed negative value on custom_events --- discordanalytics/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discordanalytics/client.py b/discordanalytics/client.py index 746c6d5..e5d0eee 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -59,7 +59,7 @@ def increment(self, count: int = 1): def decrement(self, count: int = 1): if self.analytics.debug: print(f"[DISCORDANALYTICS] Decrementing event {self.event_key} by {count}") - if not isinstance(count, int) or count < 0: + if not isinstance(count, int) or count < 0 or self.get() - count < 0: raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) self.analytics.stats["custom_events"][self.event_key] -= count From 7efb75ef094a497d60d11f80de11ac88d28e2b39 Mon Sep 17 00:00:00 2001 From: nolhan Date: Fri, 19 Dec 2025 15:28:30 +0100 Subject: [PATCH 14/17] chore: upgraded dependencies --- requirements.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index b1f0f9b..8583ee3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -discord.py==2.5.2 -aiohttp==3.11.18 -setuptools==79.0.1 -wheel==0.46.1 \ No newline at end of file +discord.py==2.6.4 +aiohttp==3.13.2 +setuptools==80.9.0 +wheel==0.45.1 \ No newline at end of file From b3b809b2e023b9bfedd3eee6ebdd19d8851130f4 Mon Sep 17 00:00:00 2001 From: nolhan Date: Fri, 19 Dec 2025 15:28:35 +0100 Subject: [PATCH 15/17] chore: added .idea to .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index aee2a57..8f8b73c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ dist/ __pycache__/ tests/ .vscode/ -*.egg-info/ \ No newline at end of file +*.egg-info/ +.idea \ No newline at end of file From 11e31dcd802fa10a750e742affd30e699201ca62 Mon Sep 17 00:00:00 2001 From: nolhan Date: Fri, 19 Dec 2025 15:58:55 +0100 Subject: [PATCH 16/17] fix: custom events --- discordanalytics/client.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/discordanalytics/client.py b/discordanalytics/client.py index e5d0eee..e608a8f 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -30,38 +30,43 @@ class Event: def __init__(self, analytics, event_key: str): self.analytics = analytics self.event_key = event_key + self.last_action = "" self.ensure() - def ensure(self): - if self.analytics.debug: - print(f"[DISCORDANALYTICS] Ensuring event {self.event_key} exists") + async def ensure(self): if not isinstance(self.event_key, str) or len(self.event_key) < 1 or len(self.event_key) > 50: raise ValueError(ErrorCodes.INVALID_EVENTS_COUNT) - + + if self.event_key not in self.analytics.stats["custom_events"]: + if self.analytics.debug: + print(f"[DISCORDANALYTICS] Fetching value for event {self.event_key}") + url = ApiEndpoints.EVENT_URL.replace(":id", str(self.analytics.client.user.id)).replace(":event_key", self.event_key) - self.analytics.api_call_with_retries("GET", url, self.analytics.headers) + res = await self.analytics.api_call_with_retries("GET", url, self.analytics.headers) - if self.event_key not in self.analytics.stats["custom_events"]: - self.analytics.stats["custom_events"][self.event_key] = 0 + if res is not None and self.last_action != 'set': + self.analytics.stats["custom_events"][self.event_key] = (self.analytics.stats["custom_events"].get(self.event_key, 0) + (await res.json()).get("value", 0)) if self.analytics.debug: - print(f"[DISCORDANALYTICS] Event {self.event_key} ensured") + print(f"[DISCORDANALYTICS] Value fetched for event {self.event_key}") def increment(self, count: int = 1): if self.analytics.debug: print(f"[DISCORDANALYTICS] Incrementing event {self.event_key} by {count}") if not isinstance(count, int) or count < 0: raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) - self.analytics.stats["custom_events"][self.event_key] += count + self.analytics.stats["custom_events"][self.event_key] = self.analytics.stats["custom_events"].get(self.event_key, 0) + count + self.last_action = "increment" def decrement(self, count: int = 1): if self.analytics.debug: print(f"[DISCORDANALYTICS] Decrementing event {self.event_key} by {count}") if not isinstance(count, int) or count < 0 or self.get() - count < 0: raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) - self.analytics.stats["custom_events"][self.event_key] -= count + self.analytics.stats["custom_events"][self.event_key] = self.analytics.stats["custom_events"].get(self.event_key, 0) - count + self.last_action = "decrement" def set(self, value: int): if self.analytics.debug: @@ -69,6 +74,7 @@ def set(self, value: int): if not isinstance(value, int) or value < 0: raise ValueError(ErrorCodes.INVALID_VALUE_TYPE) self.analytics.stats["custom_events"][self.event_key] = value + self.last_action = "set" def get(self): if self.analytics.debug: @@ -180,9 +186,9 @@ async def init(self): if self.debug: if "--dev" in sys.argv: - print("[DISCORDANALYTICS] DevMode is enabled. Stats will be sent every 30s.") + print("[DISCORDANALYTICS] Fast mode is enabled. Stats will be sent every 30s.") else: - print("[DISCORDANALYTICS] DevMode is disabled. Stats will be sent every 5 minutes.") + print("[DISCORDANALYTICS] Fast mode is disabled. Stats will be sent every 5 minutes.") if not self.chunk_guilds: await self.load_members_for_all_guilds() @@ -252,10 +258,10 @@ async def send_stats(self): "other": 0, "private_message": 0 }, - "custom_events": {}, + "custom_events": self.stats["custom_events"], } - await asyncio.sleep(30 if "--dev" in sys.argv else 300) + await asyncio.sleep(30 if "--fast" in sys.argv else 300) def calculate_guild_members_repartition(self): thresholds = { From dd123b4b0311f3bbfb809cfa2b2bb50c0bf318e7 Mon Sep 17 00:00:00 2001 From: nolhan Date: Fri, 19 Dec 2025 17:01:03 +0100 Subject: [PATCH 17/17] refactor: changed --dev to --fast --- discordanalytics/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discordanalytics/client.py b/discordanalytics/client.py index e608a8f..63f4256 100644 --- a/discordanalytics/client.py +++ b/discordanalytics/client.py @@ -185,7 +185,7 @@ async def init(self): print("[DISCORDANALYTICS] Instance successfully initialized") if self.debug: - if "--dev" in sys.argv: + if "--fast" in sys.argv: print("[DISCORDANALYTICS] Fast mode is enabled. Stats will be sent every 30s.") else: print("[DISCORDANALYTICS] Fast mode is disabled. Stats will be sent every 5 minutes.")