django-cfg 1.4.21__py3-none-any.whl → 1.4.23__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.
- django_cfg/__init__.py +4 -4
- django_cfg/apps/accounts/__init__.py +1 -1
- django_cfg/apps/accounts/__models.py +30 -29
- django_cfg/apps/accounts/admin/__init__.py +14 -3
- django_cfg/apps/accounts/admin/activity_admin.py +19 -19
- django_cfg/apps/accounts/admin/filters.py +7 -6
- django_cfg/apps/accounts/admin/group_admin.py +10 -16
- django_cfg/apps/accounts/admin/inlines.py +21 -19
- django_cfg/apps/accounts/admin/otp_admin.py +12 -12
- django_cfg/apps/accounts/admin/registration_admin.py +24 -24
- django_cfg/apps/accounts/admin/resources.py +49 -48
- django_cfg/apps/accounts/admin/twilio_admin.py +37 -37
- django_cfg/apps/accounts/admin/user_admin.py +45 -41
- django_cfg/apps/accounts/management/commands/otp_test.py +11 -11
- django_cfg/apps/accounts/managers/__init__.py +1 -1
- django_cfg/apps/accounts/managers/user_manager.py +6 -7
- django_cfg/apps/accounts/migrations/0001_initial.py +3 -2
- django_cfg/apps/accounts/models/__init__.py +15 -16
- django_cfg/apps/accounts/models/activity.py +5 -5
- django_cfg/apps/accounts/models/integrations.py +15 -15
- django_cfg/apps/accounts/models/registration.py +3 -2
- django_cfg/apps/accounts/models/user.py +3 -2
- django_cfg/apps/accounts/serializers/__init__.py +10 -3
- django_cfg/apps/accounts/serializers/otp.py +5 -4
- django_cfg/apps/accounts/serializers/profile.py +4 -5
- django_cfg/apps/accounts/serializers/webhook.py +13 -13
- django_cfg/apps/accounts/services/activity_service.py +13 -12
- django_cfg/apps/accounts/services/otp_service.py +16 -14
- django_cfg/apps/accounts/signals.py +18 -16
- django_cfg/apps/accounts/urls.py +10 -5
- django_cfg/apps/accounts/utils/notifications.py +22 -22
- django_cfg/apps/accounts/views/__init__.py +1 -1
- django_cfg/apps/accounts/views/otp.py +15 -14
- django_cfg/apps/accounts/views/profile.py +14 -10
- django_cfg/apps/accounts/views/webhook.py +46 -48
- django_cfg/apps/agents/__init__.py +3 -3
- django_cfg/apps/agents/admin/__init__.py +1 -1
- django_cfg/apps/agents/admin/execution_admin.py +68 -72
- django_cfg/apps/agents/admin/registry_admin.py +50 -54
- django_cfg/apps/agents/admin/toolsets_admin.py +63 -67
- django_cfg/apps/agents/apps.py +3 -3
- django_cfg/apps/agents/core/__init__.py +4 -4
- django_cfg/apps/agents/core/dependencies.py +24 -23
- django_cfg/apps/agents/core/django_agent.py +41 -39
- django_cfg/apps/agents/core/exceptions.py +12 -12
- django_cfg/apps/agents/core/models.py +16 -15
- django_cfg/apps/agents/core/orchestrator.py +58 -58
- django_cfg/apps/agents/examples/simple_example.py +24 -19
- django_cfg/apps/agents/integration/__init__.py +1 -1
- django_cfg/apps/agents/integration/middleware.py +12 -11
- django_cfg/apps/agents/integration/registry.py +52 -49
- django_cfg/apps/agents/integration/signals.py +5 -5
- django_cfg/apps/agents/management/commands/create_agent.py +39 -38
- django_cfg/apps/agents/management/commands/orchestrator_status.py +40 -39
- django_cfg/apps/agents/managers/__init__.py +8 -3
- django_cfg/apps/agents/managers/execution.py +42 -41
- django_cfg/apps/agents/managers/registry.py +40 -39
- django_cfg/apps/agents/managers/toolsets.py +87 -86
- django_cfg/apps/agents/migrations/0001_initial.py +2 -1
- django_cfg/apps/agents/models/__init__.py +2 -2
- django_cfg/apps/agents/models/execution.py +43 -42
- django_cfg/apps/agents/models/registry.py +46 -45
- django_cfg/apps/agents/models/toolsets.py +63 -62
- django_cfg/apps/agents/patterns/__init__.py +5 -5
- django_cfg/apps/agents/patterns/content_agents.py +17 -16
- django_cfg/apps/agents/toolsets/__init__.py +3 -3
- django_cfg/apps/agents/toolsets/cache_toolset.py +56 -55
- django_cfg/apps/agents/toolsets/django_toolset.py +43 -42
- django_cfg/apps/agents/toolsets/file_toolset.py +64 -63
- django_cfg/apps/agents/toolsets/orm_toolset.py +75 -74
- django_cfg/apps/agents/urls.py +3 -2
- django_cfg/apps/api/commands/urls.py +1 -0
- django_cfg/apps/api/commands/views.py +23 -26
- django_cfg/apps/api/endpoints/checker.py +5 -4
- django_cfg/apps/api/endpoints/drf_views.py +2 -2
- django_cfg/apps/api/endpoints/tests.py +6 -5
- django_cfg/apps/api/endpoints/urls.py +2 -1
- django_cfg/apps/api/endpoints/views.py +1 -0
- django_cfg/apps/api/health/drf_views.py +6 -6
- django_cfg/apps/api/health/urls.py +2 -1
- django_cfg/apps/api/health/views.py +41 -41
- django_cfg/{modules/django_ipc_client → apps/ipc}/__init__.py +6 -6
- django_cfg/apps/ipc/apps.py +28 -0
- django_cfg/apps/ipc/serializers/__init__.py +19 -0
- django_cfg/apps/ipc/serializers/serializers.py +229 -0
- django_cfg/apps/ipc/services/__init__.py +7 -0
- django_cfg/apps/ipc/services/client/__init__.py +23 -0
- django_cfg/{modules/django_ipc_client → apps/ipc/services/client}/client.py +7 -6
- django_cfg/{modules/django_ipc_client → apps/ipc/services/client}/exceptions.py +1 -1
- django_cfg/{modules/django_ipc_client/dashboard → apps/ipc/services}/monitor.py +23 -5
- django_cfg/{modules/django_ipc_client/dashboard/static/django_ipc_dashboard/js/dashboard.js → apps/ipc/static/django_cfg_ipc/js/dashboard.mjs} +131 -63
- django_cfg/{modules/django_ipc_client/dashboard/templates/django_ipc_dashboard → apps/ipc/templates/django_cfg_ipc}/base.html +5 -10
- django_cfg/apps/ipc/templates/django_cfg_ipc/dashboard.html +202 -0
- django_cfg/apps/ipc/urls.py +21 -0
- django_cfg/apps/ipc/urls_admin.py +20 -0
- django_cfg/apps/ipc/views/__init__.py +8 -0
- django_cfg/apps/ipc/views/dashboard.py +15 -0
- django_cfg/apps/ipc/views/viewsets.py +245 -0
- django_cfg/apps/knowbase/admin/__init__.py +2 -2
- django_cfg/apps/knowbase/admin/actions/__init__.py +1 -1
- django_cfg/apps/knowbase/admin/actions/visibility_actions.py +2 -1
- django_cfg/apps/knowbase/admin/archive_admin.py +81 -84
- django_cfg/apps/knowbase/admin/chat_admin.py +70 -72
- django_cfg/apps/knowbase/admin/document_admin.py +10 -11
- django_cfg/apps/knowbase/admin/external_data_admin.py +69 -71
- django_cfg/apps/knowbase/admin/helpers/__init__.py +1 -1
- django_cfg/apps/knowbase/admin/helpers/configs.py +2 -2
- django_cfg/apps/knowbase/admin/helpers/statistics.py +1 -1
- django_cfg/apps/knowbase/apps.py +13 -13
- django_cfg/apps/knowbase/config/__init__.py +7 -6
- django_cfg/apps/knowbase/config/constance_fields.py +14 -12
- django_cfg/apps/knowbase/config/constance_settings.py +32 -31
- django_cfg/apps/knowbase/config/settings.py +28 -28
- django_cfg/apps/knowbase/examples/external_data_usage.py +35 -32
- django_cfg/apps/knowbase/management/commands/knowbase_stats.py +33 -32
- django_cfg/apps/knowbase/management/commands/setup_knowbase.py +11 -13
- django_cfg/apps/knowbase/managers/__init__.py +2 -2
- django_cfg/apps/knowbase/managers/archive.py +86 -85
- django_cfg/apps/knowbase/managers/base.py +5 -5
- django_cfg/apps/knowbase/managers/chat.py +29 -28
- django_cfg/apps/knowbase/managers/document.py +39 -39
- django_cfg/apps/knowbase/managers/external_data.py +74 -73
- django_cfg/apps/knowbase/migrations/0001_initial.py +2 -1
- django_cfg/apps/knowbase/migrations/0002_archiveitem_archiveitemchunk_documentarchive_and_more.py +2 -1
- django_cfg/apps/knowbase/mixins/__init__.py +4 -4
- django_cfg/apps/knowbase/mixins/config/__init__.py +1 -1
- django_cfg/apps/knowbase/mixins/config/meta_config.py +1 -1
- django_cfg/apps/knowbase/mixins/config.py +19 -18
- django_cfg/apps/knowbase/mixins/creator.py +7 -7
- django_cfg/apps/knowbase/mixins/examples/vehicle_model_example.py +29 -28
- django_cfg/apps/knowbase/mixins/external_data_mixin.py +6 -5
- django_cfg/apps/knowbase/mixins/generators/__init__.py +1 -1
- django_cfg/apps/knowbase/mixins/generators/content_generator.py +2 -2
- django_cfg/apps/knowbase/mixins/service.py +47 -45
- django_cfg/apps/knowbase/models/__init__.py +7 -7
- django_cfg/apps/knowbase/models/archive.py +72 -72
- django_cfg/apps/knowbase/models/base.py +12 -13
- django_cfg/apps/knowbase/models/chat.py +20 -19
- django_cfg/apps/knowbase/models/document.py +37 -35
- django_cfg/apps/knowbase/models/external_data.py +41 -42
- django_cfg/apps/knowbase/serializers/__init__.py +7 -7
- django_cfg/apps/knowbase/serializers/archive_serializers.py +50 -42
- django_cfg/apps/knowbase/serializers/chat_serializers.py +16 -15
- django_cfg/apps/knowbase/serializers/document_serializers.py +13 -12
- django_cfg/apps/knowbase/serializers/external_data_serializers.py +31 -31
- django_cfg/apps/knowbase/serializers/public_serializers.py +10 -9
- django_cfg/apps/knowbase/services/__init__.py +7 -7
- django_cfg/apps/knowbase/services/archive/__init__.py +7 -7
- django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +1 -1
- django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +1 -1
- django_cfg/apps/knowbase/services/archive/archive_service.py +109 -112
- django_cfg/apps/knowbase/services/archive/chunking/__init__.py +3 -3
- django_cfg/apps/knowbase/services/archive/chunking/base.py +1 -0
- django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +4 -3
- django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +5 -4
- django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +6 -5
- django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +4 -3
- django_cfg/apps/knowbase/services/archive/chunking_service.py +3 -7
- django_cfg/apps/knowbase/services/archive/context/__init__.py +1 -1
- django_cfg/apps/knowbase/services/archive/context/builders.py +2 -1
- django_cfg/apps/knowbase/services/archive/context/models.py +2 -1
- django_cfg/apps/knowbase/services/archive/exceptions.py +5 -5
- django_cfg/apps/knowbase/services/archive/extraction_service.py +111 -110
- django_cfg/apps/knowbase/services/archive/vectorization_service.py +80 -77
- django_cfg/apps/knowbase/services/base.py +11 -9
- django_cfg/apps/knowbase/services/chat_service.py +40 -39
- django_cfg/apps/knowbase/services/document_service.py +28 -27
- django_cfg/apps/knowbase/services/embedding/__init__.py +9 -9
- django_cfg/apps/knowbase/services/embedding/async_processor.py +38 -40
- django_cfg/apps/knowbase/services/embedding/batch_processor.py +45 -42
- django_cfg/apps/knowbase/services/embedding/batch_result.py +7 -6
- django_cfg/apps/knowbase/services/embedding/models.py +52 -51
- django_cfg/apps/knowbase/services/embedding/processors.py +24 -23
- django_cfg/apps/knowbase/services/embedding/utils.py +17 -17
- django_cfg/apps/knowbase/services/prompt_builder.py +24 -23
- django_cfg/apps/knowbase/services/search_service.py +52 -49
- django_cfg/apps/knowbase/signals/__init__.py +2 -5
- django_cfg/apps/knowbase/signals/archive_signals.py +35 -34
- django_cfg/apps/knowbase/signals/chat_signals.py +6 -5
- django_cfg/apps/knowbase/signals/document_signals.py +22 -22
- django_cfg/apps/knowbase/signals/external_data_signals.py +22 -22
- django_cfg/apps/knowbase/tasks/__init__.py +6 -7
- django_cfg/apps/knowbase/tasks/archive_tasks.py +41 -41
- django_cfg/apps/knowbase/tasks/document_processing.py +49 -44
- django_cfg/apps/knowbase/tasks/external_data_tasks.py +46 -44
- django_cfg/apps/knowbase/tasks/maintenance.py +26 -24
- django_cfg/apps/knowbase/urls.py +3 -2
- django_cfg/apps/knowbase/urls_admin.py +6 -3
- django_cfg/apps/knowbase/urls_system.py +4 -5
- django_cfg/apps/knowbase/utils/chunk_settings.py +22 -20
- django_cfg/apps/knowbase/utils/text_processing.py +76 -75
- django_cfg/apps/knowbase/utils/validation.py +9 -9
- django_cfg/apps/knowbase/views/__init__.py +5 -5
- django_cfg/apps/knowbase/views/archive_views.py +90 -87
- django_cfg/apps/knowbase/views/base.py +9 -12
- django_cfg/apps/knowbase/views/chat_views.py +32 -32
- django_cfg/apps/knowbase/views/document_views.py +27 -28
- django_cfg/apps/knowbase/views/public_views.py +19 -19
- django_cfg/apps/leads/admin/leads_admin.py +41 -45
- django_cfg/apps/leads/admin/resources.py +14 -14
- django_cfg/apps/leads/admin.py +7 -9
- django_cfg/apps/leads/apps.py +1 -1
- django_cfg/apps/leads/models.py +17 -17
- django_cfg/apps/leads/serializers.py +5 -4
- django_cfg/apps/leads/signals.py +7 -7
- django_cfg/apps/leads/tests.py +47 -47
- django_cfg/apps/leads/urls.py +2 -2
- django_cfg/apps/leads/views.py +11 -11
- django_cfg/apps/maintenance/__init__.py +3 -3
- django_cfg/apps/maintenance/admin/__init__.py +1 -1
- django_cfg/apps/maintenance/admin/api_key_admin.py +36 -36
- django_cfg/apps/maintenance/admin/log_admin.py +35 -37
- django_cfg/apps/maintenance/admin/scheduled_admin.py +47 -51
- django_cfg/apps/maintenance/admin/site_admin.py +49 -52
- django_cfg/apps/maintenance/apps.py +2 -2
- django_cfg/apps/maintenance/management/commands/maintenance.py +53 -52
- django_cfg/apps/maintenance/management/commands/process_scheduled_maintenance.py +44 -44
- django_cfg/apps/maintenance/management/commands/sync_cloudflare.py +32 -32
- django_cfg/apps/maintenance/managers/__init__.py +1 -1
- django_cfg/apps/maintenance/managers/cloudflare_site_manager.py +39 -38
- django_cfg/apps/maintenance/managers/maintenance_log_manager.py +32 -31
- django_cfg/apps/maintenance/migrations/0001_initial.py +1 -0
- django_cfg/apps/maintenance/models/__init__.py +2 -2
- django_cfg/apps/maintenance/models/cloudflare_api_key.py +15 -15
- django_cfg/apps/maintenance/models/cloudflare_site.py +24 -22
- django_cfg/apps/maintenance/models/maintenance_log.py +15 -14
- django_cfg/apps/maintenance/models/scheduled_maintenance.py +53 -52
- django_cfg/apps/maintenance/services/__init__.py +3 -3
- django_cfg/apps/maintenance/services/bulk_operations_service.py +68 -68
- django_cfg/apps/maintenance/services/maintenance_service.py +59 -58
- django_cfg/apps/maintenance/services/scheduled_maintenance_service.py +52 -52
- django_cfg/apps/maintenance/services/site_sync_service.py +64 -65
- django_cfg/apps/maintenance/utils/__init__.py +1 -1
- django_cfg/apps/maintenance/utils/retry_utils.py +17 -17
- django_cfg/apps/newsletter/admin/__init__.py +12 -16
- django_cfg/apps/newsletter/admin/newsletter_admin.py +90 -87
- django_cfg/apps/newsletter/admin/resources.py +29 -29
- django_cfg/apps/newsletter/admin.py +39 -32
- django_cfg/apps/newsletter/management/commands/test_newsletter.py +3 -3
- django_cfg/apps/newsletter/managers/__init__.py +1 -1
- django_cfg/apps/newsletter/migrations/0001_initial.py +2 -1
- django_cfg/apps/newsletter/models.py +34 -33
- django_cfg/apps/newsletter/serializers.py +13 -13
- django_cfg/apps/newsletter/services/email_service.py +42 -40
- django_cfg/apps/newsletter/signals.py +4 -3
- django_cfg/apps/newsletter/urls.py +7 -7
- django_cfg/apps/newsletter/views/__init__.py +14 -19
- django_cfg/apps/newsletter/views/campaigns.py +19 -19
- django_cfg/apps/newsletter/views/emails.py +20 -20
- django_cfg/apps/newsletter/views/newsletters.py +5 -5
- django_cfg/apps/newsletter/views/subscriptions.py +24 -24
- django_cfg/apps/newsletter/views/tracking.py +6 -5
- django_cfg/apps/payments/admin/__init__.py +6 -5
- django_cfg/apps/payments/admin/api_keys_admin.py +43 -45
- django_cfg/apps/payments/admin/balance_admin.py +41 -47
- django_cfg/apps/payments/admin/currencies_admin.py +60 -62
- django_cfg/apps/payments/admin/endpoint_groups_admin.py +14 -28
- django_cfg/apps/payments/admin/filters.py +59 -59
- django_cfg/apps/payments/admin/networks_admin.py +36 -50
- django_cfg/apps/payments/admin/payments_admin.py +47 -49
- django_cfg/apps/payments/admin/subscriptions_admin.py +30 -32
- django_cfg/apps/payments/admin/tariffs_admin.py +37 -42
- django_cfg/apps/payments/admin_interface/serializers/__init__.py +12 -13
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +28 -27
- django_cfg/apps/payments/admin_interface/serializers/webhook_serializers.py +4 -5
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +407 -3
- django_cfg/apps/payments/admin_interface/templates/payments/components/ngrok_status.html +13 -13
- django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +5 -1
- django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +105 -49
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +4 -1
- django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +16 -8
- django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +16 -8
- django_cfg/apps/payments/admin_interface/views/__init__.py +8 -9
- django_cfg/apps/payments/admin_interface/views/api/__init__.py +3 -3
- django_cfg/apps/payments/admin_interface/views/api/payments.py +52 -54
- django_cfg/apps/payments/admin_interface/views/api/stats.py +33 -30
- django_cfg/apps/payments/admin_interface/views/api/users.py +10 -11
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +46 -51
- django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +9 -9
- django_cfg/apps/payments/admin_interface/views/base.py +17 -19
- django_cfg/apps/payments/admin_interface/views/dashboard.py +10 -10
- django_cfg/apps/payments/admin_interface/views/forms.py +21 -20
- django_cfg/apps/payments/apps.py +7 -6
- django_cfg/apps/payments/config/__init__.py +4 -4
- django_cfg/apps/payments/config/django_cfg_integration.py +22 -21
- django_cfg/apps/payments/config/helpers.py +14 -12
- django_cfg/apps/payments/management/commands/cleanup_expired_data.py +85 -86
- django_cfg/apps/payments/management/commands/currency_stats.py +84 -87
- django_cfg/apps/payments/management/commands/manage_currencies.py +59 -58
- django_cfg/apps/payments/management/commands/manage_providers.py +103 -105
- django_cfg/apps/payments/management/commands/process_pending_payments.py +67 -70
- django_cfg/apps/payments/management/commands/test_providers.py +83 -84
- django_cfg/apps/payments/middleware/__init__.py +1 -1
- django_cfg/apps/payments/middleware/api_access.py +77 -78
- django_cfg/apps/payments/middleware/rate_limiting.py +72 -72
- django_cfg/apps/payments/middleware/usage_tracking.py +66 -64
- django_cfg/apps/payments/migrations/0001_initial.py +2 -1
- django_cfg/apps/payments/models/__init__.py +11 -12
- django_cfg/apps/payments/models/api_keys.py +29 -27
- django_cfg/apps/payments/models/balance.py +38 -38
- django_cfg/apps/payments/models/base.py +12 -11
- django_cfg/apps/payments/models/currencies.py +53 -52
- django_cfg/apps/payments/models/managers/__init__.py +13 -14
- django_cfg/apps/payments/models/managers/api_key_managers.py +55 -53
- django_cfg/apps/payments/models/managers/balance_managers.py +98 -97
- django_cfg/apps/payments/models/managers/currency_managers.py +70 -69
- django_cfg/apps/payments/models/managers/payment_managers.py +113 -111
- django_cfg/apps/payments/models/managers/subscription_managers.py +99 -97
- django_cfg/apps/payments/models/payments.py +167 -73
- django_cfg/apps/payments/models/subscriptions.py +56 -54
- django_cfg/apps/payments/models/tariffs.py +35 -34
- django_cfg/apps/payments/services/__init__.py +33 -36
- django_cfg/apps/payments/services/cache/__init__.py +7 -1
- django_cfg/apps/payments/services/cache_service/__init__.py +22 -20
- django_cfg/apps/payments/services/cache_service/api_key_cache.py +6 -5
- django_cfg/apps/payments/services/cache_service/interfaces.py +5 -5
- django_cfg/apps/payments/services/cache_service/keys.py +8 -8
- django_cfg/apps/payments/services/cache_service/rate_limit_cache.py +8 -7
- django_cfg/apps/payments/services/cache_service/simple_cache.py +17 -14
- django_cfg/apps/payments/services/core/__init__.py +3 -3
- django_cfg/apps/payments/services/core/balance_service.py +69 -65
- django_cfg/apps/payments/services/core/base.py +25 -22
- django_cfg/apps/payments/services/core/currency/__init__.py +1 -1
- django_cfg/apps/payments/services/core/currency/currency_converter.py +2 -0
- django_cfg/apps/payments/services/core/currency_service.py +68 -66
- django_cfg/apps/payments/services/core/operations/__init__.py +1 -1
- django_cfg/apps/payments/services/core/operations/payment_canceller.py +2 -1
- django_cfg/apps/payments/services/core/operations/payment_creator.py +2 -1
- django_cfg/apps/payments/services/core/operations/status_checker.py +2 -1
- django_cfg/apps/payments/services/core/payment_service.py +10 -7
- django_cfg/apps/payments/services/core/providers/provider_client.py +2 -2
- django_cfg/apps/payments/services/core/subscription_service.py +77 -74
- django_cfg/apps/payments/services/core/utils/data_converter.py +1 -0
- django_cfg/apps/payments/services/core/utils/statistics_calculator.py +1 -0
- django_cfg/apps/payments/services/core/webhook_service.py +67 -63
- django_cfg/apps/payments/services/integrations/__init__.py +3 -3
- django_cfg/apps/payments/services/integrations/ngrok_service.py +1 -0
- django_cfg/apps/payments/services/integrations/providers_config.py +3 -2
- django_cfg/apps/payments/services/providers/base.py +59 -57
- django_cfg/apps/payments/services/providers/models/__init__.py +7 -14
- django_cfg/apps/payments/services/providers/models/base.py +15 -15
- django_cfg/apps/payments/services/providers/models/providers.py +13 -12
- django_cfg/apps/payments/services/providers/models/universal.py +6 -5
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +4 -4
- django_cfg/apps/payments/services/providers/nowpayments/config.py +9 -8
- django_cfg/apps/payments/services/providers/nowpayments/models.py +15 -15
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +2 -2
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +26 -26
- django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +3 -2
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +95 -99
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +41 -40
- django_cfg/apps/payments/services/providers/registry.py +65 -63
- django_cfg/apps/payments/services/providers/sync_service.py +50 -50
- django_cfg/apps/payments/services/types/__init__.py +21 -22
- django_cfg/apps/payments/services/types/data.py +14 -13
- django_cfg/apps/payments/services/types/requests.py +21 -22
- django_cfg/apps/payments/services/types/responses.py +16 -15
- django_cfg/apps/payments/services/types/webhooks.py +30 -30
- django_cfg/apps/payments/signals/__init__.py +4 -6
- django_cfg/apps/payments/signals/api_key_signals.py +33 -32
- django_cfg/apps/payments/signals/balance_signals.py +28 -26
- django_cfg/apps/payments/signals/payment_signals.py +29 -28
- django_cfg/apps/payments/signals/subscription_signals.py +39 -38
- django_cfg/apps/payments/static/payments/js/ngrok-status.js +12 -8
- django_cfg/apps/payments/static/payments/js/payment-detail.js +1 -1
- django_cfg/apps/payments/static/payments/js/payment-form.js +3 -3
- django_cfg/apps/payments/static/payments/js/payment-list.js +13 -6
- django_cfg/apps/payments/static/payments/js/webhook-dashboard-mjs.js +241 -0
- django_cfg/apps/payments/tasks/__init__.py +11 -12
- django_cfg/apps/payments/tasks/types.py +10 -9
- django_cfg/apps/payments/tasks/usage_tracking.py +44 -46
- django_cfg/apps/payments/templatetags/payment_tags.py +27 -27
- django_cfg/apps/payments/urls.py +31 -14
- django_cfg/apps/payments/urls_admin.py +10 -10
- django_cfg/apps/payments/views/api/__init__.py +32 -33
- django_cfg/apps/payments/views/api/api_keys.py +62 -62
- django_cfg/apps/payments/views/api/balances.py +63 -64
- django_cfg/apps/payments/views/api/base.py +52 -52
- django_cfg/apps/payments/views/api/currencies.py +75 -63
- django_cfg/apps/payments/views/api/payments.py +73 -74
- django_cfg/apps/payments/views/api/subscriptions.py +71 -72
- django_cfg/apps/payments/views/api/webhooks.py +85 -84
- django_cfg/apps/payments/views/overview/__init__.py +7 -7
- django_cfg/apps/payments/views/overview/serializers.py +13 -14
- django_cfg/apps/payments/views/overview/services.py +66 -67
- django_cfg/apps/payments/views/overview/urls.py +2 -1
- django_cfg/apps/payments/views/overview/views.py +31 -31
- django_cfg/apps/payments/views/serializers/__init__.py +35 -36
- django_cfg/apps/payments/views/serializers/api_keys.py +59 -57
- django_cfg/apps/payments/views/serializers/balances.py +34 -33
- django_cfg/apps/payments/views/serializers/currencies.py +36 -34
- django_cfg/apps/payments/views/serializers/payments.py +48 -47
- django_cfg/apps/payments/views/serializers/subscriptions.py +50 -45
- django_cfg/apps/payments/views/serializers/webhooks.py +17 -16
- django_cfg/apps/support/admin/__init__.py +3 -3
- django_cfg/apps/support/admin/resources.py +26 -26
- django_cfg/apps/support/admin/support_admin.py +44 -48
- django_cfg/apps/support/admin.py +16 -15
- django_cfg/apps/support/apps.py +1 -1
- django_cfg/apps/support/managers/message_manager.py +4 -4
- django_cfg/apps/support/managers/ticket_manager.py +13 -12
- django_cfg/apps/support/migrations/0001_initial.py +2 -1
- django_cfg/apps/support/models.py +3 -1
- django_cfg/apps/support/serializers.py +4 -2
- django_cfg/apps/support/signals.py +12 -10
- django_cfg/apps/support/urls.py +4 -3
- django_cfg/apps/support/utils/support_email_service.py +11 -9
- django_cfg/apps/support/views/__init__.py +3 -3
- django_cfg/apps/support/views/admin.py +9 -9
- django_cfg/apps/support/views/api.py +10 -9
- django_cfg/apps/support/views/chat.py +14 -14
- django_cfg/apps/tasks/admin/tasks_admin.py +65 -74
- django_cfg/apps/tasks/apps.py +2 -2
- django_cfg/apps/tasks/serializers.py +6 -6
- django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +44 -20
- django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +7 -5
- django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +5 -3
- django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +5 -3
- django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +5 -3
- django_cfg/apps/tasks/tasks/demo_tasks.py +12 -11
- django_cfg/apps/tasks/templates/tasks/components/tasks_mjs_integration.html +269 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard-improved.html +168 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +21 -2
- django_cfg/apps/tasks/urls.py +3 -2
- django_cfg/apps/tasks/urls_admin.py +1 -0
- django_cfg/apps/tasks/utils/simulator.py +49 -52
- django_cfg/apps/tasks/views/api.py +75 -73
- django_cfg/apps/tasks/views/dashboard.py +5 -4
- django_cfg/apps/urls.py +20 -11
- django_cfg/apps.py +6 -5
- django_cfg/cli/commands/create_project.py +7 -6
- django_cfg/cli/commands/info.py +25 -25
- django_cfg/cli/utils.py +27 -27
- django_cfg/config.py +1 -1
- django_cfg/core/__init__.py +8 -8
- django_cfg/core/base/config_model.py +13 -12
- django_cfg/core/builders/apps_builder.py +2 -2
- django_cfg/core/builders/middleware_builder.py +1 -1
- django_cfg/core/builders/security_builder.py +1 -1
- django_cfg/core/config.py +2 -2
- django_cfg/core/environment/detector.py +27 -28
- django_cfg/core/exceptions.py +1 -1
- django_cfg/core/generation/core_generators/settings.py +1 -1
- django_cfg/core/generation/core_generators/static.py +11 -5
- django_cfg/core/generation/core_generators/templates.py +1 -1
- django_cfg/core/generation/data_generators/__init__.py +1 -1
- django_cfg/core/generation/data_generators/cache.py +1 -1
- django_cfg/core/generation/data_generators/database.py +1 -1
- django_cfg/core/generation/generation.py +1 -3
- django_cfg/core/generation/integration_generators/__init__.py +2 -2
- django_cfg/core/generation/integration_generators/api.py +12 -2
- django_cfg/core/generation/integration_generators/sessions.py +1 -1
- django_cfg/core/generation/integration_generators/tailwind.py +1 -1
- django_cfg/core/generation/integration_generators/tasks.py +1 -1
- django_cfg/core/generation/integration_generators/third_party.py +1 -1
- django_cfg/core/generation/orchestrator.py +1 -1
- django_cfg/core/generation/protocols.py +1 -1
- django_cfg/core/generation/utility_generators/__init__.py +1 -1
- django_cfg/core/generation/utility_generators/email.py +1 -1
- django_cfg/core/generation/utility_generators/i18n.py +1 -1
- django_cfg/core/generation/utility_generators/limits.py +1 -1
- django_cfg/core/generation/utility_generators/logging.py +1 -1
- django_cfg/core/generation/utility_generators/security.py +1 -1
- django_cfg/core/generation/utils/helpers.py +1 -1
- django_cfg/core/integration/__init__.py +5 -5
- django_cfg/core/integration/commands_collector.py +38 -39
- django_cfg/core/integration/display/__init__.py +2 -2
- django_cfg/core/integration/display/base.py +30 -30
- django_cfg/core/integration/display/ngrok.py +35 -36
- django_cfg/core/integration/display/startup.py +149 -139
- django_cfg/core/integration/url_integration.py +10 -10
- django_cfg/core/integration/version_checker.py +20 -19
- django_cfg/core/services/config_service.py +4 -4
- django_cfg/core/state/__init__.py +1 -1
- django_cfg/core/state/registry.py +1 -1
- django_cfg/core/types/__init__.py +8 -1
- django_cfg/core/validation.py +36 -39
- django_cfg/management/commands/check_endpoints.py +3 -1
- django_cfg/management/commands/check_settings.py +3 -1
- django_cfg/management/commands/clear_constance.py +3 -1
- django_cfg/management/commands/create_token.py +3 -1
- django_cfg/management/commands/generate_clients.py +3 -1
- django_cfg/management/commands/migrate_all.py +3 -1
- django_cfg/management/commands/rundramatiq.py +3 -1
- django_cfg/management/commands/rundramatiq_simulator.py +3 -1
- django_cfg/management/commands/runserver_ngrok.py +3 -1
- django_cfg/management/commands/show_config.py +3 -1
- django_cfg/management/commands/superuser.py +3 -1
- django_cfg/management/commands/task_clear.py +3 -1
- django_cfg/management/commands/task_status.py +3 -1
- django_cfg/management/commands/test_email.py +3 -1
- django_cfg/management/commands/test_telegram.py +3 -1
- django_cfg/management/commands/test_twilio.py +3 -1
- django_cfg/management/commands/validate_openapi.py +3 -1
- django_cfg/middleware/pagination.py +8 -8
- django_cfg/middleware/public_endpoints.py +24 -23
- django_cfg/middleware/user_activity.py +27 -25
- django_cfg/models/__init__.py +19 -20
- django_cfg/models/api/__init__.py +4 -4
- django_cfg/models/api/config.py +23 -21
- django_cfg/models/api/cors.py +17 -16
- django_cfg/models/api/drf/__init__.py +1 -1
- django_cfg/models/api/drf/config.py +2 -1
- django_cfg/models/api/drf/redoc.py +2 -1
- django_cfg/models/api/drf/spectacular.py +4 -2
- django_cfg/models/api/drf/swagger.py +2 -1
- django_cfg/models/api/jwt.py +37 -36
- django_cfg/models/api/keys.py +13 -12
- django_cfg/models/api/limits.py +31 -30
- django_cfg/models/base/config.py +40 -41
- django_cfg/models/base/module.py +8 -8
- django_cfg/models/django/__init__.py +1 -1
- django_cfg/models/django/constance.py +8 -7
- django_cfg/models/django/environment.py +5 -3
- django_cfg/models/django/openapi.py +6 -16
- django_cfg/models/django/revolution_legacy.py +17 -16
- django_cfg/models/infrastructure/__init__.py +1 -1
- django_cfg/models/infrastructure/cache.py +46 -45
- django_cfg/models/infrastructure/database/config.py +4 -6
- django_cfg/models/infrastructure/database/converters.py +1 -1
- django_cfg/models/infrastructure/database/parsers.py +1 -1
- django_cfg/models/infrastructure/database/validators.py +1 -1
- django_cfg/models/infrastructure/logging.py +59 -57
- django_cfg/models/infrastructure/security.py +26 -24
- django_cfg/models/ngrok/auth.py +2 -1
- django_cfg/models/ngrok/config.py +3 -2
- django_cfg/models/ngrok/tunnel.py +2 -1
- django_cfg/models/payments/__init__.py +1 -1
- django_cfg/models/payments/api_keys.py +3 -1
- django_cfg/models/payments/config.py +4 -1
- django_cfg/models/payments/providers/base.py +2 -1
- django_cfg/models/payments/providers/nowpayments.py +3 -1
- django_cfg/models/services/__init__.py +1 -1
- django_cfg/models/services/base.py +2 -1
- django_cfg/models/services/email.py +28 -26
- django_cfg/models/services/telegram.py +2 -1
- django_cfg/models/tasks/__init__.py +2 -2
- django_cfg/models/tasks/backends.py +4 -3
- django_cfg/models/tasks/config.py +6 -4
- django_cfg/models/tasks/utils.py +3 -3
- django_cfg/modules/base.py +18 -17
- django_cfg/modules/django_admin/__init__.py +14 -15
- django_cfg/modules/django_admin/decorators/__init__.py +1 -1
- django_cfg/modules/django_admin/decorators/actions.py +8 -7
- django_cfg/modules/django_admin/decorators/display.py +9 -7
- django_cfg/modules/django_admin/icons/__init__.py +1 -1
- django_cfg/modules/django_admin/icons/constants.py +27 -27
- django_cfg/modules/django_admin/icons/generate_icons.py +54 -54
- django_cfg/modules/django_admin/management/commands/check_endpoints.py +5 -3
- django_cfg/modules/django_admin/management/commands/check_settings.py +40 -44
- django_cfg/modules/django_admin/management/commands/clear_constance.py +29 -30
- django_cfg/modules/django_admin/management/commands/create_token.py +42 -42
- django_cfg/modules/django_admin/management/commands/list_urls.py +37 -38
- django_cfg/modules/django_admin/management/commands/migrate_all.py +13 -15
- django_cfg/modules/django_admin/management/commands/migrator.py +17 -17
- django_cfg/modules/django_admin/management/commands/script.py +58 -60
- django_cfg/modules/django_admin/management/commands/show_config.py +32 -30
- django_cfg/modules/django_admin/management/commands/show_urls.py +46 -44
- django_cfg/modules/django_admin/management/commands/superuser.py +47 -48
- django_cfg/modules/django_admin/management/commands/tree.py +50 -54
- django_cfg/modules/django_admin/mixins/display_mixin.py +16 -15
- django_cfg/modules/django_admin/mixins/optimization_mixin.py +9 -8
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +25 -24
- django_cfg/modules/django_admin/models/__init__.py +4 -4
- django_cfg/modules/django_admin/models/action_models.py +3 -1
- django_cfg/modules/django_admin/models/badge_models.py +4 -2
- django_cfg/modules/django_admin/models/base.py +3 -3
- django_cfg/modules/django_admin/models/display_models.py +1 -0
- django_cfg/modules/django_admin/utils/badges.py +27 -26
- django_cfg/modules/django_admin/utils/displays.py +49 -49
- django_cfg/modules/django_client/apps.py +21 -3
- django_cfg/modules/django_client/core/__init__.py +9 -10
- django_cfg/modules/django_client/core/archive/manager.py +2 -2
- django_cfg/modules/django_client/core/cli/main.py +1 -3
- django_cfg/modules/django_client/core/config/config.py +3 -1
- django_cfg/modules/django_client/core/config/group.py +1 -0
- django_cfg/modules/django_client/core/config/service.py +2 -1
- django_cfg/modules/django_client/core/generator/__init__.py +1 -1
- django_cfg/modules/django_client/core/generator/base.py +2 -2
- django_cfg/modules/django_client/core/generator/python/async_client_gen.py +1 -1
- django_cfg/modules/django_client/core/generator/python/files_generator.py +1 -1
- django_cfg/modules/django_client/core/generator/python/generator.py +4 -4
- django_cfg/modules/django_client/core/generator/python/models_generator.py +1 -1
- django_cfg/modules/django_client/core/generator/python/operations_generator.py +2 -2
- django_cfg/modules/django_client/core/generator/python/sync_client_gen.py +1 -1
- django_cfg/modules/django_client/core/generator/typescript/client_generator.py +3 -1
- django_cfg/modules/django_client/core/generator/typescript/fetchers_generator.py +14 -13
- django_cfg/modules/django_client/core/generator/typescript/files_generator.py +1 -0
- django_cfg/modules/django_client/core/generator/typescript/generator.py +6 -6
- django_cfg/modules/django_client/core/generator/typescript/hooks_generator.py +12 -10
- django_cfg/modules/django_client/core/generator/typescript/models_generator.py +2 -1
- django_cfg/modules/django_client/core/generator/typescript/naming.py +2 -3
- django_cfg/modules/django_client/core/generator/typescript/operations_generator.py +12 -10
- django_cfg/modules/django_client/core/generator/typescript/schemas_generator.py +3 -2
- django_cfg/modules/django_client/core/generator/typescript/templates/client/client.ts.jinja +14 -6
- django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +4 -10
- django_cfg/modules/django_client/core/groups/__init__.py +1 -1
- django_cfg/modules/django_client/core/groups/detector.py +2 -1
- django_cfg/modules/django_client/core/groups/manager.py +2 -1
- django_cfg/modules/django_client/core/ir/schema.py +1 -1
- django_cfg/modules/django_client/core/parser/base.py +0 -2
- django_cfg/modules/django_client/core/parser/models/schema.py +1 -1
- django_cfg/modules/django_client/core/validation/__init__.py +1 -1
- django_cfg/modules/django_client/core/validation/fixer.py +1 -2
- django_cfg/modules/django_client/core/validation/reporter.py +2 -2
- django_cfg/modules/django_client/core/validation/safety.py +1 -1
- django_cfg/modules/django_client/management/commands/generate_client.py +14 -11
- django_cfg/modules/django_client/management/commands/validate_openapi.py +4 -6
- django_cfg/modules/django_client/spectacular/__init__.py +1 -1
- django_cfg/modules/django_client/spectacular/async_detection.py +3 -2
- django_cfg/modules/django_client/spectacular/enum_naming.py +1 -1
- django_cfg/modules/django_client/spectacular/schema.py +5 -5
- django_cfg/modules/django_client/system/__init__.py +24 -0
- django_cfg/modules/django_client/system/base_generator.py +123 -0
- django_cfg/modules/django_client/system/generate_mjs_clients.py +174 -0
- django_cfg/modules/django_client/system/mjs_generator.py +219 -0
- django_cfg/modules/django_client/system/schema_parser.py +195 -0
- django_cfg/modules/django_client/system/templates/api_client.js.j2 +87 -0
- django_cfg/modules/django_client/system/templates/app_index.js.j2 +13 -0
- django_cfg/modules/django_client/system/templates/base_client.js.j2 +166 -0
- django_cfg/modules/django_client/system/templates/main_index.js.j2 +80 -0
- django_cfg/modules/django_client/system/templates/types.js.j2 +24 -0
- django_cfg/modules/django_client/urls.py +3 -2
- django_cfg/modules/django_currency/__init__.py +17 -18
- django_cfg/modules/django_currency/clients/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/coinpaprika_client.py +48 -48
- django_cfg/modules/django_currency/clients/hybrid_client.py +76 -75
- django_cfg/modules/django_currency/core/__init__.py +7 -13
- django_cfg/modules/django_currency/core/converter.py +25 -24
- django_cfg/modules/django_currency/core/models.py +9 -8
- django_cfg/modules/django_currency/database/__init__.py +4 -4
- django_cfg/modules/django_currency/database/database_loader.py +65 -66
- django_cfg/modules/django_currency/examples/example_database_usage.py +29 -28
- django_cfg/modules/django_currency/utils/cache.py +10 -11
- django_cfg/modules/django_dashboard/__init__.py +4 -5
- django_cfg/modules/django_dashboard/components.py +11 -7
- django_cfg/modules/django_dashboard/debug.py +1 -3
- django_cfg/modules/django_dashboard/management/commands/debug_dashboard.py +3 -3
- django_cfg/modules/django_dashboard/sections/base.py +2 -1
- django_cfg/modules/django_dashboard/sections/commands.py +3 -2
- django_cfg/modules/django_dashboard/sections/documentation.py +8 -6
- django_cfg/modules/django_dashboard/sections/overview.py +13 -9
- django_cfg/modules/django_dashboard/sections/stats.py +2 -2
- django_cfg/modules/django_dashboard/sections/system.py +2 -1
- django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +12 -4
- django_cfg/modules/django_email/management/commands/test_email.py +8 -7
- django_cfg/modules/django_email/service.py +5 -4
- django_cfg/modules/django_health/service.py +46 -44
- django_cfg/modules/django_import_export/__init__.py +7 -3
- django_cfg/modules/django_llm/__init__.py +3 -2
- django_cfg/modules/django_llm/example.py +58 -56
- django_cfg/modules/django_llm/llm/__init__.py +1 -1
- django_cfg/modules/django_llm/llm/cache.py +21 -20
- django_cfg/modules/django_llm/llm/client.py +9 -9
- django_cfg/modules/django_llm/llm/costs.py +14 -14
- django_cfg/modules/django_llm/llm/embeddings/__init__.py +1 -1
- django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +1 -2
- django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +1 -2
- django_cfg/modules/django_llm/llm/extractor.py +8 -8
- django_cfg/modules/django_llm/llm/models.py +5 -5
- django_cfg/modules/django_llm/llm/models_api/models_query.py +2 -2
- django_cfg/modules/django_llm/llm/models_cache.py +91 -92
- django_cfg/modules/django_llm/llm/providers/config_builder.py +1 -1
- django_cfg/modules/django_llm/llm/providers/provider_manager.py +2 -1
- django_cfg/modules/django_llm/llm/requests/cache_manager.py +1 -1
- django_cfg/modules/django_llm/llm/requests/chat_handler.py +2 -2
- django_cfg/modules/django_llm/llm/requests/embedding_handler.py +1 -1
- django_cfg/modules/django_llm/llm/responses/response_builder.py +2 -2
- django_cfg/modules/django_llm/llm/stats/stats_manager.py +1 -1
- django_cfg/modules/django_llm/llm/tokenizer.py +10 -9
- django_cfg/modules/django_llm/translator/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/cache.py +36 -35
- django_cfg/modules/django_llm/translator/detectors/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/detectors/script_detector.py +0 -1
- django_cfg/modules/django_llm/translator/stats/stats_tracker.py +1 -1
- django_cfg/modules/django_llm/translator/translator.py +5 -4
- django_cfg/modules/django_llm/translator/translators/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/translators/json_translator.py +1 -1
- django_cfg/modules/django_llm/translator/utils/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/utils/prompt_builder.py +0 -1
- django_cfg/modules/django_logging/__init__.py +1 -1
- django_cfg/modules/django_logging/django_logger.py +33 -34
- django_cfg/modules/django_logging/logger.py +3 -7
- django_cfg/modules/django_ngrok/__init__.py +7 -7
- django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +33 -30
- django_cfg/modules/django_ngrok/service.py +33 -32
- django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +4 -36
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +1 -1
- django_cfg/modules/django_tasks/__init__.py +5 -5
- django_cfg/modules/django_tasks/dramatiq_setup.py +1 -1
- django_cfg/modules/django_tasks/factory.py +1 -1
- django_cfg/modules/django_tasks/management/commands/rundramatiq.py +39 -40
- django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +79 -80
- django_cfg/modules/django_tasks/management/commands/task_clear.py +34 -34
- django_cfg/modules/django_tasks/management/commands/task_status.py +34 -34
- django_cfg/modules/django_tasks/service.py +4 -3
- django_cfg/modules/django_tasks/settings.py +1 -1
- django_cfg/modules/django_telegram/__init__.py +4 -4
- django_cfg/modules/django_telegram/management/commands/test_telegram.py +4 -5
- django_cfg/modules/django_telegram/service.py +4 -3
- django_cfg/modules/django_telegram/utils.py +1 -1
- django_cfg/modules/django_twilio/__init__.py +15 -16
- django_cfg/modules/django_twilio/_imports.py +1 -1
- django_cfg/modules/django_twilio/base.py +9 -5
- django_cfg/modules/django_twilio/email_otp.py +4 -3
- django_cfg/modules/django_twilio/exceptions.py +36 -36
- django_cfg/modules/django_twilio/management/commands/test_twilio.py +6 -7
- django_cfg/modules/django_twilio/models.py +54 -53
- django_cfg/modules/django_twilio/sendgrid_service.py +70 -72
- django_cfg/modules/django_twilio/simple_service.py +42 -41
- django_cfg/modules/django_twilio/sms.py +1 -0
- django_cfg/modules/django_twilio/twilio_service.py +79 -83
- django_cfg/modules/django_twilio/unified.py +6 -5
- django_cfg/modules/django_twilio/utils.py +2 -3
- django_cfg/modules/django_twilio/whatsapp.py +3 -2
- django_cfg/modules/django_unfold/__init__.py +7 -6
- django_cfg/modules/django_unfold/callbacks/actions.py +6 -5
- django_cfg/modules/django_unfold/callbacks/apizones.py +122 -0
- django_cfg/modules/django_unfold/callbacks/base.py +9 -8
- django_cfg/modules/django_unfold/callbacks/charts.py +36 -37
- django_cfg/modules/django_unfold/callbacks/commands.py +2 -2
- django_cfg/modules/django_unfold/callbacks/main.py +27 -27
- django_cfg/modules/django_unfold/callbacks/statistics.py +12 -12
- django_cfg/modules/django_unfold/callbacks/system.py +5 -5
- django_cfg/modules/django_unfold/callbacks/users.py +4 -4
- django_cfg/modules/django_unfold/dashboard.py +29 -29
- django_cfg/modules/django_unfold/models/__init__.py +23 -8
- django_cfg/modules/django_unfold/models/config.py +84 -81
- django_cfg/modules/django_unfold/models/dashboard.py +20 -19
- django_cfg/modules/django_unfold/models/dropdown.py +6 -4
- django_cfg/modules/django_unfold/models/navigation.py +6 -4
- django_cfg/modules/django_unfold/models/tabs.py +4 -3
- django_cfg/modules/django_unfold/models.py +2 -3
- django_cfg/modules/django_unfold/system_monitor.py +27 -25
- django_cfg/modules/django_unfold/tailwind.py +12 -14
- django_cfg/modules/django_unfold/utils.py +7 -6
- django_cfg/pyproject.toml +1 -1
- django_cfg/registry/__init__.py +3 -3
- django_cfg/registry/core.py +8 -8
- django_cfg/registry/modules.py +2 -2
- django_cfg/registry/services.py +2 -2
- django_cfg/registry/third_party.py +3 -3
- django_cfg/routing/__init__.py +3 -3
- django_cfg/routing/callbacks.py +27 -26
- django_cfg/routing/routers.py +2 -2
- django_cfg/static/js/api/accounts/client.mjs +69 -0
- django_cfg/static/js/api/accounts/index.mjs +13 -0
- django_cfg/static/js/api/base.mjs +166 -0
- django_cfg/static/js/api/index.mjs +100 -0
- django_cfg/static/js/api/ipc/client.mjs +74 -0
- django_cfg/static/js/api/ipc/index.mjs +13 -0
- django_cfg/static/js/api/leads/client.mjs +71 -0
- django_cfg/static/js/api/leads/index.mjs +13 -0
- django_cfg/static/js/api/newsletter/client.mjs +109 -0
- django_cfg/static/js/api/newsletter/index.mjs +13 -0
- django_cfg/static/js/api/payments/client.mjs +1264 -0
- django_cfg/static/js/api/payments/index.mjs +13 -0
- django_cfg/static/js/api/support/client.mjs +84 -0
- django_cfg/static/js/api/support/index.mjs +13 -0
- django_cfg/static/js/api/tasks/client.mjs +74 -0
- django_cfg/static/js/api/tasks/index.mjs +13 -0
- django_cfg/static/js/api/types.mjs +729 -0
- django_cfg/static/js/api-loader.mjs +169 -0
- django_cfg/templates/admin/snippets/zones/zones_table.html +4 -3
- django_cfg/templatetags/django_cfg.py +4 -4
- django_cfg/utils/path_resolution.py +49 -50
- django_cfg/utils/smart_defaults.py +27 -29
- django_cfg/utils/version_check.py +14 -14
- {django_cfg-1.4.21.dist-info → django_cfg-1.4.23.dist-info}/METADATA +1 -1
- django_cfg-1.4.23.dist-info/RECORD +1137 -0
- django_cfg/apps/payments/static/payments/js/api-client.js +0 -408
- django_cfg/modules/django_ipc_client/dashboard/README.md +0 -517
- django_cfg/modules/django_ipc_client/dashboard/UNFOLD_INTEGRATION.md +0 -439
- django_cfg/modules/django_ipc_client/dashboard/__init__.py +0 -11
- django_cfg/modules/django_ipc_client/dashboard/apps.py +0 -22
- django_cfg/modules/django_ipc_client/dashboard/templates/django_ipc_dashboard/dashboard.html +0 -200
- django_cfg/modules/django_ipc_client/dashboard/urls.py +0 -22
- django_cfg/modules/django_ipc_client/dashboard/urls_admin.py +0 -9
- django_cfg/modules/django_ipc_client/dashboard/views.py +0 -251
- django_cfg/modules/django_rpc_old/POETRY.md +0 -344
- django_cfg/modules/django_rpc_old/README.md +0 -397
- django_cfg/modules/django_rpc_old/TESTING.md +0 -358
- django_cfg/modules/django_rpc_old/__init__.py +0 -39
- django_cfg/modules/django_rpc_old/client.py +0 -531
- django_cfg/modules/django_rpc_old/config.py +0 -279
- django_cfg/modules/django_rpc_old/exceptions.py +0 -172
- django_cfg/modules/django_unfold/callbacks/revolution.py +0 -81
- django_cfg-1.4.21.dist-info/RECORD +0 -1111
- /django_cfg/{modules/django_ipc_client → apps/ipc}/README.md +0 -0
- /django_cfg/{modules/django_ipc_client → apps/ipc/services/client}/config.py +0 -0
- {django_cfg-1.4.21.dist-info → django_cfg-1.4.23.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.21.dist-info → django_cfg-1.4.23.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.21.dist-info → django_cfg-1.4.23.dist-info}/licenses/LICENSE +0 -0
@@ -5,7 +5,7 @@ Following CRITICAL_REQUIREMENTS.md - proper exception handling with specific typ
|
|
5
5
|
No exception suppression, all errors must be properly typed and handled.
|
6
6
|
"""
|
7
7
|
|
8
|
-
from typing import
|
8
|
+
from typing import Any, Dict, List, Optional
|
9
9
|
|
10
10
|
|
11
11
|
class TwilioError(Exception):
|
@@ -15,10 +15,10 @@ class TwilioError(Exception):
|
|
15
15
|
All Twilio module exceptions inherit from this base class to allow
|
16
16
|
for specific exception handling patterns.
|
17
17
|
"""
|
18
|
-
|
18
|
+
|
19
19
|
def __init__(
|
20
|
-
self,
|
21
|
-
message: str,
|
20
|
+
self,
|
21
|
+
message: str,
|
22
22
|
error_code: Optional[str] = None,
|
23
23
|
context: Optional[Dict[str, Any]] = None,
|
24
24
|
suggestions: Optional[List[str]] = None
|
@@ -37,22 +37,22 @@ class TwilioError(Exception):
|
|
37
37
|
self.error_code = error_code
|
38
38
|
self.context = context or {}
|
39
39
|
self.suggestions = suggestions or []
|
40
|
-
|
40
|
+
|
41
41
|
def __str__(self) -> str:
|
42
42
|
"""Return formatted error message with context."""
|
43
43
|
parts = [self.message]
|
44
|
-
|
44
|
+
|
45
45
|
if self.error_code:
|
46
46
|
parts.append(f"Error Code: {self.error_code}")
|
47
|
-
|
47
|
+
|
48
48
|
if self.context:
|
49
49
|
context_str = ", ".join(f"{k}={v}" for k, v in self.context.items())
|
50
50
|
parts.append(f"Context: {context_str}")
|
51
|
-
|
51
|
+
|
52
52
|
if self.suggestions:
|
53
53
|
suggestions_str = "; ".join(self.suggestions)
|
54
54
|
parts.append(f"Suggestions: {suggestions_str}")
|
55
|
-
|
55
|
+
|
56
56
|
return " | ".join(parts)
|
57
57
|
|
58
58
|
|
@@ -66,7 +66,7 @@ class TwilioConfigurationError(TwilioError):
|
|
66
66
|
- Missing environment variables
|
67
67
|
- Incorrect service setup
|
68
68
|
"""
|
69
|
-
|
69
|
+
|
70
70
|
def __init__(
|
71
71
|
self,
|
72
72
|
message: str,
|
@@ -84,23 +84,23 @@ class TwilioConfigurationError(TwilioError):
|
|
84
84
|
**kwargs: Additional context passed to base class
|
85
85
|
"""
|
86
86
|
context = kwargs.get("context", {})
|
87
|
-
|
87
|
+
|
88
88
|
if missing_fields:
|
89
89
|
context["missing_fields"] = missing_fields
|
90
90
|
if invalid_fields:
|
91
91
|
context["invalid_fields"] = invalid_fields
|
92
|
-
|
92
|
+
|
93
93
|
kwargs["context"] = context
|
94
|
-
|
94
|
+
|
95
95
|
# Add default suggestions for configuration errors
|
96
96
|
suggestions = kwargs.get("suggestions", [])
|
97
97
|
if missing_fields:
|
98
98
|
suggestions.append(f"Set environment variables: {', '.join(missing_fields)}")
|
99
99
|
if invalid_fields:
|
100
100
|
suggestions.append(f"Check configuration for fields: {', '.join(invalid_fields)}")
|
101
|
-
|
101
|
+
|
102
102
|
kwargs["suggestions"] = suggestions
|
103
|
-
|
103
|
+
|
104
104
|
super().__init__(message, **kwargs)
|
105
105
|
|
106
106
|
|
@@ -114,7 +114,7 @@ class TwilioVerificationError(TwilioError):
|
|
114
114
|
- Too many verification attempts
|
115
115
|
- Verification service unavailable
|
116
116
|
"""
|
117
|
-
|
117
|
+
|
118
118
|
def __init__(
|
119
119
|
self,
|
120
120
|
message: str,
|
@@ -136,7 +136,7 @@ class TwilioVerificationError(TwilioError):
|
|
136
136
|
**kwargs: Additional context passed to base class
|
137
137
|
"""
|
138
138
|
context = kwargs.get("context", {})
|
139
|
-
|
139
|
+
|
140
140
|
if verification_sid:
|
141
141
|
context["verification_sid"] = verification_sid
|
142
142
|
if phone_number:
|
@@ -151,9 +151,9 @@ class TwilioVerificationError(TwilioError):
|
|
151
151
|
context["email"] = masked_email
|
152
152
|
if attempts_remaining is not None:
|
153
153
|
context["attempts_remaining"] = attempts_remaining
|
154
|
-
|
154
|
+
|
155
155
|
kwargs["context"] = context
|
156
|
-
|
156
|
+
|
157
157
|
super().__init__(message, **kwargs)
|
158
158
|
|
159
159
|
|
@@ -168,7 +168,7 @@ class TwilioSendError(TwilioError):
|
|
168
168
|
- Network connectivity issues
|
169
169
|
- Service rate limits exceeded
|
170
170
|
"""
|
171
|
-
|
171
|
+
|
172
172
|
def __init__(
|
173
173
|
self,
|
174
174
|
message: str,
|
@@ -190,7 +190,7 @@ class TwilioSendError(TwilioError):
|
|
190
190
|
**kwargs: Additional context passed to base class
|
191
191
|
"""
|
192
192
|
context = kwargs.get("context", {})
|
193
|
-
|
193
|
+
|
194
194
|
if channel:
|
195
195
|
context["channel"] = channel
|
196
196
|
if recipient:
|
@@ -207,9 +207,9 @@ class TwilioSendError(TwilioError):
|
|
207
207
|
context["twilio_error_code"] = twilio_error_code
|
208
208
|
if twilio_error_message:
|
209
209
|
context["twilio_error_message"] = twilio_error_message
|
210
|
-
|
210
|
+
|
211
211
|
kwargs["context"] = context
|
212
|
-
|
212
|
+
|
213
213
|
# Add channel-specific suggestions
|
214
214
|
suggestions = kwargs.get("suggestions", [])
|
215
215
|
if channel == "whatsapp":
|
@@ -230,9 +230,9 @@ class TwilioSendError(TwilioError):
|
|
230
230
|
"Check if sender email is verified in SendGrid",
|
231
231
|
"Verify recipient email format"
|
232
232
|
])
|
233
|
-
|
233
|
+
|
234
234
|
kwargs["suggestions"] = suggestions
|
235
|
-
|
235
|
+
|
236
236
|
super().__init__(message, **kwargs)
|
237
237
|
|
238
238
|
|
@@ -245,7 +245,7 @@ class TwilioRateLimitError(TwilioSendError):
|
|
245
245
|
- SendGrid rate limits are exceeded
|
246
246
|
- Too many requests in a time window
|
247
247
|
"""
|
248
|
-
|
248
|
+
|
249
249
|
def __init__(
|
250
250
|
self,
|
251
251
|
message: str,
|
@@ -261,12 +261,12 @@ class TwilioRateLimitError(TwilioSendError):
|
|
261
261
|
**kwargs: Additional context passed to base class
|
262
262
|
"""
|
263
263
|
context = kwargs.get("context", {})
|
264
|
-
|
264
|
+
|
265
265
|
if retry_after:
|
266
266
|
context["retry_after_seconds"] = retry_after
|
267
|
-
|
267
|
+
|
268
268
|
kwargs["context"] = context
|
269
|
-
|
269
|
+
|
270
270
|
suggestions = kwargs.get("suggestions", [])
|
271
271
|
suggestions.extend([
|
272
272
|
f"Wait {retry_after} seconds before retrying" if retry_after else "Wait before retrying",
|
@@ -274,7 +274,7 @@ class TwilioRateLimitError(TwilioSendError):
|
|
274
274
|
"Consider upgrading Twilio plan for higher limits"
|
275
275
|
])
|
276
276
|
kwargs["suggestions"] = suggestions
|
277
|
-
|
277
|
+
|
278
278
|
super().__init__(message, **kwargs)
|
279
279
|
|
280
280
|
|
@@ -288,7 +288,7 @@ class TwilioNetworkError(TwilioError):
|
|
288
288
|
- DNS resolution failures
|
289
289
|
- Timeout errors
|
290
290
|
"""
|
291
|
-
|
291
|
+
|
292
292
|
def __init__(
|
293
293
|
self,
|
294
294
|
message: str,
|
@@ -306,14 +306,14 @@ class TwilioNetworkError(TwilioError):
|
|
306
306
|
**kwargs: Additional context passed to base class
|
307
307
|
"""
|
308
308
|
context = kwargs.get("context", {})
|
309
|
-
|
309
|
+
|
310
310
|
if service:
|
311
311
|
context["service"] = service
|
312
312
|
if timeout:
|
313
313
|
context["timeout_seconds"] = timeout
|
314
|
-
|
314
|
+
|
315
315
|
kwargs["context"] = context
|
316
|
-
|
316
|
+
|
317
317
|
suggestions = kwargs.get("suggestions", [])
|
318
318
|
suggestions.extend([
|
319
319
|
"Check internet connectivity",
|
@@ -322,7 +322,7 @@ class TwilioNetworkError(TwilioError):
|
|
322
322
|
"Check Twilio/SendGrid service status"
|
323
323
|
])
|
324
324
|
kwargs["suggestions"] = suggestions
|
325
|
-
|
325
|
+
|
326
326
|
super().__init__(message, **kwargs)
|
327
327
|
|
328
328
|
|
@@ -330,7 +330,7 @@ class TwilioNetworkError(TwilioError):
|
|
330
330
|
__all__ = [
|
331
331
|
"TwilioError",
|
332
332
|
"TwilioConfigurationError",
|
333
|
-
"TwilioVerificationError",
|
333
|
+
"TwilioVerificationError",
|
334
334
|
"TwilioSendError",
|
335
335
|
"TwilioRateLimitError",
|
336
336
|
"TwilioNetworkError",
|
@@ -5,9 +5,8 @@ Tests Twilio messaging functionality using django_cfg configuration.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
from django.core.management.base import BaseCommand
|
8
|
-
from django_cfg.modules.django_logging import get_logger
|
9
|
-
|
10
8
|
|
9
|
+
from django_cfg.modules.django_logging import get_logger
|
11
10
|
|
12
11
|
logger = get_logger('test_twilio')
|
13
12
|
|
@@ -57,10 +56,10 @@ class Command(BaseCommand):
|
|
57
56
|
try:
|
58
57
|
from django_cfg.modules.django_twilio import SimpleTwilioService
|
59
58
|
twilio_service = SimpleTwilioService()
|
60
|
-
|
59
|
+
|
61
60
|
if is_whatsapp:
|
62
61
|
self.stdout.write(f"\n📱 Sending WhatsApp message to {to_number}...")
|
63
|
-
|
62
|
+
|
64
63
|
if content_sid:
|
65
64
|
# Send with template
|
66
65
|
result = twilio_service.send_whatsapp_message(
|
@@ -86,13 +85,13 @@ class Command(BaseCommand):
|
|
86
85
|
self.stdout.write(self.style.SUCCESS("✅ SMS message sent!"))
|
87
86
|
|
88
87
|
# Show result details
|
89
|
-
self.stdout.write(
|
88
|
+
self.stdout.write("\n📊 Message Details:")
|
90
89
|
self.stdout.write(f" SID: {result['sid']}")
|
91
90
|
self.stdout.write(f" Status: {result['status']}")
|
92
91
|
self.stdout.write(f" To: {result['to']}")
|
93
92
|
self.stdout.write(f" From: {result['from']}")
|
94
93
|
self.stdout.write(f" Created: {result['date_created']}")
|
95
|
-
|
94
|
+
|
96
95
|
if result.get('price'):
|
97
96
|
self.stdout.write(f" Price: {result['price']} {result['price_unit']}")
|
98
97
|
|
@@ -101,7 +100,7 @@ class Command(BaseCommand):
|
|
101
100
|
except ImportError as e:
|
102
101
|
self.stdout.write(self.style.ERROR(f"\n❌ Twilio dependencies not installed: {e}"))
|
103
102
|
self.stdout.write("💡 Install with: pip install twilio")
|
104
|
-
|
103
|
+
|
105
104
|
except Exception as e:
|
106
105
|
self.stdout.write(self.style.ERROR(f"\n❌ Failed to send message: {e}"))
|
107
106
|
self.stdout.write("\n💡 Troubleshooting:")
|
@@ -8,9 +8,10 @@ Following CRITICAL_REQUIREMENTS.md:
|
|
8
8
|
- Comprehensive validation and error handling
|
9
9
|
"""
|
10
10
|
|
11
|
-
from typing import Optional, Dict, Any, List, Literal
|
12
|
-
from pydantic import BaseModel, Field, field_validator, model_validator, SecretStr
|
13
11
|
from enum import Enum
|
12
|
+
from typing import Any, Dict, List, Optional
|
13
|
+
|
14
|
+
from pydantic import BaseModel, Field, SecretStr, field_validator, model_validator
|
14
15
|
|
15
16
|
from django_cfg.modules.django_twilio.exceptions import TwilioConfigurationError
|
16
17
|
|
@@ -43,13 +44,13 @@ class TwilioVerifyConfig(BaseModel):
|
|
43
44
|
|
44
45
|
Handles OTP verification across multiple channels with smart fallbacks.
|
45
46
|
"""
|
46
|
-
|
47
|
+
|
47
48
|
model_config = {
|
48
49
|
"str_strip_whitespace": True,
|
49
50
|
"validate_assignment": True,
|
50
51
|
"extra": "forbid",
|
51
52
|
}
|
52
|
-
|
53
|
+
|
53
54
|
# Core Verify service settings
|
54
55
|
service_sid: str = Field(
|
55
56
|
...,
|
@@ -58,26 +59,26 @@ class TwilioVerifyConfig(BaseModel):
|
|
58
59
|
max_length=34,
|
59
60
|
pattern=r"^VA[a-f0-9]{32}$",
|
60
61
|
)
|
61
|
-
|
62
|
+
|
62
63
|
service_name: str = Field(
|
63
64
|
default="OTP Verification",
|
64
65
|
description="Human-readable service name for OTP messages",
|
65
66
|
min_length=1,
|
66
67
|
max_length=50,
|
67
68
|
)
|
68
|
-
|
69
|
+
|
69
70
|
# Channel configuration
|
70
71
|
default_channel: TwilioChannelType = Field(
|
71
72
|
default=TwilioChannelType.SMS,
|
72
73
|
description="Default channel for OTP delivery",
|
73
74
|
)
|
74
|
-
|
75
|
+
|
75
76
|
fallback_channels: List[TwilioChannelType] = Field(
|
76
77
|
default_factory=lambda: [TwilioChannelType.SMS],
|
77
78
|
description="Fallback channels if primary channel fails",
|
78
79
|
min_length=1,
|
79
80
|
)
|
80
|
-
|
81
|
+
|
81
82
|
# OTP settings
|
82
83
|
code_length: int = Field(
|
83
84
|
default=6,
|
@@ -85,21 +86,21 @@ class TwilioVerifyConfig(BaseModel):
|
|
85
86
|
ge=4,
|
86
87
|
le=10,
|
87
88
|
)
|
88
|
-
|
89
|
+
|
89
90
|
ttl_seconds: int = Field(
|
90
91
|
default=600, # 10 minutes
|
91
92
|
description="Time-to-live for OTP codes in seconds",
|
92
93
|
ge=60, # Minimum 1 minute
|
93
94
|
le=3600, # Maximum 1 hour
|
94
95
|
)
|
95
|
-
|
96
|
+
|
96
97
|
max_attempts: int = Field(
|
97
98
|
default=5,
|
98
99
|
description="Maximum verification attempts per code",
|
99
100
|
ge=1,
|
100
101
|
le=10,
|
101
102
|
)
|
102
|
-
|
103
|
+
|
103
104
|
# Rate limiting
|
104
105
|
rate_limit_per_phone: int = Field(
|
105
106
|
default=5,
|
@@ -107,14 +108,14 @@ class TwilioVerifyConfig(BaseModel):
|
|
107
108
|
ge=1,
|
108
109
|
le=20,
|
109
110
|
)
|
110
|
-
|
111
|
+
|
111
112
|
rate_limit_per_ip: int = Field(
|
112
113
|
default=10,
|
113
114
|
description="Maximum OTP requests per IP address per hour",
|
114
115
|
ge=1,
|
115
116
|
le=50,
|
116
117
|
)
|
117
|
-
|
118
|
+
|
118
119
|
@field_validator("fallback_channels")
|
119
120
|
@classmethod
|
120
121
|
def validate_fallback_channels(cls, v: List[TwilioChannelType]) -> List[TwilioChannelType]:
|
@@ -130,13 +131,13 @@ class SendGridConfig(BaseModel):
|
|
130
131
|
|
131
132
|
Handles email OTP delivery with template support and deliverability optimization.
|
132
133
|
"""
|
133
|
-
|
134
|
+
|
134
135
|
model_config = {
|
135
136
|
"str_strip_whitespace": True,
|
136
137
|
"validate_assignment": True,
|
137
138
|
"extra": "forbid",
|
138
139
|
}
|
139
|
-
|
140
|
+
|
140
141
|
# Core SendGrid settings
|
141
142
|
api_key: SecretStr = Field(
|
142
143
|
...,
|
@@ -144,32 +145,32 @@ class SendGridConfig(BaseModel):
|
|
144
145
|
min_length=69, # SendGrid API keys are 69 characters
|
145
146
|
max_length=69,
|
146
147
|
)
|
147
|
-
|
148
|
+
|
148
149
|
from_email: str = Field(
|
149
150
|
...,
|
150
151
|
description="Verified sender email address",
|
151
152
|
pattern=r"^[^@]+@[^@]+\.[^@]+$",
|
152
153
|
)
|
153
|
-
|
154
|
+
|
154
155
|
from_name: str = Field(
|
155
156
|
default="OTP Service",
|
156
157
|
description="Sender name displayed in emails",
|
157
158
|
min_length=1,
|
158
159
|
max_length=100,
|
159
160
|
)
|
160
|
-
|
161
|
+
|
161
162
|
# Template configuration
|
162
163
|
otp_template_id: Optional[str] = Field(
|
163
164
|
default=None,
|
164
165
|
description="SendGrid dynamic template ID for OTP emails",
|
165
166
|
pattern=r"^d-[a-f0-9]{32}$",
|
166
167
|
)
|
167
|
-
|
168
|
+
|
168
169
|
template_type: SendGridTemplateType = Field(
|
169
170
|
default=SendGridTemplateType.DYNAMIC,
|
170
171
|
description="Type of SendGrid template to use",
|
171
172
|
)
|
172
|
-
|
173
|
+
|
173
174
|
# Email content settings (used when no template is specified)
|
174
175
|
default_subject: str = Field(
|
175
176
|
default="Your verification code",
|
@@ -177,25 +178,25 @@ class SendGridConfig(BaseModel):
|
|
177
178
|
min_length=1,
|
178
179
|
max_length=200,
|
179
180
|
)
|
180
|
-
|
181
|
+
|
181
182
|
# Deliverability settings
|
182
183
|
reply_to_email: Optional[str] = Field(
|
183
184
|
default=None,
|
184
185
|
description="Reply-to email address",
|
185
186
|
pattern=r"^[^@]+@[^@]+\.[^@]+$",
|
186
187
|
)
|
187
|
-
|
188
|
+
|
188
189
|
tracking_enabled: bool = Field(
|
189
190
|
default=True,
|
190
191
|
description="Enable email open and click tracking",
|
191
192
|
)
|
192
|
-
|
193
|
+
|
193
194
|
# Template data customization
|
194
195
|
custom_template_data: Dict[str, Any] = Field(
|
195
196
|
default_factory=dict,
|
196
197
|
description="Additional data to pass to email templates",
|
197
198
|
)
|
198
|
-
|
199
|
+
|
199
200
|
@field_validator("api_key")
|
200
201
|
@classmethod
|
201
202
|
def validate_api_key(cls, v: SecretStr) -> SecretStr:
|
@@ -213,14 +214,14 @@ class TwilioConfig(BaseModel):
|
|
213
214
|
Provides type-safe configuration for all Twilio services including
|
214
215
|
Verify API, WhatsApp, SMS, and SendGrid email integration.
|
215
216
|
"""
|
216
|
-
|
217
|
+
|
217
218
|
model_config = {
|
218
219
|
"str_strip_whitespace": True,
|
219
220
|
"validate_assignment": True,
|
220
221
|
"extra": "forbid",
|
221
222
|
"validate_default": True,
|
222
223
|
}
|
223
|
-
|
224
|
+
|
224
225
|
# Core Twilio credentials
|
225
226
|
account_sid: str = Field(
|
226
227
|
...,
|
@@ -229,48 +230,48 @@ class TwilioConfig(BaseModel):
|
|
229
230
|
max_length=34,
|
230
231
|
pattern=r"^AC[a-f0-9]{32}$",
|
231
232
|
)
|
232
|
-
|
233
|
+
|
233
234
|
auth_token: SecretStr = Field(
|
234
235
|
...,
|
235
236
|
description="Twilio Auth Token",
|
236
237
|
min_length=32,
|
237
238
|
max_length=32,
|
238
239
|
)
|
239
|
-
|
240
|
+
|
240
241
|
# Service configuration
|
241
242
|
verify: Optional[TwilioVerifyConfig] = Field(
|
242
243
|
default=None,
|
243
244
|
description="Twilio Verify service configuration for OTP",
|
244
245
|
)
|
245
|
-
|
246
|
+
|
246
247
|
sendgrid: Optional[SendGridConfig] = Field(
|
247
248
|
default=None,
|
248
249
|
description="SendGrid email service configuration",
|
249
250
|
)
|
250
|
-
|
251
|
+
|
251
252
|
# Global settings
|
252
253
|
region: TwilioRegion = Field(
|
253
254
|
default=TwilioRegion.US,
|
254
255
|
description="Twilio service region for compliance and performance",
|
255
256
|
)
|
256
|
-
|
257
|
+
|
257
258
|
webhook_url: Optional[str] = Field(
|
258
259
|
default=None,
|
259
260
|
description="Webhook URL for delivery status callbacks",
|
260
261
|
pattern=r"^https?://[^\s]+$",
|
261
262
|
)
|
262
|
-
|
263
|
+
|
263
264
|
# Debug and testing
|
264
265
|
test_mode: bool = Field(
|
265
266
|
default=False,
|
266
267
|
description="Enable test mode (uses Twilio test credentials)",
|
267
268
|
)
|
268
|
-
|
269
|
+
|
269
270
|
debug_logging: bool = Field(
|
270
271
|
default=False,
|
271
272
|
description="Enable detailed logging for debugging",
|
272
273
|
)
|
273
|
-
|
274
|
+
|
274
275
|
# Timeout settings
|
275
276
|
request_timeout: int = Field(
|
276
277
|
default=30,
|
@@ -278,7 +279,7 @@ class TwilioConfig(BaseModel):
|
|
278
279
|
ge=5,
|
279
280
|
le=300,
|
280
281
|
)
|
281
|
-
|
282
|
+
|
282
283
|
# Retry configuration
|
283
284
|
max_retries: int = Field(
|
284
285
|
default=3,
|
@@ -286,14 +287,14 @@ class TwilioConfig(BaseModel):
|
|
286
287
|
ge=0,
|
287
288
|
le=10,
|
288
289
|
)
|
289
|
-
|
290
|
+
|
290
291
|
retry_delay: float = Field(
|
291
292
|
default=1.0,
|
292
293
|
description="Base delay between retries in seconds",
|
293
294
|
ge=0.1,
|
294
295
|
le=60.0,
|
295
296
|
)
|
296
|
-
|
297
|
+
|
297
298
|
@model_validator(mode="after")
|
298
299
|
def validate_service_configuration(self) -> "TwilioConfig":
|
299
300
|
"""Validate service configuration - allow basic messaging without services."""
|
@@ -309,10 +310,10 @@ class TwilioConfig(BaseModel):
|
|
309
310
|
context={"enabled_channels": [ch.value for ch in all_channels]},
|
310
311
|
suggestions=["Configure SendGrid settings for email OTP delivery"]
|
311
312
|
)
|
312
|
-
|
313
|
+
|
313
314
|
return self
|
314
|
-
|
315
|
-
|
315
|
+
|
316
|
+
|
316
317
|
def get_client_config(self) -> Dict[str, Any]:
|
317
318
|
"""
|
318
319
|
Get configuration for Twilio client initialization.
|
@@ -325,12 +326,12 @@ class TwilioConfig(BaseModel):
|
|
325
326
|
"password": self.auth_token.get_secret_value(),
|
326
327
|
"region": self.region.value,
|
327
328
|
}
|
328
|
-
|
329
|
+
|
329
330
|
if self.webhook_url:
|
330
331
|
config["webhook_url"] = self.webhook_url
|
331
|
-
|
332
|
+
|
332
333
|
return config
|
333
|
-
|
334
|
+
|
334
335
|
def get_sendgrid_config(self) -> Optional[Dict[str, Any]]:
|
335
336
|
"""
|
336
337
|
Get configuration for SendGrid client initialization.
|
@@ -340,7 +341,7 @@ class TwilioConfig(BaseModel):
|
|
340
341
|
"""
|
341
342
|
if not self.sendgrid:
|
342
343
|
return None
|
343
|
-
|
344
|
+
|
344
345
|
return {
|
345
346
|
"api_key": self.sendgrid.api_key.get_secret_value(),
|
346
347
|
"from_email": self.sendgrid.from_email,
|
@@ -348,7 +349,7 @@ class TwilioConfig(BaseModel):
|
|
348
349
|
"template_id": self.sendgrid.otp_template_id,
|
349
350
|
"tracking_enabled": self.sendgrid.tracking_enabled,
|
350
351
|
}
|
351
|
-
|
352
|
+
|
352
353
|
def is_channel_enabled(self, channel: TwilioChannelType) -> bool:
|
353
354
|
"""
|
354
355
|
Check if a specific channel is enabled in the configuration.
|
@@ -362,14 +363,14 @@ class TwilioConfig(BaseModel):
|
|
362
363
|
# Check email channel separately (SendGrid)
|
363
364
|
if channel == TwilioChannelType.EMAIL:
|
364
365
|
return self.sendgrid is not None
|
365
|
-
|
366
|
+
|
366
367
|
# Check Verify channels (WhatsApp, SMS, Voice)
|
367
368
|
if not self.verify:
|
368
369
|
return False
|
369
|
-
|
370
|
+
|
370
371
|
all_channels = [self.verify.default_channel] + self.verify.fallback_channels
|
371
372
|
return channel in all_channels
|
372
|
-
|
373
|
+
|
373
374
|
def get_enabled_channels(self) -> List[TwilioChannelType]:
|
374
375
|
"""
|
375
376
|
Get list of all enabled channels.
|
@@ -378,14 +379,14 @@ class TwilioConfig(BaseModel):
|
|
378
379
|
List of enabled channel types
|
379
380
|
"""
|
380
381
|
channels = []
|
381
|
-
|
382
|
+
|
382
383
|
if self.verify:
|
383
384
|
channels.append(self.verify.default_channel)
|
384
385
|
channels.extend(self.verify.fallback_channels)
|
385
|
-
|
386
|
+
|
386
387
|
if self.sendgrid and TwilioChannelType.EMAIL not in channels:
|
387
388
|
channels.append(TwilioChannelType.EMAIL)
|
388
|
-
|
389
|
+
|
389
390
|
# Remove duplicates while preserving order
|
390
391
|
seen = set()
|
391
392
|
unique_channels = []
|
@@ -393,14 +394,14 @@ class TwilioConfig(BaseModel):
|
|
393
394
|
if channel not in seen:
|
394
395
|
seen.add(channel)
|
395
396
|
unique_channels.append(channel)
|
396
|
-
|
397
|
+
|
397
398
|
return unique_channels
|
398
399
|
|
399
400
|
|
400
401
|
# Export configuration models
|
401
402
|
__all__ = [
|
402
403
|
"TwilioConfig",
|
403
|
-
"TwilioVerifyConfig",
|
404
|
+
"TwilioVerifyConfig",
|
404
405
|
"SendGridConfig",
|
405
406
|
"TwilioChannelType",
|
406
407
|
"TwilioRegion",
|