django-cfg 1.4.21__py3-none-any.whl → 1.4.24__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 +36 -7
- 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.24.dist-info}/METADATA +1 -1
- django_cfg-1.4.24.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.24.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.21.dist-info → django_cfg-1.4.24.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.21.dist-info → django_cfg-1.4.24.dist-info}/licenses/LICENSE +0 -0
@@ -4,41 +4,37 @@ NowPayments provider implementation for Universal Payment System v2.0.
|
|
4
4
|
Enhanced crypto payment provider with currency synchronization.
|
5
5
|
"""
|
6
6
|
|
7
|
-
import requests
|
8
7
|
import hashlib
|
9
8
|
import hmac
|
10
|
-
from typing import Optional, List, Dict, Any
|
11
|
-
from decimal import Decimal
|
12
9
|
from datetime import datetime
|
10
|
+
from decimal import Decimal
|
11
|
+
from typing import Any, Dict, Optional
|
13
12
|
|
14
13
|
from django_cfg.modules.django_logging import get_logger
|
15
|
-
|
16
|
-
from ..models import PaymentRequest
|
14
|
+
|
17
15
|
from ...types import ProviderResponse, ServiceOperationResult
|
18
|
-
from
|
19
|
-
NowPaymentsProviderConfig,
|
20
|
-
NowPaymentsCurrency,
|
21
|
-
NowPaymentsFullCurrenciesResponse
|
22
|
-
)
|
16
|
+
from ..base import BaseProvider
|
23
17
|
from ..models import (
|
24
|
-
|
18
|
+
CurrencySyncResult,
|
19
|
+
PaymentRequest,
|
25
20
|
UniversalCurrenciesResponse,
|
26
|
-
|
21
|
+
UniversalCurrency,
|
27
22
|
)
|
28
|
-
from .sync import NowPaymentsCurrencySync
|
29
|
-
from .parsers import NowPaymentsCurrencyParser
|
30
23
|
from .config import NowPaymentsConfig as Config
|
24
|
+
from .models import NowPaymentsProviderConfig
|
25
|
+
from .parsers import NowPaymentsCurrencyParser
|
26
|
+
from .sync import NowPaymentsCurrencySync
|
31
27
|
|
32
28
|
logger = get_logger("nowpayments")
|
33
29
|
|
34
30
|
|
35
31
|
class NowPaymentsProvider(BaseProvider):
|
36
32
|
"""NowPayments cryptocurrency payment provider."""
|
37
|
-
|
33
|
+
|
38
34
|
# Map NowPayments status to universal status
|
39
35
|
STATUS_MAPPING = {
|
40
36
|
'waiting': 'pending',
|
41
|
-
'confirming': 'processing',
|
37
|
+
'confirming': 'processing',
|
42
38
|
'confirmed': 'completed',
|
43
39
|
'sending': 'processing',
|
44
40
|
'partially_paid': 'pending',
|
@@ -47,49 +43,49 @@ class NowPaymentsProvider(BaseProvider):
|
|
47
43
|
'refunded': 'refunded',
|
48
44
|
'expired': 'expired'
|
49
45
|
}
|
50
|
-
|
46
|
+
|
51
47
|
def __init__(self, config: NowPaymentsProviderConfig):
|
52
48
|
"""Initialize NowPayments provider."""
|
53
49
|
super().__init__(config)
|
54
50
|
self.config: NowPaymentsProviderConfig = config
|
55
51
|
self.sync_service = NowPaymentsCurrencySync(self.name)
|
56
52
|
self.parser = NowPaymentsCurrencyParser()
|
57
|
-
|
53
|
+
|
58
54
|
# Log initialization
|
59
55
|
api_key_str = str(self.config.api_key)
|
60
56
|
if hasattr(self.config.api_key, 'get_secret_value'):
|
61
57
|
api_key_str = self.config.api_key.get_secret_value()
|
62
|
-
|
58
|
+
|
63
59
|
logger.info(
|
64
60
|
f"🔑 NowPayments initialized: api_key={api_key_str[:10]}..., "
|
65
61
|
f"sandbox={self.is_sandbox}, base_url={self.config.api_url}"
|
66
62
|
)
|
67
|
-
|
63
|
+
|
68
64
|
# Override BaseProvider configuration methods
|
69
65
|
def get_fee_percentage(self, currency_code: str = None, currency_type: str = None) -> Decimal:
|
70
66
|
"""Get NowPayments fee percentage."""
|
71
67
|
return Config.FEE_PERCENTAGE
|
72
|
-
|
68
|
+
|
73
69
|
def get_fixed_fee_usd(self, currency_code: str = None, currency_type: str = None) -> Decimal:
|
74
70
|
"""Get NowPayments fixed fee."""
|
75
71
|
return Config.FIXED_FEE_USD
|
76
|
-
|
72
|
+
|
77
73
|
def get_min_amount_usd(self, currency_code: str = None, currency_type: str = None, is_stable: bool = False) -> Decimal:
|
78
74
|
"""Get NowPayments minimum amount."""
|
79
75
|
return Config.get_min_amount()
|
80
|
-
|
76
|
+
|
81
77
|
def get_max_amount_usd(self, currency_code: str = None, currency_type: str = None) -> Decimal:
|
82
78
|
"""Get NowPayments maximum amount."""
|
83
79
|
return Config.MAX_AMOUNT_USD
|
84
|
-
|
80
|
+
|
85
81
|
def get_confirmation_blocks(self, network_code: str) -> int:
|
86
82
|
"""Get confirmation blocks for network."""
|
87
83
|
return Config.get_confirmation_blocks(network_code)
|
88
|
-
|
84
|
+
|
89
85
|
def get_network_name(self, network_code: str) -> str:
|
90
86
|
"""Get human-readable network name."""
|
91
87
|
return Config.get_network_name(network_code)
|
92
|
-
|
88
|
+
|
93
89
|
def create_payment(self, request: PaymentRequest) -> ProviderResponse:
|
94
90
|
"""Create payment with NowPayments."""
|
95
91
|
try:
|
@@ -98,10 +94,10 @@ class NowPaymentsProvider(BaseProvider):
|
|
98
94
|
'currency': request.currency_code,
|
99
95
|
'order_id': request.order_id
|
100
96
|
})
|
101
|
-
|
97
|
+
|
102
98
|
# Use provider_currency_code from metadata if available, otherwise use original currency_code
|
103
99
|
provider_currency_code = request.metadata.get('provider_currency_code', request.currency_code)
|
104
|
-
|
100
|
+
|
105
101
|
# Prepare NowPayments request
|
106
102
|
payment_data = {
|
107
103
|
'price_amount': request.amount_usd,
|
@@ -110,7 +106,7 @@ class NowPaymentsProvider(BaseProvider):
|
|
110
106
|
'order_id': request.order_id,
|
111
107
|
'order_description': request.description or f'Payment {request.order_id}',
|
112
108
|
}
|
113
|
-
|
109
|
+
|
114
110
|
# Log the request data for debugging
|
115
111
|
self.logger.info("NowPayments request data", extra={
|
116
112
|
'payment_data': payment_data,
|
@@ -119,33 +115,33 @@ class NowPaymentsProvider(BaseProvider):
|
|
119
115
|
'request_amount_usd': request.amount_usd,
|
120
116
|
'request_order_id': request.order_id
|
121
117
|
})
|
122
|
-
|
118
|
+
|
123
119
|
# Add optional fields
|
124
120
|
if request.callback_url:
|
125
121
|
payment_data['success_url'] = request.callback_url
|
126
|
-
|
122
|
+
|
127
123
|
if request.cancel_url:
|
128
124
|
payment_data['cancel_url'] = request.cancel_url
|
129
|
-
|
125
|
+
|
130
126
|
if request.customer_email:
|
131
127
|
payment_data['customer_email'] = request.customer_email
|
132
|
-
|
128
|
+
|
133
129
|
# Add IPN callback URL if configured
|
134
130
|
if self.config.callback_url:
|
135
131
|
payment_data['ipn_callback_url'] = self.config.callback_url
|
136
|
-
|
132
|
+
|
137
133
|
# Make API request
|
138
134
|
headers = {
|
139
135
|
'x-api-key': self._get_api_key()
|
140
136
|
}
|
141
|
-
|
137
|
+
|
142
138
|
response_data = self._make_request(
|
143
139
|
method='POST',
|
144
140
|
endpoint='payment',
|
145
141
|
data=payment_data,
|
146
142
|
headers=headers
|
147
143
|
)
|
148
|
-
|
144
|
+
|
149
145
|
# Parse NowPayments response
|
150
146
|
if response_data and 'payment_id' in response_data:
|
151
147
|
# Log the full response for debugging
|
@@ -155,10 +151,10 @@ class NowPaymentsProvider(BaseProvider):
|
|
155
151
|
'pay_amount': response_data.get('pay_amount'),
|
156
152
|
'full_response': response_data
|
157
153
|
})
|
158
|
-
|
154
|
+
|
159
155
|
# Successful payment creation
|
160
156
|
payment_url = response_data.get('invoice_url') or response_data.get('pay_url')
|
161
|
-
|
157
|
+
|
162
158
|
return self._create_provider_response(
|
163
159
|
success=True,
|
164
160
|
raw_response=response_data,
|
@@ -178,14 +174,14 @@ class NowPaymentsProvider(BaseProvider):
|
|
178
174
|
raw_response=response_data or {},
|
179
175
|
error_message=error_message
|
180
176
|
)
|
181
|
-
|
177
|
+
|
182
178
|
except Exception as e:
|
183
179
|
error_msg = str(e)
|
184
180
|
self.logger.error(f"NowPayments payment creation failed: {error_msg}", extra={
|
185
181
|
'order_id': request.order_id,
|
186
182
|
'error_type': type(e).__name__
|
187
183
|
})
|
188
|
-
|
184
|
+
|
189
185
|
# Provide user-friendly error messages
|
190
186
|
if "IP address blocked" in error_msg:
|
191
187
|
user_message = "NowPayments has blocked this IP address. Please contact support or try from a different location."
|
@@ -199,34 +195,34 @@ class NowPaymentsProvider(BaseProvider):
|
|
199
195
|
user_message = "NowPayments service is temporarily unavailable. Please try again later."
|
200
196
|
else:
|
201
197
|
user_message = f"Payment creation failed: {error_msg}"
|
202
|
-
|
198
|
+
|
203
199
|
return self._create_provider_response(
|
204
200
|
success=False,
|
205
201
|
raw_response={'error': error_msg, 'error_type': type(e).__name__},
|
206
202
|
error_message=user_message
|
207
203
|
)
|
208
|
-
|
204
|
+
|
209
205
|
def get_payment_status(self, provider_payment_id: str) -> ProviderResponse:
|
210
206
|
"""Get payment status from NowPayments."""
|
211
207
|
try:
|
212
208
|
self.logger.debug("Getting NowPayments payment status", extra={
|
213
209
|
'payment_id': provider_payment_id
|
214
210
|
})
|
215
|
-
|
211
|
+
|
216
212
|
headers = {
|
217
213
|
'x-api-key': self._get_api_key()
|
218
214
|
}
|
219
|
-
|
215
|
+
|
220
216
|
response_data = self._make_request(
|
221
217
|
method='GET',
|
222
218
|
endpoint=f'payment/{provider_payment_id}',
|
223
219
|
headers=headers
|
224
220
|
)
|
225
|
-
|
221
|
+
|
226
222
|
if response_data and 'payment_status' in response_data:
|
227
223
|
provider_status = response_data['payment_status']
|
228
224
|
universal_status = self.STATUS_MAPPING.get(provider_status, 'unknown')
|
229
|
-
|
225
|
+
|
230
226
|
return self._create_provider_response(
|
231
227
|
success=True,
|
232
228
|
raw_response=response_data,
|
@@ -243,14 +239,14 @@ class NowPaymentsProvider(BaseProvider):
|
|
243
239
|
raw_response=response_data or {},
|
244
240
|
error_message=error_message
|
245
241
|
)
|
246
|
-
|
242
|
+
|
247
243
|
except Exception as e:
|
248
244
|
error_msg = str(e)
|
249
245
|
self.logger.error(f"NowPayments status check failed: {error_msg}", extra={
|
250
246
|
'payment_id': provider_payment_id,
|
251
247
|
'error_type': type(e).__name__
|
252
248
|
})
|
253
|
-
|
249
|
+
|
254
250
|
# Provide user-friendly error messages
|
255
251
|
if "IP address blocked" in error_msg:
|
256
252
|
user_message = "NowPayments has blocked this IP address. Cannot check payment status."
|
@@ -260,31 +256,31 @@ class NowPaymentsProvider(BaseProvider):
|
|
260
256
|
user_message = "NowPayments service is temporarily unavailable. Please try again later."
|
261
257
|
else:
|
262
258
|
user_message = f"Status check failed: {error_msg}"
|
263
|
-
|
259
|
+
|
264
260
|
return self._create_provider_response(
|
265
261
|
success=False,
|
266
262
|
raw_response={'error': error_msg, 'error_type': type(e).__name__},
|
267
263
|
error_message=user_message
|
268
264
|
)
|
269
|
-
|
265
|
+
|
270
266
|
def get_supported_currencies(self) -> ServiceOperationResult:
|
271
267
|
"""Get supported currencies from NowPayments."""
|
272
268
|
try:
|
273
269
|
self.logger.debug("Getting NowPayments supported currencies")
|
274
|
-
|
270
|
+
|
275
271
|
headers = {
|
276
272
|
'x-api-key': self._get_api_key()
|
277
273
|
}
|
278
|
-
|
274
|
+
|
279
275
|
response_data = self._make_request(
|
280
276
|
method='GET',
|
281
277
|
endpoint='full-currencies',
|
282
278
|
headers=headers
|
283
279
|
)
|
284
|
-
|
280
|
+
|
285
281
|
if response_data and 'currencies' in response_data:
|
286
282
|
currencies = response_data['currencies']
|
287
|
-
|
283
|
+
|
288
284
|
return ServiceOperationResult(
|
289
285
|
success=True,
|
290
286
|
message=f"Retrieved {len(currencies)} supported currencies",
|
@@ -300,16 +296,16 @@ class NowPaymentsProvider(BaseProvider):
|
|
300
296
|
message="Failed to get currencies from NowPayments",
|
301
297
|
error_code="currencies_fetch_failed"
|
302
298
|
)
|
303
|
-
|
299
|
+
|
304
300
|
except Exception as e:
|
305
301
|
self.logger.error(f"NowPayments currencies fetch failed: {e}")
|
306
|
-
|
302
|
+
|
307
303
|
return ServiceOperationResult(
|
308
304
|
success=False,
|
309
305
|
message=f"Currencies fetch error: {e}",
|
310
306
|
error_code="currencies_fetch_error"
|
311
307
|
)
|
312
|
-
|
308
|
+
|
313
309
|
def get_parsed_currencies(self) -> UniversalCurrenciesResponse:
|
314
310
|
"""Get parsed and normalized currencies from NowPayments."""
|
315
311
|
try:
|
@@ -317,50 +313,50 @@ class NowPaymentsProvider(BaseProvider):
|
|
317
313
|
headers = {
|
318
314
|
'x-api-key': self._get_api_key()
|
319
315
|
}
|
320
|
-
|
316
|
+
|
321
317
|
response_data = self._make_request(
|
322
318
|
method='GET',
|
323
319
|
endpoint='full-currencies',
|
324
320
|
headers=headers
|
325
321
|
)
|
326
|
-
|
322
|
+
|
327
323
|
if not response_data or 'currencies' not in response_data:
|
328
324
|
return UniversalCurrenciesResponse(currencies=[])
|
329
|
-
|
325
|
+
|
330
326
|
universal_currencies = []
|
331
|
-
|
327
|
+
|
332
328
|
for currency_data in response_data['currencies']:
|
333
329
|
if not currency_data.get('enable', True):
|
334
330
|
continue # Skip disabled currencies
|
335
|
-
|
331
|
+
|
336
332
|
provider_code = currency_data.get('code', '').upper()
|
337
333
|
if not provider_code:
|
338
334
|
continue
|
339
|
-
|
335
|
+
|
340
336
|
# Parse provider code into base currency + network using API data
|
341
337
|
currency_name = currency_data.get('name', '')
|
342
338
|
api_network = currency_data.get('network')
|
343
339
|
ticker = currency_data.get('ticker', '')
|
344
|
-
|
340
|
+
|
345
341
|
# Use parser to extract base currency and network
|
346
342
|
parse_result = self.parser.parse_currency_code(
|
347
343
|
provider_code, currency_name, api_network, ticker
|
348
344
|
)
|
349
|
-
|
345
|
+
|
350
346
|
# Skip currencies that should be filtered out (empty network duplicates)
|
351
347
|
if parse_result[0] is None:
|
352
348
|
continue
|
353
|
-
|
349
|
+
|
354
350
|
base_currency_code, network_code = parse_result
|
355
|
-
|
351
|
+
|
356
352
|
# Determine currency type
|
357
353
|
currency_type = 'fiat' if network_code is None else 'crypto'
|
358
|
-
|
354
|
+
|
359
355
|
# Generate proper currency name
|
360
356
|
proper_name = self.parser.generate_currency_name(
|
361
357
|
base_currency_code, network_code, currency_name
|
362
358
|
)
|
363
|
-
|
359
|
+
|
364
360
|
universal_currency = UniversalCurrency(
|
365
361
|
provider_currency_code=provider_code,
|
366
362
|
base_currency_code=base_currency_code,
|
@@ -376,45 +372,45 @@ class NowPaymentsProvider(BaseProvider):
|
|
376
372
|
available_for_payout=currency_data.get('available_for_payout', True),
|
377
373
|
raw_data=currency_data
|
378
374
|
)
|
379
|
-
|
375
|
+
|
380
376
|
universal_currencies.append(universal_currency)
|
381
|
-
|
377
|
+
|
382
378
|
return UniversalCurrenciesResponse(currencies=universal_currencies)
|
383
|
-
|
379
|
+
|
384
380
|
except Exception as e:
|
385
381
|
logger.error(f"Error parsing currencies: {e}")
|
386
382
|
return UniversalCurrenciesResponse(currencies=[])
|
387
|
-
|
383
|
+
|
388
384
|
def sync_currencies_to_db(self) -> CurrencySyncResult:
|
389
385
|
"""Sync currencies from NowPayments API to database."""
|
390
386
|
try:
|
391
387
|
self.logger.info("Starting NowPayments currency synchronization")
|
392
|
-
|
388
|
+
|
393
389
|
# Get parsed currencies from API
|
394
390
|
currencies_response = self.get_parsed_currencies()
|
395
|
-
|
391
|
+
|
396
392
|
if not currencies_response.currencies:
|
397
393
|
return CurrencySyncResult(
|
398
394
|
errors=["No currencies received from NowPayments API"]
|
399
395
|
)
|
400
|
-
|
396
|
+
|
401
397
|
# Sync to database
|
402
398
|
result = self.sync_service.sync_currencies_to_db(currencies_response.currencies)
|
403
|
-
|
399
|
+
|
404
400
|
self.logger.info(
|
405
401
|
f"NowPayments currency sync completed: "
|
406
402
|
f"{result.currencies_created} currencies created, "
|
407
403
|
f"{result.provider_currencies_created} provider currencies created, "
|
408
404
|
f"{len(result.errors)} errors"
|
409
405
|
)
|
410
|
-
|
406
|
+
|
411
407
|
return result
|
412
|
-
|
408
|
+
|
413
409
|
except Exception as e:
|
414
410
|
error_msg = f"Currency sync failed: {e}"
|
415
411
|
self.logger.error(error_msg)
|
416
412
|
return CurrencySyncResult(errors=[error_msg])
|
417
|
-
|
413
|
+
|
418
414
|
def validate_webhook(self, payload: Dict[str, Any], signature: str = None) -> ServiceOperationResult:
|
419
415
|
"""Validate NowPayments IPN webhook."""
|
420
416
|
try:
|
@@ -422,7 +418,7 @@ class NowPaymentsProvider(BaseProvider):
|
|
422
418
|
'has_signature': bool(signature),
|
423
419
|
'payment_id': payload.get('payment_id')
|
424
420
|
})
|
425
|
-
|
421
|
+
|
426
422
|
# Validate payload structure
|
427
423
|
try:
|
428
424
|
from .models import NowPaymentsWebhook
|
@@ -433,7 +429,7 @@ class NowPaymentsProvider(BaseProvider):
|
|
433
429
|
message=f"Invalid webhook payload: {e}",
|
434
430
|
error_code="invalid_payload"
|
435
431
|
)
|
436
|
-
|
432
|
+
|
437
433
|
# Validate signature if provided and secret is configured
|
438
434
|
if signature and self.config.ipn_secret:
|
439
435
|
is_valid_signature = self._validate_ipn_signature(payload, signature)
|
@@ -443,7 +439,7 @@ class NowPaymentsProvider(BaseProvider):
|
|
443
439
|
message="Invalid webhook signature",
|
444
440
|
error_code="invalid_signature"
|
445
441
|
)
|
446
|
-
|
442
|
+
|
447
443
|
return ServiceOperationResult(
|
448
444
|
success=True,
|
449
445
|
message="Webhook validated successfully",
|
@@ -455,16 +451,16 @@ class NowPaymentsProvider(BaseProvider):
|
|
455
451
|
'webhook_data': webhook_data.model_dump()
|
456
452
|
}
|
457
453
|
)
|
458
|
-
|
454
|
+
|
459
455
|
except Exception as e:
|
460
456
|
self.logger.error(f"NowPayments webhook validation failed: {e}")
|
461
|
-
|
457
|
+
|
462
458
|
return ServiceOperationResult(
|
463
459
|
success=False,
|
464
460
|
message=f"Webhook validation error: {e}",
|
465
461
|
error_code="validation_error"
|
466
462
|
)
|
467
|
-
|
463
|
+
|
468
464
|
def health_check(self) -> ServiceOperationResult:
|
469
465
|
"""Perform NowPayments-specific health check."""
|
470
466
|
try:
|
@@ -472,18 +468,18 @@ class NowPaymentsProvider(BaseProvider):
|
|
472
468
|
headers = {
|
473
469
|
'x-api-key': self._get_api_key()
|
474
470
|
}
|
475
|
-
|
471
|
+
|
476
472
|
response_data = self._make_request(
|
477
473
|
method='GET',
|
478
474
|
endpoint='status',
|
479
475
|
headers=headers
|
480
476
|
)
|
481
|
-
|
477
|
+
|
482
478
|
if response_data and response_data.get('message') == 'OK':
|
483
479
|
# Also check currencies endpoint
|
484
480
|
currencies_result = self.get_supported_currencies()
|
485
481
|
currency_count = len(currencies_result.data.get('currencies', [])) if currencies_result.success else 0
|
486
|
-
|
482
|
+
|
487
483
|
return ServiceOperationResult(
|
488
484
|
success=True,
|
489
485
|
message="NowPayments provider is healthy",
|
@@ -506,7 +502,7 @@ class NowPaymentsProvider(BaseProvider):
|
|
506
502
|
'response': response_data
|
507
503
|
}
|
508
504
|
)
|
509
|
-
|
505
|
+
|
510
506
|
except Exception as e:
|
511
507
|
return ServiceOperationResult(
|
512
508
|
success=False,
|
@@ -514,42 +510,42 @@ class NowPaymentsProvider(BaseProvider):
|
|
514
510
|
error_code="health_check_error",
|
515
511
|
data={'provider': self.name}
|
516
512
|
)
|
517
|
-
|
518
|
-
|
513
|
+
|
514
|
+
|
519
515
|
def _validate_ipn_signature(self, payload: Dict[str, Any], signature: str) -> bool:
|
520
516
|
"""Validate IPN signature using HMAC-SHA512."""
|
521
517
|
try:
|
522
518
|
import json
|
523
|
-
|
519
|
+
|
524
520
|
# Sort payload and create canonical string
|
525
521
|
sorted_payload = json.dumps(payload, separators=(',', ':'), sort_keys=True)
|
526
|
-
|
522
|
+
|
527
523
|
# Calculate expected signature
|
528
524
|
expected_signature = hmac.new(
|
529
525
|
self.config.ipn_secret.encode('utf-8'),
|
530
526
|
sorted_payload.encode('utf-8'),
|
531
527
|
hashlib.sha512
|
532
528
|
).hexdigest()
|
533
|
-
|
529
|
+
|
534
530
|
# Compare signatures
|
535
531
|
return hmac.compare_digest(expected_signature, signature)
|
536
|
-
|
532
|
+
|
537
533
|
except Exception as e:
|
538
534
|
self.logger.error(f"Signature validation error: {e}")
|
539
535
|
return False
|
540
|
-
|
536
|
+
|
541
537
|
def _parse_expiry_time(self, expiry_str: Optional[str]) -> Optional[datetime]:
|
542
538
|
"""Parse NowPayments expiry time string."""
|
543
539
|
if not expiry_str:
|
544
540
|
return None
|
545
|
-
|
541
|
+
|
546
542
|
try:
|
547
543
|
# NowPayments typically returns ISO format
|
548
544
|
return datetime.fromisoformat(expiry_str.replace('Z', '+00:00'))
|
549
545
|
except Exception:
|
550
546
|
self.logger.warning(f"Failed to parse expiry time: {expiry_str}")
|
551
547
|
return None
|
552
|
-
|
548
|
+
|
553
549
|
def _get_api_key(self) -> str:
|
554
550
|
"""Get API key as string."""
|
555
551
|
if hasattr(self.config.api_key, 'get_secret_value'):
|