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
@@ -10,21 +10,19 @@ Handles all SendGrid-specific functionality including:
|
|
10
10
|
import logging
|
11
11
|
import random
|
12
12
|
import string
|
13
|
-
from typing import Optional, Dict, Any, Tuple
|
14
13
|
from datetime import datetime, timedelta
|
14
|
+
from typing import Any, Dict, Optional, Tuple
|
15
15
|
|
16
|
-
from sendgrid import SendGridAPIClient
|
17
|
-
from sendgrid.helpers.mail import Mail, From
|
18
|
-
from asgiref.sync import sync_to_async
|
19
16
|
from django.template.loader import render_to_string
|
20
|
-
from
|
17
|
+
from sendgrid import SendGridAPIClient
|
18
|
+
from sendgrid.helpers.mail import Mail
|
21
19
|
|
22
20
|
from django_cfg.modules.base import BaseCfgModule
|
23
|
-
from django_cfg.modules.django_twilio.models import TwilioConfig, SendGridConfig
|
24
21
|
from django_cfg.modules.django_twilio.exceptions import (
|
25
22
|
TwilioConfigurationError,
|
26
23
|
TwilioSendError,
|
27
24
|
)
|
25
|
+
from django_cfg.modules.django_twilio.models import SendGridConfig, TwilioConfig
|
28
26
|
|
29
27
|
try:
|
30
28
|
from django_cfg.apps.accounts.models import CustomUser
|
@@ -40,14 +38,14 @@ class SendGridService(BaseCfgModule):
|
|
40
38
|
|
41
39
|
Handles email operations with auto-configuration from DjangoConfig.
|
42
40
|
"""
|
43
|
-
|
41
|
+
|
44
42
|
def __init__(self):
|
45
43
|
"""Initialize with auto-discovered configuration."""
|
46
44
|
super().__init__()
|
47
45
|
self._twilio_config: Optional[TwilioConfig] = None
|
48
46
|
self._client: Optional[SendGridAPIClient] = None
|
49
47
|
self._otp_storage: Dict[str, Dict[str, Any]] = {} # In-memory storage for OTP codes
|
50
|
-
|
48
|
+
|
51
49
|
def get_twilio_config(self) -> TwilioConfig:
|
52
50
|
"""Get Twilio configuration (which includes SendGrid config)."""
|
53
51
|
if self._twilio_config is None:
|
@@ -57,7 +55,7 @@ class SendGridService(BaseCfgModule):
|
|
57
55
|
"DjangoConfig instance not found",
|
58
56
|
suggestions=["Ensure DjangoConfig is properly initialized"]
|
59
57
|
)
|
60
|
-
|
58
|
+
|
61
59
|
twilio_config = getattr(django_config, 'twilio', None)
|
62
60
|
if not twilio_config:
|
63
61
|
raise TwilioConfigurationError(
|
@@ -65,46 +63,46 @@ class SendGridService(BaseCfgModule):
|
|
65
63
|
missing_fields=["twilio"],
|
66
64
|
suggestions=["Add TwilioConfig to your DjangoConfig class"]
|
67
65
|
)
|
68
|
-
|
66
|
+
|
69
67
|
self._twilio_config = twilio_config
|
70
|
-
|
68
|
+
|
71
69
|
return self._twilio_config
|
72
|
-
|
70
|
+
|
73
71
|
def get_sendgrid_config(self) -> SendGridConfig:
|
74
72
|
"""Get SendGrid configuration."""
|
75
73
|
config = self.get_twilio_config()
|
76
|
-
|
74
|
+
|
77
75
|
if not config.sendgrid:
|
78
76
|
raise TwilioConfigurationError(
|
79
77
|
"SendGrid configuration not found",
|
80
78
|
missing_fields=["sendgrid"],
|
81
79
|
suggestions=["Configure SendGridConfig in your Twilio settings"]
|
82
80
|
)
|
83
|
-
|
81
|
+
|
84
82
|
return config.sendgrid
|
85
|
-
|
83
|
+
|
86
84
|
def get_client(self) -> SendGridAPIClient:
|
87
85
|
"""Get or create SendGrid client."""
|
88
86
|
if self._client is None:
|
89
87
|
config = self.get_sendgrid_config()
|
90
|
-
|
88
|
+
|
91
89
|
try:
|
92
90
|
self._client = SendGridAPIClient(
|
93
91
|
api_key=config.api_key.get_secret_value()
|
94
92
|
)
|
95
|
-
|
93
|
+
|
96
94
|
logger.info("SendGrid client initialized")
|
97
|
-
|
95
|
+
|
98
96
|
except Exception as e:
|
99
97
|
raise TwilioConfigurationError(
|
100
98
|
f"Failed to initialize SendGrid client: {str(e)}",
|
101
99
|
suggestions=["Check SendGrid API key configuration"]
|
102
100
|
)
|
103
|
-
|
101
|
+
|
104
102
|
return self._client
|
105
|
-
|
103
|
+
|
106
104
|
# === Email Methods ===
|
107
|
-
|
105
|
+
|
108
106
|
def send_email(
|
109
107
|
self,
|
110
108
|
to_email: str,
|
@@ -131,11 +129,11 @@ class SendGridService(BaseCfgModule):
|
|
131
129
|
try:
|
132
130
|
client = self.get_client()
|
133
131
|
config = self.get_sendgrid_config()
|
134
|
-
|
132
|
+
|
135
133
|
# Use config defaults if not provided
|
136
134
|
sender_email = from_email or config.from_email
|
137
135
|
sender_name = from_name or config.from_name
|
138
|
-
|
136
|
+
|
139
137
|
message = Mail(
|
140
138
|
from_email=(sender_email, sender_name),
|
141
139
|
to_emails=to_email,
|
@@ -143,35 +141,35 @@ class SendGridService(BaseCfgModule):
|
|
143
141
|
html_content=html_content,
|
144
142
|
plain_text_content=plain_content
|
145
143
|
)
|
146
|
-
|
144
|
+
|
147
145
|
if config.reply_to_email:
|
148
146
|
message.reply_to = config.reply_to_email
|
149
|
-
|
147
|
+
|
150
148
|
response = client.send(message)
|
151
|
-
|
149
|
+
|
152
150
|
result = {
|
153
151
|
'status_code': response.status_code,
|
154
152
|
'success': response.status_code in [200, 201, 202],
|
155
153
|
'to_email': to_email,
|
156
154
|
'subject': subject,
|
157
155
|
}
|
158
|
-
|
156
|
+
|
159
157
|
if result['success']:
|
160
158
|
logger.info(f"Email sent successfully to {self._mask_email(to_email)}")
|
161
159
|
else:
|
162
160
|
logger.error(f"SendGrid API error: {response.status_code}")
|
163
|
-
|
161
|
+
|
164
162
|
return result
|
165
|
-
|
163
|
+
|
166
164
|
except Exception as e:
|
167
165
|
logger.error(f"Failed to send email: {e}")
|
168
166
|
raise TwilioSendError(
|
169
167
|
f"Failed to send email: {str(e)}",
|
170
168
|
context={'to_email': to_email, 'subject': subject}
|
171
169
|
)
|
172
|
-
|
170
|
+
|
173
171
|
# === OTP Methods ===
|
174
|
-
|
172
|
+
|
175
173
|
def send_otp_email(
|
176
174
|
self,
|
177
175
|
email: str,
|
@@ -194,14 +192,14 @@ class SendGridService(BaseCfgModule):
|
|
194
192
|
try:
|
195
193
|
client = self.get_client()
|
196
194
|
config = self.get_sendgrid_config()
|
197
|
-
|
195
|
+
|
198
196
|
# Use provided OTP code or generate new one
|
199
197
|
if not otp_code:
|
200
198
|
otp_code = self._generate_otp(6)
|
201
199
|
# Store OTP for verification (10 minutes TTL)
|
202
200
|
self._store_otp(email, otp_code, 600)
|
203
201
|
# If OTP code is provided, don't store it (it's already in database)
|
204
|
-
|
202
|
+
|
205
203
|
# Prepare email content
|
206
204
|
if config.otp_template_id:
|
207
205
|
# Use dynamic template
|
@@ -213,13 +211,13 @@ class SendGridService(BaseCfgModule):
|
|
213
211
|
success, message = self._send_simple_otp_email(
|
214
212
|
client, config, email, otp_code, subject
|
215
213
|
)
|
216
|
-
|
214
|
+
|
217
215
|
if success:
|
218
216
|
logger.info(f"Email OTP sent successfully to {self._mask_email(email)}")
|
219
217
|
return True, message, otp_code
|
220
218
|
else:
|
221
219
|
raise TwilioSendError(message)
|
222
|
-
|
220
|
+
|
223
221
|
except Exception as e:
|
224
222
|
if isinstance(e, TwilioSendError):
|
225
223
|
raise
|
@@ -227,7 +225,7 @@ class SendGridService(BaseCfgModule):
|
|
227
225
|
f"Failed to send email OTP: {e}",
|
228
226
|
context={'email': email}
|
229
227
|
) from e
|
230
|
-
|
228
|
+
|
231
229
|
def verify_otp(self, email: str, code: str) -> Tuple[bool, str]:
|
232
230
|
"""
|
233
231
|
Verify OTP code.
|
@@ -240,30 +238,30 @@ class SendGridService(BaseCfgModule):
|
|
240
238
|
Tuple[bool, str]: (is_valid, message)
|
241
239
|
"""
|
242
240
|
stored_data = self._get_stored_otp(email)
|
243
|
-
|
241
|
+
|
244
242
|
if not stored_data:
|
245
243
|
return False, "OTP not found. Please request a new code."
|
246
|
-
|
244
|
+
|
247
245
|
if datetime.now() > stored_data['expires_at']:
|
248
246
|
self._remove_otp(email)
|
249
247
|
return False, "OTP expired. Please request a new code."
|
250
|
-
|
248
|
+
|
251
249
|
# Increment attempt counter
|
252
250
|
stored_data['attempts'] += 1
|
253
|
-
|
251
|
+
|
254
252
|
if stored_data['attempts'] > 5: # Max attempts
|
255
253
|
self._remove_otp(email)
|
256
254
|
return False, "Too many attempts. Please request a new code."
|
257
|
-
|
255
|
+
|
258
256
|
if stored_data['code'] == code:
|
259
257
|
self._remove_otp(email)
|
260
258
|
logger.info(f"Email OTP verified successfully for {self._mask_email(email)}")
|
261
259
|
return True, "OTP verified successfully"
|
262
260
|
else:
|
263
261
|
return False, f"Invalid OTP code. {5 - stored_data['attempts']} attempts remaining."
|
264
|
-
|
262
|
+
|
265
263
|
# === Helper Methods ===
|
266
|
-
|
264
|
+
|
267
265
|
def _get_user_data(self, email: str) -> Tuple[str, str]:
|
268
266
|
"""
|
269
267
|
Retrieves user's full name and username from the database.
|
@@ -285,9 +283,9 @@ class SendGridService(BaseCfgModule):
|
|
285
283
|
# Fallback to email prefix
|
286
284
|
email_prefix = email.split('@')[0]
|
287
285
|
return email_prefix, email_prefix
|
288
|
-
|
286
|
+
|
289
287
|
# === Template Methods ===
|
290
|
-
|
288
|
+
|
291
289
|
def _send_template_email(
|
292
290
|
self,
|
293
291
|
client: SendGridAPIClient,
|
@@ -300,17 +298,17 @@ class SendGridService(BaseCfgModule):
|
|
300
298
|
try:
|
301
299
|
# Get config for dynamic data
|
302
300
|
cfg = self.get_config()
|
303
|
-
|
301
|
+
|
304
302
|
# Get user data for template
|
305
303
|
user_full_name, user_username = self._get_user_data(email)
|
306
|
-
|
304
|
+
|
307
305
|
# Prepare subject
|
308
306
|
subject = f"Your {cfg.project_name if cfg else 'Django CFG'} verification code"
|
309
|
-
|
307
|
+
|
310
308
|
# Prepare template data matching sendgrid_otp_email.html template
|
311
309
|
dynamic_data = {
|
312
310
|
'site_name': cfg.project_name if cfg else 'Django CFG',
|
313
|
-
'project_name': cfg.project_name if cfg else 'Django CFG',
|
311
|
+
'project_name': cfg.project_name if cfg else 'Django CFG',
|
314
312
|
'user_name': user_full_name, # Real user name
|
315
313
|
'user_email': email,
|
316
314
|
'user': {
|
@@ -325,29 +323,29 @@ class SendGridService(BaseCfgModule):
|
|
325
323
|
**config.custom_template_data,
|
326
324
|
**(template_data or {})
|
327
325
|
}
|
328
|
-
|
326
|
+
|
329
327
|
message = Mail(
|
330
328
|
from_email=(config.from_email, config.from_name),
|
331
329
|
to_emails=email
|
332
330
|
# subject is handled by dynamic template with {{{subject}}} in SendGrid Console
|
333
331
|
)
|
334
|
-
|
332
|
+
|
335
333
|
message.template_id = config.otp_template_id
|
336
334
|
message.dynamic_template_data = dynamic_data
|
337
|
-
|
335
|
+
|
338
336
|
if config.reply_to_email:
|
339
337
|
message.reply_to = config.reply_to_email
|
340
|
-
|
338
|
+
|
341
339
|
response = client.send(message)
|
342
|
-
|
340
|
+
|
343
341
|
if response.status_code in [200, 201, 202]:
|
344
342
|
return True, f"OTP sent via email template to {self._mask_email(email)}"
|
345
343
|
else:
|
346
344
|
return False, f"SendGrid API error: {response.status_code}"
|
347
|
-
|
345
|
+
|
348
346
|
except Exception as e:
|
349
347
|
return False, f"Template email error: {e}"
|
350
|
-
|
348
|
+
|
351
349
|
def _send_simple_otp_email(
|
352
350
|
self,
|
353
351
|
client: SendGridAPIClient,
|
@@ -361,7 +359,7 @@ class SendGridService(BaseCfgModule):
|
|
361
359
|
# Get current config for template context
|
362
360
|
from django_cfg.core.state import get_current_config
|
363
361
|
current_config = get_current_config()
|
364
|
-
|
362
|
+
|
365
363
|
# Prepare context for unified template
|
366
364
|
cfg = self.get_config()
|
367
365
|
context = {
|
@@ -371,11 +369,11 @@ class SendGridService(BaseCfgModule):
|
|
371
369
|
"project_name": cfg.project_name if cfg else 'Django CFG',
|
372
370
|
"user": {"username": email.split("@")[0]}, # Fallback user object
|
373
371
|
}
|
374
|
-
|
372
|
+
|
375
373
|
# Add OTP link if config is available
|
376
374
|
if current_config:
|
377
375
|
context["otp_link"] = current_config.get_otp_url(otp_code)
|
378
|
-
|
376
|
+
|
379
377
|
# Render Django templates
|
380
378
|
try:
|
381
379
|
html_content = render_to_string("emails/otp_email.html", context)
|
@@ -385,7 +383,7 @@ class SendGridService(BaseCfgModule):
|
|
385
383
|
logger.warning(f"Django template render failed: {template_error}, using fallback HTML")
|
386
384
|
html_content = self._generate_html_content(otp_code, config.from_name)
|
387
385
|
plain_content = self._generate_plain_content(otp_code)
|
388
|
-
|
386
|
+
|
389
387
|
message = Mail(
|
390
388
|
from_email=(config.from_email, config.from_name),
|
391
389
|
to_emails=email,
|
@@ -393,26 +391,26 @@ class SendGridService(BaseCfgModule):
|
|
393
391
|
html_content=html_content,
|
394
392
|
plain_text_content=plain_content
|
395
393
|
)
|
396
|
-
|
394
|
+
|
397
395
|
if config.reply_to_email:
|
398
396
|
message.reply_to = config.reply_to_email
|
399
|
-
|
397
|
+
|
400
398
|
response = client.send(message)
|
401
|
-
|
399
|
+
|
402
400
|
if response.status_code in [200, 201, 202]:
|
403
401
|
return True, f"OTP sent via email to {self._mask_email(email)}"
|
404
402
|
else:
|
405
403
|
return False, f"SendGrid API error: {response.status_code}"
|
406
|
-
|
404
|
+
|
407
405
|
except Exception as e:
|
408
406
|
return False, f"Simple email error: {e}"
|
409
|
-
|
407
|
+
|
410
408
|
# === Utility Methods ===
|
411
|
-
|
409
|
+
|
412
410
|
def _generate_otp(self, length: int = 6) -> str:
|
413
411
|
"""Generate numeric OTP code."""
|
414
412
|
return ''.join(random.choices(string.digits, k=length))
|
415
|
-
|
413
|
+
|
416
414
|
def _store_otp(self, email: str, code: str, ttl_seconds: int = 600) -> None:
|
417
415
|
"""Store OTP code with expiration."""
|
418
416
|
self._otp_storage[email] = {
|
@@ -421,15 +419,15 @@ class SendGridService(BaseCfgModule):
|
|
421
419
|
'expires_at': datetime.now() + timedelta(seconds=ttl_seconds),
|
422
420
|
'attempts': 0,
|
423
421
|
}
|
424
|
-
|
422
|
+
|
425
423
|
def _get_stored_otp(self, email: str) -> Optional[Dict[str, Any]]:
|
426
424
|
"""Get stored OTP data."""
|
427
425
|
return self._otp_storage.get(email)
|
428
|
-
|
426
|
+
|
429
427
|
def _remove_otp(self, email: str) -> None:
|
430
428
|
"""Remove OTP from storage."""
|
431
429
|
self._otp_storage.pop(email, None)
|
432
|
-
|
430
|
+
|
433
431
|
def _mask_email(self, email: str) -> str:
|
434
432
|
"""Mask email for security in logs."""
|
435
433
|
if "@" in email:
|
@@ -437,7 +435,7 @@ class SendGridService(BaseCfgModule):
|
|
437
435
|
if len(parts) == 2:
|
438
436
|
return f"{parts[0][:2]}***@{parts[1]}"
|
439
437
|
return "***"
|
440
|
-
|
438
|
+
|
441
439
|
def _generate_html_content(self, otp_code: str, company_name: str) -> str:
|
442
440
|
"""Generate HTML email content."""
|
443
441
|
return f"""
|
@@ -462,7 +460,7 @@ class SendGridService(BaseCfgModule):
|
|
462
460
|
</div>
|
463
461
|
</div>
|
464
462
|
"""
|
465
|
-
|
463
|
+
|
466
464
|
def _generate_plain_content(self, otp_code: str) -> str:
|
467
465
|
"""Generate plain text email content."""
|
468
466
|
return f"""
|
@@ -6,16 +6,17 @@ without the complexity of the OTP system.
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
import logging
|
9
|
-
from typing import
|
10
|
-
from ._imports import Client, TwilioException
|
9
|
+
from typing import Any, Dict, Optional
|
11
10
|
|
12
11
|
from django_cfg.modules.base import BaseCfgModule
|
13
|
-
from django_cfg.modules.django_twilio.models import TwilioConfig
|
14
12
|
from django_cfg.modules.django_twilio.exceptions import (
|
15
|
-
TwilioError,
|
16
13
|
TwilioConfigurationError,
|
14
|
+
TwilioError,
|
17
15
|
TwilioSendError,
|
18
16
|
)
|
17
|
+
from django_cfg.modules.django_twilio.models import TwilioConfig
|
18
|
+
|
19
|
+
from ._imports import Client, TwilioException
|
19
20
|
|
20
21
|
logger = logging.getLogger(__name__)
|
21
22
|
|
@@ -27,13 +28,13 @@ class SimpleTwilioService(BaseCfgModule):
|
|
27
28
|
Provides easy-to-use methods for sending WhatsApp and SMS messages
|
28
29
|
without the complexity of OTP verification systems.
|
29
30
|
"""
|
30
|
-
|
31
|
+
|
31
32
|
def __init__(self):
|
32
33
|
"""Initialize with auto-discovered configuration."""
|
33
34
|
super().__init__()
|
34
35
|
self._config: Optional[TwilioConfig] = None
|
35
36
|
self._client: Optional[Client] = None
|
36
|
-
|
37
|
+
|
37
38
|
def get_config(self) -> TwilioConfig:
|
38
39
|
"""Get Twilio configuration from DjangoConfig."""
|
39
40
|
if self._config is None:
|
@@ -43,7 +44,7 @@ class SimpleTwilioService(BaseCfgModule):
|
|
43
44
|
"DjangoConfig instance not found",
|
44
45
|
suggestions=["Ensure DjangoConfig is properly initialized"]
|
45
46
|
)
|
46
|
-
|
47
|
+
|
47
48
|
twilio_config = getattr(django_config, 'twilio', None)
|
48
49
|
if not twilio_config:
|
49
50
|
raise TwilioConfigurationError(
|
@@ -51,11 +52,11 @@ class SimpleTwilioService(BaseCfgModule):
|
|
51
52
|
missing_fields=["twilio"],
|
52
53
|
suggestions=["Add TwilioConfig to your DjangoConfig class"]
|
53
54
|
)
|
54
|
-
|
55
|
+
|
55
56
|
self._config = twilio_config
|
56
|
-
|
57
|
+
|
57
58
|
return self._config
|
58
|
-
|
59
|
+
|
59
60
|
def get_client(self) -> Client:
|
60
61
|
"""Get or create Twilio client."""
|
61
62
|
if self._client is None:
|
@@ -65,23 +66,23 @@ class SimpleTwilioService(BaseCfgModule):
|
|
65
66
|
config.account_sid,
|
66
67
|
config.auth_token.get_secret_value()
|
67
68
|
)
|
68
|
-
|
69
|
+
|
69
70
|
if config.debug_logging:
|
70
71
|
logger.info(f"Twilio client initialized for account: {config.account_sid[:8]}...")
|
71
|
-
|
72
|
+
|
72
73
|
except Exception as e:
|
73
74
|
raise TwilioConfigurationError(
|
74
75
|
f"Failed to initialize Twilio client: {str(e)}",
|
75
76
|
context={"account_sid": config.account_sid[:8] + "..."},
|
76
77
|
suggestions=["Verify your Twilio credentials"]
|
77
78
|
)
|
78
|
-
|
79
|
+
|
79
80
|
return self._client
|
80
|
-
|
81
|
+
|
81
82
|
def send_whatsapp_message(
|
82
|
-
self,
|
83
|
-
to: str,
|
84
|
-
body: str,
|
83
|
+
self,
|
84
|
+
to: str,
|
85
|
+
body: str,
|
85
86
|
from_number: Optional[str] = None,
|
86
87
|
content_sid: Optional[str] = None,
|
87
88
|
content_variables: Optional[Dict[str, str]] = None
|
@@ -105,23 +106,23 @@ class SimpleTwilioService(BaseCfgModule):
|
|
105
106
|
try:
|
106
107
|
client = self.get_client()
|
107
108
|
config = self.get_config()
|
108
|
-
|
109
|
+
|
109
110
|
# Ensure to number has whatsapp prefix
|
110
111
|
if not to.startswith('whatsapp:'):
|
111
112
|
to = f'whatsapp:{to}'
|
112
|
-
|
113
|
+
|
113
114
|
# Use default from number if not provided
|
114
115
|
if not from_number:
|
115
116
|
from_number = 'whatsapp:+14155238886' # Twilio sandbox
|
116
117
|
elif not from_number.startswith('whatsapp:'):
|
117
118
|
from_number = f'whatsapp:{from_number}'
|
118
|
-
|
119
|
+
|
119
120
|
# Prepare message parameters
|
120
121
|
message_params = {
|
121
122
|
'to': to,
|
122
123
|
'from_': from_number,
|
123
124
|
}
|
124
|
-
|
125
|
+
|
125
126
|
# Use content template if provided
|
126
127
|
if content_sid:
|
127
128
|
message_params['content_sid'] = content_sid
|
@@ -130,13 +131,13 @@ class SimpleTwilioService(BaseCfgModule):
|
|
130
131
|
message_params['content_variables'] = json.dumps(content_variables)
|
131
132
|
else:
|
132
133
|
message_params['body'] = body
|
133
|
-
|
134
|
+
|
134
135
|
if config.debug_logging:
|
135
136
|
logger.info(f"Sending WhatsApp message to {to[:15]}...")
|
136
|
-
|
137
|
+
|
137
138
|
# Send message
|
138
139
|
message = client.messages.create(**message_params)
|
139
|
-
|
140
|
+
|
140
141
|
result = {
|
141
142
|
'sid': message.sid,
|
142
143
|
'status': message.status,
|
@@ -147,12 +148,12 @@ class SimpleTwilioService(BaseCfgModule):
|
|
147
148
|
'price': message.price,
|
148
149
|
'price_unit': message.price_unit,
|
149
150
|
}
|
150
|
-
|
151
|
+
|
151
152
|
if config.debug_logging:
|
152
153
|
logger.info(f"WhatsApp message sent successfully: {message.sid}")
|
153
|
-
|
154
|
+
|
154
155
|
return result
|
155
|
-
|
156
|
+
|
156
157
|
except TwilioException as e:
|
157
158
|
logger.error(f"Twilio API error: {e}")
|
158
159
|
raise TwilioSendError(
|
@@ -167,11 +168,11 @@ class SimpleTwilioService(BaseCfgModule):
|
|
167
168
|
except Exception as e:
|
168
169
|
logger.error(f"Unexpected error sending WhatsApp message: {e}")
|
169
170
|
raise TwilioSendError(f"Unexpected error: {str(e)}")
|
170
|
-
|
171
|
+
|
171
172
|
def send_sms_message(
|
172
|
-
self,
|
173
|
-
to: str,
|
174
|
-
body: str,
|
173
|
+
self,
|
174
|
+
to: str,
|
175
|
+
body: str,
|
175
176
|
from_number: Optional[str] = None
|
176
177
|
) -> Dict[str, Any]:
|
177
178
|
"""
|
@@ -191,21 +192,21 @@ class SimpleTwilioService(BaseCfgModule):
|
|
191
192
|
try:
|
192
193
|
client = self.get_client()
|
193
194
|
config = self.get_config()
|
194
|
-
|
195
|
+
|
195
196
|
# Use default from number if not provided
|
196
197
|
if not from_number:
|
197
198
|
from_number = '+12297021650' # Your SMS number
|
198
|
-
|
199
|
+
|
199
200
|
if config.debug_logging:
|
200
201
|
logger.info(f"Sending SMS to {to[:10]}...")
|
201
|
-
|
202
|
+
|
202
203
|
# Send message
|
203
204
|
message = client.messages.create(
|
204
205
|
to=to,
|
205
206
|
from_=from_number,
|
206
207
|
body=body
|
207
208
|
)
|
208
|
-
|
209
|
+
|
209
210
|
result = {
|
210
211
|
'sid': message.sid,
|
211
212
|
'status': message.status,
|
@@ -216,12 +217,12 @@ class SimpleTwilioService(BaseCfgModule):
|
|
216
217
|
'price': message.price,
|
217
218
|
'price_unit': message.price_unit,
|
218
219
|
}
|
219
|
-
|
220
|
+
|
220
221
|
if config.debug_logging:
|
221
222
|
logger.info(f"SMS sent successfully: {message.sid}")
|
222
|
-
|
223
|
+
|
223
224
|
return result
|
224
|
-
|
225
|
+
|
225
226
|
except TwilioException as e:
|
226
227
|
logger.error(f"Twilio API error: {e}")
|
227
228
|
raise TwilioSendError(
|
@@ -236,7 +237,7 @@ class SimpleTwilioService(BaseCfgModule):
|
|
236
237
|
except Exception as e:
|
237
238
|
logger.error(f"Unexpected error sending SMS: {e}")
|
238
239
|
raise TwilioSendError(f"Unexpected error: {str(e)}")
|
239
|
-
|
240
|
+
|
240
241
|
def get_message_status(self, message_sid: str) -> Dict[str, Any]:
|
241
242
|
"""
|
242
243
|
Get status of a sent message.
|
@@ -250,7 +251,7 @@ class SimpleTwilioService(BaseCfgModule):
|
|
250
251
|
try:
|
251
252
|
client = self.get_client()
|
252
253
|
message = client.messages(message_sid).fetch()
|
253
|
-
|
254
|
+
|
254
255
|
return {
|
255
256
|
'sid': message.sid,
|
256
257
|
'status': message.status,
|
@@ -265,7 +266,7 @@ class SimpleTwilioService(BaseCfgModule):
|
|
265
266
|
'error_code': message.error_code,
|
266
267
|
'error_message': message.error_message,
|
267
268
|
}
|
268
|
-
|
269
|
+
|
269
270
|
except TwilioException as e:
|
270
271
|
raise TwilioError(f"Failed to get message status: {str(e)}")
|
271
272
|
|