Ryzenth 2.0.4__py3-none-any.whl → 2.0.6__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.
Ryzenth/__init__.py CHANGED
@@ -19,11 +19,12 @@
19
19
 
20
20
  from . import *
21
21
  from .__version__ import __version__
22
- from ._client import ApiKeyFrom, RyzenthApiClient, SmallConvertDot, UrHellFrom
22
+ from ._base_client import ApiKeyFrom, FromConvertDot, UrHellFrom
23
+ from ._client import RyzenthApiClient
23
24
 
24
25
  __all__ = [
25
26
  "ApiKeyFrom",
26
27
  "RyzenthApiClient",
27
28
  "UrHellFrom",
28
- "SmallConvertDot"
29
+ "FromConvertDot"
29
30
  ]
Ryzenth/__version__.py CHANGED
@@ -4,7 +4,7 @@ import platform
4
4
  def get_user_agent() -> str:
5
5
  return f"Ryzenth/Python-{platform.python_version()}"
6
6
 
7
- __version__ = "2.0.4"
7
+ __version__ = "2.0.6"
8
8
  __author__ = "TeamKillerX"
9
9
  __title__ = "Ryzenth"
10
10
  __description__ = "Ryzenth Python API Wrapper"
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # Copyright 2019-2025 (c) Randy W @xtdevs, @xtsea
4
+ #
5
+ # from : https://github.com/TeamKillerX
6
+ # Channel : @RendyProjects
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Affero General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Affero General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Affero General Public License
18
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
19
+
20
+ import base64
21
+ from os import environ
22
+
23
+ from box import Box
24
+
25
+ from ._asynchisded import RyzenthXAsync
26
+ from ._shared import UNKNOWN_TEST
27
+ from ._synchisded import RyzenthXSync
28
+ from .helper import Decorators
29
+
30
+
31
+ class ApiKeyFrom:
32
+ def __init__(self, api_key: str = None, is_ok=False):
33
+ if api_key == Ellipsis:
34
+ is_ok = True
35
+ api_key = None
36
+
37
+ if not api_key:
38
+ api_key = environ.get("RYZENTH_API_KEY")
39
+
40
+ if not api_key:
41
+ error404_bytes = UNKNOWN_TEST.encode("ascii")
42
+ string_bytes = base64.b64decode(error404_bytes)
43
+ api_key = string_bytes.decode("ascii") if is_ok else None
44
+
45
+
46
+ self.api_key = api_key
47
+ self.aio = RyzenthXAsync(api_key)
48
+ self._sync = RyzenthXSync(api_key)
49
+
50
+ def something(self):
51
+ pass
52
+
53
+ class UrHellFrom:
54
+ def __init__(self, name: str, only_author=False):
55
+ self.decorators = Decorators(ApiKeyFrom)
56
+ self.ai = self.decorators.send_ai(name=name, only_author=only_author)
57
+
58
+ def something(self):
59
+ pass
60
+
61
+ class FromConvertDot:
62
+ def __init__(self, obj):
63
+ self.obj = obj
64
+
65
+ def to_dot(self):
66
+ return Box(self.obj if self.obj is not None else {})
Ryzenth/_client.py CHANGED
@@ -17,84 +17,75 @@
17
17
  # You should have received a copy of the GNU Affero General Public License
18
18
  # along with this program. If not, see <https://www.gnu.org/licenses/>.
19
19
 
20
- import os
21
- import platform
20
+ import asyncio
21
+ import json
22
+ import logging
23
+ import random
24
+ import time
22
25
  import typing as t
26
+ from os import getenv
23
27
 
24
28
  import aiohttp
25
- from box import Box
29
+ import httpx
26
30
 
27
31
  from .__version__ import get_user_agent
28
- from ._asynchisded import RyzenthXAsync
29
32
  from ._errors import ForbiddenError, InternalError, ToolNotFoundError, WhatFuckError
30
- from ._synchisded import RyzenthXSync
31
- from .helper import Decorators
33
+ from ._shared import TOOL_DOMAIN_MAP
34
+ from .helper import AutoRetry
35
+ from .tl import LoggerService
32
36
 
33
37
 
34
- class ApiKeyFrom:
35
- def __init__(self, api_key: str = None, is_ok=False):
36
- if api_key is Ellipsis:
37
- is_ok = True
38
- api_key = None
39
-
40
- if not api_key:
41
- api_key = os.environ.get("RYZENTH_API_KEY")
42
-
43
- if not api_key:
44
- api_key = "akeno_UKQEQMt991kh2Ehh7JqJYKapx8CCyeC" if is_ok else None
45
-
46
- self.api_key = api_key
47
- self.aio = RyzenthXAsync(api_key)
48
- self._sync = RyzenthXSync(api_key)
49
-
50
- def something(self):
51
- pass
52
-
53
- class UrHellFrom:
54
- def __init__(self, name: str, only_author=False):
55
- self.decorators = Decorators(ApiKeyFrom)
56
- self.ai = self.decorators.send_ai(name=name, only_author=only_author)
57
-
58
- def something(self):
59
- pass
60
-
61
- class SmallConvertDot:
62
- def __init__(self, obj):
63
- self.obj = obj
64
-
65
- def to_dot(self):
66
- return Box(self.obj if self.obj is not None else {})
67
-
68
- TOOL_DOMAIN_MAP = {
69
- "itzpire": "https://itzpire.com",
70
- "ryzenth": "https://randydev-ryu-js.hf.space",
71
- }
72
-
73
38
  class RyzenthApiClient:
74
39
  def __init__(
75
40
  self,
76
41
  *,
77
- api_key: str,
78
42
  tools_name: list[str],
79
- use_default_headers: bool = False
43
+ api_key: dict[str, list[dict]],
44
+ rate_limit: int = 5,
45
+ use_default_headers: bool = False,
46
+ use_httpx: bool = False,
47
+ settings: dict = None,
48
+ logger: t.Optional[LoggerService] = None
80
49
  ) -> None:
81
- if not api_key:
82
- raise WhatFuckError("API Key cannot be empty.")
50
+ if not isinstance(api_key, dict) or not api_key:
51
+ raise WhatFuckError("API Key must be a non-empty dict of tool_name → list of headers")
83
52
  if not tools_name:
84
53
  raise WhatFuckError("A non-empty list of tool names must be provided for 'tools_name'.")
85
54
 
86
- self._api_key: str = api_key
55
+ self._api_keys = api_key
87
56
  self._use_default_headers: bool = use_default_headers
88
- self._session: aiohttp.ClientSession = aiohttp.ClientSession(
89
- headers={
90
- "User-Agent": get_user_agent(),
91
- **({"x-api-key": self._api_key} if self._use_default_headers else {})
92
- }
93
- )
57
+ self._rate_limit = rate_limit
58
+ self._request_counter = 0
59
+ self._last_reset = time.monotonic()
60
+ self._use_httpx = use_httpx
61
+ self._settings = settings or {}
62
+ self._logger = logger
63
+ self._init_logging()
64
+
94
65
  self._tools: dict[str, str] = {
95
66
  name: TOOL_DOMAIN_MAP.get(name)
96
67
  for name in tools_name
97
68
  }
69
+ self._session = (
70
+ httpx.AsyncClient()
71
+ if use_httpx else
72
+ aiohttp.ClientSession()
73
+ )
74
+
75
+ def _init_logging(self):
76
+ log_level = "WARNING"
77
+ disable_httpx_log = False
78
+
79
+ for entry in self._settings.get("logging", []):
80
+ if "level" in entry:
81
+ log_level = entry["level"].upper()
82
+ if "httpx_log" in entry:
83
+ disable_httpx_log = not entry["httpx_log"]
84
+
85
+ logging.basicConfig(level=getattr(logging, log_level, logging.WARNING))
86
+ if disable_httpx_log:
87
+ logging.getLogger("httpx").setLevel(logging.CRITICAL)
88
+ logging.getLogger("httpcore").setLevel(logging.CRITICAL)
98
89
 
99
90
  def get_base_url(self, tool: str) -> str:
100
91
  check_ok = self._tools.get(tool, None)
@@ -102,59 +93,122 @@ class RyzenthApiClient:
102
93
  raise ToolNotFoundError(f"Base URL for tool '{tool}' not found.")
103
94
  return check_ok
104
95
 
96
+ def _get_headers_for_tool(self, tool: str) -> dict:
97
+ base = {"User-Agent": get_user_agent()}
98
+ if self._use_default_headers and tool in self._api_keys:
99
+ base.update(random.choice(self._api_keys[tool]))
100
+ return base
101
+
102
+ async def _throttle(self):
103
+ now = time.monotonic()
104
+ if now - self._last_reset >= 1:
105
+ self._last_reset = now
106
+ self._request_counter = 0
107
+
108
+ if self._request_counter >= self._rate_limit:
109
+ await asyncio.sleep(1 - (now - self._last_reset))
110
+ self._last_reset = time.monotonic()
111
+ self._request_counter = 0
112
+
113
+ self._request_counter += 1
114
+
105
115
  @classmethod
106
116
  def from_env(cls) -> "RyzenthApiClient":
107
- api_key: t.Optional[str] = os.environ.get("RYZENTH_API_KEY")
108
- if not api_key:
109
- raise WhatFuckError("API Key cannot be empty.")
110
- return cls(api_key=api_key)
111
-
112
- async def _status_resp_error(self, resp):
113
- if resp.status == 403:
114
- raise ForbiddenError("Access Forbidden: You may be blocked or banned.")
115
- if resp.status == 500:
116
- raise InternalError("Error requests status code 5000")
117
+ tools_raw = getenv("RYZENTH_TOOLS")
118
+ api_key_raw = getenv("RYZENTH_API_KEY_JSON")
119
+ rate_limit_raw = getenv("RYZENTH_RATE_LIMIT", "5")
120
+ use_headers = getenv("RYZENTH_USE_HEADERS", "true")
121
+ use_httpx = getenv("RYZENTH_USE_HTTPX", "false")
122
+
123
+ if not tools_raw or not api_key_raw:
124
+ raise WhatFuckError("Environment variables RYZENTH_TOOLS and RYZENTH_API_KEY_JSON are required.")
125
+
126
+ tools = [t.strip() for t in tools_raw.split(",")]
127
+ api_keys = json.loads(api_key_raw)
128
+ rate_limit = int(rate_limit_raw)
129
+ use_default_headers = use_headers.lower() == "true"
130
+ httpx_flag = use_httpx.lower() == "true"
131
+
132
+ return cls(
133
+ tools_name=tools,
134
+ api_key=api_keys,
135
+ rate_limit=rate_limit,
136
+ use_default_headers=use_default_headers,
137
+ use_httpx=httpx_flag
138
+ )
117
139
 
140
+ async def _status_resp_error(self, resp, status_httpx=False):
141
+ if status_httpx:
142
+ if resp.status_code == 403:
143
+ raise ForbiddenError("Access Forbidden: You may be blocked or banned.")
144
+ elif resp.status_code == 401:
145
+ raise ForbiddenError("Access Forbidden: Required API key or invalid params.")
146
+ elif resp.status_code == 500:
147
+ raise InternalError("Error requests status code 500")
148
+ else:
149
+ if resp.status == 403:
150
+ raise ForbiddenError("Access Forbidden: You may be blocked or banned.")
151
+ elif resp.status == 401:
152
+ raise ForbiddenError("Access Forbidden: Required API key or invalid params.")
153
+ elif resp.status == 500:
154
+ raise InternalError("Error requests status code 500")
155
+
156
+ @AutoRetry(max_retries=3, delay=1.5)
118
157
  async def get(
119
158
  self,
120
159
  tool: str,
121
160
  path: str,
122
- params: t.Optional[dict] = None
123
- ) -> dict:
161
+ params: t.Optional[dict] = None,
162
+ use_image_content: bool = False
163
+ ) -> t.Union[dict, bytes]:
164
+ await self._throttle()
124
165
  base_url = self.get_base_url(tool)
125
166
  url = f"{base_url}{path}"
126
- try:
127
- async with self._session.get(url, params=params) as resp:
128
- await self._status_resp_error(resp)
167
+ headers = self._get_headers_for_tool(tool)
168
+
169
+ if self._use_httpx:
170
+ resp = await self._session.get(url, params=params, headers=headers)
171
+ await self._status_resp_error(resp, status_httpx=True)
172
+ resp.raise_for_status()
173
+ data = resp.content if use_image_content else resp.json()
174
+ else:
175
+ async with self._session.get(url, params=params, headers=headers) as resp:
176
+ await self._status_resp_error(resp, status_httpx=False)
129
177
  resp.raise_for_status()
130
- return await resp.json()
131
- except ForbiddenError as e:
132
- return {"error": str(e)}
133
- except aiohttp.ClientResponseError as e:
134
- return {"error": f"HTTP Error: {e.status} {e.message}"}
135
- except Exception as e:
136
- return {"error": str(e)}
178
+ data = await resp.read() if use_image_content else await resp.json()
179
+
180
+ if self._logger:
181
+ await self._logger.log(f"[GET {tool}] ✅ Success: {url}")
182
+ return data
137
183
 
184
+ @AutoRetry(max_retries=3, delay=1.5)
138
185
  async def post(
139
186
  self,
140
187
  tool: str,
141
188
  path: str,
142
189
  data: t.Optional[dict] = None,
143
- json: t.Optional[dict] = None
144
- ) -> dict:
190
+ json: t.Optional[dict] = None,
191
+ use_image_content: bool = False
192
+ ) -> t.Union[dict, bytes]:
193
+ await self._throttle()
145
194
  base_url = self.get_base_url(tool)
146
195
  url = f"{base_url}{path}"
147
- try:
148
- async with self._session.post(url, data=data, json=json) as resp:
149
- await self._status_resp_error(resp)
196
+ headers = self._get_headers_for_tool(tool)
197
+
198
+ if self._use_httpx:
199
+ resp = await self._session.post(url, data=data, json=json, headers=headers)
200
+ await self._status_resp_error(resp, status_httpx=True)
201
+ resp.raise_for_status()
202
+ data = resp.content if use_image_content else resp.json()
203
+ else:
204
+ async with self._session.post(url, data=data, json=json, headers=headers) as resp:
205
+ await self._status_resp_error(resp, status_httpx=False)
150
206
  resp.raise_for_status()
151
- return await resp.json()
152
- except ForbiddenError as e:
153
- return {"error": str(e)}
154
- except aiohttp.ClientResponseError as e:
155
- return {"error": f"HTTP Error: {e.status} {e.message}"}
156
- except Exception as e:
157
- return {"error": str(e)}
207
+ data = await resp.read() if use_image_content else await resp.json()
208
+
209
+ if self._logger:
210
+ await self._logger.log(f"[POST {tool}] ✅ Success: {url}")
211
+ return data
158
212
 
159
213
  async def close(self):
160
- await self._session.close()
214
+ return await self._session.aclose() if self._use_httpx else await self._session.close()
Ryzenth/_shared.py CHANGED
@@ -1,3 +1,13 @@
1
+ UNKNOWN_TEST = "YWtlbm9fVUtRRVFNdDk5MWtoMkVoaDdKcUpZS2FweDhDQ3llQw=="
2
+
3
+ TOOL_DOMAIN_MAP = {
4
+ "itzpire": "https://itzpire.com",
5
+ "ryzenth": "https://randydev-ryu-js.hf.space",
6
+ "onrender": "https://x-api-js.onrender.com",
7
+ "openai": "https://api.openai.com/v1",
8
+ "gemini": "https://generativelanguage.googleapis.com/v1"
9
+ }
10
+
1
11
  # this API is different
2
12
 
3
13
  BASE_DICT_RENDER = {
@@ -17,7 +17,7 @@
17
17
  # You should have received a copy of the GNU Affero General Public License
18
18
  # along with this program. If not, see <https://www.gnu.org/licenses/>.
19
19
 
20
- from ._decorators import Decorators
20
+ from ._decorators import AutoRetry, Decorators
21
21
  from ._federation import FbanAsync, FbanSync
22
22
  from ._fonts import FontsAsync, FontsSync
23
23
  from ._images import ImagesAsync, ImagesSync
@@ -41,5 +41,6 @@ __all__ = [
41
41
  "FontsSync",
42
42
  "HumanizeAsync",
43
43
  "HumanizeSync",
44
- "Decorators"
44
+ "Decorators",
45
+ "AutoRetry"
45
46
  ]
@@ -17,11 +17,33 @@
17
17
  # You should have received a copy of the GNU Affero General Public License
18
18
  # along with this program. If not, see <https://www.gnu.org/licenses/>.
19
19
 
20
+ import asyncio
20
21
  from functools import wraps
21
22
 
23
+ import aiohttp
24
+ import httpx
25
+
22
26
  from ..types import QueryParameter
23
27
 
24
28
 
29
+ def AutoRetry(max_retries: int = 3, delay: float = 1.5):
30
+ def decorator(func):
31
+ @wraps(func)
32
+ async def wrapper(*args, **kwargs):
33
+ for attempt in range(max_retries):
34
+ try:
35
+ return await func(*args, **kwargs)
36
+ except (
37
+ httpx.HTTPError,
38
+ aiohttp.ClientError,
39
+ asyncio.TimeoutError
40
+ ) as e:
41
+ if attempt == max_retries - 1:
42
+ raise e
43
+ await asyncio.sleep(delay)
44
+ return wrapper
45
+ return decorator
46
+
25
47
  class Decorators:
26
48
  def __init__(self, class_func):
27
49
  self._clients_ai = class_func(..., is_ok=True)
Ryzenth/helper/_images.py CHANGED
@@ -17,6 +17,11 @@
17
17
  # You should have received a copy of the GNU Affero General Public License
18
18
  # along with this program. If not, see <https://www.gnu.org/licenses/>.
19
19
 
20
+ import asyncio
21
+ import logging
22
+ import os
23
+ import uuid
24
+
20
25
  from .._errors import WhatFuckError
21
26
  from ..types import QueryParameter
22
27
 
@@ -43,7 +48,7 @@ class ImagesAsync:
43
48
 
44
49
  async def to_save(self, params: QueryParameter, file_path="fluxai.jpg"):
45
50
  content = await self.generate(params)
46
- return ResponseFileImage(content).to_save(file_path)
51
+ return await ResponseFileImage(content).to_save(file_path)
47
52
 
48
53
  class ImagesSync:
49
54
  def __init__(self, parent):
@@ -66,14 +71,32 @@ class ImagesSync:
66
71
 
67
72
  def to_save(self, params: QueryParameter, file_path="fluxai.jpg"):
68
73
  content = self.generate(params)
69
- return ResponseFileImage(content).to_save(file_path)
74
+ return ResponseFileImage(content).sync_to_save(file_path)
70
75
 
71
76
 
72
77
  class ResponseFileImage:
73
78
  def __init__(self, response_content: bytes):
74
79
  self.response_content = response_content
75
80
 
76
- def to_save(self, file_path="fluxai.jpg"):
81
+ def sync_to_save(self, file_path="fluxai.jpg"):
82
+ with open(file_path, "wb") as f:
83
+ f.write(self.response_content)
84
+ logging.info(f"File saved: {file_path}")
85
+ return file_path
86
+
87
+ async def to_save(self, file_path: str = None, auto_delete: bool = False, delay: int = 5):
88
+ if file_path is None:
89
+ file_path = f"{uuid.uuid4().hex}.jpg"
90
+
77
91
  with open(file_path, "wb") as f:
78
92
  f.write(self.response_content)
93
+ logging.info(f"File saved: {file_path}")
94
+
95
+ if auto_delete:
96
+ await asyncio.sleep(delay)
97
+ try:
98
+ os.remove(file_path)
99
+ return True
100
+ except FileNotFoundError:
101
+ return False
79
102
  return file_path
Ryzenth/tl/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ from .logger_service import LoggerService
2
+
3
+ __all__ = ["LoggerService"]
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # Copyright 2019-2025 (c) Randy W @xtdevs, @xtsea
4
+ #
5
+ # from : https://github.com/TeamKillerX
6
+ # Channel : @RendyProjects
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Affero General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Affero General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Affero General Public License
18
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
19
+
20
+ import logging
21
+ from datetime import datetime as dt
22
+
23
+ import httpx
24
+
25
+ from .._errors import ForbiddenError, InternalError
26
+
27
+
28
+ class LoggerService:
29
+ def __init__(self, config: dict):
30
+ self.config = config
31
+
32
+ async def log(self, message: str):
33
+ timestamp = dt.now().strftime("%Y-%m-%d %H:%M:%S")
34
+ full_message = f"[{timestamp}] {message}"
35
+
36
+ if self.config.get("telegram", {}).get("enabled"):
37
+ try:
38
+ await self._send_telegram(full_message)
39
+ except Exception as e:
40
+ logging.info(f"[Logger] Telegram log failed: {e}")
41
+
42
+ if self.config.get("database", {}).get("enabled"):
43
+ try:
44
+ await self.config["database"]["save_func"](full_message)
45
+ except Exception as e:
46
+ logging.info(f"[Logger] DB log failed: {e}")
47
+
48
+ async def _send_telegram(self, text: str):
49
+ token = self.config["telegram"]["token"]
50
+ chat_id = self.config["telegram"]["chat_id"]
51
+ url = f"https://api.telegram.org/bot{token}/sendMessage"
52
+
53
+ try:
54
+ async with httpx.AsyncClient() as client:
55
+ resp = await client.post(url, data={"chat_id": chat_id, "text": text})
56
+ if resp.status_code == 200:
57
+ logging.info("[Logger] Telegram log success")
58
+ elif resp.status_code == 403:
59
+ raise ForbiddenError("Access Forbidden: You may be blocked or banned.")
60
+ elif resp.status_code == 401:
61
+ raise ForbiddenError("Access Forbidden: Required bot token or invalid params.")
62
+ elif resp.status_code == 500:
63
+ raise InternalError("Error requests status code 500")
64
+ except Exception as e:
65
+ logging.info(f"[Logger] httpx failed: {e}")
66
+ raise e
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Ryzenth
3
- Version: 2.0.4
3
+ Version: 2.0.6
4
4
  Summary: Ryzenth Python Wrapper For Perfomance
5
5
  Author: TeamKillerX
6
6
  License: MIT
@@ -63,7 +63,17 @@ Dynamic: summary
63
63
  <a href="https://github.com/TeamKillerX/Ryzenth/workflows/"><img src="https://github.com/TeamKillerX/Ryzenth/actions/workflows/sync-tests.yml/badge.svg" alt="API Tests"/></a>
64
64
  </div>
65
65
 
66
- **Ryzenth** is a powerful and flexible Python SDK for interacting with the new **Ryzenth API V1** a successor to the Ryzenth API V1 supporting both synchronous and asynchronous workflows out of the box.
66
+ ---
67
+
68
+ ![Image](https://github.com/user-attachments/assets/ebb42582-4d5d-4f6a-8e8b-78d737810510)
69
+
70
+ ---
71
+
72
+ **Ryzenth** is a flexible Multi-API SDK with built-in support for API key management and database integration.
73
+
74
+ It supports both **synchronous and asynchronous** workflows out of the box, making it ideal for modern use cases such as AI APIs, Telegram bots, REST services, and automation tools.
75
+
76
+ With native integration for `httpx`, `aiohttp`, advanced logging (including optional Telegram alerts), and support for database storage like MongoDB, Ryzenth is designed for developers who need a lightweight, scalable, and customizable API client.
67
77
 
68
78
  > Note: Ryzenth API V1 (**javascript**) is still alive and supported, but Ryzenth is the next generation.
69
79
 
@@ -73,6 +83,7 @@ Dynamic: summary
73
83
  - Built-in API Key management
74
84
  - Support for modern AI endpoints (image generation, search, text, and more)
75
85
  - Designed for speed with `httpx`
86
+ - Etc
76
87
 
77
88
  ## Installation
78
89
 
@@ -125,6 +136,11 @@ export RYZENTH_API_KEY=your-api-key
125
136
  ## Web scrapers
126
137
  * [`itzpire`](https://itzpire.com) - Team Developer
127
138
 
139
+ ## Tool Developer
140
+ ~ Artificial Intelligence
141
+ - [`OpenAI`](https://platform.openai.com/docs) - OpenAI Docs
142
+ - [`Gemini AI`](https://ai.google.dev) - Gemini AI Docs
143
+
128
144
  ## Credits
129
145
 
130
146
  * Built with love by [xtdevs](https://t.me/xtdevs)
@@ -1,15 +1,16 @@
1
- Ryzenth/__init__.py,sha256=ON7RbtPrgK-Fw414Vro5J2OAGocv0522rRIojMNX2Q0,1043
2
- Ryzenth/__version__.py,sha256=Q04fL4sPvcvdeXFCEVrdKyedK87dQO--pzGS5kN23dI,223
1
+ Ryzenth/__init__.py,sha256=tUSSKb2xEQGDZFg1g-9PsSuWAPvuUBG9cAXyIHyBmMg,1066
2
+ Ryzenth/__version__.py,sha256=_TA3rYUCdqJrMGE_VClpMOuFcVFr0KLvvOY2ER_Ic98,223
3
3
  Ryzenth/_asynchisded.py,sha256=5ZjrXZzMSZw3T6kQ3eg-owgH1Y2dmGWJy9AOQqcoFUQ,5051
4
- Ryzenth/_client.py,sha256=LinE_H_5LpBT2k_ulgH693IV0lkh884wNxOotmHIA_g,5226
4
+ Ryzenth/_base_client.py,sha256=9oVkoYduSILsk38T2_jvT0frsl2B7ISD2YsR4BJ3Rfk,2032
5
+ Ryzenth/_client.py,sha256=hbt3U5szOrBuJkszY6jTmAoxHs89_mEfRZHvFXOnVWk,8028
5
6
  Ryzenth/_errors.py,sha256=bOqi0_DElcmRrBqyDim6K248Ys-JQRSOvd32sJGW3aw,1812
6
- Ryzenth/_shared.py,sha256=zlERjX4XmYsDbkei8BRQ_-G1ozPlsn0SSalsAN6roT0,1682
7
+ Ryzenth/_shared.py,sha256=GfKOf7SPmtS5xJS9Sd5t846atH_1Ox9oCjhpqO4PXMA,2018
7
8
  Ryzenth/_synchisded.py,sha256=Ns0F4iA4kWUg2j5u0Tyqj2E1mXIMs29IoQZCYW5G1Gw,4922
8
- Ryzenth/helper/__init__.py,sha256=BkP6fQ3IJnOqyXn07jD7anumVPlm8lVPNkFnK9b6XpE,1447
9
- Ryzenth/helper/_decorators.py,sha256=rEdJRoQrJfqd4LqNOiFfPwEQwMU4uVuEsoqRuQfw99I,2125
9
+ Ryzenth/helper/__init__.py,sha256=ZditYtDnZOtTJ_odPgWH0Nrj-qQJ868zjy41_DzK_ns,1473
10
+ Ryzenth/helper/_decorators.py,sha256=8uKdcseA7Cbq5sy2twgujZhbwqjaLwX13BT70diNRFs,2782
10
11
  Ryzenth/helper/_federation.py,sha256=pfqqGjg179f-olvW1Z7aX1nQf0GQJdSK4NDMaMDxmbA,14552
11
12
  Ryzenth/helper/_fonts.py,sha256=Yy5qWdumGf0Y7tcvEXGLSn87mKlr-x_gmO241a465j8,3035
12
- Ryzenth/helper/_images.py,sha256=sDIqo964oDeLvhf1XtJ1khNgSuYXSzmQY9w_jJS89fI,3073
13
+ Ryzenth/helper/_images.py,sha256=NltJZidfhFCvTf3sF5WBIuWlym1cKpr2WDrk0sJbh20,3739
13
14
  Ryzenth/helper/_moderator.py,sha256=fAi0Xxk6CSShXl94H0FT8oDn6FttVq3ysBiROjSesCw,5501
14
15
  Ryzenth/helper/_openai.py,sha256=YkoW40X7Hgo_gQCWqrxHAe_uTx1fR5AyFAZh2MMiNJo,2582
15
16
  Ryzenth/helper/_ryzenth.py,sha256=VPjo09JOjtzS74AxUwcXsaWFGY923_scqZ2ujzBEa3A,2874
@@ -20,9 +21,11 @@ Ryzenth/tests/test_deepseek.py,sha256=_KbYr-haKBt5Xc-YULBL9Ic5OM02SX17hvQWWjYpNA
20
21
  Ryzenth/tests/test_moderator.py,sha256=wc9A_0gx3LobMD7CDS-h2eTNPNYxeJk_rqtd2QTt428,291
21
22
  Ryzenth/tests/test_send.py,sha256=yPQV3XRsPKBo4eSsz5kc2R6BEuru0zmMexYshX0Ac3s,573
22
23
  Ryzenth/tests/test_send_downloader.py,sha256=23Lkq6bkh5SVDZ2hRH1Q3nlqpl-dqqGMSznDkmgDbhc,1318
24
+ Ryzenth/tl/__init__.py,sha256=SDoC1aFqHf682PasjkCIWzBdqvOJQ-Wn7ybDOxhHmMo,71
25
+ Ryzenth/tl/logger_service.py,sha256=23Mdi9obe-aF9SWBwgbRlk3hgQJdK9JYfg1iOsaUAW0,2651
23
26
  Ryzenth/types/__init__.py,sha256=2q3Oy7wCtgHa1cVY1JVN6cJht7uEAva3yFijSiJxYdI,1392
24
- ryzenth-2.0.4.dist-info/licenses/LICENSE,sha256=C73aiGSgoCAVNzvAHs-TROaf5vV8yCj9nqpGrmfNHHo,1068
25
- ryzenth-2.0.4.dist-info/METADATA,sha256=pujr79wsNKFr6W8UJqVJODRvlN0HyuY-xh9PllIE3Jg,4642
26
- ryzenth-2.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- ryzenth-2.0.4.dist-info/top_level.txt,sha256=0vIhjOjoQuCxLeZO0of8VCx2jsri-bLHV28nh8wWDnc,8
28
- ryzenth-2.0.4.dist-info/RECORD,,
27
+ ryzenth-2.0.6.dist-info/licenses/LICENSE,sha256=C73aiGSgoCAVNzvAHs-TROaf5vV8yCj9nqpGrmfNHHo,1068
28
+ ryzenth-2.0.6.dist-info/METADATA,sha256=rJu9rxGBq-7Ds5maFxs5rYugNOQGin7BVx7vZiiRkUI,5250
29
+ ryzenth-2.0.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ ryzenth-2.0.6.dist-info/top_level.txt,sha256=0vIhjOjoQuCxLeZO0of8VCx2jsri-bLHV28nh8wWDnc,8
31
+ ryzenth-2.0.6.dist-info/RECORD,,