epok-toolkit 1.5.2__py3-none-any.whl → 1.7.1__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.

Potentially problematic release.


This version of epok-toolkit might be problematic. Click here for more details.

@@ -0,0 +1 @@
1
+ from .cacher import cache_full, cache_get, CachedViewSet, TimeToLive
@@ -0,0 +1,130 @@
1
+ # utils/cacher.py
2
+ from rest_framework import viewsets
3
+ from rest_framework_extensions.cache.mixins import CacheResponseMixin
4
+ from rest_framework_extensions.cache.decorators import cache_response
5
+ from django.views.decorators.cache import cache_page
6
+ from colorstreak import log
7
+ from functools import wraps
8
+ from django.utils.decorators import method_decorator
9
+ # --- clave por usuario + params + página ----------------------
10
+ from rest_framework_extensions.key_constructor.constructors import DefaultKeyConstructor
11
+ from rest_framework_extensions.key_constructor.bits import UserKeyBit, QueryParamsKeyBit, PaginationKeyBit
12
+
13
+
14
+ """
15
+ cacher.py — utilidades de caché centralizadas
16
+ ============================================
17
+
18
+ Este módulo agrupa, en un solo lugar, las dos capas de caché que aplicamos en
19
+ nuestra API DRF:
20
+
21
+ 📦 cache_get → capa de *serialización* (drf extensions @cache_response)
22
+ 🚀 cache_full → capa de *vista completa* (Django @cache_page)
23
+
24
+ Para no repetir la misma lógica en cada vista, exportamos:
25
+
26
+ • `CachedViewSet` -> incluye CacheResponseMixin listo para usar.
27
+ • Decoradores -> `cache_get`, `cache_full`.
28
+ • `TimeToLive` -> constantes de segundos ligadas a colores/emoji.
29
+
30
+ Leyenda TTL (la misma del CSV)
31
+ ------------------------------
32
+ 🔴 1 min (60 s) | cambios frecuentes
33
+ 🟡 2 --> 5 min (~300 s) | lecturas comunes
34
+ 🟢 10 --> 30 min (~1800 s) | datos casi estáticos
35
+
36
+ Emojis ↔ capas
37
+ --------------
38
+ 🗄️ consultas ORM (cacheops / get_or_set)
39
+ 📦 serialización (cache_response)
40
+ 🚀 vista completa (cache_page)
41
+ 🌐 CDN / navegador (Cache‑Control)
42
+
43
+ """
44
+
45
+
46
+
47
+ class TimeToLive:
48
+ """
49
+ Constantes de TTL ligadas a la paleta del CSV:
50
+
51
+ 🔴 RED | 1 min (60 s)
52
+ 🟡 YELLOW | 5 min (300 s)
53
+ 🟢 GREEN | 30 min (1800 s)
54
+ """
55
+ RED = 60 # 1 minuto
56
+ YELLOW = 60 * 5 # 5 minutos
57
+ GREEN = 60 * 30 # 30 minutos
58
+
59
+
60
+ class UserQueryKey(DefaultKeyConstructor):
61
+ user = UserKeyBit()
62
+ query_params = QueryParamsKeyBit()
63
+ pagination = PaginationKeyBit()
64
+
65
+ _DEFAULT_KEY = UserQueryKey().get_key
66
+ _DEFAULT_TTL = TimeToLive.RED
67
+
68
+
69
+
70
+ class CachedViewSet(CacheResponseMixin, viewsets.ModelViewSet):
71
+ """
72
+ Herédame si vas a usar cache_get o cache_full.
73
+ Nada más que eso; no impone TTL.
74
+ """
75
+ pass
76
+
77
+
78
+
79
+
80
+ def cache_get(ttl=_DEFAULT_TTL, key_func=_DEFAULT_KEY):
81
+ """
82
+ Capa: Serialización 📦
83
+ Devuelve un decorador que cachea la serialización DRF *una sola vez*,
84
+ evitando envolver la vista nuevamente en cada petición.
85
+
86
+ Ejemplo:
87
+ @cache_get(ttl=TimeToLive.RED)
88
+ def view(...): ...
89
+ """
90
+ def decorator(view_fn):
91
+ # Pre‑construimos la función cacheada UNA vez
92
+ cached_fn = cache_response(ttl, key_func=key_func)(view_fn)
93
+
94
+ @wraps(view_fn)
95
+ def wrapped(*args, **kwargs):
96
+ log.debug(
97
+ f"[📦 cache_get] {view_fn.__qualname__} | ttl={ttl}s"
98
+ )
99
+ # Llamamos directamente a la versión ya decorada,
100
+ # para no crear cadenas de closures ni excepciones duplicadas.
101
+ return cached_fn(*args, **kwargs)
102
+
103
+ return wrapped
104
+
105
+ return decorator
106
+
107
+
108
+ def cache_full(ttl=_DEFAULT_TTL, key_prefix=""):
109
+ """
110
+ Capa: Respuesta HTTP 🚀
111
+ Devuelve un decorador que cachea la vista completa vía cache_page
112
+ *al momento de ejecutar la vista*.
113
+
114
+ Ejemplo:
115
+ @cache_full(ttl=TimeToLive.GREEN, key_prefix="ticket_pdf")
116
+ def view(...): ...
117
+ """
118
+ def decorator(view_fn):
119
+ # Adapt the function-level cache_page decorator to a bound‑method
120
+ page_deco = cache_page(ttl, key_prefix=key_prefix)
121
+ decorated_fn = method_decorator(page_deco)(view_fn)
122
+
123
+ @wraps(view_fn)
124
+ def wrapped(self, request, *args, **kwargs):
125
+ log.debug(f"[🚀 cache_full] {view_fn.__qualname__} | ttl={ttl}s | prefix={key_prefix}")
126
+ return decorated_fn(self, request, *args, **kwargs)
127
+
128
+ return wrapped
129
+
130
+ return decorator
@@ -1 +1 @@
1
- from .whatsapp_instanced import send_text
1
+ from .whatsapp_instanced import send_text, send_media
@@ -1,3 +1,4 @@
1
+ from colorstreak import log
1
2
  from .whatsapp import WhatsappClient
2
3
  from django.conf import settings
3
4
  from celery import shared_task
@@ -9,16 +10,27 @@ SERVER_URL = settings.SERVER_URL
9
10
 
10
11
  @shared_task
11
12
  def send_whatsapp_message_async(number: str, message: str):
12
- try:
13
- from colorstreak import log
14
- log.debug(f"Enviando mensaje a {number}: '{message}'")
13
+ log.debug(f"Enviando mensaje a {number}: '{message}'")
14
+ client = WhatsappClient(api_key=API_KEY, server_url=SERVER_URL, instance_name=INSTANCE)
15
+ return client.send_text(number, message)
16
+
17
+
18
+ @shared_task
19
+ def send_whatsapp_media_async(number: str, media_b64: str, filename: str, caption: str, mediatype: str = "document", mimetype: str = "application/pdf"):
20
+ log.debug(f"Enviando media a {number}: '{filename}'")
21
+ client = WhatsappClient(api_key=API_KEY, server_url=SERVER_URL, instance_name=INSTANCE)
22
+ return client.send_media(number, media_b64, filename, caption, mediatype, mimetype)
23
+
24
+
15
25
 
16
- client = WhatsappClient(api_key=API_KEY, server_url=SERVER_URL, instance_name=INSTANCE)
17
- return client.send_text(number, message)
18
- except Exception as e:
19
- log.error(f"Error al enviar mensaje a {number}: {e}")
20
26
 
21
27
  def send_text(number: str, message: str):
22
28
  from colorstreak import log
23
29
  log.debug(f"Programando tarea para {number}")
24
- send_whatsapp_message_async.delay(number, message)
30
+ send_whatsapp_message_async.delay(number, message)
31
+
32
+
33
+ def send_media(number: str, media_b64: str, filename: str, caption: str, mediatype: str = "document", mimetype: str = "application/pdf"):
34
+ from colorstreak import log
35
+ log.debug(f"Programando tarea para enviar media a {number}")
36
+ send_whatsapp_media_async.delay(number, media_b64, filename, caption, mediatype, mimetype)
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: epok-toolkit
3
- Version: 1.5.2
4
- Summary: A toolkit for building Django applications with Celery support
3
+ Version: 1.7.1
4
+ Summary: Una herramienta para la gestión de tareas y procesos en Django con Celery.
5
5
  Author-email: Fernando Leon Franco <fernanlee2131@gmail.com>
6
6
  License: MIT
7
7
  Classifier: Programming Language :: Python :: 3
@@ -14,6 +14,7 @@ License-File: LICENSE
14
14
  Requires-Dist: Django>=5.0.2
15
15
  Requires-Dist: celery[redis]>=5.5.3
16
16
  Requires-Dist: django-celery-beat>=2.6.0
17
+ Requires-Dist: colorstreak>=0.1.0
17
18
  Dynamic: license-file
18
19
 
19
20
  # EPOK Toolkit
@@ -1,13 +1,15 @@
1
1
  epok_toolkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  epok_toolkit/apps.py,sha256=O3q3CcucJOHjlYIS0VgbKsbtim2hpng_FxpKEG_MlWs,486
3
3
  epok_toolkit/default_settings.py,sha256=hxsRmsAcjk4ar-pRz_X6AI17mJ3192Ljbx-xBuP5rdY,452
4
+ epok_toolkit/cache/__init__.py,sha256=q1-pMbXk-r80a3woyq01E84Tt6kB-UH5u06XoQROaM0,68
5
+ epok_toolkit/cache/cacher.py,sha256=R179_Hrlw1k0tsry9EN0zGl4-Of02L-VzE-xqFuXjaU,4107
4
6
  epok_toolkit/email/__init__.py,sha256=pyJwysyVoq6DuYAG72fulsKFoOuAfjw3aBH7FhmYGHc,35
5
7
  epok_toolkit/email/email_async.py,sha256=oC0WowWNUpTpXdxo6hJag5gWUaStxI6VBEArEKQxXko,1521
6
8
  epok_toolkit/email/engine.py,sha256=IIifqRI9z76pHdrO5oSSZ25aP5txOTAgrj1JuVVPlMY,2387
7
9
  epok_toolkit/email/templates.py,sha256=uO3gYn2iiGxcjxioaG066gGPts1m-3C1Gp7XatGgVOg,7578
8
- epok_toolkit/messaging/__init__.py,sha256=AL9bL5fmVZx3ZvdzBWaVgvBJVnRuyYzrCp13txNTc3Q,41
10
+ epok_toolkit/messaging/__init__.py,sha256=lo0URCOr8tR62ljc0MWTtYZ_YR-tecQaAhhAbyGcOxs,53
9
11
  epok_toolkit/messaging/whatsapp.py,sha256=TrMSiKzvnhWOotSDEGil1BGgOJ7jLK7h3MXKdW3zCJw,14114
10
- epok_toolkit/messaging/whatsapp_instanced.py,sha256=fv2UuRHb6rLjTJ4AZCca3O8Evto_eiBo1MP81nggdPE,788
12
+ epok_toolkit/messaging/whatsapp_instanced.py,sha256=q1CR--9N7IsR5MSf6Fps_l0zpHzTBFcJnB5nw14a28U,1414
11
13
  epok_toolkit/pdf/__init__.py,sha256=Scb1iOYnVIUEiUVHLNaPmcigyD-jOSBs3ws5RmolMKE,33
12
14
  epok_toolkit/pdf/ticket_pdf.py,sha256=ce21N7OyaSQkfZvOL4c0mEFv7XSGajlOzL-gNb8vBro,8989
13
15
  epok_toolkit/pdf/fuentes/Kollektif-Bold.ttf,sha256=MiaucCL_aPGhbDl6M0xA2g2nf84MXHGciOd-XSw0XRo,78780
@@ -16,8 +18,8 @@ epok_toolkit/pdf/fuentes/Kollektif-Italic.ttf,sha256=1CXPyw43il9u0tQ_7aRzsEaVtg3
16
18
  epok_toolkit/pdf/fuentes/Kollektif.ttf,sha256=7wTLkVVNUm1giLjIZcWRUH5r2r3o0GjdKic4V1A-pNQ,51128
17
19
  epok_toolkit/pdf/plantillas/Ticket_congrats.png,sha256=OSQhVR0j_nLHE6kSJ33BTR-77HM1fNAfJBe2EuX6wVk,157141
18
20
  epok_toolkit/pdf/plantillas/Ticket_congrats2.png,sha256=1RBogBdo-8WSMpD3H73HoLgJtr5EC5oVKfOCIWOxPSo,373605
19
- epok_toolkit-1.5.2.dist-info/licenses/LICENSE,sha256=iLDbGXdLSIOT5OsxzHCvtmxHtonE21GiFlS3LNkug4A,128
20
- epok_toolkit-1.5.2.dist-info/METADATA,sha256=xckzx1LsdYeSbO73pXieyrZqqBB6GsrRFXKzK23DL4s,739
21
- epok_toolkit-1.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
- epok_toolkit-1.5.2.dist-info/top_level.txt,sha256=Wo72AqIFcfWwBGM5F5iGFw9PrO3WBnTSprFZIJk_pNg,13
23
- epok_toolkit-1.5.2.dist-info/RECORD,,
21
+ epok_toolkit-1.7.1.dist-info/licenses/LICENSE,sha256=iLDbGXdLSIOT5OsxzHCvtmxHtonE21GiFlS3LNkug4A,128
22
+ epok_toolkit-1.7.1.dist-info/METADATA,sha256=ty3DKZsCJ_239FAUKBJAIK46nbU9ZPZhfP5MRUIbFnM,786
23
+ epok_toolkit-1.7.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
+ epok_toolkit-1.7.1.dist-info/top_level.txt,sha256=Wo72AqIFcfWwBGM5F5iGFw9PrO3WBnTSprFZIJk_pNg,13
25
+ epok_toolkit-1.7.1.dist-info/RECORD,,