From 9c625f06ce5e262bf7c1ab609e8b4957a240f0c5 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Tue, 2 May 2023 13:19:37 -0600 Subject: [PATCH 01/18] Add files of PoC, remove old ones --- {infobip_channels/core => api}/__init__.py | 0 api/sms.py | 43 + client.py | 18 + infobip_channels/__init__.py | 15 - infobip_channels/core/channel.py | 239 ---- infobip_channels/core/http_client.py | 114 -- infobip_channels/core/models.py | 386 ----- infobip_channels/email/__init__.py | 0 infobip_channels/email/channel.py | 413 ------ infobip_channels/email/models/__init__.py | 0 .../email/models/body/__init__.py | 0 .../email/models/body/add_new_domain.py | 5 - .../email/models/body/reschedule_messages.py | 14 - .../email/models/body/send_email.py | 49 - .../models/body/update_scheduled_status.py | 5 - .../models/body/update_tracking_events.py | 11 - .../models/body/validate_email_addresses.py | 5 - .../email/models/path_parameters/__init__.py | 0 .../email/models/path_parameters/core.py | 5 - .../path_parameters/delete_existing_domain.py | 5 - .../path_parameters/get_domain_details.py | 5 - .../path_parameters/update_tracking_events.py | 5 - .../models/path_parameters/verify_domain.py | 5 - .../email/models/query_parameters/__init__.py | 0 .../email/models/query_parameters/core.py | 5 - .../query_parameters/delivery_reports.py | 9 - .../query_parameters/get_all_domains.py | 10 - .../email/models/query_parameters/get_logs.py | 20 - .../models/query_parameters/get_sent_bulks.py | 5 - .../query_parameters/get_sent_bulks_status.py | 5 - .../query_parameters/reschedule_messages.py | 5 - .../update_scheduled_status.py | 5 - .../email/models/response/__init__.py | 0 .../email/models/response/add_new_domain.py | 6 - .../email/models/response/core.py | 63 - .../email/models/response/delivery_reports.py | 22 - .../email/models/response/get_all_domains.py | 16 - .../models/response/get_domain_details.py | 6 - .../email/models/response/get_logs.py | 15 - .../models/response/get_sent_bulk_status.py | 11 - .../email/models/response/get_sent_bulks.py | 11 - .../models/response/reschedule_messages.py | 6 - .../email/models/response/send_email.py | 14 - .../response/update_scheduled_status.py | 6 - .../models/response/update_tracking_events.py | 6 - .../response/validate_email_addresses.py | 13 - infobip_channels/mms/__init__.py | 0 infobip_channels/mms/channel.py | 102 -- infobip_channels/mms/models/__init__.py | 0 infobip_channels/mms/models/body/__init__.py | 0 infobip_channels/mms/models/body/send_mms.py | 73 - .../mms/models/query_parameters/__init__.py | 0 .../get_inbound_mms_messages.py | 7 - .../get_mms_delivery_reports.py | 9 - .../mms/models/response/__init__.py | 0 infobip_channels/mms/models/response/core.py | 8 - .../response/get_inbound_mms_messages.py | 21 - .../response/get_mms_delivery_reports.py | 33 - .../mms/models/response/send_mms.py | 15 - infobip_channels/rcs/Models/__init__.py | 0 infobip_channels/rcs/Models/body/__init__.py | 0 .../rcs/Models/body/send_bulk_rcs_message.py | 8 - .../rcs/Models/body/send_rcs_message.py | 215 --- .../rcs/Models/response/__init__.py | 0 infobip_channels/rcs/Models/response/core.py | 36 - infobip_channels/rcs/__init__.py | 0 infobip_channels/rcs/channel.py | 68 - infobip_channels/sms/__init__.py | 0 infobip_channels/sms/channel.py | 665 --------- infobip_channels/sms/models/__init__.py | 0 infobip_channels/sms/models/body/__init__.py | 0 infobip_channels/sms/models/body/core.py | 108 -- .../sms/models/body/create_tfa_application.py | 6 - .../body/create_tfa_message_template.py | 6 - .../sms/models/body/preview_message.py | 13 - .../models/body/reschedule_sms_messages.py | 14 - .../sms/models/body/resend_pin_over_sms.py | 7 - .../sms/models/body/resend_pin_over_voice.py | 3 - .../sms/models/body/send_binary_message.py | 31 - .../sms/models/body/send_message.py | 39 - .../sms/models/body/send_pin_over_sms.py | 13 - .../sms/models/body/send_pin_over_voice.py | 3 - .../body/update_scheduled_messages_status.py | 5 - .../sms/models/body/update_tfa_application.py | 6 - .../body/update_tfa_message_template.py | 6 - .../sms/models/body/verify_phone_number.py | 7 - infobip_channels/sms/models/core/__init__.py | 0 .../sms/models/core/tfa_application.py | 15 - .../core/tfa_application_configuration.py | 12 - .../sms/models/core/tfa_message_template.py | 54 - .../sms/models/core/tfa_pin_status.py | 11 - .../sms/models/core/tfa_pin_verification.py | 11 - .../sms/models/query_parameters/__init__.py | 0 .../sms/models/query_parameters/core.py | 5 - .../query_parameters/get_inbound_messages.py | 9 - .../get_outbound_delivery_reports.py | 11 - .../query_parameters/get_outbound_logs.py | 31 - .../get_scheduled_messages.py | 5 - .../get_scheduled_messages_status.py | 5 - .../get_tfa_verification_status.py | 9 - .../query_parameters/reschedule_messages.py | 5 - .../models/query_parameters/send_message.py | 58 - .../query_parameters/send_pin_over_sms.py | 7 - .../query_parameters/send_pin_over_voice.py | 7 - .../update_scheduled_messages_status.py | 5 - .../query_parameters/verify_phone_number.py | 7 - .../sms/models/response/__init__.py | 0 infobip_channels/sms/models/response/core.py | 49 - .../models/response/create_tfa_application.py | 6 - .../response/create_tfa_message_template.py | 6 - .../models/response/get_scheduled_messages.py | 5 - .../response/get_scheduled_messages_status.py | 8 - .../models/response/get_tfa_application.py | 6 - .../models/response/get_tfa_applications.py | 8 - .../response/get_tfa_message_template.py | 6 - .../response/get_tfa_message_templates.py | 8 - .../response/get_tfa_verification_status.py | 14 - .../sms/models/response/inbound_messages.py | 25 - .../response/outbound_delivery_reports.py | 8 - .../models/response/outbound_message_logs.py | 12 - .../sms/models/response/preview_message.py | 29 - .../response/reschedule_sms_messages.py | 5 - .../models/response/resend_pin_over_sms.py | 5 - .../models/response/resend_pin_over_voice.py | 5 - .../sms/models/response/send_message.py | 15 - .../sms/models/response/send_pin_over_sms.py | 6 - .../models/response/send_pin_over_voice.py | 6 - .../update_scheduled_messages_status.py | 5 - .../models/response/update_tfa_application.py | 6 - .../response/update_tfa_message_template.py | 6 - .../models/response/verify_phone_number.py | 6 - infobip_channels/web_rtc/__init__.py | 0 infobip_channels/web_rtc/channel.py | 138 -- infobip_channels/web_rtc/models/__init__.py | 0 .../web_rtc/models/body/__init__.py | 0 infobip_channels/web_rtc/models/body/core.py | 25 - .../web_rtc/models/body/generate_token.py | 42 - .../web_rtc/models/body/save_application.py | 5 - .../web_rtc/models/body/update_application.py | 5 - .../models/path_parameters/__init__.py | 0 .../web_rtc/models/path_parameters/core.py | 5 - .../path_parameters/web_rtc_application.py | 5 - .../web_rtc/models/response/__init__.py | 0 .../web_rtc/models/response/core.py | 41 - .../web_rtc/models/response/generate_token.py | 6 - .../models/response/get_applications.py | 8 - infobip_channels/whatsapp/__init__.py | 0 infobip_channels/whatsapp/channel.py | 368 ----- infobip_channels/whatsapp/models/__init__.py | 0 .../whatsapp/models/body/__init__.py | 0 .../whatsapp/models/body/action_sections.py | 21 - .../whatsapp/models/body/audio_message.py | 16 - .../whatsapp/models/body/buttons_message.py | 78 -- .../whatsapp/models/body/contact_message.py | 95 -- infobip_channels/whatsapp/models/body/core.py | 17 - .../whatsapp/models/body/create_template.py | 179 --- .../whatsapp/models/body/document_message.py | 20 - .../whatsapp/models/body/image_message.py | 19 - .../whatsapp/models/body/list_message.py | 85 -- .../whatsapp/models/body/location_message.py | 17 - .../models/body/multi_product_message.py | 53 - .../whatsapp/models/body/product_message.py | 29 - .../whatsapp/models/body/sticker_message.py | 16 - .../whatsapp/models/body/template_message.py | 109 -- .../whatsapp/models/body/text_message.py | 15 - .../whatsapp/models/body/video_message.py | 19 - .../models/path_parameters/__init__.py | 0 .../whatsapp/models/path_parameters/core.py | 5 - .../models/path_parameters/delete_template.py | 5 - .../path_parameters/manage_templates.py | 5 - .../whatsapp/models/response/__init__.py | 0 .../whatsapp/models/response/core.py | 28 - .../models/response/create_template.py | 6 - .../whatsapp/models/response/get_templates.py | 39 - .../models/response/template_message.py | 9 - infobip_platform/__init__.py | 0 infobip_platform/app_entities/__init__.py | 0 infobip_platform/app_entities/api.py | 118 -- .../app_entities/models/__init__.py | 0 .../app_entities/models/body/__init__.py | 0 .../app_entities/models/body/create_entity.py | 6 - .../app_entities/models/body/modify_entity.py | 9 - .../app_entities/models/core/__init__.py | 0 .../app_entities/models/core/entity.py | 10 - .../models/query_parameters/__init__.py | 0 .../models/query_parameters/get_entities.py | 10 - .../app_entities/models/response/__init__.py | 0 .../app_entities/models/response/core.py | 13 - .../models/response/create_entity.py | 5 - .../models/response/get_entities.py | 10 - .../models/response/get_entity.py | 6 - .../models/response/modify_entity.py | 5 - models/__init__.py | 251 ++++ models/application.py | 75 + models/channel.py | 30 + models/entity.py | 72 + models/message_error.py | 85 ++ models/message_price.py | 73 + models/message_status.py | 85 ++ models/mms_advanced_message.py | 167 +++ models/mms_advanced_message_segment.py | 188 +++ models/mms_advanced_message_segment_binary.py | 81 ++ models/mms_advanced_message_segment_link.py | 81 ++ models/mms_advanced_message_segment_smil.py | 82 ++ models/mms_advanced_message_segment_text.py | 70 + ...vanced_message_segment_upload_reference.py | 77 + models/mms_advanced_request.py | 88 ++ models/mms_delivery_day.py | 33 + models/mms_delivery_time.py | 72 + models/mms_delivery_time_window.py | 86 ++ models/mms_destination.py | 73 + models/mms_error.py | 81 ++ models/mms_inbound_report.py | 116 ++ models/mms_inbound_report_response.py | 79 ++ models/mms_message_result.py | 83 ++ models/mms_price.py | 73 + models/mms_report.py | 153 ++ models/mms_report_response.py | 77 + models/mms_send_result.py | 89 ++ models/mms_status.py | 76 + models/mms_upload_binary_result.py | 69 + models/mms_webhook_inbound_message_segment.py | 157 +++ ...ms_webhook_inbound_message_segment_link.py | 68 + ...ms_webhook_inbound_message_segment_text.py | 68 + models/mms_webhook_inbound_report.py | 154 ++ models/mms_webhook_inbound_report_response.py | 92 ++ models/mms_webhook_outbound_report.py | 147 ++ .../mms_webhook_outbound_report_response.py | 80 ++ models/modify_application.py | 67 + models/modify_entity.py | 65 + models/number_price.py | 73 + models/number_registration_address.py | 82 ++ models/number_registration_brand.py | 135 ++ models/number_registration_brand_preview.py | 66 + models/number_registration_brand_status.py | 111 ++ models/number_registration_brand_vet.py | 102 ++ ...number_registration_business_identifier.py | 114 ++ models/number_registration_campaign.py | 147 ++ ..._data_universal_numbering_system_number.py | 81 ++ .../number_registration_document_metadata.py | 73 + ..._registration_external_ten_dlc_campaign.py | 124 ++ ...obal_intermediary_identification_number.py | 87 ++ .../number_registration_government_brand.py | 176 +++ ...ation_interactive_voice_response_opt_in.py | 70 + models/number_registration_keyword_opt_in.py | 72 + ...er_registration_legal_entity_identifier.py | 77 + models/number_registration_network_status.py | 109 ++ .../number_registration_non_profit_brand.py | 176 +++ models/number_registration_number_preview.py | 71 + models/number_registration_opt_ins.py | 111 ++ models/number_registration_page_info.py | 80 ++ ...number_registration_page_response_brand.py | 92 ++ ...er_registration_page_response_brand_vet.py | 94 ++ ...ber_registration_page_response_campaign.py | 94 ++ ...mber_registration_private_company_brand.py | 176 +++ ...umber_registration_public_company_brand.py | 224 +++ .../number_registration_ten_dlc_campaign.py | 286 ++++ ...umber_registration_update_brand_request.py | 138 ++ ...er_registration_update_campaign_request.py | 68 + models/number_registration_verbal_opt_in.py | 68 + models/number_registration_web_opt_in.py | 69 + models/number_response.py | 191 +++ models/numbers_auto_response_action.py | 93 ++ models/numbers_block_action.py | 79 ++ models/numbers_delivery_time_window.py | 116 ++ models/numbers_edit_permissions.py | 71 + .../numbers_forward_to_ivr_action_details.py | 69 + ...numbers_forward_to_subscription_details.py | 64 + models/numbers_http_forward_action.py | 95 ++ models/numbers_mail_forward_action.py | 69 + models/numbers_mo_action.py | 154 ++ models/numbers_mo_configuration.py | 136 ++ models/numbers_mo_configurations.py | 84 ++ models/numbers_mo_non_forward_action.py | 134 ++ models/numbers_no_action.py | 64 + models/numbers_pull_action.py | 64 + models/numbers_purchase_number_request.py | 81 ++ models/numbers_response.py | 81 ++ models/numbers_smpp_forward_action.py | 64 + models/numbers_stored_mo_configuration.py | 139 ++ models/numbers_use_conversation.py | 65 + models/numbers_voice_action_details.py | 145 ++ ...ice_call_forward_to_application_details.py | 69 + ...ers_voice_number_masking_action_details.py | 73 + models/numbers_voice_setup.py | 85 ++ models/page_application.py | 87 ++ models/page_entity.py | 85 ++ models/page_info.py | 80 ++ models/page_resource_association.py | 90 ++ models/resource_association_request.py | 94 ++ models/resource_association_response.py | 95 ++ models/resource_type.py | 29 + models/sms_advanced_binary_request.py | 100 ++ models/sms_advanced_textual_request.py | 114 ++ models/sms_binary_content.py | 82 ++ models/sms_binary_message.py | 184 +++ models/sms_bulk_request.py | 67 + models/sms_bulk_response.py | 74 + models/sms_bulk_status.py | 32 + models/sms_bulk_status_response.py | 71 + models/sms_delivery_day.py | 33 + models/sms_delivery_result.py | 77 + models/sms_delivery_time_from.py | 71 + models/sms_delivery_time_to.py | 71 + models/sms_delivery_time_window.py | 87 ++ models/sms_destination.py | 73 + models/sms_error.py | 85 ++ models/sms_inbound_message.py | 124 ++ models/sms_inbound_message_result.py | 93 ++ models/sms_india_dlt_options.py | 77 + models/sms_language.py | 67 + models/sms_language_configuration.py | 78 ++ models/sms_log.py | 146 ++ models/sms_logs_response.py | 77 + models/sms_preview.py | 98 ++ models/sms_preview_request.py | 97 ++ models/sms_preview_response.py | 88 ++ models/sms_price.py | 73 + models/sms_regional_options.py | 81 ++ models/sms_report.py | 158 +++ models/sms_response.py | 88 ++ models/sms_response_details.py | 83 ++ models/sms_sending_speed_limit.py | 70 + models/sms_speed_limit_time_unit.py | 29 + models/sms_status.py | 90 ++ models/sms_textual_message.py | 195 +++ models/sms_tracking.py | 87 ++ models/sms_turkey_iys_options.py | 83 ++ models/sms_update_status_request.py | 63 + models/sms_url_options.py | 107 ++ models/sms_webhook_inbound_report.py | 124 ++ models/sms_webhook_inbound_report_response.py | 92 ++ models/sms_webhook_outbound_report.py | 151 ++ .../sms_webhook_outbound_report_response.py | 82 ++ models/webhook_message_count.py | 77 + requirements.txt | 3 + requirements/common.txt | 3 - requirements/dev.txt | 9 - .../test_entity_management.py | 40 - samples/test_sms_live.py | 54 + samples/tfa/test_tfa.py | 192 --- samples/whatsapp/test_whatsapp.py | 19 - tests/app_entities/conftest.py | 71 - .../integration/test_create_entity_body.py | 108 -- .../test_create_entity_body_cases.py | 63 - .../integration/test_get_entities_query.py | 79 -- .../test_get_entities_query_cases.py | 42 - .../integration/test_get_entity_path.py | 125 -- .../integration/test_get_entity_path_cases.py | 64 - .../test_modify_entity_body_path.py | 110 -- .../test_modify_entity_body_path_cases.py | 47 - .../app_entities/models/test_create_entity.py | 45 - .../app_entities/models/test_get_entities.py | 37 - .../app_entities/models/test_modify_entity.py | 24 - tests/conftest.py | 102 -- tests/email/conftest.py | 363 ----- .../test_email_endpoints_integration.py | 119 -- .../test_email_endpoints_integration_cases.py | 167 --- .../test_email_with_body_integration.py | 127 -- .../test_email_with_body_integration_cases.py | 120 -- tests/email/models/test_add_new_domain.py | 24 - .../models/test_delete_existing_domain.py | 26 - tests/email/models/test_delivery_reports.py | 46 - tests/email/models/test_get_all_domains.py | 38 - tests/email/models/test_get_domain_details.py | 26 - tests/email/models/test_get_logs.py | 99 -- .../email/models/test_get_sent_bulk_status.py | 26 - tests/email/models/test_get_sent_bulks.py | 26 - .../email/models/test_reschedule_messages.py | 57 - tests/email/models/test_send_email.py | 370 ----- .../models/test_update_scheduled_status.py | 49 - .../models/test_update_tracking_events.py | 72 - .../models/test_validate_email_adresses.py | 26 - tests/mms/conftest.py | 126 -- .../integration/test_endpoints_integration.py | 116 -- .../test_endpoints_integration_cases.py | 83 -- .../models/test_get_inbound_mms_messages.py | 19 - .../models/test_get_mms_delivery_reports.py | 31 - tests/mms/models/test_send_mms.py | 269 ---- tests/rcs/conftest.py | 250 ---- tests/rcs/integration/test_rcs_endpoints.py | 118 -- .../integration/test_rcs_endpoints_cases.py | 77 - .../rcs/models/test_send_bulk_rcs_message.py | 37 - tests/rcs/models/test_send_rcs_message.py | 1238 ----------------- tests/sms/conftest.py | 660 --------- .../integration/test_reschedule_and_update.py | 119 -- .../test_reschedule_and_update_cases.py | 78 -- .../test_send_sms_body_endpoints.py | 119 -- .../test_send_sms_body_endpoints_cases.py | 91 -- .../integration/test_sms_query_endpoints.py | 117 -- .../test_sms_query_endpoints_cases.py | 139 -- .../test_tfa_create_and_update_path.py | 121 -- .../test_tfa_create_and_update_path_cases.py | 82 -- .../test_tfa_create_application.py | 119 -- .../test_tfa_create_application_cases.py | 63 - tests/sms/integration/test_tfa_get.py | 123 -- tests/sms/integration/test_tfa_get_cases.py | 64 - tests/sms/integration/test_tfa_get_path.py | 123 -- .../integration/test_tfa_get_path_cases.py | 78 -- .../integration/test_tfa_get_path_query.py | 119 -- .../test_tfa_get_path_query_cases.py | 61 - .../integration/test_tfa_get_template_path.py | 120 -- .../test_tfa_get_template_path_cases.py | 61 - .../test_tfa_resend_verify_pin_path.py | 122 -- .../test_tfa_resend_verify_pin_path_cases.py | 97 -- tests/sms/integration/test_tfa_send_pin.py | 119 -- .../integration/test_tfa_send_pin_cases.py | 82 -- .../test_tfa_update_template_path.py | 123 -- .../test_tfa_update_template_path_cases.py | 63 - .../sms/models/test_create_tfa_application.py | 27 - .../test_create_tfa_message_template.py | 108 -- .../sms/models/test_get_scheduled_messages.py | 27 - .../test_get_scheduled_messages_status.py | 27 - tests/sms/models/test_inbound_messages.py | 27 - .../models/test_outbound_delivery_reports.py | 52 - tests/sms/models/test_outbound_logs.py | 123 -- tests/sms/models/test_preview.py | 43 - .../models/test_reschedule_sms_messages.py | 60 - tests/sms/models/test_send.py | 295 ---- tests/sms/models/test_send_binary.py | 337 ----- tests/sms/models/test_send_pin.py | 61 - tests/sms/models/test_send_query.py | 293 ---- .../test_update_scheduled_messages_status.py | 51 - .../sms/models/test_update_tfa_application.py | 27 - tests/sms/models/test_verify_phone_number.py | 25 - tests/test_core.py | 70 - tests/test_sms.py | 43 + tests/webrtc/conftest.py | 137 -- .../test_webrtc_endpoints_with_body.py | 116 -- .../test_webrtc_endpoints_with_body_cases.py | 89 -- .../test_webrtc_endpoints_without_body.py | 117 -- ...est_webrtc_endpoints_without_body_cases.py | 81 -- tests/webrtc/models/test_generate_token.py | 79 -- tests/webrtc/models/test_save_application.py | 133 -- tests/whatsapp/conftest.py | 328 ----- .../test_create_template_integration.py | 127 -- .../test_create_template_integration_cases.py | 99 -- .../test_delete_template_integration.py | 106 -- .../test_delete_template_integration_cases.py | 61 - .../integration/test_get_templates.py | 117 -- .../integration/test_get_templates_cases.py | 102 -- .../whatsapp/integration/test_send_message.py | 128 -- .../integration/test_send_message_cases.py | 158 --- tests/whatsapp/models/test_audio_message.py | 40 - tests/whatsapp/models/test_buttons_message.py | 327 ----- tests/whatsapp/models/test_contact_message.py | 267 ---- tests/whatsapp/models/test_core_models.py | 56 - tests/whatsapp/models/test_create_template.py | 354 ----- tests/whatsapp/models/test_delete_template.py | 16 - .../whatsapp/models/test_document_message.py | 64 - tests/whatsapp/models/test_image_message.py | 49 - tests/whatsapp/models/test_list_message.py | 426 ------ .../whatsapp/models/test_location_message.py | 84 -- .../models/test_multi_product_message.py | 379 ----- tests/whatsapp/models/test_product_message.py | 144 -- tests/whatsapp/models/test_sticker_message.py | 42 - .../whatsapp/models/test_template_message.py | 727 ---------- tests/whatsapp/models/test_text_message.py | 45 - tests/whatsapp/models/test_video_message.py | 48 - 459 files changed, 13914 insertions(+), 20401 deletions(-) rename {infobip_channels/core => api}/__init__.py (100%) create mode 100644 api/sms.py create mode 100644 client.py delete mode 100644 infobip_channels/__init__.py delete mode 100644 infobip_channels/core/channel.py delete mode 100644 infobip_channels/core/http_client.py delete mode 100644 infobip_channels/core/models.py delete mode 100644 infobip_channels/email/__init__.py delete mode 100644 infobip_channels/email/channel.py delete mode 100644 infobip_channels/email/models/__init__.py delete mode 100644 infobip_channels/email/models/body/__init__.py delete mode 100644 infobip_channels/email/models/body/add_new_domain.py delete mode 100644 infobip_channels/email/models/body/reschedule_messages.py delete mode 100644 infobip_channels/email/models/body/send_email.py delete mode 100644 infobip_channels/email/models/body/update_scheduled_status.py delete mode 100644 infobip_channels/email/models/body/update_tracking_events.py delete mode 100644 infobip_channels/email/models/body/validate_email_addresses.py delete mode 100644 infobip_channels/email/models/path_parameters/__init__.py delete mode 100644 infobip_channels/email/models/path_parameters/core.py delete mode 100644 infobip_channels/email/models/path_parameters/delete_existing_domain.py delete mode 100644 infobip_channels/email/models/path_parameters/get_domain_details.py delete mode 100644 infobip_channels/email/models/path_parameters/update_tracking_events.py delete mode 100644 infobip_channels/email/models/path_parameters/verify_domain.py delete mode 100644 infobip_channels/email/models/query_parameters/__init__.py delete mode 100644 infobip_channels/email/models/query_parameters/core.py delete mode 100644 infobip_channels/email/models/query_parameters/delivery_reports.py delete mode 100644 infobip_channels/email/models/query_parameters/get_all_domains.py delete mode 100644 infobip_channels/email/models/query_parameters/get_logs.py delete mode 100644 infobip_channels/email/models/query_parameters/get_sent_bulks.py delete mode 100644 infobip_channels/email/models/query_parameters/get_sent_bulks_status.py delete mode 100644 infobip_channels/email/models/query_parameters/reschedule_messages.py delete mode 100644 infobip_channels/email/models/query_parameters/update_scheduled_status.py delete mode 100644 infobip_channels/email/models/response/__init__.py delete mode 100644 infobip_channels/email/models/response/add_new_domain.py delete mode 100644 infobip_channels/email/models/response/core.py delete mode 100644 infobip_channels/email/models/response/delivery_reports.py delete mode 100644 infobip_channels/email/models/response/get_all_domains.py delete mode 100644 infobip_channels/email/models/response/get_domain_details.py delete mode 100644 infobip_channels/email/models/response/get_logs.py delete mode 100644 infobip_channels/email/models/response/get_sent_bulk_status.py delete mode 100644 infobip_channels/email/models/response/get_sent_bulks.py delete mode 100644 infobip_channels/email/models/response/reschedule_messages.py delete mode 100644 infobip_channels/email/models/response/send_email.py delete mode 100644 infobip_channels/email/models/response/update_scheduled_status.py delete mode 100644 infobip_channels/email/models/response/update_tracking_events.py delete mode 100644 infobip_channels/email/models/response/validate_email_addresses.py delete mode 100644 infobip_channels/mms/__init__.py delete mode 100644 infobip_channels/mms/channel.py delete mode 100644 infobip_channels/mms/models/__init__.py delete mode 100644 infobip_channels/mms/models/body/__init__.py delete mode 100644 infobip_channels/mms/models/body/send_mms.py delete mode 100644 infobip_channels/mms/models/query_parameters/__init__.py delete mode 100644 infobip_channels/mms/models/query_parameters/get_inbound_mms_messages.py delete mode 100644 infobip_channels/mms/models/query_parameters/get_mms_delivery_reports.py delete mode 100644 infobip_channels/mms/models/response/__init__.py delete mode 100644 infobip_channels/mms/models/response/core.py delete mode 100644 infobip_channels/mms/models/response/get_inbound_mms_messages.py delete mode 100644 infobip_channels/mms/models/response/get_mms_delivery_reports.py delete mode 100644 infobip_channels/mms/models/response/send_mms.py delete mode 100644 infobip_channels/rcs/Models/__init__.py delete mode 100644 infobip_channels/rcs/Models/body/__init__.py delete mode 100644 infobip_channels/rcs/Models/body/send_bulk_rcs_message.py delete mode 100644 infobip_channels/rcs/Models/body/send_rcs_message.py delete mode 100644 infobip_channels/rcs/Models/response/__init__.py delete mode 100644 infobip_channels/rcs/Models/response/core.py delete mode 100644 infobip_channels/rcs/__init__.py delete mode 100644 infobip_channels/rcs/channel.py delete mode 100644 infobip_channels/sms/__init__.py delete mode 100644 infobip_channels/sms/channel.py delete mode 100644 infobip_channels/sms/models/__init__.py delete mode 100644 infobip_channels/sms/models/body/__init__.py delete mode 100644 infobip_channels/sms/models/body/core.py delete mode 100644 infobip_channels/sms/models/body/create_tfa_application.py delete mode 100644 infobip_channels/sms/models/body/create_tfa_message_template.py delete mode 100644 infobip_channels/sms/models/body/preview_message.py delete mode 100644 infobip_channels/sms/models/body/reschedule_sms_messages.py delete mode 100644 infobip_channels/sms/models/body/resend_pin_over_sms.py delete mode 100644 infobip_channels/sms/models/body/resend_pin_over_voice.py delete mode 100644 infobip_channels/sms/models/body/send_binary_message.py delete mode 100644 infobip_channels/sms/models/body/send_message.py delete mode 100644 infobip_channels/sms/models/body/send_pin_over_sms.py delete mode 100644 infobip_channels/sms/models/body/send_pin_over_voice.py delete mode 100644 infobip_channels/sms/models/body/update_scheduled_messages_status.py delete mode 100644 infobip_channels/sms/models/body/update_tfa_application.py delete mode 100644 infobip_channels/sms/models/body/update_tfa_message_template.py delete mode 100644 infobip_channels/sms/models/body/verify_phone_number.py delete mode 100644 infobip_channels/sms/models/core/__init__.py delete mode 100644 infobip_channels/sms/models/core/tfa_application.py delete mode 100644 infobip_channels/sms/models/core/tfa_application_configuration.py delete mode 100644 infobip_channels/sms/models/core/tfa_message_template.py delete mode 100644 infobip_channels/sms/models/core/tfa_pin_status.py delete mode 100644 infobip_channels/sms/models/core/tfa_pin_verification.py delete mode 100644 infobip_channels/sms/models/query_parameters/__init__.py delete mode 100644 infobip_channels/sms/models/query_parameters/core.py delete mode 100644 infobip_channels/sms/models/query_parameters/get_inbound_messages.py delete mode 100644 infobip_channels/sms/models/query_parameters/get_outbound_delivery_reports.py delete mode 100644 infobip_channels/sms/models/query_parameters/get_outbound_logs.py delete mode 100644 infobip_channels/sms/models/query_parameters/get_scheduled_messages.py delete mode 100644 infobip_channels/sms/models/query_parameters/get_scheduled_messages_status.py delete mode 100644 infobip_channels/sms/models/query_parameters/get_tfa_verification_status.py delete mode 100644 infobip_channels/sms/models/query_parameters/reschedule_messages.py delete mode 100644 infobip_channels/sms/models/query_parameters/send_message.py delete mode 100644 infobip_channels/sms/models/query_parameters/send_pin_over_sms.py delete mode 100644 infobip_channels/sms/models/query_parameters/send_pin_over_voice.py delete mode 100644 infobip_channels/sms/models/query_parameters/update_scheduled_messages_status.py delete mode 100644 infobip_channels/sms/models/query_parameters/verify_phone_number.py delete mode 100644 infobip_channels/sms/models/response/__init__.py delete mode 100644 infobip_channels/sms/models/response/core.py delete mode 100644 infobip_channels/sms/models/response/create_tfa_application.py delete mode 100644 infobip_channels/sms/models/response/create_tfa_message_template.py delete mode 100644 infobip_channels/sms/models/response/get_scheduled_messages.py delete mode 100644 infobip_channels/sms/models/response/get_scheduled_messages_status.py delete mode 100644 infobip_channels/sms/models/response/get_tfa_application.py delete mode 100644 infobip_channels/sms/models/response/get_tfa_applications.py delete mode 100644 infobip_channels/sms/models/response/get_tfa_message_template.py delete mode 100644 infobip_channels/sms/models/response/get_tfa_message_templates.py delete mode 100644 infobip_channels/sms/models/response/get_tfa_verification_status.py delete mode 100644 infobip_channels/sms/models/response/inbound_messages.py delete mode 100644 infobip_channels/sms/models/response/outbound_delivery_reports.py delete mode 100644 infobip_channels/sms/models/response/outbound_message_logs.py delete mode 100644 infobip_channels/sms/models/response/preview_message.py delete mode 100644 infobip_channels/sms/models/response/reschedule_sms_messages.py delete mode 100644 infobip_channels/sms/models/response/resend_pin_over_sms.py delete mode 100644 infobip_channels/sms/models/response/resend_pin_over_voice.py delete mode 100644 infobip_channels/sms/models/response/send_message.py delete mode 100644 infobip_channels/sms/models/response/send_pin_over_sms.py delete mode 100644 infobip_channels/sms/models/response/send_pin_over_voice.py delete mode 100644 infobip_channels/sms/models/response/update_scheduled_messages_status.py delete mode 100644 infobip_channels/sms/models/response/update_tfa_application.py delete mode 100644 infobip_channels/sms/models/response/update_tfa_message_template.py delete mode 100644 infobip_channels/sms/models/response/verify_phone_number.py delete mode 100644 infobip_channels/web_rtc/__init__.py delete mode 100644 infobip_channels/web_rtc/channel.py delete mode 100644 infobip_channels/web_rtc/models/__init__.py delete mode 100644 infobip_channels/web_rtc/models/body/__init__.py delete mode 100644 infobip_channels/web_rtc/models/body/core.py delete mode 100644 infobip_channels/web_rtc/models/body/generate_token.py delete mode 100644 infobip_channels/web_rtc/models/body/save_application.py delete mode 100644 infobip_channels/web_rtc/models/body/update_application.py delete mode 100644 infobip_channels/web_rtc/models/path_parameters/__init__.py delete mode 100644 infobip_channels/web_rtc/models/path_parameters/core.py delete mode 100644 infobip_channels/web_rtc/models/path_parameters/web_rtc_application.py delete mode 100644 infobip_channels/web_rtc/models/response/__init__.py delete mode 100644 infobip_channels/web_rtc/models/response/core.py delete mode 100644 infobip_channels/web_rtc/models/response/generate_token.py delete mode 100644 infobip_channels/web_rtc/models/response/get_applications.py delete mode 100644 infobip_channels/whatsapp/__init__.py delete mode 100644 infobip_channels/whatsapp/channel.py delete mode 100644 infobip_channels/whatsapp/models/__init__.py delete mode 100644 infobip_channels/whatsapp/models/body/__init__.py delete mode 100644 infobip_channels/whatsapp/models/body/action_sections.py delete mode 100644 infobip_channels/whatsapp/models/body/audio_message.py delete mode 100644 infobip_channels/whatsapp/models/body/buttons_message.py delete mode 100644 infobip_channels/whatsapp/models/body/contact_message.py delete mode 100644 infobip_channels/whatsapp/models/body/core.py delete mode 100644 infobip_channels/whatsapp/models/body/create_template.py delete mode 100644 infobip_channels/whatsapp/models/body/document_message.py delete mode 100644 infobip_channels/whatsapp/models/body/image_message.py delete mode 100644 infobip_channels/whatsapp/models/body/list_message.py delete mode 100644 infobip_channels/whatsapp/models/body/location_message.py delete mode 100644 infobip_channels/whatsapp/models/body/multi_product_message.py delete mode 100644 infobip_channels/whatsapp/models/body/product_message.py delete mode 100644 infobip_channels/whatsapp/models/body/sticker_message.py delete mode 100644 infobip_channels/whatsapp/models/body/template_message.py delete mode 100644 infobip_channels/whatsapp/models/body/text_message.py delete mode 100644 infobip_channels/whatsapp/models/body/video_message.py delete mode 100644 infobip_channels/whatsapp/models/path_parameters/__init__.py delete mode 100644 infobip_channels/whatsapp/models/path_parameters/core.py delete mode 100644 infobip_channels/whatsapp/models/path_parameters/delete_template.py delete mode 100644 infobip_channels/whatsapp/models/path_parameters/manage_templates.py delete mode 100644 infobip_channels/whatsapp/models/response/__init__.py delete mode 100644 infobip_channels/whatsapp/models/response/core.py delete mode 100644 infobip_channels/whatsapp/models/response/create_template.py delete mode 100644 infobip_channels/whatsapp/models/response/get_templates.py delete mode 100644 infobip_channels/whatsapp/models/response/template_message.py delete mode 100644 infobip_platform/__init__.py delete mode 100644 infobip_platform/app_entities/__init__.py delete mode 100644 infobip_platform/app_entities/api.py delete mode 100644 infobip_platform/app_entities/models/__init__.py delete mode 100644 infobip_platform/app_entities/models/body/__init__.py delete mode 100644 infobip_platform/app_entities/models/body/create_entity.py delete mode 100644 infobip_platform/app_entities/models/body/modify_entity.py delete mode 100644 infobip_platform/app_entities/models/core/__init__.py delete mode 100644 infobip_platform/app_entities/models/core/entity.py delete mode 100644 infobip_platform/app_entities/models/query_parameters/__init__.py delete mode 100644 infobip_platform/app_entities/models/query_parameters/get_entities.py delete mode 100644 infobip_platform/app_entities/models/response/__init__.py delete mode 100644 infobip_platform/app_entities/models/response/core.py delete mode 100644 infobip_platform/app_entities/models/response/create_entity.py delete mode 100644 infobip_platform/app_entities/models/response/get_entities.py delete mode 100644 infobip_platform/app_entities/models/response/get_entity.py delete mode 100644 infobip_platform/app_entities/models/response/modify_entity.py create mode 100644 models/__init__.py create mode 100644 models/application.py create mode 100644 models/channel.py create mode 100644 models/entity.py create mode 100644 models/message_error.py create mode 100644 models/message_price.py create mode 100644 models/message_status.py create mode 100644 models/mms_advanced_message.py create mode 100644 models/mms_advanced_message_segment.py create mode 100644 models/mms_advanced_message_segment_binary.py create mode 100644 models/mms_advanced_message_segment_link.py create mode 100644 models/mms_advanced_message_segment_smil.py create mode 100644 models/mms_advanced_message_segment_text.py create mode 100644 models/mms_advanced_message_segment_upload_reference.py create mode 100644 models/mms_advanced_request.py create mode 100644 models/mms_delivery_day.py create mode 100644 models/mms_delivery_time.py create mode 100644 models/mms_delivery_time_window.py create mode 100644 models/mms_destination.py create mode 100644 models/mms_error.py create mode 100644 models/mms_inbound_report.py create mode 100644 models/mms_inbound_report_response.py create mode 100644 models/mms_message_result.py create mode 100644 models/mms_price.py create mode 100644 models/mms_report.py create mode 100644 models/mms_report_response.py create mode 100644 models/mms_send_result.py create mode 100644 models/mms_status.py create mode 100644 models/mms_upload_binary_result.py create mode 100644 models/mms_webhook_inbound_message_segment.py create mode 100644 models/mms_webhook_inbound_message_segment_link.py create mode 100644 models/mms_webhook_inbound_message_segment_text.py create mode 100644 models/mms_webhook_inbound_report.py create mode 100644 models/mms_webhook_inbound_report_response.py create mode 100644 models/mms_webhook_outbound_report.py create mode 100644 models/mms_webhook_outbound_report_response.py create mode 100644 models/modify_application.py create mode 100644 models/modify_entity.py create mode 100644 models/number_price.py create mode 100644 models/number_registration_address.py create mode 100644 models/number_registration_brand.py create mode 100644 models/number_registration_brand_preview.py create mode 100644 models/number_registration_brand_status.py create mode 100644 models/number_registration_brand_vet.py create mode 100644 models/number_registration_business_identifier.py create mode 100644 models/number_registration_campaign.py create mode 100644 models/number_registration_data_universal_numbering_system_number.py create mode 100644 models/number_registration_document_metadata.py create mode 100644 models/number_registration_external_ten_dlc_campaign.py create mode 100644 models/number_registration_global_intermediary_identification_number.py create mode 100644 models/number_registration_government_brand.py create mode 100644 models/number_registration_interactive_voice_response_opt_in.py create mode 100644 models/number_registration_keyword_opt_in.py create mode 100644 models/number_registration_legal_entity_identifier.py create mode 100644 models/number_registration_network_status.py create mode 100644 models/number_registration_non_profit_brand.py create mode 100644 models/number_registration_number_preview.py create mode 100644 models/number_registration_opt_ins.py create mode 100644 models/number_registration_page_info.py create mode 100644 models/number_registration_page_response_brand.py create mode 100644 models/number_registration_page_response_brand_vet.py create mode 100644 models/number_registration_page_response_campaign.py create mode 100644 models/number_registration_private_company_brand.py create mode 100644 models/number_registration_public_company_brand.py create mode 100644 models/number_registration_ten_dlc_campaign.py create mode 100644 models/number_registration_update_brand_request.py create mode 100644 models/number_registration_update_campaign_request.py create mode 100644 models/number_registration_verbal_opt_in.py create mode 100644 models/number_registration_web_opt_in.py create mode 100644 models/number_response.py create mode 100644 models/numbers_auto_response_action.py create mode 100644 models/numbers_block_action.py create mode 100644 models/numbers_delivery_time_window.py create mode 100644 models/numbers_edit_permissions.py create mode 100644 models/numbers_forward_to_ivr_action_details.py create mode 100644 models/numbers_forward_to_subscription_details.py create mode 100644 models/numbers_http_forward_action.py create mode 100644 models/numbers_mail_forward_action.py create mode 100644 models/numbers_mo_action.py create mode 100644 models/numbers_mo_configuration.py create mode 100644 models/numbers_mo_configurations.py create mode 100644 models/numbers_mo_non_forward_action.py create mode 100644 models/numbers_no_action.py create mode 100644 models/numbers_pull_action.py create mode 100644 models/numbers_purchase_number_request.py create mode 100644 models/numbers_response.py create mode 100644 models/numbers_smpp_forward_action.py create mode 100644 models/numbers_stored_mo_configuration.py create mode 100644 models/numbers_use_conversation.py create mode 100644 models/numbers_voice_action_details.py create mode 100644 models/numbers_voice_call_forward_to_application_details.py create mode 100644 models/numbers_voice_number_masking_action_details.py create mode 100644 models/numbers_voice_setup.py create mode 100644 models/page_application.py create mode 100644 models/page_entity.py create mode 100644 models/page_info.py create mode 100644 models/page_resource_association.py create mode 100644 models/resource_association_request.py create mode 100644 models/resource_association_response.py create mode 100644 models/resource_type.py create mode 100644 models/sms_advanced_binary_request.py create mode 100644 models/sms_advanced_textual_request.py create mode 100644 models/sms_binary_content.py create mode 100644 models/sms_binary_message.py create mode 100644 models/sms_bulk_request.py create mode 100644 models/sms_bulk_response.py create mode 100644 models/sms_bulk_status.py create mode 100644 models/sms_bulk_status_response.py create mode 100644 models/sms_delivery_day.py create mode 100644 models/sms_delivery_result.py create mode 100644 models/sms_delivery_time_from.py create mode 100644 models/sms_delivery_time_to.py create mode 100644 models/sms_delivery_time_window.py create mode 100644 models/sms_destination.py create mode 100644 models/sms_error.py create mode 100644 models/sms_inbound_message.py create mode 100644 models/sms_inbound_message_result.py create mode 100644 models/sms_india_dlt_options.py create mode 100644 models/sms_language.py create mode 100644 models/sms_language_configuration.py create mode 100644 models/sms_log.py create mode 100644 models/sms_logs_response.py create mode 100644 models/sms_preview.py create mode 100644 models/sms_preview_request.py create mode 100644 models/sms_preview_response.py create mode 100644 models/sms_price.py create mode 100644 models/sms_regional_options.py create mode 100644 models/sms_report.py create mode 100644 models/sms_response.py create mode 100644 models/sms_response_details.py create mode 100644 models/sms_sending_speed_limit.py create mode 100644 models/sms_speed_limit_time_unit.py create mode 100644 models/sms_status.py create mode 100644 models/sms_textual_message.py create mode 100644 models/sms_tracking.py create mode 100644 models/sms_turkey_iys_options.py create mode 100644 models/sms_update_status_request.py create mode 100644 models/sms_url_options.py create mode 100644 models/sms_webhook_inbound_report.py create mode 100644 models/sms_webhook_inbound_report_response.py create mode 100644 models/sms_webhook_outbound_report.py create mode 100644 models/sms_webhook_outbound_report_response.py create mode 100644 models/webhook_message_count.py create mode 100644 requirements.txt delete mode 100644 requirements/common.txt delete mode 100644 requirements/dev.txt delete mode 100644 samples/app_entity_management/test_entity_management.py create mode 100644 samples/test_sms_live.py delete mode 100644 samples/tfa/test_tfa.py delete mode 100644 samples/whatsapp/test_whatsapp.py delete mode 100644 tests/app_entities/conftest.py delete mode 100644 tests/app_entities/integration/test_create_entity_body.py delete mode 100644 tests/app_entities/integration/test_create_entity_body_cases.py delete mode 100644 tests/app_entities/integration/test_get_entities_query.py delete mode 100644 tests/app_entities/integration/test_get_entities_query_cases.py delete mode 100644 tests/app_entities/integration/test_get_entity_path.py delete mode 100644 tests/app_entities/integration/test_get_entity_path_cases.py delete mode 100644 tests/app_entities/integration/test_modify_entity_body_path.py delete mode 100644 tests/app_entities/integration/test_modify_entity_body_path_cases.py delete mode 100644 tests/app_entities/models/test_create_entity.py delete mode 100644 tests/app_entities/models/test_get_entities.py delete mode 100644 tests/app_entities/models/test_modify_entity.py delete mode 100644 tests/conftest.py delete mode 100644 tests/email/conftest.py delete mode 100644 tests/email/integration/test_email_endpoints_integration.py delete mode 100644 tests/email/integration/test_email_endpoints_integration_cases.py delete mode 100644 tests/email/integration/test_email_with_body_integration.py delete mode 100644 tests/email/integration/test_email_with_body_integration_cases.py delete mode 100644 tests/email/models/test_add_new_domain.py delete mode 100644 tests/email/models/test_delete_existing_domain.py delete mode 100644 tests/email/models/test_delivery_reports.py delete mode 100644 tests/email/models/test_get_all_domains.py delete mode 100644 tests/email/models/test_get_domain_details.py delete mode 100644 tests/email/models/test_get_logs.py delete mode 100644 tests/email/models/test_get_sent_bulk_status.py delete mode 100644 tests/email/models/test_get_sent_bulks.py delete mode 100644 tests/email/models/test_reschedule_messages.py delete mode 100644 tests/email/models/test_send_email.py delete mode 100644 tests/email/models/test_update_scheduled_status.py delete mode 100644 tests/email/models/test_update_tracking_events.py delete mode 100644 tests/email/models/test_validate_email_adresses.py delete mode 100644 tests/mms/conftest.py delete mode 100644 tests/mms/integration/test_endpoints_integration.py delete mode 100644 tests/mms/integration/test_endpoints_integration_cases.py delete mode 100644 tests/mms/models/test_get_inbound_mms_messages.py delete mode 100644 tests/mms/models/test_get_mms_delivery_reports.py delete mode 100644 tests/mms/models/test_send_mms.py delete mode 100644 tests/rcs/conftest.py delete mode 100644 tests/rcs/integration/test_rcs_endpoints.py delete mode 100644 tests/rcs/integration/test_rcs_endpoints_cases.py delete mode 100644 tests/rcs/models/test_send_bulk_rcs_message.py delete mode 100644 tests/rcs/models/test_send_rcs_message.py delete mode 100644 tests/sms/conftest.py delete mode 100644 tests/sms/integration/test_reschedule_and_update.py delete mode 100644 tests/sms/integration/test_reschedule_and_update_cases.py delete mode 100644 tests/sms/integration/test_send_sms_body_endpoints.py delete mode 100644 tests/sms/integration/test_send_sms_body_endpoints_cases.py delete mode 100644 tests/sms/integration/test_sms_query_endpoints.py delete mode 100644 tests/sms/integration/test_sms_query_endpoints_cases.py delete mode 100644 tests/sms/integration/test_tfa_create_and_update_path.py delete mode 100644 tests/sms/integration/test_tfa_create_and_update_path_cases.py delete mode 100644 tests/sms/integration/test_tfa_create_application.py delete mode 100644 tests/sms/integration/test_tfa_create_application_cases.py delete mode 100644 tests/sms/integration/test_tfa_get.py delete mode 100644 tests/sms/integration/test_tfa_get_cases.py delete mode 100644 tests/sms/integration/test_tfa_get_path.py delete mode 100644 tests/sms/integration/test_tfa_get_path_cases.py delete mode 100644 tests/sms/integration/test_tfa_get_path_query.py delete mode 100644 tests/sms/integration/test_tfa_get_path_query_cases.py delete mode 100644 tests/sms/integration/test_tfa_get_template_path.py delete mode 100644 tests/sms/integration/test_tfa_get_template_path_cases.py delete mode 100644 tests/sms/integration/test_tfa_resend_verify_pin_path.py delete mode 100644 tests/sms/integration/test_tfa_resend_verify_pin_path_cases.py delete mode 100644 tests/sms/integration/test_tfa_send_pin.py delete mode 100644 tests/sms/integration/test_tfa_send_pin_cases.py delete mode 100644 tests/sms/integration/test_tfa_update_template_path.py delete mode 100644 tests/sms/integration/test_tfa_update_template_path_cases.py delete mode 100644 tests/sms/models/test_create_tfa_application.py delete mode 100644 tests/sms/models/test_create_tfa_message_template.py delete mode 100644 tests/sms/models/test_get_scheduled_messages.py delete mode 100644 tests/sms/models/test_get_scheduled_messages_status.py delete mode 100644 tests/sms/models/test_inbound_messages.py delete mode 100644 tests/sms/models/test_outbound_delivery_reports.py delete mode 100644 tests/sms/models/test_outbound_logs.py delete mode 100644 tests/sms/models/test_preview.py delete mode 100644 tests/sms/models/test_reschedule_sms_messages.py delete mode 100644 tests/sms/models/test_send.py delete mode 100644 tests/sms/models/test_send_binary.py delete mode 100644 tests/sms/models/test_send_pin.py delete mode 100644 tests/sms/models/test_send_query.py delete mode 100644 tests/sms/models/test_update_scheduled_messages_status.py delete mode 100644 tests/sms/models/test_update_tfa_application.py delete mode 100644 tests/sms/models/test_verify_phone_number.py delete mode 100644 tests/test_core.py create mode 100644 tests/test_sms.py delete mode 100644 tests/webrtc/conftest.py delete mode 100644 tests/webrtc/integration/test_webrtc_endpoints_with_body.py delete mode 100644 tests/webrtc/integration/test_webrtc_endpoints_with_body_cases.py delete mode 100644 tests/webrtc/integration/test_webrtc_endpoints_without_body.py delete mode 100644 tests/webrtc/integration/test_webrtc_endpoints_without_body_cases.py delete mode 100644 tests/webrtc/models/test_generate_token.py delete mode 100644 tests/webrtc/models/test_save_application.py delete mode 100644 tests/whatsapp/conftest.py delete mode 100644 tests/whatsapp/integration/test_create_template_integration.py delete mode 100644 tests/whatsapp/integration/test_create_template_integration_cases.py delete mode 100644 tests/whatsapp/integration/test_delete_template_integration.py delete mode 100644 tests/whatsapp/integration/test_delete_template_integration_cases.py delete mode 100644 tests/whatsapp/integration/test_get_templates.py delete mode 100644 tests/whatsapp/integration/test_get_templates_cases.py delete mode 100644 tests/whatsapp/integration/test_send_message.py delete mode 100644 tests/whatsapp/integration/test_send_message_cases.py delete mode 100644 tests/whatsapp/models/test_audio_message.py delete mode 100644 tests/whatsapp/models/test_buttons_message.py delete mode 100644 tests/whatsapp/models/test_contact_message.py delete mode 100644 tests/whatsapp/models/test_core_models.py delete mode 100644 tests/whatsapp/models/test_create_template.py delete mode 100644 tests/whatsapp/models/test_delete_template.py delete mode 100644 tests/whatsapp/models/test_document_message.py delete mode 100644 tests/whatsapp/models/test_image_message.py delete mode 100644 tests/whatsapp/models/test_list_message.py delete mode 100644 tests/whatsapp/models/test_location_message.py delete mode 100644 tests/whatsapp/models/test_multi_product_message.py delete mode 100644 tests/whatsapp/models/test_product_message.py delete mode 100644 tests/whatsapp/models/test_sticker_message.py delete mode 100644 tests/whatsapp/models/test_template_message.py delete mode 100644 tests/whatsapp/models/test_text_message.py delete mode 100644 tests/whatsapp/models/test_video_message.py diff --git a/infobip_channels/core/__init__.py b/api/__init__.py similarity index 100% rename from infobip_channels/core/__init__.py rename to api/__init__.py diff --git a/api/sms.py b/api/sms.py new file mode 100644 index 0000000..3d401c1 --- /dev/null +++ b/api/sms.py @@ -0,0 +1,43 @@ +from collections.abc import Awaitable + +from httpx import AsyncClient, Response + +from models import SendRequestBody +from models.sms_preview_request import PreviewSMSRequestBody + + +class SMSClient: + PATH_PREVIEW_SMS = "/sms/1/preview" + PATH_SEND_SMS = "/sms/2/text/advanced" + + def __init__(self, client: AsyncClient): + self.client = client + self.client.headers.update({"content-type": "application/json"}) + + def preview_message( + self, request_body: PreviewSMSRequestBody + ) -> Awaitable[Response]: + """Check how different message configurations will affect your message text, number of characters and message + parts. + + :param request_body: Request body for previewing an SMS message + """ + + return self.client.post( + self.PATH_PREVIEW_SMS, + json=request_body.to_dict(), + ) + + def send( + self, + request_body: SendRequestBody, + ) -> Awaitable[Response]: + """Send SMS message + + :param request_body: Request body for sending an SMS message + """ + + return self.client.post( + self.PATH_SEND_SMS, + json=request_body.to_dict(), + ) diff --git a/client.py b/client.py new file mode 100644 index 0000000..dade456 --- /dev/null +++ b/client.py @@ -0,0 +1,18 @@ +from os import getenv +from httpx import AsyncClient +from api.sms import SMSClient + + +class InfobipAPIClient(AsyncClient): + def __init__(self, base_url=None, api_key: str = None): + if base_url is None: + base_url = getenv("IB_BASE_URL") + if api_key is None: + api_key = getenv("IB_API_KEY") + + headers = {"Authorization": f"App {api_key}"} + headers.update({"User-Agent": "infobip-api-python-sdk/6.0.0"}) + + super().__init__(base_url=base_url, headers=headers) + + self.SMS = SMSClient(self) diff --git a/infobip_channels/__init__.py b/infobip_channels/__init__.py deleted file mode 100644 index 3c4d5d7..0000000 --- a/infobip_channels/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -from .email.channel import EmailChannel -from .mms.channel import MMSChannel -from .rcs.channel import RCSChannel -from .sms.channel import SMSChannel -from .web_rtc.channel import WebRtcChannel -from .whatsapp.channel import WhatsAppChannel - -__all__ = [ - "WhatsAppChannel", - "WebRtcChannel", - "MMSChannel", - "RCSChannel", - "SMSChannel", - "EmailChannel", -] diff --git a/infobip_channels/core/channel.py b/infobip_channels/core/channel.py deleted file mode 100644 index 34e1561..0000000 --- a/infobip_channels/core/channel.py +++ /dev/null @@ -1,239 +0,0 @@ -import os -from abc import ABC, abstractmethod -from typing import Any, Dict, Type, Union - -import requests -from pydantic import AnyHttpUrl, BaseModel, ValidationError - -from infobip_channels.core.http_client import _HttpClient -from infobip_channels.core.models import ( - Authentication, - DeleteHeaders, - GetHeaders, - MessageBodyBase, - PathParameter, - PostHeaders, - PutHeaders, - QueryParameter, - ResponseBase, -) - - -class Channel(ABC): - """Parent class for all Infobip channels.""" - - def __init__(self, client: Union[_HttpClient, Any]) -> None: - self._client = client - - @classmethod - def from_auth_params(cls, auth_params: Dict[str, str]) -> "Channel": - """Create an Authentication instance from the provided dictionary and - use it to instantiate the Channel subclass. Dictionary has to contain - "base_url" and "api_key" to be able to authenticate with the Infobip's API. - The Channel subclass instantiated this way will use the default _HttpClient - class for making HTTP requests. - - :param auth_params: Dictionary containing "base_url" and "api_key" - :return: Instance of the subclass - """ - client = _HttpClient(Authentication(**auth_params)) - return cls(client) - - @classmethod - def from_env(cls) -> "Channel": - """Create an Authentication instance from the environment and - use it to instantiate the Channel subclass. The IB_API_KEY and IB_BASE_URL environment variables must be set. - The Channel subclass instantiated this way will use the default _HttpClient - class for making HTTP requests. Keep in mind that you may have set those variables in another context; make - sure that the correct values are set in this process’ specific context and are not overridden somewhere else - in the program flow. - - :return: Instance of the subclass - """ - base_url = os.environ.get("IB_BASE_URL") - api_key = os.environ.get("IB_API_KEY") - - auth_params = {"base_url": base_url, "api_key": api_key} - client = _HttpClient(Authentication(**auth_params)) - return cls(client) - - @classmethod - def from_auth_instance(cls, auth_instance: Authentication) -> "Channel": - """Instantiate the Channel subclass with the provided auth object. - The Channel subclass instantiated this way will use the default _HttpClient - class for making HTTP requests. - - :param: auth_instance: Authentication class instance - :return: Instance of the subclass - """ - client = _HttpClient(auth_instance) - return cls(client) - - @classmethod - def from_provided_client(cls, client: Any) -> "Channel": - """Instantiate the Channel subclass with the provided client object. - The Channel subclass instantiated this way will use the provided client for - making HTTP requests. This client can implement its own retry mechanisms, - timeouts, etc., but it has to implement all the methods used in the default - _HttpClient class. When using the Channel subclass this way, the user has to - take care of providing a valid base_url and constructing headers to be used for - every Channel subclass request. - - :param client: Client used for making HTTP requests - :return: Instance of the subclass - """ - return cls(client) - - @staticmethod - def validate_query_parameter( - parameter: Union[QueryParameter, Dict], parameter_type: Type[QueryParameter] - ) -> QueryParameter: - """ - Validate the query parameter by trying to instantiate the provided class. - If the passed parameter is already of that type, just return it as is. - - :param parameter: Query parameter to validate - :param parameter_type: Type of the query parameter - :return: Class instance corresponding to the provided parameter type - """ - return ( - parameter - if isinstance(parameter, parameter_type) - else parameter_type(**parameter) - ) - - @staticmethod - def validate_auth_params( - base_url: Union[AnyHttpUrl, str], api_key: str - ) -> Authentication: - """Validate the provided base_url and api_key. This validation is purely client - side. If the parameters are validated successfully, an instance of the - Authentication class is returned which holds the base_url and api_key values. - - :param base_url: Base url which the requests will call for each endpoint - :param api_key: Secret used for authenticating the user - :return: Authentication class instance - """ - return Authentication(base_url=base_url, api_key=api_key) - - @staticmethod - def build_post_request_headers(api_key: str) -> Dict: - """Build the request headers dictionary which has to be used for each of the - post requests. - - :param api_key: Key used for populating Authorization header - :return: Dictionary of headers to be used for post requests - """ - return PostHeaders(authorization=api_key).dict(by_alias=True) - - @staticmethod - def build_put_request_headers(api_key: str) -> Dict: - """Build the request headers dictionary which has to be used for each of the - put requests. - - :param api_key: Key used for populating Authorization header - :return: Dictionary of headers to be used for post requests - """ - return PutHeaders(authorization=api_key).dict(by_alias=True) - - @staticmethod - def build_get_request_headers(api_key: str) -> Dict: - """Build the request headers dictionary which has to be used for each of the - get requests. - - :param api_key: Key used for populating Authorization header - :return: Dictionary of headers to be used for get requests - """ - return GetHeaders(authorization=api_key).dict(by_alias=True) - - @staticmethod - def build_delete_request_headers(api_key: str) -> Dict: - """Build the request headers dictionary which has to be used for each of the - delete requests. - - :param api_key: Key used for populating Authorization header - :return: Dictionary of headers to be used for get requests - """ - return DeleteHeaders(authorization=api_key).dict(by_alias=True) - - @staticmethod - def convert_model_to_dict( - model: BaseModel, by_alias: bool = True, exclude_unset: bool = True, **kwargs - ) -> Dict: - """ - Convert the Pydantic model into a Python dictionary. By default, model is - converted with by_alias=True and exclude_unset=True flags. The former changes - model fields to camel case and the latter omits the fields which were not - received from the server originally. - For additional flags, check Pydantic's documentation on exporting models: - https://pydantic-docs.helpmanual.io/usage/exporting_models/. - - :param model: Pydantic model to convert - :param by_alias: Whether the model should be converted with aliased fields - :param exclude_unset: Whether the model's unset values should be omitted - :return: Dictionary of the converted model - """ - return model.dict(by_alias=by_alias, exclude_unset=exclude_unset, **kwargs) - - @staticmethod - def validate_path_parameter( - parameter: Union[PathParameter, Dict], parameter_type: Type[PathParameter] - ) -> Union[PathParameter]: - """ - Validate path parameter by trying to instantiate the provided class and - extract valid path parameter. - - :param parameter: Path parameter to validate - :param parameter_type: Type of path parameter - :return: Class instance corresponding to the provided parameter type - """ - return ( - parameter - if isinstance(parameter, parameter_type) - else parameter_type(**parameter) - ) - - @staticmethod - def validate_message_body( - message: Union[MessageBodyBase, Dict], - message_type: Type[MessageBodyBase], - ) -> Union[MessageBodyBase]: - """Validate the message by trying to instantiate the provided type class. - If the passed message is already of that type, just return it as is. - - :param message: Message body to validate - :param message_type: Type of the message body - :return: Class instance corresponding to the provided message body type - """ - return message if isinstance(message, message_type) else message_type(**message) - - def _construct_response( - self, raw_response: Union[requests.Response, Any], *args, **kwargs - ) -> Union[ResponseBase, requests.Response, Any]: - try: - response_class = self._get_custom_response_class( - raw_response, *args, **kwargs - ) - - response_json = raw_response.json() - if type(response_json) is list: - raw_response_data = {"list": response_json} - else: - raw_response_data = response_json - - return response_class( - **{ - "status_code": raw_response.status_code, - "raw_response": raw_response, - **raw_response_data, - } - ) - - except (AttributeError, ValueError, ValidationError): - return raw_response - - @abstractmethod - def _get_custom_response_class( - self, raw_response: Union[requests.Response, Any], *args, **kwargs - ) -> Type[ResponseBase]: - raise NotImplementedError diff --git a/infobip_channels/core/http_client.py b/infobip_channels/core/http_client.py deleted file mode 100644 index 12df709..0000000 --- a/infobip_channels/core/http_client.py +++ /dev/null @@ -1,114 +0,0 @@ -from typing import Dict, Union - -import requests - -from infobip_channels.core.models import ( - Authentication, - DeleteHeaders, - GetHeaders, - PostHeaders, - PutHeaders, - RequestHeaders, -) - - -class _HttpClient: - """Default HTTP client used by the Infobip channels for making HTTP requests.""" - - def __init__( - self, - auth: Authentication, - post_headers: RequestHeaders = None, - get_headers: RequestHeaders = None, - put_headers: RequestHeaders = None, - delete_headers: RequestHeaders = None, - ): - """Create an instance of the _HttpClient class with the provided - authentication model instance. Headers can optionally be provided, otherwise - default instances will be created. These headers will be used as defaults in - the HTTP methods, unless new values are sent through method arguments. - """ - self.auth = auth - self.post_headers = post_headers or PostHeaders(authorization=self.auth.api_key) - self.get_headers = get_headers or GetHeaders(authorization=self.auth.api_key) - self.put_headers = put_headers or PutHeaders(authorization=self.auth.api_key) - self.delete_headers = delete_headers or DeleteHeaders( - authorization=self.auth.api_key - ) - - def post( - self, - endpoint: str, - body: Union[Dict, bytes] = None, - headers: RequestHeaders = None, - params: Dict = None, - ) -> requests.Response: - """Send an HTTP post request to base_url + endpoint. - - :param endpoint: Which endpoint to hit - :param body: Body to send with the request - :param headers: Request headers - :param params: Additional parameters - :return: Received response - """ - headers = headers or self.post_headers - url = self.auth.base_url + endpoint - - if isinstance(body, dict): - kwargs = {"json": body} - else: - kwargs = {"data": body} - - kwargs.setdefault("params", params) - - return requests.post(url=url, headers=headers.dict(by_alias=True), **kwargs) - - def get( - self, endpoint: str, headers: RequestHeaders = None, params: Dict = None - ) -> requests.Response: - """Send an HTTP get request to base_url + endpoint. - :param endpoint: Which endpoint to hit - :param headers: Request headers - :param params: Dictionary of query parameters - :return: Received response - """ - headers = headers or self.get_headers - url = self.auth.base_url + endpoint - - return requests.get(url=url, headers=headers.dict(by_alias=True), params=params) - - def put( - self, - endpoint: str, - body: Dict, - headers: RequestHeaders = None, - params: Dict = None, - ) -> requests.Response: - """Send an HTTP put request to base_url + endpoint. - - :param endpoint: Which endpoint to hit - :param headers: Request headers - :param body: Body to send with the request - :param params: Dictionary of query parameters - :return: Received response - """ - headers = headers or self.put_headers - url = self.auth.base_url + endpoint - - return requests.put( - url=url, json=body, headers=headers.dict(by_alias=True), params=params - ) - - def delete( - self, endpoint: str, headers: RequestHeaders = None - ) -> requests.Response: - """Send an HTTP delete request to base_url + endpoint. - - :param endpoint: Which endpoint to hit - :param headers: Request headers - :return: Received response - """ - headers = headers or self.delete_headers - url = self.auth.base_url + endpoint - - return requests.delete(url=url, headers=headers.dict(by_alias=True)) diff --git a/infobip_channels/core/models.py b/infobip_channels/core/models.py deleted file mode 100644 index c9d48e6..0000000 --- a/infobip_channels/core/models.py +++ /dev/null @@ -1,386 +0,0 @@ -import json -import os -import sys -import urllib.parse -import xml.etree.ElementTree as ET -from datetime import datetime, timedelta, timezone -from enum import Enum -from http import HTTPStatus -from typing import Any, Dict, List, Optional, Tuple, Union - -import pkg_resources -import requests -from pydantic import AnyHttpUrl, BaseModel, constr, validator -from urllib3 import encode_multipart_formdata - - -def to_camel_case(string: str) -> str: - output = "".join(word.capitalize() for word in string.split("_")) - return output[0].lower() + output[1:] - - -def to_header_specific_case(string: str) -> str: - return "-".join(word.capitalize() for word in string.split("_")) - - -def get_package_version() -> str: - sdk_version = "" - if "infobip_channels" in sys.modules: - try: - sdk_version = ( - "/" + pkg_resources.get_distribution("infobip-api-python-sdk").version - ) - except pkg_resources.DistributionNotFound: - # Ignore as package is not installed in development environment. - pass - - return sdk_version - - -def url_encoding(string_to_encode: str, safe: str = "", encoding: str = "utf-8") -> str: - """ - Special characters and user credentials are properly encoded. - Use a URL encoding reference as a guide: - https://www.w3schools.com/tags/ref_urlencode.asp - - The optional safe parameter specifies additional ASCII characters - that should not be quoted — its default value is '/'. - """ - return urllib.parse.quote( - string_to_encode, safe=safe, encoding=encoding, errors=None - ) - - -class Authentication(BaseModel): - base_url: AnyHttpUrl - api_key: constr(min_length=1) - - @validator("base_url", pre=True) - def validate_scheme(cls, value: str) -> str: - if not isinstance(value, str): - return value - - if value.startswith(("http://", "https://")): - return value - - return f"https://{value}" - - -class UrlLengthValidatorMixin: - _MAX_URL_LENGTH = 2048 - - @classmethod - def validate_url_length(cls, value: str) -> str: - if not isinstance(value, str): - return value - - if len(value) > cls._MAX_URL_LENGTH: - raise ValueError(f"Url length must be less than {cls._MAX_URL_LENGTH}") - - return value - - -class FromAndToTimeValidator: - _MINIMUM_DELIVERY_WINDOW_MINUTES = 60 - - @classmethod - def _validate_time_differences(cls, from_time, to_time): - from_time_in_minutes = from_time.hour * 60 + from_time.minute - to_time_in_minutes = to_time.hour * 60 + to_time.minute - - if ( - to_time_in_minutes - from_time_in_minutes - < cls._MINIMUM_DELIVERY_WINDOW_MINUTES - ): - raise ValueError( - f"Minimum of {cls._MINIMUM_DELIVERY_WINDOW_MINUTES} minutes has to pass " - f"between from and to delivery window times." - ) - - @classmethod - def validate_from_and_to(cls, values): - if not values.get("from_time") and not values.get("to"): - return values - - if values.get("from_time") and not values.get("to"): - raise ValueError("If 'from_time' is set, 'to' has to be set also") - - if values.get("to") and not values.get("from_time"): - raise ValueError("If 'to' is set, 'from_time' has to be set also") - - cls._validate_time_differences(values["from_time"], values["to"]) - - return values - - -class DateTimeValidator: - _TIME_LIMIT = 180 - _EXPECTED_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ" - - @classmethod - def convert_to_date_time_format(cls, value): - if not value: - return - if isinstance(value, str): - value = datetime.fromisoformat(value) - - return value - - @classmethod - def convert_time_to_correct_format(cls, value) -> str: - date_time_format = cls.convert_to_date_time_format(value) - - return date_time_format.strftime(cls._EXPECTED_TIME_FORMAT) - - @classmethod - def convert_time_to_correct_format_validate_limit(cls, value): - date_time_format = cls.convert_to_date_time_format(value) - date_time_limit = datetime.now(timezone.utc) + timedelta(days=cls._TIME_LIMIT) - if date_time_format > date_time_limit: - raise ValueError( - "Scheduled message must be sooner than 180 days from today" - ) - - return value.strftime(cls._EXPECTED_TIME_FORMAT) - - -class CamelCaseModel(BaseModel): - class Config: - alias_generator = to_camel_case - allow_population_by_field_name = True - - -class MessageBodyBase(CamelCaseModel): - pass - - -class ResponseBase(CamelCaseModel): - status_code: HTTPStatus - raw_response: requests.Response - - class Config(CamelCaseModel.Config): - arbitrary_types_allowed = True - - -class ResponseStatus(CamelCaseModel): - group_id: int - group_name: str - id: int - name: str - description: str - action: Optional[str] = None - - -class RequestHeaders(BaseModel): - authorization: str - accept: Optional[str] = "application/json" - - user_agent: str = ( - f"@infobip/python-sdk{get_package_version()} python/{sys.version.split(' ')[0]}" - ) - - class Config: - alias_generator = to_header_specific_case - allow_population_by_field_name = True - - def __init__(self, **data: str) -> None: - super().__init__(**data) - self.authorization = f"App {self.authorization}" - - -class GetHeaders(RequestHeaders): - pass - - -class PostHeaders(RequestHeaders): - content_type: Optional[str] = "application/json" - - -class PutHeaders(RequestHeaders): - content_type: Optional[str] = "application/json" - - -class DeleteHeaders(RequestHeaders): - pass - - -class PathParameter(CamelCaseModel): - pass - - -class QueryParameter(CamelCaseModel): - pass - - -class XML(str): - @classmethod - def __get_validators__(cls): - yield cls.validate - - @classmethod - def validate(cls, value): - if not isinstance(value, str): - raise TypeError("String required") - - if not value: - return - - try: - ET.fromstring(value) - except ET.ParseError: - raise ValueError("Invalid XML string sent") - - return cls(value) - - -class LanguageEnum(str, Enum): - TURKISH = "TR" - SPANISH = "ES" - PORTUGUESE = "PT" - AUTODETECT = "AUTODETECT" - - -class TransliterationEnum(str, Enum): - TURKISH = "TURKISH" - GREEK = "GREEK" - CYRILLIC = "CYRILLIC" - SERBIAN_CYRILLIC = "SERBIAN_CYRILLIC" - CENTRAL_EUROPEAN = "CENTRAL_EUROPEAN" - BALTIC = "BALTIC" - NON_UNICODE = "NON_UNICODE" - - -class GeneralStatus(str, Enum): - ACCEPTED = "ACCEPTED" - PENDING = "PENDING" - UNDELIVERABLE = "UNDELIVERABLE" - DELIVERED = "DELIVERED" - REJECTED = "REJECTED" - EXPIRED = "EXPIRED" - - -class MessageStatus(str, Enum): - PENDING = "PENDING" - PAUSED = "PAUSED" - PROCESSING = "PROCESSING" - CANCELED = "CANCELED" - FINISHED = "FINISHED" - FAILED = "FAILED" - - -class DaysEnum(str, Enum): - MONDAY = "MONDAY" - TUESDAY = "TUESDAY" - WEDNESDAY = "WEDNESDAY" - THURSDAY = "THURSDAY" - FRIDAY = "FRIDAY" - SATURDAY = "SATURDAY" - SUNDAY = "SUNDAY" - - -class ContentTypeEnum(str, Enum): - APPLICATION_JSON = "application/json" - APPLICATION_XML = "application/xml" - - -class MultipartMixin: - """Mixin used for allowing models to export their fields to a multipart/form-data - format. Field types currently supported are listed in the - _FIELD_TYPE_TO_MULTIPART_INFO_MAP attribute. All other BaseModel type fields are - covered with the _JSON_INFO attribute. - """ - - _FIELD_TYPE_TO_MULTIPART_INFO_MAP: Dict = { - "str": {"is_file": False, "content_type": "text/plain"}, - "int": {"is_file": False, "content_type": "text/plain"}, - "AnyHttpUrl": {"is_file": False, "content_type": "text/plain"}, - "StrictBool": {"is_file": False, "content_type": "text/plain"}, - "ContentTypeEnum": {"is_file": False, "content_type": "text/plain"}, - "ConstrainedStrValue": {"is_file": False, "content_type": "text/plain"}, - "datetime": {"is_file": False, "content_type": "text/plain"}, - "IOBase": {"is_file": True, "content_type": ""}, - "XML": {"is_file": False, "content_type": "application/xml"}, - } - - _JSON_INFO: Dict = {"is_file": False, "content_type": "application/json"} - - def to_multipart(self) -> Tuple[bytes, str]: - """Export model's fields to a multipart/form-data format. The method returns - a tuple of binary type body to send via POST request, and the content_type - of the body including the multipart boundary. - The resulting multipart_fields dictionary will have the model's field names as - its keys and the tuples describing fields' multipart format as their values. - - For a Pydantic model with a "name: str" field and an "address: Address" field, - the resulting multipart_fields dictionary would look like: - - multipart_fields = { - "name": (None, "some name", "text/plain"), - "address:" (None, {"street": "...", "city": "..."}, "application/json") - } - - The tuple format is enforced by the urllib3's encode_multipart_formdata - function: (filename, data, MIME type), where the MIME type is optional. - The filename is None for all non-file types. - - :return: Tuple of binary encoded body and the multipart's content_type - """ - multipart_fields = {} - - for field_name, field_object in self.__fields__.items(): - self._add_multipart_tuple( - multipart_fields, - field_object.alias, - getattr(self, field_name), - field_object.type_, - ) - - return encode_multipart_formdata(multipart_fields) - - def _add_multipart_tuple( - self, multipart_fields: Dict, field_name: str, field_value: Any, field_type: Any - ) -> None: - if not field_value: - return - - """ - In case of Union we have complex field type - str(field_type) is 'typing.Union[str, int, NoneType]' - """ - if "Union" in str(field_type): - """ - field_subtypes gives ['str', 'int', 'NoneType'] - """ - field_subtypes = str(field_type).split("[")[1].strip("]").split(", ") - for f in field_subtypes: - if f in self._FIELD_TYPE_TO_MULTIPART_INFO_MAP: - field_info = self._FIELD_TYPE_TO_MULTIPART_INFO_MAP[f] - break - else: - field_info = self._JSON_INFO - else: - field_info = self._FIELD_TYPE_TO_MULTIPART_INFO_MAP.get( - field_type.__name__, self._JSON_INFO - ) - - multipart_fields[field_name] = self._get_multipart_tuple( - field_value, field_info - ) - - def _get_multipart_tuple(self, field_value: Any, field_info: Dict) -> Tuple: - if field_info["is_file"]: - return os.path.basename(field_value.name), field_value.read() - - if field_info["content_type"] == "application/json": - field_value = self._get_json_for_field(field_value) - - return None, field_value, field_info["content_type"] - - @staticmethod - def _get_json_for_field(model: Union[CamelCaseModel, List[CamelCaseModel]]) -> str: - if isinstance(model, list): - model_aliased = [item.dict(by_alias=True) for item in model] - else: - model_aliased = model.dict(by_alias=True) - - return json.dumps(model_aliased) diff --git a/infobip_channels/email/__init__.py b/infobip_channels/email/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/email/channel.py b/infobip_channels/email/channel.py deleted file mode 100644 index 7f7e036..0000000 --- a/infobip_channels/email/channel.py +++ /dev/null @@ -1,413 +0,0 @@ -from http import HTTPStatus -from typing import Any, Dict, Type, Union - -import requests - -from infobip_channels.core.channel import Channel -from infobip_channels.core.models import PostHeaders, ResponseBase -from infobip_channels.email.models.body.add_new_domain import AddNewDomainMessageBody -from infobip_channels.email.models.body.reschedule_messages import ( - RescheduleMessagesMessageBody, -) -from infobip_channels.email.models.body.send_email import EmailMessageBody -from infobip_channels.email.models.body.update_scheduled_status import ( - UpdateScheduledStatusMessageBody, -) -from infobip_channels.email.models.body.update_tracking_events import ( - UpdateTrackingEventsMessageBody, -) -from infobip_channels.email.models.body.validate_email_addresses import ( - ValidateEmailAddressesMessageBody, -) -from infobip_channels.email.models.path_parameters.delete_existing_domain import ( - DeleteExistingDomainPathParameter, -) -from infobip_channels.email.models.path_parameters.get_domain_details import ( - GetDomainDetailsPathParameter, -) -from infobip_channels.email.models.path_parameters.update_tracking_events import ( - UpdateTrackingEventsPathParameter, -) -from infobip_channels.email.models.path_parameters.verify_domain import ( - VerifyDomainPathParameter, -) -from infobip_channels.email.models.query_parameters.delivery_reports import ( - DeliveryReportsQueryParameters, -) -from infobip_channels.email.models.query_parameters.get_all_domains import ( - GetAllDomainsForAccountQueryParameters, -) -from infobip_channels.email.models.query_parameters.get_logs import ( - GetLogsQueryParameters, -) -from infobip_channels.email.models.query_parameters.get_sent_bulks import ( - GetSentBulksQueryParameters, -) -from infobip_channels.email.models.query_parameters.get_sent_bulks_status import ( - GetSentBulksStatusQueryParameters, -) -from infobip_channels.email.models.query_parameters.reschedule_messages import ( - RescheduleMessagesQueryParameters, -) -from infobip_channels.email.models.query_parameters.update_scheduled_status import ( - UpdateScheduledStatusQueryParameters, -) -from infobip_channels.email.models.response.add_new_domain import AddNewDomainResponse -from infobip_channels.email.models.response.core import EmailResponseError -from infobip_channels.email.models.response.delivery_reports import ( - DeliveryReportsResponse, -) -from infobip_channels.email.models.response.get_all_domains import ( - GetAllDomainsForAccountResponse, -) -from infobip_channels.email.models.response.get_domain_details import ( - GetDomainDetailsResponse, -) -from infobip_channels.email.models.response.get_logs import GetLogsResponse -from infobip_channels.email.models.response.get_sent_bulk_status import ( - GetSentEmailBulksStatusResponse, -) -from infobip_channels.email.models.response.get_sent_bulks import ( - GetSentEmailBulksResponse, -) -from infobip_channels.email.models.response.reschedule_messages import ( - RescheduleMessagesResponse, -) -from infobip_channels.email.models.response.send_email import SendEmailResponse -from infobip_channels.email.models.response.update_scheduled_status import ( - UpdateScheduledStatusResponse, -) -from infobip_channels.email.models.response.update_tracking_events import ( - UpdateTrackingEventsResponse, -) -from infobip_channels.email.models.response.validate_email_addresses import ( - ValidateEmailAddressesResponse, -) - - -class EmailChannel(Channel): - """Class used for interaction with the Infobip's Email API.""" - - EMAIL_URL_TEMPLATE_V1 = "/email/1/" - EMAIL_URL_TEMPLATE_V2 = "/email/2/" - EMAIL_URL_TEMPLATE_V3 = "/email/3/" - - def _get_custom_response_class( - self, - raw_response: Union[requests.Response, Any], - response_class: Type[ResponseBase] = SendEmailResponse, - *args, - **kwargs, - ) -> Type[ResponseBase]: - if raw_response.status_code == HTTPStatus.OK: - return response_class - elif raw_response.status_code in ( - HTTPStatus.BAD_REQUEST, - HTTPStatus.UNAUTHORIZED, - HTTPStatus.FORBIDDEN, - HTTPStatus.TOO_MANY_REQUESTS, - HTTPStatus.INTERNAL_SERVER_ERROR, - HTTPStatus.NOT_FOUND, - ): - return EmailResponseError - - raise ValueError - - def send_email_message( - self, message: Union[EmailMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - Send an email or multiple emails to a recipient or multiple recipients - with CC/BCC enabled. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, EmailMessageBody) - body, content_type = message.to_multipart() - - response = self._client.post( - self.EMAIL_URL_TEMPLATE_V3 + "send", - body, - PostHeaders( - content_type=content_type, authorization=self._client.auth.api_key - ), - ) - return self._construct_response(response, SendEmailResponse) - - def email_delivery_reports( - self, query_parameters: Union[DeliveryReportsQueryParameters, Dict] = None - ) -> Union[ResponseBase, requests.Response, Any]: - """ - Get one-time delivery reports for all sent emails. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - - query_parameters = self.validate_query_parameter( - query_parameters or {}, DeliveryReportsQueryParameters - ) - - response = self._client.get( - self.EMAIL_URL_TEMPLATE_V1 + "reports", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, DeliveryReportsResponse) - - def get_email_logs( - self, query_parameters: Union[GetLogsQueryParameters, Dict] = None - ) -> Union[ResponseBase, requests.Response, Any]: - """ - This method allows you to get email logs of sent Email messagesId for - request. Email logs are available for the last 48 hours. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - - query_parameters = self.validate_query_parameter( - query_parameters or {}, GetLogsQueryParameters - ) - - response = self._client.get( - self.EMAIL_URL_TEMPLATE_V1 + "logs", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, GetLogsResponse) - - def get_sent_email_bulks( - self, query_parameters: Union[GetSentBulksQueryParameters, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - See the scheduled time of your Email messages. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - - query_parameters = self.validate_query_parameter( - query_parameters, GetSentBulksQueryParameters - ) - - response = self._client.get( - self.EMAIL_URL_TEMPLATE_V1 + "bulks", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, GetSentEmailBulksResponse) - - def get_sent_email_bulks_status( - self, query_parameters: Union[GetSentBulksStatusQueryParameters, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - See the status of scheduled email messages. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - - query_parameters = self.validate_query_parameter( - query_parameters, GetSentBulksStatusQueryParameters - ) - - response = self._client.get( - self.EMAIL_URL_TEMPLATE_V1 + "bulks/status", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, GetSentEmailBulksStatusResponse) - - def reschedule_email_messages( - self, - query_parameters: Union[RescheduleMessagesQueryParameters, Dict], - message: Union[RescheduleMessagesMessageBody, Dict], - ) -> Union[ResponseBase, requests.Response, Any]: - """ - Change the date and time for sending scheduled Email messages. - - :param query_parameters: Query parameters to send with the request - :param message: Body of the message to send - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters, RescheduleMessagesQueryParameters - ) - - message = self.validate_message_body(message, RescheduleMessagesMessageBody) - - response = self._client.put( - self.EMAIL_URL_TEMPLATE_V1 + "bulks", - message.dict(by_alias=True), - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, RescheduleMessagesResponse) - - def update_scheduled_email_messages( - self, - query_parameters: Union[UpdateScheduledStatusQueryParameters, Dict], - message: Union[UpdateScheduledStatusMessageBody, Dict], - ) -> Union[ResponseBase, requests.Response, Any]: - """ - Change status or completely cancel sending of scheduled Email messages. - - :param query_parameters: Query parameters to send with the request - :param message: Body of the message to send - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters, UpdateScheduledStatusQueryParameters - ) - - message = self.validate_message_body(message, UpdateScheduledStatusMessageBody) - - response = self._client.put( - self.EMAIL_URL_TEMPLATE_V1 + "bulks/status", - message.dict(by_alias=True), - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, UpdateScheduledStatusResponse) - - def validate_email_addresses( - self, message: Union[ValidateEmailAddressesMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - Run validation to identify poor quality emails to clean up your recipient list. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, ValidateEmailAddressesMessageBody) - - response = self._client.post( - self.EMAIL_URL_TEMPLATE_V2 + "validation", - message.dict(by_alias=True), - ) - return self._construct_response(response, ValidateEmailAddressesResponse) - - def get_all_domains_for_account( - self, - query_parameters: Union[GetAllDomainsForAccountQueryParameters, Dict] = None, - ) -> Union[ResponseBase, requests.Response, Any]: - """ - This API is to get all domain associated with the account. It also provides - details of the retrieved domain like the DNS records, Tracking details, - Active/Blocked status,etc. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - - query_parameters = self.validate_query_parameter( - query_parameters or {}, GetAllDomainsForAccountQueryParameters - ) - - response = self._client.get( - self.EMAIL_URL_TEMPLATE_V1 + "domains", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, GetAllDomainsForAccountResponse) - - def get_domain_details( - self, - parameter: Union[GetDomainDetailsPathParameter, Dict], - ) -> Union[ResponseBase, requests.Response, Any]: - """ - This API provides with the details of the domain like the DNS records, - Tracking details, Active/Blocked status,etc. - - :param parameter: Domain for which the details need to be viewed. - :return: Received response - """ - path_parameter = self.validate_path_parameter( - parameter, GetDomainDetailsPathParameter - ) - - response = self._client.get( - self.EMAIL_URL_TEMPLATE_V1 + "domains/" + path_parameter.domain_name, - ) - return self._construct_response(response, GetDomainDetailsResponse) - - def add_new_domain( - self, message: Union[AddNewDomainMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - This method allows you to add new domains with a limit to create a maximum of - 10 domains in a day. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, AddNewDomainMessageBody) - - response = self._client.post( - self.EMAIL_URL_TEMPLATE_V1 + "domains", - message.dict(by_alias=True), - ) - return self._construct_response(response, AddNewDomainResponse) - - def delete_existing_domain( - self, parameter: Union[DeleteExistingDomainPathParameter, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - This method allows you to delete an existing domain. - - :param parameter: Domain name which needs to be deleted. - :return: Received response - """ - path_parameter = self.validate_path_parameter( - parameter, DeleteExistingDomainPathParameter - ) - - response = self._client.delete( - self.EMAIL_URL_TEMPLATE_V1 + "domains/" + path_parameter.domain_name, - ) - return response - - def verify_domain( - self, parameter: Union[VerifyDomainPathParameter, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - API request to verify records(TXT, MX, DKIM) associated with the provided - domain. - - :param parameter: Domain name which needs to be deleted. - :return: Received response - """ - path_parameter = self.validate_path_parameter( - parameter, VerifyDomainPathParameter - ) - - response = self._client.post( - self.EMAIL_URL_TEMPLATE_V1 - + "domains/" - + path_parameter.domain_name - + "/verify" - ) - return response - - def update_tracking_events( - self, - parameter: Union[UpdateTrackingEventsPathParameter, Dict], - message: Union[UpdateTrackingEventsMessageBody, Dict], - ) -> Union[ResponseBase, requests.Response, Any]: - """ - API to update tracking events for the provided domain. Tracking events can be - updated only for CLICKS, OPENS and UNSUBSCRIBES. - - :param parameter: Domain name which needs to be deleted. - :param message: Body of the message to send - :return: Received response - """ - path_parameter = self.validate_path_parameter( - parameter, UpdateTrackingEventsPathParameter - ) - - message = self.validate_message_body(message, UpdateTrackingEventsMessageBody) - - response = self._client.put( - self.EMAIL_URL_TEMPLATE_V1 - + "domains/" - + path_parameter.domain_name - + "/tracking", - message.dict(by_alias=True), - ) - return self._construct_response(response, UpdateTrackingEventsResponse) diff --git a/infobip_channels/email/models/__init__.py b/infobip_channels/email/models/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/email/models/body/__init__.py b/infobip_channels/email/models/body/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/email/models/body/add_new_domain.py b/infobip_channels/email/models/body/add_new_domain.py deleted file mode 100644 index af98327..0000000 --- a/infobip_channels/email/models/body/add_new_domain.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.core.models import MessageBodyBase - - -class AddNewDomainMessageBody(MessageBodyBase): - domain_name: str diff --git a/infobip_channels/email/models/body/reschedule_messages.py b/infobip_channels/email/models/body/reschedule_messages.py deleted file mode 100644 index 714ee75..0000000 --- a/infobip_channels/email/models/body/reschedule_messages.py +++ /dev/null @@ -1,14 +0,0 @@ -from datetime import datetime -from typing import Union - -from pydantic import validator - -from infobip_channels.core.models import DateTimeValidator, MessageBodyBase - - -class RescheduleMessagesMessageBody(MessageBodyBase, DateTimeValidator): - send_at: Union[datetime, str] - - @validator("send_at") - def convert_send_at_to_correct_format(cls, value): - return super().convert_time_to_correct_format(value) diff --git a/infobip_channels/email/models/body/send_email.py b/infobip_channels/email/models/body/send_email.py deleted file mode 100644 index 3f6d856..0000000 --- a/infobip_channels/email/models/body/send_email.py +++ /dev/null @@ -1,49 +0,0 @@ -from datetime import datetime -from io import IOBase -from typing import Optional, Union - -from pydantic import AnyHttpUrl, Field, StrictBool, constr, validator - -from infobip_channels.core.models import ( - CamelCaseModel, - ContentTypeEnum, - DateTimeValidator, - MessageBodyBase, - MultipartMixin, -) - - -class EmailMessageBody(MultipartMixin, MessageBodyBase, DateTimeValidator): - from_email: str = Field(alias="from") - to: str - cc: Optional[str] = None - bcc: Optional[str] = None - subject: str - text: Optional[str] = None - bulk_id: Optional[str] = None - message_id: Optional[str] = None - templateid: Optional[int] = None - attachment: Optional[IOBase] = None - inline_image: Optional[IOBase] = None - html: Optional[str] = Field(alias="HTML", default=None) - replyto: Optional[str] = None - defaultplaceholders: Optional[str] = None - preserverecipients: Optional[StrictBool] = False - tracking_url: Optional[str] = None - trackclicks: Optional[StrictBool] = False - trackopens: Optional[StrictBool] = False - track: Optional[StrictBool] = True - callback_data: Optional[constr(max_length=4000)] = None - intermediateReport: Optional[StrictBool] = False - notify_url: Optional[AnyHttpUrl] = None - notify_content_type: Optional[ContentTypeEnum] = None - send_at: Optional[Union[datetime, str]] = None - landing_page_placeholders: Optional[str] = None - landing_page_id: Optional[str] = None - - @validator("send_at") - def convert_send_at_to_correct_format(cls, value): - return super().convert_time_to_correct_format(value) - - class Config(CamelCaseModel.Config): - arbitrary_types_allowed = True diff --git a/infobip_channels/email/models/body/update_scheduled_status.py b/infobip_channels/email/models/body/update_scheduled_status.py deleted file mode 100644 index 85124c2..0000000 --- a/infobip_channels/email/models/body/update_scheduled_status.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.core.models import MessageBodyBase, MessageStatus - - -class UpdateScheduledStatusMessageBody(MessageBodyBase): - status: MessageStatus diff --git a/infobip_channels/email/models/body/update_tracking_events.py b/infobip_channels/email/models/body/update_tracking_events.py deleted file mode 100644 index 5f84dc5..0000000 --- a/infobip_channels/email/models/body/update_tracking_events.py +++ /dev/null @@ -1,11 +0,0 @@ -from typing import Optional - -from pydantic import StrictBool - -from infobip_channels.core.models import MessageBodyBase - - -class UpdateTrackingEventsMessageBody(MessageBodyBase): - open: Optional[StrictBool] = None - clicks: Optional[StrictBool] = None - unsubscribe: Optional[StrictBool] = None diff --git a/infobip_channels/email/models/body/validate_email_addresses.py b/infobip_channels/email/models/body/validate_email_addresses.py deleted file mode 100644 index 0569496..0000000 --- a/infobip_channels/email/models/body/validate_email_addresses.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.core.models import MessageBodyBase - - -class ValidateEmailAddressesMessageBody(MessageBodyBase): - to: str diff --git a/infobip_channels/email/models/path_parameters/__init__.py b/infobip_channels/email/models/path_parameters/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/email/models/path_parameters/core.py b/infobip_channels/email/models/path_parameters/core.py deleted file mode 100644 index 6da8312..0000000 --- a/infobip_channels/email/models/path_parameters/core.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.core.models import PathParameter - - -class EmailPathParameter(PathParameter): - domain_name: str diff --git a/infobip_channels/email/models/path_parameters/delete_existing_domain.py b/infobip_channels/email/models/path_parameters/delete_existing_domain.py deleted file mode 100644 index 214cf8c..0000000 --- a/infobip_channels/email/models/path_parameters/delete_existing_domain.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.email.models.path_parameters.core import EmailPathParameter - - -class DeleteExistingDomainPathParameter(EmailPathParameter): - pass diff --git a/infobip_channels/email/models/path_parameters/get_domain_details.py b/infobip_channels/email/models/path_parameters/get_domain_details.py deleted file mode 100644 index 7e65fb6..0000000 --- a/infobip_channels/email/models/path_parameters/get_domain_details.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.email.models.path_parameters.core import EmailPathParameter - - -class GetDomainDetailsPathParameter(EmailPathParameter): - pass diff --git a/infobip_channels/email/models/path_parameters/update_tracking_events.py b/infobip_channels/email/models/path_parameters/update_tracking_events.py deleted file mode 100644 index 8de1953..0000000 --- a/infobip_channels/email/models/path_parameters/update_tracking_events.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.email.models.path_parameters.core import EmailPathParameter - - -class UpdateTrackingEventsPathParameter(EmailPathParameter): - pass diff --git a/infobip_channels/email/models/path_parameters/verify_domain.py b/infobip_channels/email/models/path_parameters/verify_domain.py deleted file mode 100644 index 2be7b27..0000000 --- a/infobip_channels/email/models/path_parameters/verify_domain.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.email.models.path_parameters.core import EmailPathParameter - - -class VerifyDomainPathParameter(EmailPathParameter): - pass diff --git a/infobip_channels/email/models/query_parameters/__init__.py b/infobip_channels/email/models/query_parameters/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/email/models/query_parameters/core.py b/infobip_channels/email/models/query_parameters/core.py deleted file mode 100644 index 8fae0b4..0000000 --- a/infobip_channels/email/models/query_parameters/core.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.core.models import QueryParameter - - -class BulksQueryParameters(QueryParameter): - bulk_id: str diff --git a/infobip_channels/email/models/query_parameters/delivery_reports.py b/infobip_channels/email/models/query_parameters/delivery_reports.py deleted file mode 100644 index 7a861c6..0000000 --- a/infobip_channels/email/models/query_parameters/delivery_reports.py +++ /dev/null @@ -1,9 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import QueryParameter - - -class DeliveryReportsQueryParameters(QueryParameter): - bulk_id: Optional[str] = None - message_id: Optional[str] = None - limit: Optional[int] = None diff --git a/infobip_channels/email/models/query_parameters/get_all_domains.py b/infobip_channels/email/models/query_parameters/get_all_domains.py deleted file mode 100644 index 6207f26..0000000 --- a/infobip_channels/email/models/query_parameters/get_all_domains.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Optional - -from pydantic import conint - -from infobip_channels.core.models import QueryParameter - - -class GetAllDomainsForAccountQueryParameters(QueryParameter): - size: Optional[conint(ge=1, le=20)] = None - page: Optional[conint(ge=0)] = None diff --git a/infobip_channels/email/models/query_parameters/get_logs.py b/infobip_channels/email/models/query_parameters/get_logs.py deleted file mode 100644 index 10aaa37..0000000 --- a/infobip_channels/email/models/query_parameters/get_logs.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Optional - -from pydantic import Field - -from infobip_channels.core.models import ( - DateTimeValidator, - GeneralStatus, - QueryParameter, -) - - -class GetLogsQueryParameters(QueryParameter, DateTimeValidator): - message_id: Optional[str] = None - from_email: Optional[str] = Field(alias="from") - to: Optional[str] = None - bulk_id: Optional[str] = None - general_status: Optional[GeneralStatus] = None - sent_since: Optional[str] = None - sent_until: Optional[str] = None - limit: Optional[int] = None diff --git a/infobip_channels/email/models/query_parameters/get_sent_bulks.py b/infobip_channels/email/models/query_parameters/get_sent_bulks.py deleted file mode 100644 index 9677e78..0000000 --- a/infobip_channels/email/models/query_parameters/get_sent_bulks.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.email.models.query_parameters.core import BulksQueryParameters - - -class GetSentBulksQueryParameters(BulksQueryParameters): - pass diff --git a/infobip_channels/email/models/query_parameters/get_sent_bulks_status.py b/infobip_channels/email/models/query_parameters/get_sent_bulks_status.py deleted file mode 100644 index 4743adc..0000000 --- a/infobip_channels/email/models/query_parameters/get_sent_bulks_status.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.email.models.query_parameters.core import BulksQueryParameters - - -class GetSentBulksStatusQueryParameters(BulksQueryParameters): - pass diff --git a/infobip_channels/email/models/query_parameters/reschedule_messages.py b/infobip_channels/email/models/query_parameters/reschedule_messages.py deleted file mode 100644 index ce2770f..0000000 --- a/infobip_channels/email/models/query_parameters/reschedule_messages.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.email.models.query_parameters.core import BulksQueryParameters - - -class RescheduleMessagesQueryParameters(BulksQueryParameters): - pass diff --git a/infobip_channels/email/models/query_parameters/update_scheduled_status.py b/infobip_channels/email/models/query_parameters/update_scheduled_status.py deleted file mode 100644 index 5b1082d..0000000 --- a/infobip_channels/email/models/query_parameters/update_scheduled_status.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.email.models.query_parameters.core import BulksQueryParameters - - -class UpdateScheduledStatusQueryParameters(BulksQueryParameters): - pass diff --git a/infobip_channels/email/models/response/__init__.py b/infobip_channels/email/models/response/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/email/models/response/add_new_domain.py b/infobip_channels/email/models/response/add_new_domain.py deleted file mode 100644 index 5619246..0000000 --- a/infobip_channels/email/models/response/add_new_domain.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.email.models.response.core import ResultDomain - - -class AddNewDomainResponse(ResponseBase, ResultDomain): - pass diff --git a/infobip_channels/email/models/response/core.py b/infobip_channels/email/models/response/core.py deleted file mode 100644 index 114797e..0000000 --- a/infobip_channels/email/models/response/core.py +++ /dev/null @@ -1,63 +0,0 @@ -from typing import List, Optional - -from infobip_channels.core.models import CamelCaseModel, ResponseBase, ResponseStatus - - -class ServiceException(CamelCaseModel): - message_id: str - text: str - - -class RequestError(CamelCaseModel): - service_exception: ServiceException - - -class Price(CamelCaseModel): - price_per_message: int - currency: str - - -class ResultBase(CamelCaseModel): - bulk_id: Optional[str] = None - message_id: str - to: str - sent_at: str - done_at: str - message_count: int - price: Price - status: ResponseStatus - - -class BulksBase(ResponseBase): - external_bulk_id: str - - -class BulkBase(CamelCaseModel): - bulk_id: str - - -class EmailResponseError(ResponseBase): - request_error: RequestError - - -class Tracking(CamelCaseModel): - clicks: bool - opens: bool - unsubscribe: bool - - -class DnsRecord(CamelCaseModel): - record_type: str - name: str - expected_value: str - verified: bool - - -class ResultDomain(CamelCaseModel): - domain_id: int - domain_name: str - active: bool - tracking: Tracking - dns_records: List[DnsRecord] - blocked: int - created_at: str diff --git a/infobip_channels/email/models/response/delivery_reports.py b/infobip_channels/email/models/response/delivery_reports.py deleted file mode 100644 index d1bfaec..0000000 --- a/infobip_channels/email/models/response/delivery_reports.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import List - -from infobip_channels.core.models import CamelCaseModel, ResponseBase -from infobip_channels.email.models.response.core import ResultBase - - -class Error(CamelCaseModel): - group_id: int - group_name: str - id: int - name: str - description: str - permanent: bool - - -class Result(ResultBase): - error: Error - channel: str - - -class DeliveryReportsResponse(ResponseBase): - results: List[Result] diff --git a/infobip_channels/email/models/response/get_all_domains.py b/infobip_channels/email/models/response/get_all_domains.py deleted file mode 100644 index b6f9df5..0000000 --- a/infobip_channels/email/models/response/get_all_domains.py +++ /dev/null @@ -1,16 +0,0 @@ -from typing import List - -from infobip_channels.core.models import CamelCaseModel, ResponseBase -from infobip_channels.email.models.response.core import ResultDomain - - -class Paging(CamelCaseModel): - page: int - size: int - total_pages: int - total_results: int - - -class GetAllDomainsForAccountResponse(ResponseBase): - paging: Paging - results: List[ResultDomain] diff --git a/infobip_channels/email/models/response/get_domain_details.py b/infobip_channels/email/models/response/get_domain_details.py deleted file mode 100644 index 1b5fd92..0000000 --- a/infobip_channels/email/models/response/get_domain_details.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.email.models.response.core import ResultDomain - - -class GetDomainDetailsResponse(ResponseBase, ResultDomain): - pass diff --git a/infobip_channels/email/models/response/get_logs.py b/infobip_channels/email/models/response/get_logs.py deleted file mode 100644 index e587a30..0000000 --- a/infobip_channels/email/models/response/get_logs.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import List - -from pydantic import Field - -from infobip_channels.core.models import ResponseBase -from infobip_channels.email.models.response.core import ResultBase - - -class Result(ResultBase): - from_email: str = Field(alias="from") - text: str - - -class GetLogsResponse(ResponseBase): - results: List[Result] diff --git a/infobip_channels/email/models/response/get_sent_bulk_status.py b/infobip_channels/email/models/response/get_sent_bulk_status.py deleted file mode 100644 index 15e10f9..0000000 --- a/infobip_channels/email/models/response/get_sent_bulk_status.py +++ /dev/null @@ -1,11 +0,0 @@ -from typing import List - -from infobip_channels.email.models.response.core import BulkBase, BulksBase - - -class Bulk(BulkBase): - status: str - - -class GetSentEmailBulksStatusResponse(BulksBase): - bulks: List[Bulk] diff --git a/infobip_channels/email/models/response/get_sent_bulks.py b/infobip_channels/email/models/response/get_sent_bulks.py deleted file mode 100644 index 4aa83af..0000000 --- a/infobip_channels/email/models/response/get_sent_bulks.py +++ /dev/null @@ -1,11 +0,0 @@ -from typing import List - -from infobip_channels.email.models.response.core import BulkBase, BulksBase - - -class Bulk(BulkBase): - send_at: str - - -class GetSentEmailBulksResponse(BulksBase): - bulks: List[Bulk] diff --git a/infobip_channels/email/models/response/reschedule_messages.py b/infobip_channels/email/models/response/reschedule_messages.py deleted file mode 100644 index 7400b85..0000000 --- a/infobip_channels/email/models/response/reschedule_messages.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase - - -class RescheduleMessagesResponse(ResponseBase): - bulk_id: str - send_at: str diff --git a/infobip_channels/email/models/response/send_email.py b/infobip_channels/email/models/response/send_email.py deleted file mode 100644 index c72341d..0000000 --- a/infobip_channels/email/models/response/send_email.py +++ /dev/null @@ -1,14 +0,0 @@ -from typing import List, Optional - -from infobip_channels.core.models import CamelCaseModel, ResponseBase, ResponseStatus - - -class SendEmailResponseMessage(CamelCaseModel): - to: Optional[str] = None - message_count: Optional[int] = None - message_id: Optional[str] = None - status: ResponseStatus - - -class SendEmailResponse(ResponseBase): - messages: List[SendEmailResponseMessage] diff --git a/infobip_channels/email/models/response/update_scheduled_status.py b/infobip_channels/email/models/response/update_scheduled_status.py deleted file mode 100644 index 68bb04b..0000000 --- a/infobip_channels/email/models/response/update_scheduled_status.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase - - -class UpdateScheduledStatusResponse(ResponseBase): - bulk_id: str - status: str diff --git a/infobip_channels/email/models/response/update_tracking_events.py b/infobip_channels/email/models/response/update_tracking_events.py deleted file mode 100644 index ae9d94b..0000000 --- a/infobip_channels/email/models/response/update_tracking_events.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.email.models.response.core import ResultDomain - - -class UpdateTrackingEventsResponse(ResponseBase, ResultDomain): - pass diff --git a/infobip_channels/email/models/response/validate_email_addresses.py b/infobip_channels/email/models/response/validate_email_addresses.py deleted file mode 100644 index 3bdd53d..0000000 --- a/infobip_channels/email/models/response/validate_email_addresses.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import ResponseBase - - -class ValidateEmailAddressesResponse(ResponseBase): - to: str - valid_mailbox: str - valid_syntax: bool - catch_all: bool - disposable: bool - role_based: bool - reason: Optional[str] = None diff --git a/infobip_channels/mms/__init__.py b/infobip_channels/mms/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/mms/channel.py b/infobip_channels/mms/channel.py deleted file mode 100644 index 5379fdd..0000000 --- a/infobip_channels/mms/channel.py +++ /dev/null @@ -1,102 +0,0 @@ -from http import HTTPStatus -from typing import Any, Dict, Type, Union - -import requests - -from infobip_channels.core.channel import Channel -from infobip_channels.core.models import PostHeaders, ResponseBase -from infobip_channels.mms.models.body.send_mms import MMSMessageBody -from infobip_channels.mms.models.query_parameters.get_inbound_mms_messages import ( - GetInboundMMSMessagesQueryParameters, -) -from infobip_channels.mms.models.query_parameters.get_mms_delivery_reports import ( - GetMMSDeliveryReportsQueryParameters, -) -from infobip_channels.mms.models.response.get_inbound_mms_messages import ( - GetInboundMMSMessagesResponse, -) -from infobip_channels.mms.models.response.get_mms_delivery_reports import ( - GetMMSDeliveryReportsResponse, -) -from infobip_channels.mms.models.response.send_mms import SendMMSResponse - - -class MMSChannel(Channel): - """Class used for interaction with the Infobip's MMS API.""" - - MMS_URL_TEMPLATE = "/mms/1/" - - def _get_custom_response_class( - self, - raw_response: Union[requests.Response, Any], - response_class: Type[ResponseBase] = SendMMSResponse, - *args, - **kwargs, - ) -> Type[ResponseBase]: - if raw_response.status_code in ( - HTTPStatus.OK, - HTTPStatus.BAD_REQUEST, - HTTPStatus.INTERNAL_SERVER_ERROR, - ): - return response_class - - raise ValueError - - def send_mms_message( - self, message: Union[MMSMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send a single MMS message to one destination address. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, MMSMessageBody) - body, content_type = message.to_multipart() - - response = self._client.post( - self.MMS_URL_TEMPLATE + "single", - body, - PostHeaders( - content_type=content_type, authorization=self._client.auth.api_key - ), - ) - return self._construct_response(response, SendMMSResponse) - - def get_mms_delivery_reports( - self, query_parameters: Union[GetMMSDeliveryReportsQueryParameters, Dict] - ) -> Union[ResponseBase, Any]: - """Use this API method to learn if and when the message has been delivered to - the recipient. Each request will return a batch of delivery reports - only once. - The following API request will return only new reports that arrived since the - last API request. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters, GetMMSDeliveryReportsQueryParameters - ) - response = self._client.get( - self.MMS_URL_TEMPLATE + "reports", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, GetMMSDeliveryReportsResponse) - - def get_inbound_mms_messages( - self, query_parameters: Union[GetInboundMMSMessagesQueryParameters, Dict] - ) -> Union[ResponseBase, Any]: - """Use this API method to fetch messages. Each request will return a batch of - received messages - only once. The following API request will return only new - messages that arrived since the last API request. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters, GetInboundMMSMessagesQueryParameters - ) - response = self._client.get( - self.MMS_URL_TEMPLATE + "inbox/reports", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, GetInboundMMSMessagesResponse) diff --git a/infobip_channels/mms/models/__init__.py b/infobip_channels/mms/models/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/mms/models/body/__init__.py b/infobip_channels/mms/models/body/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/mms/models/body/send_mms.py b/infobip_channels/mms/models/body/send_mms.py deleted file mode 100644 index c677cf2..0000000 --- a/infobip_channels/mms/models/body/send_mms.py +++ /dev/null @@ -1,73 +0,0 @@ -from datetime import datetime -from io import IOBase -from typing import List, Optional, Union - -from pydantic import ( - AnyHttpUrl, - Field, - StrictBool, - conint, - conlist, - constr, - root_validator, - validator, -) - -from infobip_channels.core.models import ( - XML, - CamelCaseModel, - DateTimeValidator, - DaysEnum, - FromAndToTimeValidator, - MessageBodyBase, - MultipartMixin, -) - - -class Time(CamelCaseModel): - hour: conint(ge=0, le=23) - minute: conint(ge=0, le=59) - - -class ExternallyHostedMedia(CamelCaseModel): - content_type: str - content_id: str - content_url: AnyHttpUrl - - -class DeliveryTimeWindow(CamelCaseModel, FromAndToTimeValidator): - days: conlist(DaysEnum, min_items=1) - from_time: Optional[Time] = Field(alias="from", default=None) - to: Optional[Time] = None - - @root_validator - def validate_from_and_to(cls, values): - return super().validate_from_and_to(values) - - -class Head(CamelCaseModel, DateTimeValidator): - from_number: str = Field(alias="from") - to: str - id: Optional[str] = None - subject: Optional[str] = None - validity_period_minutes: Optional[int] = None - callback_data: Optional[constr(max_length=200)] = None - notify_url: Optional[AnyHttpUrl] = None - send_at: Optional[Union[datetime, str]] = None - intermediate_report: Optional[StrictBool] = False - delivery_time_window: Optional[DeliveryTimeWindow] = None - - @validator("send_at") - def convert_send_at_to_correct_format(cls, value): - return super().convert_time_to_correct_format(value) - - -class MMSMessageBody(MultipartMixin, MessageBodyBase): - head: Head - text: Optional[str] = None - media: Optional[IOBase] = None - externally_hosted_media: Optional[List[ExternallyHostedMedia]] = None - smil: Optional[XML] = None - - class Config(CamelCaseModel.Config): - arbitrary_types_allowed = True diff --git a/infobip_channels/mms/models/query_parameters/__init__.py b/infobip_channels/mms/models/query_parameters/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/mms/models/query_parameters/get_inbound_mms_messages.py b/infobip_channels/mms/models/query_parameters/get_inbound_mms_messages.py deleted file mode 100644 index bb7824f..0000000 --- a/infobip_channels/mms/models/query_parameters/get_inbound_mms_messages.py +++ /dev/null @@ -1,7 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import QueryParameter - - -class GetInboundMMSMessagesQueryParameters(QueryParameter): - limit: Optional[int] = None diff --git a/infobip_channels/mms/models/query_parameters/get_mms_delivery_reports.py b/infobip_channels/mms/models/query_parameters/get_mms_delivery_reports.py deleted file mode 100644 index 3938edb..0000000 --- a/infobip_channels/mms/models/query_parameters/get_mms_delivery_reports.py +++ /dev/null @@ -1,9 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import QueryParameter - - -class GetMMSDeliveryReportsQueryParameters(QueryParameter): - bulk_id: Optional[str] = None - message_id: Optional[str] = None - limit: Optional[int] = None diff --git a/infobip_channels/mms/models/response/__init__.py b/infobip_channels/mms/models/response/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/mms/models/response/core.py b/infobip_channels/mms/models/response/core.py deleted file mode 100644 index d92f9cf..0000000 --- a/infobip_channels/mms/models/response/core.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import CamelCaseModel - - -class Price(CamelCaseModel): - price_per_message: Optional[int] = None - currency: Optional[str] = None diff --git a/infobip_channels/mms/models/response/get_inbound_mms_messages.py b/infobip_channels/mms/models/response/get_inbound_mms_messages.py deleted file mode 100644 index c4f9be2..0000000 --- a/infobip_channels/mms/models/response/get_inbound_mms_messages.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import List, Optional - -from pydantic import Field - -from infobip_channels.core.models import CamelCaseModel, ResponseBase -from infobip_channels.mms.models.response.core import Price - - -class Result(CamelCaseModel): - message_id: Optional[str] = None - to: Optional[str] = None - from_id: Optional[str] = Field(default=None, alias="from") - message: Optional[str] = None - received_at: Optional[str] = None - mms_count: Optional[int] = None - callback_data: Optional[str] = None - price: Optional[Price] = None - - -class GetInboundMMSMessagesResponse(ResponseBase): - results: Optional[List[Result]] = None diff --git a/infobip_channels/mms/models/response/get_mms_delivery_reports.py b/infobip_channels/mms/models/response/get_mms_delivery_reports.py deleted file mode 100644 index f6c0cd4..0000000 --- a/infobip_channels/mms/models/response/get_mms_delivery_reports.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import List, Optional - -from pydantic import Field - -from infobip_channels.core.models import CamelCaseModel, ResponseBase, ResponseStatus -from infobip_channels.mms.models.response.core import Price - - -class Error(CamelCaseModel): - group_id: Optional[int] = None - group_name: Optional[str] = None - id: Optional[int] = None - name: Optional[str] = None - description: Optional[str] = None - - -class Result(CamelCaseModel): - bulk_id: Optional[str] = None - message_id: Optional[str] = None - to: Optional[str] = None - from_id: Optional[str] = Field(default=None, alias="from") - sent_at: Optional[str] = None - done_at: Optional[str] = None - mms_count: Optional[int] = None - mcc_mnc: Optional[str] = None - callback_data: Optional[str] = None - price: Optional[Price] = None - status: Optional[ResponseStatus] = None - error: Optional[Error] = None - - -class GetMMSDeliveryReportsResponse(ResponseBase): - results: Optional[List[Result]] = None diff --git a/infobip_channels/mms/models/response/send_mms.py b/infobip_channels/mms/models/response/send_mms.py deleted file mode 100644 index 36db936..0000000 --- a/infobip_channels/mms/models/response/send_mms.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import List, Optional - -from infobip_channels.core.models import CamelCaseModel, ResponseBase, ResponseStatus - - -class SendMMSResponseMessage(CamelCaseModel): - to: Optional[str] = None - status: ResponseStatus - message_id: Optional[str] = None - - -class SendMMSResponse(ResponseBase): - bulk_id: Optional[str] = None - messages: List[SendMMSResponseMessage] - error_message: Optional[str] = None diff --git a/infobip_channels/rcs/Models/__init__.py b/infobip_channels/rcs/Models/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/rcs/Models/body/__init__.py b/infobip_channels/rcs/Models/body/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/rcs/Models/body/send_bulk_rcs_message.py b/infobip_channels/rcs/Models/body/send_bulk_rcs_message.py deleted file mode 100644 index a6d49d2..0000000 --- a/infobip_channels/rcs/Models/body/send_bulk_rcs_message.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import List - -from infobip_channels.core.models import MessageBodyBase -from infobip_channels.rcs.Models.body.send_rcs_message import RCSMessageBody - - -class RCSMessageBodyList(MessageBodyBase): - messages: List[RCSMessageBody] diff --git a/infobip_channels/rcs/Models/body/send_rcs_message.py b/infobip_channels/rcs/Models/body/send_rcs_message.py deleted file mode 100644 index 6f64c56..0000000 --- a/infobip_channels/rcs/Models/body/send_rcs_message.py +++ /dev/null @@ -1,215 +0,0 @@ -from enum import Enum -from typing import List, Optional, Union - -try: - from typing import Literal -except ImportError: - from typing_extensions import Literal - -from pydantic import AnyHttpUrl, Field, confloat, constr, validator - -from infobip_channels.core.models import ( - CamelCaseModel, - MessageBodyBase, - UrlLengthValidatorMixin, -) - - -class ValidityPeriodTimeUnitEnum(str, Enum): - SECONDS = "SECONDS" - MINUTES = "MINUTES" - HOURS = "HOURS" - DAYS = "DAYS" - - -class CardWidth(str, Enum): - SMALL = "SMALL" - MEDIUM = "MEDIUM" - - -class HeightEnum(str, Enum): - SHORT = "SHORT" - MEDIUM = "MEDIUM" - TALL = "TALL" - - -class AlignmentEnum(str, Enum): - LEFT = "LEFT" - RIGHT = "RIGHT" - - -class OrientationEnum(str, Enum): - HORIZONTAL = "HORIZONTAL" - VERTICAL = "VERTICAL" - - -class FileProperties(CamelCaseModel, UrlLengthValidatorMixin): - url: AnyHttpUrl - - _MAX_URL_LENGTH = 1000 - - @validator("url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class ThumbnailProperties(CamelCaseModel, UrlLengthValidatorMixin): - url: AnyHttpUrl - - _MAX_URL_LENGTH = 1000 - - @validator("url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class Suggestion(CamelCaseModel): - text: constr(min_length=1, max_length=25) - postback_data: constr(min_length=1, max_length=2048) - - -class SuggestionReply(Suggestion): - type: Literal["REPLY"] - - -class SuggestionOpenUrl(Suggestion, UrlLengthValidatorMixin): - type: Literal["OPEN_URL"] - url: AnyHttpUrl - - _MAX_URL_LENGTH = 1000 - - @validator("url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class SuggestionDialPhone(Suggestion): - type: Literal["DIAL_PHONE"] - phone_number: Optional[constr(regex=r"\+?\d{5,15}")] = None # noqa: F722 - - -class SuggestionShowLocation(Suggestion): - type: Literal["SHOW_LOCATION"] - latitude: confloat(ge=-90, le=90) - longitude: confloat(ge=-180, le=180) - label: Optional[constr(min_length=1, max_length=100)] = None - - -class SuggestionRequestLocation(Suggestion): - type: Literal["REQUEST_LOCATION"] - - -class CardMedia(CamelCaseModel): - file: FileProperties - thumbnail: Optional[ThumbnailProperties] = None - height: HeightEnum - - -class CardContent(CamelCaseModel): - title: Optional[constr(min_length=1, max_length=200)] = None - description: Optional[constr(min_length=1, max_length=2000)] = None - media: Optional[CardMedia] = None - suggestions: Optional[ - List[ - Union[ - SuggestionShowLocation, - SuggestionDialPhone, - SuggestionOpenUrl, - SuggestionReply, - SuggestionRequestLocation, - ] - ] - ] = None - - @validator("suggestions") - def validate_suggestions(cls, suggestions: List[Suggestion]) -> List[Suggestion]: - if len(suggestions) > 4: - raise ValueError("There can be only four suggestions in a card") - return suggestions - - -class Contents(CardContent): - pass - - -class ContentCarousel(CamelCaseModel): - type: Literal["CAROUSEL"] - card_width: CardWidth - contents: List[Contents] - suggestions: Optional[ - List[ - Union[ - SuggestionShowLocation, - SuggestionDialPhone, - SuggestionOpenUrl, - SuggestionReply, - SuggestionRequestLocation, - ] - ] - ] = None - - @validator("contents") - def validate_contents(cls, contents: List[Contents]) -> List[Contents]: - if len(contents) < 2 or len(contents) > 10: - raise ValueError("There can be only 2 - 10 content objects in a Carousel") - - return contents - - -class ContentCard(CamelCaseModel): - type: Literal["CARD"] - orientation: OrientationEnum - alignment: AlignmentEnum - content: CardContent - suggestions: Optional[ - List[ - Union[ - SuggestionShowLocation, - SuggestionDialPhone, - SuggestionOpenUrl, - SuggestionReply, - SuggestionRequestLocation, - ] - ] - ] = None - - -class ContentFile(CamelCaseModel): - type: Literal["FILE"] - file: FileProperties - thumbnail: Optional[ThumbnailProperties] = None - - -class ContentText(CamelCaseModel): - type: Literal["TEXT"] - text: constr(min_length=1, max_length=1000) - suggestions: Optional[ - List[ - Union[ - SuggestionShowLocation, - SuggestionDialPhone, - SuggestionOpenUrl, - SuggestionReply, - SuggestionRequestLocation, - ] - ] - ] = [] - - -class SmsFailover(CamelCaseModel): - from_number: constr(min_length=1) = Field(alias="from") - text: constr(min_length=1) - validity_period: Optional[int] = None - validity_period_time_unit: Optional[ValidityPeriodTimeUnitEnum] = None - - -class RCSMessageBody(MessageBodyBase): - from_number: Optional[str] = Field(alias="from") - to: str - validity_period: Optional[int] = None - validity_period_time_unit: Optional[ValidityPeriodTimeUnitEnum] = None - content: Union[ContentCarousel, ContentCard, ContentFile, ContentText] - sms_failover: Optional[SmsFailover] = None - notify_url: Optional[str] = None - callback_data: Optional[str] = None - message_id: Optional[str] = None diff --git a/infobip_channels/rcs/Models/response/__init__.py b/infobip_channels/rcs/Models/response/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/rcs/Models/response/core.py b/infobip_channels/rcs/Models/response/core.py deleted file mode 100644 index da748ca..0000000 --- a/infobip_channels/rcs/Models/response/core.py +++ /dev/null @@ -1,36 +0,0 @@ -from typing import Dict, List, Optional - -from infobip_channels.core.models import CamelCaseModel, ResponseBase, ResponseStatus - - -class ServiceException(CamelCaseModel): - message_id: str - text: str - validation_errors: Optional[Dict[str, List[str]]] = None - - -class RequestError(CamelCaseModel): - service_exception: ServiceException - - -class RCSResponseError(ResponseBase): - request_error: RequestError - - -class SendRcsResponseMessage(CamelCaseModel): - to: Optional[str] = None - message_count: Optional[int] = None - message_id: Optional[str] = None - status: ResponseStatus - - -class RCSResponseOK(ResponseBase): - messages: List[SendRcsResponseMessage] - - -class Message(CamelCaseModel): - messages: List[SendRcsResponseMessage] - - -class RCSResponseOKList(ResponseBase): - list: List[Message] diff --git a/infobip_channels/rcs/__init__.py b/infobip_channels/rcs/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/rcs/channel.py b/infobip_channels/rcs/channel.py deleted file mode 100644 index d9030eb..0000000 --- a/infobip_channels/rcs/channel.py +++ /dev/null @@ -1,68 +0,0 @@ -from http import HTTPStatus -from typing import Any, Dict, Type, Union - -import requests - -from infobip_channels.core.channel import Channel -from infobip_channels.core.models import ResponseBase -from infobip_channels.rcs.Models.body.send_bulk_rcs_message import RCSMessageBodyList -from infobip_channels.rcs.Models.body.send_rcs_message import RCSMessageBody -from infobip_channels.rcs.Models.response.core import ( - RCSResponseError, - RCSResponseOK, - RCSResponseOKList, -) - - -class RCSChannel(Channel): - """Class used for interaction with the Infobip's RCS API.""" - - RCS_URL_TEMPLATE = "/ott/rcs/1/" - - def _get_custom_response_class( - self, - raw_response: Union[requests.Response, Any], - response_ok_class: Type[ResponseBase] = RCSResponseOK, - *args, - **kwargs, - ) -> Type[ResponseBase]: - if raw_response.status_code == HTTPStatus.OK: - return response_ok_class - - if raw_response.status_code in ( - HTTPStatus.OK, - HTTPStatus.BAD_REQUEST, - ): - return RCSResponseError - - raise ValueError - - def send_rcs_message( - self, message: Union[RCSMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Used for sending single RCS messages - - :param message: Body of the message to send - :return: Received response - """ - - message = self.validate_message_body(message, RCSMessageBody) - response = self._client.post( - self.RCS_URL_TEMPLATE + "message", message.dict(by_alias=True) - ) - return self._construct_response(response, RCSResponseOK) - - def send_bulk_rcs_message( - self, message: Union[RCSMessageBodyList, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Used for sending bulk RCS messages - - :param message: Body of the message to send - :return: Received response - """ - - message = self.validate_message_body(message, RCSMessageBodyList) - response = self._client.post( - self.RCS_URL_TEMPLATE + "message/bulk", message.dict(by_alias=True) - ) - return self._construct_response(response, RCSResponseOKList) diff --git a/infobip_channels/sms/__init__.py b/infobip_channels/sms/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/sms/channel.py b/infobip_channels/sms/channel.py deleted file mode 100644 index de6c996..0000000 --- a/infobip_channels/sms/channel.py +++ /dev/null @@ -1,665 +0,0 @@ -from http import HTTPStatus -from typing import Any, Dict, Type, Union - -import requests - -from infobip_channels.core.channel import Channel -from infobip_channels.core.models import PostHeaders, ResponseBase -from infobip_channels.sms.models.body.create_tfa_application import ( - CreateTFAApplicationBody, -) -from infobip_channels.sms.models.body.create_tfa_message_template import ( - CreateTFAMessageTemplateBody, -) -from infobip_channels.sms.models.body.preview_message import PreviewSMSMessage -from infobip_channels.sms.models.body.reschedule_sms_messages import ( - RescheduleSMSMessagesMessageBody, -) -from infobip_channels.sms.models.body.resend_pin_over_sms import ResendPINOverSMSBody -from infobip_channels.sms.models.body.resend_pin_over_voice import ( - ResendPINOverVoiceBody, -) -from infobip_channels.sms.models.body.send_binary_message import BinarySMSMessageBody -from infobip_channels.sms.models.body.send_message import SMSMessageBody -from infobip_channels.sms.models.body.send_pin_over_sms import SendPINOverSMSBody -from infobip_channels.sms.models.body.send_pin_over_voice import SendPINOverVoiceBody -from infobip_channels.sms.models.body.update_scheduled_messages_status import ( - UpdateScheduledSMSMessagesMessageBody, -) -from infobip_channels.sms.models.body.update_tfa_application import ( - UpdateTFAApplicationBody, -) -from infobip_channels.sms.models.body.update_tfa_message_template import ( - UpdateTFAMessageTemplateBody, -) -from infobip_channels.sms.models.body.verify_phone_number import VerifyPhoneNumberBody -from infobip_channels.sms.models.query_parameters.get_inbound_messages import ( - GetInboundSMSMessagesQueryParameters, -) -from infobip_channels.sms.models.query_parameters.get_outbound_delivery_reports import ( - GetOutboundSMSDeliveryReportsQueryParameters, -) -from infobip_channels.sms.models.query_parameters.get_outbound_logs import ( - GetOutboundSMSLogsQueryParameters, -) -from infobip_channels.sms.models.query_parameters.get_scheduled_messages import ( - GetScheduledSMSMessagesQueryParameters, -) -from infobip_channels.sms.models.query_parameters.get_scheduled_messages_status import ( - GetScheduledSMSMessagesStatusQueryParameters, -) -from infobip_channels.sms.models.query_parameters.get_tfa_verification_status import ( - GetTFAVerificationStatusQueryParameters, -) -from infobip_channels.sms.models.query_parameters.reschedule_messages import ( - RescheduleSMSMessagesQueryParameters, -) -from infobip_channels.sms.models.query_parameters.send_message import ( - SendSMSMessageQueryParameters, -) -from infobip_channels.sms.models.query_parameters.send_pin_over_sms import ( - SendPINOverSMSQueryParameters, -) -from infobip_channels.sms.models.query_parameters.send_pin_over_voice import ( - SendPINOverVoiceQueryParameters, -) -from infobip_channels.sms.models.query_parameters.update_scheduled_messages_status import ( - UpdateScheduledSMSMessagesQueryParameters, -) -from infobip_channels.sms.models.response.core import SMSResponseError -from infobip_channels.sms.models.response.create_tfa_application import ( - CreateTFAApplicationResponse, -) -from infobip_channels.sms.models.response.create_tfa_message_template import ( - CreateTFAMessageTemplateResponse, -) -from infobip_channels.sms.models.response.get_scheduled_messages import ( - GetScheduledSMSMessagesResponse, -) -from infobip_channels.sms.models.response.get_scheduled_messages_status import ( - GetScheduledSMSMessagesStatusResponse, -) -from infobip_channels.sms.models.response.get_tfa_application import ( - GetTFAApplicationResponse, -) -from infobip_channels.sms.models.response.get_tfa_applications import ( - GetTFAApplicationsResponse, -) -from infobip_channels.sms.models.response.get_tfa_message_template import ( - GetTFAMessageTemplateResponse, -) -from infobip_channels.sms.models.response.get_tfa_message_templates import ( - GetTFAMessageTemplatesResponse, -) -from infobip_channels.sms.models.response.get_tfa_verification_status import ( - GetTFAVerificationStatusResponse, -) -from infobip_channels.sms.models.response.inbound_messages import ( - InboundSMSMessagesResponse, -) -from infobip_channels.sms.models.response.outbound_delivery_reports import ( - OutboundDeliveryReportsResponse, -) -from infobip_channels.sms.models.response.outbound_message_logs import ( - OutboundMessageLogsResponse, -) -from infobip_channels.sms.models.response.preview_message import ( - PreviewSMSMessageResponse, -) -from infobip_channels.sms.models.response.reschedule_sms_messages import ( - RescheduleSMSMessagesResponse, -) -from infobip_channels.sms.models.response.resend_pin_over_sms import ( - ResendPINOverSMSResponse, -) -from infobip_channels.sms.models.response.resend_pin_over_voice import ( - ResendPINOverVoiceResponse, -) -from infobip_channels.sms.models.response.send_message import SendSMSResponse -from infobip_channels.sms.models.response.send_pin_over_sms import ( - SendPINOverSMSResponse, -) -from infobip_channels.sms.models.response.send_pin_over_voice import ( - SendPINOverVoiceResponse, -) -from infobip_channels.sms.models.response.update_scheduled_messages_status import ( - UpdateScheduledSMSMessagesStatusResponse, -) -from infobip_channels.sms.models.response.update_tfa_application import ( - UpdateTFAApplicationResponse, -) -from infobip_channels.sms.models.response.update_tfa_message_template import ( - UpdateTFAMessageTemplateResponse, -) -from infobip_channels.sms.models.response.verify_phone_number import ( - VerifyPhoneNumberResponse, -) - - -class SMSChannel(Channel): - """Class used for interaction with the Infobip's SMS API.""" - - SMS_URL_TEMPLATE_VERSION_1 = "/sms/1/" - SMS_URL_TEMPLATE_VERSION_2 = "/sms/2/" - TFA_URL_TEMPLATE_VERSION_2 = "/2fa/2/" - - def _get_custom_response_class( - self, - raw_response: Union[requests.Response, Any], - response_class: Type[ResponseBase] = SendSMSResponse, - *args, - **kwargs, - ) -> Type[ResponseBase]: - if raw_response.status_code == HTTPStatus.OK: - return response_class - elif raw_response.status_code in ( - HTTPStatus.BAD_REQUEST, - HTTPStatus.UNAUTHORIZED, - HTTPStatus.FORBIDDEN, - HTTPStatus.TOO_MANY_REQUESTS, - HTTPStatus.INTERNAL_SERVER_ERROR, - HTTPStatus.NOT_FOUND, - ): - return SMSResponseError - - raise ValueError - - def send_sms_message( - self, message: Union[SMSMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """99% of all use cases can be achieved by using this API method. Everything - from sending a simple single message to a single destination, up to batch - sending of personalized messages to the thousands of recipients with a single - API request. Language, transliteration, scheduling and every advanced feature - you can think of is supported. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, SMSMessageBody) - - response = self._client.post( - self.SMS_URL_TEMPLATE_VERSION_2 + "text/advanced", - message.dict(by_alias=True), - PostHeaders(authorization=self._client.auth.api_key), - ) - return self._construct_response(response, SendSMSResponse) - - def send_binary_sms_message( - self, message: Union[BinarySMSMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send single or multiple binary messages to one or more destination address. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, BinarySMSMessageBody) - - response = self._client.post( - self.SMS_URL_TEMPLATE_VERSION_2 + "binary/advanced", - message.dict(by_alias=True), - ) - return self._construct_response(response, SendSMSResponse) - - def send_sms_message_over_query_parameters( - self, query_parameters: Union[SendSMSMessageQueryParameters, Dict] - ) -> Union[ResponseBase, Any]: - """ - All message parameters of the message can be defined in the query string. Use - this method only if Send SMS message is not an option for your use case! - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters, SendSMSMessageQueryParameters - ) - - response = self._client.get( - self.SMS_URL_TEMPLATE_VERSION_1 + "text/query", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, SendSMSResponse) - - def preview_sms_message( - self, message: Union[PreviewSMSMessage, Dict] - ) -> Union[ResponseBase, Any]: - """ - Avoid unpleasant surprises and check how different message configurations - will affect your message text, number of characters and message parts. - - :param message: Body of the message to send - :return: Received response - """ - - message = self.validate_message_body(message, PreviewSMSMessage) - - response = self._client.post( - self.SMS_URL_TEMPLATE_VERSION_1 + "preview", - message.dict(by_alias=True), - ) - return self._construct_response(response, PreviewSMSMessageResponse) - - def get_outbound_sms_delivery_reports( - self, - query_parameters: Union[ - GetOutboundSMSDeliveryReportsQueryParameters, Dict - ] = None, - ) -> Union[ResponseBase, Any]: - """If you are for any reason unable to receive real-time delivery reports on - your endpoint, you can use this API method to learn if and when the message - has been delivered to the recipient. Each request will return a batch of - delivery reports - only once. The following API request will return only new - reports that arrived since the last API request in the last 48 hours. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters or {}, GetOutboundSMSDeliveryReportsQueryParameters - ) - - response = self._client.get( - self.SMS_URL_TEMPLATE_VERSION_1 + "reports", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, OutboundDeliveryReportsResponse) - - def get_outbound_sms_message_logs( - self, - query_parameters: Union[GetOutboundSMSLogsQueryParameters, Dict] = None, - ) -> Union[ResponseBase, Any]: - """Use this method for displaying logs for example in the user interface. - Available are the logs for the last 48 hours and you can only retrieve - maximum of 1000 logs per call. See message delivery reports if your use case - is to verify message delivery. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters or {}, GetOutboundSMSLogsQueryParameters - ) - - response = self._client.get( - self.SMS_URL_TEMPLATE_VERSION_1 + "logs", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, OutboundMessageLogsResponse) - - def get_inbound_sms_messages( - self, - query_parameters: Union[GetInboundSMSMessagesQueryParameters, Dict] = None, - ) -> Union[ResponseBase, Any]: - """If for some reason you are unable to receive incoming SMS to the endpoint - of your choice in real time, you can use this API call to fetch messages. - Each request will return a batch of received messages - only once. The API - request will only return new messages that arrived since the last API request. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters or {}, GetInboundSMSMessagesQueryParameters - ) - - response = self._client.get( - self.SMS_URL_TEMPLATE_VERSION_1 + "inbox/reports", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, InboundSMSMessagesResponse) - - def get_scheduled_sms_messages( - self, - query_parameters: Union[GetScheduledSMSMessagesQueryParameters, Dict], - ) -> Union[ResponseBase, Any]: - """See the status and the scheduled time of your SMS messages. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters, GetScheduledSMSMessagesQueryParameters - ) - - response = self._client.get( - self.SMS_URL_TEMPLATE_VERSION_1 + "bulks", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, GetScheduledSMSMessagesResponse) - - def reschedule_sms_messages( - self, - query_parameters: Union[RescheduleSMSMessagesQueryParameters, Dict], - message: Union[RescheduleSMSMessagesMessageBody, Dict], - ) -> Union[ResponseBase, Any]: - """Change the date and time for sending scheduled messages. - - :param query_parameters: Query parameters to send with the request - :param message: Body of the message to send - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters, RescheduleSMSMessagesQueryParameters - ) - - message = self.validate_message_body(message, RescheduleSMSMessagesMessageBody) - - response = self._client.put( - self.SMS_URL_TEMPLATE_VERSION_1 + "bulks", - message.dict(by_alias=True), - params=query_parameters.dict(by_alias=True), - ) - - return self._construct_response(response, RescheduleSMSMessagesResponse) - - def get_scheduled_sms_messages_status( - self, - query_parameters: Union[GetScheduledSMSMessagesStatusQueryParameters, Dict], - ) -> Union[ResponseBase, Any]: - """See the status of scheduled messages. - - :param query_parameters: Query parameters to send with the request - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters, GetScheduledSMSMessagesStatusQueryParameters - ) - - response = self._client.get( - self.SMS_URL_TEMPLATE_VERSION_1 + "bulks/status", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, GetScheduledSMSMessagesStatusResponse) - - def update_scheduled_sms_messages_status( - self, - query_parameters: Union[UpdateScheduledSMSMessagesQueryParameters, Dict], - message: Union[UpdateScheduledSMSMessagesMessageBody, Dict], - ) -> Union[ResponseBase, Any]: - """Change status or completely cancel sending of scheduled messages. - - :param query_parameters: Query parameters to send with the request - :param message: Body of the message to send - :return: Received response - """ - query_parameters = self.validate_query_parameter( - query_parameters, UpdateScheduledSMSMessagesQueryParameters - ) - - message = self.validate_message_body( - message, UpdateScheduledSMSMessagesMessageBody - ) - - response = self._client.put( - self.SMS_URL_TEMPLATE_VERSION_1 + "bulks/status", - message.dict(by_alias=True), - params=query_parameters.dict(by_alias=True), - ) - - return self._construct_response( - response, UpdateScheduledSMSMessagesStatusResponse - ) - - def get_tfa_applications(self) -> Union[ResponseBase, Any]: - """Use this method to list your applications. - - :return: Received response - """ - response = self._client.get(self.TFA_URL_TEMPLATE_VERSION_2 + "applications") - return self._construct_response(response, GetTFAApplicationsResponse) - - def create_tfa_application( - self, - request_body: Union[CreateTFAApplicationBody, Dict], - ) -> Union[ResponseBase, Any]: - """Create and configure a new 2FA application. - - :param request_body: Body of the TFA application to create - :return: Received response - """ - message = self.validate_message_body(request_body, CreateTFAApplicationBody) - - response = self._client.post( - self.TFA_URL_TEMPLATE_VERSION_2 + "applications", - message.dict(by_alias=True), - ) - - return self._construct_response(response, CreateTFAApplicationResponse) - - def get_tfa_application( - self, - application_id: str, - ) -> Union[ResponseBase, Any]: - """Get a single 2FA application to see its configuration details. - - :param application_id: ID of application for which configuration view was requested. - :return: Received response - """ - response = self._client.get( - self.TFA_URL_TEMPLATE_VERSION_2 + f"applications/{application_id}" - ) - return self._construct_response(response, GetTFAApplicationResponse) - - def update_tfa_application( - self, - application_id: str, - request_body: Union[UpdateTFAApplicationBody, Dict], - ) -> Union[ResponseBase, Any]: - """Change configuration options for your existing 2FA application. - - :param application_id: ID of application that should be updated. - :param request_body: Body of the TFA application to update - :return: Received response - """ - message = self.validate_message_body(request_body, UpdateTFAApplicationBody) - - response = self._client.put( - self.TFA_URL_TEMPLATE_VERSION_2 + f"applications/{application_id}", - message.dict(by_alias=True), - ) - - return self._construct_response(response, UpdateTFAApplicationResponse) - - def get_tfa_message_templates( - self, - application_id: str, - ) -> Union[ResponseBase, Any]: - """Use this method to list your message templates. - - :return: Received response - """ - response = self._client.get( - self.TFA_URL_TEMPLATE_VERSION_2 + f"applications/{application_id}/messages" - ) - return self._construct_response(response, GetTFAMessageTemplatesResponse) - - def create_tfa_message_template( - self, - application_id: str, - request_body: Union[CreateTFAMessageTemplateBody, Dict], - ) -> Union[ResponseBase, Any]: - """Once you have your 2FA application, create one or more message templates where your PIN will be dynamically - included when you send the PIN message. - - :param application_id: ID of application for which requested message was created. - :param request_body: Body of the TFA message template to create - :return: Received response - """ - message = self.validate_message_body(request_body, CreateTFAMessageTemplateBody) - - response = self._client.post( - self.TFA_URL_TEMPLATE_VERSION_2 + f"applications/{application_id}/messages", - message.dict(by_alias=True), - ) - - return self._construct_response(response, CreateTFAMessageTemplateResponse) - - def get_tfa_message_template( - self, - application_id: str, - message_id: str, - ) -> Union[ResponseBase, GetTFAMessageTemplateResponse, Any]: - """Get a single 2FA message template to see its configuration details. - - :param application_id: ID of application for which requested message was created. - :param message_id: requested message ID - :return: Received response - """ - response = self._client.get( - self.TFA_URL_TEMPLATE_VERSION_2 - + f"applications/{application_id}/messages/{message_id}" - ) - return self._construct_response(response, GetTFAMessageTemplateResponse) - - def update_tfa_message_template( - self, - application_id: str, - message_id: str, - request_body: Union[UpdateTFAMessageTemplateBody, Dict], - ) -> Union[ResponseBase, Any]: - """Change configuration options for your existing 2FA message template. - - :param application_id: ID of application for which requested message was created. - :param message_id: requested message ID - :param request_body: Body of the TFA message template to update - :return: Received response - """ - message = self.validate_message_body(request_body, UpdateTFAMessageTemplateBody) - - response = self._client.put( - self.TFA_URL_TEMPLATE_VERSION_2 - + f"applications/{application_id}/messages/{message_id}", - message.dict(by_alias=True), - ) - - return self._construct_response(response, UpdateTFAMessageTemplateResponse) - - def send_pin_over_sms( - self, - query_parameters: Union[SendPINOverSMSQueryParameters, Dict], - request_body: Union[SendPINOverSMSBody, Dict], - ) -> Union[ResponseBase, SendPINOverSMSResponse, Any]: - """Send a PIN code over SMS using a previously created message template. - - :param query_parameters: Query parameters for the request - :param request_body: Body of the send PIN request - :return: Received response - """ - - query_parameters = self.validate_query_parameter( - query_parameters or {}, SendPINOverSMSQueryParameters - ) - - body = self.validate_message_body(request_body, SendPINOverSMSBody) - - response = self._client.post( - self.TFA_URL_TEMPLATE_VERSION_2 + "pin", - body.dict(by_alias=True), - headers=PostHeaders(authorization=self._client.auth.api_key), - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, SendPINOverSMSResponse) - - def resend_pin_over_sms( - self, - pin_id: str, - request_body: Union[ResendPINOverSMSBody, Dict], - ) -> Union[ResponseBase, ResendPINOverSMSResponse, Any]: - """If needed, you can resend the same (previously sent) PIN code over SMS. - - :param pin_id: ID of the pin code that has to be verified - :param request_body: Body of the resend PIN request - :return: Received response - """ - body = self.validate_message_body(request_body, ResendPINOverSMSBody) - - response = self._client.post( - self.TFA_URL_TEMPLATE_VERSION_2 + f"pin/{pin_id}/resend", - body.dict(by_alias=True), - PostHeaders(authorization=self._client.auth.api_key), - ) - return self._construct_response(response, ResendPINOverSMSResponse) - - def send_pin_over_voice( - self, - query_parameters: Union[SendPINOverVoiceQueryParameters, Dict], - request_body: Union[SendPINOverVoiceBody, Dict], - ) -> Union[ResponseBase, SendPINOverVoiceResponse, Any]: - """Send a PIN code over Voice using previously created message template. - - :param query_parameters: Query parameters for the request - :param request_body: Body of the TFA message template to create - :return: Received response - """ - body = self.validate_message_body(request_body, SendPINOverVoiceBody) - - response = self._client.post( - self.TFA_URL_TEMPLATE_VERSION_2 + "pin/voice", - body.dict(by_alias=True), - PostHeaders(authorization=self._client.auth.api_key), - ) - return self._construct_response(response, SendPINOverVoiceResponse) - - def resend_pin_over_voice( - self, - pin_id: str, - request_body: Union[ResendPINOverVoiceBody, Dict], - ) -> Union[ResponseBase, ResendPINOverVoiceResponse, Any]: - """If needed, you can resend the same (previously sent) PIN code over Voice. - - :param pin_id: ID of the pin code that has to be verified - :param request_body: Body of the TFA message template to update - :return: Received response - """ - - body = self.validate_message_body(request_body, ResendPINOverVoiceBody) - - response = self._client.post( - self.TFA_URL_TEMPLATE_VERSION_2 + f"pin/{pin_id}/resend/voice", - body.dict(by_alias=True), - PostHeaders(authorization=self._client.auth.api_key), - ) - return self._construct_response(response, ResendPINOverVoiceResponse) - - def verify_phone_number( - self, - pin_id: str, - request_body: Union[VerifyPhoneNumberBody, Dict], - ) -> Union[ResponseBase, VerifyPhoneNumberResponse, Any]: - """Verify a phone number to confirm successful 2FA authentication. - - :param pin_id: ID of the pin code that has to be verified - :param request_body: Body of the request to verify phone number - :return: Received response - """ - body = self.validate_message_body(request_body, VerifyPhoneNumberBody) - - response = self._client.post( - self.TFA_URL_TEMPLATE_VERSION_2 + f"pin/{pin_id}/verify", - body.dict(by_alias=True), - headers=PostHeaders(authorization=self._client.auth.api_key), - ) - return self._construct_response(response, VerifyPhoneNumberResponse) - - def get_tfa_verification_status( - self, - app_id: str, - query_parameters: Union[GetTFAVerificationStatusQueryParameters, Dict], - ) -> Union[ResponseBase, GetTFAVerificationStatusResponse, Any]: - """Check if a phone number is already verified for a specific 2FA application. - - :param app_id: ID of the pin code that has to be verified - :param query_parameters: Query parameters for the request - :return: Received response - """ - - query_parameters = self.validate_query_parameter( - query_parameters or {}, GetTFAVerificationStatusQueryParameters - ) - - response = self._client.get( - self.TFA_URL_TEMPLATE_VERSION_2 + f"applications/{app_id}/verifications", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, GetTFAVerificationStatusResponse) diff --git a/infobip_channels/sms/models/__init__.py b/infobip_channels/sms/models/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/sms/models/body/__init__.py b/infobip_channels/sms/models/body/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/sms/models/body/core.py b/infobip_channels/sms/models/body/core.py deleted file mode 100644 index a69ccac..0000000 --- a/infobip_channels/sms/models/body/core.py +++ /dev/null @@ -1,108 +0,0 @@ -from datetime import datetime -from enum import Enum -from typing import List, Optional, Union - -from pydantic import ( - AnyHttpUrl, - Field, - StrictBool, - conint, - conlist, - constr, - root_validator, - validator, -) - -from infobip_channels.core.models import ( - CamelCaseModel, - ContentTypeEnum, - DateTimeValidator, - DaysEnum, - FromAndToTimeValidator, -) - - -class TrackEnum(str, Enum): - SMS = "SMS" - URL = "URL" - - -class TypeEnum(str, Enum): - ONE_TIME_PIN = "ONE_TIME_PIN" - SOCIAL_INVITES = "SOCIAL_INVITES" - - -class TimeUnitEnum(str, Enum): - MINUTE = "MINUTE" - HOUR = "HOUR" - DAY = "DAY" - - -class IndiaDlt(CamelCaseModel): - content_template_id: Optional[str] = None - principal_entity_id: constr(min_length=1, max_length=30) = None - - -class TurkeyRecipientTypeEnum(str, Enum): - BIREYSEL = "BIREYSEL" - TACIR = "TACIR" - - -class TurkeyIys(CamelCaseModel): - brand_code: Optional[int] - recipient_type: TurkeyRecipientTypeEnum - - -class Regional(CamelCaseModel): - india_dlt: Optional[IndiaDlt] = None - turkey_iys: Optional[TurkeyIys] = None - - -class Time(CamelCaseModel): - hour: conint(ge=0, le=23) - minute: conint(ge=0, le=59) - - -class Destination(CamelCaseModel): - message_id: Optional[str] = None - to: constr(min_length=0, max_length=50) - - -class DeliveryTimeWindow(CamelCaseModel, FromAndToTimeValidator): - days: conlist(DaysEnum, min_items=1) - from_time: Optional[Time] = Field(alias="from", default=None) - to: Optional[Time] = None - - @root_validator - def validate_from_and_to(cls, values): - return super().validate_from_and_to(values) - - -class CoreMessage(CamelCaseModel, DateTimeValidator): - callback_data: Optional[constr(min_length=0, max_length=4000)] = None - delivery_time_window: Optional[DeliveryTimeWindow] = None - destinations: List[Destination] - flash: Optional[StrictBool] = False - from_name: Optional[str] = Field(alias="from", default=None) - intermediate_report: Optional[StrictBool] = False - notify_content_type: Optional[ContentTypeEnum] = None - notify_url: Optional[AnyHttpUrl] = None - regional: Optional[Regional] = None - send_at: Optional[Union[datetime, str]] = None - validity_period: Optional[conint(gt=0, le=2880)] - - @validator("send_at") - def convert_send_at_time_to_correct_format_validate_limit(cls, value): - return super().convert_time_to_correct_format_validate_limit(value) - - -class SendingSpeedLimit(CamelCaseModel): - amount: int - time_unit: Optional[TimeUnitEnum] = None - - -class Tracking(CamelCaseModel): - base_url: Optional[str] = None - process_key: Optional[str] = None - track: Optional[TrackEnum] = None - type: Optional[TypeEnum] = None diff --git a/infobip_channels/sms/models/body/create_tfa_application.py b/infobip_channels/sms/models/body/create_tfa_application.py deleted file mode 100644 index 3712453..0000000 --- a/infobip_channels/sms/models/body/create_tfa_application.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import MessageBodyBase -from infobip_channels.sms.models.core.tfa_application import TFAApplication - - -class CreateTFAApplicationBody(MessageBodyBase, TFAApplication): - pass diff --git a/infobip_channels/sms/models/body/create_tfa_message_template.py b/infobip_channels/sms/models/body/create_tfa_message_template.py deleted file mode 100644 index c7c36ca..0000000 --- a/infobip_channels/sms/models/body/create_tfa_message_template.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import MessageBodyBase -from infobip_channels.sms.models.core.tfa_message_template import TFAMessageTemplate - - -class CreateTFAMessageTemplateBody(MessageBodyBase, TFAMessageTemplate): - pass diff --git a/infobip_channels/sms/models/body/preview_message.py b/infobip_channels/sms/models/body/preview_message.py deleted file mode 100644 index a995f26..0000000 --- a/infobip_channels/sms/models/body/preview_message.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import ( - LanguageEnum, - MessageBodyBase, - TransliterationEnum, -) - - -class PreviewSMSMessage(MessageBodyBase): - language_code: Optional[LanguageEnum] = None - text: str - transliteration: Optional[TransliterationEnum] diff --git a/infobip_channels/sms/models/body/reschedule_sms_messages.py b/infobip_channels/sms/models/body/reschedule_sms_messages.py deleted file mode 100644 index 3025cca..0000000 --- a/infobip_channels/sms/models/body/reschedule_sms_messages.py +++ /dev/null @@ -1,14 +0,0 @@ -from datetime import datetime -from typing import Optional, Union - -from pydantic import validator - -from infobip_channels.core.models import DateTimeValidator, MessageBodyBase - - -class RescheduleSMSMessagesMessageBody(MessageBodyBase, DateTimeValidator): - send_at: Optional[Union[datetime, str]] = None - - @validator("send_at") - def convert_send_at_time_to_correct_format_validate_limit(cls, value): - return super().convert_time_to_correct_format_validate_limit(value) diff --git a/infobip_channels/sms/models/body/resend_pin_over_sms.py b/infobip_channels/sms/models/body/resend_pin_over_sms.py deleted file mode 100644 index bba9d1e..0000000 --- a/infobip_channels/sms/models/body/resend_pin_over_sms.py +++ /dev/null @@ -1,7 +0,0 @@ -from typing import Dict, Optional - -from infobip_channels.core.models import CamelCaseModel, MessageBodyBase - - -class ResendPINOverSMSBody(MessageBodyBase, CamelCaseModel): - placeholders: Optional[Dict[str, str]] diff --git a/infobip_channels/sms/models/body/resend_pin_over_voice.py b/infobip_channels/sms/models/body/resend_pin_over_voice.py deleted file mode 100644 index f9b95ea..0000000 --- a/infobip_channels/sms/models/body/resend_pin_over_voice.py +++ /dev/null @@ -1,3 +0,0 @@ -from infobip_channels.sms.models.body.resend_pin_over_sms import ResendPINOverSMSBody - -ResendPINOverVoiceBody = ResendPINOverSMSBody diff --git a/infobip_channels/sms/models/body/send_binary_message.py b/infobip_channels/sms/models/body/send_binary_message.py deleted file mode 100644 index 820b339..0000000 --- a/infobip_channels/sms/models/body/send_binary_message.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import List, Optional - -from pydantic import validator - -from infobip_channels.core.models import CamelCaseModel, MessageBodyBase -from infobip_channels.sms.models.body.core import CoreMessage, SendingSpeedLimit - - -class Binary(CamelCaseModel): - data_coding: Optional[int] = None - esm_class: Optional[int] = None - hex: str - - @validator("hex") - def validate_string_characters(cls, value: str) -> str: - remove_whitespace = "".join(value.split()) - try: - int(remove_whitespace, 16) - return value - except ValueError: - raise ValueError("Not all characters in hex field are hex values") - - -class Message(CoreMessage): - binary: Binary - - -class BinarySMSMessageBody(MessageBodyBase): - bulk_id: Optional[str] = None - messages: List[Message] - sending_speed_limit: Optional[SendingSpeedLimit] = None diff --git a/infobip_channels/sms/models/body/send_message.py b/infobip_channels/sms/models/body/send_message.py deleted file mode 100644 index 796f864..0000000 --- a/infobip_channels/sms/models/body/send_message.py +++ /dev/null @@ -1,39 +0,0 @@ -from typing import List, Optional - -from pydantic.types import constr - -from infobip_channels.core.models import ( - CamelCaseModel, - LanguageEnum, - MessageBodyBase, - TransliterationEnum, -) -from infobip_channels.sms.models.body.core import ( - CoreMessage, - SendingSpeedLimit, - Tracking, -) - - -class Message(CoreMessage): - text: Optional[str] = None - language: Optional[LanguageEnum] = None - transliteration: Optional[TransliterationEnum] - entity_id: Optional[constr(max_length=50)] = None - application_id: Optional[constr(max_length=50)] = None - - -class URLOptions(CamelCaseModel): - shorten_url: Optional[bool] = None - track_clicks: Optional[bool] = None - tracking_url: Optional[str] = None - remove_protocol: Optional[bool] = None - custom_domain: Optional[str] = None - - -class SMSMessageBody(MessageBodyBase): - bulk_id: Optional[str] = None - messages: List[Message] - sending_speed_limit: Optional[SendingSpeedLimit] = None - url_options: Optional[URLOptions] = None - tracking: Optional[Tracking] = None diff --git a/infobip_channels/sms/models/body/send_pin_over_sms.py b/infobip_channels/sms/models/body/send_pin_over_sms.py deleted file mode 100644 index d9258a2..0000000 --- a/infobip_channels/sms/models/body/send_pin_over_sms.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Dict, Optional - -from pydantic.types import constr - -from infobip_channels.core.models import CamelCaseModel, MessageBodyBase - - -class SendPINOverSMSBody(MessageBodyBase, CamelCaseModel): - application_id: constr(min_length=1) = None - message_id: constr(min_length=1) = None - from_id: Optional[str] - to: constr(min_length=1) = None - placeholders: Optional[Dict[str, str]] diff --git a/infobip_channels/sms/models/body/send_pin_over_voice.py b/infobip_channels/sms/models/body/send_pin_over_voice.py deleted file mode 100644 index 980272a..0000000 --- a/infobip_channels/sms/models/body/send_pin_over_voice.py +++ /dev/null @@ -1,3 +0,0 @@ -from infobip_channels.sms.models.body.send_pin_over_sms import SendPINOverSMSBody - -SendPINOverVoiceBody = SendPINOverSMSBody diff --git a/infobip_channels/sms/models/body/update_scheduled_messages_status.py b/infobip_channels/sms/models/body/update_scheduled_messages_status.py deleted file mode 100644 index e021d14..0000000 --- a/infobip_channels/sms/models/body/update_scheduled_messages_status.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.core.models import MessageBodyBase, MessageStatus - - -class UpdateScheduledSMSMessagesMessageBody(MessageBodyBase): - status: MessageStatus diff --git a/infobip_channels/sms/models/body/update_tfa_application.py b/infobip_channels/sms/models/body/update_tfa_application.py deleted file mode 100644 index 7f391eb..0000000 --- a/infobip_channels/sms/models/body/update_tfa_application.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import MessageBodyBase -from infobip_channels.sms.models.core.tfa_application import TFAApplication - - -class UpdateTFAApplicationBody(MessageBodyBase, TFAApplication): - pass diff --git a/infobip_channels/sms/models/body/update_tfa_message_template.py b/infobip_channels/sms/models/body/update_tfa_message_template.py deleted file mode 100644 index c0503f5..0000000 --- a/infobip_channels/sms/models/body/update_tfa_message_template.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import MessageBodyBase -from infobip_channels.sms.models.core.tfa_message_template import TFAMessageTemplate - - -class UpdateTFAMessageTemplateBody(MessageBodyBase, TFAMessageTemplate): - pass diff --git a/infobip_channels/sms/models/body/verify_phone_number.py b/infobip_channels/sms/models/body/verify_phone_number.py deleted file mode 100644 index 02f1478..0000000 --- a/infobip_channels/sms/models/body/verify_phone_number.py +++ /dev/null @@ -1,7 +0,0 @@ -from pydantic.types import constr - -from infobip_channels.core.models import CamelCaseModel, MessageBodyBase - - -class VerifyPhoneNumberBody(MessageBodyBase, CamelCaseModel): - pin: constr(min_length=1) diff --git a/infobip_channels/sms/models/core/__init__.py b/infobip_channels/sms/models/core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/sms/models/core/tfa_application.py b/infobip_channels/sms/models/core/tfa_application.py deleted file mode 100644 index bf793cf..0000000 --- a/infobip_channels/sms/models/core/tfa_application.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Optional - -from pydantic.types import constr - -from infobip_channels.core.models import CamelCaseModel -from infobip_channels.sms.models.core.tfa_application_configuration import ( - TFAApplicationConfiguration, -) - - -class TFAApplication(CamelCaseModel): - application_id: Optional[str] - name: constr(min_length=1) = None - configuration: Optional[TFAApplicationConfiguration] = None - enabled: Optional[bool] diff --git a/infobip_channels/sms/models/core/tfa_application_configuration.py b/infobip_channels/sms/models/core/tfa_application_configuration.py deleted file mode 100644 index d749b18..0000000 --- a/infobip_channels/sms/models/core/tfa_application_configuration.py +++ /dev/null @@ -1,12 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import CamelCaseModel - - -class TFAApplicationConfiguration(CamelCaseModel): - allow_multiple_pin_verifications: Optional[bool] - pin_attempts: Optional[int] - pin_time_to_live: Optional[str] - verify_pin_limit: Optional[str] - send_pin_per_application_limit: Optional[str] - send_pin_per_phone_number_limit: Optional[str] diff --git a/infobip_channels/sms/models/core/tfa_message_template.py b/infobip_channels/sms/models/core/tfa_message_template.py deleted file mode 100644 index df72b1b..0000000 --- a/infobip_channels/sms/models/core/tfa_message_template.py +++ /dev/null @@ -1,54 +0,0 @@ -from enum import Enum -from typing import Optional - -from pydantic import Field -from pydantic.types import constr - -from infobip_channels.core.models import CamelCaseModel -from infobip_channels.sms.models.body.core import Regional - - -class PINTypeEnum(str, Enum): - NUMERIC = "NUMERIC" - ALPHA = "ALPHA" - HEX = "HEX" - ALPHANUMERIC = "ALPHANUMERIC" - - -class LanguageEnum(str, Enum): - EN = "en" - ES = "es" - CA = "ca" - DA = "da" - NL = "nl" - FR = "fr" - DE = "de" - IT = "it" - JA = "ja" - KO = "ko" - NO = "no" - PL = "pl" - RU = "ru" - SV = "sv" - FI = "fi" - HR = "hr" - SL = "sl" - RO = "ro" - PT_PT = "pt-pt" - PT_BR = "pt-br" - ZH_CN = "zh-cn" - ZH_TW = "zh-tw" - - -class TFAMessageTemplate(CamelCaseModel): - application_id: Optional[str] - language: Optional[LanguageEnum] - message_id: Optional[str] - message_text: constr(min_length=1) = None - pin_length: Optional[int] - pin_placeholder: constr(min_length=1) = None - pin_type: PINTypeEnum - regional: Optional[Regional] = None - repeat_dtmf: Optional[str] = Field(alias="repeatDTMF", default=None) - sender_id: Optional[str] - speech_rate: Optional[float] diff --git a/infobip_channels/sms/models/core/tfa_pin_status.py b/infobip_channels/sms/models/core/tfa_pin_status.py deleted file mode 100644 index 8f3e166..0000000 --- a/infobip_channels/sms/models/core/tfa_pin_status.py +++ /dev/null @@ -1,11 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import CamelCaseModel - - -class PINStatus(CamelCaseModel): - pin_id: str - to: str - call_status: Optional[str] - nc_status: Optional[str] - sms_status: Optional[str] diff --git a/infobip_channels/sms/models/core/tfa_pin_verification.py b/infobip_channels/sms/models/core/tfa_pin_verification.py deleted file mode 100644 index 9aa1875..0000000 --- a/infobip_channels/sms/models/core/tfa_pin_verification.py +++ /dev/null @@ -1,11 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import CamelCaseModel - - -class PINVerification(CamelCaseModel): - attempts_remaining: int - msisdn: str - pin_error: Optional[str] - pin_id: str - verified: bool diff --git a/infobip_channels/sms/models/query_parameters/__init__.py b/infobip_channels/sms/models/query_parameters/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/sms/models/query_parameters/core.py b/infobip_channels/sms/models/query_parameters/core.py deleted file mode 100644 index aab43d2..0000000 --- a/infobip_channels/sms/models/query_parameters/core.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.core.models import QueryParameter - - -class ScheduledSMSMessages(QueryParameter): - bulk_id: str diff --git a/infobip_channels/sms/models/query_parameters/get_inbound_messages.py b/infobip_channels/sms/models/query_parameters/get_inbound_messages.py deleted file mode 100644 index d9833de..0000000 --- a/infobip_channels/sms/models/query_parameters/get_inbound_messages.py +++ /dev/null @@ -1,9 +0,0 @@ -from typing import Optional - -from pydantic import conint - -from infobip_channels.core.models import QueryParameter - - -class GetInboundSMSMessagesQueryParameters(QueryParameter): - limit: Optional[conint(ge=1, le=1000)] diff --git a/infobip_channels/sms/models/query_parameters/get_outbound_delivery_reports.py b/infobip_channels/sms/models/query_parameters/get_outbound_delivery_reports.py deleted file mode 100644 index b0cfb76..0000000 --- a/infobip_channels/sms/models/query_parameters/get_outbound_delivery_reports.py +++ /dev/null @@ -1,11 +0,0 @@ -from typing import Optional - -from pydantic import conint - -from infobip_channels.core.models import QueryParameter - - -class GetOutboundSMSDeliveryReportsQueryParameters(QueryParameter): - bulk_id: Optional[str] = None - message_id: Optional[str] = None - limit: Optional[conint(ge=1, le=1000)] diff --git a/infobip_channels/sms/models/query_parameters/get_outbound_logs.py b/infobip_channels/sms/models/query_parameters/get_outbound_logs.py deleted file mode 100644 index 987067a..0000000 --- a/infobip_channels/sms/models/query_parameters/get_outbound_logs.py +++ /dev/null @@ -1,31 +0,0 @@ -from datetime import datetime -from typing import List, Optional, Union - -from pydantic import Field, conint, validator - -from infobip_channels.core.models import ( - DateTimeValidator, - GeneralStatus, - QueryParameter, -) - - -class GetOutboundSMSLogsQueryParameters(QueryParameter, DateTimeValidator): - from_name: Optional[str] = Field(alias="from", default=None) - to: Optional[str] = None - bulk_id: Optional[List[str]] = None - message_id: Optional[List[str]] = None - general_status: Optional[GeneralStatus] = None - sent_since: Optional[Union[datetime, str]] = None - sent_until: Optional[Union[datetime, str]] = None - limit: Optional[conint(ge=1, le=1000)] = None - mcc: Optional[str] = None - mnc: Optional[str] = None - - @validator("sent_since") - def convert_send_at_to_correct_format(cls, value): - return super().convert_time_to_correct_format(value) - - @validator("sent_until") - def convert_sent_until_to_correct_format(cls, value): - return super().convert_time_to_correct_format(value) diff --git a/infobip_channels/sms/models/query_parameters/get_scheduled_messages.py b/infobip_channels/sms/models/query_parameters/get_scheduled_messages.py deleted file mode 100644 index 62f5f5e..0000000 --- a/infobip_channels/sms/models/query_parameters/get_scheduled_messages.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.sms.models.query_parameters.core import ScheduledSMSMessages - - -class GetScheduledSMSMessagesQueryParameters(ScheduledSMSMessages): - pass diff --git a/infobip_channels/sms/models/query_parameters/get_scheduled_messages_status.py b/infobip_channels/sms/models/query_parameters/get_scheduled_messages_status.py deleted file mode 100644 index 63ffe00..0000000 --- a/infobip_channels/sms/models/query_parameters/get_scheduled_messages_status.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.sms.models.query_parameters.core import ScheduledSMSMessages - - -class GetScheduledSMSMessagesStatusQueryParameters(ScheduledSMSMessages): - pass diff --git a/infobip_channels/sms/models/query_parameters/get_tfa_verification_status.py b/infobip_channels/sms/models/query_parameters/get_tfa_verification_status.py deleted file mode 100644 index 3bdc91c..0000000 --- a/infobip_channels/sms/models/query_parameters/get_tfa_verification_status.py +++ /dev/null @@ -1,9 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import QueryParameter - - -class GetTFAVerificationStatusQueryParameters(QueryParameter): - msisdn: str - verified: Optional[bool] - sent: Optional[bool] diff --git a/infobip_channels/sms/models/query_parameters/reschedule_messages.py b/infobip_channels/sms/models/query_parameters/reschedule_messages.py deleted file mode 100644 index 5b47524..0000000 --- a/infobip_channels/sms/models/query_parameters/reschedule_messages.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.sms.models.query_parameters.core import ScheduledSMSMessages - - -class RescheduleSMSMessagesQueryParameters(ScheduledSMSMessages): - pass diff --git a/infobip_channels/sms/models/query_parameters/send_message.py b/infobip_channels/sms/models/query_parameters/send_message.py deleted file mode 100644 index e61d0eb..0000000 --- a/infobip_channels/sms/models/query_parameters/send_message.py +++ /dev/null @@ -1,58 +0,0 @@ -from datetime import datetime -from enum import Enum -from typing import List, Optional, Union - -from pydantic import AnyHttpUrl, Field, StrictBool, conint, validator - -from infobip_channels.core.models import DateTimeValidator, QueryParameter, url_encoding - - -class TransliterationEnum(str, Enum): - TURKISH = "TURKISH" - GREEK = "GREEK" - CYRILLIC = "CYRILLIC" - SERBIAN_CYRILLIC = "SERBIAN_CYRILLIC" - CENTRAL_EUROPEAN = "CENTRAL_EUROPEAN" - BALTIC = "BALTIC" - NON_UNICODE = "NON_UNICODE" - - -class ContentTypeEnum(str, Enum): - APPLICATION_JSON = "application/json" - APPLICATION_XML = "application/xml" - - -class TrackEnum(str, Enum): - SMS = "SMS" - URL = "URL" - - -class SendSMSMessageQueryParameters(QueryParameter, DateTimeValidator): - username: str - password: str - bulk_id: Optional[str] = None - from_name: Optional[str] = Field(alias="from", default=None) - to: List[str] - text: Optional[str] = None - flash: Optional[StrictBool] = False - transliteration: Optional[TransliterationEnum] - language_code: Optional[str] = None - intermediate_report: Optional[StrictBool] = None - notify_url: Optional[AnyHttpUrl] = None - notify_content_type: Optional[ContentTypeEnum] = None - callback_data: Optional[str] = None - validity_period: Optional[conint(gt=0, le=2880)] - send_at: Optional[Union[datetime, str]] = None - track: Optional[TrackEnum] = None - process_key: Optional[str] = None - tracking_type: Optional[str] = None - india_dlt_content_template_id: Optional[str] = None - india_dlt_principal_entity_id: Optional[str] = None - - def url_encode(self): - self.username = url_encoding(self.username) - self.password = url_encoding(self.password) - - @validator("send_at") - def convert_send_at_time_to_correct_format_validate_limit(cls, value): - return super().convert_time_to_correct_format_validate_limit(value) diff --git a/infobip_channels/sms/models/query_parameters/send_pin_over_sms.py b/infobip_channels/sms/models/query_parameters/send_pin_over_sms.py deleted file mode 100644 index f03a37f..0000000 --- a/infobip_channels/sms/models/query_parameters/send_pin_over_sms.py +++ /dev/null @@ -1,7 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import QueryParameter - - -class SendPINOverSMSQueryParameters(QueryParameter): - nc_needed: Optional[bool] diff --git a/infobip_channels/sms/models/query_parameters/send_pin_over_voice.py b/infobip_channels/sms/models/query_parameters/send_pin_over_voice.py deleted file mode 100644 index 52e97db..0000000 --- a/infobip_channels/sms/models/query_parameters/send_pin_over_voice.py +++ /dev/null @@ -1,7 +0,0 @@ -from typing import Optional - -from infobip_channels.core.models import QueryParameter - - -class SendPINOverVoiceQueryParameters(QueryParameter): - nc_needed: Optional[bool] diff --git a/infobip_channels/sms/models/query_parameters/update_scheduled_messages_status.py b/infobip_channels/sms/models/query_parameters/update_scheduled_messages_status.py deleted file mode 100644 index 4558b17..0000000 --- a/infobip_channels/sms/models/query_parameters/update_scheduled_messages_status.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.sms.models.query_parameters.core import ScheduledSMSMessages - - -class UpdateScheduledSMSMessagesQueryParameters(ScheduledSMSMessages): - pass diff --git a/infobip_channels/sms/models/query_parameters/verify_phone_number.py b/infobip_channels/sms/models/query_parameters/verify_phone_number.py deleted file mode 100644 index be62b77..0000000 --- a/infobip_channels/sms/models/query_parameters/verify_phone_number.py +++ /dev/null @@ -1,7 +0,0 @@ -from pydantic.types import constr - -from infobip_channels.core.models import QueryParameter - - -class VerifyPhoneNumberQueryParameters(QueryParameter): - pin_id: constr(min_length=1) diff --git a/infobip_channels/sms/models/response/__init__.py b/infobip_channels/sms/models/response/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/sms/models/response/core.py b/infobip_channels/sms/models/response/core.py deleted file mode 100644 index bfeb82f..0000000 --- a/infobip_channels/sms/models/response/core.py +++ /dev/null @@ -1,49 +0,0 @@ -from typing import Dict, List, Optional - -from pydantic import StrictBool - -from infobip_channels.core.models import CamelCaseModel, ResponseBase, ResponseStatus - - -class ServiceException(CamelCaseModel): - message_id: str - text: str - validation_errors: Optional[Dict[str, List[str]]] = None - - -class RequestError(CamelCaseModel): - service_exception: ServiceException - - -class SMSResponseError(ResponseBase): - request_error: RequestError - - -class Error(ResponseStatus): - permanent: Optional[StrictBool] = None - - -class Price(CamelCaseModel): - price_per_message: Optional[float] = None - currency: Optional[str] = None - - -class CoreResult(CamelCaseModel): - bulk_id: Optional[str] = None - message_id: Optional[str] = None - to: Optional[str] = None - sent_at: Optional[str] = None - done_at: Optional[str] = None - sms_count: Optional[int] = None - price: Optional[Price] = None - status: Optional[ResponseStatus] = None - error: Optional[Error] = None - - -class SMSReport(CoreResult): - mcc_mnc: Optional[str] = None - callback_data: Optional[str] = None - - -class ScheduledSMSMessages(ResponseBase): - bulk_id: str diff --git a/infobip_channels/sms/models/response/create_tfa_application.py b/infobip_channels/sms/models/response/create_tfa_application.py deleted file mode 100644 index e024355..0000000 --- a/infobip_channels/sms/models/response/create_tfa_application.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.core.tfa_application import TFAApplication - - -class CreateTFAApplicationResponse(ResponseBase, TFAApplication): - pass diff --git a/infobip_channels/sms/models/response/create_tfa_message_template.py b/infobip_channels/sms/models/response/create_tfa_message_template.py deleted file mode 100644 index a1e521a..0000000 --- a/infobip_channels/sms/models/response/create_tfa_message_template.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.core.tfa_message_template import TFAMessageTemplate - - -class CreateTFAMessageTemplateResponse(ResponseBase, TFAMessageTemplate): - pass diff --git a/infobip_channels/sms/models/response/get_scheduled_messages.py b/infobip_channels/sms/models/response/get_scheduled_messages.py deleted file mode 100644 index 65f6f88..0000000 --- a/infobip_channels/sms/models/response/get_scheduled_messages.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.sms.models.response.core import ScheduledSMSMessages - - -class GetScheduledSMSMessagesResponse(ScheduledSMSMessages): - send_at: str diff --git a/infobip_channels/sms/models/response/get_scheduled_messages_status.py b/infobip_channels/sms/models/response/get_scheduled_messages_status.py deleted file mode 100644 index f6a7027..0000000 --- a/infobip_channels/sms/models/response/get_scheduled_messages_status.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import List - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.response.core import SMSReport - - -class GetScheduledSMSMessagesStatusResponse(ResponseBase): - results: List[SMSReport] diff --git a/infobip_channels/sms/models/response/get_tfa_application.py b/infobip_channels/sms/models/response/get_tfa_application.py deleted file mode 100644 index 368d45e..0000000 --- a/infobip_channels/sms/models/response/get_tfa_application.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.core.tfa_application import TFAApplication - - -class GetTFAApplicationResponse(ResponseBase, TFAApplication): - pass diff --git a/infobip_channels/sms/models/response/get_tfa_applications.py b/infobip_channels/sms/models/response/get_tfa_applications.py deleted file mode 100644 index aba0d35..0000000 --- a/infobip_channels/sms/models/response/get_tfa_applications.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import List - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.core.tfa_application import TFAApplication - - -class GetTFAApplicationsResponse(ResponseBase): - list: List[TFAApplication] diff --git a/infobip_channels/sms/models/response/get_tfa_message_template.py b/infobip_channels/sms/models/response/get_tfa_message_template.py deleted file mode 100644 index 5cabd40..0000000 --- a/infobip_channels/sms/models/response/get_tfa_message_template.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.core.tfa_message_template import TFAMessageTemplate - - -class GetTFAMessageTemplateResponse(ResponseBase, TFAMessageTemplate): - pass diff --git a/infobip_channels/sms/models/response/get_tfa_message_templates.py b/infobip_channels/sms/models/response/get_tfa_message_templates.py deleted file mode 100644 index 6ac2ddd..0000000 --- a/infobip_channels/sms/models/response/get_tfa_message_templates.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import List - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.core.tfa_message_template import TFAMessageTemplate - - -class GetTFAMessageTemplatesResponse(ResponseBase): - list: List[TFAMessageTemplate] diff --git a/infobip_channels/sms/models/response/get_tfa_verification_status.py b/infobip_channels/sms/models/response/get_tfa_verification_status.py deleted file mode 100644 index 55dea24..0000000 --- a/infobip_channels/sms/models/response/get_tfa_verification_status.py +++ /dev/null @@ -1,14 +0,0 @@ -from typing import List - -from infobip_channels.core.models import CamelCaseModel, ResponseBase - - -class Verification(CamelCaseModel): - msisdn: str - verified: bool - verified_at: int - sent_at: int - - -class GetTFAVerificationStatusResponse(ResponseBase): - verifications: List[Verification] diff --git a/infobip_channels/sms/models/response/inbound_messages.py b/infobip_channels/sms/models/response/inbound_messages.py deleted file mode 100644 index 143e7e2..0000000 --- a/infobip_channels/sms/models/response/inbound_messages.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import List, Optional - -from pydantic import Field - -from infobip_channels.core.models import CamelCaseModel, ResponseBase -from infobip_channels.sms.models.response.core import Price - - -class Result(CamelCaseModel): - message_id: Optional[str] = None - from_name: Optional[str] = Field(alias="from", default=None) - to: Optional[str] = None - text: Optional[str] = None - clean_text: Optional[str] = None - keyword: Optional[str] = None - received_at: Optional[str] = None - sms_count: Optional[int] = None - price: Optional[Price] = None - callback_data: Optional[str] = None - - -class InboundSMSMessagesResponse(ResponseBase): - results: List[Result] - message_count: Optional[int] = None - pending_message_count: Optional[int] = None diff --git a/infobip_channels/sms/models/response/outbound_delivery_reports.py b/infobip_channels/sms/models/response/outbound_delivery_reports.py deleted file mode 100644 index 1465c0b..0000000 --- a/infobip_channels/sms/models/response/outbound_delivery_reports.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import List - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.response.core import SMSReport - - -class OutboundDeliveryReportsResponse(ResponseBase): - results: List[SMSReport] diff --git a/infobip_channels/sms/models/response/outbound_message_logs.py b/infobip_channels/sms/models/response/outbound_message_logs.py deleted file mode 100644 index 551a8e3..0000000 --- a/infobip_channels/sms/models/response/outbound_message_logs.py +++ /dev/null @@ -1,12 +0,0 @@ -from typing import List, Optional - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.response.core import CoreResult - - -class Result(CoreResult): - mcc_mnc: Optional[str] = None - - -class OutboundMessageLogsResponse(ResponseBase): - results: List[Result] diff --git a/infobip_channels/sms/models/response/preview_message.py b/infobip_channels/sms/models/response/preview_message.py deleted file mode 100644 index 615ac3e..0000000 --- a/infobip_channels/sms/models/response/preview_message.py +++ /dev/null @@ -1,29 +0,0 @@ -from typing import List, Optional - -from infobip_channels.core.models import ( - CamelCaseModel, - LanguageEnum, - ResponseBase, - TransliterationEnum, -) - - -class Language(CamelCaseModel): - language_code: LanguageEnum - - -class Configuration(CamelCaseModel): - language: Optional[Language] = None - transliteration: Optional[TransliterationEnum] = None - - -class Preview(CamelCaseModel): - text_preview: str - message_count: int - characters_remaining: int - configuration: Configuration - - -class PreviewSMSMessageResponse(ResponseBase): - original_text: str - previews: List[Preview] diff --git a/infobip_channels/sms/models/response/reschedule_sms_messages.py b/infobip_channels/sms/models/response/reschedule_sms_messages.py deleted file mode 100644 index fc45e16..0000000 --- a/infobip_channels/sms/models/response/reschedule_sms_messages.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.sms.models.response.core import ScheduledSMSMessages - - -class RescheduleSMSMessagesResponse(ScheduledSMSMessages): - send_at: str diff --git a/infobip_channels/sms/models/response/resend_pin_over_sms.py b/infobip_channels/sms/models/response/resend_pin_over_sms.py deleted file mode 100644 index e4834a2..0000000 --- a/infobip_channels/sms/models/response/resend_pin_over_sms.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.sms.models.response.send_pin_over_sms import ( - SendPINOverSMSResponse, -) - -ResendPINOverSMSResponse = SendPINOverSMSResponse diff --git a/infobip_channels/sms/models/response/resend_pin_over_voice.py b/infobip_channels/sms/models/response/resend_pin_over_voice.py deleted file mode 100644 index 7e0a6a2..0000000 --- a/infobip_channels/sms/models/response/resend_pin_over_voice.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.sms.models.response.send_pin_over_voice import ( - SendPINOverVoiceResponse, -) - -ResendPINOverVoiceResponse = SendPINOverVoiceResponse diff --git a/infobip_channels/sms/models/response/send_message.py b/infobip_channels/sms/models/response/send_message.py deleted file mode 100644 index 73037de..0000000 --- a/infobip_channels/sms/models/response/send_message.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import List, Optional - -from infobip_channels.core.models import CamelCaseModel, ResponseBase, ResponseStatus - - -class SendSMSResponseMessage(CamelCaseModel): - message_id: Optional[str] = None - status: ResponseStatus - to: Optional[str] = None - - -class SendSMSResponse(ResponseBase): - bulk_id: Optional[str] = None - messages: List[SendSMSResponseMessage] - error_message: Optional[str] = None diff --git a/infobip_channels/sms/models/response/send_pin_over_sms.py b/infobip_channels/sms/models/response/send_pin_over_sms.py deleted file mode 100644 index ace1e61..0000000 --- a/infobip_channels/sms/models/response/send_pin_over_sms.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.core.tfa_pin_status import PINStatus - - -class SendPINOverSMSResponse(ResponseBase, PINStatus): - pass diff --git a/infobip_channels/sms/models/response/send_pin_over_voice.py b/infobip_channels/sms/models/response/send_pin_over_voice.py deleted file mode 100644 index 8b7117f..0000000 --- a/infobip_channels/sms/models/response/send_pin_over_voice.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.core.tfa_pin_status import PINStatus - - -class SendPINOverVoiceResponse(ResponseBase, PINStatus): - pass diff --git a/infobip_channels/sms/models/response/update_scheduled_messages_status.py b/infobip_channels/sms/models/response/update_scheduled_messages_status.py deleted file mode 100644 index 543125f..0000000 --- a/infobip_channels/sms/models/response/update_scheduled_messages_status.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.sms.models.response.core import ScheduledSMSMessages - - -class UpdateScheduledSMSMessagesStatusResponse(ScheduledSMSMessages): - status: str diff --git a/infobip_channels/sms/models/response/update_tfa_application.py b/infobip_channels/sms/models/response/update_tfa_application.py deleted file mode 100644 index d1b2614..0000000 --- a/infobip_channels/sms/models/response/update_tfa_application.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.core.tfa_application import TFAApplication - - -class UpdateTFAApplicationResponse(ResponseBase, TFAApplication): - pass diff --git a/infobip_channels/sms/models/response/update_tfa_message_template.py b/infobip_channels/sms/models/response/update_tfa_message_template.py deleted file mode 100644 index 7489cd6..0000000 --- a/infobip_channels/sms/models/response/update_tfa_message_template.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.core.tfa_message_template import TFAMessageTemplate - - -class UpdateTFAMessageTemplateResponse(ResponseBase, TFAMessageTemplate): - pass diff --git a/infobip_channels/sms/models/response/verify_phone_number.py b/infobip_channels/sms/models/response/verify_phone_number.py deleted file mode 100644 index 52ae9ca..0000000 --- a/infobip_channels/sms/models/response/verify_phone_number.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.models.core.tfa_pin_verification import PINVerification - - -class VerifyPhoneNumberResponse(ResponseBase, PINVerification): - pass diff --git a/infobip_channels/web_rtc/__init__.py b/infobip_channels/web_rtc/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/web_rtc/channel.py b/infobip_channels/web_rtc/channel.py deleted file mode 100644 index 007c95f..0000000 --- a/infobip_channels/web_rtc/channel.py +++ /dev/null @@ -1,138 +0,0 @@ -from http import HTTPStatus -from typing import Any, Dict, Type, Union - -import requests - -from infobip_channels.core.channel import Channel -from infobip_channels.core.models import ResponseBase -from infobip_channels.web_rtc.models.body.generate_token import GenerateTokenBody -from infobip_channels.web_rtc.models.body.save_application import SaveApplicationBody -from infobip_channels.web_rtc.models.body.update_application import ( - UpdateApplicationBody, -) -from infobip_channels.web_rtc.models.path_parameters.web_rtc_application import ( - WebRtcPathParameters, -) -from infobip_channels.web_rtc.models.response.core import ( - WebRtcResponseError, - WebRtcResponseOK, -) -from infobip_channels.web_rtc.models.response.generate_token import ( - GenerateTokenResponseOK, -) -from infobip_channels.web_rtc.models.response.get_applications import ( - GetApplicationsResponseOK, -) - - -class WebRtcChannel(Channel): - """Class used for interaction with the Infobip's WebRTC API.""" - - WEB_RTC_URL_TEMPLATE = "/webrtc/1/" - - def _get_custom_response_class( - self, - response: Union[requests.Response, Any], - response_ok_model: Type[ResponseBase] = WebRtcResponseOK, - *args, - **kwargs, - ) -> Type[ResponseBase]: - if response.status_code == HTTPStatus.OK: - return response_ok_model - - elif response.status_code in ( - HTTPStatus.BAD_REQUEST, - HTTPStatus.UNAUTHORIZED, - ): - return WebRtcResponseError - - raise ValueError - - def generate_token( - self, message: Union[GenerateTokenBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - This endpoint allows you to generate token for WebRTC channel. - - :param message: Body of request to send - :return: Received response - """ - message = self.validate_message_body(message, GenerateTokenBody) - response = self._client.post( - self.WEB_RTC_URL_TEMPLATE + "token", message.dict(by_alias=True) - ) - return self._construct_response(response, GenerateTokenResponseOK) - - def save_application( - self, message: Union[SaveApplicationBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - Create and configure a new WebRTC application. - - :param message: Body of request to send - :return: Received response - """ - message = self.validate_message_body(message, SaveApplicationBody) - response = self._client.post( - self.WEB_RTC_URL_TEMPLATE + "applications", message.dict(by_alias=True) - ) - return self._construct_response(response) - - def get_applications(self) -> Union[ResponseBase, requests.Response, Any]: - """ - List all applications for WebRTC channel. - - :return: Received response - """ - response = self._client.get(self.WEB_RTC_URL_TEMPLATE + "applications") - return self._construct_response(response, GetApplicationsResponseOK) - - def get_application( - self, parameter: Union[WebRtcPathParameters, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - Get a single WebRTC application to see its configuration details. - - :param parameter: Application Id - :return: Received response - """ - path_parameter = self.validate_path_parameter(parameter, WebRtcPathParameters) - response = self._client.get( - self.WEB_RTC_URL_TEMPLATE + "applications/" + path_parameter.id - ) - return self._construct_response(response) - - def delete_application( - self, parameter: Union[WebRtcPathParameters, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - Delete WebRTC application for a given id. - - :param parameter: Application Id - :return: Received response - """ - path_parameter = self.validate_path_parameter(parameter, WebRtcPathParameters) - response = self._client.delete( - self.WEB_RTC_URL_TEMPLATE + "applications/" + path_parameter.id - ) - return self._construct_response(response) - - def update_application( - self, - parameter: Union[WebRtcPathParameters, Dict], - message: Union[UpdateApplicationBody, Dict], - ) -> Union[ResponseBase, requests.Response, Any]: - """ - Change configuration details of your existing WebRTC application. - - :param parameter: Application Id - :param message: Body of request to send - :return: Received response - """ - path_parameter = self.validate_path_parameter(parameter, WebRtcPathParameters) - message = self.validate_message_body(message, UpdateApplicationBody) - response = self._client.put( - self.WEB_RTC_URL_TEMPLATE + "applications/" + path_parameter.id, - message.dict(by_alias=True), - ) - return self._construct_response(response) diff --git a/infobip_channels/web_rtc/models/__init__.py b/infobip_channels/web_rtc/models/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/web_rtc/models/body/__init__.py b/infobip_channels/web_rtc/models/body/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/web_rtc/models/body/core.py b/infobip_channels/web_rtc/models/body/core.py deleted file mode 100644 index 593958b..0000000 --- a/infobip_channels/web_rtc/models/body/core.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Optional - -from pydantic import constr - -from infobip_channels.core.models import CamelCaseModel, MessageBodyBase - - -class AndroidServerKey(CamelCaseModel): - fcm_server_key: constr(min_length=1) - - -class IosCertificates(CamelCaseModel): - apns_certificate_file_name: constr(min_length=1) - apns_certificate_file_content: constr(min_length=1) - apns_certificate_password: Optional[str] = None - - -class ApplicationBody(MessageBodyBase): - name: constr(min_length=1) - description: Optional[constr(max_length=160)] = None - ios: Optional[IosCertificates] = None - android: Optional[AndroidServerKey] = None - app_to_app: Optional[bool] = None - app_to_conversations: Optional[bool] = None - app_to_phone: Optional[bool] = None diff --git a/infobip_channels/web_rtc/models/body/generate_token.py b/infobip_channels/web_rtc/models/body/generate_token.py deleted file mode 100644 index a017a20..0000000 --- a/infobip_channels/web_rtc/models/body/generate_token.py +++ /dev/null @@ -1,42 +0,0 @@ -from enum import Enum -from typing import Optional - -import regex -from pydantic import conint, constr, validator - -from infobip_channels.core.models import CamelCaseModel, MessageBodyBase - - -class RecordingEnum(str, Enum): - ALWAYS = "ALWAYS" - ON_DEMAND = "ON_DEMAND" - DISABLED = "DISABLED" - - -class Capabilities(CamelCaseModel): - recording: RecordingEnum - - -class GenerateTokenBody(MessageBodyBase): - identity: str - application_id: Optional[str] = None - display_name: Optional[constr(min_length=5, max_length=50)] = None - capabilities: Optional[Capabilities] = None - time_to_live: Optional[conint(gt=0, lt=86401)] = None - - @validator("identity") - def validate_identity(cls, identity: str) -> str: - """ - Using regex lib for unicode characters - This module supports Unicode 14.0.0. - Full Unicode case-folding is supported. - https://pypi.org/project/regex/ - - :param identity: Identity string to check - :return: Valid Identity string format - """ - identity_match = regex.match(r"^[\p{L}\p{N}\-_+=/.]{3,64}$", identity) - if identity_match: - return identity - else: - raise ValueError("Identity format is not valid") diff --git a/infobip_channels/web_rtc/models/body/save_application.py b/infobip_channels/web_rtc/models/body/save_application.py deleted file mode 100644 index ec6b264..0000000 --- a/infobip_channels/web_rtc/models/body/save_application.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.web_rtc.models.body.core import ApplicationBody - - -class SaveApplicationBody(ApplicationBody): - pass diff --git a/infobip_channels/web_rtc/models/body/update_application.py b/infobip_channels/web_rtc/models/body/update_application.py deleted file mode 100644 index dec613a..0000000 --- a/infobip_channels/web_rtc/models/body/update_application.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.web_rtc.models.body.core import ApplicationBody - - -class UpdateApplicationBody(ApplicationBody): - pass diff --git a/infobip_channels/web_rtc/models/path_parameters/__init__.py b/infobip_channels/web_rtc/models/path_parameters/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/web_rtc/models/path_parameters/core.py b/infobip_channels/web_rtc/models/path_parameters/core.py deleted file mode 100644 index e3f9345..0000000 --- a/infobip_channels/web_rtc/models/path_parameters/core.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.core.models import CamelCaseModel - - -class PathParameter(CamelCaseModel): - id: str diff --git a/infobip_channels/web_rtc/models/path_parameters/web_rtc_application.py b/infobip_channels/web_rtc/models/path_parameters/web_rtc_application.py deleted file mode 100644 index e959ab9..0000000 --- a/infobip_channels/web_rtc/models/path_parameters/web_rtc_application.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.web_rtc.models.path_parameters.core import PathParameter - - -class WebRtcPathParameters(PathParameter): - pass diff --git a/infobip_channels/web_rtc/models/response/__init__.py b/infobip_channels/web_rtc/models/response/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/web_rtc/models/response/core.py b/infobip_channels/web_rtc/models/response/core.py deleted file mode 100644 index b492b48..0000000 --- a/infobip_channels/web_rtc/models/response/core.py +++ /dev/null @@ -1,41 +0,0 @@ -from typing import Dict, List, Optional - -from infobip_channels.core.models import CamelCaseModel, ResponseBase - - -class ServiceException(CamelCaseModel): - message_id: str - text: str - validation_errors: Optional[Dict[str, List[str]]] = None - - -class RequestError(CamelCaseModel): - service_exception: ServiceException - - -class WebRtcResponseError(ResponseBase): - request_error: RequestError - - -class AndroidServerKey(CamelCaseModel): - fcm_server_key: str - - -class IosCertificate(CamelCaseModel): - apns_certificate_file_name: str - apns_certificate_password: str - - -class WebRtcResponseOKPayload(CamelCaseModel): - id: str - name: str - description: str - ios: Optional[IosCertificate] = None - android: Optional[AndroidServerKey] = None - app_to_app: bool - app_to_conversations: bool - app_to_phone: bool - - -class WebRtcResponseOK(WebRtcResponseOKPayload, ResponseBase): - pass diff --git a/infobip_channels/web_rtc/models/response/generate_token.py b/infobip_channels/web_rtc/models/response/generate_token.py deleted file mode 100644 index 1cab153..0000000 --- a/infobip_channels/web_rtc/models/response/generate_token.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase - - -class GenerateTokenResponseOK(ResponseBase): - token: str - expiration_time: str diff --git a/infobip_channels/web_rtc/models/response/get_applications.py b/infobip_channels/web_rtc/models/response/get_applications.py deleted file mode 100644 index 6d5433d..0000000 --- a/infobip_channels/web_rtc/models/response/get_applications.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import List - -from infobip_channels.core.models import ResponseBase -from infobip_channels.web_rtc.models.response.core import WebRtcResponseOKPayload - - -class GetApplicationsResponseOK(ResponseBase): - list: List[WebRtcResponseOKPayload] diff --git a/infobip_channels/whatsapp/__init__.py b/infobip_channels/whatsapp/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/whatsapp/channel.py b/infobip_channels/whatsapp/channel.py deleted file mode 100644 index 3d300db..0000000 --- a/infobip_channels/whatsapp/channel.py +++ /dev/null @@ -1,368 +0,0 @@ -from http import HTTPStatus -from typing import Any, Dict, Type, Union - -import requests - -from infobip_channels.core.channel import Channel -from infobip_channels.core.models import ResponseBase -from infobip_channels.whatsapp.models.body.audio_message import AudioMessageBody -from infobip_channels.whatsapp.models.body.buttons_message import ButtonsMessageBody -from infobip_channels.whatsapp.models.body.contact_message import ContactMessageBody -from infobip_channels.whatsapp.models.body.create_template import CreateTemplate -from infobip_channels.whatsapp.models.body.document_message import DocumentMessageBody -from infobip_channels.whatsapp.models.body.image_message import ImageMessageBody -from infobip_channels.whatsapp.models.body.list_message import ListMessageBody -from infobip_channels.whatsapp.models.body.location_message import LocationMessageBody -from infobip_channels.whatsapp.models.body.multi_product_message import ( - MultiProductMessageBody, -) -from infobip_channels.whatsapp.models.body.product_message import ProductMessageBody -from infobip_channels.whatsapp.models.body.sticker_message import StickerMessageBody -from infobip_channels.whatsapp.models.body.template_message import TemplateMessageBody -from infobip_channels.whatsapp.models.body.text_message import TextMessageBody -from infobip_channels.whatsapp.models.body.video_message import VideoMessageBody -from infobip_channels.whatsapp.models.path_parameters.delete_template import ( - DeleteTemplatePathParameters, -) -from infobip_channels.whatsapp.models.path_parameters.manage_templates import ( - ManageTemplatesPathParameters, -) -from infobip_channels.whatsapp.models.response.core import ( - WhatsAppResponseError, - WhatsAppResponseOK, -) -from infobip_channels.whatsapp.models.response.create_template import ( - CreateTemplateResponseOK, -) -from infobip_channels.whatsapp.models.response.get_templates import ( - GetTemplatesResponseOK, -) -from infobip_channels.whatsapp.models.response.template_message import ( - TemplateMessageResponseOK, -) - - -class WhatsAppChannel(Channel): - """Class used for interaction with the Infobip's WhatsApp API.""" - - SEND_MESSAGE_URL_TEMPLATE = "/whatsapp/1/message/" - MANAGE_URL_TEMPLATE = "/whatsapp/1/senders/" - DELETE_URL_TEMPLATE = "/whatsapp/2/senders/" - - def _get_custom_response_class( - self, - raw_response: Union[requests.Response, Any], - response_ok_model: Type[ResponseBase] = WhatsAppResponseOK, - *args, - **kwargs, - ) -> Type[ResponseBase]: - if raw_response.status_code in (HTTPStatus.OK, HTTPStatus.CREATED): - return response_ok_model - - elif raw_response.status_code in ( - HTTPStatus.BAD_REQUEST, - HTTPStatus.UNAUTHORIZED, - HTTPStatus.FORBIDDEN, - HTTPStatus.TOO_MANY_REQUESTS, - ): - return WhatsAppResponseError - - raise ValueError - - def send_template_message( - self, message: Union[TemplateMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send a single or multiple template messages to a one or more recipients. - Template messages can be sent and delivered at anytime. Each template sent - needs to be registered and pre-approved by WhatsApp. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, TemplateMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "template", - message.dict(by_alias=True), - ) - return self._construct_response(response, TemplateMessageResponseOK) - - def send_text_message( - self, message: Union[TextMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send a text message to a single recipient. Text messages can only be - successfully delivered, if the recipient has contacted the business within the - last 24 hours, otherwise template message should be used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, TextMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "text", message.dict(by_alias=True) - ) - return self._construct_response(response) - - def send_document_message( - self, message: Union[DocumentMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send a document to a single recipient. Document messages can only be - successfully delivered, if the recipient has contacted the business within the - last 24 hours, otherwise template message should be used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, DocumentMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "document", message.dict(by_alias=True) - ) - return self._construct_response(response) - - def send_image_message( - self, message: Union[ImageMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """ - Send an image to a single recipient. Image messages can only be successfully - delivered, if the recipient has contacted the business within the last 24 - hours, otherwise template message should be used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, ImageMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "image", message.dict(by_alias=True) - ) - return self._construct_response(response) - - def send_audio_message( - self, message: Union[AudioMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send an audio to a single recipient. Audio messages can only be - successfully delivered, if the recipient has contacted the business within - the last 24 hours, otherwise template message should be used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, AudioMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "audio", message.dict(by_alias=True) - ) - return self._construct_response(response) - - def send_video_message( - self, message: Union[VideoMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send a video to a single recipient. Video messages can only be - successfully delivered, if the recipient has contacted the business within - the last 24 hours, otherwise template message should be used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, VideoMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "video", message.dict(by_alias=True) - ) - return self._construct_response(response) - - def send_sticker_message( - self, message: Union[StickerMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send a sticker to a single recipient. Sticker messages can only be - successfully delivered, if the recipient has contacted the business within - the last 24 hours, otherwise template message should be used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, StickerMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "sticker", message.dict(by_alias=True) - ) - return self._construct_response(response) - - def send_location_message( - self, message: Union[LocationMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send a location to a single recipient. Location messages can only be - successfully delivered, if the recipient has contacted the business within - the last 24 hours, otherwise template message should be used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, LocationMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "location", message.dict(by_alias=True) - ) - return self._construct_response(response) - - def send_contact_message( - self, message: Union[ContactMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send a contact to a single recipient. Contact messages can only be - successfully delivered, if the recipient has contacted the business within - the last 24 hours, otherwise template message should be used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, ContactMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "contact", message.dict(by_alias=True) - ) - return self._construct_response(response) - - def send_interactive_buttons_message( - self, message: Union[ButtonsMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send an interactive buttons message to a single recipient. Interactive - buttons messages can only be successfully delivered, if the recipient has - contacted the business within the last 24 hours, otherwise template message - should be used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, ButtonsMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "interactive/buttons", - message.dict(by_alias=True), - ) - return self._construct_response(response) - - def send_interactive_list_message( - self, message: Union[ListMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send an interactive list message to a single recipient. Interactive list - messages can only be successfully delivered, if the recipient has contacted - the business within the last 24 hours, otherwise template message should be - used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, ListMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "interactive/list", - message.dict(by_alias=True), - ) - return self._construct_response(response) - - def send_interactive_product_message( - self, message: Union[ProductMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send an interactive product message to a single recipient. Interactive - product messages can only be successfully delivered, if the recipient has - contacted the business within the last 24 hours, otherwise template message - should be used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, ProductMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "interactive/product", - message.dict(by_alias=True), - ) - return self._construct_response(response) - - def send_interactive_multi_product_message( - self, message: Union[MultiProductMessageBody, Dict] - ) -> Union[ResponseBase, requests.Response, Any]: - """Send an interactive multi-product message to a single recipient. - Interactive multi-product messages can only be successfully delivered, - if the recipient has contacted the business within the last 24 hours, - otherwise template message should be used. - - :param message: Body of the message to send - :return: Received response - """ - message = self.validate_message_body(message, MultiProductMessageBody) - - response = self._client.post( - self.SEND_MESSAGE_URL_TEMPLATE + "interactive/multi-product", - message.dict(by_alias=True), - ) - return self._construct_response(response) - - def get_templates( - self, parameter: Union[ManageTemplatesPathParameters, Dict] - ) -> Union[ResponseBase, Any]: - """Get all the templates and their statuses for a given sender. - - :param parameter: Registered WhatsApp sender number. Must be in international - format - :return: Received response - """ - path_parameter = self.validate_path_parameter( - parameter, ManageTemplatesPathParameters - ) - response = self._client.get( - self.MANAGE_URL_TEMPLATE + path_parameter.sender + "/templates" - ) - return self._construct_response(response, GetTemplatesResponseOK) - - def create_template( - self, - parameter: Union[ManageTemplatesPathParameters, Dict], - message: Union[CreateTemplate, Dict], - ) -> Union[ResponseBase, Any]: - """Create WhatsApp template. Created template will be submitted for - WhatsApp's review and approval. Once approved, template can be sent to - end-users. Refer to template guidelines for additional info. - - :param parameter: Registered WhatsApp sender number. Must be in international - format - :param message: Body of the template to send - :return: Received response - """ - message = self.validate_message_body(message, CreateTemplate) - path_parameter = self.validate_path_parameter( - parameter, ManageTemplatesPathParameters - ) - response = self._client.post( - self.MANAGE_URL_TEMPLATE + path_parameter.sender + "/templates", - message.dict(by_alias=True), - ) - return self._construct_response(response, CreateTemplateResponseOK) - - def delete_template( - self, parameter: Union[DeleteTemplatePathParameters, Dict] - ) -> Union[ResponseBase, Any]: - """Delete a WhatsApp template. If registered in multiple languages, deleting - the message template will also delete all its languages. The template will be - deleted for all senders registered under the same WhatsApp Business Account ( - WABA). The system will attempt to deliver sent messages for 30 days, - regardless of the template deletion. Once deleted, the name of the approved - template cannot be reused for 30 days. - - :param parameter: Registered WhatsApp sender number, must be in international - format. Template name of WhatsApp template. - :return: Received response - """ - path_parameter = self.validate_path_parameter( - parameter, DeleteTemplatePathParameters - ) - - response = self._client.delete( - self.DELETE_URL_TEMPLATE - + "".join( - [path_parameter.sender, "/templates/", path_parameter.template_name] - ) - ) - return response diff --git a/infobip_channels/whatsapp/models/__init__.py b/infobip_channels/whatsapp/models/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/whatsapp/models/body/__init__.py b/infobip_channels/whatsapp/models/body/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/whatsapp/models/body/action_sections.py b/infobip_channels/whatsapp/models/body/action_sections.py deleted file mode 100644 index ff3be16..0000000 --- a/infobip_channels/whatsapp/models/body/action_sections.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import List, Optional - -from pydantic import constr - -from infobip_channels.core.models import CamelCaseModel - - -class SectionBase(CamelCaseModel): - title: Optional[constr(max_length=24)] = None - - -class SectionTitleValidatorMixin: - @classmethod - def validate_section_titles(cls, sections: List[SectionBase]) -> None: - if len(sections) > 1: - for section in sections: - if not section.title: - raise ValueError( - "When there is more than one section, " - "each one of them needs to have a title" - ) diff --git a/infobip_channels/whatsapp/models/body/audio_message.py b/infobip_channels/whatsapp/models/body/audio_message.py deleted file mode 100644 index d4a0077..0000000 --- a/infobip_channels/whatsapp/models/body/audio_message.py +++ /dev/null @@ -1,16 +0,0 @@ -from pydantic import AnyHttpUrl, validator - -from infobip_channels.core.models import CamelCaseModel, UrlLengthValidatorMixin -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class Content(UrlLengthValidatorMixin, CamelCaseModel): - media_url: AnyHttpUrl - - @validator("media_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class AudioMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/body/buttons_message.py b/infobip_channels/whatsapp/models/body/buttons_message.py deleted file mode 100644 index 0e7e9bc..0000000 --- a/infobip_channels/whatsapp/models/body/buttons_message.py +++ /dev/null @@ -1,78 +0,0 @@ -from enum import Enum -from typing import Optional, Union - -try: - from typing import Literal -except ImportError: - from typing_extensions import Literal - -from pydantic import AnyHttpUrl, conlist, constr, validator - -from infobip_channels.core.models import CamelCaseModel, UrlLengthValidatorMixin -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class ButtonTypeEnum(str, Enum): - REPLY = "REPLY" - - -class Footer(CamelCaseModel): - text: constr(min_length=1, max_length=60) - - -class HeaderDocument(UrlLengthValidatorMixin, CamelCaseModel): - type: Literal["DOCUMENT"] - media_url: AnyHttpUrl - filename: Optional[constr(max_length=240)] = None - - @validator("media_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class HeaderVideo(UrlLengthValidatorMixin, CamelCaseModel): - type: Literal["VIDEO"] - media_url: AnyHttpUrl - - @validator("media_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class HeaderImage(UrlLengthValidatorMixin, CamelCaseModel): - type: Literal["IMAGE"] - media_url: AnyHttpUrl - - @validator("media_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class HeaderText(CamelCaseModel): - type: Literal["TEXT"] - text: constr(min_length=1, max_length=60) - - -class Button(CamelCaseModel): - type: ButtonTypeEnum - id: constr(min_length=1, max_length=256) - title: constr(min_length=1, max_length=20) - - -class Action(CamelCaseModel): - buttons: conlist(Button, min_items=1, max_items=3) - - -class Body(CamelCaseModel): - text: constr(min_length=1, max_length=1024) - - -class Content(CamelCaseModel): - body: Body - action: Action - header: Optional[Union[HeaderText, HeaderImage, HeaderDocument, HeaderVideo]] = None - footer: Optional[Footer] = None - - -class ButtonsMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/body/contact_message.py b/infobip_channels/whatsapp/models/body/contact_message.py deleted file mode 100644 index f862b3c..0000000 --- a/infobip_channels/whatsapp/models/body/contact_message.py +++ /dev/null @@ -1,95 +0,0 @@ -from datetime import date -from enum import Enum -from typing import List, Optional - -from pydantic import validator - -from infobip_channels.core.models import CamelCaseModel -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class AddressTypeEnum(str, Enum): - HOME = "HOME" - WORK = "WORK" - - -class EmailTypeEnum(str, Enum): - HOME = "HOME" - WORK = "WORK" - - -class UrlTypeEnum(str, Enum): - HOME = "HOME" - WORK = "WORK" - - -class PhoneTypeEnum(str, Enum): - CELL = "CELL" - MAIN = "MAIN" - IPHONE = "IPHONE" - HOME = "HOME" - WORK = "WORK" - - -class Address(CamelCaseModel): - street: Optional[str] = None - city: Optional[str] = None - state: Optional[str] = None - zip: Optional[str] = None - country: Optional[str] = None - country_code: Optional[str] = None - type: Optional[AddressTypeEnum] - - -class Email(CamelCaseModel): - email: Optional[str] = None - type: Optional[EmailTypeEnum] - - -class Name(CamelCaseModel): - first_name: str - last_name: Optional[str] = None - middle_name: Optional[str] = None - name_suffix: Optional[str] = None - name_prefix: Optional[str] = None - formatted_name: str - - -class Org(CamelCaseModel): - company: Optional[str] = None - department: Optional[str] = None - title: Optional[str] = None - - -class Phone(CamelCaseModel): - phone: Optional[str] = None - type: Optional[PhoneTypeEnum] - wa_id: Optional[str] = None - - -class Url(CamelCaseModel): - url: Optional[str] = None - type: Optional[UrlTypeEnum] - - -class Contact(CamelCaseModel): - addresses: Optional[List[Address]] = None - birthday: Optional[date] = None - emails: Optional[List[Email]] = None - name: Name - org: Optional[Org] = None - phones: Optional[List[Phone]] = None - urls: Optional[List[Url]] = None - - @validator("birthday") - def datetime_to_string(cls, v): - if v: - return v.isoformat() - - -class Content(CamelCaseModel): - contacts: List[Contact] - - -class ContactMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/body/core.py b/infobip_channels/whatsapp/models/body/core.py deleted file mode 100644 index cf466e4..0000000 --- a/infobip_channels/whatsapp/models/body/core.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Optional - -from pydantic import AnyHttpUrl, Field, constr, validator - -from infobip_channels.core.models import MessageBodyBase, UrlLengthValidatorMixin - - -class MessageBody(UrlLengthValidatorMixin, MessageBodyBase): - from_number: constr(min_length=1, max_length=24) = Field(alias="from") - to: constr(min_length=1, max_length=24) - message_id: Optional[constr(max_length=50)] = None - callback_data: Optional[constr(max_length=4000)] = None - notify_url: Optional[AnyHttpUrl] = None - - @validator("notify_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) diff --git a/infobip_channels/whatsapp/models/body/create_template.py b/infobip_channels/whatsapp/models/body/create_template.py deleted file mode 100644 index b8b46c1..0000000 --- a/infobip_channels/whatsapp/models/body/create_template.py +++ /dev/null @@ -1,179 +0,0 @@ -from enum import Enum -from typing import List, Optional, Union - -try: - from typing import Literal -except ImportError: - from typing_extensions import Literal - -from pydantic import AnyHttpUrl, conlist, constr, validator - -from infobip_channels.core.models import ( - CamelCaseModel, - MessageBodyBase, - UrlLengthValidatorMixin, -) - - -class LanguageEnum(str, Enum): - AF = "af" - SQ = "sq" - AR = "ar" - AZ = "az" - BN = "bn" - BG = "bg" - CA = "ca" - ZH_CN = "zh_CN" - ZH_HK = "zh_HK" - ZH_TW = "zh_TW" - HR = "hr" - CS = "cs" - DA = "da" - NL = "nl" - EN = "en" - EN_GB = "en_GB" - EN_US = "en_US" - ET = "et" - FIL = "fil" - FI = "fi" - FR = "fr" - DE = "de" - EL = "el" - GU = "gu" - HA = "ha" - HE = "he" - HI = "hi" - HU = "hu" - ID = "id" - GA = "ga" - IT = "it" - JA = "ja" - KN = "kn" - KK = "kk" - KO = "ko" - LO = "lo" - LV = "lv" - LT = "lt" - MK = "mk" - MS = "ms" - ML = "ml" - MR = "mr" - NB = "nb" - FA = "fa" - PL = "pl" - PT_BR = "pt_BR" - PT_PT = "pt_PT" - PA = "pa" - RO = "ro" - RU = "ru" - SR = "sr" - SK = "sk" - SL = "sl" - ES = "es" - ES_AR = "es_AR" - ES_ES = "es_ES" - ES_MX = "es_MX" - SW = "sw" - SV = "sv" - TA = "ta" - TE = "te" - TH = "th" - TR = "tr" - UK = "uk" - UR = "ur" - UZ = "uz" - VI = "vi" - UNKNOWN = "unknown" - - -class HeaderText(CamelCaseModel): - format: Literal["TEXT"] - text: constr(max_length=60) - example: Optional[str] = None - - -class HeaderImage(CamelCaseModel): - format: Literal["IMAGE"] - example: Optional[AnyHttpUrl] = None - - -class HeaderVideo(CamelCaseModel): - format: Literal["VIDEO"] - example: Optional[AnyHttpUrl] = None - - -class HeaderDocument(CamelCaseModel): - format: Literal["DOCUMENT"] - example: Optional[AnyHttpUrl] = None - - -class HeaderLocation(CamelCaseModel): - format: Literal["LOCATION"] - - -class CategoryEnum(str, Enum): - MARKETING = "MARKETING" - TRANSACTIONAL = "TRANSACTIONAL" - OTP = "OTP" - - -class Button(CamelCaseModel): - text: constr(max_length=200) - - -class ButtonPhoneNumber(Button): - type: Literal["PHONE_NUMBER"] - phone_number: str - - -class ButtonUrl(UrlLengthValidatorMixin, Button): - type: Literal["URL"] - url: AnyHttpUrl - - @validator("url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class ButtonQuickReply(Button): - type: Literal["QUICK_REPLY"] - - -class Body(CamelCaseModel): - text: str - examples: Optional[List[str]] = None - - -class Footer(CamelCaseModel): - text: constr(max_length=60) - - -class Structure(CamelCaseModel): - header: Optional[ - Union[HeaderText, HeaderImage, HeaderVideo, HeaderDocument, HeaderLocation] - ] = None - body: Body - footer: Optional[Footer] = None - buttons: Optional[ - Union[ - conlist(Union[ButtonPhoneNumber, ButtonUrl], max_items=2), - conlist(ButtonQuickReply, max_items=3), - ] - ] = None - - @validator("buttons") - def validate_buttons(cls, buttons: List[Button]) -> List[Button]: - if not buttons or isinstance(buttons[0], ButtonQuickReply) or len(buttons) == 1: - return buttons - - if buttons[0].type == buttons[1].type: - raise ValueError("Call to action buttons must be unique in type") - - return buttons - - -class CreateTemplate(MessageBodyBase): - name: constr(regex=r"^[a-z0-9_]+$") # noqa: F722 - language: LanguageEnum - category: CategoryEnum - structure: Structure diff --git a/infobip_channels/whatsapp/models/body/document_message.py b/infobip_channels/whatsapp/models/body/document_message.py deleted file mode 100644 index ae85f42..0000000 --- a/infobip_channels/whatsapp/models/body/document_message.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Optional - -from pydantic import AnyHttpUrl, constr, validator - -from infobip_channels.core.models import CamelCaseModel, UrlLengthValidatorMixin -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class Content(UrlLengthValidatorMixin, CamelCaseModel): - media_url: AnyHttpUrl - caption: Optional[constr(max_length=3000)] = None - filename: Optional[constr(max_length=240)] = None - - @validator("media_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class DocumentMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/body/image_message.py b/infobip_channels/whatsapp/models/body/image_message.py deleted file mode 100644 index dc27f64..0000000 --- a/infobip_channels/whatsapp/models/body/image_message.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Optional - -from pydantic import AnyHttpUrl, constr, validator - -from infobip_channels.core.models import CamelCaseModel, UrlLengthValidatorMixin -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class Content(UrlLengthValidatorMixin, CamelCaseModel): - media_url: AnyHttpUrl - caption: Optional[constr(max_length=3000)] = None - - @validator("media_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class ImageMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/body/list_message.py b/infobip_channels/whatsapp/models/body/list_message.py deleted file mode 100644 index c5e1774..0000000 --- a/infobip_channels/whatsapp/models/body/list_message.py +++ /dev/null @@ -1,85 +0,0 @@ -from enum import Enum -from typing import List, Optional - -from pydantic import conlist, constr, validator - -from infobip_channels.core.models import CamelCaseModel -from infobip_channels.whatsapp.models.body.action_sections import ( - SectionBase, - SectionTitleValidatorMixin, -) -from infobip_channels.whatsapp.models.body.core import MessageBody - -MESSAGE_ROWS_MAXIMUM_NUMBER = 10 - - -class HeaderTypeEnum(str, Enum): - TEXT = "TEXT" - - -class Footer(CamelCaseModel): - text: constr(min_length=1, max_length=60) - - -class Header(CamelCaseModel): - type: HeaderTypeEnum - text: constr(min_length=1, max_length=60) - - -class Row(CamelCaseModel): - id: constr(min_length=1, max_length=200) - title: constr(min_length=1, max_length=24) - description: Optional[constr(max_length=72)] = None - - -class Section(SectionBase): - title: Optional[constr(max_length=24)] = None - rows: conlist(Row, min_items=1) - - -class Action(SectionTitleValidatorMixin, CamelCaseModel): - title: constr(min_length=1, max_length=20) - sections: conlist(Section, min_items=1, max_items=10) - - @validator("sections") - def validate_sections(cls, sections: List[Section]) -> List[SectionBase]: - super().validate_section_titles(sections) - cls._validate_row_id_uniqueness(sections) - cls._validate_number_of_rows(sections) - - return sections - - @classmethod - def _validate_row_id_uniqueness(cls, sections: List[Section]) -> None: - row_ids = [] - for section in sections: - for row in section.rows: - if row.id in row_ids: - raise ValueError("Row ids must be unique across all sections") - row_ids.append(row.id) - - @classmethod - def _validate_number_of_rows(cls, sections: List[Section]) -> None: - number_of_rows = 0 - for section in sections: - number_of_rows += len(section.rows) - - if number_of_rows > MESSAGE_ROWS_MAXIMUM_NUMBER: - raise ValueError( - f"Message must have a maximum of {MESSAGE_ROWS_MAXIMUM_NUMBER} rows" - ) - - -class Body(CamelCaseModel): - text: constr(min_length=1, max_length=1024) - - -class Content(CamelCaseModel): - body: Body - action: Action - header: Optional[Header] = None - footer: Optional[Footer] = None - - -class ListMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/body/location_message.py b/infobip_channels/whatsapp/models/body/location_message.py deleted file mode 100644 index 8bbab31..0000000 --- a/infobip_channels/whatsapp/models/body/location_message.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Optional - -from pydantic import confloat, constr - -from infobip_channels.core.models import CamelCaseModel -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class Content(CamelCaseModel): - latitude: confloat(ge=-90, le=90) - longitude: confloat(ge=-180, le=180) - name: Optional[constr(max_length=1000)] = None - address: Optional[constr(max_length=1000)] = None - - -class LocationMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/body/multi_product_message.py b/infobip_channels/whatsapp/models/body/multi_product_message.py deleted file mode 100644 index f1d7cde..0000000 --- a/infobip_channels/whatsapp/models/body/multi_product_message.py +++ /dev/null @@ -1,53 +0,0 @@ -from enum import Enum -from typing import List, Optional - -from pydantic import conlist, constr, validator - -from infobip_channels.core.models import CamelCaseModel -from infobip_channels.whatsapp.models.body.action_sections import ( - SectionBase, - SectionTitleValidatorMixin, -) -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class HeaderTypeEnum(str, Enum): - TEXT = "TEXT" - - -class Section(SectionBase): - product_retailer_ids: List[str] - - -class Footer(CamelCaseModel): - text: constr(min_length=1, max_length=60) - - -class Action(SectionTitleValidatorMixin, CamelCaseModel): - catalog_id: str - sections: conlist(Section, min_items=1, max_items=10) - - @validator("sections") - def validate_section_titles(cls, sections: List[Section]) -> List[SectionBase]: - super().validate_section_titles(sections) - return sections - - -class Header(CamelCaseModel): - type: HeaderTypeEnum - text: constr(min_length=1, max_length=60) - - -class Body(CamelCaseModel): - text: constr(min_length=1, max_length=1024) - - -class Content(CamelCaseModel): - header: Header - body: Body - action: Action - footer: Optional[Footer] = None - - -class MultiProductMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/body/product_message.py b/infobip_channels/whatsapp/models/body/product_message.py deleted file mode 100644 index 09dbc59..0000000 --- a/infobip_channels/whatsapp/models/body/product_message.py +++ /dev/null @@ -1,29 +0,0 @@ -from typing import Optional - -from pydantic import constr - -from infobip_channels.core.models import CamelCaseModel -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class Action(CamelCaseModel): - catalog_id: str - product_retailer_id: str - - -class Footer(CamelCaseModel): - text: constr(min_length=1, max_length=60) - - -class Body(CamelCaseModel): - text: constr(min_length=1, max_length=1024) - - -class Content(CamelCaseModel): - action: Action - body: Optional[Body] = None - footer: Optional[Footer] = None - - -class ProductMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/body/sticker_message.py b/infobip_channels/whatsapp/models/body/sticker_message.py deleted file mode 100644 index c7de391..0000000 --- a/infobip_channels/whatsapp/models/body/sticker_message.py +++ /dev/null @@ -1,16 +0,0 @@ -from pydantic import AnyHttpUrl, validator - -from infobip_channels.core.models import CamelCaseModel, UrlLengthValidatorMixin -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class Content(UrlLengthValidatorMixin, CamelCaseModel): - media_url: AnyHttpUrl - - @validator("media_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class StickerMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/body/template_message.py b/infobip_channels/whatsapp/models/body/template_message.py deleted file mode 100644 index 74f4874..0000000 --- a/infobip_channels/whatsapp/models/body/template_message.py +++ /dev/null @@ -1,109 +0,0 @@ -from typing import List, Optional, Union - -try: - from typing import Literal -except ImportError: - from typing_extensions import Literal - -from pydantic import AnyHttpUrl, Field, confloat, conlist, constr, validator - -from infobip_channels.core.models import ( - CamelCaseModel, - MessageBodyBase, - UrlLengthValidatorMixin, -) -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class ButtonQuickReply(CamelCaseModel): - type: Literal["QUICK_REPLY"] - parameter: constr(min_length=1, max_length=128) - - -class ButtonUrl(CamelCaseModel): - type: Literal["URL"] - parameter: str - - -class HeaderLocation(CamelCaseModel): - type: Literal["LOCATION"] - latitude: confloat(ge=-90, le=90) - longitude: confloat(ge=-180, le=180) - - -class HeaderDocument(UrlLengthValidatorMixin, CamelCaseModel): - type: Literal["DOCUMENT"] - media_url: AnyHttpUrl - filename: constr(min_length=1, max_length=240) - - @validator("media_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class HeaderVideo(UrlLengthValidatorMixin, CamelCaseModel): - type: Literal["VIDEO"] - media_url: AnyHttpUrl - - @validator("media_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class HeaderImage(UrlLengthValidatorMixin, CamelCaseModel): - type: Literal["IMAGE"] - media_url: AnyHttpUrl - - @validator("media_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class HeaderText(CamelCaseModel): - type: Literal["TEXT"] - placeholder: str - - -class Placeholders(CamelCaseModel): - placeholders: List[str] - - @validator("placeholders", pre=True) - def validate_placeholders(cls, placeholders: List[str]) -> List[str]: - for placeholder in placeholders: - if not placeholder: - raise ValueError("Placeholder value must not be None or empty") - - return placeholders - - -class TemplateData(CamelCaseModel): - body: Placeholders - header: Optional[ - Union[HeaderText, HeaderImage, HeaderDocument, HeaderVideo, HeaderLocation] - ] = None - buttons: Optional[ - Union[conlist(ButtonUrl, max_items=1), conlist(ButtonQuickReply, max_items=3)] - ] = None - - -class Content(CamelCaseModel): - template_name: constr( - min_length=1, max_length=512, regex=r"^[a-z0-9_]+$" # noqa: F722 - ) - template_data: TemplateData - language: constr(min_length=1) - - -class SmsFailover(CamelCaseModel): - from_number: constr(min_length=1, max_length=24) = Field(alias="from") - text: constr(min_length=1, max_length=4096) - - -class Message(MessageBody): - content: Content - sms_failover: Optional[SmsFailover] = None - - -class TemplateMessageBody(MessageBodyBase): - messages: List[Message] - bulk_id: Optional[constr(max_length=100)] = None diff --git a/infobip_channels/whatsapp/models/body/text_message.py b/infobip_channels/whatsapp/models/body/text_message.py deleted file mode 100644 index 8a60440..0000000 --- a/infobip_channels/whatsapp/models/body/text_message.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Optional - -from pydantic import StrictBool, constr - -from infobip_channels.core.models import CamelCaseModel -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class Content(CamelCaseModel): - text: constr(min_length=1, max_length=4096) - preview_url: Optional[StrictBool] = False - - -class TextMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/body/video_message.py b/infobip_channels/whatsapp/models/body/video_message.py deleted file mode 100644 index 62f4f39..0000000 --- a/infobip_channels/whatsapp/models/body/video_message.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Optional - -from pydantic import AnyHttpUrl, constr, validator - -from infobip_channels.core.models import CamelCaseModel, UrlLengthValidatorMixin -from infobip_channels.whatsapp.models.body.core import MessageBody - - -class Content(UrlLengthValidatorMixin, CamelCaseModel): - media_url: AnyHttpUrl - caption: Optional[constr(max_length=3000)] = None - - @validator("media_url", pre=True) - def validate_url_length(cls, value: str) -> str: - return super().validate_url_length(value) - - -class VideoMessageBody(MessageBody): - content: Content diff --git a/infobip_channels/whatsapp/models/path_parameters/__init__.py b/infobip_channels/whatsapp/models/path_parameters/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/whatsapp/models/path_parameters/core.py b/infobip_channels/whatsapp/models/path_parameters/core.py deleted file mode 100644 index 8e1b389..0000000 --- a/infobip_channels/whatsapp/models/path_parameters/core.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.core.models import PathParameter - - -class WhatsAppPathParameters(PathParameter): - sender: str diff --git a/infobip_channels/whatsapp/models/path_parameters/delete_template.py b/infobip_channels/whatsapp/models/path_parameters/delete_template.py deleted file mode 100644 index 7803dd2..0000000 --- a/infobip_channels/whatsapp/models/path_parameters/delete_template.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.whatsapp.models.path_parameters.core import WhatsAppPathParameters - - -class DeleteTemplatePathParameters(WhatsAppPathParameters): - template_name: str diff --git a/infobip_channels/whatsapp/models/path_parameters/manage_templates.py b/infobip_channels/whatsapp/models/path_parameters/manage_templates.py deleted file mode 100644 index 7c1032f..0000000 --- a/infobip_channels/whatsapp/models/path_parameters/manage_templates.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.whatsapp.models.path_parameters.core import WhatsAppPathParameters - - -class ManageTemplatesPathParameters(WhatsAppPathParameters): - pass diff --git a/infobip_channels/whatsapp/models/response/__init__.py b/infobip_channels/whatsapp/models/response/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_channels/whatsapp/models/response/core.py b/infobip_channels/whatsapp/models/response/core.py deleted file mode 100644 index c46f793..0000000 --- a/infobip_channels/whatsapp/models/response/core.py +++ /dev/null @@ -1,28 +0,0 @@ -from typing import Dict, List, Optional - -from infobip_channels.core.models import CamelCaseModel, ResponseBase, ResponseStatus - - -class ServiceException(CamelCaseModel): - message_id: str - text: str - validation_errors: Optional[Dict[str, List[str]]] = None - - -class RequestError(CamelCaseModel): - service_exception: ServiceException - - -class WhatsAppResponseError(ResponseBase): - request_error: RequestError - - -class WhatsAppResponseOKPayload(CamelCaseModel): - to: str - message_count: int - message_id: str - status: ResponseStatus - - -class WhatsAppResponseOK(WhatsAppResponseOKPayload, ResponseBase): - pass diff --git a/infobip_channels/whatsapp/models/response/create_template.py b/infobip_channels/whatsapp/models/response/create_template.py deleted file mode 100644 index 70a5c7f..0000000 --- a/infobip_channels/whatsapp/models/response/create_template.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_channels.whatsapp.models.response.get_templates import Template - - -class CreateTemplateResponseOK(ResponseBase, Template): - pass diff --git a/infobip_channels/whatsapp/models/response/get_templates.py b/infobip_channels/whatsapp/models/response/get_templates.py deleted file mode 100644 index 19fe235..0000000 --- a/infobip_channels/whatsapp/models/response/get_templates.py +++ /dev/null @@ -1,39 +0,0 @@ -from typing import List, Optional - -from pydantic import AnyHttpUrl - -from infobip_channels.core.models import CamelCaseModel, ResponseBase - - -class Button(CamelCaseModel): - text: str - type: str - phone_number: Optional[str] = None - url: Optional[AnyHttpUrl] = None - - -class Header(CamelCaseModel): - format: str - text: Optional[str] = None - - -class Structure(CamelCaseModel): - header: Optional[Header] = None - body: str - footer: Optional[str] = None - type: str - buttons: Optional[List[Button]] = None - - -class Template(CamelCaseModel): - id: str - business_account_id: int - name: str - language: str - status: str - category: str - structure: Structure - - -class GetTemplatesResponseOK(ResponseBase): - templates: List[Template] diff --git a/infobip_channels/whatsapp/models/response/template_message.py b/infobip_channels/whatsapp/models/response/template_message.py deleted file mode 100644 index d5be67f..0000000 --- a/infobip_channels/whatsapp/models/response/template_message.py +++ /dev/null @@ -1,9 +0,0 @@ -from typing import List, Optional - -from infobip_channels.core.models import ResponseBase -from infobip_channels.whatsapp.models.response.core import WhatsAppResponseOKPayload - - -class TemplateMessageResponseOK(ResponseBase): - messages: List[WhatsAppResponseOKPayload] - bulk_id: Optional[str] = None diff --git a/infobip_platform/__init__.py b/infobip_platform/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_platform/app_entities/__init__.py b/infobip_platform/app_entities/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_platform/app_entities/api.py b/infobip_platform/app_entities/api.py deleted file mode 100644 index 92ac950..0000000 --- a/infobip_platform/app_entities/api.py +++ /dev/null @@ -1,118 +0,0 @@ -from http import HTTPStatus -from typing import Any, Dict, Type, Union - -import requests - -from infobip_channels.core.channel import Channel -from infobip_channels.core.models import ResponseBase -from infobip_platform.app_entities.models.body.create_entity import CreateEntityBody -from infobip_platform.app_entities.models.body.modify_entity import ModifyEntityBody -from infobip_platform.app_entities.models.query_parameters.get_entities import ( - GetEntitiesQueryParameters, -) -from infobip_platform.app_entities.models.response.core import PlatformResponseError -from infobip_platform.app_entities.models.response.create_entity import ( - CreateEntityResponse, -) -from infobip_platform.app_entities.models.response.get_entities import ( - GetEntitiesResponse, -) -from infobip_platform.app_entities.models.response.get_entity import GetEntityResponse -from infobip_platform.app_entities.models.response.modify_entity import ( - ModifyEntityResponse, -) - - -class ApplicationEntityManagement(Channel): - """Class used for interaction with the Infobip Application and Entity Management API.""" - - PROVISIONING_PATH_VERSION_1 = "/provisioning/1/" - - def _get_custom_response_class( - self, - raw_response: Union[requests.Response, Any], - response_class: Type[ResponseBase], - *args, - **kwargs, - ) -> Type[ResponseBase]: - if raw_response.status_code == HTTPStatus.OK: - return response_class - elif raw_response.status_code in ( - HTTPStatus.BAD_REQUEST, - HTTPStatus.UNAUTHORIZED, - HTTPStatus.FORBIDDEN, - HTTPStatus.TOO_MANY_REQUESTS, - HTTPStatus.INTERNAL_SERVER_ERROR, - HTTPStatus.NOT_FOUND, - ): - return PlatformResponseError - - raise ValueError - - def get_entities( - self, - query_parameters: Union[GetEntitiesQueryParameters, Dict], - ) -> Union[GetEntitiesResponse, ResponseBase, Any]: - """Get a paginated list of entities. - - :return Response with a list of Entity objects. - """ - query_parameters = self.validate_query_parameter( - query_parameters or {}, GetEntitiesQueryParameters - ) - - response = self._client.get( - self.PROVISIONING_PATH_VERSION_1 + "entities", - params=query_parameters.dict(by_alias=True), - ) - return self._construct_response(response, GetEntitiesResponse) - - def create_entity( - self, - request_body: Union[CreateEntityBody, Dict], - ) -> Union[CreateEntityResponse, ResponseBase, Any]: - """Create an entity associated with the specified entityId. - - :param request_body: Body of the Entity to be created. - :return Response with status. - """ - - message = self.validate_message_body(request_body, CreateEntityBody) - - response = self._client.post( - self.PROVISIONING_PATH_VERSION_1 + "entities", - message.dict(by_alias=True), - ) - - return self._construct_response(response, CreateEntityResponse) - - def get_entity(self, entity_id: str) -> Union[GetEntityResponse, ResponseBase, Any]: - """Get an entity for the specified entityId. - - :param entity_id: Entity ID. - :return Response with the Entity object. - """ - response = self._client.get( - self.PROVISIONING_PATH_VERSION_1 + "entities/" + entity_id - ) - return self._construct_response(response, GetEntityResponse) - - def modify_entity( - self, - entity_id: str, - request_body: Union[ModifyEntityBody, Dict], - ) -> Union[ModifyEntityResponse, ResponseBase, Any]: - """Modify an entity for the specified entityId. - - :param entity_id: Entity ID. - :param request_body: Body of the Entity to be modified. - :return Response with status. - """ - message = self.validate_message_body(request_body, ModifyEntityBody) - - response = self._client.put( - self.PROVISIONING_PATH_VERSION_1 + "entities/" + entity_id, - message.dict(by_alias=True), - ) - - return self._construct_response(response, ModifyEntityResponse) diff --git a/infobip_platform/app_entities/models/__init__.py b/infobip_platform/app_entities/models/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_platform/app_entities/models/body/__init__.py b/infobip_platform/app_entities/models/body/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_platform/app_entities/models/body/create_entity.py b/infobip_platform/app_entities/models/body/create_entity.py deleted file mode 100644 index bebb6cc..0000000 --- a/infobip_platform/app_entities/models/body/create_entity.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import MessageBodyBase -from infobip_platform.app_entities.models.core.entity import Entity - - -class CreateEntityBody(MessageBodyBase, Entity): - pass diff --git a/infobip_platform/app_entities/models/body/modify_entity.py b/infobip_platform/app_entities/models/body/modify_entity.py deleted file mode 100644 index 616cf61..0000000 --- a/infobip_platform/app_entities/models/body/modify_entity.py +++ /dev/null @@ -1,9 +0,0 @@ -from typing import Optional - -from pydantic.types import constr - -from infobip_channels.core.models import MessageBodyBase - - -class ModifyEntityBody(MessageBodyBase): - entity_name: Optional[constr(max_length=255)] = None diff --git a/infobip_platform/app_entities/models/core/__init__.py b/infobip_platform/app_entities/models/core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_platform/app_entities/models/core/entity.py b/infobip_platform/app_entities/models/core/entity.py deleted file mode 100644 index 06c131e..0000000 --- a/infobip_platform/app_entities/models/core/entity.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Optional - -from pydantic.types import constr - -from infobip_channels.core.models import CamelCaseModel - - -class Entity(CamelCaseModel): - entity_name: Optional[constr(max_length=255)] = None - entity_id: constr(min_length=1, max_length=255) = None diff --git a/infobip_platform/app_entities/models/query_parameters/__init__.py b/infobip_platform/app_entities/models/query_parameters/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_platform/app_entities/models/query_parameters/get_entities.py b/infobip_platform/app_entities/models/query_parameters/get_entities.py deleted file mode 100644 index b3ab783..0000000 --- a/infobip_platform/app_entities/models/query_parameters/get_entities.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Optional - -from pydantic.types import conint - -from infobip_channels.core.models import QueryParameter - - -class GetEntitiesQueryParameters(QueryParameter): - page: Optional[conint(ge=0)] = 0 - size: Optional[conint(ge=1, le=100)] = 20 diff --git a/infobip_platform/app_entities/models/response/__init__.py b/infobip_platform/app_entities/models/response/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/infobip_platform/app_entities/models/response/core.py b/infobip_platform/app_entities/models/response/core.py deleted file mode 100644 index 52a7cdc..0000000 --- a/infobip_platform/app_entities/models/response/core.py +++ /dev/null @@ -1,13 +0,0 @@ -from infobip_channels.core.models import CamelCaseModel, ResponseBase -from infobip_channels.sms.models.response.core import RequestError - - -class PlatformResponseError(ResponseBase): - request_error: RequestError - - -class Paging(CamelCaseModel): - page: int - size: int - total_pages: int - total_results: int diff --git a/infobip_platform/app_entities/models/response/create_entity.py b/infobip_platform/app_entities/models/response/create_entity.py deleted file mode 100644 index 3868278..0000000 --- a/infobip_platform/app_entities/models/response/create_entity.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.core.models import ResponseBase - - -class CreateEntityResponse(ResponseBase): - pass diff --git a/infobip_platform/app_entities/models/response/get_entities.py b/infobip_platform/app_entities/models/response/get_entities.py deleted file mode 100644 index 0f5fd13..0000000 --- a/infobip_platform/app_entities/models/response/get_entities.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import List - -from infobip_channels.core.models import ResponseBase -from infobip_platform.app_entities.models.core.entity import Entity -from infobip_platform.app_entities.models.response.core import Paging - - -class GetEntitiesResponse(ResponseBase): - results: List[Entity] - paging: Paging diff --git a/infobip_platform/app_entities/models/response/get_entity.py b/infobip_platform/app_entities/models/response/get_entity.py deleted file mode 100644 index 4c415e9..0000000 --- a/infobip_platform/app_entities/models/response/get_entity.py +++ /dev/null @@ -1,6 +0,0 @@ -from infobip_channels.core.models import ResponseBase -from infobip_platform.app_entities.models.core.entity import Entity - - -class GetEntityResponse(ResponseBase, Entity): - pass diff --git a/infobip_platform/app_entities/models/response/modify_entity.py b/infobip_platform/app_entities/models/response/modify_entity.py deleted file mode 100644 index 04718c9..0000000 --- a/infobip_platform/app_entities/models/response/modify_entity.py +++ /dev/null @@ -1,5 +0,0 @@ -from infobip_channels.core.models import ResponseBase - - -class ModifyEntityResponse(ResponseBase): - pass diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..b841123 --- /dev/null +++ b/models/__init__.py @@ -0,0 +1,251 @@ +# coding: utf-8 + +# flake8: noqa +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import absolute_import + +# import models into model package +from models.application import Application +from models.channel import Channel +from models.entity import Entity +from models.message_error import MessageError +from models.message_price import MessagePrice +from models.message_status import MessageStatus +from models.mms_advanced_message import MmsAdvancedMessage +from models.mms_advanced_message_segment import MmsAdvancedMessageSegment +from models.mms_advanced_message_segment_binary import ( + MmsAdvancedMessageSegmentBinary, +) +from models.mms_advanced_message_segment_link import ( + MmsAdvancedMessageSegmentLink, +) +from models.mms_advanced_message_segment_smil import ( + MmsAdvancedMessageSegmentSmil, +) +from models.mms_advanced_message_segment_text import ( + MmsAdvancedMessageSegmentText, +) +from models.mms_advanced_message_segment_upload_reference import ( + MmsAdvancedMessageSegmentUploadReference, +) +from models.mms_advanced_request import MmsAdvancedRequest +from models.mms_delivery_day import MmsDeliveryDay +from models.mms_delivery_time import MmsDeliveryTime +from models.mms_delivery_time_window import MmsDeliveryTimeWindow +from models.mms_destination import MmsDestination +from models.mms_error import MmsError +from models.mms_inbound_report import MmsInboundReport +from models.mms_inbound_report_response import MmsInboundReportResponse +from models.mms_message_result import MmsMessageResult +from models.mms_price import MmsPrice +from models.mms_report import MmsReport +from models.mms_report_response import MmsReportResponse +from models.mms_send_result import MmsSendResult +from models.mms_status import MmsStatus +from models.mms_upload_binary_result import MmsUploadBinaryResult +from models.mms_webhook_inbound_message_segment import ( + MmsWebhookInboundMessageSegment, +) +from models.mms_webhook_inbound_message_segment_link import ( + MmsWebhookInboundMessageSegmentLink, +) +from models.mms_webhook_inbound_message_segment_text import ( + MmsWebhookInboundMessageSegmentText, +) +from models.mms_webhook_inbound_report import MmsWebhookInboundReport +from models.mms_webhook_inbound_report_response import ( + MmsWebhookInboundReportResponse, +) +from models.mms_webhook_outbound_report import MmsWebhookOutboundReport +from models.mms_webhook_outbound_report_response import ( + MmsWebhookOutboundReportResponse, +) +from models.modify_application import ModifyApplication +from models.modify_entity import ModifyEntity +from models.number_price import NumberPrice +from models.number_registration_address import NumberRegistrationAddress +from models.number_registration_brand import NumberRegistrationBrand +from models.number_registration_brand_preview import ( + NumberRegistrationBrandPreview, +) +from models.number_registration_brand_status import ( + NumberRegistrationBrandStatus, +) +from models.number_registration_brand_vet import ( + NumberRegistrationBrandVet, +) +from models.number_registration_business_identifier import ( + NumberRegistrationBusinessIdentifier, +) +from models.number_registration_campaign import ( + NumberRegistrationCampaign, +) +from models.number_registration_data_universal_numbering_system_number import ( + NumberRegistrationDataUniversalNumberingSystemNumber, +) +from models.number_registration_document_metadata import ( + NumberRegistrationDocumentMetadata, +) +from models.number_registration_external_ten_dlc_campaign import ( + NumberRegistrationExternalTenDlcCampaign, +) +from models.number_registration_global_intermediary_identification_number import ( + NumberRegistrationGlobalIntermediaryIdentificationNumber, +) +from models.number_registration_government_brand import ( + NumberRegistrationGovernmentBrand, +) +from models.number_registration_interactive_voice_response_opt_in import ( + NumberRegistrationInteractiveVoiceResponseOptIn, +) +from models.number_registration_keyword_opt_in import ( + NumberRegistrationKeywordOptIn, +) +from models.number_registration_legal_entity_identifier import ( + NumberRegistrationLegalEntityIdentifier, +) +from models.number_registration_network_status import ( + NumberRegistrationNetworkStatus, +) +from models.number_registration_non_profit_brand import ( + NumberRegistrationNonProfitBrand, +) +from models.number_registration_number_preview import ( + NumberRegistrationNumberPreview, +) +from models.number_registration_opt_ins import NumberRegistrationOptIns +from models.number_registration_page_info import ( + NumberRegistrationPageInfo, +) +from models.number_registration_page_response_brand import ( + NumberRegistrationPageResponseBrand, +) +from models.number_registration_page_response_brand_vet import ( + NumberRegistrationPageResponseBrandVet, +) +from models.number_registration_page_response_campaign import ( + NumberRegistrationPageResponseCampaign, +) +from models.number_registration_private_company_brand import ( + NumberRegistrationPrivateCompanyBrand, +) +from models.number_registration_public_company_brand import ( + NumberRegistrationPublicCompanyBrand, +) +from models.number_registration_ten_dlc_campaign import ( + NumberRegistrationTenDlcCampaign, +) +from models.number_registration_update_brand_request import ( + NumberRegistrationUpdateBrandRequest, +) +from models.number_registration_update_campaign_request import ( + NumberRegistrationUpdateCampaignRequest, +) +from models.number_registration_verbal_opt_in import ( + NumberRegistrationVerbalOptIn, +) +from models.number_registration_web_opt_in import ( + NumberRegistrationWebOptIn, +) +from models.number_response import NumberResponse +from models.numbers_auto_response_action import NumbersAutoResponseAction +from models.numbers_block_action import NumbersBlockAction +from models.numbers_delivery_time_window import NumbersDeliveryTimeWindow +from models.numbers_edit_permissions import NumbersEditPermissions +from models.numbers_forward_to_ivr_action_details import ( + NumbersForwardToIvrActionDetails, +) +from models.numbers_forward_to_subscription_details import ( + NumbersForwardToSubscriptionDetails, +) +from models.numbers_http_forward_action import NumbersHttpForwardAction +from models.numbers_mail_forward_action import NumbersMailForwardAction +from models.numbers_mo_action import NumbersMoAction +from models.numbers_mo_configuration import NumbersMoConfiguration +from models.numbers_mo_configurations import NumbersMoConfigurations +from models.numbers_mo_non_forward_action import ( + NumbersMoNonForwardAction, +) +from models.numbers_no_action import NumbersNoAction +from models.numbers_pull_action import NumbersPullAction +from models.numbers_purchase_number_request import ( + NumbersPurchaseNumberRequest, +) +from models.numbers_response import NumbersResponse +from models.numbers_smpp_forward_action import NumbersSmppForwardAction +from models.numbers_stored_mo_configuration import ( + NumbersStoredMoConfiguration, +) +from models.numbers_use_conversation import NumbersUseConversation +from models.numbers_voice_action_details import NumbersVoiceActionDetails +from models.numbers_voice_call_forward_to_application_details import ( + NumbersVoiceCallForwardToApplicationDetails, +) +from models.numbers_voice_number_masking_action_details import ( + NumbersVoiceNumberMaskingActionDetails, +) +from models.numbers_voice_setup import NumbersVoiceSetup +from models.page_application import PageApplication +from models.page_entity import PageEntity +from models.page_info import PageInfo +from models.page_resource_association import PageResourceAssociation +from models.resource_association_request import ( + ResourceAssociationRequest, +) +from models.resource_association_response import ( + ResourceAssociationResponse, +) +from models.resource_type import ResourceType +from models.sms_advanced_binary_request import SmsAdvancedBinaryRequest +from models.sms_advanced_textual_request import SendRequestBody +from models.sms_binary_content import SmsBinaryContent +from models.sms_binary_message import SmsBinaryMessage +from models.sms_bulk_request import SmsBulkRequest +from models.sms_bulk_response import SmsBulkResponse +from models.sms_bulk_status import SmsBulkStatus +from models.sms_bulk_status_response import SmsBulkStatusResponse +from models.sms_delivery_day import SmsDeliveryDay +from models.sms_delivery_result import SmsDeliveryResult +from models.sms_delivery_time_from import SmsDeliveryTimeFrom +from models.sms_delivery_time_to import SmsDeliveryTimeTo +from models.sms_delivery_time_window import SmsDeliveryTimeWindow +from models.sms_destination import Destination +from models.sms_error import SmsError +from models.sms_inbound_message import SmsInboundMessage +from models.sms_inbound_message_result import SmsInboundMessageResult +from models.sms_india_dlt_options import SmsIndiaDltOptions +from models.sms_language import SmsLanguage +from models.sms_language_configuration import SmsLanguageConfiguration +from models.sms_log import SmsLog +from models.sms_logs_response import SmsLogsResponse +from models.sms_preview import SmsPreview +from models.sms_preview_request import PreviewSMSRequestBody +from models.sms_preview_response import PreviewSMSResponseBody +from models.sms_price import SmsPrice +from models.sms_regional_options import SmsRegionalOptions +from models.sms_report import SmsReport +from models.sms_response import SmsResponse +from models.sms_response_details import SmsResponseDetails +from models.sms_sending_speed_limit import SmsSendingSpeedLimit +from models.sms_speed_limit_time_unit import SmsSpeedLimitTimeUnit +from models.sms_status import SmsStatus +from models.sms_textual_message import Message +from models.sms_tracking import SmsTracking +from models.sms_turkey_iys_options import SmsTurkeyIysOptions +from models.sms_update_status_request import SmsUpdateStatusRequest +from models.sms_url_options import SmsUrlOptions +from models.sms_webhook_inbound_report import SmsWebhookInboundReport +from models.sms_webhook_inbound_report_response import ( + SmsWebhookInboundReportResponse, +) +from models.sms_webhook_outbound_report import SmsWebhookOutboundReport +from models.sms_webhook_outbound_report_response import ( + SmsWebhookOutboundReportResponse, +) +from models.webhook_message_count import WebhookMessageCount diff --git a/models/application.py b/models/application.py new file mode 100644 index 0000000..e5efc2b --- /dev/null +++ b/models/application.py @@ -0,0 +1,75 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, constr + + +class Application(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + application_name: Optional[constr(strict=True, max_length=255)] = Field( + None, alias="applicationName", description="Descriptive name of the resource." + ) + application_id: constr(strict=True, max_length=255) = Field( + ..., + alias="applicationId", + description="Id of the application, this `id` will be a URL path parameter, the validation on our backend will verify its validity by doing `urlEncode(id) = id` meaning if any character in the `id` would require encoding the validation will fail.", + ) + __properties = ["applicationName", "applicationId"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Application: + """Create an instance of Application from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> Application: + """Create an instance of Application from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return Application.parse_obj(obj) + + _obj = Application.parse_obj( + { + "application_name": obj.get("applicationName"), + "application_id": obj.get("applicationId"), + } + ) + return _obj diff --git a/models/channel.py b/models/channel.py new file mode 100644 index 0000000..ea5afd9 --- /dev/null +++ b/models/channel.py @@ -0,0 +1,30 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from inspect import getfullargspec +import pprint +import re # noqa: F401 +from aenum import Enum, no_arg + + +class Channel(str, Enum): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + allowed enum values + """ + + SMS = "SMS" + MMS = "MMS" + EMAIL = "EMAIL" + VOICE_VIDEO = "VOICE_VIDEO" diff --git a/models/entity.py b/models/entity.py new file mode 100644 index 0000000..2b685a2 --- /dev/null +++ b/models/entity.py @@ -0,0 +1,72 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, constr + + +class Entity(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + entity_name: Optional[constr(strict=True, max_length=255)] = Field( + None, alias="entityName", description="Descriptive name of the resource." + ) + entity_id: constr(strict=True, max_length=255) = Field( + ..., + alias="entityId", + description="Id of the entity, this `id` will be a URL path parameter, the validation on our backend will verify its validity by doing `urlEncode(id) = id` meaning if any character in the `id` would require encoding the validation will fail.", + ) + __properties = ["entityName", "entityId"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Entity: + """Create an instance of Entity from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> Entity: + """Create an instance of Entity from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return Entity.parse_obj(obj) + + _obj = Entity.parse_obj( + {"entity_name": obj.get("entityName"), "entity_id": obj.get("entityId")} + ) + return _obj diff --git a/models/message_error.py b/models/message_error.py new file mode 100644 index 0000000..0e6b4b9 --- /dev/null +++ b/models/message_error.py @@ -0,0 +1,85 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr + + +class MessageError(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + description: Optional[StrictStr] = Field( + None, description="Human-readable description of the error." + ) + permanent: Optional[StrictBool] = Field( + None, description="Indicates whether the error is permanent." + ) + name: Optional[StrictStr] = Field(None, description="Error name.") + id: Optional[StrictInt] = Field(None, description="Error ID.") + group_name: Optional[StrictStr] = Field( + None, alias="groupName", description="Error group name." + ) + group_id: Optional[StrictInt] = Field( + None, alias="groupId", description="Error group ID." + ) + __properties = ["description", "permanent", "name", "id", "groupName", "groupId"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MessageError: + """Create an instance of MessageError from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MessageError: + """Create an instance of MessageError from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MessageError.parse_obj(obj) + + _obj = MessageError.parse_obj( + { + "description": obj.get("description"), + "permanent": obj.get("permanent"), + "name": obj.get("name"), + "id": obj.get("id"), + "group_name": obj.get("groupName"), + "group_id": obj.get("groupId"), + } + ) + return _obj diff --git a/models/message_price.py b/models/message_price.py new file mode 100644 index 0000000..e980260 --- /dev/null +++ b/models/message_price.py @@ -0,0 +1,73 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictFloat, StrictStr + + +class MessagePrice(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + currency: Optional[StrictStr] = Field( + None, description="The currency in which the price is displayed." + ) + price_per_message: Optional[StrictFloat] = Field( + None, alias="pricePerMessage", description="The price per individual message." + ) + __properties = ["currency", "pricePerMessage"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MessagePrice: + """Create an instance of MessagePrice from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MessagePrice: + """Create an instance of MessagePrice from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MessagePrice.parse_obj(obj) + + _obj = MessagePrice.parse_obj( + { + "currency": obj.get("currency"), + "price_per_message": obj.get("pricePerMessage"), + } + ) + return _obj diff --git a/models/message_status.py b/models/message_status.py new file mode 100644 index 0000000..916b80b --- /dev/null +++ b/models/message_status.py @@ -0,0 +1,85 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr + + +class MessageStatus(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + group_name: Optional[StrictStr] = Field( + None, alias="groupName", description="Group name for the status." + ) + id: Optional[StrictInt] = Field(None, description="Status ID.") + group_id: Optional[StrictInt] = Field( + None, alias="groupId", description="Status group ID." + ) + name: Optional[StrictStr] = Field(None, description="Status name.") + action: Optional[StrictStr] = Field( + None, description="Action that should be taken to fix the error." + ) + description: Optional[StrictStr] = Field( + None, description="Human-readable description of the status." + ) + __properties = ["groupName", "id", "groupId", "name", "action", "description"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MessageStatus: + """Create an instance of MessageStatus from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MessageStatus: + """Create an instance of MessageStatus from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MessageStatus.parse_obj(obj) + + _obj = MessageStatus.parse_obj( + { + "group_name": obj.get("groupName"), + "id": obj.get("id"), + "group_id": obj.get("groupId"), + "name": obj.get("name"), + "action": obj.get("action"), + "description": obj.get("description"), + } + ) + return _obj diff --git a/models/mms_advanced_message.py b/models/mms_advanced_message.py new file mode 100644 index 0000000..a4b5ebd --- /dev/null +++ b/models/mms_advanced_message.py @@ -0,0 +1,167 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, constr +from models.mms_advanced_message_segment import MmsAdvancedMessageSegment +from models.mms_delivery_time_window import MmsDeliveryTimeWindow +from models.mms_destination import MmsDestination + + +class MmsAdvancedMessage(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + callback_data: Optional[constr(strict=True, max_length=4000, min_length=0)] = Field( + None, + alias="callbackData", + description="Additional client data to be sent over the notifyUrl. The maximum value is 4000 characters.", + ) + delivery_time_window: Optional[MmsDeliveryTimeWindow] = Field( + None, alias="deliveryTimeWindow" + ) + destinations: List[MmsDestination] = Field( + ..., + description="An array of destination objects for where messages are being sent. A valid destination is required.", + ) + var_from: Optional[StrictStr] = Field( + None, + alias="from", + description="The sender ID which can be alphanumeric or numeric (e.g., `CompanyName`).", + ) + intermediate_report: Optional[StrictBool] = Field( + None, + alias="intermediateReport", + description="The [real-time intermediate delivery report](https://www.infobip.com/docs/api/channels/mms/get-outbound-mms-message-delivery-reports) containing GSM error codes, messages status, pricing, network and country codes, etc., which will be sent on your callback server. Defaults to `false`.", + ) + notify_url: Optional[StrictStr] = Field( + None, + alias="notifyUrl", + description="The URL on your call back server on to which a delivery report will be sent.", + ) + message_segments: List[MmsAdvancedMessageSegment] = Field( + ..., alias="messageSegments", description="Content of the message being sent." + ) + validity_period: Optional[StrictInt] = Field( + None, + alias="validityPeriod", + description="The message validity period in minutes. When the period expires, it will not be allowed for the message to be sent. Validity period longer than 48h is not supported. Any bigger value will automatically default back to `2880`.", + ) + title: Optional[constr(strict=True, max_length=66, min_length=0)] = None + entity_id: Optional[constr(strict=True, max_length=50, min_length=0)] = Field( + None, + alias="entityId", + description="Required for entity use in a send request for outbound traffic. Returned in notification events.", + ) + application_id: Optional[constr(strict=True, max_length=50, min_length=0)] = Field( + None, + alias="applicationId", + description="Required for application use in a send request for outbound traffic. Returned in notification events.", + ) + __properties = [ + "callbackData", + "deliveryTimeWindow", + "destinations", + "from", + "intermediateReport", + "notifyUrl", + "messageSegments", + "validityPeriod", + "title", + "entityId", + "applicationId", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsAdvancedMessage: + """Create an instance of MmsAdvancedMessage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of delivery_time_window + if self.delivery_time_window: + _dict["deliveryTimeWindow"] = self.delivery_time_window.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in destinations (list) + _items = [] + if self.destinations: + for _item in self.destinations: + if _item: + _items.append(_item.to_dict()) + _dict["destinations"] = _items + # override the default output from pydantic by calling `to_dict()` of each item in message_segments (list) + _items = [] + if self.message_segments: + for _item in self.message_segments: + if _item: + _items.append(_item.to_dict()) + _dict["messageSegments"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsAdvancedMessage: + """Create an instance of MmsAdvancedMessage from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsAdvancedMessage.parse_obj(obj) + + _obj = MmsAdvancedMessage.parse_obj( + { + "callback_data": obj.get("callbackData"), + "delivery_time_window": MmsDeliveryTimeWindow.from_dict( + obj.get("deliveryTimeWindow") + ) + if obj.get("deliveryTimeWindow") is not None + else None, + "destinations": [ + MmsDestination.from_dict(_item) for _item in obj.get("destinations") + ] + if obj.get("destinations") is not None + else None, + "var_from": obj.get("from"), + "intermediate_report": obj.get("intermediateReport"), + "notify_url": obj.get("notifyUrl"), + "message_segments": [ + MmsAdvancedMessageSegment.from_dict(_item) + for _item in obj.get("messageSegments") + ] + if obj.get("messageSegments") is not None + else None, + "validity_period": obj.get("validityPeriod"), + "title": obj.get("title"), + "entity_id": obj.get("entityId"), + "application_id": obj.get("applicationId"), + } + ) + return _obj diff --git a/models/mms_advanced_message_segment.py b/models/mms_advanced_message_segment.py new file mode 100644 index 0000000..9b75378 --- /dev/null +++ b/models/mms_advanced_message_segment.py @@ -0,0 +1,188 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, ValidationError, validator +from models.mms_advanced_message_segment_binary import ( + MmsAdvancedMessageSegmentBinary, +) +from models.mms_advanced_message_segment_link import ( + MmsAdvancedMessageSegmentLink, +) +from models.mms_advanced_message_segment_smil import ( + MmsAdvancedMessageSegmentSmil, +) +from models.mms_advanced_message_segment_text import ( + MmsAdvancedMessageSegmentText, +) +from models.mms_advanced_message_segment_upload_reference import ( + MmsAdvancedMessageSegmentUploadReference, +) +from typing import Any, List +from pydantic import StrictStr, Field + +MMSADVANCEDMESSAGESEGMENT_ANY_OF_SCHEMAS = [ + "MmsAdvancedMessageSegmentBinary", + "MmsAdvancedMessageSegmentLink", + "MmsAdvancedMessageSegmentSmil", + "MmsAdvancedMessageSegmentText", + "MmsAdvancedMessageSegmentUploadReference", +] + + +class MmsAdvancedMessageSegment(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + # data type: MmsAdvancedMessageSegmentText + anyof_schema_1_validator: Optional[MmsAdvancedMessageSegmentText] = None + # data type: MmsAdvancedMessageSegmentLink + anyof_schema_2_validator: Optional[MmsAdvancedMessageSegmentLink] = None + # data type: MmsAdvancedMessageSegmentBinary + anyof_schema_3_validator: Optional[MmsAdvancedMessageSegmentBinary] = None + # data type: MmsAdvancedMessageSegmentSmil + anyof_schema_4_validator: Optional[MmsAdvancedMessageSegmentSmil] = None + # data type: MmsAdvancedMessageSegmentUploadReference + anyof_schema_5_validator: Optional[MmsAdvancedMessageSegmentUploadReference] = None + actual_instance: Any + any_of_schemas: List[str] = Field( + MMSADVANCEDMESSAGESEGMENT_ANY_OF_SCHEMAS, const=True + ) + + class Config: + validate_assignment = True + + @validator("actual_instance") + def actual_instance_must_validate_anyof(cls, v): + instance = cls() + error_messages = [] + # validate data type: MmsAdvancedMessageSegmentText + if type(v) is not MmsAdvancedMessageSegmentText: + error_messages.append( + f"Error! Input type `{type(v)}` is not `MmsAdvancedMessageSegmentText`" + ) + else: + return v + + # validate data type: MmsAdvancedMessageSegmentLink + if type(v) is not MmsAdvancedMessageSegmentLink: + error_messages.append( + f"Error! Input type `{type(v)}` is not `MmsAdvancedMessageSegmentLink`" + ) + else: + return v + + # validate data type: MmsAdvancedMessageSegmentBinary + if type(v) is not MmsAdvancedMessageSegmentBinary: + error_messages.append( + f"Error! Input type `{type(v)}` is not `MmsAdvancedMessageSegmentBinary`" + ) + else: + return v + + # validate data type: MmsAdvancedMessageSegmentSmil + if type(v) is not MmsAdvancedMessageSegmentSmil: + error_messages.append( + f"Error! Input type `{type(v)}` is not `MmsAdvancedMessageSegmentSmil`" + ) + else: + return v + + # validate data type: MmsAdvancedMessageSegmentUploadReference + if type(v) is not MmsAdvancedMessageSegmentUploadReference: + error_messages.append( + f"Error! Input type `{type(v)}` is not `MmsAdvancedMessageSegmentUploadReference`" + ) + else: + return v + + if error_messages: + # no match + raise ValueError( + "No match found when deserializing the JSON string into MmsAdvancedMessageSegment with anyOf schemas: MmsAdvancedMessageSegmentBinary, MmsAdvancedMessageSegmentLink, MmsAdvancedMessageSegmentSmil, MmsAdvancedMessageSegmentText, MmsAdvancedMessageSegmentUploadReference. Details: " + + ", ".join(error_messages) + ) + else: + return v + + @classmethod + def from_json(cls, json_str: str) -> MmsAdvancedMessageSegment: + """Returns the object represented by the json string""" + instance = cls() + error_messages = [] + # anyof_schema_1_validator: Optional[MmsAdvancedMessageSegmentText] = None + try: + instance.actual_instance = MmsAdvancedMessageSegmentText.from_json(json_str) + return instance + except ValidationError as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[MmsAdvancedMessageSegmentLink] = None + try: + instance.actual_instance = MmsAdvancedMessageSegmentLink.from_json(json_str) + return instance + except ValidationError as e: + error_messages.append(str(e)) + # anyof_schema_3_validator: Optional[MmsAdvancedMessageSegmentBinary] = None + try: + instance.actual_instance = MmsAdvancedMessageSegmentBinary.from_json( + json_str + ) + return instance + except ValidationError as e: + error_messages.append(str(e)) + # anyof_schema_4_validator: Optional[MmsAdvancedMessageSegmentSmil] = None + try: + instance.actual_instance = MmsAdvancedMessageSegmentSmil.from_json(json_str) + return instance + except ValidationError as e: + error_messages.append(str(e)) + # anyof_schema_5_validator: Optional[MmsAdvancedMessageSegmentUploadReference] = None + try: + instance.actual_instance = ( + MmsAdvancedMessageSegmentUploadReference.from_json(json_str) + ) + return instance + except ValidationError as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError( + "No match found when deserializing the JSON string into MmsAdvancedMessageSegment with anyOf schemas: MmsAdvancedMessageSegmentBinary, MmsAdvancedMessageSegmentLink, MmsAdvancedMessageSegmentSmil, MmsAdvancedMessageSegmentText, MmsAdvancedMessageSegmentUploadReference. Details: " + + ", ".join(error_messages) + ) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is not None: + return self.actual_instance.to_json() + else: + return "null" + + def to_dict(self) -> dict: + """Returns the dict representation of the actual instance""" + if self.actual_instance is not None: + return self.actual_instance.to_dict() + else: + return dict() + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.dict()) diff --git a/models/mms_advanced_message_segment_binary.py b/models/mms_advanced_message_segment_binary.py new file mode 100644 index 0000000..2a11bb6 --- /dev/null +++ b/models/mms_advanced_message_segment_binary.py @@ -0,0 +1,81 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class MmsAdvancedMessageSegmentBinary(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + content_id: Optional[StrictStr] = Field( + None, + alias="contentId", + description="Unique identifier within single message. `[a-zA-Z]` up to 20 characters. Using other characters (e.g. spaces) may cause your message to be rejected by some mobile carriers.", + ) + content_type: Optional[StrictStr] = Field( + None, + alias="contentType", + description="Content type for media, for example `image/png`.", + ) + content_base64: Optional[StrictStr] = Field( + None, alias="contentBase64", description="Content in Base64 format." + ) + __properties = ["contentId", "contentType", "contentBase64"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsAdvancedMessageSegmentBinary: + """Create an instance of MmsAdvancedMessageSegmentBinary from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsAdvancedMessageSegmentBinary: + """Create an instance of MmsAdvancedMessageSegmentBinary from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsAdvancedMessageSegmentBinary.parse_obj(obj) + + _obj = MmsAdvancedMessageSegmentBinary.parse_obj( + { + "content_id": obj.get("contentId"), + "content_type": obj.get("contentType"), + "content_base64": obj.get("contentBase64"), + } + ) + return _obj diff --git a/models/mms_advanced_message_segment_link.py b/models/mms_advanced_message_segment_link.py new file mode 100644 index 0000000..befa8bc --- /dev/null +++ b/models/mms_advanced_message_segment_link.py @@ -0,0 +1,81 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class MmsAdvancedMessageSegmentLink(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + content_id: Optional[StrictStr] = Field( + None, + alias="contentId", + description="Unique identifier within single message. `[a-zA-Z]` up to 20 characters. Using other characters (e.g. spaces) may cause your message to be rejected by some mobile carriers.", + ) + content_type: Optional[StrictStr] = Field( + None, + alias="contentType", + description="Content type for media, for example `image/png`.", + ) + content_url: StrictStr = Field( + ..., alias="contentUrl", description="URL of externally hosted content." + ) + __properties = ["contentId", "contentType", "contentUrl"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsAdvancedMessageSegmentLink: + """Create an instance of MmsAdvancedMessageSegmentLink from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsAdvancedMessageSegmentLink: + """Create an instance of MmsAdvancedMessageSegmentLink from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsAdvancedMessageSegmentLink.parse_obj(obj) + + _obj = MmsAdvancedMessageSegmentLink.parse_obj( + { + "content_id": obj.get("contentId"), + "content_type": obj.get("contentType"), + "content_url": obj.get("contentUrl"), + } + ) + return _obj diff --git a/models/mms_advanced_message_segment_smil.py b/models/mms_advanced_message_segment_smil.py new file mode 100644 index 0000000..a729204 --- /dev/null +++ b/models/mms_advanced_message_segment_smil.py @@ -0,0 +1,82 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class MmsAdvancedMessageSegmentSmil(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + content_id: Optional[StrictStr] = Field( + None, + alias="contentId", + description="Unique identifier within single message. `[a-zA-Z]` up to 20 characters. Using other characters (e.g. spaces) may cause your message to be rejected by some mobile carriers.", + ) + content_type: Optional[StrictStr] = Field( + None, + alias="contentType", + description="Content type for media, for example `application/smil`.", + ) + smil: Optional[StrictStr] = Field( + None, + description="Message segment as SMIL format. Be aware that some devices and/or operating systems ignore SMIL, so there is no guarantee that segments will be displayed as specified in SMIL format.", + ) + __properties = ["contentId", "contentType", "smil"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsAdvancedMessageSegmentSmil: + """Create an instance of MmsAdvancedMessageSegmentSmil from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsAdvancedMessageSegmentSmil: + """Create an instance of MmsAdvancedMessageSegmentSmil from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsAdvancedMessageSegmentSmil.parse_obj(obj) + + _obj = MmsAdvancedMessageSegmentSmil.parse_obj( + { + "content_id": obj.get("contentId"), + "content_type": obj.get("contentType"), + "smil": obj.get("smil"), + } + ) + return _obj diff --git a/models/mms_advanced_message_segment_text.py b/models/mms_advanced_message_segment_text.py new file mode 100644 index 0000000..8c921a1 --- /dev/null +++ b/models/mms_advanced_message_segment_text.py @@ -0,0 +1,70 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class MmsAdvancedMessageSegmentText(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + content_id: Optional[StrictStr] = Field( + None, + alias="contentId", + description="Unique identifier within single message. `[a-zA-Z]` up to 20 characters. Using other characters (e.g. spaces) may cause your message to be rejected by some mobile carriers.", + ) + text: Optional[StrictStr] = Field(None, description="Message text.") + __properties = ["contentId", "text"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsAdvancedMessageSegmentText: + """Create an instance of MmsAdvancedMessageSegmentText from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsAdvancedMessageSegmentText: + """Create an instance of MmsAdvancedMessageSegmentText from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsAdvancedMessageSegmentText.parse_obj(obj) + + _obj = MmsAdvancedMessageSegmentText.parse_obj( + {"content_id": obj.get("contentId"), "text": obj.get("text")} + ) + return _obj diff --git a/models/mms_advanced_message_segment_upload_reference.py b/models/mms_advanced_message_segment_upload_reference.py new file mode 100644 index 0000000..813eddf --- /dev/null +++ b/models/mms_advanced_message_segment_upload_reference.py @@ -0,0 +1,77 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class MmsAdvancedMessageSegmentUploadReference(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + content_id: Optional[StrictStr] = Field( + None, + alias="contentId", + description="Unique identifier within single message. `[a-zA-Z]` up to 20 characters. Using other characters (e.g. spaces) may cause your message to be rejected by some mobile carriers.", + ) + uploaded_content_id: Optional[StrictStr] = Field( + None, + alias="uploadedContentId", + description="ID of previously uploaded binary content.", + ) + __properties = ["contentId", "uploadedContentId"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsAdvancedMessageSegmentUploadReference: + """Create an instance of MmsAdvancedMessageSegmentUploadReference from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsAdvancedMessageSegmentUploadReference: + """Create an instance of MmsAdvancedMessageSegmentUploadReference from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsAdvancedMessageSegmentUploadReference.parse_obj(obj) + + _obj = MmsAdvancedMessageSegmentUploadReference.parse_obj( + { + "content_id": obj.get("contentId"), + "uploaded_content_id": obj.get("uploadedContentId"), + } + ) + return _obj diff --git a/models/mms_advanced_request.py b/models/mms_advanced_request.py new file mode 100644 index 0000000..427bb41 --- /dev/null +++ b/models/mms_advanced_request.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictStr +from models.mms_advanced_message import MmsAdvancedMessage + + +class MmsAdvancedRequest(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field( + None, + alias="bulkId", + description="Unique ID assigned to the request if messaging multiple recipients via a single API request. If not provided, it will be autogenerated and returned in the API response. Typically, used to fetch [delivery reports](https://www.infobip.com/docs/api/channels/mms/receive-outbound-mms-message-report).", + ) + messages: List[MmsAdvancedMessage] = Field( + ..., + description="An array of message objects of a single message or multiple messages sent under one bulk ID.", + ) + __properties = ["bulkId", "messages"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsAdvancedRequest: + """Create an instance of MmsAdvancedRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in messages (list) + _items = [] + if self.messages: + for _item in self.messages: + if _item: + _items.append(_item.to_dict()) + _dict["messages"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsAdvancedRequest: + """Create an instance of MmsAdvancedRequest from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsAdvancedRequest.parse_obj(obj) + + _obj = MmsAdvancedRequest.parse_obj( + { + "bulk_id": obj.get("bulkId"), + "messages": [ + MmsAdvancedMessage.from_dict(_item) for _item in obj.get("messages") + ] + if obj.get("messages") is not None + else None, + } + ) + return _obj diff --git a/models/mms_delivery_day.py b/models/mms_delivery_day.py new file mode 100644 index 0000000..4db5cbb --- /dev/null +++ b/models/mms_delivery_day.py @@ -0,0 +1,33 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from inspect import getfullargspec +import pprint +import re # noqa: F401 +from aenum import Enum, no_arg + + +class MmsDeliveryDay(str, Enum): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + allowed enum values + """ + + MONDAY = "MONDAY" + TUESDAY = "TUESDAY" + WEDNESDAY = "WEDNESDAY" + THURSDAY = "THURSDAY" + FRIDAY = "FRIDAY" + SATURDAY = "SATURDAY" + SUNDAY = "SUNDAY" diff --git a/models/mms_delivery_time.py b/models/mms_delivery_time.py new file mode 100644 index 0000000..1344f9e --- /dev/null +++ b/models/mms_delivery_time.py @@ -0,0 +1,72 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, conint + + +class MmsDeliveryTime(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + hour: Optional[conint(strict=True, le=23, ge=0)] = Field( + None, + description="Hour when the time window opens when used in the `from` property or closes when used in the `to` property.", + ) + minute: Optional[conint(strict=True, le=59, ge=0)] = Field( + None, + description="Minute when the time window opens when used in the `from` property or closes when used in the `to` property.", + ) + __properties = ["hour", "minute"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsDeliveryTime: + """Create an instance of MmsDeliveryTime from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsDeliveryTime: + """Create an instance of MmsDeliveryTime from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsDeliveryTime.parse_obj(obj) + + _obj = MmsDeliveryTime.parse_obj( + {"hour": obj.get("hour"), "minute": obj.get("minute")} + ) + return _obj diff --git a/models/mms_delivery_time_window.py b/models/mms_delivery_time_window.py new file mode 100644 index 0000000..cc1ab38 --- /dev/null +++ b/models/mms_delivery_time_window.py @@ -0,0 +1,86 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field +from models.mms_delivery_day import MmsDeliveryDay +from models.mms_delivery_time import MmsDeliveryTime + + +class MmsDeliveryTimeWindow(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + days: List[MmsDeliveryDay] = Field( + ..., + description="Days of the week which are included in the delivery time window. At least one day must be provided.", + ) + var_from: Optional[MmsDeliveryTime] = Field(None, alias="from") + to: Optional[MmsDeliveryTime] = None + __properties = ["days", "from", "to"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsDeliveryTimeWindow: + """Create an instance of MmsDeliveryTimeWindow from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of var_from + if self.var_from: + _dict["from"] = self.var_from.to_dict() + # override the default output from pydantic by calling `to_dict()` of to + if self.to: + _dict["to"] = self.to.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsDeliveryTimeWindow: + """Create an instance of MmsDeliveryTimeWindow from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsDeliveryTimeWindow.parse_obj(obj) + + _obj = MmsDeliveryTimeWindow.parse_obj( + { + "days": obj.get("days"), + "var_from": MmsDeliveryTime.from_dict(obj.get("from")) + if obj.get("from") is not None + else None, + "to": MmsDeliveryTime.from_dict(obj.get("to")) + if obj.get("to") is not None + else None, + } + ) + return _obj diff --git a/models/mms_destination.py b/models/mms_destination.py new file mode 100644 index 0000000..745332e --- /dev/null +++ b/models/mms_destination.py @@ -0,0 +1,73 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, constr + + +class MmsDestination(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + message_id: Optional[StrictStr] = Field( + None, + alias="messageId", + description="The ID that uniquely identifies the message sent.", + ) + to: constr(strict=True, max_length=50, min_length=0) = Field( + ..., + description="Message destination address. Addresses must be in international format (Example: `41793026727`).", + ) + __properties = ["messageId", "to"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsDestination: + """Create an instance of MmsDestination from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsDestination: + """Create an instance of MmsDestination from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsDestination.parse_obj(obj) + + _obj = MmsDestination.parse_obj( + {"message_id": obj.get("messageId"), "to": obj.get("to")} + ) + return _obj diff --git a/models/mms_error.py b/models/mms_error.py new file mode 100644 index 0000000..e72ba85 --- /dev/null +++ b/models/mms_error.py @@ -0,0 +1,81 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr + + +class MmsError(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + group_id: Optional[StrictInt] = Field( + None, alias="groupId", description="Error group ID." + ) + group_name: Optional[StrictStr] = Field( + None, alias="groupName", description="Error group name." + ) + id: Optional[StrictInt] = Field(None, description="Error ID.") + name: Optional[StrictStr] = Field(None, description="Error name.") + description: Optional[StrictStr] = Field( + None, description="Human-readable description of the error." + ) + __properties = ["groupId", "groupName", "id", "name", "description"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsError: + """Create an instance of MmsError from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsError: + """Create an instance of MmsError from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsError.parse_obj(obj) + + _obj = MmsError.parse_obj( + { + "group_id": obj.get("groupId"), + "group_name": obj.get("groupName"), + "id": obj.get("id"), + "name": obj.get("name"), + "description": obj.get("description"), + } + ) + return _obj diff --git a/models/mms_inbound_report.py b/models/mms_inbound_report.py new file mode 100644 index 0000000..4d32fee --- /dev/null +++ b/models/mms_inbound_report.py @@ -0,0 +1,116 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr +from models.mms_price import MmsPrice + + +class MmsInboundReport(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + message_id: Optional[StrictStr] = Field( + None, + alias="messageId", + description="The ID that uniquely identifies the received message.", + ) + to: Optional[StrictStr] = Field( + None, description="The message destination address." + ) + var_from: Optional[StrictStr] = Field( + None, alias="from", description="Sender ID that can be alphanumeric or numeric." + ) + message: Optional[StrictStr] = Field( + None, description="Full text of the received message." + ) + received_at: Optional[datetime] = Field( + None, + alias="receivedAt", + description="Tells when Infobip platform received the message. It has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`.", + ) + mms_count: Optional[StrictInt] = Field( + None, alias="mmsCount", description="The number of sent message segments." + ) + callback_data: Optional[StrictStr] = Field( + None, + alias="callbackData", + description="Custom callback data can be inserted during the setup phase.", + ) + price: Optional[MmsPrice] = None + __properties = [ + "messageId", + "to", + "from", + "message", + "receivedAt", + "mmsCount", + "callbackData", + "price", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsInboundReport: + """Create an instance of MmsInboundReport from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of price + if self.price: + _dict["price"] = self.price.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsInboundReport: + """Create an instance of MmsInboundReport from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsInboundReport.parse_obj(obj) + + _obj = MmsInboundReport.parse_obj( + { + "message_id": obj.get("messageId"), + "to": obj.get("to"), + "var_from": obj.get("from"), + "message": obj.get("message"), + "received_at": obj.get("receivedAt"), + "mms_count": obj.get("mmsCount"), + "callback_data": obj.get("callbackData"), + "price": MmsPrice.from_dict(obj.get("price")) + if obj.get("price") is not None + else None, + } + ) + return _obj diff --git a/models/mms_inbound_report_response.py b/models/mms_inbound_report_response.py new file mode 100644 index 0000000..9146096 --- /dev/null +++ b/models/mms_inbound_report_response.py @@ -0,0 +1,79 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field +from models.mms_inbound_report import MmsInboundReport + + +class MmsInboundReportResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[MmsInboundReport]] = Field(None, description="Results.") + __properties = ["results"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsInboundReportResponse: + """Create an instance of MmsInboundReportResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsInboundReportResponse: + """Create an instance of MmsInboundReportResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsInboundReportResponse.parse_obj(obj) + + _obj = MmsInboundReportResponse.parse_obj( + { + "results": [ + MmsInboundReport.from_dict(_item) for _item in obj.get("results") + ] + if obj.get("results") is not None + else None + } + ) + return _obj diff --git a/models/mms_message_result.py b/models/mms_message_result.py new file mode 100644 index 0000000..3ac9ce0 --- /dev/null +++ b/models/mms_message_result.py @@ -0,0 +1,83 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr +from models.mms_status import MmsStatus + + +class MmsMessageResult(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + to: Optional[StrictStr] = Field( + None, description="The message destination address." + ) + status: MmsStatus = ... + message_id: Optional[StrictStr] = Field( + None, + alias="messageId", + description="The ID that uniquely identifies the message sent.", + ) + __properties = ["to", "status", "messageId"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsMessageResult: + """Create an instance of MmsMessageResult from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of status + if self.status: + _dict["status"] = self.status.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsMessageResult: + """Create an instance of MmsMessageResult from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsMessageResult.parse_obj(obj) + + _obj = MmsMessageResult.parse_obj( + { + "to": obj.get("to"), + "status": MmsStatus.from_dict(obj.get("status")) + if obj.get("status") is not None + else None, + "message_id": obj.get("messageId"), + } + ) + return _obj diff --git a/models/mms_price.py b/models/mms_price.py new file mode 100644 index 0000000..c7220d0 --- /dev/null +++ b/models/mms_price.py @@ -0,0 +1,73 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictFloat, StrictStr + + +class MmsPrice(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + price_per_message: Optional[StrictFloat] = Field( + None, alias="pricePerMessage", description="Price per one MMS." + ) + currency: Optional[StrictStr] = Field( + None, description="The currency in which the price is expressed." + ) + __properties = ["pricePerMessage", "currency"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsPrice: + """Create an instance of MmsPrice from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsPrice: + """Create an instance of MmsPrice from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsPrice.parse_obj(obj) + + _obj = MmsPrice.parse_obj( + { + "price_per_message": obj.get("pricePerMessage"), + "currency": obj.get("currency"), + } + ) + return _obj diff --git a/models/mms_report.py b/models/mms_report.py new file mode 100644 index 0000000..9c3158e --- /dev/null +++ b/models/mms_report.py @@ -0,0 +1,153 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr +from models.mms_error import MmsError +from models.mms_price import MmsPrice +from models.mms_status import MmsStatus + + +class MmsReport(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field(None, alias="bulkId", description="Bulk ID.") + message_id: Optional[StrictStr] = Field( + None, alias="messageId", description="Message ID." + ) + to: Optional[StrictStr] = Field(None, description="Destination address.") + var_from: Optional[StrictStr] = Field( + None, alias="from", description="Sender ID that can be alphanumeric or numeric." + ) + sent_at: Optional[datetime] = Field( + None, + alias="sentAt", + description="Indicates whether the MMS was sent. Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`.", + ) + done_at: Optional[datetime] = Field( + None, + alias="doneAt", + description="Indicates Whether the MMS was finished processing by Infobip (i.e., delivered to the destination, delivered to the destination network, etc.). Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`.", + ) + mms_count: Optional[StrictInt] = Field( + None, + alias="mmsCount", + description="The number of parts the sent MMS was split into.", + ) + mcc_mnc: Optional[StrictStr] = Field( + None, alias="mccMnc", description="Mobile country and network codes." + ) + callback_data: Optional[StrictStr] = Field( + None, + alias="callbackData", + description="Callback data sent through `callbackData` field in fully featured MMS message.", + ) + price: Optional[MmsPrice] = None + status: Optional[MmsStatus] = None + error: Optional[MmsError] = None + entity_id: Optional[StrictStr] = Field( + None, alias="entityId", description="Entity used in MMS request." + ) + application_id: Optional[StrictStr] = Field( + None, alias="applicationId", description="Application used in MMS request." + ) + __properties = [ + "bulkId", + "messageId", + "to", + "from", + "sentAt", + "doneAt", + "mmsCount", + "mccMnc", + "callbackData", + "price", + "status", + "error", + "entityId", + "applicationId", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsReport: + """Create an instance of MmsReport from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of price + if self.price: + _dict["price"] = self.price.to_dict() + # override the default output from pydantic by calling `to_dict()` of status + if self.status: + _dict["status"] = self.status.to_dict() + # override the default output from pydantic by calling `to_dict()` of error + if self.error: + _dict["error"] = self.error.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsReport: + """Create an instance of MmsReport from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsReport.parse_obj(obj) + + _obj = MmsReport.parse_obj( + { + "bulk_id": obj.get("bulkId"), + "message_id": obj.get("messageId"), + "to": obj.get("to"), + "var_from": obj.get("from"), + "sent_at": obj.get("sentAt"), + "done_at": obj.get("doneAt"), + "mms_count": obj.get("mmsCount"), + "mcc_mnc": obj.get("mccMnc"), + "callback_data": obj.get("callbackData"), + "price": MmsPrice.from_dict(obj.get("price")) + if obj.get("price") is not None + else None, + "status": MmsStatus.from_dict(obj.get("status")) + if obj.get("status") is not None + else None, + "error": MmsError.from_dict(obj.get("error")) + if obj.get("error") is not None + else None, + "entity_id": obj.get("entityId"), + "application_id": obj.get("applicationId"), + } + ) + return _obj diff --git a/models/mms_report_response.py b/models/mms_report_response.py new file mode 100644 index 0000000..6930b5f --- /dev/null +++ b/models/mms_report_response.py @@ -0,0 +1,77 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel +from models.mms_report import MmsReport + + +class MmsReportResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[MmsReport]] = None + __properties = ["results"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsReportResponse: + """Create an instance of MmsReportResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsReportResponse: + """Create an instance of MmsReportResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsReportResponse.parse_obj(obj) + + _obj = MmsReportResponse.parse_obj( + { + "results": [MmsReport.from_dict(_item) for _item in obj.get("results")] + if obj.get("results") is not None + else None + } + ) + return _obj diff --git a/models/mms_send_result.py b/models/mms_send_result.py new file mode 100644 index 0000000..9dd40dc --- /dev/null +++ b/models/mms_send_result.py @@ -0,0 +1,89 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictStr +from models.mms_message_result import MmsMessageResult + + +class MmsSendResult(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field( + None, alias="bulkId", description="Unique bulk identifier." + ) + messages: List[MmsMessageResult] = Field( + ..., description="Array of sent message objects, one object per every message." + ) + error_message: Optional[StrictStr] = Field( + None, alias="errorMessage", description="General error description." + ) + __properties = ["bulkId", "messages", "errorMessage"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsSendResult: + """Create an instance of MmsSendResult from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in messages (list) + _items = [] + if self.messages: + for _item in self.messages: + if _item: + _items.append(_item.to_dict()) + _dict["messages"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsSendResult: + """Create an instance of MmsSendResult from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsSendResult.parse_obj(obj) + + _obj = MmsSendResult.parse_obj( + { + "bulk_id": obj.get("bulkId"), + "messages": [ + MmsMessageResult.from_dict(_item) for _item in obj.get("messages") + ] + if obj.get("messages") is not None + else None, + "error_message": obj.get("errorMessage"), + } + ) + return _obj diff --git a/models/mms_status.py b/models/mms_status.py new file mode 100644 index 0000000..98ea834 --- /dev/null +++ b/models/mms_status.py @@ -0,0 +1,76 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, StrictInt, StrictStr + + +class MmsStatus(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + group_id: StrictInt = Field(..., alias="groupId", description="Status group ID.") + group_name: StrictStr = Field( + ..., alias="groupName", description="Status group name." + ) + id: StrictInt = Field(..., description="Status ID.") + name: StrictStr = Field(..., description="Status name.") + description: StrictStr = Field(..., description="Status description.") + __properties = ["groupId", "groupName", "id", "name", "description"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsStatus: + """Create an instance of MmsStatus from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsStatus: + """Create an instance of MmsStatus from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsStatus.parse_obj(obj) + + _obj = MmsStatus.parse_obj( + { + "group_id": obj.get("groupId"), + "group_name": obj.get("groupName"), + "id": obj.get("id"), + "name": obj.get("name"), + "description": obj.get("description"), + } + ) + return _obj diff --git a/models/mms_upload_binary_result.py b/models/mms_upload_binary_result.py new file mode 100644 index 0000000..6a68f46 --- /dev/null +++ b/models/mms_upload_binary_result.py @@ -0,0 +1,69 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class MmsUploadBinaryResult(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + uploaded_content_id: Optional[StrictStr] = Field( + None, + alias="uploadedContentId", + description="The ID that uniquely identifies the uploaded content.", + ) + __properties = ["uploadedContentId"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsUploadBinaryResult: + """Create an instance of MmsUploadBinaryResult from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsUploadBinaryResult: + """Create an instance of MmsUploadBinaryResult from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsUploadBinaryResult.parse_obj(obj) + + _obj = MmsUploadBinaryResult.parse_obj( + {"uploaded_content_id": obj.get("uploadedContentId")} + ) + return _obj diff --git a/models/mms_webhook_inbound_message_segment.py b/models/mms_webhook_inbound_message_segment.py new file mode 100644 index 0000000..6b0494a --- /dev/null +++ b/models/mms_webhook_inbound_message_segment.py @@ -0,0 +1,157 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations + +import pprint +import re # noqa: F401 +from typing import Any, List +from typing import Optional + +from pydantic import BaseModel, ValidationError, validator +from pydantic import Field + +from models.mms_webhook_inbound_message_segment_link import ( + MmsWebhookInboundMessageSegmentLink, +) +from models.mms_webhook_inbound_message_segment_text import ( + MmsWebhookInboundMessageSegmentText, +) + +MMSWEBHOOKINBOUNDMESSAGESEGMENT_ANY_OF_SCHEMAS = [ + "MmsWebhookInboundMessageSegmentLink", + "MmsWebhookInboundMessageSegmentText", +] + + +class MmsWebhookInboundMessageSegment(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + # data type: MmsWebhookInboundMessageSegmentText + anyof_schema_1_validator: Optional[MmsWebhookInboundMessageSegmentText] = None + # data type: MmsWebhookInboundMessageSegmentLink + anyof_schema_2_validator: Optional[MmsWebhookInboundMessageSegmentLink] = None + actual_instance: Any + any_of_schemas: List[str] = Field( + MMSWEBHOOKINBOUNDMESSAGESEGMENT_ANY_OF_SCHEMAS, const=True + ) + + class Config: + validate_assignment = True + + @validator("actual_instance") + def actual_instance_must_validate_anyof(cls, v): + instance = cls() + error_messages = [] + # validate data type: MmsWebhookInboundMessageSegmentText + if type(v) is not MmsWebhookInboundMessageSegmentText: + error_messages.append( + f"Error! Input type `{type(v)}` is not `MmsWebhookInboundMessageSegmentText`" + ) + else: + return v + + # validate data type: MmsWebhookInboundMessageSegmentLink + if type(v) is not MmsWebhookInboundMessageSegmentLink: + error_messages.append( + f"Error! Input type `{type(v)}` is not `MmsWebhookInboundMessageSegmentLink`" + ) + else: + return v + + if error_messages: + # no match + raise ValueError( + "No match found when deserializing the JSON string into MmsWebhookInboundMessageSegment with anyOf schemas: MmsWebhookInboundMessageSegmentLink, MmsWebhookInboundMessageSegmentText. Details: " + + ", ".join(error_messages) + ) + else: + return v + + @classmethod + def from_json(cls, json_str: str) -> MmsWebhookInboundMessageSegment: + """Returns the object represented by the json string""" + instance = cls() + error_messages = [] + try: + instance.actual_instance = MmsWebhookInboundMessageSegmentText.from_json( + json_str + ) + return instance + except ValidationError as e: + error_messages.append(str(e)) + try: + instance.actual_instance = MmsWebhookInboundMessageSegmentLink.from_json( + json_str + ) + return instance + except ValidationError as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError( + "No match found when deserializing the JSON into MmsWebhookInboundMessageSegment with anyOf schemas: " + + "MmsWebhookInboundMessageSegmentLink, MmsWebhookInboundMessageSegmentText. Details:" + + ", ".join(error_messages) + ) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is not None: + return self.actual_instance.to_json() + else: + return "null" + + @classmethod + def from_dict(cls, obj: dict) -> MmsWebhookInboundMessageSegment: + """Create an instance of MmsWebhookInboundMessageSegment from a dict""" + instance = cls() + error_messages = [] + try: + instance.actual_instance = MmsWebhookInboundMessageSegmentText.from_dict( + obj + ) + return instance + except ValidationError as e: + error_messages.append(str(e)) + try: + instance.actual_instance = MmsWebhookInboundMessageSegmentLink.from_dict( + obj + ) + return instance + except ValidationError as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError( + "No match found when deserializing the dict into MmsWebhookInboundMessageSegment with anyOf schemas: " + + "MmsWebhookInboundMessageSegmentLink, MmsWebhookInboundMessageSegmentText. Details:" + + ", ".join(error_messages) + ) + else: + return instance + + def to_dict(self) -> dict: + """Returns the dict representation of the actual instance""" + if self.actual_instance is not None: + return self.actual_instance.to_dict() + else: + return dict() + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.dict()) diff --git a/models/mms_webhook_inbound_message_segment_link.py b/models/mms_webhook_inbound_message_segment_link.py new file mode 100644 index 0000000..e2c14c6 --- /dev/null +++ b/models/mms_webhook_inbound_message_segment_link.py @@ -0,0 +1,68 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 + +from pydantic import BaseModel, Field, StrictStr + + +class MmsWebhookInboundMessageSegmentLink(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + content_type: StrictStr = Field( + ..., + alias="contentType", + description="Content type of the message segment, e.g. `image/jpeg`.", + ) + url: StrictStr = Field(..., description="URL from which content can be downloaded.") + __properties = ["contentType", "url"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsWebhookInboundMessageSegmentLink: + """Create an instance of MmsWebhookInboundMessageSegmentLink from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsWebhookInboundMessageSegmentLink: + """Create an instance of MmsWebhookInboundMessageSegmentLink from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsWebhookInboundMessageSegmentLink.parse_obj(obj) + + _obj = MmsWebhookInboundMessageSegmentLink.parse_obj( + {"content_type": obj.get("contentType"), "url": obj.get("url")} + ) + return _obj diff --git a/models/mms_webhook_inbound_message_segment_text.py b/models/mms_webhook_inbound_message_segment_text.py new file mode 100644 index 0000000..1155281 --- /dev/null +++ b/models/mms_webhook_inbound_message_segment_text.py @@ -0,0 +1,68 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 + +from pydantic import BaseModel, Field, StrictStr + + +class MmsWebhookInboundMessageSegmentText(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + content_type: StrictStr = Field( + ..., + alias="contentType", + description="Content type of the message segment, e.g. `text/plain`.", + ) + value: StrictStr = Field(..., description="Message text.") + __properties = ["contentType", "value"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsWebhookInboundMessageSegmentText: + """Create an instance of MmsWebhookInboundMessageSegmentText from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsWebhookInboundMessageSegmentText: + """Create an instance of MmsWebhookInboundMessageSegmentText from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsWebhookInboundMessageSegmentText.parse_obj(obj) + + _obj = MmsWebhookInboundMessageSegmentText.parse_obj( + {"content_type": obj.get("contentType"), "value": obj.get("value")} + ) + return _obj diff --git a/models/mms_webhook_inbound_report.py b/models/mms_webhook_inbound_report.py new file mode 100644 index 0000000..196a398 --- /dev/null +++ b/models/mms_webhook_inbound_report.py @@ -0,0 +1,154 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import List, Optional +from pydantic import BaseModel, Field, StrictStr +from models.message_price import MessagePrice +from models.mms_webhook_inbound_message_segment import ( + MmsWebhookInboundMessageSegment, +) + + +class MmsWebhookInboundReport(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + entity_id: Optional[StrictStr] = Field( + None, + alias="entityId", + description="The ID of the entity, if application and entity management is used.", + ) + application_id: Optional[StrictStr] = Field( + None, + alias="applicationId", + description="The ID of the application, if application and entity management is used.", + ) + var_from: Optional[StrictStr] = Field( + None, alias="from", description="Sender ID that can be alphanumeric or numeric." + ) + to: Optional[StrictStr] = Field( + None, description="The message destination address." + ) + received_at: Optional[datetime] = Field( + None, + alias="receivedAt", + description="Date and time when Infobip received the message.", + ) + message_id: Optional[StrictStr] = Field( + None, + alias="messageId", + description="The ID that uniquely identifies the received message.", + ) + paired_message_id: Optional[StrictStr] = Field( + None, + alias="pairedMessageId", + description="Message ID of paired outgoing message if matched by Infobip platform.", + ) + callback_data: Optional[StrictStr] = Field( + None, + alias="callbackData", + description="Callback data sent through `callbackData` field in fully featured MMS message.", + ) + user_agent: Optional[StrictStr] = Field( + None, + alias="userAgent", + description="Identifier of the device from which the message was sent.", + ) + message: Optional[List[MmsWebhookInboundMessageSegment]] = Field( + None, description="All parts of the received message." + ) + price: Optional[MessagePrice] = None + __properties = [ + "entityId", + "applicationId", + "from", + "to", + "receivedAt", + "messageId", + "pairedMessageId", + "callbackData", + "userAgent", + "message", + "price", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsWebhookInboundReport: + """Create an instance of MmsWebhookInboundReport from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in message (list) + _items = [] + if self.message: + for _item in self.message: + if _item: + _items.append(_item.to_dict()) + _dict["message"] = _items + # override the default output from pydantic by calling `to_dict()` of price + if self.price: + _dict["price"] = self.price.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsWebhookInboundReport: + """Create an instance of MmsWebhookInboundReport from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsWebhookInboundReport.parse_obj(obj) + + _obj = MmsWebhookInboundReport.parse_obj( + { + "entity_id": obj.get("entityId"), + "application_id": obj.get("applicationId"), + "var_from": obj.get("from"), + "to": obj.get("to"), + "received_at": obj.get("receivedAt"), + "message_id": obj.get("messageId"), + "paired_message_id": obj.get("pairedMessageId"), + "callback_data": obj.get("callbackData"), + "user_agent": obj.get("userAgent"), + "message": [ + MmsWebhookInboundMessageSegment.from_dict(_item) + for _item in obj.get("message") + ] + if obj.get("message") is not None + else None, + "price": MessagePrice.from_dict(obj.get("price")) + if obj.get("price") is not None + else None, + } + ) + return _obj diff --git a/models/mms_webhook_inbound_report_response.py b/models/mms_webhook_inbound_report_response.py new file mode 100644 index 0000000..2cd5e63 --- /dev/null +++ b/models/mms_webhook_inbound_report_response.py @@ -0,0 +1,92 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictInt +from models.mms_webhook_inbound_report import MmsWebhookInboundReport + + +class MmsWebhookInboundReportResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[MmsWebhookInboundReport]] = None + message_count: Optional[StrictInt] = Field( + None, + alias="messageCount", + description="Number of returned messages in this request.", + ) + pending_message_count: Optional[StrictInt] = Field( + None, + alias="pendingMessageCount", + description="Number of remaining new messages on Infobip servers ready to be returned in the next request.", + ) + __properties = ["results", "messageCount", "pendingMessageCount"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsWebhookInboundReportResponse: + """Create an instance of MmsWebhookInboundReportResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsWebhookInboundReportResponse: + """Create an instance of MmsWebhookInboundReportResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsWebhookInboundReportResponse.parse_obj(obj) + + _obj = MmsWebhookInboundReportResponse.parse_obj( + { + "results": [ + MmsWebhookInboundReport.from_dict(_item) + for _item in obj.get("results") + ] + if obj.get("results") is not None + else None, + "message_count": obj.get("messageCount"), + "pending_message_count": obj.get("pendingMessageCount"), + } + ) + return _obj diff --git a/models/mms_webhook_outbound_report.py b/models/mms_webhook_outbound_report.py new file mode 100644 index 0000000..c0afc93 --- /dev/null +++ b/models/mms_webhook_outbound_report.py @@ -0,0 +1,147 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr +from models.message_error import MessageError +from models.message_price import MessagePrice +from models.message_status import MessageStatus + + +class MmsWebhookOutboundReport(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field(None, alias="bulkId", description="Bulk ID.") + message_id: Optional[StrictStr] = Field( + None, alias="messageId", description="Message ID." + ) + to: Optional[StrictStr] = Field(None, description="Destination address") + sent_at: Optional[datetime] = Field( + None, + alias="sentAt", + description="Tells when the MMS was sent. Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`.", + ) + done_at: Optional[datetime] = Field( + None, + alias="doneAt", + description="Tells when the MMS was finished processing by Infobip (i.e., delivered to the destination, delivered to the destination network, etc.)", + ) + sms_count: Optional[StrictInt] = Field( + None, + alias="smsCount", + description="The number of parts the sent MMS was split into.", + ) + mcc_mnc: Optional[StrictStr] = Field( + None, alias="mccMnc", description="Mobile country and network codes." + ) + callback_data: Optional[StrictStr] = Field( + None, + alias="callbackData", + description="Callback data sent through `callbackData` field in fully featured MMS message.", + ) + price: Optional[MessagePrice] = None + status: Optional[MessageStatus] = None + error: Optional[MessageError] = None + entity_id: Optional[StrictStr] = Field( + None, alias="entityId", description="Entity used in MMS request." + ) + application_id: Optional[StrictStr] = Field( + None, alias="applicationId", description="Application used in MMS request." + ) + __properties = [ + "bulkId", + "messageId", + "to", + "sentAt", + "doneAt", + "smsCount", + "mccMnc", + "callbackData", + "price", + "status", + "error", + "entityId", + "applicationId", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsWebhookOutboundReport: + """Create an instance of MmsWebhookOutboundReport from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of price + if self.price: + _dict["price"] = self.price.to_dict() + # override the default output from pydantic by calling `to_dict()` of status + if self.status: + _dict["status"] = self.status.to_dict() + # override the default output from pydantic by calling `to_dict()` of error + if self.error: + _dict["error"] = self.error.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsWebhookOutboundReport: + """Create an instance of MmsWebhookOutboundReport from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsWebhookOutboundReport.parse_obj(obj) + + _obj = MmsWebhookOutboundReport.parse_obj( + { + "bulk_id": obj.get("bulkId"), + "message_id": obj.get("messageId"), + "to": obj.get("to"), + "sent_at": obj.get("sentAt"), + "done_at": obj.get("doneAt"), + "sms_count": obj.get("smsCount"), + "mcc_mnc": obj.get("mccMnc"), + "callback_data": obj.get("callbackData"), + "price": MessagePrice.from_dict(obj.get("price")) + if obj.get("price") is not None + else None, + "status": MessageStatus.from_dict(obj.get("status")) + if obj.get("status") is not None + else None, + "error": MessageError.from_dict(obj.get("error")) + if obj.get("error") is not None + else None, + "entity_id": obj.get("entityId"), + "application_id": obj.get("applicationId"), + } + ) + return _obj diff --git a/models/mms_webhook_outbound_report_response.py b/models/mms_webhook_outbound_report_response.py new file mode 100644 index 0000000..6e06cf8 --- /dev/null +++ b/models/mms_webhook_outbound_report_response.py @@ -0,0 +1,80 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel +from models.mms_webhook_outbound_report import MmsWebhookOutboundReport + + +class MmsWebhookOutboundReportResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[MmsWebhookOutboundReport]] = None + __properties = ["results"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> MmsWebhookOutboundReportResponse: + """Create an instance of MmsWebhookOutboundReportResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> MmsWebhookOutboundReportResponse: + """Create an instance of MmsWebhookOutboundReportResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return MmsWebhookOutboundReportResponse.parse_obj(obj) + + _obj = MmsWebhookOutboundReportResponse.parse_obj( + { + "results": [ + MmsWebhookOutboundReport.from_dict(_item) + for _item in obj.get("results") + ] + if obj.get("results") is not None + else None + } + ) + return _obj diff --git a/models/modify_application.py b/models/modify_application.py new file mode 100644 index 0000000..4ff2e8e --- /dev/null +++ b/models/modify_application.py @@ -0,0 +1,67 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, constr + + +class ModifyApplication(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + application_name: Optional[constr(strict=True, max_length=255)] = Field( + None, alias="applicationName", description="Descriptive name of the resource." + ) + __properties = ["applicationName"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> ModifyApplication: + """Create an instance of ModifyApplication from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> ModifyApplication: + """Create an instance of ModifyApplication from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return ModifyApplication.parse_obj(obj) + + _obj = ModifyApplication.parse_obj( + {"application_name": obj.get("applicationName")} + ) + return _obj diff --git a/models/modify_entity.py b/models/modify_entity.py new file mode 100644 index 0000000..f6e984d --- /dev/null +++ b/models/modify_entity.py @@ -0,0 +1,65 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, constr + + +class ModifyEntity(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + entity_name: Optional[constr(strict=True, max_length=255)] = Field( + None, alias="entityName", description="Descriptive name of the resource." + ) + __properties = ["entityName"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> ModifyEntity: + """Create an instance of ModifyEntity from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> ModifyEntity: + """Create an instance of ModifyEntity from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return ModifyEntity.parse_obj(obj) + + _obj = ModifyEntity.parse_obj({"entity_name": obj.get("entityName")}) + return _obj diff --git a/models/number_price.py b/models/number_price.py new file mode 100644 index 0000000..4b4ebec --- /dev/null +++ b/models/number_price.py @@ -0,0 +1,73 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictFloat, StrictStr + + +class NumberPrice(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + price_per_month: Optional[StrictFloat] = Field(None, alias="pricePerMonth") + setup_price: Optional[StrictFloat] = Field(None, alias="setupPrice") + initial_month_price: Optional[StrictFloat] = Field(None, alias="initialMonthPrice") + currency: Optional[StrictStr] = None + __properties = ["pricePerMonth", "setupPrice", "initialMonthPrice", "currency"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberPrice: + """Create an instance of NumberPrice from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberPrice: + """Create an instance of NumberPrice from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberPrice.parse_obj(obj) + + _obj = NumberPrice.parse_obj( + { + "price_per_month": obj.get("pricePerMonth"), + "setup_price": obj.get("setupPrice"), + "initial_month_price": obj.get("initialMonthPrice"), + "currency": obj.get("currency"), + } + ) + return _obj diff --git a/models/number_registration_address.py b/models/number_registration_address.py new file mode 100644 index 0000000..aef9b26 --- /dev/null +++ b/models/number_registration_address.py @@ -0,0 +1,82 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, constr + + +class NumberRegistrationAddress(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + city: constr(strict=True, max_length=50, min_length=1) = Field( + ..., description="The city in which the brand is located." + ) + state: Optional[constr(strict=True, max_length=50, min_length=1)] = Field( + None, + description="State or province. For the United States, please use 2 character codes. E.g. 'CA' for California.", + ) + street: constr(strict=True, max_length=100, min_length=1) = Field( + ..., description="The street address for the brand." + ) + zip_code: constr(strict=True, max_length=10, min_length=1) = Field( + ..., alias="zipCode", description="The zipcode in which the brand is located." + ) + __properties = ["city", "state", "street", "zipCode"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationAddress: + """Create an instance of NumberRegistrationAddress from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationAddress: + """Create an instance of NumberRegistrationAddress from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationAddress.parse_obj(obj) + + _obj = NumberRegistrationAddress.parse_obj( + { + "city": obj.get("city"), + "state": obj.get("state"), + "street": obj.get("street"), + "zip_code": obj.get("zipCode"), + } + ) + return _obj diff --git a/models/number_registration_brand.py b/models/number_registration_brand.py new file mode 100644 index 0000000..1d1dfc8 --- /dev/null +++ b/models/number_registration_brand.py @@ -0,0 +1,135 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json +import models + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, constr, validator + + +class NumberRegistrationBrand(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + id: Optional[StrictStr] = Field(None, description="The identifier for the brand.") + name: constr(strict=True, max_length=100, min_length=1) = Field( + ..., description="The customer defined name of brand." + ) + website: constr(strict=True, max_length=255, min_length=11) = Field( + ..., description="The website for the brand." + ) + created_date: Optional[datetime] = Field( + None, + alias="createdDate", + description="The date and time when the brand was created.", + ) + last_modified_date: Optional[datetime] = Field( + None, + alias="lastModifiedDate", + description="The date and time when the brand was last modified.", + ) + type: StrictStr = Field(..., description="The type of brand.") + __properties = ["id", "name", "website", "createdDate", "lastModifiedDate", "type"] + + @validator("type") + def type_validate_enum(cls, v): + if v not in ( + '"TENDLC_NON_PROFIT","TENDLC_PRIVATE_COMPANY","TENDLC_PUBLIC_COMPANY","TENDLC_GOVERNMENT"' + ): + raise ValueError( + 'must validate the enum values (\'"TENDLC_NON_PROFIT","TENDLC_PRIVATE_COMPANY","TENDLC_PUBLIC_COMPANY","TENDLC_GOVERNMENT"\')' + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + # JSON field name that stores the object type + __discriminator_property_name = "type" + + # discriminator mappings + __discriminator_value_class_map = { + "NumberRegistrationGovernmentBrand": "NumberRegistrationGovernmentBrand", + "NumberRegistrationNonProfitBrand": "NumberRegistrationNonProfitBrand", + "NumberRegistrationPrivateCompanyBrand": "NumberRegistrationPrivateCompanyBrand", + "NumberRegistrationPublicCompanyBrand": "NumberRegistrationPublicCompanyBrand", + "TENDLC_GOVERNMENT": "NumberRegistrationGovernmentBrand", + "TENDLC_NON_PROFIT": "NumberRegistrationNonProfitBrand", + "TENDLC_PRIVATE_COMPANY": "NumberRegistrationPrivateCompanyBrand", + "TENDLC_PUBLIC_COMPANY": "NumberRegistrationPublicCompanyBrand", + } + + @classmethod + def get_discriminator_value(cls, obj: dict) -> str: + """Returns the discriminator value (object type) of the data""" + discriminator_value = obj[cls.__discriminator_property_name] + if discriminator_value: + return cls.__discriminator_value_class_map.get(discriminator_value) + else: + return None + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json( + cls, json_str: str + ) -> Union( + NumberRegistrationGovernmentBrand, + NumberRegistrationNonProfitBrand, + NumberRegistrationPrivateCompanyBrand, + NumberRegistrationPublicCompanyBrand, + ): + """Create an instance of NumberRegistrationBrand from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict( + cls, obj: dict + ) -> Union( + NumberRegistrationGovernmentBrand, + NumberRegistrationNonProfitBrand, + NumberRegistrationPrivateCompanyBrand, + NumberRegistrationPublicCompanyBrand, + ): + """Create an instance of NumberRegistrationBrand from a dict""" + # look up the object type based on discriminator mapping + object_type = cls.get_discriminator_value(obj) + if object_type: + klass = getattr(models, object_type) + return klass.from_dict(obj) + else: + raise ValueError( + "NumberRegistrationBrand failed to lookup discriminator value from " + + json.dumps(obj) + + ". Discriminator property name: " + + cls.__discriminator_property_name + + ", mapping: " + + json.dumps(cls.__discriminator_value_class_map) + ) diff --git a/models/number_registration_brand_preview.py b/models/number_registration_brand_preview.py new file mode 100644 index 0000000..f4b2e33 --- /dev/null +++ b/models/number_registration_brand_preview.py @@ -0,0 +1,66 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class NumberRegistrationBrandPreview(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + brand_id: Optional[StrictStr] = Field(None, alias="brandId") + brand_name: Optional[StrictStr] = Field(None, alias="brandName") + __properties = ["brandId", "brandName"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationBrandPreview: + """Create an instance of NumberRegistrationBrandPreview from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationBrandPreview: + """Create an instance of NumberRegistrationBrandPreview from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationBrandPreview.parse_obj(obj) + + _obj = NumberRegistrationBrandPreview.parse_obj( + {"brand_id": obj.get("brandId"), "brand_name": obj.get("brandName")} + ) + return _obj diff --git a/models/number_registration_brand_status.py b/models/number_registration_brand_status.py new file mode 100644 index 0000000..c2c4e86 --- /dev/null +++ b/models/number_registration_brand_status.py @@ -0,0 +1,111 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, validator + + +class NumberRegistrationBrandStatus(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + registrar: Optional[StrictStr] = Field( + None, + description="The name of the registrar with which the brand has been registered.", + ) + state: Optional[StrictStr] = Field( + None, description="The state of the registration for this brand." + ) + brand_identity_status: Optional[StrictStr] = Field( + None, + alias="brandIdentityStatus", + description="The status of the brand as determined by the registrar.", + ) + __properties = ["registrar", "state", "brandIdentityStatus"] + + @validator("registrar") + def registrar_validate_enum(cls, v): + if v is None: + return v + + if v not in ("CAMPAIGN_REGISTRY"): + raise ValueError("must validate the enum values ('CAMPAIGN_REGISTRY')") + return v + + @validator("state") + def state_validate_enum(cls, v): + if v is None: + return v + + if v not in ("ACTIVE", "PENDING", "REJECTED"): + raise ValueError( + "must validate the enum values ('ACTIVE', 'PENDING', 'REJECTED')" + ) + return v + + @validator("brand_identity_status") + def brand_identity_status_validate_enum(cls, v): + if v is None: + return v + + if v not in ("SELF_DECLARED", "UNVERIFIED", "VERIFIED", "VETTED_VERIFIED"): + raise ValueError( + "must validate the enum values ('SELF_DECLARED', 'UNVERIFIED', 'VERIFIED', 'VETTED_VERIFIED')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationBrandStatus: + """Create an instance of NumberRegistrationBrandStatus from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationBrandStatus: + """Create an instance of NumberRegistrationBrandStatus from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationBrandStatus.parse_obj(obj) + + _obj = NumberRegistrationBrandStatus.parse_obj( + { + "registrar": obj.get("registrar"), + "state": obj.get("state"), + "brand_identity_status": obj.get("brandIdentityStatus"), + } + ) + return _obj diff --git a/models/number_registration_brand_vet.py b/models/number_registration_brand_vet.py new file mode 100644 index 0000000..522401a --- /dev/null +++ b/models/number_registration_brand_vet.py @@ -0,0 +1,102 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr, validator + + +class NumberRegistrationBrandVet(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + vet_id: Optional[StrictStr] = Field( + None, alias="vetId", description="The ID of the vet record." + ) + brand_id: Optional[StrictStr] = Field( + None, alias="brandId", description="The ID of the brand the vet belongs to." + ) + score: Optional[StrictInt] = Field( + None, description="The score the brand received after being vetted." + ) + vetted_date: Optional[datetime] = Field( + None, alias="vettedDate", description="The date the vet was completed." + ) + enhanced_vetted_date: Optional[datetime] = Field( + None, + alias="enhancedVettedDate", + description="The date the vet was completed if it was an enhanced vet or if it was converted to enhanced from a standard vet.", + ) + type: StrictStr = Field(..., description="The type of vet.") + __properties = [ + "vetId", + "brandId", + "score", + "vettedDate", + "enhancedVettedDate", + "type", + ] + + @validator("type") + def type_validate_enum(cls, v): + if v not in ("STANDARD", "ENHANCED"): + raise ValueError("must validate the enum values ('STANDARD', 'ENHANCED')") + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationBrandVet: + """Create an instance of NumberRegistrationBrandVet from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationBrandVet: + """Create an instance of NumberRegistrationBrandVet from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationBrandVet.parse_obj(obj) + + _obj = NumberRegistrationBrandVet.parse_obj( + { + "vet_id": obj.get("vetId"), + "brand_id": obj.get("brandId"), + "score": obj.get("score"), + "vetted_date": obj.get("vettedDate"), + "enhanced_vetted_date": obj.get("enhancedVettedDate"), + "type": obj.get("type"), + } + ) + return _obj diff --git a/models/number_registration_business_identifier.py b/models/number_registration_business_identifier.py new file mode 100644 index 0000000..de1757e --- /dev/null +++ b/models/number_registration_business_identifier.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json +import models + + +from typing import Optional +from pydantic import BaseModel, StrictStr, validator + + +class NumberRegistrationBusinessIdentifier(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + id: Optional[StrictStr] = None + type: Optional[StrictStr] = None + __properties = ["id", "type"] + + @validator("type") + def type_validate_enum(cls, v): + if v is None: + return v + + if v not in ("DUNS", "GIIN", "LEI"): + raise ValueError("must validate the enum values ('DUNS', 'GIIN', 'LEI')") + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + # JSON field name that stores the object type + __discriminator_property_name = "type" + + # discriminator mappings + __discriminator_value_class_map = { + "DUNS": "NumberRegistrationDataUniversalNumberingSystemNumber", + "GIIN": "NumberRegistrationGlobalIntermediaryIdentificationNumber", + "LEI": "NumberRegistrationLegalEntityIdentifier", + "NumberRegistrationDataUniversalNumberingSystemNumber": "NumberRegistrationDataUniversalNumberingSystemNumber", + "NumberRegistrationGlobalIntermediaryIdentificationNumber": "NumberRegistrationGlobalIntermediaryIdentificationNumber", + "NumberRegistrationLegalEntityIdentifier": "NumberRegistrationLegalEntityIdentifier", + } + + @classmethod + def get_discriminator_value(cls, obj: dict) -> str: + """Returns the discriminator value (object type) of the data""" + discriminator_value = obj[cls.__discriminator_property_name] + if discriminator_value: + return cls.__discriminator_value_class_map.get(discriminator_value) + else: + return None + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json( + cls, json_str: str + ) -> Union( + NumberRegistrationDataUniversalNumberingSystemNumber, + NumberRegistrationGlobalIntermediaryIdentificationNumber, + NumberRegistrationLegalEntityIdentifier, + ): + """Create an instance of NumberRegistrationBusinessIdentifier from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict( + cls, obj: dict + ) -> Union( + NumberRegistrationDataUniversalNumberingSystemNumber, + NumberRegistrationGlobalIntermediaryIdentificationNumber, + NumberRegistrationLegalEntityIdentifier, + ): + """Create an instance of NumberRegistrationBusinessIdentifier from a dict""" + # look up the object type based on discriminator mapping + object_type = cls.get_discriminator_value(obj) + if object_type: + klass = getattr(models, object_type) + return klass.from_dict(obj) + else: + raise ValueError( + "NumberRegistrationBusinessIdentifier failed to lookup discriminator value from " + + json.dumps(obj) + + ". Discriminator property name: " + + cls.__discriminator_property_name + + ", mapping: " + + json.dumps(cls.__discriminator_value_class_map) + ) diff --git a/models/number_registration_campaign.py b/models/number_registration_campaign.py new file mode 100644 index 0000000..e2e1801 --- /dev/null +++ b/models/number_registration_campaign.py @@ -0,0 +1,147 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json +import models + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, constr, validator + + +class NumberRegistrationCampaign(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + id: Optional[StrictStr] = Field( + None, description="The identifier for the campaign." + ) + reference_id: Optional[StrictStr] = Field( + None, + alias="referenceId", + description="Unique user defined ID for the campaign. While not required, it is recommended to supply a referenceId as the uniqueness constraint will help ensure a campaign is not accidentally created multiple times. Subsequent create requests with the same referenceId will be rejected with an error.", + ) + name: constr(strict=True, max_length=30, min_length=1) = Field( + ..., description="The name of the campaign." + ) + created_date: Optional[datetime] = Field( + None, + alias="createdDate", + description="The date and time when the campaign was created.", + ) + last_modified_date: Optional[datetime] = Field( + None, + alias="lastModifiedDate", + description="The date and time when the campaign was last modified.", + ) + type: Optional[StrictStr] = None + __properties = [ + "id", + "referenceId", + "name", + "createdDate", + "lastModifiedDate", + "type", + ] + + @validator("name") + def name_validate_regular_expression(cls, v): + if not re.match(r"[A-Za-z0-9_ ]*", v): + raise ValueError(r"must validate the regular expression /[A-Za-z0-9_ ]*/") + return v + + @validator("type") + def type_validate_enum(cls, v): + if v is None: + return v + + if v not in ( + "TEN_DIGIT_LONG_CODE", + "EXTERNAL_TEN_DIGIT_LONG_CODE", + "SHORT_CODE", + ): + raise ValueError( + "must validate the enum values ('TEN_DIGIT_LONG_CODE', 'EXTERNAL_TEN_DIGIT_LONG_CODE', 'SHORT_CODE')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + # JSON field name that stores the object type + __discriminator_property_name = "type" + + # discriminator mappings + __discriminator_value_class_map = { + "EXTERNAL_TEN_DIGIT_LONG_CODE": "NumberRegistrationExternalTenDlcCampaign", + "NumberRegistrationExternalTenDlcCampaign": "NumberRegistrationExternalTenDlcCampaign", + "NumberRegistrationTenDlcCampaign": "NumberRegistrationTenDlcCampaign", + "TEN_DIGIT_LONG_CODE": "NumberRegistrationTenDlcCampaign", + } + + @classmethod + def get_discriminator_value(cls, obj: dict) -> str: + """Returns the discriminator value (object type) of the data""" + discriminator_value = obj[cls.__discriminator_property_name] + if discriminator_value: + return cls.__discriminator_value_class_map.get(discriminator_value) + else: + return None + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json( + cls, json_str: str + ) -> Union( + NumberRegistrationExternalTenDlcCampaign, NumberRegistrationTenDlcCampaign + ): + """Create an instance of NumberRegistrationCampaign from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict( + cls, obj: dict + ) -> Union( + NumberRegistrationExternalTenDlcCampaign, NumberRegistrationTenDlcCampaign + ): + """Create an instance of NumberRegistrationCampaign from a dict""" + # look up the object type based on discriminator mapping + object_type = cls.get_discriminator_value(obj) + if object_type: + klass = getattr(models, object_type) + return klass.from_dict(obj) + else: + raise ValueError( + "NumberRegistrationCampaign failed to lookup discriminator value from " + + json.dumps(obj) + + ". Discriminator property name: " + + cls.__discriminator_property_name + + ", mapping: " + + json.dumps(cls.__discriminator_value_class_map) + ) diff --git a/models/number_registration_data_universal_numbering_system_number.py b/models/number_registration_data_universal_numbering_system_number.py new file mode 100644 index 0000000..88b3c76 --- /dev/null +++ b/models/number_registration_data_universal_numbering_system_number.py @@ -0,0 +1,81 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, constr, validator +from models.number_registration_business_identifier import ( + NumberRegistrationBusinessIdentifier, +) + + +class NumberRegistrationDataUniversalNumberingSystemNumber( + NumberRegistrationBusinessIdentifier +): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + id: constr(strict=True, max_length=9, min_length=9) = Field( + ..., description="The DUNS identifier." + ) + __properties = ["id", "type"] + + @validator("id") + def id_validate_regular_expression(cls, v): + if not re.match(r"\d{9}", v): + raise ValueError(r"must validate the regular expression /\d{9}/") + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json( + cls, json_str: str + ) -> NumberRegistrationDataUniversalNumberingSystemNumber: + """Create an instance of NumberRegistrationDataUniversalNumberingSystemNumber from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict( + cls, obj: dict + ) -> NumberRegistrationDataUniversalNumberingSystemNumber: + """Create an instance of NumberRegistrationDataUniversalNumberingSystemNumber from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationDataUniversalNumberingSystemNumber.parse_obj(obj) + + _obj = NumberRegistrationDataUniversalNumberingSystemNumber.parse_obj( + {"id": obj.get("id"), "type": obj.get("type")} + ) + return _obj diff --git a/models/number_registration_document_metadata.py b/models/number_registration_document_metadata.py new file mode 100644 index 0000000..fa760cd --- /dev/null +++ b/models/number_registration_document_metadata.py @@ -0,0 +1,73 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr + + +class NumberRegistrationDocumentMetadata(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + document_id: Optional[StrictStr] = Field(None, alias="documentId") + document_name: Optional[StrictStr] = Field(None, alias="documentName") + content_type: Optional[StrictStr] = Field(None, alias="contentType") + content_length: Optional[StrictInt] = Field(None, alias="contentLength") + __properties = ["documentId", "documentName", "contentType", "contentLength"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationDocumentMetadata: + """Create an instance of NumberRegistrationDocumentMetadata from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationDocumentMetadata: + """Create an instance of NumberRegistrationDocumentMetadata from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationDocumentMetadata.parse_obj(obj) + + _obj = NumberRegistrationDocumentMetadata.parse_obj( + { + "document_id": obj.get("documentId"), + "document_name": obj.get("documentName"), + "content_type": obj.get("contentType"), + "content_length": obj.get("contentLength"), + } + ) + return _obj diff --git a/models/number_registration_external_ten_dlc_campaign.py b/models/number_registration_external_ten_dlc_campaign.py new file mode 100644 index 0000000..2f98f2e --- /dev/null +++ b/models/number_registration_external_ten_dlc_campaign.py @@ -0,0 +1,124 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictStr, conlist +from models.number_registration_campaign import ( + NumberRegistrationCampaign, +) +from models.number_registration_number_preview import ( + NumberRegistrationNumberPreview, +) + + +class NumberRegistrationExternalTenDlcCampaign(NumberRegistrationCampaign): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + external_campaign_id: StrictStr = Field( + ..., + alias="externalCampaignId", + description="The ID of the campaign as defined by the external registrar (e.g. The Campaign Registry).", + ) + number_keys: conlist(StrictStr, max_items=50, min_items=1) = Field( + ..., + alias="numberKeys", + description="The numberKey(s) of the numbers to use with the campaign.", + ) + number_previews: Optional[List[NumberRegistrationNumberPreview]] = Field( + None, + alias="numberPreviews", + description="The number(s) to use with the campaign. This property is read-only and ignored in POST/PUT calls.", + unique_items=True, + ) + __properties = [ + "id", + "referenceId", + "name", + "createdDate", + "lastModifiedDate", + "type", + "externalCampaignId", + "numberKeys", + "numberPreviews", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationExternalTenDlcCampaign: + """Create an instance of NumberRegistrationExternalTenDlcCampaign from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict( + by_alias=True, + exclude={ + "number_previews", + }, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in number_previews (list) + _items = [] + if self.number_previews: + for _item in self.number_previews: + if _item: + _items.append(_item.to_dict()) + _dict["numberPreviews"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationExternalTenDlcCampaign: + """Create an instance of NumberRegistrationExternalTenDlcCampaign from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationExternalTenDlcCampaign.parse_obj(obj) + + _obj = NumberRegistrationExternalTenDlcCampaign.parse_obj( + { + "id": obj.get("id"), + "reference_id": obj.get("referenceId"), + "name": obj.get("name"), + "created_date": obj.get("createdDate"), + "last_modified_date": obj.get("lastModifiedDate"), + "type": obj.get("type"), + "external_campaign_id": obj.get("externalCampaignId"), + "number_keys": obj.get("numberKeys"), + "number_previews": [ + NumberRegistrationNumberPreview.from_dict(_item) + for _item in obj.get("numberPreviews") + ] + if obj.get("numberPreviews") is not None + else None, + } + ) + return _obj diff --git a/models/number_registration_global_intermediary_identification_number.py b/models/number_registration_global_intermediary_identification_number.py new file mode 100644 index 0000000..f726eb8 --- /dev/null +++ b/models/number_registration_global_intermediary_identification_number.py @@ -0,0 +1,87 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, constr, validator +from models.number_registration_business_identifier import ( + NumberRegistrationBusinessIdentifier, +) + + +class NumberRegistrationGlobalIntermediaryIdentificationNumber( + NumberRegistrationBusinessIdentifier +): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + id: constr(strict=True, max_length=19, min_length=19) = Field( + ..., description="The GIIN identifier." + ) + __properties = ["id", "type"] + + @validator("id") + def id_validate_regular_expression(cls, v): + if not re.match( + r"([A-NP-Z0-9]{6})\.([A-NP-Z0-9]{5})\.(LE|SL|ME|BR|SP)\.(\d{3})", v + ): + raise ValueError( + r"must validate the regular expression /([A-NP-Z0-9]{6})\.([A-NP-Z0-9]{5})\.(LE|SL|ME|BR|SP)\.(\d{3})/" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json( + cls, json_str: str + ) -> NumberRegistrationGlobalIntermediaryIdentificationNumber: + """Create an instance of NumberRegistrationGlobalIntermediaryIdentificationNumber from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict( + cls, obj: dict + ) -> NumberRegistrationGlobalIntermediaryIdentificationNumber: + """Create an instance of NumberRegistrationGlobalIntermediaryIdentificationNumber from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationGlobalIntermediaryIdentificationNumber.parse_obj( + obj + ) + + _obj = NumberRegistrationGlobalIntermediaryIdentificationNumber.parse_obj( + {"id": obj.get("id"), "type": obj.get("type")} + ) + return _obj diff --git a/models/number_registration_government_brand.py b/models/number_registration_government_brand.py new file mode 100644 index 0000000..d82d897 --- /dev/null +++ b/models/number_registration_government_brand.py @@ -0,0 +1,176 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, constr, validator +from models.number_registration_address import NumberRegistrationAddress +from models.number_registration_brand import NumberRegistrationBrand +from models.number_registration_business_identifier import ( + NumberRegistrationBusinessIdentifier, +) + + +class NumberRegistrationGovernmentBrand(NumberRegistrationBrand): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + reference_id: Optional[StrictStr] = Field( + None, + alias="referenceId", + description="Unique user defined ID for the brand. While not required, it is recommended to supply a referenceId as the uniqueness constraint will help ensure a brand is not accidentally created multiple times. Subsequent create requests with the same referenceId will be rejected with an error.", + ) + legal_name: constr(strict=True, max_length=255, min_length=1) = Field( + ..., alias="legalName", description="The legal name of the brand." + ) + address: NumberRegistrationAddress = ... + country_code: constr(strict=True, max_length=2, min_length=1) = Field( + ..., alias="countryCode", description="The country where the brand is located." + ) + alternate_business_id: Optional[NumberRegistrationBusinessIdentifier] = Field( + None, alias="alternateBusinessId" + ) + support_email: constr(strict=True, max_length=100, min_length=1) = Field( + ..., + alias="supportEmail", + description="The business email address to contact about brand compliance issues. Must be a well formed email address that does not include a '=' character.", + ) + support_phone: constr(strict=True, max_length=16, min_length=3) = Field( + ..., + alias="supportPhone", + description="The business phone number to contact about brand compliance issues.", + ) + vertical: StrictStr = Field( + ..., description="The vertical in which the brand operates." + ) + tax_id: constr(strict=True, max_length=21, min_length=1) = Field( + ..., alias="taxId", description="The tax identifier (EIN) for the brand." + ) + __properties = [ + "id", + "name", + "website", + "createdDate", + "lastModifiedDate", + "type", + "referenceId", + "legalName", + "address", + "countryCode", + "alternateBusinessId", + "supportEmail", + "supportPhone", + "vertical", + "taxId", + ] + + @validator("support_phone") + def support_phone_validate_regular_expression(cls, v): + if not re.match(r"\+?[1-9]\d{1,14}", v): + raise ValueError(r"must validate the regular expression /\+?[1-9]\d{1,14}/") + return v + + @validator("vertical") + def vertical_validate_enum(cls, v): + if v not in ( + "AGRICULTURE", + "CONSTRUCTION_AND_MATERIALS", + "EDUCATION", + "ENERGY_AND_UTILITIES", + "ENTERTAINMENT", + "FINANCIAL_SERVICES", + "GAMBLING_AND_LOTTERY", + "HEALTHCARE_AND_LIFESCIENCES", + "HOSPITALITY", + "INFORMATION_TECHNOLOGY_SERVICES", + "INSURANCE", + "MANUFACTURING", + "MASS_MEDIA_AND_COMMUNICATION", + "NON_PROFIT_ORGANIZATION", + "PUBLIC_SECTOR", + "REAL_ESTATE", + "RETAIL_AND_CONSUMER_PRODUCTS", + ): + raise ValueError( + "must validate the enum values ('AGRICULTURE', 'CONSTRUCTION_AND_MATERIALS', 'EDUCATION', 'ENERGY_AND_UTILITIES', 'ENTERTAINMENT', 'FINANCIAL_SERVICES', 'GAMBLING_AND_LOTTERY', 'HEALTHCARE_AND_LIFESCIENCES', 'HOSPITALITY', 'INFORMATION_TECHNOLOGY_SERVICES', 'INSURANCE', 'MANUFACTURING', 'MASS_MEDIA_AND_COMMUNICATION', 'NON_PROFIT_ORGANIZATION', 'PUBLIC_SECTOR', 'REAL_ESTATE', 'RETAIL_AND_CONSUMER_PRODUCTS')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationGovernmentBrand: + """Create an instance of NumberRegistrationGovernmentBrand from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of address + if self.address: + _dict["address"] = self.address.to_dict() + # override the default output from pydantic by calling `to_dict()` of alternate_business_id + if self.alternate_business_id: + _dict["alternateBusinessId"] = self.alternate_business_id.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationGovernmentBrand: + """Create an instance of NumberRegistrationGovernmentBrand from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationGovernmentBrand.parse_obj(obj) + + _obj = NumberRegistrationGovernmentBrand.parse_obj( + { + "id": obj.get("id"), + "name": obj.get("name"), + "website": obj.get("website"), + "created_date": obj.get("createdDate"), + "last_modified_date": obj.get("lastModifiedDate"), + "type": obj.get("type"), + "reference_id": obj.get("referenceId"), + "legal_name": obj.get("legalName"), + "address": NumberRegistrationAddress.from_dict(obj.get("address")) + if obj.get("address") is not None + else None, + "country_code": obj.get("countryCode"), + "alternate_business_id": NumberRegistrationBusinessIdentifier.from_dict( + obj.get("alternateBusinessId") + ) + if obj.get("alternateBusinessId") is not None + else None, + "support_email": obj.get("supportEmail"), + "support_phone": obj.get("supportPhone"), + "vertical": obj.get("vertical"), + "tax_id": obj.get("taxId"), + } + ) + return _obj diff --git a/models/number_registration_interactive_voice_response_opt_in.py b/models/number_registration_interactive_voice_response_opt_in.py new file mode 100644 index 0000000..5a47aa6 --- /dev/null +++ b/models/number_registration_interactive_voice_response_opt_in.py @@ -0,0 +1,70 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, constr + + +class NumberRegistrationInteractiveVoiceResponseOptIn(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + call_to_action: constr(strict=True, max_length=1024, min_length=20) = Field( + ..., + alias="callToAction", + description="The message sent to the user to tell them how to subscribe.", + ) + __properties = ["callToAction"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json( + cls, json_str: str + ) -> NumberRegistrationInteractiveVoiceResponseOptIn: + """Create an instance of NumberRegistrationInteractiveVoiceResponseOptIn from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationInteractiveVoiceResponseOptIn: + """Create an instance of NumberRegistrationInteractiveVoiceResponseOptIn from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationInteractiveVoiceResponseOptIn.parse_obj(obj) + + _obj = NumberRegistrationInteractiveVoiceResponseOptIn.parse_obj( + {"call_to_action": obj.get("callToAction")} + ) + return _obj diff --git a/models/number_registration_keyword_opt_in.py b/models/number_registration_keyword_opt_in.py new file mode 100644 index 0000000..6d4e008 --- /dev/null +++ b/models/number_registration_keyword_opt_in.py @@ -0,0 +1,72 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List +from pydantic import BaseModel, Field, StrictStr, constr + + +class NumberRegistrationKeywordOptIn(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + call_to_action: constr(strict=True, max_length=1024, min_length=20) = Field( + ..., + alias="callToAction", + description="The message sent to the user to tell them how to subscribe.", + ) + keywords: List[StrictStr] = Field( + ..., description="The keyword(s) the user will text to subscribe." + ) + __properties = ["callToAction", "keywords"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationKeywordOptIn: + """Create an instance of NumberRegistrationKeywordOptIn from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationKeywordOptIn: + """Create an instance of NumberRegistrationKeywordOptIn from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationKeywordOptIn.parse_obj(obj) + + _obj = NumberRegistrationKeywordOptIn.parse_obj( + {"call_to_action": obj.get("callToAction"), "keywords": obj.get("keywords")} + ) + return _obj diff --git a/models/number_registration_legal_entity_identifier.py b/models/number_registration_legal_entity_identifier.py new file mode 100644 index 0000000..6dfc477 --- /dev/null +++ b/models/number_registration_legal_entity_identifier.py @@ -0,0 +1,77 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, constr, validator +from models.number_registration_business_identifier import ( + NumberRegistrationBusinessIdentifier, +) + + +class NumberRegistrationLegalEntityIdentifier(NumberRegistrationBusinessIdentifier): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + id: constr(strict=True, max_length=20, min_length=20) = Field( + ..., description="The LEI identifier." + ) + __properties = ["id", "type"] + + @validator("id") + def id_validate_regular_expression(cls, v): + if not re.match(r"(\d{4})(00)([A-Z0-9]{12})(\d{2})", v): + raise ValueError( + r"must validate the regular expression /(\d{4})(00)([A-Z0-9]{12})(\d{2})/" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationLegalEntityIdentifier: + """Create an instance of NumberRegistrationLegalEntityIdentifier from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationLegalEntityIdentifier: + """Create an instance of NumberRegistrationLegalEntityIdentifier from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationLegalEntityIdentifier.parse_obj(obj) + + _obj = NumberRegistrationLegalEntityIdentifier.parse_obj( + {"id": obj.get("id"), "type": obj.get("type")} + ) + return _obj diff --git a/models/number_registration_network_status.py b/models/number_registration_network_status.py new file mode 100644 index 0000000..c7b0648 --- /dev/null +++ b/models/number_registration_network_status.py @@ -0,0 +1,109 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, validator + + +class NumberRegistrationNetworkStatus(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + network: Optional[StrictStr] = Field( + None, description="The network with which the campaign has been registered." + ) + state: Optional[StrictStr] = Field( + None, description="The state of the campaign's registration with this network." + ) + message_class: Optional[StrictStr] = Field( + None, + alias="messageClass", + description="This value is provided by some carriers to help determine throughput and daily limits. Refer to the [current documentation](https://www.infobip.com/docs/10dlc/how-vetting-works) for how to interpret these values as they may change over time.", + ) + __properties = ["network", "state", "messageClass"] + + @validator("network") + def network_validate_enum(cls, v): + if v is None: + return v + + if v not in ( + "ATT", + "T_MOBILE", + "VERIZON", + "US_CELLULAR", + "INTEROP", + "CLEARSKY", + "GOOGLE_VOICE", + ): + raise ValueError( + "must validate the enum values ('ATT', 'T_MOBILE', 'VERIZON', 'US_CELLULAR', 'INTEROP', 'CLEARSKY', 'GOOGLE_VOICE')" + ) + return v + + @validator("state") + def state_validate_enum(cls, v): + if v is None: + return v + + if v not in ("ACTIVE", "PENDING", "NOT_REGISTERED", "CERTIFICATION"): + raise ValueError( + "must validate the enum values ('ACTIVE', 'PENDING', 'NOT_REGISTERED', 'CERTIFICATION')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationNetworkStatus: + """Create an instance of NumberRegistrationNetworkStatus from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationNetworkStatus: + """Create an instance of NumberRegistrationNetworkStatus from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationNetworkStatus.parse_obj(obj) + + _obj = NumberRegistrationNetworkStatus.parse_obj( + { + "network": obj.get("network"), + "state": obj.get("state"), + "message_class": obj.get("messageClass"), + } + ) + return _obj diff --git a/models/number_registration_non_profit_brand.py b/models/number_registration_non_profit_brand.py new file mode 100644 index 0000000..416c6fe --- /dev/null +++ b/models/number_registration_non_profit_brand.py @@ -0,0 +1,176 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, constr, validator +from models.number_registration_address import NumberRegistrationAddress +from models.number_registration_brand import NumberRegistrationBrand +from models.number_registration_business_identifier import ( + NumberRegistrationBusinessIdentifier, +) + + +class NumberRegistrationNonProfitBrand(NumberRegistrationBrand): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + reference_id: Optional[StrictStr] = Field( + None, + alias="referenceId", + description="Unique user defined ID for the brand. While not required, it is recommended to supply a referenceId as the uniqueness constraint will help ensure a brand is not accidentally created multiple times. Subsequent create requests with the same referenceId will be rejected with an error.", + ) + legal_name: constr(strict=True, max_length=255, min_length=1) = Field( + ..., alias="legalName", description="The legal name of the brand." + ) + address: NumberRegistrationAddress = ... + country_code: constr(strict=True, max_length=2, min_length=1) = Field( + ..., alias="countryCode", description="The country where the brand is located." + ) + alternate_business_id: Optional[NumberRegistrationBusinessIdentifier] = Field( + None, alias="alternateBusinessId" + ) + support_email: constr(strict=True, max_length=100, min_length=1) = Field( + ..., + alias="supportEmail", + description="The business email address to contact about brand compliance issues. Must be a well formed email address that does not include a '=' character.", + ) + support_phone: constr(strict=True, max_length=16, min_length=3) = Field( + ..., + alias="supportPhone", + description="The business phone number to contact about brand compliance issues.", + ) + vertical: StrictStr = Field( + ..., description="The vertical in which the brand operates." + ) + tax_id: constr(strict=True, max_length=21, min_length=1) = Field( + ..., alias="taxId", description="The tax identifier (EIN) for the brand." + ) + __properties = [ + "id", + "name", + "website", + "createdDate", + "lastModifiedDate", + "type", + "referenceId", + "legalName", + "address", + "countryCode", + "alternateBusinessId", + "supportEmail", + "supportPhone", + "vertical", + "taxId", + ] + + @validator("support_phone") + def support_phone_validate_regular_expression(cls, v): + if not re.match(r"\+?[1-9]\d{1,14}", v): + raise ValueError(r"must validate the regular expression /\+?[1-9]\d{1,14}/") + return v + + @validator("vertical") + def vertical_validate_enum(cls, v): + if v not in ( + "AGRICULTURE", + "CONSTRUCTION_AND_MATERIALS", + "EDUCATION", + "ENERGY_AND_UTILITIES", + "ENTERTAINMENT", + "FINANCIAL_SERVICES", + "GAMBLING_AND_LOTTERY", + "HEALTHCARE_AND_LIFESCIENCES", + "HOSPITALITY", + "INFORMATION_TECHNOLOGY_SERVICES", + "INSURANCE", + "MANUFACTURING", + "MASS_MEDIA_AND_COMMUNICATION", + "NON_PROFIT_ORGANIZATION", + "PUBLIC_SECTOR", + "REAL_ESTATE", + "RETAIL_AND_CONSUMER_PRODUCTS", + ): + raise ValueError( + "must validate the enum values ('AGRICULTURE', 'CONSTRUCTION_AND_MATERIALS', 'EDUCATION', 'ENERGY_AND_UTILITIES', 'ENTERTAINMENT', 'FINANCIAL_SERVICES', 'GAMBLING_AND_LOTTERY', 'HEALTHCARE_AND_LIFESCIENCES', 'HOSPITALITY', 'INFORMATION_TECHNOLOGY_SERVICES', 'INSURANCE', 'MANUFACTURING', 'MASS_MEDIA_AND_COMMUNICATION', 'NON_PROFIT_ORGANIZATION', 'PUBLIC_SECTOR', 'REAL_ESTATE', 'RETAIL_AND_CONSUMER_PRODUCTS')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationNonProfitBrand: + """Create an instance of NumberRegistrationNonProfitBrand from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of address + if self.address: + _dict["address"] = self.address.to_dict() + # override the default output from pydantic by calling `to_dict()` of alternate_business_id + if self.alternate_business_id: + _dict["alternateBusinessId"] = self.alternate_business_id.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationNonProfitBrand: + """Create an instance of NumberRegistrationNonProfitBrand from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationNonProfitBrand.parse_obj(obj) + + _obj = NumberRegistrationNonProfitBrand.parse_obj( + { + "id": obj.get("id"), + "name": obj.get("name"), + "website": obj.get("website"), + "created_date": obj.get("createdDate"), + "last_modified_date": obj.get("lastModifiedDate"), + "type": obj.get("type"), + "reference_id": obj.get("referenceId"), + "legal_name": obj.get("legalName"), + "address": NumberRegistrationAddress.from_dict(obj.get("address")) + if obj.get("address") is not None + else None, + "country_code": obj.get("countryCode"), + "alternate_business_id": NumberRegistrationBusinessIdentifier.from_dict( + obj.get("alternateBusinessId") + ) + if obj.get("alternateBusinessId") is not None + else None, + "support_email": obj.get("supportEmail"), + "support_phone": obj.get("supportPhone"), + "vertical": obj.get("vertical"), + "tax_id": obj.get("taxId"), + } + ) + return _obj diff --git a/models/number_registration_number_preview.py b/models/number_registration_number_preview.py new file mode 100644 index 0000000..76c00ab --- /dev/null +++ b/models/number_registration_number_preview.py @@ -0,0 +1,71 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class NumberRegistrationNumberPreview(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + number_key: Optional[StrictStr] = Field(None, alias="numberKey") + number: Optional[StrictStr] = None + country_code: Optional[StrictStr] = Field(None, alias="countryCode") + __properties = ["numberKey", "number", "countryCode"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationNumberPreview: + """Create an instance of NumberRegistrationNumberPreview from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationNumberPreview: + """Create an instance of NumberRegistrationNumberPreview from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationNumberPreview.parse_obj(obj) + + _obj = NumberRegistrationNumberPreview.parse_obj( + { + "number_key": obj.get("numberKey"), + "number": obj.get("number"), + "country_code": obj.get("countryCode"), + } + ) + return _obj diff --git a/models/number_registration_opt_ins.py b/models/number_registration_opt_ins.py new file mode 100644 index 0000000..b700cf4 --- /dev/null +++ b/models/number_registration_opt_ins.py @@ -0,0 +1,111 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field +from models.number_registration_interactive_voice_response_opt_in import ( + NumberRegistrationInteractiveVoiceResponseOptIn, +) +from models.number_registration_keyword_opt_in import ( + NumberRegistrationKeywordOptIn, +) +from models.number_registration_verbal_opt_in import ( + NumberRegistrationVerbalOptIn, +) +from models.number_registration_web_opt_in import ( + NumberRegistrationWebOptIn, +) + + +class NumberRegistrationOptIns(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + keyword: Optional[NumberRegistrationKeywordOptIn] = None + web: Optional[NumberRegistrationWebOptIn] = None + verbal: Optional[NumberRegistrationVerbalOptIn] = None + interactive_voice_response: Optional[ + NumberRegistrationInteractiveVoiceResponseOptIn + ] = Field(None, alias="interactiveVoiceResponse") + __properties = ["keyword", "web", "verbal", "interactiveVoiceResponse"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationOptIns: + """Create an instance of NumberRegistrationOptIns from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of keyword + if self.keyword: + _dict["keyword"] = self.keyword.to_dict() + # override the default output from pydantic by calling `to_dict()` of web + if self.web: + _dict["web"] = self.web.to_dict() + # override the default output from pydantic by calling `to_dict()` of verbal + if self.verbal: + _dict["verbal"] = self.verbal.to_dict() + # override the default output from pydantic by calling `to_dict()` of interactive_voice_response + if self.interactive_voice_response: + _dict[ + "interactiveVoiceResponse" + ] = self.interactive_voice_response.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationOptIns: + """Create an instance of NumberRegistrationOptIns from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationOptIns.parse_obj(obj) + + _obj = NumberRegistrationOptIns.parse_obj( + { + "keyword": NumberRegistrationKeywordOptIn.from_dict(obj.get("keyword")) + if obj.get("keyword") is not None + else None, + "web": NumberRegistrationWebOptIn.from_dict(obj.get("web")) + if obj.get("web") is not None + else None, + "verbal": NumberRegistrationVerbalOptIn.from_dict(obj.get("verbal")) + if obj.get("verbal") is not None + else None, + "interactive_voice_response": NumberRegistrationInteractiveVoiceResponseOptIn.from_dict( + obj.get("interactiveVoiceResponse") + ) + if obj.get("interactiveVoiceResponse") is not None + else None, + } + ) + return _obj diff --git a/models/number_registration_page_info.py b/models/number_registration_page_info.py new file mode 100644 index 0000000..b115344 --- /dev/null +++ b/models/number_registration_page_info.py @@ -0,0 +1,80 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, conint + + +class NumberRegistrationPageInfo(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + page: conint(strict=True, ge=0) = Field(..., description="Requested page number.") + size: conint(strict=True, ge=1) = Field(..., description="Requested page size.") + total_pages: conint(strict=True, ge=0) = Field( + ..., + alias="totalPages", + description="The total number of pages of the results matching the requested parameters.", + ) + total_results: conint(strict=True, ge=0) = Field( + ..., + alias="totalResults", + description="The total number of the results matching the requested parameters.", + ) + __properties = ["page", "size", "totalPages", "totalResults"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationPageInfo: + """Create an instance of NumberRegistrationPageInfo from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationPageInfo: + """Create an instance of NumberRegistrationPageInfo from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationPageInfo.parse_obj(obj) + + _obj = NumberRegistrationPageInfo.parse_obj( + { + "page": obj.get("page"), + "size": obj.get("size"), + "total_pages": obj.get("totalPages"), + "total_results": obj.get("totalResults"), + } + ) + return _obj diff --git a/models/number_registration_page_response_brand.py b/models/number_registration_page_response_brand.py new file mode 100644 index 0000000..9b3888c --- /dev/null +++ b/models/number_registration_page_response_brand.py @@ -0,0 +1,92 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field +from models.number_registration_brand import NumberRegistrationBrand +from models.number_registration_page_info import ( + NumberRegistrationPageInfo, +) + + +class NumberRegistrationPageResponseBrand(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[NumberRegistrationBrand]] = Field( + None, description="The list of the results for this page." + ) + paging: Optional[NumberRegistrationPageInfo] = None + __properties = ["results", "paging"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationPageResponseBrand: + """Create an instance of NumberRegistrationPageResponseBrand from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + # override the default output from pydantic by calling `to_dict()` of paging + if self.paging: + _dict["paging"] = self.paging.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationPageResponseBrand: + """Create an instance of NumberRegistrationPageResponseBrand from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationPageResponseBrand.parse_obj(obj) + + _obj = NumberRegistrationPageResponseBrand.parse_obj( + { + "results": [ + NumberRegistrationBrand.from_dict(_item) + for _item in obj.get("results") + ] + if obj.get("results") is not None + else None, + "paging": NumberRegistrationPageInfo.from_dict(obj.get("paging")) + if obj.get("paging") is not None + else None, + } + ) + return _obj diff --git a/models/number_registration_page_response_brand_vet.py b/models/number_registration_page_response_brand_vet.py new file mode 100644 index 0000000..0ce2de2 --- /dev/null +++ b/models/number_registration_page_response_brand_vet.py @@ -0,0 +1,94 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field +from models.number_registration_brand_vet import ( + NumberRegistrationBrandVet, +) +from models.number_registration_page_info import ( + NumberRegistrationPageInfo, +) + + +class NumberRegistrationPageResponseBrandVet(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[NumberRegistrationBrandVet]] = Field( + None, description="The list of the results for this page." + ) + paging: Optional[NumberRegistrationPageInfo] = None + __properties = ["results", "paging"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationPageResponseBrandVet: + """Create an instance of NumberRegistrationPageResponseBrandVet from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + # override the default output from pydantic by calling `to_dict()` of paging + if self.paging: + _dict["paging"] = self.paging.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationPageResponseBrandVet: + """Create an instance of NumberRegistrationPageResponseBrandVet from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationPageResponseBrandVet.parse_obj(obj) + + _obj = NumberRegistrationPageResponseBrandVet.parse_obj( + { + "results": [ + NumberRegistrationBrandVet.from_dict(_item) + for _item in obj.get("results") + ] + if obj.get("results") is not None + else None, + "paging": NumberRegistrationPageInfo.from_dict(obj.get("paging")) + if obj.get("paging") is not None + else None, + } + ) + return _obj diff --git a/models/number_registration_page_response_campaign.py b/models/number_registration_page_response_campaign.py new file mode 100644 index 0000000..ce6ffec --- /dev/null +++ b/models/number_registration_page_response_campaign.py @@ -0,0 +1,94 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field +from models.number_registration_campaign import ( + NumberRegistrationCampaign, +) +from models.number_registration_page_info import ( + NumberRegistrationPageInfo, +) + + +class NumberRegistrationPageResponseCampaign(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[NumberRegistrationCampaign]] = Field( + None, description="The list of the results for this page." + ) + paging: Optional[NumberRegistrationPageInfo] = None + __properties = ["results", "paging"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationPageResponseCampaign: + """Create an instance of NumberRegistrationPageResponseCampaign from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + # override the default output from pydantic by calling `to_dict()` of paging + if self.paging: + _dict["paging"] = self.paging.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationPageResponseCampaign: + """Create an instance of NumberRegistrationPageResponseCampaign from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationPageResponseCampaign.parse_obj(obj) + + _obj = NumberRegistrationPageResponseCampaign.parse_obj( + { + "results": [ + NumberRegistrationCampaign.from_dict(_item) + for _item in obj.get("results") + ] + if obj.get("results") is not None + else None, + "paging": NumberRegistrationPageInfo.from_dict(obj.get("paging")) + if obj.get("paging") is not None + else None, + } + ) + return _obj diff --git a/models/number_registration_private_company_brand.py b/models/number_registration_private_company_brand.py new file mode 100644 index 0000000..05cc162 --- /dev/null +++ b/models/number_registration_private_company_brand.py @@ -0,0 +1,176 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, constr, validator +from models.number_registration_address import NumberRegistrationAddress +from models.number_registration_brand import NumberRegistrationBrand +from models.number_registration_business_identifier import ( + NumberRegistrationBusinessIdentifier, +) + + +class NumberRegistrationPrivateCompanyBrand(NumberRegistrationBrand): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + reference_id: Optional[StrictStr] = Field( + None, + alias="referenceId", + description="Unique user defined ID for the brand. While not required, it is recommended to supply a referenceId as the uniqueness constraint will help ensure a brand is not accidentally created multiple times. Subsequent create requests with the same referenceId will be rejected with an error.", + ) + legal_name: constr(strict=True, max_length=255, min_length=1) = Field( + ..., alias="legalName", description="The legal name of the brand." + ) + address: NumberRegistrationAddress = ... + country_code: constr(strict=True, max_length=2, min_length=1) = Field( + ..., alias="countryCode", description="The country where the brand is located." + ) + alternate_business_id: Optional[NumberRegistrationBusinessIdentifier] = Field( + None, alias="alternateBusinessId" + ) + support_email: constr(strict=True, max_length=100, min_length=1) = Field( + ..., + alias="supportEmail", + description="The business email address to contact about brand compliance issues. Must be a well formed email address that does not include a '=' character.", + ) + support_phone: constr(strict=True, max_length=16, min_length=3) = Field( + ..., + alias="supportPhone", + description="The business phone number to contact about brand compliance issues.", + ) + vertical: StrictStr = Field( + ..., description="The vertical in which the brand operates." + ) + tax_id: constr(strict=True, max_length=21, min_length=1) = Field( + ..., alias="taxId", description="The tax identifier (EIN) for the brand." + ) + __properties = [ + "id", + "name", + "website", + "createdDate", + "lastModifiedDate", + "type", + "referenceId", + "legalName", + "address", + "countryCode", + "alternateBusinessId", + "supportEmail", + "supportPhone", + "vertical", + "taxId", + ] + + @validator("support_phone") + def support_phone_validate_regular_expression(cls, v): + if not re.match(r"\+?[1-9]\d{1,14}", v): + raise ValueError(r"must validate the regular expression /\+?[1-9]\d{1,14}/") + return v + + @validator("vertical") + def vertical_validate_enum(cls, v): + if v not in ( + "AGRICULTURE", + "CONSTRUCTION_AND_MATERIALS", + "EDUCATION", + "ENERGY_AND_UTILITIES", + "ENTERTAINMENT", + "FINANCIAL_SERVICES", + "GAMBLING_AND_LOTTERY", + "HEALTHCARE_AND_LIFESCIENCES", + "HOSPITALITY", + "INFORMATION_TECHNOLOGY_SERVICES", + "INSURANCE", + "MANUFACTURING", + "MASS_MEDIA_AND_COMMUNICATION", + "NON_PROFIT_ORGANIZATION", + "PUBLIC_SECTOR", + "REAL_ESTATE", + "RETAIL_AND_CONSUMER_PRODUCTS", + ): + raise ValueError( + "must validate the enum values ('AGRICULTURE', 'CONSTRUCTION_AND_MATERIALS', 'EDUCATION', 'ENERGY_AND_UTILITIES', 'ENTERTAINMENT', 'FINANCIAL_SERVICES', 'GAMBLING_AND_LOTTERY', 'HEALTHCARE_AND_LIFESCIENCES', 'HOSPITALITY', 'INFORMATION_TECHNOLOGY_SERVICES', 'INSURANCE', 'MANUFACTURING', 'MASS_MEDIA_AND_COMMUNICATION', 'NON_PROFIT_ORGANIZATION', 'PUBLIC_SECTOR', 'REAL_ESTATE', 'RETAIL_AND_CONSUMER_PRODUCTS')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationPrivateCompanyBrand: + """Create an instance of NumberRegistrationPrivateCompanyBrand from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of address + if self.address: + _dict["address"] = self.address.to_dict() + # override the default output from pydantic by calling `to_dict()` of alternate_business_id + if self.alternate_business_id: + _dict["alternateBusinessId"] = self.alternate_business_id.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationPrivateCompanyBrand: + """Create an instance of NumberRegistrationPrivateCompanyBrand from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationPrivateCompanyBrand.parse_obj(obj) + + _obj = NumberRegistrationPrivateCompanyBrand.parse_obj( + { + "id": obj.get("id"), + "name": obj.get("name"), + "website": obj.get("website"), + "created_date": obj.get("createdDate"), + "last_modified_date": obj.get("lastModifiedDate"), + "type": obj.get("type"), + "reference_id": obj.get("referenceId"), + "legal_name": obj.get("legalName"), + "address": NumberRegistrationAddress.from_dict(obj.get("address")) + if obj.get("address") is not None + else None, + "country_code": obj.get("countryCode"), + "alternate_business_id": NumberRegistrationBusinessIdentifier.from_dict( + obj.get("alternateBusinessId") + ) + if obj.get("alternateBusinessId") is not None + else None, + "support_email": obj.get("supportEmail"), + "support_phone": obj.get("supportPhone"), + "vertical": obj.get("vertical"), + "tax_id": obj.get("taxId"), + } + ) + return _obj diff --git a/models/number_registration_public_company_brand.py b/models/number_registration_public_company_brand.py new file mode 100644 index 0000000..2dd0321 --- /dev/null +++ b/models/number_registration_public_company_brand.py @@ -0,0 +1,224 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, constr, validator +from models.number_registration_address import NumberRegistrationAddress +from models.number_registration_brand import NumberRegistrationBrand +from models.number_registration_business_identifier import ( + NumberRegistrationBusinessIdentifier, +) + + +class NumberRegistrationPublicCompanyBrand(NumberRegistrationBrand): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + reference_id: Optional[StrictStr] = Field( + None, + alias="referenceId", + description="Unique user defined ID for the brand. While not required, it is recommended to supply a referenceId as the uniqueness constraint will help ensure a brand is not accidentally created multiple times. Subsequent create requests with the same referenceId will be rejected with an error.", + ) + legal_name: constr(strict=True, max_length=255, min_length=1) = Field( + ..., alias="legalName", description="The legal name of the brand." + ) + address: NumberRegistrationAddress = ... + country_code: constr(strict=True, max_length=2, min_length=1) = Field( + ..., alias="countryCode", description="The country where the brand is located." + ) + alternate_business_id: Optional[NumberRegistrationBusinessIdentifier] = Field( + None, alias="alternateBusinessId" + ) + support_email: constr(strict=True, max_length=100, min_length=1) = Field( + ..., + alias="supportEmail", + description="The business email address to contact about brand compliance issues. Must be a well formed email address that does not include a '=' character.", + ) + support_phone: constr(strict=True, max_length=16, min_length=3) = Field( + ..., + alias="supportPhone", + description="The business phone number to contact about brand compliance issues.", + ) + vertical: StrictStr = Field( + ..., description="The vertical in which the brand operates." + ) + tax_id: constr(strict=True, max_length=21, min_length=1) = Field( + ..., alias="taxId", description="The tax identifier (EIN) for the brand." + ) + stock_exchange: StrictStr = Field( + ..., + alias="stockExchange", + description="The stock exchange where brand is listed.", + ) + stock_symbol: constr(strict=True, max_length=30, min_length=1) = Field( + ..., + alias="stockSymbol", + description="The ticker symbol for the brand on the exchange where it is listed.", + ) + __properties = [ + "id", + "name", + "website", + "createdDate", + "lastModifiedDate", + "type", + "referenceId", + "legalName", + "address", + "countryCode", + "alternateBusinessId", + "supportEmail", + "supportPhone", + "vertical", + "taxId", + "stockExchange", + "stockSymbol", + ] + + @validator("support_phone") + def support_phone_validate_regular_expression(cls, v): + if not re.match(r"\+?[1-9]\d{1,14}", v): + raise ValueError(r"must validate the regular expression /\+?[1-9]\d{1,14}/") + return v + + @validator("vertical") + def vertical_validate_enum(cls, v): + if v not in ( + "AGRICULTURE", + "CONSTRUCTION_AND_MATERIALS", + "EDUCATION", + "ENERGY_AND_UTILITIES", + "ENTERTAINMENT", + "FINANCIAL_SERVICES", + "GAMBLING_AND_LOTTERY", + "HEALTHCARE_AND_LIFESCIENCES", + "HOSPITALITY", + "INFORMATION_TECHNOLOGY_SERVICES", + "INSURANCE", + "MANUFACTURING", + "MASS_MEDIA_AND_COMMUNICATION", + "NON_PROFIT_ORGANIZATION", + "PUBLIC_SECTOR", + "REAL_ESTATE", + "RETAIL_AND_CONSUMER_PRODUCTS", + ): + raise ValueError( + "must validate the enum values ('AGRICULTURE', 'CONSTRUCTION_AND_MATERIALS', 'EDUCATION', 'ENERGY_AND_UTILITIES', 'ENTERTAINMENT', 'FINANCIAL_SERVICES', 'GAMBLING_AND_LOTTERY', 'HEALTHCARE_AND_LIFESCIENCES', 'HOSPITALITY', 'INFORMATION_TECHNOLOGY_SERVICES', 'INSURANCE', 'MANUFACTURING', 'MASS_MEDIA_AND_COMMUNICATION', 'NON_PROFIT_ORGANIZATION', 'PUBLIC_SECTOR', 'REAL_ESTATE', 'RETAIL_AND_CONSUMER_PRODUCTS')" + ) + return v + + @validator("stock_exchange") + def stock_exchange_validate_enum(cls, v): + if v not in ( + "AMEX", + "AMX", + "ASX", + "B3", + "BME", + "BSE", + "FRA", + "ICEX", + "JPX", + "JSE", + "KRX", + "LON", + "NASDAQ", + "NSE", + "NYSE", + "OMX", + "SEHK", + "SGX", + "SSE", + "STO", + "SWX", + "SZSE", + "TSX", + "TWSE", + "VSE", + ): + raise ValueError( + "must validate the enum values ('AMEX', 'AMX', 'ASX', 'B3', 'BME', 'BSE', 'FRA', 'ICEX', 'JPX', 'JSE', 'KRX', 'LON', 'NASDAQ', 'NSE', 'NYSE', 'OMX', 'SEHK', 'SGX', 'SSE', 'STO', 'SWX', 'SZSE', 'TSX', 'TWSE', 'VSE')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationPublicCompanyBrand: + """Create an instance of NumberRegistrationPublicCompanyBrand from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of address + if self.address: + _dict["address"] = self.address.to_dict() + # override the default output from pydantic by calling `to_dict()` of alternate_business_id + if self.alternate_business_id: + _dict["alternateBusinessId"] = self.alternate_business_id.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationPublicCompanyBrand: + """Create an instance of NumberRegistrationPublicCompanyBrand from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationPublicCompanyBrand.parse_obj(obj) + + _obj = NumberRegistrationPublicCompanyBrand.parse_obj( + { + "id": obj.get("id"), + "name": obj.get("name"), + "website": obj.get("website"), + "created_date": obj.get("createdDate"), + "last_modified_date": obj.get("lastModifiedDate"), + "type": obj.get("type"), + "reference_id": obj.get("referenceId"), + "legal_name": obj.get("legalName"), + "address": NumberRegistrationAddress.from_dict(obj.get("address")) + if obj.get("address") is not None + else None, + "country_code": obj.get("countryCode"), + "alternate_business_id": NumberRegistrationBusinessIdentifier.from_dict( + obj.get("alternateBusinessId") + ) + if obj.get("alternateBusinessId") is not None + else None, + "support_email": obj.get("supportEmail"), + "support_phone": obj.get("supportPhone"), + "vertical": obj.get("vertical"), + "tax_id": obj.get("taxId"), + "stock_exchange": obj.get("stockExchange"), + "stock_symbol": obj.get("stockSymbol"), + } + ) + return _obj diff --git a/models/number_registration_ten_dlc_campaign.py b/models/number_registration_ten_dlc_campaign.py new file mode 100644 index 0000000..c79ce82 --- /dev/null +++ b/models/number_registration_ten_dlc_campaign.py @@ -0,0 +1,286 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictBool, StrictStr, conlist, constr, validator +from models.number_registration_brand_preview import ( + NumberRegistrationBrandPreview, +) +from models.number_registration_campaign import ( + NumberRegistrationCampaign, +) +from models.number_registration_document_metadata import ( + NumberRegistrationDocumentMetadata, +) +from models.number_registration_number_preview import ( + NumberRegistrationNumberPreview, +) +from models.number_registration_opt_ins import NumberRegistrationOptIns + + +class NumberRegistrationTenDlcCampaign(NumberRegistrationCampaign): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + brand_id: StrictStr = Field( + ..., + alias="brandId", + description="The ID of the brand to use with the campaign.", + ) + program_summary: constr(strict=True, max_length=255, min_length=40) = Field( + ..., + alias="programSummary", + description="A brief description of the purpose of the campaign.", + ) + customer_care_email: constr(strict=True, max_length=255, min_length=1) = Field( + ..., + alias="customerCareEmail", + description="The email address the user may contact to get customer care. Must be a well formed email address that does not include a '=' character.", + ) + confirmation_message: constr(strict=True, max_length=255, min_length=20) = Field( + ..., + alias="confirmationMessage", + description="The message sent to the user after they have subscribed.", + ) + example_messages: conlist(StrictStr, max_items=5, min_items=1) = Field( + ..., + alias="exampleMessages", + description="The example message(s) a user may receive from this campaign. Each example message must be at least 20 characters long.", + ) + help_message: constr(strict=True, max_length=255, min_length=20) = Field( + ..., + alias="helpMessage", + description="The message sent to a user after they have asked for help.", + ) + stop_message: constr(strict=True, max_length=255, min_length=20) = Field( + ..., + alias="stopMessage", + description="The message sent to a user after they have asked to stop receiving messages.", + ) + message_types: List[StrictStr] = Field( + ..., + alias="messageTypes", + description="The message type(s) this campaign will use to send messages.", + unique_items=True, + ) + terms_and_conditions_url: constr( + strict=True, max_length=255, min_length=11 + ) = Field( + ..., + alias="termsAndConditionsUrl", + description="URL where the terms and conditions of the campaign are located.", + ) + terms_and_conditions_document_id: Optional[StrictStr] = Field( + None, alias="termsAndConditionsDocumentId" + ) + terms_and_conditions_document_preview: Optional[ + NumberRegistrationDocumentMetadata + ] = Field(None, alias="termsAndConditionsDocumentPreview") + opt_ins: NumberRegistrationOptIns = Field(..., alias="optIns") + brand_preview: Optional[NumberRegistrationBrandPreview] = Field( + None, alias="brandPreview" + ) + customer_care_phone: constr(strict=True, max_length=16, min_length=3) = Field( + ..., + alias="customerCarePhone", + description="The phone number the user may call to get customer care.", + ) + low_volume: StrictBool = Field( + ..., + alias="lowVolume", + description="Low volume campaigns are a lower cost campaign designed for low daily volume and non-time-sensitive messages. They are limited to 6 messages per minute on most carriers and no more than 5,000 messages per month on all carriers.", + ) + use_case: StrictStr = Field( + ..., alias="useCase", description="The use case for this campaign." + ) + number_keys: conlist(StrictStr, max_items=50, min_items=1) = Field( + ..., + alias="numberKeys", + description="The numberKey(s) of the numbers to use with the campaign.", + ) + number_previews: Optional[List[NumberRegistrationNumberPreview]] = Field( + None, + alias="numberPreviews", + description="The number(s) to use with the campaign. This property is read-only and ignored in POST/PUT calls.", + unique_items=True, + ) + __properties = [ + "id", + "referenceId", + "name", + "createdDate", + "lastModifiedDate", + "type", + "brandId", + "programSummary", + "customerCareEmail", + "confirmationMessage", + "exampleMessages", + "helpMessage", + "stopMessage", + "messageTypes", + "termsAndConditionsUrl", + "termsAndConditionsDocumentId", + "termsAndConditionsDocumentPreview", + "optIns", + "brandPreview", + "customerCarePhone", + "lowVolume", + "useCase", + "numberKeys", + "numberPreviews", + ] + + @validator("message_types") + def message_types_validate_enum(cls, v): + if v is None: + return + for enum_value in v: + if enum_value not in ("SMS", "MMS", "sms", "mms"): + raise ValueError("must validate the enum values ('SMS', 'MMS')") + return v + + @validator("customer_care_phone") + def customer_care_phone_validate_regular_expression(cls, v): + if not re.match(r"\+?[1-9]\d{1,14}", v): + raise ValueError(r"must validate the regular expression /\+?[1-9]\d{1,14}/") + return v + + @validator("use_case") + def use_case_validate_enum(cls, v): + if v not in ( + "ALERTS", + "CHAT", + "DONATION", + "EDUCATION", + "FRAUD_ALERTS", + "PROMOTIONAL_MARKETING", + "PUBLIC_SERVICE_ANNOUNCEMENT", + "SWEEPSTAKES_CONTEST", + "TWO_FACTOR_AUTH", + "VOTING_POLLING", + ): + raise ValueError( + "must validate the enum values ('ALERTS', 'CHAT', 'DONATION', 'EDUCATION', 'FRAUD_ALERTS', 'PROMOTIONAL_MARKETING', 'PUBLIC_SERVICE_ANNOUNCEMENT', 'SWEEPSTAKES_CONTEST', 'TWO_FACTOR_AUTH', 'VOTING_POLLING')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationTenDlcCampaign: + """Create an instance of NumberRegistrationTenDlcCampaign from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict( + by_alias=True, + exclude={ + "number_previews", + }, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of terms_and_conditions_document_preview + if self.terms_and_conditions_document_preview: + _dict[ + "termsAndConditionsDocumentPreview" + ] = self.terms_and_conditions_document_preview.to_dict() + # override the default output from pydantic by calling `to_dict()` of opt_ins + if self.opt_ins: + _dict["optIns"] = self.opt_ins.to_dict() + # override the default output from pydantic by calling `to_dict()` of brand_preview + if self.brand_preview: + _dict["brandPreview"] = self.brand_preview.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in number_previews (list) + _items = [] + if self.number_previews: + for _item in self.number_previews: + if _item: + _items.append(_item.to_dict()) + _dict["numberPreviews"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationTenDlcCampaign: + """Create an instance of NumberRegistrationTenDlcCampaign from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationTenDlcCampaign.parse_obj(obj) + + _obj = NumberRegistrationTenDlcCampaign.parse_obj( + { + "id": obj.get("id"), + "reference_id": obj.get("referenceId"), + "name": obj.get("name"), + "created_date": obj.get("createdDate"), + "last_modified_date": obj.get("lastModifiedDate"), + "type": obj.get("type"), + "brand_id": obj.get("brandId"), + "program_summary": obj.get("programSummary"), + "customer_care_email": obj.get("customerCareEmail"), + "confirmation_message": obj.get("confirmationMessage"), + "example_messages": obj.get("exampleMessages"), + "help_message": obj.get("helpMessage"), + "stop_message": obj.get("stopMessage"), + "message_types": obj.get("messageTypes"), + "terms_and_conditions_url": obj.get("termsAndConditionsUrl"), + "terms_and_conditions_document_id": obj.get( + "termsAndConditionsDocumentId" + ), + "terms_and_conditions_document_preview": NumberRegistrationDocumentMetadata.from_dict( + obj.get("termsAndConditionsDocumentPreview") + ) + if obj.get("termsAndConditionsDocumentPreview") is not None + else None, + "opt_ins": NumberRegistrationOptIns.from_dict(obj.get("optIns")) + if obj.get("optIns") is not None + else None, + "brand_preview": NumberRegistrationBrandPreview.from_dict( + obj.get("brandPreview") + ) + if obj.get("brandPreview") is not None + else None, + "customer_care_phone": obj.get("customerCarePhone"), + "low_volume": obj.get("lowVolume") + if obj.get("lowVolume") is not None + else False, + "use_case": obj.get("useCase"), + "number_keys": obj.get("numberKeys"), + "number_previews": [ + NumberRegistrationNumberPreview.from_dict(_item) + for _item in obj.get("numberPreviews") + ] + if obj.get("numberPreviews") is not None + else None, + } + ) + return _obj diff --git a/models/number_registration_update_brand_request.py b/models/number_registration_update_brand_request.py new file mode 100644 index 0000000..f1c0106 --- /dev/null +++ b/models/number_registration_update_brand_request.py @@ -0,0 +1,138 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr +from models.number_registration_address import NumberRegistrationAddress + + +class NumberRegistrationUpdateBrandRequest(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + address: Optional[NumberRegistrationAddress] = None + country_code: Optional[StrictStr] = Field( + None, alias="countryCode", description="The country where the brand is located." + ) + legal_name: Optional[StrictStr] = Field( + None, alias="legalName", description="The legal name of the brand." + ) + name: Optional[StrictStr] = Field( + None, description="The customer defined name of brand." + ) + support_email: Optional[StrictStr] = Field( + None, + alias="supportEmail", + description="The business email address to contact about brand compliance issues. Must be a well formed email address that does not include a '=' character.", + ) + support_phone: Optional[StrictStr] = Field( + None, + alias="supportPhone", + description="The business phone number to contact about brand compliance issues.", + ) + reference_id: Optional[StrictStr] = Field( + None, + alias="referenceId", + description="Unique user defined ID for the brand. While not required, it is recommended to supply a referenceId as the uniqueness constraint will help ensure a brand is not accidentally created multiple times. Subsequent create requests with the same referenceId will be rejected with an error.", + ) + tax_id: Optional[StrictStr] = Field( + None, alias="taxId", description="The tax identifier for the brand." + ) + vertical: Optional[StrictStr] = Field( + None, description="The vertical in which the brand operates." + ) + website: Optional[StrictStr] = Field(None, description="The website for the brand.") + stock_exchange: Optional[StrictStr] = Field( + None, + alias="stockExchange", + description="The stock exchange where brand is listed.", + ) + stock_symbol: Optional[StrictStr] = Field( + None, + alias="stockSymbol", + description="The ticker symbol for the brand on the exchange where it is listed.", + ) + __properties = [ + "address", + "countryCode", + "legalName", + "name", + "supportEmail", + "supportPhone", + "referenceId", + "taxId", + "vertical", + "website", + "stockExchange", + "stockSymbol", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationUpdateBrandRequest: + """Create an instance of NumberRegistrationUpdateBrandRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of address + if self.address: + _dict["address"] = self.address.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationUpdateBrandRequest: + """Create an instance of NumberRegistrationUpdateBrandRequest from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationUpdateBrandRequest.parse_obj(obj) + + _obj = NumberRegistrationUpdateBrandRequest.parse_obj( + { + "address": NumberRegistrationAddress.from_dict(obj.get("address")) + if obj.get("address") is not None + else None, + "country_code": obj.get("countryCode"), + "legal_name": obj.get("legalName"), + "name": obj.get("name"), + "support_email": obj.get("supportEmail"), + "support_phone": obj.get("supportPhone"), + "reference_id": obj.get("referenceId"), + "tax_id": obj.get("taxId"), + "vertical": obj.get("vertical"), + "website": obj.get("website"), + "stock_exchange": obj.get("stockExchange"), + "stock_symbol": obj.get("stockSymbol"), + } + ) + return _obj diff --git a/models/number_registration_update_campaign_request.py b/models/number_registration_update_campaign_request.py new file mode 100644 index 0000000..4a128bc --- /dev/null +++ b/models/number_registration_update_campaign_request.py @@ -0,0 +1,68 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, StrictStr, conlist + + +class NumberRegistrationUpdateCampaignRequest(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + number_keys: conlist(StrictStr, max_items=50, min_items=1) = Field( + ..., + alias="numberKeys", + description="The numberKey(s) of the numbers to use with the campaign.", + ) + __properties = ["numberKeys"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationUpdateCampaignRequest: + """Create an instance of NumberRegistrationUpdateCampaignRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationUpdateCampaignRequest: + """Create an instance of NumberRegistrationUpdateCampaignRequest from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationUpdateCampaignRequest.parse_obj(obj) + + _obj = NumberRegistrationUpdateCampaignRequest.parse_obj( + {"number_keys": obj.get("numberKeys")} + ) + return _obj diff --git a/models/number_registration_verbal_opt_in.py b/models/number_registration_verbal_opt_in.py new file mode 100644 index 0000000..2b9d861 --- /dev/null +++ b/models/number_registration_verbal_opt_in.py @@ -0,0 +1,68 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, constr + + +class NumberRegistrationVerbalOptIn(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + call_to_action: constr(strict=True, max_length=1024, min_length=20) = Field( + ..., + alias="callToAction", + description="The message sent to the user to tell them how to subscribe.", + ) + __properties = ["callToAction"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationVerbalOptIn: + """Create an instance of NumberRegistrationVerbalOptIn from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationVerbalOptIn: + """Create an instance of NumberRegistrationVerbalOptIn from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationVerbalOptIn.parse_obj(obj) + + _obj = NumberRegistrationVerbalOptIn.parse_obj( + {"call_to_action": obj.get("callToAction")} + ) + return _obj diff --git a/models/number_registration_web_opt_in.py b/models/number_registration_web_opt_in.py new file mode 100644 index 0000000..92e39ce --- /dev/null +++ b/models/number_registration_web_opt_in.py @@ -0,0 +1,69 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, constr + + +class NumberRegistrationWebOptIn(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + call_to_action: constr(strict=True, max_length=1024, min_length=20) = Field( + ..., + alias="callToAction", + description="The message sent to the user to tell them how to subscribe.", + ) + url: constr(strict=True, max_length=255, min_length=11) = ... + __properties = ["callToAction", "url"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberRegistrationWebOptIn: + """Create an instance of NumberRegistrationWebOptIn from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberRegistrationWebOptIn: + """Create an instance of NumberRegistrationWebOptIn from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberRegistrationWebOptIn.parse_obj(obj) + + _obj = NumberRegistrationWebOptIn.parse_obj( + {"call_to_action": obj.get("callToAction"), "url": obj.get("url")} + ) + return _obj diff --git a/models/number_response.py b/models/number_response.py new file mode 100644 index 0000000..a6b62e6 --- /dev/null +++ b/models/number_response.py @@ -0,0 +1,191 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictBool, StrictStr, constr, validator +from models.number_price import NumberPrice +from models.numbers_edit_permissions import NumbersEditPermissions +from models.numbers_voice_setup import NumbersVoiceSetup + + +class NumberResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + number_key: Optional[StrictStr] = Field(None, alias="numberKey") + number: Optional[StrictStr] = None + country: Optional[StrictStr] = None + country_name: Optional[StrictStr] = Field(None, alias="countryName") + type: Optional[StrictStr] = None + capabilities: Optional[List[StrictStr]] = None + shared: Optional[StrictBool] = None + price: Optional[NumberPrice] = None + network: Optional[StrictStr] = None + keywords: Optional[List[StrictStr]] = None + voice_setup: Optional[NumbersVoiceSetup] = Field(None, alias="voiceSetup") + reservation_status: Optional[StrictStr] = Field(None, alias="reservationStatus") + additional_setup_required: Optional[StrictBool] = Field( + None, alias="additionalSetupRequired" + ) + edit_permissions: Optional[NumbersEditPermissions] = Field( + None, alias="editPermissions" + ) + application_id: Optional[constr(strict=True, max_length=255, min_length=0)] = Field( + None, + alias="applicationId", + description="ID of the Application that would be associated with the number.", + ) + entity_id: Optional[constr(strict=True, max_length=255, min_length=0)] = Field( + None, + alias="entityId", + description="ID of the Entity that would be associated with the number.", + ) + __properties = [ + "numberKey", + "number", + "country", + "countryName", + "type", + "capabilities", + "shared", + "price", + "network", + "keywords", + "voiceSetup", + "reservationStatus", + "additionalSetupRequired", + "editPermissions", + "applicationId", + "entityId", + ] + + @validator("type") + def type_validate_enum(cls, v): + if v is None: + return v + + if v not in ( + "VIRTUAL_LONG_NUMBER", + "SHORT_CODE", + "SIM_HOSTING", + "VIRTUAL_SIM_HOSTING", + "VIRTUAL_LONG_NUMBER_CALL_TRIGGER", + "SHORT_CODE_USSD", + "WHATSAPP", + "VIBER", + "VIBER_VOICE", + "FACEBOOK", + ): + raise ValueError( + "must validate the enum values ('VIRTUAL_LONG_NUMBER', 'SHORT_CODE', 'SIM_HOSTING', 'VIRTUAL_SIM_HOSTING', 'VIRTUAL_LONG_NUMBER_CALL_TRIGGER', 'SHORT_CODE_USSD', 'WHATSAPP', 'VIBER', 'VIBER_VOICE', 'FACEBOOK')" + ) + return v + + @validator("capabilities") + def capabilities_validate_enum(cls, v): + if v is None: + return v + + for enum_value in v: + if enum_value not in ("SMS", "VOICE", "MMS"): + raise ValueError( + "must validate the enum values ('SMS', 'VOICE', 'MMS')" + ) + return v + + @validator("reservation_status") + def reservation_status_validate_enum(cls, v): + if v is None: + return v + + if v not in ("PENDING", "BILLING_FAILED", "ERROR"): + raise ValueError( + "must validate the enum values ('PENDING', 'BILLING_FAILED', 'ERROR')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumberResponse: + """Create an instance of NumberResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of price + if self.price: + _dict["price"] = self.price.to_dict() + # override the default output from pydantic by calling `to_dict()` of voice_setup + if self.voice_setup: + _dict["voiceSetup"] = self.voice_setup.to_dict() + # override the default output from pydantic by calling `to_dict()` of edit_permissions + if self.edit_permissions: + _dict["editPermissions"] = self.edit_permissions.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumberResponse: + """Create an instance of NumberResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumberResponse.parse_obj(obj) + + _obj = NumberResponse.parse_obj( + { + "number_key": obj.get("numberKey"), + "number": obj.get("number"), + "country": obj.get("country"), + "country_name": obj.get("countryName"), + "type": obj.get("type"), + "capabilities": obj.get("capabilities"), + "shared": obj.get("shared"), + "price": NumberPrice.from_dict(obj.get("price")) + if obj.get("price") is not None + else None, + "network": obj.get("network"), + "keywords": obj.get("keywords"), + "voice_setup": NumbersVoiceSetup.from_dict(obj.get("voiceSetup")) + if obj.get("voiceSetup") is not None + else None, + "reservation_status": obj.get("reservationStatus"), + "additional_setup_required": obj.get("additionalSetupRequired"), + "edit_permissions": NumbersEditPermissions.from_dict( + obj.get("editPermissions") + ) + if obj.get("editPermissions") is not None + else None, + "application_id": obj.get("applicationId"), + "entity_id": obj.get("entityId"), + } + ) + return _obj diff --git a/models/numbers_auto_response_action.py b/models/numbers_auto_response_action.py new file mode 100644 index 0000000..009b922 --- /dev/null +++ b/models/numbers_auto_response_action.py @@ -0,0 +1,93 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, constr +from models.numbers_delivery_time_window import NumbersDeliveryTimeWindow +from models.numbers_mo_non_forward_action import ( + NumbersMoNonForwardAction, +) + + +class NumbersAutoResponseAction(NumbersMoNonForwardAction): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + message: constr(strict=True, max_length=1080, min_length=0) = Field( + ..., description="Text that will be sent as response message." + ) + sender: Optional[StrictStr] = Field( + "null", + description="If set, response message will be sent from this sender, not from MO receiver.", + ) + delivery_time_window: Optional[NumbersDeliveryTimeWindow] = Field( + None, alias="deliveryTimeWindow" + ) + __properties = ["type", "editable", "message", "sender", "deliveryTimeWindow"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersAutoResponseAction: + """Create an instance of NumbersAutoResponseAction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of delivery_time_window + if self.delivery_time_window: + _dict["deliveryTimeWindow"] = self.delivery_time_window.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersAutoResponseAction: + """Create an instance of NumbersAutoResponseAction from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersAutoResponseAction.parse_obj(obj) + + _obj = NumbersAutoResponseAction.parse_obj( + { + "type": obj.get("type"), + "editable": obj.get("editable"), + "message": obj.get("message"), + "sender": obj.get("sender") + if obj.get("sender") is not None + else "null", + "delivery_time_window": NumbersDeliveryTimeWindow.from_dict( + obj.get("deliveryTimeWindow") + ) + if obj.get("deliveryTimeWindow") is not None + else None, + } + ) + return _obj diff --git a/models/numbers_block_action.py b/models/numbers_block_action.py new file mode 100644 index 0000000..bc524fc --- /dev/null +++ b/models/numbers_block_action.py @@ -0,0 +1,79 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, StrictStr, validator +from models.numbers_mo_non_forward_action import ( + NumbersMoNonForwardAction, +) + + +class NumbersBlockAction(NumbersMoNonForwardAction): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + block_type: StrictStr = Field(..., alias="blockType", description="Block type.") + __properties = ["type", "editable", "blockType"] + + @validator("block_type") + def block_type_validate_enum(cls, v): + if v not in ("FROM_ANY_SENDER", "FROM_SENDER"): + raise ValueError( + "must validate the enum values ('FROM_ANY_SENDER', 'FROM_SENDER')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersBlockAction: + """Create an instance of NumbersBlockAction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersBlockAction: + """Create an instance of NumbersBlockAction from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersBlockAction.parse_obj(obj) + + _obj = NumbersBlockAction.parse_obj( + { + "type": obj.get("type"), + "editable": obj.get("editable"), + "block_type": obj.get("blockType"), + } + ) + return _obj diff --git a/models/numbers_delivery_time_window.py b/models/numbers_delivery_time_window.py new file mode 100644 index 0000000..86e52db --- /dev/null +++ b/models/numbers_delivery_time_window.py @@ -0,0 +1,116 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, conlist, validator + + +class NumbersDeliveryTimeWindow(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + var_from: StrictStr = Field( + ..., + alias="from", + description="Exact time of day in which the sending can start. Consists of hour and minute properties, both mandatory. Time is expressed in the UTC time zone. Formatted as HH:mm.", + ) + to: StrictStr = Field( + ..., + description="Exact time of day in which the sending will end. Consists of an hour and minute properties, both mandatory. Time is expressed in the UTC time zone. Formatted as HH:mm.", + ) + days: conlist(StrictStr, max_items=7, min_items=1) = Field( + ..., description="Days which are included in the delivery time window." + ) + delivery_time_zone: Optional[StrictStr] = Field( + None, + alias="deliveryTimeZone", + description="Sending time zone. If null USER_TIME_ZONE will be set.", + ) + __properties = ["from", "to", "days", "deliveryTimeZone"] + + @validator("days") + def days_validate_enum(cls, v): + if v is None: + return + for enum_value in v: + if enum_value not in ( + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY", + "SUNDAY", + ): + raise ValueError( + "must validate the enum values ('MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY')" + ) + return v + + @validator("delivery_time_zone") + def delivery_time_zone_validate_enum(cls, v): + if v is None: + return v + + if v not in ("USER_TIME_ZONE", "DESTINATION_TIME_ZONE"): + raise ValueError( + "must validate the enum values ('USER_TIME_ZONE', 'DESTINATION_TIME_ZONE')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersDeliveryTimeWindow: + """Create an instance of NumbersDeliveryTimeWindow from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersDeliveryTimeWindow: + """Create an instance of NumbersDeliveryTimeWindow from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersDeliveryTimeWindow.parse_obj(obj) + + _obj = NumbersDeliveryTimeWindow.parse_obj( + { + "var_from": obj.get("from"), + "to": obj.get("to"), + "days": obj.get("days"), + "delivery_time_zone": obj.get("deliveryTimeZone"), + } + ) + return _obj diff --git a/models/numbers_edit_permissions.py b/models/numbers_edit_permissions.py new file mode 100644 index 0000000..008a3a3 --- /dev/null +++ b/models/numbers_edit_permissions.py @@ -0,0 +1,71 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictBool + + +class NumbersEditPermissions(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + can_edit_number: Optional[StrictBool] = Field(None, alias="canEditNumber") + can_edit_configuration: Optional[StrictBool] = Field( + None, alias="canEditConfiguration" + ) + __properties = ["canEditNumber", "canEditConfiguration"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersEditPermissions: + """Create an instance of NumbersEditPermissions from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersEditPermissions: + """Create an instance of NumbersEditPermissions from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersEditPermissions.parse_obj(obj) + + _obj = NumbersEditPermissions.parse_obj( + { + "can_edit_number": obj.get("canEditNumber"), + "can_edit_configuration": obj.get("canEditConfiguration"), + } + ) + return _obj diff --git a/models/numbers_forward_to_ivr_action_details.py b/models/numbers_forward_to_ivr_action_details.py new file mode 100644 index 0000000..331c102 --- /dev/null +++ b/models/numbers_forward_to_ivr_action_details.py @@ -0,0 +1,69 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, StrictStr +from models.numbers_voice_action_details import NumbersVoiceActionDetails + + +class NumbersForwardToIvrActionDetails(NumbersVoiceActionDetails): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + scenario_key: StrictStr = Field(..., alias="scenarioKey") + __properties = ["type", "description", "scenarioKey"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersForwardToIvrActionDetails: + """Create an instance of NumbersForwardToIvrActionDetails from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersForwardToIvrActionDetails: + """Create an instance of NumbersForwardToIvrActionDetails from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersForwardToIvrActionDetails.parse_obj(obj) + + _obj = NumbersForwardToIvrActionDetails.parse_obj( + { + "type": obj.get("type"), + "description": obj.get("description"), + "scenario_key": obj.get("scenarioKey"), + } + ) + return _obj diff --git a/models/numbers_forward_to_subscription_details.py b/models/numbers_forward_to_subscription_details.py new file mode 100644 index 0000000..62c8a88 --- /dev/null +++ b/models/numbers_forward_to_subscription_details.py @@ -0,0 +1,64 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel +from models.numbers_voice_action_details import NumbersVoiceActionDetails + + +class NumbersForwardToSubscriptionDetails(NumbersVoiceActionDetails): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + __properties = ["type", "description"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersForwardToSubscriptionDetails: + """Create an instance of NumbersForwardToSubscriptionDetails from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersForwardToSubscriptionDetails: + """Create an instance of NumbersForwardToSubscriptionDetails from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersForwardToSubscriptionDetails.parse_obj(obj) + + _obj = NumbersForwardToSubscriptionDetails.parse_obj( + {"type": obj.get("type"), "description": obj.get("description")} + ) + return _obj diff --git a/models/numbers_http_forward_action.py b/models/numbers_http_forward_action.py new file mode 100644 index 0000000..df8d079 --- /dev/null +++ b/models/numbers_http_forward_action.py @@ -0,0 +1,95 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, validator +from models.numbers_mo_action import NumbersMoAction + + +class NumbersHttpForwardAction(NumbersMoAction): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + url: StrictStr = Field( + ..., description="Specifies URL where message will be pushed." + ) + http_method: StrictStr = Field( + ..., alias="httpMethod", description="Specifies push format." + ) + content_type: Optional[StrictStr] = Field( + None, alias="contentType", description="Specifies content type." + ) + __properties = ["type", "description", "url", "httpMethod", "contentType"] + + @validator("http_method") + def http_method_validate_enum(cls, v): + if v not in ("GET", "POST"): + raise ValueError("must validate the enum values ('GET', 'POST')") + return v + + @validator("content_type") + def content_type_validate_enum(cls, v): + if v is None: + return v + + if v not in ("JSON", "XML"): + raise ValueError("must validate the enum values ('JSON', 'XML')") + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersHttpForwardAction: + """Create an instance of NumbersHttpForwardAction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersHttpForwardAction: + """Create an instance of NumbersHttpForwardAction from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersHttpForwardAction.parse_obj(obj) + + _obj = NumbersHttpForwardAction.parse_obj( + { + "type": obj.get("type"), + "description": obj.get("description"), + "url": obj.get("url"), + "http_method": obj.get("httpMethod"), + "content_type": obj.get("contentType"), + } + ) + return _obj diff --git a/models/numbers_mail_forward_action.py b/models/numbers_mail_forward_action.py new file mode 100644 index 0000000..b02fab3 --- /dev/null +++ b/models/numbers_mail_forward_action.py @@ -0,0 +1,69 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, StrictStr +from models.numbers_mo_action import NumbersMoAction + + +class NumbersMailForwardAction(NumbersMoAction): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + mail: StrictStr = Field(..., description="Specifies e-mail destination.") + __properties = ["type", "description", "mail"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersMailForwardAction: + """Create an instance of NumbersMailForwardAction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersMailForwardAction: + """Create an instance of NumbersMailForwardAction from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersMailForwardAction.parse_obj(obj) + + _obj = NumbersMailForwardAction.parse_obj( + { + "type": obj.get("type"), + "description": obj.get("description"), + "mail": obj.get("mail"), + } + ) + return _obj diff --git a/models/numbers_mo_action.py b/models/numbers_mo_action.py new file mode 100644 index 0000000..32e03bc --- /dev/null +++ b/models/numbers_mo_action.py @@ -0,0 +1,154 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json +import models + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, validator + + +class NumbersMoAction(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + type: Optional[StrictStr] = Field( + None, + description="Defines action type. It is not possible to create new action type.", + ) + description: Optional[StrictStr] = Field( + None, description="Additional action description." + ) + __properties = ["type", "description"] + + @validator("type") + def type_validate_enum(cls, v): + if v is None: + return v + + if v not in ( + "PULL", + "HTTP_FORWARD", + "SMPP_FORWARD", + "MAIL_FORWARD", + "NO_ACTION", + "BLOCK", + "AUTORESPONSE", + "USSD", + "SEND_BULK_MT", + "EMAIL_TO_SMS_FORWARD", + "CNS_FWD", + "USE_CONVERSATIONS", + "FORWARD_TO_PSTN", + "FORWARD_TO_IP", + "FORWARD_TO_SOFT_PHONE", + "FORWARD_TO_IVR", + "VOICE_NUMBER_MASKING", + "VOICE_CALL_DROP", + "FORWARD_TO_WEBRTC", + "VOICE_FORWARD_TO_CONVERSATIONS", + "VOICE_FORWARD_TO_CONVERSATIONS_WITH_FLOW", + "CALL_FORWARD_TO_APPLICATION", + "FORWARD_TO_SUBSCRIPTION", + "OTHER", + ): + raise ValueError( + "must validate the enum values ('PULL', 'HTTP_FORWARD', 'SMPP_FORWARD', 'MAIL_FORWARD', 'NO_ACTION', 'BLOCK', 'AUTORESPONSE', 'USSD', 'SEND_BULK_MT', 'EMAIL_TO_SMS_FORWARD', 'CNS_FWD', 'USE_CONVERSATIONS', 'FORWARD_TO_PSTN', 'FORWARD_TO_IP', 'FORWARD_TO_SOFT_PHONE', 'FORWARD_TO_IVR', 'VOICE_NUMBER_MASKING', 'VOICE_CALL_DROP', 'FORWARD_TO_WEBRTC', 'VOICE_FORWARD_TO_CONVERSATIONS', 'VOICE_FORWARD_TO_CONVERSATIONS_WITH_FLOW', 'CALL_FORWARD_TO_APPLICATION', 'FORWARD_TO_SUBSCRIPTION', 'OTHER')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + # JSON field name that stores the object type + __discriminator_property_name = "type" + + # discriminator mappings + __discriminator_value_class_map = { + "HTTP_FORWARD": "NumbersHttpForwardAction", + "MAIL_FORWARD": "NumbersMailForwardAction", + "NO_ACTION": "NumbersNoAction", + "NumbersHttpForwardAction": "NumbersHttpForwardAction", + "NumbersMailForwardAction": "NumbersMailForwardAction", + "NumbersNoAction": "NumbersNoAction", + "NumbersPullAction": "NumbersPullAction", + "NumbersSmppForwardAction": "NumbersSmppForwardAction", + "PULL": "NumbersPullAction", + "SMPP_FORWARD": "NumbersSmppForwardAction", + } + + @classmethod + def get_discriminator_value(cls, obj: dict) -> str: + """Returns the discriminator value (object type) of the data""" + discriminator_value = obj[cls.__discriminator_property_name] + if discriminator_value: + return cls.__discriminator_value_class_map.get(discriminator_value) + else: + return None + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json( + cls, json_str: str + ) -> Union( + NumbersHttpForwardAction, + NumbersMailForwardAction, + NumbersNoAction, + NumbersPullAction, + NumbersSmppForwardAction, + ): + """Create an instance of NumbersMoAction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict( + cls, obj: dict + ) -> Union( + NumbersHttpForwardAction, + NumbersMailForwardAction, + NumbersNoAction, + NumbersPullAction, + NumbersSmppForwardAction, + ): + """Create an instance of NumbersMoAction from a dict""" + # look up the object type based on discriminator mapping + object_type = cls.get_discriminator_value(obj) + if object_type: + klass = getattr(models, object_type) + return klass.from_dict(obj) + else: + raise ValueError( + "NumbersMoAction failed to lookup discriminator value from " + + json.dumps(obj) + + ". Discriminator property name: " + + cls.__discriminator_property_name + + ", mapping: " + + json.dumps(cls.__discriminator_value_class_map) + ) diff --git a/models/numbers_mo_configuration.py b/models/numbers_mo_configuration.py new file mode 100644 index 0000000..194f2c5 --- /dev/null +++ b/models/numbers_mo_configuration.py @@ -0,0 +1,136 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictStr, constr +from models.numbers_mo_action import NumbersMoAction +from models.numbers_mo_non_forward_action import ( + NumbersMoNonForwardAction, +) +from models.numbers_use_conversation import NumbersUseConversation + + +class NumbersMoConfiguration(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + keyword: Optional[constr(strict=True, max_length=50, min_length=0)] = Field( + None, description="Configuration keyword." + ) + action: NumbersMoAction = ... + use_conversation: Optional[NumbersUseConversation] = Field( + None, alias="useConversation" + ) + other_actions_details: Optional[List[NumbersMoNonForwardAction]] = Field( + None, + alias="otherActionsDetails", + description="List of other configured actions on this keyword. Ignored in POST/PUT calls.", + ) + other_actions: Optional[List[StrictStr]] = Field( + None, + alias="otherActions", + description="List of other configured action types/names on this keyword. Ignored in POST/PUT calls.", + ) + application_id: Optional[constr(strict=True, max_length=255, min_length=0)] = Field( + None, + alias="applicationId", + description="ID of the Application that would be associated with the configuration.", + ) + entity_id: Optional[constr(strict=True, max_length=255, min_length=0)] = Field( + None, + alias="entityId", + description="ID of the Entity that would be associated with the configuration.", + ) + __properties = [ + "keyword", + "action", + "useConversation", + "otherActionsDetails", + "otherActions", + "applicationId", + "entityId", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersMoConfiguration: + """Create an instance of NumbersMoConfiguration from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of action + if self.action: + _dict["action"] = self.action.to_dict() + # override the default output from pydantic by calling `to_dict()` of use_conversation + if self.use_conversation: + _dict["useConversation"] = self.use_conversation.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in other_actions_details (list) + _items = [] + if self.other_actions_details: + for _item in self.other_actions_details: + if _item: + _items.append(_item.to_dict()) + _dict["otherActionsDetails"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersMoConfiguration: + """Create an instance of NumbersMoConfiguration from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersMoConfiguration.parse_obj(obj) + + _obj = NumbersMoConfiguration.parse_obj( + { + "keyword": obj.get("keyword"), + "action": NumbersMoAction.from_dict(obj.get("action")) + if obj.get("action") is not None + else None, + "use_conversation": NumbersUseConversation.from_dict( + obj.get("useConversation") + ) + if obj.get("useConversation") is not None + else None, + "other_actions_details": [ + NumbersMoNonForwardAction.from_dict(_item) + for _item in obj.get("otherActionsDetails") + ] + if obj.get("otherActionsDetails") is not None + else None, + "other_actions": obj.get("otherActions"), + "application_id": obj.get("applicationId"), + "entity_id": obj.get("entityId"), + } + ) + return _obj diff --git a/models/numbers_mo_configurations.py b/models/numbers_mo_configurations.py new file mode 100644 index 0000000..ec34c77 --- /dev/null +++ b/models/numbers_mo_configurations.py @@ -0,0 +1,84 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictInt +from models.numbers_stored_mo_configuration import ( + NumbersStoredMoConfiguration, +) + + +class NumbersMoConfigurations(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + configurations: Optional[List[NumbersStoredMoConfiguration]] = None + total_count: Optional[StrictInt] = Field(None, alias="totalCount") + __properties = ["configurations", "totalCount"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersMoConfigurations: + """Create an instance of NumbersMoConfigurations from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in configurations (list) + _items = [] + if self.configurations: + for _item in self.configurations: + if _item: + _items.append(_item.to_dict()) + _dict["configurations"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersMoConfigurations: + """Create an instance of NumbersMoConfigurations from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersMoConfigurations.parse_obj(obj) + + _obj = NumbersMoConfigurations.parse_obj( + { + "configurations": [ + NumbersStoredMoConfiguration.from_dict(_item) + for _item in obj.get("configurations") + ] + if obj.get("configurations") is not None + else None, + "total_count": obj.get("totalCount"), + } + ) + return _obj diff --git a/models/numbers_mo_non_forward_action.py b/models/numbers_mo_non_forward_action.py new file mode 100644 index 0000000..de620f1 --- /dev/null +++ b/models/numbers_mo_non_forward_action.py @@ -0,0 +1,134 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json +import models + + +from typing import Optional +from pydantic import BaseModel, Field, StrictBool, StrictStr, validator + + +class NumbersMoNonForwardAction(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + type: StrictStr = Field( + ..., + description="Defines action type. It is not possible to create new action type.", + ) + editable: Optional[StrictBool] = Field( + None, + description="Flag which indicates if given action is editable. Ignored on POST/PUT requests.", + ) + __properties = ["type", "editable"] + + @validator("type") + def type_validate_enum(cls, v): + if v not in ( + "PULL", + "HTTP_FORWARD", + "SMPP_FORWARD", + "MAIL_FORWARD", + "NO_ACTION", + "BLOCK", + "AUTORESPONSE", + "USSD", + "SEND_BULK_MT", + "EMAIL_TO_SMS_FORWARD", + "CNS_FWD", + "USE_CONVERSATIONS", + "FORWARD_TO_PSTN", + "FORWARD_TO_IP", + "FORWARD_TO_SOFT_PHONE", + "FORWARD_TO_IVR", + "VOICE_NUMBER_MASKING", + "VOICE_CALL_DROP", + "FORWARD_TO_WEBRTC", + "VOICE_FORWARD_TO_CONVERSATIONS", + "VOICE_FORWARD_TO_CONVERSATIONS_WITH_FLOW", + "CALL_FORWARD_TO_APPLICATION", + "FORWARD_TO_SUBSCRIPTION", + "OTHER", + ): + raise ValueError( + "must validate the enum values ('PULL', 'HTTP_FORWARD', 'SMPP_FORWARD', 'MAIL_FORWARD', 'NO_ACTION', 'BLOCK', 'AUTORESPONSE', 'USSD', 'SEND_BULK_MT', 'EMAIL_TO_SMS_FORWARD', 'CNS_FWD', 'USE_CONVERSATIONS', 'FORWARD_TO_PSTN', 'FORWARD_TO_IP', 'FORWARD_TO_SOFT_PHONE', 'FORWARD_TO_IVR', 'VOICE_NUMBER_MASKING', 'VOICE_CALL_DROP', 'FORWARD_TO_WEBRTC', 'VOICE_FORWARD_TO_CONVERSATIONS', 'VOICE_FORWARD_TO_CONVERSATIONS_WITH_FLOW', 'CALL_FORWARD_TO_APPLICATION', 'FORWARD_TO_SUBSCRIPTION', 'OTHER')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + # JSON field name that stores the object type + __discriminator_property_name = "type" + + # discriminator mappings + __discriminator_value_class_map = { + "AUTORESPONSE": "NumbersAutoResponseAction", + "BLOCK": "NumbersBlockAction", + "NumbersAutoResponseAction": "NumbersAutoResponseAction", + "NumbersBlockAction": "NumbersBlockAction", + } + + @classmethod + def get_discriminator_value(cls, obj: dict) -> str: + """Returns the discriminator value (object type) of the data""" + discriminator_value = obj[cls.__discriminator_property_name] + if discriminator_value: + return cls.__discriminator_value_class_map.get(discriminator_value) + else: + return None + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json( + cls, json_str: str + ) -> Union(NumbersAutoResponseAction, NumbersBlockAction): + """Create an instance of NumbersMoNonForwardAction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict( + cls, obj: dict + ) -> Union(NumbersAutoResponseAction, NumbersBlockAction): + """Create an instance of NumbersMoNonForwardAction from a dict""" + # look up the object type based on discriminator mapping + object_type = cls.get_discriminator_value(obj) + if object_type: + klass = getattr(models, object_type) + return klass.from_dict(obj) + else: + raise ValueError( + "NumbersMoNonForwardAction failed to lookup discriminator value from " + + json.dumps(obj) + + ". Discriminator property name: " + + cls.__discriminator_property_name + + ", mapping: " + + json.dumps(cls.__discriminator_value_class_map) + ) diff --git a/models/numbers_no_action.py b/models/numbers_no_action.py new file mode 100644 index 0000000..cb0f2b4 --- /dev/null +++ b/models/numbers_no_action.py @@ -0,0 +1,64 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel +from models.numbers_mo_action import NumbersMoAction + + +class NumbersNoAction(NumbersMoAction): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + __properties = ["type", "description"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersNoAction: + """Create an instance of NumbersNoAction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersNoAction: + """Create an instance of NumbersNoAction from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersNoAction.parse_obj(obj) + + _obj = NumbersNoAction.parse_obj( + {"type": obj.get("type"), "description": obj.get("description")} + ) + return _obj diff --git a/models/numbers_pull_action.py b/models/numbers_pull_action.py new file mode 100644 index 0000000..93bff49 --- /dev/null +++ b/models/numbers_pull_action.py @@ -0,0 +1,64 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel +from models.numbers_mo_action import NumbersMoAction + + +class NumbersPullAction(NumbersMoAction): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + __properties = ["type", "description"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersPullAction: + """Create an instance of NumbersPullAction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersPullAction: + """Create an instance of NumbersPullAction from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersPullAction.parse_obj(obj) + + _obj = NumbersPullAction.parse_obj( + {"type": obj.get("type"), "description": obj.get("description")} + ) + return _obj diff --git a/models/numbers_purchase_number_request.py b/models/numbers_purchase_number_request.py new file mode 100644 index 0000000..6ce4222 --- /dev/null +++ b/models/numbers_purchase_number_request.py @@ -0,0 +1,81 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, constr + + +class NumbersPurchaseNumberRequest(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + number_key: Optional[StrictStr] = Field(None, alias="numberKey") + number: Optional[StrictStr] = None + application_id: Optional[constr(strict=True, max_length=255, min_length=0)] = Field( + None, + alias="applicationId", + description="ID of the Application that would be associated with the number.", + ) + entity_id: Optional[constr(strict=True, max_length=255, min_length=0)] = Field( + None, + alias="entityId", + description="ID of the Entity that would be associated with the number.", + ) + __properties = ["numberKey", "number", "applicationId", "entityId"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersPurchaseNumberRequest: + """Create an instance of NumbersPurchaseNumberRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersPurchaseNumberRequest: + """Create an instance of NumbersPurchaseNumberRequest from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersPurchaseNumberRequest.parse_obj(obj) + + _obj = NumbersPurchaseNumberRequest.parse_obj( + { + "number_key": obj.get("numberKey"), + "number": obj.get("number"), + "application_id": obj.get("applicationId"), + "entity_id": obj.get("entityId"), + } + ) + return _obj diff --git a/models/numbers_response.py b/models/numbers_response.py new file mode 100644 index 0000000..c5cf22d --- /dev/null +++ b/models/numbers_response.py @@ -0,0 +1,81 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictInt +from models.number_response import NumberResponse + + +class NumbersResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + numbers: Optional[List[NumberResponse]] = None + number_count: Optional[StrictInt] = Field(None, alias="numberCount") + __properties = ["numbers", "numberCount"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersResponse: + """Create an instance of NumbersResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in numbers (list) + _items = [] + if self.numbers: + for _item in self.numbers: + if _item: + _items.append(_item.to_dict()) + _dict["numbers"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersResponse: + """Create an instance of NumbersResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersResponse.parse_obj(obj) + + _obj = NumbersResponse.parse_obj( + { + "numbers": [ + NumberResponse.from_dict(_item) for _item in obj.get("numbers") + ] + if obj.get("numbers") is not None + else None, + "number_count": obj.get("numberCount"), + } + ) + return _obj diff --git a/models/numbers_smpp_forward_action.py b/models/numbers_smpp_forward_action.py new file mode 100644 index 0000000..a0a29d0 --- /dev/null +++ b/models/numbers_smpp_forward_action.py @@ -0,0 +1,64 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel +from models.numbers_mo_action import NumbersMoAction + + +class NumbersSmppForwardAction(NumbersMoAction): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + __properties = ["type", "description"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersSmppForwardAction: + """Create an instance of NumbersSmppForwardAction from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersSmppForwardAction: + """Create an instance of NumbersSmppForwardAction from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersSmppForwardAction.parse_obj(obj) + + _obj = NumbersSmppForwardAction.parse_obj( + {"type": obj.get("type"), "description": obj.get("description")} + ) + return _obj diff --git a/models/numbers_stored_mo_configuration.py b/models/numbers_stored_mo_configuration.py new file mode 100644 index 0000000..a00df12 --- /dev/null +++ b/models/numbers_stored_mo_configuration.py @@ -0,0 +1,139 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictStr, constr +from models.numbers_mo_action import NumbersMoAction +from models.numbers_mo_non_forward_action import ( + NumbersMoNonForwardAction, +) +from models.numbers_use_conversation import NumbersUseConversation + + +class NumbersStoredMoConfiguration(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + keyword: Optional[constr(strict=True, max_length=50, min_length=0)] = Field( + None, description="Configuration keyword." + ) + action: NumbersMoAction = ... + use_conversation: Optional[NumbersUseConversation] = Field( + None, alias="useConversation" + ) + other_actions_details: Optional[List[NumbersMoNonForwardAction]] = Field( + None, + alias="otherActionsDetails", + description="List of other configured actions on this keyword. Ignored in POST/PUT calls.", + ) + other_actions: Optional[List[StrictStr]] = Field( + None, + alias="otherActions", + description="List of other configured action types/names on this keyword. Ignored in POST/PUT calls.", + ) + application_id: Optional[constr(strict=True, max_length=255, min_length=0)] = Field( + None, + alias="applicationId", + description="ID of the Application that would be associated with the configuration.", + ) + entity_id: Optional[constr(strict=True, max_length=255, min_length=0)] = Field( + None, + alias="entityId", + description="ID of the Entity that would be associated with the configuration.", + ) + key: StrictStr = Field(..., description="Unique ID of configuration.") + __properties = [ + "keyword", + "action", + "useConversation", + "otherActionsDetails", + "otherActions", + "applicationId", + "entityId", + "key", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersStoredMoConfiguration: + """Create an instance of NumbersStoredMoConfiguration from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of action + if self.action: + _dict["action"] = self.action.to_dict() + # override the default output from pydantic by calling `to_dict()` of use_conversation + if self.use_conversation: + _dict["useConversation"] = self.use_conversation.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in other_actions_details (list) + _items = [] + if self.other_actions_details: + for _item in self.other_actions_details: + if _item: + _items.append(_item.to_dict()) + _dict["otherActionsDetails"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersStoredMoConfiguration: + """Create an instance of NumbersStoredMoConfiguration from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersStoredMoConfiguration.parse_obj(obj) + + _obj = NumbersStoredMoConfiguration.parse_obj( + { + "keyword": obj.get("keyword"), + "action": NumbersMoAction.from_dict(obj.get("action")) + if obj.get("action") is not None + else None, + "use_conversation": NumbersUseConversation.from_dict( + obj.get("useConversation") + ) + if obj.get("useConversation") is not None + else None, + "other_actions_details": [ + NumbersMoNonForwardAction.from_dict(_item) + for _item in obj.get("otherActionsDetails") + ] + if obj.get("otherActionsDetails") is not None + else None, + "other_actions": obj.get("otherActions"), + "application_id": obj.get("applicationId"), + "entity_id": obj.get("entityId"), + "key": obj.get("key"), + } + ) + return _obj diff --git a/models/numbers_use_conversation.py b/models/numbers_use_conversation.py new file mode 100644 index 0000000..13f5d0d --- /dev/null +++ b/models/numbers_use_conversation.py @@ -0,0 +1,65 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictBool + + +class NumbersUseConversation(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + enabled: Optional[StrictBool] = Field( + None, description="Flag which indicates if action is enabled." + ) + __properties = ["enabled"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersUseConversation: + """Create an instance of NumbersUseConversation from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersUseConversation: + """Create an instance of NumbersUseConversation from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersUseConversation.parse_obj(obj) + + _obj = NumbersUseConversation.parse_obj({"enabled": obj.get("enabled")}) + return _obj diff --git a/models/numbers_voice_action_details.py b/models/numbers_voice_action_details.py new file mode 100644 index 0000000..08619a6 --- /dev/null +++ b/models/numbers_voice_action_details.py @@ -0,0 +1,145 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json +import models + + +from typing import Optional +from pydantic import BaseModel, StrictStr, validator + + +class NumbersVoiceActionDetails(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + type: Optional[StrictStr] = None + description: Optional[StrictStr] = None + __properties = ["type", "description"] + + @validator("type") + def type_validate_enum(cls, v): + if v is None: + return v + + if v not in ( + "PULL", + "HTTP_FORWARD", + "SMPP_FORWARD", + "MAIL_FORWARD", + "NO_ACTION", + "BLOCK", + "AUTORESPONSE", + "USSD", + "SEND_BULK_MT", + "EMAIL_TO_SMS_FORWARD", + "CNS_FWD", + "USE_CONVERSATIONS", + "FORWARD_TO_PSTN", + "FORWARD_TO_IP", + "FORWARD_TO_SOFT_PHONE", + "FORWARD_TO_IVR", + "VOICE_NUMBER_MASKING", + "VOICE_CALL_DROP", + "FORWARD_TO_WEBRTC", + "VOICE_FORWARD_TO_CONVERSATIONS", + "VOICE_FORWARD_TO_CONVERSATIONS_WITH_FLOW", + "CALL_FORWARD_TO_APPLICATION", + "FORWARD_TO_SUBSCRIPTION", + "OTHER", + ): + raise ValueError( + "must validate the enum values ('PULL', 'HTTP_FORWARD', 'SMPP_FORWARD', 'MAIL_FORWARD', 'NO_ACTION', 'BLOCK', 'AUTORESPONSE', 'USSD', 'SEND_BULK_MT', 'EMAIL_TO_SMS_FORWARD', 'CNS_FWD', 'USE_CONVERSATIONS', 'FORWARD_TO_PSTN', 'FORWARD_TO_IP', 'FORWARD_TO_SOFT_PHONE', 'FORWARD_TO_IVR', 'VOICE_NUMBER_MASKING', 'VOICE_CALL_DROP', 'FORWARD_TO_WEBRTC', 'VOICE_FORWARD_TO_CONVERSATIONS', 'VOICE_FORWARD_TO_CONVERSATIONS_WITH_FLOW', 'CALL_FORWARD_TO_APPLICATION', 'FORWARD_TO_SUBSCRIPTION', 'OTHER')" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + # JSON field name that stores the object type + __discriminator_property_name = "type" + + # discriminator mappings + __discriminator_value_class_map = { + "CALL_FORWARD_TO_APPLICATION": "NumbersVoiceCallForwardToApplicationDetails", + "FORWARD_TO_IVR": "NumbersForwardToIvrActionDetails", + "FORWARD_TO_SUBSCRIPTION": "NumbersForwardToSubscriptionDetails", + "NumbersForwardToIvrActionDetails": "NumbersForwardToIvrActionDetails", + "NumbersForwardToSubscriptionDetails": "NumbersForwardToSubscriptionDetails", + "NumbersVoiceCallForwardToApplicationDetails": "NumbersVoiceCallForwardToApplicationDetails", + "NumbersVoiceNumberMaskingActionDetails": "NumbersVoiceNumberMaskingActionDetails", + "VOICE_NUMBER_MASKING": "NumbersVoiceNumberMaskingActionDetails", + } + + @classmethod + def get_discriminator_value(cls, obj: dict) -> str: + """Returns the discriminator value (object type) of the data""" + discriminator_value = obj[cls.__discriminator_property_name] + if discriminator_value: + return cls.__discriminator_value_class_map.get(discriminator_value) + else: + return None + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json( + cls, json_str: str + ) -> Union( + NumbersForwardToIvrActionDetails, + NumbersForwardToSubscriptionDetails, + NumbersVoiceCallForwardToApplicationDetails, + NumbersVoiceNumberMaskingActionDetails, + ): + """Create an instance of NumbersVoiceActionDetails from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict( + cls, obj: dict + ) -> Union( + NumbersForwardToIvrActionDetails, + NumbersForwardToSubscriptionDetails, + NumbersVoiceCallForwardToApplicationDetails, + NumbersVoiceNumberMaskingActionDetails, + ): + """Create an instance of NumbersVoiceActionDetails from a dict""" + # look up the object type based on discriminator mapping + object_type = cls.get_discriminator_value(obj) + if object_type: + klass = getattr(models, object_type) + return klass.from_dict(obj) + else: + raise ValueError( + "NumbersVoiceActionDetails failed to lookup discriminator value from " + + json.dumps(obj) + + ". Discriminator property name: " + + cls.__discriminator_property_name + + ", mapping: " + + json.dumps(cls.__discriminator_value_class_map) + ) diff --git a/models/numbers_voice_call_forward_to_application_details.py b/models/numbers_voice_call_forward_to_application_details.py new file mode 100644 index 0000000..fd3b2bb --- /dev/null +++ b/models/numbers_voice_call_forward_to_application_details.py @@ -0,0 +1,69 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, StrictStr +from models.numbers_voice_action_details import NumbersVoiceActionDetails + + +class NumbersVoiceCallForwardToApplicationDetails(NumbersVoiceActionDetails): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + application_id: StrictStr = Field(..., alias="applicationId") + __properties = ["type", "description", "applicationId"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersVoiceCallForwardToApplicationDetails: + """Create an instance of NumbersVoiceCallForwardToApplicationDetails from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersVoiceCallForwardToApplicationDetails: + """Create an instance of NumbersVoiceCallForwardToApplicationDetails from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersVoiceCallForwardToApplicationDetails.parse_obj(obj) + + _obj = NumbersVoiceCallForwardToApplicationDetails.parse_obj( + { + "type": obj.get("type"), + "description": obj.get("description"), + "application_id": obj.get("applicationId"), + } + ) + return _obj diff --git a/models/numbers_voice_number_masking_action_details.py b/models/numbers_voice_number_masking_action_details.py new file mode 100644 index 0000000..0865e54 --- /dev/null +++ b/models/numbers_voice_number_masking_action_details.py @@ -0,0 +1,73 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, StrictStr +from models.numbers_voice_action_details import NumbersVoiceActionDetails + + +class NumbersVoiceNumberMaskingActionDetails(NumbersVoiceActionDetails): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + voice_number_masking_config_key: StrictStr = Field( + ..., alias="voiceNumberMaskingConfigKey" + ) + __properties = ["type", "description", "voiceNumberMaskingConfigKey"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersVoiceNumberMaskingActionDetails: + """Create an instance of NumbersVoiceNumberMaskingActionDetails from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersVoiceNumberMaskingActionDetails: + """Create an instance of NumbersVoiceNumberMaskingActionDetails from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersVoiceNumberMaskingActionDetails.parse_obj(obj) + + _obj = NumbersVoiceNumberMaskingActionDetails.parse_obj( + { + "type": obj.get("type"), + "description": obj.get("description"), + "voice_number_masking_config_key": obj.get( + "voiceNumberMaskingConfigKey" + ), + } + ) + return _obj diff --git a/models/numbers_voice_setup.py b/models/numbers_voice_setup.py new file mode 100644 index 0000000..a665702 --- /dev/null +++ b/models/numbers_voice_setup.py @@ -0,0 +1,85 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, constr +from models.numbers_voice_action_details import NumbersVoiceActionDetails + + +class NumbersVoiceSetup(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + application_id: Optional[constr(strict=True, max_length=255, min_length=0)] = Field( + None, + alias="applicationId", + description="ID of the Application that would be associated with the voice setup.", + ) + entity_id: Optional[constr(strict=True, max_length=255, min_length=0)] = Field( + None, + alias="entityId", + description="ID of the Entity that would be associated with the voice setup.", + ) + action: NumbersVoiceActionDetails = ... + __properties = ["applicationId", "entityId", "action"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> NumbersVoiceSetup: + """Create an instance of NumbersVoiceSetup from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of action + if self.action: + _dict["action"] = self.action.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> NumbersVoiceSetup: + """Create an instance of NumbersVoiceSetup from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return NumbersVoiceSetup.parse_obj(obj) + + _obj = NumbersVoiceSetup.parse_obj( + { + "application_id": obj.get("applicationId"), + "entity_id": obj.get("entityId"), + "action": NumbersVoiceActionDetails.from_dict(obj.get("action")) + if obj.get("action") is not None + else None, + } + ) + return _obj diff --git a/models/page_application.py b/models/page_application.py new file mode 100644 index 0000000..fd6dd08 --- /dev/null +++ b/models/page_application.py @@ -0,0 +1,87 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel +from models.application import Application +from models.page_info import PageInfo + + +class PageApplication(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[Application]] = None + paging: Optional[PageInfo] = None + __properties = ["results", "paging"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> PageApplication: + """Create an instance of PageApplication from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + # override the default output from pydantic by calling `to_dict()` of paging + if self.paging: + _dict["paging"] = self.paging.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> PageApplication: + """Create an instance of PageApplication from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return PageApplication.parse_obj(obj) + + _obj = PageApplication.parse_obj( + { + "results": [ + Application.from_dict(_item) for _item in obj.get("results") + ] + if obj.get("results") is not None + else None, + "paging": PageInfo.from_dict(obj.get("paging")) + if obj.get("paging") is not None + else None, + } + ) + return _obj diff --git a/models/page_entity.py b/models/page_entity.py new file mode 100644 index 0000000..224aa67 --- /dev/null +++ b/models/page_entity.py @@ -0,0 +1,85 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel +from models.entity import Entity +from models.page_info import PageInfo + + +class PageEntity(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[Entity]] = None + paging: Optional[PageInfo] = None + __properties = ["results", "paging"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> PageEntity: + """Create an instance of PageEntity from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + # override the default output from pydantic by calling `to_dict()` of paging + if self.paging: + _dict["paging"] = self.paging.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> PageEntity: + """Create an instance of PageEntity from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return PageEntity.parse_obj(obj) + + _obj = PageEntity.parse_obj( + { + "results": [Entity.from_dict(_item) for _item in obj.get("results")] + if obj.get("results") is not None + else None, + "paging": PageInfo.from_dict(obj.get("paging")) + if obj.get("paging") is not None + else None, + } + ) + return _obj diff --git a/models/page_info.py b/models/page_info.py new file mode 100644 index 0000000..349a826 --- /dev/null +++ b/models/page_info.py @@ -0,0 +1,80 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, conint + + +class PageInfo(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + page: conint(strict=True, ge=0) = Field(..., description="Requested page number.") + size: conint(strict=True, ge=1) = Field(..., description="Requested page size.") + total_pages: conint(strict=True, ge=0) = Field( + ..., + alias="totalPages", + description="The total number of pages of the results matching the requested parameters.", + ) + total_results: conint(strict=True, ge=0) = Field( + ..., + alias="totalResults", + description="The total number of the results matching the requested parameters.", + ) + __properties = ["page", "size", "totalPages", "totalResults"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> PageInfo: + """Create an instance of PageInfo from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> PageInfo: + """Create an instance of PageInfo from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return PageInfo.parse_obj(obj) + + _obj = PageInfo.parse_obj( + { + "page": obj.get("page"), + "size": obj.get("size"), + "total_pages": obj.get("totalPages"), + "total_results": obj.get("totalResults"), + } + ) + return _obj diff --git a/models/page_resource_association.py b/models/page_resource_association.py new file mode 100644 index 0000000..4ea9027 --- /dev/null +++ b/models/page_resource_association.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel +from models.page_info import PageInfo +from models.resource_association_response import ( + ResourceAssociationResponse, +) + + +class PageResourceAssociation(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[ResourceAssociationResponse]] = None + paging: Optional[PageInfo] = None + __properties = ["results", "paging"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> PageResourceAssociation: + """Create an instance of PageResourceAssociation from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + # override the default output from pydantic by calling `to_dict()` of paging + if self.paging: + _dict["paging"] = self.paging.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> PageResourceAssociation: + """Create an instance of PageResourceAssociation from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return PageResourceAssociation.parse_obj(obj) + + _obj = PageResourceAssociation.parse_obj( + { + "results": [ + ResourceAssociationResponse.from_dict(_item) + for _item in obj.get("results") + ] + if obj.get("results") is not None + else None, + "paging": PageInfo.from_dict(obj.get("paging")) + if obj.get("paging") is not None + else None, + } + ) + return _obj diff --git a/models/resource_association_request.py b/models/resource_association_request.py new file mode 100644 index 0000000..430d28a --- /dev/null +++ b/models/resource_association_request.py @@ -0,0 +1,94 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, constr +from models.channel import Channel +from models.resource_type import ResourceType + + +class ResourceAssociationRequest(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + resource_type: ResourceType = Field(..., alias="resourceType") + channel: Channel = ... + application_id: constr(strict=True, max_length=255) = Field( + ..., + alias="applicationId", + description="Id of the application, this `id` will be a URL path parameter, the validation on our backend will verify its validity by doing `urlEncode(id) = id` meaning if any character in the `id` would require encoding the validation will fail.", + ) + entity_id: constr(strict=True, max_length=255) = Field( + ..., + alias="entityId", + description="Id of the entity, this `id` will be a URL path parameter, the validation on our backend will verify its validity by doing `urlEncode(id) = id` meaning if any character in the `id` would require encoding the validation will fail. If there is no entity associated with this exact resource, the value for entity should be `null`.", + ) + resource_id: constr(strict=True, max_length=255) = Field( + ..., + alias="resourceId", + description="ID of the resource. Depends on `resourceType` and `channel`.
Use [numberKey](https://www.infobip.com/docs/api/platform-connectivity/numbers/phone-numbers/list-purchased-numbers) for the NUMBER `resourceType` available for: 10DLC, Short Code, VLN for the following channels: SMS, MMS.
Use [domainName](https://www.infobip.com/docs/api/channels/email/get-all-domains) for the DOMAIN `resourceType` available for domain for the following channel: Email.", + ) + __properties = [ + "resourceType", + "channel", + "applicationId", + "entityId", + "resourceId", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> ResourceAssociationRequest: + """Create an instance of ResourceAssociationRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> ResourceAssociationRequest: + """Create an instance of ResourceAssociationRequest from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return ResourceAssociationRequest.parse_obj(obj) + + _obj = ResourceAssociationRequest.parse_obj( + { + "resource_type": obj.get("resourceType"), + "channel": obj.get("channel"), + "application_id": obj.get("applicationId"), + "entity_id": obj.get("entityId"), + "resource_id": obj.get("resourceId"), + } + ) + return _obj diff --git a/models/resource_association_response.py b/models/resource_association_response.py new file mode 100644 index 0000000..d42b4a5 --- /dev/null +++ b/models/resource_association_response.py @@ -0,0 +1,95 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, constr +from models.channel import Channel +from models.resource_type import ResourceType + + +class ResourceAssociationResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + resource_type: ResourceType = Field(..., alias="resourceType") + channel: Channel = ... + application_id: constr(strict=True, max_length=255) = Field( + ..., + alias="applicationId", + description="Id of the application, this `id` will be a URL path parameter, the validation on our backend will verify its validity by doing `urlEncode(id) = id` meaning if any character in the `id` would require encoding the validation will fail.", + ) + entity_id: Optional[constr(strict=True, max_length=255)] = Field( + None, + alias="entityId", + description="Id of the entity, this `id` will be a URL path parameter, the validation on our backend will verify its validity by doing `urlEncode(id) = id` meaning if any character in the `id` would require encoding the validation will fail.", + ) + resource_id: constr(strict=True, max_length=255) = Field( + ..., + alias="resourceId", + description="ID of the resource. Depends on `resourceType` and `channel`.
Use [numberKey](https://www.infobip.com/docs/api/platform-connectivity/numbers/phone-numbers/list-purchased-numbers) for the NUMBER `resourceType` available for: 10DLC, Short Code, VLN for the following channels: SMS, MMS.
Use [domainName](https://www.infobip.com/docs/api/channels/email/get-all-domains) for the DOMAIN `resourceType` available for domain for the following channel: Email.", + ) + __properties = [ + "resourceType", + "channel", + "applicationId", + "entityId", + "resourceId", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> ResourceAssociationResponse: + """Create an instance of ResourceAssociationResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> ResourceAssociationResponse: + """Create an instance of ResourceAssociationResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return ResourceAssociationResponse.parse_obj(obj) + + _obj = ResourceAssociationResponse.parse_obj( + { + "resource_type": obj.get("resourceType"), + "channel": obj.get("channel"), + "application_id": obj.get("applicationId"), + "entity_id": obj.get("entityId"), + "resource_id": obj.get("resourceId"), + } + ) + return _obj diff --git a/models/resource_type.py b/models/resource_type.py new file mode 100644 index 0000000..7298f67 --- /dev/null +++ b/models/resource_type.py @@ -0,0 +1,29 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from inspect import getfullargspec +import pprint +import re # noqa: F401 +from aenum import Enum, no_arg + + +class ResourceType(str, Enum): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + allowed enum values + """ + + NUMBER = "NUMBER" + DOMAIN = "DOMAIN" + WEBRTC_PUSH_CONFIG = "WEBRTC_PUSH_CONFIG" diff --git a/models/sms_advanced_binary_request.py b/models/sms_advanced_binary_request.py new file mode 100644 index 0000000..5806199 --- /dev/null +++ b/models/sms_advanced_binary_request.py @@ -0,0 +1,100 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictStr +from models.sms_binary_message import SmsBinaryMessage +from models.sms_sending_speed_limit import SmsSendingSpeedLimit + + +class SmsAdvancedBinaryRequest(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field( + None, + alias="bulkId", + description="Unique ID assigned to the request if messaging multiple recipients or sending multiple messages via a single API request. If not provided, it will be auto-generated and returned in the API response. Typically, used to fetch [delivery reports](#channels/sms/get-outbound-sms-message-delivery-reports) and [message logs](#channels/sms/get-outbound-sms-message-logs).", + ) + messages: List[SmsBinaryMessage] = Field( + ..., + description="An array of message objects of a single message or multiple messages sent under one bulk ID.", + ) + sending_speed_limit: Optional[SmsSendingSpeedLimit] = Field( + None, alias="sendingSpeedLimit" + ) + __properties = ["bulkId", "messages", "sendingSpeedLimit"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsAdvancedBinaryRequest: + """Create an instance of SmsAdvancedBinaryRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in messages (list) + _items = [] + if self.messages: + for _item in self.messages: + if _item: + _items.append(_item.to_dict()) + _dict["messages"] = _items + # override the default output from pydantic by calling `to_dict()` of sending_speed_limit + if self.sending_speed_limit: + _dict["sendingSpeedLimit"] = self.sending_speed_limit.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsAdvancedBinaryRequest: + """Create an instance of SmsAdvancedBinaryRequest from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsAdvancedBinaryRequest.parse_obj(obj) + + _obj = SmsAdvancedBinaryRequest.parse_obj( + { + "bulk_id": obj.get("bulkId"), + "messages": [ + SmsBinaryMessage.from_dict(_item) for _item in obj.get("messages") + ] + if obj.get("messages") is not None + else None, + "sending_speed_limit": SmsSendingSpeedLimit.from_dict( + obj.get("sendingSpeedLimit") + ) + if obj.get("sendingSpeedLimit") is not None + else None, + } + ) + return _obj diff --git a/models/sms_advanced_textual_request.py b/models/sms_advanced_textual_request.py new file mode 100644 index 0000000..bc019fe --- /dev/null +++ b/models/sms_advanced_textual_request.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictStr +from models.sms_sending_speed_limit import SmsSendingSpeedLimit +from models.sms_textual_message import Message +from models.sms_tracking import SmsTracking +from models.sms_url_options import SmsUrlOptions + + +class SendRequestBody(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field( + None, + alias="bulkId", + description="Unique ID assigned to the request if messaging multiple recipients or sending multiple messages via a single API request. If not provided, it will be auto-generated and returned in the API response. Typically, used to fetch [delivery reports](#channels/sms/get-outbound-sms-message-delivery-reports) and [message logs](#channels/sms/get-outbound-sms-message-logs).", + ) + messages: List[Message] = Field( + ..., + description="An array of message objects of a single message or multiple messages sent under one bulk ID.", + ) + sending_speed_limit: Optional[SmsSendingSpeedLimit] = Field( + None, alias="sendingSpeedLimit" + ) + url_options: Optional[SmsUrlOptions] = Field(None, alias="urlOptions") + tracking: Optional[SmsTracking] = None + __properties = ["bulkId", "messages", "sendingSpeedLimit", "urlOptions", "tracking"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SendRequestBody: + """Create an instance of SmsAdvancedTextualRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in messages (list) + _items = [] + if self.messages: + for _item in self.messages: + if _item: + _items.append(_item.to_dict()) + _dict["messages"] = _items + # override the default output from pydantic by calling `to_dict()` of sending_speed_limit + if self.sending_speed_limit: + _dict["sendingSpeedLimit"] = self.sending_speed_limit.to_dict() + # override the default output from pydantic by calling `to_dict()` of url_options + if self.url_options: + _dict["urlOptions"] = self.url_options.to_dict() + # override the default output from pydantic by calling `to_dict()` of tracking + if self.tracking: + _dict["tracking"] = self.tracking.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SendRequestBody: + """Create an instance of SmsAdvancedTextualRequest from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SendRequestBody.parse_obj(obj) + + _obj = SendRequestBody.parse_obj( + { + "bulk_id": obj.get("bulkId"), + "messages": [Message.from_dict(_item) for _item in obj.get("messages")] + if obj.get("messages") is not None + else None, + "sending_speed_limit": SmsSendingSpeedLimit.from_dict( + obj.get("sendingSpeedLimit") + ) + if obj.get("sendingSpeedLimit") is not None + else None, + "url_options": SmsUrlOptions.from_dict(obj.get("urlOptions")) + if obj.get("urlOptions") is not None + else None, + "tracking": SmsTracking.from_dict(obj.get("tracking")) + if obj.get("tracking") is not None + else None, + } + ) + return _obj diff --git a/models/sms_binary_content.py b/models/sms_binary_content.py new file mode 100644 index 0000000..c978b03 --- /dev/null +++ b/models/sms_binary_content.py @@ -0,0 +1,82 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr + + +class SmsBinaryContent(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + data_coding: Optional[StrictInt] = Field( + None, + alias="dataCoding", + description="Binary content data coding. The default value is (`0`) for GSM7. Example: (`8`) for Unicode data.", + ) + esm_class: Optional[StrictInt] = Field( + None, + alias="esmClass", + description="“Esm_class” parameter. Indicate special message attributes associated with the SMS. Default value is (`0`).", + ) + hex: StrictStr = Field( + ..., + description="Hexadecimal string. This is the representation of your binary data. Two hex digits represent one byte. They should be separated by the space character (Example: `0f c2 4a bf 34 13 ba`).", + ) + __properties = ["dataCoding", "esmClass", "hex"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsBinaryContent: + """Create an instance of SmsBinaryContent from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsBinaryContent: + """Create an instance of SmsBinaryContent from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsBinaryContent.parse_obj(obj) + + _obj = SmsBinaryContent.parse_obj( + { + "data_coding": obj.get("dataCoding"), + "esm_class": obj.get("esmClass"), + "hex": obj.get("hex"), + } + ) + return _obj diff --git a/models/sms_binary_message.py b/models/sms_binary_message.py new file mode 100644 index 0000000..99fedf7 --- /dev/null +++ b/models/sms_binary_message.py @@ -0,0 +1,184 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import List, Optional +from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, constr +from models.sms_binary_content import SmsBinaryContent +from models.sms_delivery_time_window import SmsDeliveryTimeWindow +from models.sms_destination import Destination +from models.sms_regional_options import SmsRegionalOptions + + +class SmsBinaryMessage(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + binary: Optional[SmsBinaryContent] = None + callback_data: Optional[constr(strict=True, max_length=4000, min_length=0)] = Field( + None, + alias="callbackData", + description="Additional client data that will be sent on the notifyUrl. The maximum value is 4000 characters.", + ) + delivery_time_window: Optional[SmsDeliveryTimeWindow] = Field( + None, alias="deliveryTimeWindow" + ) + destinations: List[Destination] = Field( + ..., + description="An array of destination objects for where messages are being sent. A valid destination is required.", + ) + flash: Optional[StrictBool] = Field( + None, + description="Allows for sending a [flash SMS](https://www.infobip.com/docs/sms/message-types#flash-sms) to automatically appear on recipient devices without interaction. Set to `true` to enable flash SMS, or leave the default value, `false` to send a standard SMS.", + ) + var_from: Optional[StrictStr] = Field( + None, + alias="from", + description="The sender ID which can be alphanumeric or numeric (e.g., `CompanyName`). Make sure you don't exceed [character limit](https://www.infobip.com/docs/sms/get-started#sender-names).", + ) + intermediate_report: Optional[StrictBool] = Field( + None, + alias="intermediateReport", + description="The [real-time intermediate delivery report](https://www.infobip.com/docs/api#channels/sms/receive-outbound-sms-message-report) containing GSM error codes, messages status, pricing, network and country codes, etc., which will be sent on your callback server. Defaults to `false`.", + ) + notify_content_type: Optional[StrictStr] = Field( + None, + alias="notifyContentType", + description="Preferred delivery report content type, `application/json` or `application/xml`.", + ) + notify_url: Optional[StrictStr] = Field( + None, + alias="notifyUrl", + description="The URL on your call back server on which the Delivery report will be sent.", + ) + regional: Optional[SmsRegionalOptions] = None + send_at: Optional[datetime] = Field( + None, + alias="sendAt", + description="Date and time when the message is to be sent. Used for [scheduled SMS](https://www.infobip.com/docs/api#channels/sms/get-scheduled-sms-messages). Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`, and can only be scheduled for no later than 180 days in advance.", + ) + validity_period: Optional[StrictInt] = Field( + None, + alias="validityPeriod", + description="The message validity period in minutes. When the period expires, it will not be allowed for the message to be sent. Validity period longer than 48h is not supported (in this case, it will be automatically set to 48h).", + ) + entity_id: Optional[constr(strict=True, max_length=66, min_length=0)] = Field( + None, + alias="entityId", + description="Required for entity use in a send request for outbound traffic. Returned in notification events. For more details, see our [documentation](https://www.infobip.com/docs/cpaas-x/application-and-entity-management).", + ) + application_id: Optional[constr(strict=True, max_length=66, min_length=0)] = Field( + None, + alias="applicationId", + description="Required for application use in a send request for outbound traffic. Returned in notification events. For more details, see our [documentation](https://www.infobip.com/docs/cpaas-x/application-and-entity-management).", + ) + __properties = [ + "binary", + "callbackData", + "deliveryTimeWindow", + "destinations", + "flash", + "from", + "intermediateReport", + "notifyContentType", + "notifyUrl", + "regional", + "sendAt", + "validityPeriod", + "entityId", + "applicationId", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsBinaryMessage: + """Create an instance of SmsBinaryMessage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of binary + if self.binary: + _dict["binary"] = self.binary.to_dict() + # override the default output from pydantic by calling `to_dict()` of delivery_time_window + if self.delivery_time_window: + _dict["deliveryTimeWindow"] = self.delivery_time_window.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in destinations (list) + _items = [] + if self.destinations: + for _item in self.destinations: + if _item: + _items.append(_item.to_dict()) + _dict["destinations"] = _items + # override the default output from pydantic by calling `to_dict()` of regional + if self.regional: + _dict["regional"] = self.regional.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsBinaryMessage: + """Create an instance of SmsBinaryMessage from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsBinaryMessage.parse_obj(obj) + + _obj = SmsBinaryMessage.parse_obj( + { + "binary": SmsBinaryContent.from_dict(obj.get("binary")) + if obj.get("binary") is not None + else None, + "callback_data": obj.get("callbackData"), + "delivery_time_window": SmsDeliveryTimeWindow.from_dict( + obj.get("deliveryTimeWindow") + ) + if obj.get("deliveryTimeWindow") is not None + else None, + "destinations": [ + Destination.from_dict(_item) for _item in obj.get("destinations") + ] + if obj.get("destinations") is not None + else None, + "flash": obj.get("flash"), + "var_from": obj.get("from"), + "intermediate_report": obj.get("intermediateReport"), + "notify_content_type": obj.get("notifyContentType"), + "notify_url": obj.get("notifyUrl"), + "regional": SmsRegionalOptions.from_dict(obj.get("regional")) + if obj.get("regional") is not None + else None, + "send_at": obj.get("sendAt"), + "validity_period": obj.get("validityPeriod"), + "entity_id": obj.get("entityId"), + "application_id": obj.get("applicationId"), + } + ) + return _obj diff --git a/models/sms_bulk_request.py b/models/sms_bulk_request.py new file mode 100644 index 0000000..231f3ed --- /dev/null +++ b/models/sms_bulk_request.py @@ -0,0 +1,67 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime + +from pydantic import BaseModel, Field + + +class SmsBulkRequest(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + send_at: datetime = Field( + ..., + alias="sendAt", + description="Date and time when the message is to be sent. Used for scheduled SMS (see [Scheduled SMS endpoints](#channels/sms/get-scheduled-sms-messages) for more details). Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`, and can only be scheduled for no later than 180 days in advance.", + ) + __properties = ["sendAt"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsBulkRequest: + """Create an instance of SmsBulkRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsBulkRequest: + """Create an instance of SmsBulkRequest from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsBulkRequest.parse_obj(obj) + + _obj = SmsBulkRequest.parse_obj({"send_at": obj.get("sendAt")}) + return _obj diff --git a/models/sms_bulk_response.py b/models/sms_bulk_response.py new file mode 100644 index 0000000..2345e57 --- /dev/null +++ b/models/sms_bulk_response.py @@ -0,0 +1,74 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class SmsBulkResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field( + None, + alias="bulkId", + description="Unique ID assigned to the request if messaging multiple recipients or sending multiple messages via a single API request.", + ) + send_at: Optional[datetime] = Field( + None, + alias="sendAt", + description="Date and time when the message is to be sent. Used for scheduled SMS (see [Scheduled SMS endpoints](#channels/sms/get-scheduled-sms-messages) for more details). Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`, and can only be scheduled for no later than 180 days in advance.", + ) + __properties = ["bulkId", "sendAt"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsBulkResponse: + """Create an instance of SmsBulkResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsBulkResponse: + """Create an instance of SmsBulkResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsBulkResponse.parse_obj(obj) + + _obj = SmsBulkResponse.parse_obj( + {"bulk_id": obj.get("bulkId"), "send_at": obj.get("sendAt")} + ) + return _obj diff --git a/models/sms_bulk_status.py b/models/sms_bulk_status.py new file mode 100644 index 0000000..e406975 --- /dev/null +++ b/models/sms_bulk_status.py @@ -0,0 +1,32 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from inspect import getfullargspec +import pprint +import re # noqa: F401 +from aenum import Enum, no_arg + + +class SmsBulkStatus(str, Enum): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + allowed enum values + """ + + PENDING = "PENDING" + PAUSED = "PAUSED" + PROCESSING = "PROCESSING" + CANCELED = "CANCELED" + FINISHED = "FINISHED" + FAILED = "FAILED" diff --git a/models/sms_bulk_status_response.py b/models/sms_bulk_status_response.py new file mode 100644 index 0000000..5802f38 --- /dev/null +++ b/models/sms_bulk_status_response.py @@ -0,0 +1,71 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr +from models.sms_bulk_status import SmsBulkStatus + + +class SmsBulkStatusResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field( + None, + alias="bulkId", + description="Unique ID assigned to the request if messaging multiple recipients or sending multiple messages via a single API request.", + ) + status: Optional[SmsBulkStatus] = None + __properties = ["bulkId", "status"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsBulkStatusResponse: + """Create an instance of SmsBulkStatusResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsBulkStatusResponse: + """Create an instance of SmsBulkStatusResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsBulkStatusResponse.parse_obj(obj) + + _obj = SmsBulkStatusResponse.parse_obj( + {"bulk_id": obj.get("bulkId"), "status": obj.get("status")} + ) + return _obj diff --git a/models/sms_delivery_day.py b/models/sms_delivery_day.py new file mode 100644 index 0000000..dee1839 --- /dev/null +++ b/models/sms_delivery_day.py @@ -0,0 +1,33 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from inspect import getfullargspec +import pprint +import re # noqa: F401 +from aenum import Enum, no_arg + + +class SmsDeliveryDay(str, Enum): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + allowed enum values + """ + + MONDAY = "MONDAY" + TUESDAY = "TUESDAY" + WEDNESDAY = "WEDNESDAY" + THURSDAY = "THURSDAY" + FRIDAY = "FRIDAY" + SATURDAY = "SATURDAY" + SUNDAY = "SUNDAY" diff --git a/models/sms_delivery_result.py b/models/sms_delivery_result.py new file mode 100644 index 0000000..a60f239 --- /dev/null +++ b/models/sms_delivery_result.py @@ -0,0 +1,77 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel +from models.sms_report import SmsReport + + +class SmsDeliveryResult(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[SmsReport]] = None + __properties = ["results"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsDeliveryResult: + """Create an instance of SmsDeliveryResult from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsDeliveryResult: + """Create an instance of SmsDeliveryResult from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsDeliveryResult.parse_obj(obj) + + _obj = SmsDeliveryResult.parse_obj( + { + "results": [SmsReport.from_dict(_item) for _item in obj.get("results")] + if obj.get("results") is not None + else None + } + ) + return _obj diff --git a/models/sms_delivery_time_from.py b/models/sms_delivery_time_from.py new file mode 100644 index 0000000..7130e1d --- /dev/null +++ b/models/sms_delivery_time_from.py @@ -0,0 +1,71 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, conint + + +class SmsDeliveryTimeFrom(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + hour: conint(strict=True, le=23, ge=0) = Field( + ..., + description="Hour when the time window opens when used in the `from` property or closes when used in the `to` property.", + ) + minute: conint(strict=True, le=59, ge=0) = Field( + ..., + description="Minute when the time window opens when used in the `from` property or closes when used in the `to` property.", + ) + __properties = ["hour", "minute"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsDeliveryTimeFrom: + """Create an instance of SmsDeliveryTimeFrom from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsDeliveryTimeFrom: + """Create an instance of SmsDeliveryTimeFrom from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsDeliveryTimeFrom.parse_obj(obj) + + _obj = SmsDeliveryTimeFrom.parse_obj( + {"hour": obj.get("hour"), "minute": obj.get("minute")} + ) + return _obj diff --git a/models/sms_delivery_time_to.py b/models/sms_delivery_time_to.py new file mode 100644 index 0000000..29de300 --- /dev/null +++ b/models/sms_delivery_time_to.py @@ -0,0 +1,71 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel, Field, conint + + +class SmsDeliveryTimeTo(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + hour: conint(strict=True, le=23, ge=0) = Field( + ..., + description="Hour when the time window opens when used in the `from` property or closes when used in the `to` property.", + ) + minute: conint(strict=True, le=59, ge=0) = Field( + ..., + description="Minute when the time window opens when used in the `from` property or closes when used in the `to` property.", + ) + __properties = ["hour", "minute"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsDeliveryTimeTo: + """Create an instance of SmsDeliveryTimeTo from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsDeliveryTimeTo: + """Create an instance of SmsDeliveryTimeTo from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsDeliveryTimeTo.parse_obj(obj) + + _obj = SmsDeliveryTimeTo.parse_obj( + {"hour": obj.get("hour"), "minute": obj.get("minute")} + ) + return _obj diff --git a/models/sms_delivery_time_window.py b/models/sms_delivery_time_window.py new file mode 100644 index 0000000..a5e8031 --- /dev/null +++ b/models/sms_delivery_time_window.py @@ -0,0 +1,87 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field +from models.sms_delivery_day import SmsDeliveryDay +from models.sms_delivery_time_from import SmsDeliveryTimeFrom +from models.sms_delivery_time_to import SmsDeliveryTimeTo + + +class SmsDeliveryTimeWindow(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + days: List[SmsDeliveryDay] = Field( + ..., + description="Days of the week which are included in the delivery time window. At least one day must be provided. Separate multiple days with a comma.", + ) + var_from: Optional[SmsDeliveryTimeFrom] = Field(None, alias="from") + to: Optional[SmsDeliveryTimeTo] = None + __properties = ["days", "from", "to"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsDeliveryTimeWindow: + """Create an instance of SmsDeliveryTimeWindow from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of var_from + if self.var_from: + _dict["from"] = self.var_from.to_dict() + # override the default output from pydantic by calling `to_dict()` of to + if self.to: + _dict["to"] = self.to.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsDeliveryTimeWindow: + """Create an instance of SmsDeliveryTimeWindow from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsDeliveryTimeWindow.parse_obj(obj) + + _obj = SmsDeliveryTimeWindow.parse_obj( + { + "days": obj.get("days"), + "var_from": SmsDeliveryTimeFrom.from_dict(obj.get("from")) + if obj.get("from") is not None + else None, + "to": SmsDeliveryTimeTo.from_dict(obj.get("to")) + if obj.get("to") is not None + else None, + } + ) + return _obj diff --git a/models/sms_destination.py b/models/sms_destination.py new file mode 100644 index 0000000..87a4fd4 --- /dev/null +++ b/models/sms_destination.py @@ -0,0 +1,73 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, constr + + +class Destination(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + message_id: Optional[StrictStr] = Field( + None, + alias="messageId", + description="The ID that uniquely identifies the message sent.", + ) + to: constr(strict=True, max_length=50, min_length=0) = Field( + ..., + description="Message destination address. Addresses must be in international format (Example: `41793026727`).", + ) + __properties = ["messageId", "to"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Destination: + """Create an instance of SmsDestination from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> Destination: + """Create an instance of SmsDestination from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return Destination.parse_obj(obj) + + _obj = Destination.parse_obj( + {"message_id": obj.get("messageId"), "to": obj.get("to")} + ) + return _obj diff --git a/models/sms_error.py b/models/sms_error.py new file mode 100644 index 0000000..3187f13 --- /dev/null +++ b/models/sms_error.py @@ -0,0 +1,85 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr + + +class SmsError(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + group_id: Optional[StrictInt] = Field( + None, alias="groupId", description="Error group ID." + ) + group_name: Optional[StrictStr] = Field( + None, alias="groupName", description="Error group name." + ) + id: Optional[StrictInt] = Field(None, description="Error ID.") + name: Optional[StrictStr] = Field(None, description="Error name.") + description: Optional[StrictStr] = Field( + None, description="Human-readable description of the error.." + ) + permanent: Optional[StrictBool] = Field( + None, description="Tells if the error is permanent." + ) + __properties = ["groupId", "groupName", "id", "name", "description", "permanent"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsError: + """Create an instance of SmsError from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsError: + """Create an instance of SmsError from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsError.parse_obj(obj) + + _obj = SmsError.parse_obj( + { + "group_id": obj.get("groupId"), + "group_name": obj.get("groupName"), + "id": obj.get("id"), + "name": obj.get("name"), + "description": obj.get("description"), + "permanent": obj.get("permanent"), + } + ) + return _obj diff --git a/models/sms_inbound_message.py b/models/sms_inbound_message.py new file mode 100644 index 0000000..bfba2c7 --- /dev/null +++ b/models/sms_inbound_message.py @@ -0,0 +1,124 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr +from models.sms_price import SmsPrice + + +class SmsInboundMessage(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + callback_data: Optional[StrictStr] = Field( + None, + alias="callbackData", + description="Custom callback data sent over the notifyUrl.", + ) + clean_text: Optional[StrictStr] = Field( + None, + alias="cleanText", + description="Content of the message without a keyword (if a keyword was sent).", + ) + var_from: Optional[StrictStr] = Field( + None, alias="from", description="Sender ID that can be alphanumeric or numeric." + ) + keyword: Optional[StrictStr] = Field( + None, description="Keyword extracted from the message content." + ) + message_id: Optional[StrictStr] = Field( + None, alias="messageId", description="Unique message ID." + ) + price: Optional[SmsPrice] = None + received_at: Optional[datetime] = Field( + None, + alias="receivedAt", + description="Indicates when the Infobip platform received the message. Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`.", + ) + sms_count: Optional[StrictInt] = Field( + None, alias="smsCount", description="The number of characters within a message" + ) + text: Optional[StrictStr] = Field(None, description="Full content of the message.") + to: Optional[StrictStr] = Field( + None, description="The destination address of the message." + ) + __properties = [ + "callbackData", + "cleanText", + "from", + "keyword", + "messageId", + "price", + "receivedAt", + "smsCount", + "text", + "to", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsInboundMessage: + """Create an instance of SmsInboundMessage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of price + if self.price: + _dict["price"] = self.price.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsInboundMessage: + """Create an instance of SmsInboundMessage from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsInboundMessage.parse_obj(obj) + + _obj = SmsInboundMessage.parse_obj( + { + "callback_data": obj.get("callbackData"), + "clean_text": obj.get("cleanText"), + "var_from": obj.get("from"), + "keyword": obj.get("keyword"), + "message_id": obj.get("messageId"), + "price": SmsPrice.from_dict(obj.get("price")) + if obj.get("price") is not None + else None, + "received_at": obj.get("receivedAt"), + "sms_count": obj.get("smsCount"), + "text": obj.get("text"), + "to": obj.get("to"), + } + ) + return _obj diff --git a/models/sms_inbound_message_result.py b/models/sms_inbound_message_result.py new file mode 100644 index 0000000..a7e06f3 --- /dev/null +++ b/models/sms_inbound_message_result.py @@ -0,0 +1,93 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictInt +from models.sms_inbound_message import SmsInboundMessage + + +class SmsInboundMessageResult(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + message_count: Optional[StrictInt] = Field( + None, + alias="messageCount", + description="The number of messages returned in the `results` array.", + ) + pending_message_count: Optional[StrictInt] = Field( + None, + alias="pendingMessageCount", + description="The number of messages that have not been pulled in.", + ) + results: Optional[List[SmsInboundMessage]] = Field( + None, description="An array of result objects." + ) + __properties = ["messageCount", "pendingMessageCount", "results"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsInboundMessageResult: + """Create an instance of SmsInboundMessageResult from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsInboundMessageResult: + """Create an instance of SmsInboundMessageResult from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsInboundMessageResult.parse_obj(obj) + + _obj = SmsInboundMessageResult.parse_obj( + { + "message_count": obj.get("messageCount"), + "pending_message_count": obj.get("pendingMessageCount"), + "results": [ + SmsInboundMessage.from_dict(_item) for _item in obj.get("results") + ] + if obj.get("results") is not None + else None, + } + ) + return _obj diff --git a/models/sms_india_dlt_options.py b/models/sms_india_dlt_options.py new file mode 100644 index 0000000..ddee82a --- /dev/null +++ b/models/sms_india_dlt_options.py @@ -0,0 +1,77 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class SmsIndiaDltOptions(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + content_template_id: Optional[StrictStr] = Field( + None, + alias="contentTemplateId", + description="Registered DLT content template ID which matches message you are sending.", + ) + principal_entity_id: StrictStr = Field( + ..., + alias="principalEntityId", + description="Your assigned DLT principal entity ID.", + ) + __properties = ["contentTemplateId", "principalEntityId"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsIndiaDltOptions: + """Create an instance of SmsIndiaDltOptions from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsIndiaDltOptions: + """Create an instance of SmsIndiaDltOptions from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsIndiaDltOptions.parse_obj(obj) + + _obj = SmsIndiaDltOptions.parse_obj( + { + "content_template_id": obj.get("contentTemplateId"), + "principal_entity_id": obj.get("principalEntityId"), + } + ) + return _obj diff --git a/models/sms_language.py b/models/sms_language.py new file mode 100644 index 0000000..c4877e5 --- /dev/null +++ b/models/sms_language.py @@ -0,0 +1,67 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class SmsLanguage(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + language_code: Optional[StrictStr] = Field( + None, + alias="languageCode", + description="Language code for the correct character set. Possible values: `TR` for Turkish, `ES` for Spanish, `PT` for Portuguese, or `AUTODETECT` to let platform select the character set based on message content.", + ) + __properties = ["languageCode"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsLanguage: + """Create an instance of SmsLanguage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsLanguage: + """Create an instance of SmsLanguage from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsLanguage.parse_obj(obj) + + _obj = SmsLanguage.parse_obj({"language_code": obj.get("languageCode")}) + return _obj diff --git a/models/sms_language_configuration.py b/models/sms_language_configuration.py new file mode 100644 index 0000000..a6238f7 --- /dev/null +++ b/models/sms_language_configuration.py @@ -0,0 +1,78 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr +from models.sms_language import SmsLanguage + + +class SmsLanguageConfiguration(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + language: Optional[SmsLanguage] = None + transliteration: Optional[StrictStr] = Field( + None, + description="Conversion of a message text from one script to another. Possible values: `TURKISH`, `GREEK`, `CYRILLIC`, `SERBIAN_CYRILLIC`, `BULGARIAN_CYRILLIC`, `CENTRAL_EUROPEAN`, `BALTIC` and `NON_UNICODE`.", + ) + __properties = ["language", "transliteration"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsLanguageConfiguration: + """Create an instance of SmsLanguageConfiguration from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of language + if self.language: + _dict["language"] = self.language.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsLanguageConfiguration: + """Create an instance of SmsLanguageConfiguration from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsLanguageConfiguration.parse_obj(obj) + + _obj = SmsLanguageConfiguration.parse_obj( + { + "language": SmsLanguage.from_dict(obj.get("language")) + if obj.get("language") is not None + else None, + "transliteration": obj.get("transliteration"), + } + ) + return _obj diff --git a/models/sms_log.py b/models/sms_log.py new file mode 100644 index 0000000..12614c0 --- /dev/null +++ b/models/sms_log.py @@ -0,0 +1,146 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr +from models.sms_error import SmsError +from models.sms_price import SmsPrice +from models.sms_status import SmsStatus + + +class SmsLog(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field( + None, + alias="bulkId", + description="Unique ID assigned to the request if messaging multiple recipients or sending multiple messages via a single API request.", + ) + done_at: Optional[datetime] = Field( + None, + alias="doneAt", + description="Date and time when the Infobip services finished processing the message (i.e. delivered to the destination, delivered to the destination network, etc.). Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`.", + ) + error: Optional[SmsError] = None + var_from: Optional[StrictStr] = Field( + None, alias="from", description="Sender ID that can be alphanumeric or numeric." + ) + mcc_mnc: Optional[StrictStr] = Field( + None, alias="mccMnc", description="Mobile country and network codes." + ) + message_id: Optional[StrictStr] = Field( + None, alias="messageId", description="Unique message ID." + ) + price: Optional[SmsPrice] = None + sent_at: Optional[datetime] = Field( + None, + alias="sentAt", + description="Date and time when the message was [scheduled](https://www.infobip.com/docs/api#channels/sms/get-scheduled-sms-messages) to be sent. Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`.", + ) + sms_count: Optional[StrictInt] = Field( + None, + alias="smsCount", + description="The number of parts the message content was split into.", + ) + status: Optional[SmsStatus] = None + text: Optional[StrictStr] = Field( + None, description="Content of the message being sent." + ) + to: Optional[StrictStr] = Field( + None, description="The destination address of the message." + ) + __properties = [ + "bulkId", + "doneAt", + "error", + "from", + "mccMnc", + "messageId", + "price", + "sentAt", + "smsCount", + "status", + "text", + "to", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsLog: + """Create an instance of SmsLog from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of error + if self.error: + _dict["error"] = self.error.to_dict() + # override the default output from pydantic by calling `to_dict()` of price + if self.price: + _dict["price"] = self.price.to_dict() + # override the default output from pydantic by calling `to_dict()` of status + if self.status: + _dict["status"] = self.status.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsLog: + """Create an instance of SmsLog from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsLog.parse_obj(obj) + + _obj = SmsLog.parse_obj( + { + "bulk_id": obj.get("bulkId"), + "done_at": obj.get("doneAt"), + "error": SmsError.from_dict(obj.get("error")) + if obj.get("error") is not None + else None, + "var_from": obj.get("from"), + "mcc_mnc": obj.get("mccMnc"), + "message_id": obj.get("messageId"), + "price": SmsPrice.from_dict(obj.get("price")) + if obj.get("price") is not None + else None, + "sent_at": obj.get("sentAt"), + "sms_count": obj.get("smsCount"), + "status": SmsStatus.from_dict(obj.get("status")) + if obj.get("status") is not None + else None, + "text": obj.get("text"), + "to": obj.get("to"), + } + ) + return _obj diff --git a/models/sms_logs_response.py b/models/sms_logs_response.py new file mode 100644 index 0000000..2d2d178 --- /dev/null +++ b/models/sms_logs_response.py @@ -0,0 +1,77 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field +from models.sms_log import SmsLog + + +class SmsLogsResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[SmsLog]] = Field(None, description="Collection of logs.") + __properties = ["results"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsLogsResponse: + """Create an instance of SmsLogsResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsLogsResponse: + """Create an instance of SmsLogsResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsLogsResponse.parse_obj(obj) + + _obj = SmsLogsResponse.parse_obj( + { + "results": [SmsLog.from_dict(_item) for _item in obj.get("results")] + if obj.get("results") is not None + else None + } + ) + return _obj diff --git a/models/sms_preview.py b/models/sms_preview.py new file mode 100644 index 0000000..3f91759 --- /dev/null +++ b/models/sms_preview.py @@ -0,0 +1,98 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr +from models.sms_language_configuration import SmsLanguageConfiguration + + +class SmsPreview(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + text_preview: Optional[StrictStr] = Field( + None, + alias="textPreview", + description="Preview of the message content as it should appear on the recipient’s device.", + ) + message_count: Optional[StrictInt] = Field( + None, + alias="messageCount", + description="Number of SMS message parts required to deliver the message.", + ) + characters_remaining: Optional[StrictInt] = Field( + None, + alias="charactersRemaining", + description="Number of remaining characters in the last part of the SMS.", + ) + configuration: Optional[SmsLanguageConfiguration] = None + __properties = [ + "textPreview", + "messageCount", + "charactersRemaining", + "configuration", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsPreview: + """Create an instance of SmsPreview from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of configuration + if self.configuration: + _dict["configuration"] = self.configuration.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsPreview: + """Create an instance of SmsPreview from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsPreview.parse_obj(obj) + + _obj = SmsPreview.parse_obj( + { + "text_preview": obj.get("textPreview"), + "message_count": obj.get("messageCount"), + "characters_remaining": obj.get("charactersRemaining"), + "configuration": SmsLanguageConfiguration.from_dict( + obj.get("configuration") + ) + if obj.get("configuration") is not None + else None, + } + ) + return _obj diff --git a/models/sms_preview_request.py b/models/sms_preview_request.py new file mode 100644 index 0000000..8860f1d --- /dev/null +++ b/models/sms_preview_request.py @@ -0,0 +1,97 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr, constr, validator + + +class PreviewSMSRequestBody(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + text: StrictStr = Field(..., description="Content of the message being sent.") + language_code: Optional[constr(strict=True)] = Field( + None, + alias="languageCode", + description="Language code for the correct character set. Possible values: `TR` for Turkish, `ES` for Spanish, `PT` for Portuguese, or `AUTODETECT` to let platform select the character set based on message content.", + ) + transliteration: Optional[constr(strict=True)] = Field( + None, + description="The transliteration of your sent message from one script to another. Transliteration is used to replace characters which are not recognized as part of your defaulted alphabet. Possible values: `TURKISH`, `GREEK`, `CYRILLIC`, `SERBIAN_CYRILLIC`, `BULGARIAN_CYRILLIC`, `CENTRAL_EUROPEAN`, `BALTIC` and `NON_UNICODE`.", + ) + __properties = ["text", "languageCode", "transliteration"] + + @validator("language_code") + def language_code_validate_regular_expression(cls, v): + if not re.match(r"^(TR|ES|PT|AUTODETECT)$", v): + raise ValueError( + r"must validate the regular expression /^(TR|ES|PT|AUTODETECT)$/" + ) + return v + + @validator("transliteration") + def transliteration_validate_regular_expression(cls, v): + if not re.match( + r"^(TURKISH|GREEK|CYRILLIC|SERBIAN_CYRILLIC|BULGARIAN_CYRILLIC|CENTRAL_EUROPEAN|BALTIC|NON_UNICODE)$", + v, + ): + raise ValueError( + r"must validate the regular expression /^(TURKISH|GREEK|CYRILLIC|SERBIAN_CYRILLIC|BULGARIAN_CYRILLIC|CENTRAL_EUROPEAN|BALTIC|NON_UNICODE)$/" + ) + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> PreviewSMSRequestBody: + """Create an instance of SmsPreviewRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> PreviewSMSRequestBody: + """Create an instance of SmsPreviewRequest from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return PreviewSMSRequestBody.parse_obj(obj) + + _obj = PreviewSMSRequestBody.parse_obj( + { + "text": obj.get("text"), + "language_code": obj.get("languageCode"), + "transliteration": obj.get("transliteration"), + } + ) + return _obj diff --git a/models/sms_preview_response.py b/models/sms_preview_response.py new file mode 100644 index 0000000..3109eba --- /dev/null +++ b/models/sms_preview_response.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictStr +from models.sms_preview import SmsPreview + + +class PreviewSMSResponseBody(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + original_text: Optional[StrictStr] = Field( + None, + alias="originalText", + description="Message content supplied in the request.", + ) + previews: Optional[List[SmsPreview]] = Field( + None, + description="Allows for previewing the original message content once additional language configuration has been applied to it.", + ) + __properties = ["originalText", "previews"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> PreviewSMSResponseBody: + """Create an instance of SmsPreviewResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in previews (list) + _items = [] + if self.previews: + for _item in self.previews: + if _item: + _items.append(_item.to_dict()) + _dict["previews"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> PreviewSMSResponseBody: + """Create an instance of SmsPreviewResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return PreviewSMSResponseBody.parse_obj(obj) + + _obj = PreviewSMSResponseBody.parse_obj( + { + "original_text": obj.get("originalText"), + "previews": [ + SmsPreview.from_dict(_item) for _item in obj.get("previews") + ] + if obj.get("previews") is not None + else None, + } + ) + return _obj diff --git a/models/sms_price.py b/models/sms_price.py new file mode 100644 index 0000000..1488aa5 --- /dev/null +++ b/models/sms_price.py @@ -0,0 +1,73 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictFloat, StrictStr + + +class SmsPrice(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + price_per_message: Optional[StrictFloat] = Field( + None, alias="pricePerMessage", description="Price per one SMS." + ) + currency: Optional[StrictStr] = Field( + None, description="The currency in which the price is expressed." + ) + __properties = ["pricePerMessage", "currency"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsPrice: + """Create an instance of SmsPrice from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsPrice: + """Create an instance of SmsPrice from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsPrice.parse_obj(obj) + + _obj = SmsPrice.parse_obj( + { + "price_per_message": obj.get("pricePerMessage"), + "currency": obj.get("currency"), + } + ) + return _obj diff --git a/models/sms_regional_options.py b/models/sms_regional_options.py new file mode 100644 index 0000000..253ffce --- /dev/null +++ b/models/sms_regional_options.py @@ -0,0 +1,81 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field +from models.sms_india_dlt_options import SmsIndiaDltOptions +from models.sms_turkey_iys_options import SmsTurkeyIysOptions + + +class SmsRegionalOptions(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + india_dlt: Optional[SmsIndiaDltOptions] = Field(None, alias="indiaDlt") + turkey_iys: Optional[SmsTurkeyIysOptions] = Field(None, alias="turkeyIys") + __properties = ["indiaDlt", "turkeyIys"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsRegionalOptions: + """Create an instance of SmsRegionalOptions from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of india_dlt + if self.india_dlt: + _dict["indiaDlt"] = self.india_dlt.to_dict() + # override the default output from pydantic by calling `to_dict()` of turkey_iys + if self.turkey_iys: + _dict["turkeyIys"] = self.turkey_iys.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsRegionalOptions: + """Create an instance of SmsRegionalOptions from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsRegionalOptions.parse_obj(obj) + + _obj = SmsRegionalOptions.parse_obj( + { + "india_dlt": SmsIndiaDltOptions.from_dict(obj.get("indiaDlt")) + if obj.get("indiaDlt") is not None + else None, + "turkey_iys": SmsTurkeyIysOptions.from_dict(obj.get("turkeyIys")) + if obj.get("turkeyIys") is not None + else None, + } + ) + return _obj diff --git a/models/sms_report.py b/models/sms_report.py new file mode 100644 index 0000000..3ec835b --- /dev/null +++ b/models/sms_report.py @@ -0,0 +1,158 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr +from models.sms_error import SmsError +from models.sms_price import SmsPrice +from models.sms_status import SmsStatus + + +class SmsReport(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field( + None, + alias="bulkId", + description="Unique ID assigned to the request if messaging multiple recipients or sending multiple messages via a single API request.", + ) + message_id: Optional[StrictStr] = Field( + None, alias="messageId", description="Unique message ID." + ) + to: Optional[StrictStr] = Field(None, description="Message destination address.") + var_from: Optional[StrictStr] = Field( + None, + alias="from", + description="The sender ID which can be alphanumeric or numeric (e.g., `CompanyName`).", + ) + sent_at: Optional[datetime] = Field( + None, + alias="sentAt", + description="Date and time when the message was [scheduled](#channels/sms/get-scheduled-sms-messages) to be sent. Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`.", + ) + done_at: Optional[datetime] = Field( + None, + alias="doneAt", + description="Date and time when the Infobip services finished processing the message (i.e., delivered to the destination, delivered to the destination network, etc.). Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`.", + ) + sms_count: Optional[StrictInt] = Field( + None, + alias="smsCount", + description="The number of parts the message content was split into.", + ) + mcc_mnc: Optional[StrictStr] = Field( + None, alias="mccMnc", description="Mobile country and network codes." + ) + callback_data: Optional[StrictStr] = Field( + None, + alias="callbackData", + description="Custom data sent over to the `notifyUrl`.", + ) + price: Optional[SmsPrice] = None + status: Optional[SmsStatus] = None + error: Optional[SmsError] = None + entity_id: Optional[StrictStr] = Field( + None, alias="entityId", description="Entity used in SMS request." + ) + application_id: Optional[StrictStr] = Field( + None, alias="applicationId", description="Application used in SMS request." + ) + __properties = [ + "bulkId", + "messageId", + "to", + "from", + "sentAt", + "doneAt", + "smsCount", + "mccMnc", + "callbackData", + "price", + "status", + "error", + "entityId", + "applicationId", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsReport: + """Create an instance of SmsReport from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of price + if self.price: + _dict["price"] = self.price.to_dict() + # override the default output from pydantic by calling `to_dict()` of status + if self.status: + _dict["status"] = self.status.to_dict() + # override the default output from pydantic by calling `to_dict()` of error + if self.error: + _dict["error"] = self.error.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsReport: + """Create an instance of SmsReport from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsReport.parse_obj(obj) + + _obj = SmsReport.parse_obj( + { + "bulk_id": obj.get("bulkId"), + "message_id": obj.get("messageId"), + "to": obj.get("to"), + "var_from": obj.get("from"), + "sent_at": obj.get("sentAt"), + "done_at": obj.get("doneAt"), + "sms_count": obj.get("smsCount"), + "mcc_mnc": obj.get("mccMnc"), + "callback_data": obj.get("callbackData"), + "price": SmsPrice.from_dict(obj.get("price")) + if obj.get("price") is not None + else None, + "status": SmsStatus.from_dict(obj.get("status")) + if obj.get("status") is not None + else None, + "error": SmsError.from_dict(obj.get("error")) + if obj.get("error") is not None + else None, + "entity_id": obj.get("entityId"), + "application_id": obj.get("applicationId"), + } + ) + return _obj diff --git a/models/sms_response.py b/models/sms_response.py new file mode 100644 index 0000000..a8361ac --- /dev/null +++ b/models/sms_response.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictStr +from models.sms_response_details import SmsResponseDetails + + +class SmsResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field( + None, + alias="bulkId", + description="Unique ID assigned to the request if messaging multiple recipients or sending multiple messages via a single API request. Typically, used to fetch [delivery reports](#channels/sms/get-outbound-sms-message-delivery-reports) and [message logs](#channels/sms/get-outbound-sms-message-logs).", + ) + messages: Optional[List[SmsResponseDetails]] = Field( + None, + description="An array of message objects of a single message or multiple messages sent under one bulk ID.", + ) + __properties = ["bulkId", "messages"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsResponse: + """Create an instance of SmsResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in messages (list) + _items = [] + if self.messages: + for _item in self.messages: + if _item: + _items.append(_item.to_dict()) + _dict["messages"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsResponse: + """Create an instance of SmsResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsResponse.parse_obj(obj) + + _obj = SmsResponse.parse_obj( + { + "bulk_id": obj.get("bulkId"), + "messages": [ + SmsResponseDetails.from_dict(_item) for _item in obj.get("messages") + ] + if obj.get("messages") is not None + else None, + } + ) + return _obj diff --git a/models/sms_response_details.py b/models/sms_response_details.py new file mode 100644 index 0000000..3f20f55 --- /dev/null +++ b/models/sms_response_details.py @@ -0,0 +1,83 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr +from models.sms_status import SmsStatus + + +class SmsResponseDetails(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + message_id: Optional[StrictStr] = Field( + None, + alias="messageId", + description="Unique message ID. If not passed, it will be automatically generated and returned in a response.", + ) + status: Optional[SmsStatus] = None + to: Optional[StrictStr] = Field( + None, description="The destination address of the message." + ) + __properties = ["messageId", "status", "to"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsResponseDetails: + """Create an instance of SmsResponseDetails from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of status + if self.status: + _dict["status"] = self.status.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsResponseDetails: + """Create an instance of SmsResponseDetails from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsResponseDetails.parse_obj(obj) + + _obj = SmsResponseDetails.parse_obj( + { + "message_id": obj.get("messageId"), + "status": SmsStatus.from_dict(obj.get("status")) + if obj.get("status") is not None + else None, + "to": obj.get("to"), + } + ) + return _obj diff --git a/models/sms_sending_speed_limit.py b/models/sms_sending_speed_limit.py new file mode 100644 index 0000000..1d8c7c9 --- /dev/null +++ b/models/sms_sending_speed_limit.py @@ -0,0 +1,70 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictInt +from models.sms_speed_limit_time_unit import SmsSpeedLimitTimeUnit + + +class SmsSendingSpeedLimit(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + amount: StrictInt = Field( + ..., + description="The number of messages to be sent per timeUnit. By default, the system sends messages as fast as the infrastructure allows. Use this parameter to adapt sending capacity to your needs. The system is only able to work against its maximum capacity for ambitious message batches.", + ) + time_unit: Optional[SmsSpeedLimitTimeUnit] = Field(None, alias="timeUnit") + __properties = ["amount", "timeUnit"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsSendingSpeedLimit: + """Create an instance of SmsSendingSpeedLimit from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsSendingSpeedLimit: + """Create an instance of SmsSendingSpeedLimit from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsSendingSpeedLimit.parse_obj(obj) + + _obj = SmsSendingSpeedLimit.parse_obj( + {"amount": obj.get("amount"), "time_unit": obj.get("timeUnit")} + ) + return _obj diff --git a/models/sms_speed_limit_time_unit.py b/models/sms_speed_limit_time_unit.py new file mode 100644 index 0000000..42c05ff --- /dev/null +++ b/models/sms_speed_limit_time_unit.py @@ -0,0 +1,29 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from inspect import getfullargspec +import pprint +import re # noqa: F401 +from aenum import Enum, no_arg + + +class SmsSpeedLimitTimeUnit(str, Enum): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + allowed enum values + """ + + MINUTE = "MINUTE" + HOUR = "HOUR" + DAY = "DAY" diff --git a/models/sms_status.py b/models/sms_status.py new file mode 100644 index 0000000..b73857a --- /dev/null +++ b/models/sms_status.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr + + +class SmsStatus(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + group_id: Optional[StrictInt] = Field( + None, alias="groupId", description="Status group ID." + ) + group_name: Optional[StrictStr] = Field( + None, + alias="groupName", + description="Status group name that describes which category the status code belongs to, e.g. PENDING, UNDELIVERABLE, DELIVERED, EXPIRED, REJECTED.", + ) + id: Optional[StrictInt] = Field(None, description="Status ID.") + name: Optional[StrictStr] = Field( + None, + description="[Status name](https://www.infobip.com/docs/essentials/response-status-and-error-codes).", + ) + description: Optional[StrictStr] = Field( + None, description="Human-readable description of the status." + ) + action: Optional[StrictStr] = Field( + None, description="Action that should be taken to recover from the error." + ) + __properties = ["groupId", "groupName", "id", "name", "description", "action"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsStatus: + """Create an instance of SmsStatus from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsStatus: + """Create an instance of SmsStatus from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsStatus.parse_obj(obj) + + _obj = SmsStatus.parse_obj( + { + "group_id": obj.get("groupId"), + "group_name": obj.get("groupName"), + "id": obj.get("id"), + "name": obj.get("name"), + "description": obj.get("description"), + "action": obj.get("action"), + } + ) + return _obj diff --git a/models/sms_textual_message.py b/models/sms_textual_message.py new file mode 100644 index 0000000..b76a71e --- /dev/null +++ b/models/sms_textual_message.py @@ -0,0 +1,195 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import List, Optional +from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, constr +from models.sms_delivery_time_window import SmsDeliveryTimeWindow +from models.sms_destination import Destination +from models.sms_language import SmsLanguage +from models.sms_regional_options import SmsRegionalOptions + + +class Message(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + callback_data: Optional[constr(strict=True, max_length=4000, min_length=0)] = Field( + None, + alias="callbackData", + description="Additional data that can be used for identifying, managing, or monitoring a message. Data included here will also be automatically included in the message [Delivery Report](#channels/sms/get-outbound-sms-message-delivery-reports). The maximum value is 4000 characters and any overhead may be truncated.", + ) + delivery_time_window: Optional[SmsDeliveryTimeWindow] = Field( + None, alias="deliveryTimeWindow" + ) + destinations: List[Destination] = Field( + ..., + description="An array of destination objects for where messages are being sent. A valid destination is required.", + ) + flash: Optional[StrictBool] = Field( + False, + description="Allows for sending a [flash SMS](https://www.infobip.com/docs/sms/message-types#flash-sms) to automatically appear on recipient devices without interaction. Set to `true` to enable flash SMS, or leave the default value, `false` to send a standard SMS.", + ) + var_from: Optional[StrictStr] = Field( + None, + alias="from", + description="The sender ID which can be alphanumeric or numeric (e.g., `CompanyName`). Make sure you don't exceed [character limit](https://www.infobip.com/docs/sms/get-started#sender-names).", + ) + intermediate_report: Optional[StrictBool] = Field( + None, + alias="intermediateReport", + description="The [real-time intermediate delivery report](#channels/sms/receive-outbound-sms-message-report) containing GSM error codes, messages status, pricing, network and country codes, etc., which will be sent on your callback server. Defaults to `false`.", + ) + language: Optional[SmsLanguage] = None + notify_content_type: Optional[StrictStr] = Field( + None, + alias="notifyContentType", + description="Preferred delivery report content type, `application/json` or `application/xml`.", + ) + notify_url: Optional[StrictStr] = Field( + None, + alias="notifyUrl", + description="The URL on your call back server on to which a delivery report will be sent. The [retry cycle](https://www.infobip.com/docs/sms/api#notify-url) for when your URL becomes unavailable uses the following formula: `1min + (1min * retryNumber * retryNumber)`.", + ) + regional: Optional[SmsRegionalOptions] = None + send_at: Optional[datetime] = Field( + None, + alias="sendAt", + description="Date and time when the message is to be sent. Used for [scheduled SMS](#channels/sms/get-scheduled-sms-messages). Has the following format: `yyyy-MM-dd'T'HH:mm:ss.SSSZ`, and can only be scheduled for no later than 180 days in advance.", + ) + text: Optional[StrictStr] = Field( + None, description="Content of the message being sent." + ) + transliteration: Optional[StrictStr] = Field( + None, + description="The transliteration of your sent message from one script to another. Transliteration is used to replace characters which are not recognized as part of your defaulted alphabet. Possible values: `TURKISH`, `GREEK`, `CYRILLIC`, `SERBIAN_CYRILLIC`, `BULGARIAN_CYRILLIC`, `CENTRAL_EUROPEAN`, `BALTIC` and `NON_UNICODE`.", + ) + validity_period: Optional[StrictInt] = Field( + None, + alias="validityPeriod", + description="The message validity period in minutes. When the period expires, it will not be allowed for the message to be sent. Validity period longer than 48h is not supported. Any bigger value will automatically default back to `2880`.", + ) + entity_id: Optional[constr(strict=True, max_length=50, min_length=0)] = Field( + None, + alias="entityId", + description="Required for entity use in a send request for outbound traffic. Returned in notification events. For more details, see our [documentation](https://www.infobip.com/docs/cpaas-x/application-and-entity-management).", + ) + application_id: Optional[constr(strict=True, max_length=50, min_length=0)] = Field( + None, + alias="applicationId", + description="Required for application use in a send request for outbound traffic. Returned in notification events. For more details, see our [documentation](https://www.infobip.com/docs/cpaas-x/application-and-entity-management).", + ) + __properties = [ + "callbackData", + "deliveryTimeWindow", + "destinations", + "flash", + "from", + "intermediateReport", + "language", + "notifyContentType", + "notifyUrl", + "regional", + "sendAt", + "text", + "transliteration", + "validityPeriod", + "entityId", + "applicationId", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Message: + """Create an instance of SmsTextualMessage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of delivery_time_window + if self.delivery_time_window: + _dict["deliveryTimeWindow"] = self.delivery_time_window.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in destinations (list) + _items = [] + if self.destinations: + for _item in self.destinations: + if _item: + _items.append(_item.to_dict()) + _dict["destinations"] = _items + # override the default output from pydantic by calling `to_dict()` of language + if self.language: + _dict["language"] = self.language.to_dict() + # override the default output from pydantic by calling `to_dict()` of regional + if self.regional: + _dict["regional"] = self.regional.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> Message: + """Create an instance of SmsTextualMessage from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return Message.parse_obj(obj) + + _obj = Message.parse_obj( + { + "callback_data": obj.get("callbackData"), + "delivery_time_window": SmsDeliveryTimeWindow.from_dict( + obj.get("deliveryTimeWindow") + ) + if obj.get("deliveryTimeWindow") is not None + else None, + "destinations": [ + Destination.from_dict(_item) for _item in obj.get("destinations") + ] + if obj.get("destinations") is not None + else None, + "flash": obj.get("flash") if obj.get("flash") is not None else False, + "var_from": obj.get("from"), + "intermediate_report": obj.get("intermediateReport"), + "language": SmsLanguage.from_dict(obj.get("language")) + if obj.get("language") is not None + else None, + "notify_content_type": obj.get("notifyContentType"), + "notify_url": obj.get("notifyUrl"), + "regional": SmsRegionalOptions.from_dict(obj.get("regional")) + if obj.get("regional") is not None + else None, + "send_at": obj.get("sendAt"), + "text": obj.get("text"), + "transliteration": obj.get("transliteration"), + "validity_period": obj.get("validityPeriod"), + "entity_id": obj.get("entityId"), + "application_id": obj.get("applicationId"), + } + ) + return _obj diff --git a/models/sms_tracking.py b/models/sms_tracking.py new file mode 100644 index 0000000..a58dd02 --- /dev/null +++ b/models/sms_tracking.py @@ -0,0 +1,87 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictStr + + +class SmsTracking(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + base_url: Optional[StrictStr] = Field( + None, + alias="baseUrl", + description="Custom base URL for shortened links in messages when tracking URL conversions. Legacy - use `urlOptions` instead.", + ) + process_key: Optional[StrictStr] = Field( + None, + alias="processKey", + description="The process key which uniquely identifies conversion tracking.", + ) + track: Optional[StrictStr] = Field( + None, + description="Indicates if a message has to be tracked for conversion rates. Values are: `SMS` and `URL`. `URL` is a legacy value. Use `urlOptions` instead. For more details on SMS Conversion, see: [Track Conversion](https://www.infobip.com/docs/sms/api#track-conversion).", + ) + type: Optional[StrictStr] = Field( + None, + description="Sets a custom conversion type naming convention, e.g. `ONE_TIME_PIN` or `SOCIAL_INVITES`.", + ) + __properties = ["baseUrl", "processKey", "track", "type"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsTracking: + """Create an instance of SmsTracking from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsTracking: + """Create an instance of SmsTracking from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsTracking.parse_obj(obj) + + _obj = SmsTracking.parse_obj( + { + "base_url": obj.get("baseUrl"), + "process_key": obj.get("processKey"), + "track": obj.get("track"), + "type": obj.get("type"), + } + ) + return _obj diff --git a/models/sms_turkey_iys_options.py b/models/sms_turkey_iys_options.py new file mode 100644 index 0000000..8366bfb --- /dev/null +++ b/models/sms_turkey_iys_options.py @@ -0,0 +1,83 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr, validator + + +class SmsTurkeyIysOptions(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + brand_code: Optional[StrictInt] = Field( + None, + alias="brandCode", + description="Brand code is an ID of the company based on a company VAT number. If not provided in request, default value is used from your Infobip account.", + ) + recipient_type: StrictStr = Field( + ..., + alias="recipientType", + description="Recipient Type must be `TACIR` or `BIREYSEL`.", + ) + __properties = ["brandCode", "recipientType"] + + @validator("recipient_type") + def recipient_type_validate_enum(cls, v): + if v not in ("BIREYSEL", "TACIR"): + raise ValueError("must validate the enum values ('BIREYSEL', 'TACIR')") + return v + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsTurkeyIysOptions: + """Create an instance of SmsTurkeyIysOptions from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsTurkeyIysOptions: + """Create an instance of SmsTurkeyIysOptions from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsTurkeyIysOptions.parse_obj(obj) + + _obj = SmsTurkeyIysOptions.parse_obj( + { + "brand_code": obj.get("brandCode"), + "recipient_type": obj.get("recipientType"), + } + ) + return _obj diff --git a/models/sms_update_status_request.py b/models/sms_update_status_request.py new file mode 100644 index 0000000..de9a9af --- /dev/null +++ b/models/sms_update_status_request.py @@ -0,0 +1,63 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from pydantic import BaseModel +from models.sms_bulk_status import SmsBulkStatus + + +class SmsUpdateStatusRequest(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + status: SmsBulkStatus = ... + __properties = ["status"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsUpdateStatusRequest: + """Create an instance of SmsUpdateStatusRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsUpdateStatusRequest: + """Create an instance of SmsUpdateStatusRequest from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsUpdateStatusRequest.parse_obj(obj) + + _obj = SmsUpdateStatusRequest.parse_obj({"status": obj.get("status")}) + return _obj diff --git a/models/sms_url_options.py b/models/sms_url_options.py new file mode 100644 index 0000000..23f2c3c --- /dev/null +++ b/models/sms_url_options.py @@ -0,0 +1,107 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictBool, StrictStr + + +class SmsUrlOptions(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + shorten_url: Optional[StrictBool] = Field( + True, + alias="shortenUrl", + description="Enable shortening of the URLs within a message. Set this to `true`, if you want to set up other URL options.", + ) + track_clicks: Optional[StrictBool] = Field( + True, + alias="trackClicks", + description="Enable tracking of short URL clicks within a message: which URL was clicked, how many times, and by whom.", + ) + tracking_url: Optional[StrictStr] = Field( + None, + alias="trackingUrl", + description="The URL of your callback server on to which the Click report will be sent.", + ) + remove_protocol: Optional[StrictBool] = Field( + False, + alias="removeProtocol", + description="Remove a protocol, such as `https://`, from links to shorten a message. Note that some mobiles may not recognize such links as a URL.", + ) + custom_domain: Optional[StrictStr] = Field( + None, + alias="customDomain", + description="Select a predefined custom domain to use when generating a short URL.", + ) + __properties = [ + "shortenUrl", + "trackClicks", + "trackingUrl", + "removeProtocol", + "customDomain", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsUrlOptions: + """Create an instance of SmsUrlOptions from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsUrlOptions: + """Create an instance of SmsUrlOptions from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsUrlOptions.parse_obj(obj) + + _obj = SmsUrlOptions.parse_obj( + { + "shorten_url": obj.get("shortenUrl") + if obj.get("shortenUrl") is not None + else True, + "track_clicks": obj.get("trackClicks") + if obj.get("trackClicks") is not None + else True, + "tracking_url": obj.get("trackingUrl"), + "remove_protocol": obj.get("removeProtocol") + if obj.get("removeProtocol") is not None + else False, + "custom_domain": obj.get("customDomain"), + } + ) + return _obj diff --git a/models/sms_webhook_inbound_report.py b/models/sms_webhook_inbound_report.py new file mode 100644 index 0000000..f2fedc5 --- /dev/null +++ b/models/sms_webhook_inbound_report.py @@ -0,0 +1,124 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr +from models.message_price import MessagePrice + + +class SmsWebhookInboundReport(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + message_id: Optional[StrictStr] = Field( + None, alias="messageId", description="Unique SMS ID." + ) + var_from: Optional[StrictStr] = Field( + None, alias="from", description="Sender ID that can be alphanumeric or numeric." + ) + to: Optional[StrictStr] = Field(None, description="The recipient number.") + text: Optional[StrictStr] = Field(None, description="Received message content.") + clean_text: Optional[StrictStr] = Field( + None, + alias="cleanText", + description="Text of received message without a keyword (if a keyword was sent).", + ) + keyword: Optional[StrictStr] = Field( + None, description="Keyword extracted from the message text." + ) + received_at: Optional[datetime] = Field( + None, + alias="receivedAt", + description="Date and time when Infobip received the message.", + ) + sms_count: Optional[StrictInt] = Field( + None, + alias="smsCount", + description="Long SMS messages have a character limit on how much can be sent over one message. Longer messages will be split up into multiple messages and sent separately. This is the total count of messages one SMS was sent over.", + ) + price: Optional[MessagePrice] = None + callback_data: Optional[StrictStr] = Field( + None, + alias="callbackData", + description="The callback data sent through the callbackData field in your fully featured SMS message.", + ) + __properties = [ + "messageId", + "from", + "to", + "text", + "cleanText", + "keyword", + "receivedAt", + "smsCount", + "price", + "callbackData", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsWebhookInboundReport: + """Create an instance of SmsWebhookInboundReport from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of price + if self.price: + _dict["price"] = self.price.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsWebhookInboundReport: + """Create an instance of SmsWebhookInboundReport from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsWebhookInboundReport.parse_obj(obj) + + _obj = SmsWebhookInboundReport.parse_obj( + { + "message_id": obj.get("messageId"), + "var_from": obj.get("from"), + "to": obj.get("to"), + "text": obj.get("text"), + "clean_text": obj.get("cleanText"), + "keyword": obj.get("keyword"), + "received_at": obj.get("receivedAt"), + "sms_count": obj.get("smsCount"), + "price": MessagePrice.from_dict(obj.get("price")) + if obj.get("price") is not None + else None, + "callback_data": obj.get("callbackData"), + } + ) + return _obj diff --git a/models/sms_webhook_inbound_report_response.py b/models/sms_webhook_inbound_report_response.py new file mode 100644 index 0000000..412a5c7 --- /dev/null +++ b/models/sms_webhook_inbound_report_response.py @@ -0,0 +1,92 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field, StrictInt +from models.sms_webhook_inbound_report import SmsWebhookInboundReport + + +class SmsWebhookInboundReportResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[SmsWebhookInboundReport]] = None + message_count: Optional[StrictInt] = Field( + None, + alias="messageCount", + description="Number of returned messages in this request.", + ) + pending_message_count: Optional[StrictInt] = Field( + None, + alias="pendingMessageCount", + description="Number of remaining new messages on Infobip servers ready to be returned in the next request.", + ) + __properties = ["results", "messageCount", "pendingMessageCount"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsWebhookInboundReportResponse: + """Create an instance of SmsWebhookInboundReportResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsWebhookInboundReportResponse: + """Create an instance of SmsWebhookInboundReportResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsWebhookInboundReportResponse.parse_obj(obj) + + _obj = SmsWebhookInboundReportResponse.parse_obj( + { + "results": [ + SmsWebhookInboundReport.from_dict(_item) + for _item in obj.get("results") + ] + if obj.get("results") is not None + else None, + "message_count": obj.get("messageCount"), + "pending_message_count": obj.get("pendingMessageCount"), + } + ) + return _obj diff --git a/models/sms_webhook_outbound_report.py b/models/sms_webhook_outbound_report.py new file mode 100644 index 0000000..d3bc8dd --- /dev/null +++ b/models/sms_webhook_outbound_report.py @@ -0,0 +1,151 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import Optional +from pydantic import BaseModel, Field, StrictInt, StrictStr +from models.message_error import MessageError +from models.message_price import MessagePrice +from models.message_status import MessageStatus + + +class SmsWebhookOutboundReport(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + bulk_id: Optional[StrictStr] = Field( + None, + alias="bulkId", + description="Unique ID attributed to messages sent to multiple recipients.", + ) + message_id: Optional[StrictStr] = Field( + None, + alias="messageId", + description="Unique SMS ID for individual messages sent.", + ) + to: Optional[StrictStr] = Field(None, description="Recipient number.") + sent_at: Optional[datetime] = Field( + None, alias="sentAt", description="Date and time the message was sent." + ) + done_at: Optional[datetime] = Field( + None, + alias="doneAt", + description="Date and time the message was finished processing by Infobip. This is when the message was delivered to the specified destination.", + ) + sms_count: Optional[StrictInt] = Field( + None, + alias="smsCount", + description="Long SMS messages have a character limit on how much can be sent over one message. Longer messages will be split up into multiple messages and sent separately. This is the total count of messages one SMS was sent over.", + ) + mcc_mnc: Optional[StrictStr] = Field( + None, alias="mccMnc", description="Mobile country and network codes." + ) + callback_data: Optional[StrictStr] = Field( + None, + alias="callbackData", + description="The callback data sent through the callbackData field in your fully featured SMS message.", + ) + price: Optional[MessagePrice] = None + status: Optional[MessageStatus] = None + error: Optional[MessageError] = None + entity_id: Optional[StrictStr] = Field( + None, alias="entityId", description="Entity used in SMS request." + ) + application_id: Optional[StrictStr] = Field( + None, alias="applicationId", description="Application used in SMS request." + ) + __properties = [ + "bulkId", + "messageId", + "to", + "sentAt", + "doneAt", + "smsCount", + "mccMnc", + "callbackData", + "price", + "status", + "error", + "entityId", + "applicationId", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsWebhookOutboundReport: + """Create an instance of SmsWebhookOutboundReport from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of price + if self.price: + _dict["price"] = self.price.to_dict() + # override the default output from pydantic by calling `to_dict()` of status + if self.status: + _dict["status"] = self.status.to_dict() + # override the default output from pydantic by calling `to_dict()` of error + if self.error: + _dict["error"] = self.error.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsWebhookOutboundReport: + """Create an instance of SmsWebhookOutboundReport from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsWebhookOutboundReport.parse_obj(obj) + + _obj = SmsWebhookOutboundReport.parse_obj( + { + "bulk_id": obj.get("bulkId"), + "message_id": obj.get("messageId"), + "to": obj.get("to"), + "sent_at": obj.get("sentAt"), + "done_at": obj.get("doneAt"), + "sms_count": obj.get("smsCount"), + "mcc_mnc": obj.get("mccMnc"), + "callback_data": obj.get("callbackData"), + "price": MessagePrice.from_dict(obj.get("price")) + if obj.get("price") is not None + else None, + "status": MessageStatus.from_dict(obj.get("status")) + if obj.get("status") is not None + else None, + "error": MessageError.from_dict(obj.get("error")) + if obj.get("error") is not None + else None, + "entity_id": obj.get("entityId"), + "application_id": obj.get("applicationId"), + } + ) + return _obj diff --git a/models/sms_webhook_outbound_report_response.py b/models/sms_webhook_outbound_report_response.py new file mode 100644 index 0000000..8f7df8a --- /dev/null +++ b/models/sms_webhook_outbound_report_response.py @@ -0,0 +1,82 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import List, Optional +from pydantic import BaseModel, Field +from models.sms_webhook_outbound_report import SmsWebhookOutboundReport + + +class SmsWebhookOutboundReportResponse(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + results: Optional[List[SmsWebhookOutboundReport]] = Field( + None, description="The array of objects for your sent messages." + ) + __properties = ["results"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> SmsWebhookOutboundReportResponse: + """Create an instance of SmsWebhookOutboundReportResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item in self.results: + if _item: + _items.append(_item.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> SmsWebhookOutboundReportResponse: + """Create an instance of SmsWebhookOutboundReportResponse from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return SmsWebhookOutboundReportResponse.parse_obj(obj) + + _obj = SmsWebhookOutboundReportResponse.parse_obj( + { + "results": [ + SmsWebhookOutboundReport.from_dict(_item) + for _item in obj.get("results") + ] + if obj.get("results") is not None + else None + } + ) + return _obj diff --git a/models/webhook_message_count.py b/models/webhook_message_count.py new file mode 100644 index 0000000..84b5351 --- /dev/null +++ b/models/webhook_message_count.py @@ -0,0 +1,77 @@ +# coding: utf-8 + +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import annotations +from inspect import getfullargspec +import pprint +import re # noqa: F401 +import json + + +from typing import Optional +from pydantic import BaseModel, Field, StrictInt + + +class WebhookMessageCount(BaseModel): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + message_count: Optional[StrictInt] = Field( + None, + alias="messageCount", + description="Number of returned messages in this request.", + ) + pending_message_count: Optional[StrictInt] = Field( + None, + alias="pendingMessageCount", + description="Number of remaining new messages on Infobip servers ready to be returned in the next request.", + ) + __properties = ["messageCount", "pendingMessageCount"] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> WebhookMessageCount: + """Create an instance of WebhookMessageCount from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> WebhookMessageCount: + """Create an instance of WebhookMessageCount from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return WebhookMessageCount.parse_obj(obj) + + _obj = WebhookMessageCount.parse_obj( + { + "message_count": obj.get("messageCount"), + "pending_message_count": obj.get("pendingMessageCount"), + } + ) + return _obj diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..657d93c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +pydantic~=1.10.7 +httpx~=0.24.0 +aenum~=3.1.12 \ No newline at end of file diff --git a/requirements/common.txt b/requirements/common.txt deleted file mode 100644 index 1a9c8ce..0000000 --- a/requirements/common.txt +++ /dev/null @@ -1,3 +0,0 @@ -pydantic==1.9.0 -requests==2.27.1 -regex==2022.3.15 diff --git a/requirements/dev.txt b/requirements/dev.txt deleted file mode 100644 index 8acbe8a..0000000 --- a/requirements/dev.txt +++ /dev/null @@ -1,9 +0,0 @@ --r common.txt -pytest==6.2.5 -pytest-httpserver==1.0.4 -pydantic-factories==1.2.3 -pre-commit==2.17.0 -pytest-cases==3.6.8 -pytest-cov==3.0.0 -wheel==0.38.0 -setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability diff --git a/samples/app_entity_management/test_entity_management.py b/samples/app_entity_management/test_entity_management.py deleted file mode 100644 index e349b23..0000000 --- a/samples/app_entity_management/test_entity_management.py +++ /dev/null @@ -1,40 +0,0 @@ -import unittest -from http import HTTPStatus - -import pytest - -from infobip_platform.app_entities.api import ApplicationEntityManagement - - -@pytest.mark.skip(reason="credentials needed, server state dependent") -class EntityManagementTestCase(unittest.TestCase): - api = ApplicationEntityManagement.from_env() - - def test_get_entities(self): - query_parameters = {"page": 0, "size": 5} - response = EntityManagementTestCase.api.get_entities(query_parameters) - - self.assertIsNotNone(response) - self.assertEqual(HTTPStatus.OK, response.status_code) - - def test_create_entity(self): - entity_body = {"entityName": "A cool Entity", "entityId": "test-entity"} - response = EntityManagementTestCase.api.create_entity(entity_body) - - self.assertIsNotNone(response) - self.assertEqual(HTTPStatus.CREATED, response.status_code) - - def test_get_entity(self): - response = EntityManagementTestCase.api.get_entity("test-entity") - - self.assertIsNotNone(response) - self.assertEqual(HTTPStatus.OK, response.status_code) - - def test_modify_entity(self): - entity_body = {"entityName": "An even cooler Entity"} - response = EntityManagementTestCase.api.modify_entity( - "test-entity", entity_body - ) - - self.assertIsNotNone(response) - self.assertEqual(HTTPStatus.NO_CONTENT, response.status_code) diff --git a/samples/test_sms_live.py b/samples/test_sms_live.py new file mode 100644 index 0000000..da881a4 --- /dev/null +++ b/samples/test_sms_live.py @@ -0,0 +1,54 @@ +import unittest + +from client import InfobipAPIClient +from models import SendRequestBody, Message, Destination +from models.sms_preview_request import PreviewSMSRequestBody +from models.sms_preview_response import PreviewSMSResponseBody + + +class SMSTestCase(unittest.IsolatedAsyncioTestCase): + client = InfobipAPIClient() + + async def test_preview_message(self): + # Create a request body object and validate its contents. + request_body = PreviewSMSRequestBody( + text="Let's see how many characters remain unused in this message." + ) + + # Call the endpoint and await returned Coroutine + response = await self.client.SMS.preview_message(request_body) + + # Parse and validate response if needed. + response_body = PreviewSMSResponseBody.from_json(response.text) + + # Do something with the response. + print(response) + print(response_body.previews) + + self.assertEqual(response.status_code, 200) + + async def test_send_message(self): + # Create a request body object and validate its contents. + request_body = SendRequestBody( + messages=[ + Message( + destinations=[ + Destination( + to="523311800428", + ), + ], + text="Hello from Infobip Python SDK!", + ) + ] + ) + + # Call the endpoint and await returned Coroutine + response = await self.client.SMS.send(request_body) + + # (Optional) Parse and validate response if needed. + response_body = PreviewSMSResponseBody.from_json(response.text) + + # Do something with the response. + print(response) + + self.assertEqual(response.status_code, 200) diff --git a/samples/tfa/test_tfa.py b/samples/tfa/test_tfa.py deleted file mode 100644 index f6d5ead..0000000 --- a/samples/tfa/test_tfa.py +++ /dev/null @@ -1,192 +0,0 @@ -import unittest -from http import HTTPStatus - -import pytest - -from infobip_channels.sms.channel import SMSChannel - - -@pytest.mark.skip(reason="credentials needed, server state dependent") -class TFATestCase(unittest.TestCase): - channel = SMSChannel.from_env() - - def test_get_tfa_applications(self): - response = TFATestCase.channel.get_tfa_applications() - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_create_tfa_application(self): - application = { - "name": "2fa application test", - "enabled": "true", - "configuration": { - "pinAttempts": 7, - "allowMultiplePinVerifications": "true", - "pinTimeToLive": "11m", - "verifyPinLimit": "2/4s", - "sendPinPerApplicationLimit": "5000/12h", - "sendPinPerPhoneNumberLimit": "2/1d", - }, - } - response = TFATestCase.channel.create_tfa_application(application) - - self.assertEqual(HTTPStatus.CREATED, response.status_code) - self.assertIsNotNone(response) - - def test_get_tfa_application(self): - response = TFATestCase.channel.get_tfa_application( - "02CC3CAAFD733136AA15DFAC720A0C42" - ) - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_update_tfa_application(self): - application = { - "name": "test-tfa_application-3", - "enabled": "true", - "configuration": { - "pinAttempts": 9, - "allowMultiplePinVerifications": "true", - "pinTimeToLive": "11m", - "verifyPinLimit": "2/4s", - "sendPinPerApplicationLimit": "5000/12h", - "sendPinPerPhoneNumberLimit": "2/1d", - }, - } - - response = TFATestCase.channel.update_tfa_application( - "02CC3CAAFD733136AA15DFAC720A0C42", application - ) - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_get_tfa_message_templates(self): - response = TFATestCase.channel.get_tfa_message_templates( - "02CC3CAAFD733136AA15DFAC720A0C42" - ) - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_create_tfa_message_template(self): - app_id = "02CC3CAAFD733136AA15DFAC720A0C42" - request_body = { - "pinType": "NUMERIC", - "pinPlaceholder": "{{pin}}", - "messageText": "Your pin is {{pin}}", - "pinLength": 4, - "language": "en", - "senderId": "Infobip 2FA", - "repeatDTMF": "1#", - "speechRate": 1, - } - - response = TFATestCase.channel.create_tfa_message_template(app_id, request_body) - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_get_tfa_message_template(self): - app_id = "02CC3CAAFD733136AA15DFAC720A0C42" - message_id = "2140E0A55D9E4A46429D65E218091C64" - - response = TFATestCase.channel.get_tfa_message_template(app_id, message_id) - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_update_tfa_message_template(self): - app_id = "02CC3CAAFD733136AA15DFAC720A0C42" - message_id = "2140E0A55D9E4A46429D65E218091C64" - request_body = { - "pinType": "NUMERIC", - "pinPlaceholder": "{{pin}}", - "messageText": "The PIN is {{pin}}", - "pinLength": 6, - "language": "en", - "senderId": "Infobip 2FA", - "repeatDTMF": "2#", - "speechRate": 1, - } - - response = TFATestCase.channel.update_tfa_message_template( - app_id, message_id, request_body - ) - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_send_pin_over_sms(self): - query_parameters = {"ncNeeded": "false"} - request_body = { - "applicationId": "43D78365E3257420D78752A62845A8CB", - "messageId": "9AD26BD115AB45657A0FEACACCC918BE", - "from": "InfoSMS", - "to": "555555555555", - "placeholders": { - "name": "John", - }, - } - - response = TFATestCase.channel.send_pin_over_sms(query_parameters, request_body) - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_resend_pin_over_sms(self): - placeholders = {"placeholders": {"name": "John"}} - - response = TFATestCase.channel.resend_pin_over_sms( - "B147E121929711EC4163A6FB5B44CD59", placeholders - ) - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_send_pin_over_voice(self): - query_parameters = {"ncNeeded": "false"} - request_body = { - "applicationId": "02CC3CAAFD733136AA15DFAC720A0C42", - "messageId": "2140E0A55D9E4A46429D65E218091C64", - "from": "InfoSMS", - "to": "555555555555", - } - - response = TFATestCase.channel.send_pin_over_voice( - query_parameters, request_body - ) - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_resend_pin_over_voice(self): - placeholders = {"placeholders": {"name": "John"}} - - response = TFATestCase.channel.resend_pin_over_voice( - "B147E121929711EC4163A6FB5B44CD59", placeholders - ) - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_verify_number(self): - pin_id = "B147E121929711EC4163A6FB5B44CD59" - request_body = {"pin": "1234"} - - response = TFATestCase.channel.verify_phone_number(pin_id, request_body) - - self.assertEqual(HTTPStatus.OK, response.status_code) - self.assertIsNotNone(response) - - def test_get_tfa_verification_status(self): - app_id = "02CC3CAAFD733136AA15DFAC720A0C42" - query_parameters = {"msisdn": "555555555555"} - - response = TFATestCase.channel.get_tfa_verification_status( - app_id, query_parameters - ) - - self.assertEqual(HTTPStatus.OK, response.status_code) diff --git a/samples/whatsapp/test_whatsapp.py b/samples/whatsapp/test_whatsapp.py deleted file mode 100644 index 8e5c768..0000000 --- a/samples/whatsapp/test_whatsapp.py +++ /dev/null @@ -1,19 +0,0 @@ -import unittest - -import pytest - -from infobip_channels.whatsapp.channel import WhatsAppChannel -from infobip_channels.whatsapp.models.path_parameters.manage_templates import ( - ManageTemplatesPathParameters, -) - - -@pytest.mark.skip(reason="credentials needed, server state dependent") -class WhatsAppTestCase(unittest.TestCase): - def test_get_templates(self): - channel = WhatsAppChannel.from_env() - path_parameter = ManageTemplatesPathParameters(sender="447860099299") - response = channel.get_templates(path_parameter) - - self.assertEqual(response.status_code, 200) - self.assertIsNotNone(response.raw_response) diff --git a/tests/app_entities/conftest.py b/tests/app_entities/conftest.py deleted file mode 100644 index 1e15969..0000000 --- a/tests/app_entities/conftest.py +++ /dev/null @@ -1,71 +0,0 @@ -from pydantic_factories import ModelFactory - -from infobip_platform.app_entities.models.body.create_entity import CreateEntityBody -from infobip_platform.app_entities.models.body.modify_entity import ModifyEntityBody - - -def get_get_entities_response(): - return { - "results": [{"entityName": "Test name", "entityId": "test-entity"}], - "paging": {"page": 0, "size": 1, "totalPages": 0, "totalResults": 0}, - } - - -def get_create_entity_request_error_response(): - return { - "requestError": { - "serviceException": { - "messageId": "BAD_REQUEST", - "text": "Bad request", - "validationErrors": { - "request.message.content.media.file.url": ["is not a valid url"], - }, - } - } - } - - -def get_create_entity_body(): - return {"entityName": "Test name", "entityId": "test-entity"} - - -class GenerateCreateEntityBodyFactoryIntegration(ModelFactory): - __model__ = CreateEntityBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return CreateEntityBody(**get_create_entity_body()) - - -class GenerateModifyEntityBodyFactoryIntegration(ModelFactory): - __model__ = ModifyEntityBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return ModifyEntityBody(**get_modify_entity_body()) - - -def get_create_entity_response(): - return None - - -def get_get_entity_response(): - return {"entityName": "Test name", "entityId": "test-entity"} - - -def get_get_entity_request_error_response(): - return get_create_entity_request_error_response() - - -def get_modify_entity_body(): - return {"entityName": "Test name"} - - -def get_modify_entity_response(): - return None - - -def get_modify_entity_request_error_response(): - return get_get_entity_request_error_response() diff --git a/tests/app_entities/integration/test_create_entity_body.py b/tests/app_entities/integration/test_create_entity_body.py deleted file mode 100644 index bef841f..0000000 --- a/tests/app_entities/integration/test_create_entity_body.py +++ /dev/null @@ -1,108 +0,0 @@ -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_platform.app_entities.api import ApplicationEntityManagement -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - message_body_instance = request_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = ApplicationEntityManagement.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)(request_body) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - - assert response.status_code == status_code - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/app_entities/integration/test_create_entity_body_cases.py b/tests/app_entities/integration/test_create_entity_body_cases.py deleted file mode 100644 index b3e1908..0000000 --- a/tests/app_entities/integration/test_create_entity_body_cases.py +++ /dev/null @@ -1,63 +0,0 @@ -from pytest_cases import parametrize - -from tests.app_entities.conftest import ( - GenerateCreateEntityBodyFactoryIntegration, - get_create_entity_body, - get_create_entity_request_error_response, - get_create_entity_response, -) -from tests.conftest import get_expected_post_headers - -ENDPOINT_TEST_ARGUMENTS = { - "create_entity": { - "endpoint": "/provisioning/1/entities", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": "", - "expected_query_parameters": None, - "expected_json": GenerateCreateEntityBodyFactoryIntegration, - "request_parameters": get_create_entity_body(), - "method_name": "create_entity", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [201, get_create_entity_response], - [400, get_create_entity_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_create_entity_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/app_entities/integration/test_get_entities_query.py b/tests/app_entities/integration/test_get_entities_query.py deleted file mode 100644 index 35681bd..0000000 --- a/tests/app_entities/integration/test_get_entities_query.py +++ /dev/null @@ -1,79 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_platform.app_entities.api import ApplicationEntityManagement -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = ApplicationEntityManagement.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)(expected_query_parameters) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - response_dict = ApplicationEntityManagement.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None diff --git a/tests/app_entities/integration/test_get_entities_query_cases.py b/tests/app_entities/integration/test_get_entities_query_cases.py deleted file mode 100644 index 0966ac5..0000000 --- a/tests/app_entities/integration/test_get_entities_query_cases.py +++ /dev/null @@ -1,42 +0,0 @@ -from pytest_cases import parametrize - -from tests.app_entities.conftest import get_get_entities_response -from tests.conftest import get_expected_get_headers - -ENDPOINT_TEST_ARGUMENTS = { - "get_entities": { - "endpoint": "/provisioning/1/entities", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": None, - "expected_query_parameters": {"page": "0", "size": "10"}, - "expected_json": None, - "request_parameters": None, - "method_name": "get_entities", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=([200, get_get_entities_response],), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "get_entities" and responses[0] == 200: - response_content = get_get_entities_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/app_entities/integration/test_get_entity_path.py b/tests/app_entities/integration/test_get_entity_path.py deleted file mode 100644 index 56faf06..0000000 --- a/tests/app_entities/integration/test_get_entity_path.py +++ /dev/null @@ -1,125 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_platform.app_entities.api import ApplicationEntityManagement -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - ).respond_with_response(get_response_object(status_code, response_content)) - - app_entity_management = ApplicationEntityManagement.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(app_entity_management, method_name)( - expected_path_parameters["entityId"] - ) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__supported_status", -) -def test_entity_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - response_dict = ApplicationEntityManagement.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - - if type(response_content) is list: - response_content = {"list": response_content} - else: - response_content = response_content - - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__unsupported_status", -) -def test_entity_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/app_entities/integration/test_get_entity_path_cases.py b/tests/app_entities/integration/test_get_entity_path_cases.py deleted file mode 100644 index 50042bf..0000000 --- a/tests/app_entities/integration/test_get_entity_path_cases.py +++ /dev/null @@ -1,64 +0,0 @@ -from pytest_cases import parametrize - -from tests.app_entities.conftest import ( - get_get_entity_request_error_response, - get_get_entity_response, -) -from tests.conftest import get_expected_get_headers - -ENDPOINT_TEST_ARGUMENTS = { - "get_entity": { - "endpoint": "/provisioning/1/entities/some-entity-id", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": {"entityId": "some-entity-id"}, - "expected_query_parameters": None, - "expected_json": None, - "request_parameters": None, - "method_name": "get_entity", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_get_entity_response], - [404, get_get_entity_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "get_entity" and responses[0] == 200: - response_content = get_get_entity_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_get_entity_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/app_entities/integration/test_modify_entity_body_path.py b/tests/app_entities/integration/test_modify_entity_body_path.py deleted file mode 100644 index 5a796ef..0000000 --- a/tests/app_entities/integration/test_modify_entity_body_path.py +++ /dev/null @@ -1,110 +0,0 @@ -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_platform.app_entities.api import ApplicationEntityManagement -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - message_body_instance = request_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - app_entity_management = ApplicationEntityManagement.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(app_entity_management, method_name)( - expected_path_parameters["entityId"], - request_body, - ) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__supported_status", -) -def test_entity_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - assert response.status_code == status_code - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__unsupported_status", -) -def test_entity_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/app_entities/integration/test_modify_entity_body_path_cases.py b/tests/app_entities/integration/test_modify_entity_body_path_cases.py deleted file mode 100644 index 3b831cd..0000000 --- a/tests/app_entities/integration/test_modify_entity_body_path_cases.py +++ /dev/null @@ -1,47 +0,0 @@ -from pytest_cases import parametrize - -from tests.app_entities.conftest import ( - GenerateModifyEntityBodyFactoryIntegration, - get_modify_entity_body, - get_modify_entity_request_error_response, - get_modify_entity_response, -) -from tests.conftest import get_expected_post_headers - -ENDPOINT_TEST_ARGUMENTS = { - "modify_entity": { - "endpoint": "/provisioning/1/entities/some-entity-id", - "http_method": "PUT", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": {"entityId": "some-entity-id"}, - "expected_query_parameters": None, - "expected_json": GenerateModifyEntityBodyFactoryIntegration, - "request_parameters": get_modify_entity_body(), - "method_name": "modify_entity", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [204, get_modify_entity_response], - [400, get_modify_entity_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/app_entities/models/test_create_entity.py b/tests/app_entities/models/test_create_entity.py deleted file mode 100644 index 196bd6d..0000000 --- a/tests/app_entities/models/test_create_entity.py +++ /dev/null @@ -1,45 +0,0 @@ -import pytest -from pydantic import ValidationError - -from infobip_platform.app_entities.models.body.create_entity import CreateEntityBody - - -def test_when_name_is_long__validation_error_is_raised(): - with pytest.raises(ValidationError): - CreateEntityBody( - **{ - "entityName": "x" * 256, - "entityId": "some-entity", - } - ) - - -def test_when_id_is_long__validation_error_is_raised(): - with pytest.raises(ValidationError): - CreateEntityBody( - **{ - "entityId": "x" * 256, - } - ) - - -@pytest.mark.parametrize("entity_id", ["", {}]) -def test_when_id_is_empty__validation_error_is_raised(entity_id): - with pytest.raises(ValidationError): - CreateEntityBody( - **{ - "entityId": entity_id, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - CreateEntityBody( - **{ - "entityName": "Some entity", - "entityId": "some-entity", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/app_entities/models/test_get_entities.py b/tests/app_entities/models/test_get_entities.py deleted file mode 100644 index 0a7f316..0000000 --- a/tests/app_entities/models/test_get_entities.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytest -from pydantic import ValidationError - -from infobip_platform.app_entities.models.query_parameters.get_entities import ( - GetEntitiesQueryParameters, -) - - -def test_when_page_is_negative__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetEntitiesQueryParameters( - **{ - "page": -1, - } - ) - - -@pytest.mark.parametrize("size", [0, 101]) -def test_when_size_is_out_of_range__validation_error_is_raised(size): - with pytest.raises(ValidationError): - GetEntitiesQueryParameters( - **{ - "size": size, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetEntitiesQueryParameters( - **{ - "page": 1, - "size": 10, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/app_entities/models/test_modify_entity.py b/tests/app_entities/models/test_modify_entity.py deleted file mode 100644 index 8890e40..0000000 --- a/tests/app_entities/models/test_modify_entity.py +++ /dev/null @@ -1,24 +0,0 @@ -import pytest -from pydantic import ValidationError - -from infobip_platform.app_entities.models.body.modify_entity import ModifyEntityBody - - -def test_when_name_is_long__validation_error_is_raised(): - with pytest.raises(ValidationError): - ModifyEntityBody( - **{ - "entityName": "x" * 256, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - ModifyEntityBody( - **{ - "entityName": "Some Entity", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index 55161a9..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,102 +0,0 @@ -import json -import string -from io import IOBase -from random import choice -from string import ascii_letters -from typing import Optional - -import pytest -import requests -from werkzeug import Response - -from infobip_channels.core.models import CamelCaseModel, MultipartMixin - - -def get_random_string(length: int) -> str: - return "".join(choice(ascii_letters) for _ in range(length)) - - -def get_random_numbers(length: int) -> str: - return "".join(choice(string.digits) for _ in range(length)) - - -class HttpTestClient: - def __init__(self, url, headers): - self.url = url - self.headers = headers - - def post(self, endpoint, body, headers=None): - headers = headers or self.headers - return requests.post(url=f"{self.url}" + endpoint, json=body, headers=headers) - - def get(self, endpoint, headers=None): - headers = headers or self.headers - return requests.get(url=f"{self.url}" + endpoint, headers=headers) - - def delete(self, endpoint, headers=None): - headers = headers or self.headers - return requests.delete(url=f"{self.url}" + endpoint, headers=headers) - - -class Address(CamelCaseModel): - street: str - city: str - zip_code: int - - -class UserInfo(CamelCaseModel, MultipartMixin): - name: Optional[str] = None - last_name: str - address: Address - profile_image: IOBase - - class Config(CamelCaseModel.Config): - arbitrary_types_allowed = True - - -@pytest.fixture -def http_test_client(): - def _get_http_test_client(url, headers): - return HttpTestClient(url, headers) - - return _get_http_test_client - - -def get_response_object(status_code, content): - return Response(json.dumps(content), status_code) - - -def get_response_error_invalid_content(): - return { - "error": {"field_one": "error_one", "field_two": "error_two"}, - } - - -def get_expected_post_headers(content_type="application/json"): - return { - "Authorization": "App secret", - "Content-Type": content_type, - "Accept": "application/json", - } - - -def get_expected_put_headers(content_type="application/json"): - return { - "Authorization": "App secret", - "Content-Type": content_type, - "Accept": "application/json", - } - - -def get_expected_get_headers(): - return { - "Authorization": "App secret", - "Accept": "application/json", - } - - -def get_expected_delete_headers(): - return { - "Authorization": "App secret", - "Accept": "application/json", - } diff --git a/tests/email/conftest.py b/tests/email/conftest.py deleted file mode 100644 index 56cbde6..0000000 --- a/tests/email/conftest.py +++ /dev/null @@ -1,363 +0,0 @@ -import os - -from pydantic_factories import ModelFactory - -from infobip_channels.email.models.body.add_new_domain import AddNewDomainMessageBody -from infobip_channels.email.models.body.reschedule_messages import ( - RescheduleMessagesMessageBody, -) -from infobip_channels.email.models.body.update_scheduled_status import ( - UpdateScheduledStatusMessageBody, -) -from infobip_channels.email.models.body.update_tracking_events import ( - UpdateTrackingEventsMessageBody, -) -from infobip_channels.email.models.body.validate_email_addresses import ( - ValidateEmailAddressesMessageBody, -) - - -class GenerateRescheduleEmailMessagesFactory(ModelFactory): - __model__ = RescheduleMessagesMessageBody - - @classmethod - def build(cls, *args, **kwargs): - """ - Needed because we do not want to generate any random string. - We will add custom validation to this field when datetime format changes. - """ - return RescheduleMessagesMessageBody( - **{"sendAt": "2022-06-01T18:00:00.00+00:00"} - ) - - -class GenerateUpdateScheduledEmailMessagesStatusFactory(ModelFactory): - __model__ = UpdateScheduledStatusMessageBody - - -class GenerateValidateEmailAddressesFactory(ModelFactory): - __model__ = ValidateEmailAddressesMessageBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because we do not want to generate any random string.""" - return ValidateEmailAddressesMessageBody(**{"to": "test@test"}) - - -class GenerateAddNewDomainFactory(ModelFactory): - __model__ = AddNewDomainMessageBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because we do not want to generate any random string.""" - return AddNewDomainMessageBody(**{"domainName": "newDomain.com"}) - - -class GenerateUpdateTrackingEventsFactory(ModelFactory): - __model__ = UpdateTrackingEventsMessageBody - - -def get_email_body_request(): - with open("attachment", "wb") as f: - f.write(b"random bytes") - f.flush() - attachment = open(f.name, "rb") - os.remove("attachment") - - with open("in_line_image", "wb") as f: - f.write(b"image bytes") - f.flush() - in_line_image = open(f.name, "rb") - os.remove("in_line_image") - - return { - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "cc": "john.smith2@somedomain.com", - "bcc": "john.smith3@somedomain.com", - "subject": "Mail subject text", - "text": "Mail body text", - "bulkId": "BULK-ID-123-xyz", - "messageId": "MESSAGE-ID-123-xyz", - "templateid": 1, - "attachment": attachment, - "inlineImage": in_line_image, - "HTML": "

Mail HTML text

", - "replyto": "john.smith3@somedomain.com", - "defaultplaceholders": "placeholder", - "preserverecipients": True, - "trackingUrl": "https://someurl1.com", - "trackclicks": True, - "trackopens": True, - "track": True, - "callbackData": "https://someurl2.com", - "intermediateReport": True, - "notifyUrl": "https://someurl3.com", - "notifyContentType": "application/json", - "sendAt": "2022-06-01T18:00:00.00+00:00", - "landingPagePlaceholders": "Landing page placeholders", - "landingPageId": "LANDING-PAGE-ID-123-xyz", - } - - -def get_email_body_multipart(): - return ( - b"--mockBoundary\r\nContent-Disposition: form-data; " - b'name="from"\r\nContent-Type: ' - b"text/plain\r\n\r\njane.smith@somecompany.com\r\n--mockBoundary\r\nContent" - b'-Disposition: form-data; name="to"\r\nContent-Type: ' - b"text/plain\r\n\r\njohn.smith@somedomain.com\r\n--mockBoundary\r\nContent" - b'-Disposition: form-data; name="cc"\r\nContent-Type: ' - b"text/plain\r\n\r\njohn.smith2@somedomain.com\r\n--mockBoundary\r\nContent" - b'-Disposition: form-data; name="bcc"\r\nContent-Type: ' - b"text/plain\r\n\r\njohn.smith3@somedomain.com\r\n--mockBoundary\r\nContent" - b'-Disposition: form-data; name="subject"\r\nContent-Type: ' - b"text/plain\r\n\r\nMail subject " - b"text\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="text"\r\nContent-Type: text/plain\r\n\r\nMail body ' - b"text\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="bulkId"\r\nContent-Type: ' - b"text/plain\r\n\r\nBULK-ID-123-xyz\r\n--mockBoundary\r\nContent-Disposition: " - b'form-data; name="messageId"\r\nContent-Type: ' - b"text/plain\r\n\r\nMESSAGE-ID-123-xyz\r\n--mockBoundary\r\nContent" - b'-Disposition: form-data; name="templateid"\r\nContent-Type: ' - b"text/plain\r\n\r\n1\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="attachment"; filename="attachment"\r\nContent-Type: ' - b"application/octet-stream\r\n\r\nrandom " - b"bytes\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="inlineImage"; filename="in_line_image"\r\nContent-Type: ' - b"application/octet-stream\r\n\r\nimage " - b"bytes\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="HTML"\r\nContent-Type: text/plain\r\n\r\n

Mail HTML ' - b"text

\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="replyto"\r\nContent-Type: ' - b"text/plain\r\n\r\njohn.smith3@somedomain.com\r\n--mockBoundary\r\nContent" - b'-Disposition: form-data; name="defaultplaceholders"\r\nContent-Type: ' - b"text/plain\r\n\r\nplaceholder\r\n--mockBoundary\r\nContent-Disposition: " - b'form-data; name="preserverecipients"\r\nContent-Type: ' - b"text/plain\r\n\r\nTrue\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="trackingUrl"\r\nContent-Type: ' - b"text/plain\r\n\r\nhttps://someurl1.com\r\n--mockBoundary\r\nContent" - b'-Disposition: form-data; name="trackclicks"\r\nContent-Type: ' - b"text/plain\r\n\r\nTrue\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="trackopens"\r\nContent-Type: ' - b"text/plain\r\n\r\nTrue\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="track"\r\nContent-Type: ' - b"text/plain\r\n\r\nTrue\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="callbackData"\r\nContent-Type: ' - b"text/plain\r\n\r\nhttps://someurl2.com\r\n--mockBoundary\r\nContent" - b'-Disposition: form-data; name="intermediatereport"\r\nContent-Type: ' - b"text/plain\r\n\r\nTrue\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="notifyUrl"\r\nContent-Type: ' - b"text/plain\r\n\r\nhttps://someurl3.com\r\n--mockBoundary\r\nContent" - b'-Disposition: form-data; name="notifyContentType"\r\nContent-Type: ' - b"text/plain\r\n\r\napplication/json\r\n--mockBoundary\r\nContent-Disposition" - b': form-data; name="sendAt"\r\nContent-Type: ' - b"text/plain\r\n\r\n2022-06-01T18:00:00.000000Z\r\n--mockBoundary\r\nContent" - b'-Disposition: form-data; name="landingPagePlaceholders"\r\nContent-Type: ' - b"text/plain\r\n\r\nLanding page " - b"placeholders\r\n--mockBoundary\r\nContent-Disposition: form-data; " - b'name="landingPageId"\r\nContent-Type: ' - b"text/plain\r\n\r\nLANDING-PAGE-ID-123-xyz\r\n--mockBoundary--\r\n" - ) - - -def get_empty_response(): - return "" - - -def get_sent_email_response(): - return { - "messages": [ - { - "to": "john.smith@somedomain.com", - "messageCount": 1, - "messageId": "somexternalMessageId", - "status": { - "groupId": 1, - "groupName": "PENDING", - "id": 7, - "name": "PENDING_ENROUTE", - "description": "Message sent to next instance", - }, - } - ] - } - - -def get_validate_email_addresses_response(): - return { - "to": "abc@zxc.com", - "validMailbox": "unknown", - "validSyntax": True, - "catchAll": False, - "disposable": False, - "roleBased": False, - "reason": "INBOX_FULL", - } - - -def get_add_new_domain_response(): - return { - "domainId": 1, - "domainName": "newDomain.com", - "active": False, - "tracking": {"clicks": False, "opens": True, "unsubscribe": True}, - "dnsRecords": [ - { - "recordType": "string", - "name": "string", - "expectedValue": "string", - "verified": True, - } - ], - "blocked": False, - "createdAt": "2022-06-01T18:00:00.00+00:00", - } - - -def get_reschedule_email_messages_response(): - return {"bulkId": "xyz-123-444", "sendAt": "2022-06-01T18:00:00.00+00:00"} - - -def get_email_delivery_reports_response(): - return { - "results": [ - { - "bulkId": "bulk-123", - "messageId": "abc-123", - "to": "some@some.com", - "sentAt": "2022-06-01T18:00:00.00+00:00", - "doneAt": "2022-06-01T19:00:00.00+00:00", - "messageCount": 0, - "price": {"pricePerMessage": 0, "currency": "string"}, - "status": { - "groupId": 0, - "groupName": "string", - "id": 0, - "name": "string", - "description": "string", - "action": "string", - }, - "error": { - "groupId": 0, - "groupName": "string", - "id": 0, - "name": "string", - "description": "string", - "permanent": True, - }, - "channel": "EMAIL", - } - ] - } - - -def get_email_logs_response(): - return { - "results": [ - { - "bulkId": "bulk-123", - "messageId": "abc-123", - "to": "string", - "from": "string", - "text": "string", - "sentAt": "2022-06-01T18:00:00.00+00:00", - "doneAt": "2022-06-01T19:00:00.00+00:00", - "messageCount": 0, - "price": {"pricePerMessage": 0, "currency": "string"}, - "status": { - "groupId": 0, - "groupName": "string", - "id": 0, - "name": "string", - "description": "string", - "action": "string", - }, - } - ] - } - - -def get_sent_email_bulks_response(): - return { - "externalBulkId": "string", - "bulks": [{"bulkId": "xyz-123-444", "sendAt": "2022-06-06T17:00:00.00+00:00"}], - } - - -def get_all_domains_for_account_response(): - return { - "paging": {"page": 20, "size": 0, "totalPages": 0, "totalResults": 0}, - "results": [ - { - "domainId": 1, - "domainName": "newDomain.com", - "active": False, - "tracking": {"clicks": True, "opens": True, "unsubscribe": True}, - "dnsRecords": [ - { - "recordType": "string", - "name": "string", - "expectedValue": "string", - "verified": True, - } - ], - "blocked": True, - "createdAt": "2022-06-01T18:00:00.00+00:00", - } - ], - } - - -def get_domain_response(): - return { - "domainId": 1, - "domainName": "newDomain.com", - "active": False, - "tracking": {"clicks": True, "opens": True, "unsubscribe": True}, - "dnsRecords": [ - { - "recordType": "string", - "name": "string", - "expectedValue": "string", - "verified": True, - } - ], - "blocked": False, - "createdAt": "2022-06-01T18:00:00.00+00:00", - } - - -def get_update_scheduled_email_messages_status_response(): - return {"bulkId": "xyz-123-444", "status": "PENDING"} - - -def get_email_delivery_reports_query_parameters(): - return {"messageId": "abc-123", "limit": 1} - - -def get_email_request_error_response(): - return { - "requestError": {"serviceException": {"messageId": "error", "text": "error"}} - } - - -def get_email_logs_query_parameters(): - return {"messageId": "abc-123", "limit": 1} - - -def get_sent_email_bulk_id_query_parameter(): - return {"bulkId": "xyz-123-444"} - - -def get_validate_email_addresses(): - return {"to": "test@test.com"} - - -def get_all_domains_for_account(): - return {"size": "20", "page": "0"} - - -def get_domain(): - return {"domainName": "newDomain.com"} diff --git a/tests/email/integration/test_email_endpoints_integration.py b/tests/email/integration/test_email_endpoints_integration.py deleted file mode 100644 index 0f97c8b..0000000 --- a/tests/email/integration/test_email_endpoints_integration.py +++ /dev/null @@ -1,119 +0,0 @@ -from http import HTTPStatus -from unittest.mock import patch - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.email.channel import EmailChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_data, - request_data, - method_name, -): - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - data=expected_data, - ).respond_with_response(get_response_object(status_code, response_content)) - - email_channel = EmailChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(email_channel, method_name)(request_data) - - -@patch("urllib3.filepost.choose_boundary", return_value="mockBoundary") -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_query_parameters, expected_data, request_data, method_name", - prefix="case__supported_status", -) -def test_email_endpoints__supported_status( - mock_boundary, - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_data, - request_data, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_data, - request_data, - method_name, - ) - if method_name == "delete_existing_domain" or method_name == "verify_domain": - assert response.status_code == status_code - else: - response_dict = EmailChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@patch("urllib3.filepost.choose_boundary", return_value="mockBoundary") -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_query_parameters, expected_data, request_data, method_name", - prefix="case__unsupported_status", -) -def test_email_endpoints__unsupported_status( - mock_boundary, - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_data, - request_data, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_data, - request_data, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/email/integration/test_email_endpoints_integration_cases.py b/tests/email/integration/test_email_endpoints_integration_cases.py deleted file mode 100644 index 3c84479..0000000 --- a/tests/email/integration/test_email_endpoints_integration_cases.py +++ /dev/null @@ -1,167 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import ( - get_expected_delete_headers, - get_expected_get_headers, - get_expected_post_headers, -) -from tests.email.conftest import ( - get_all_domains_for_account, - get_all_domains_for_account_response, - get_domain, - get_domain_response, - get_email_body_multipart, - get_email_body_request, - get_email_delivery_reports_query_parameters, - get_email_delivery_reports_response, - get_email_logs_query_parameters, - get_email_logs_response, - get_email_request_error_response, - get_empty_response, - get_sent_email_bulk_id_query_parameter, - get_sent_email_bulks_response, - get_sent_email_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "send_email_message": { - "response_content": get_sent_email_response(), - "endpoint": "/email/3/send", - "http_method": "POST", - "expected_headers": get_expected_post_headers( - "multipart/form-data; boundary=mockBoundary" - ), - "expected_query_parameters": None, - "expected_data": get_email_body_multipart(), - "request_data": get_email_body_request(), - "method_name": "send_email_message", - }, - "email_delivery_reports": { - "response_content": get_email_delivery_reports_response(), - "endpoint": "/email/1/reports", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_query_parameters": "messageId=abc-123&limit=1", - "expected_data": None, - "request_data": get_email_delivery_reports_query_parameters(), - "method_name": "email_delivery_reports", - }, - "get_email_logs": { - "response_content": get_email_logs_response(), - "endpoint": "/email/1/logs", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_query_parameters": "messageId=abc-123&limit=1", - "expected_data": None, - "request_data": get_email_logs_query_parameters(), - "method_name": "get_email_logs", - }, - "get_sent_email_bulks": { - "response_content": get_sent_email_bulks_response(), - "endpoint": "/email/1/bulks", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_query_parameters": "bulkId=xyz-123-444", - "expected_data": None, - "request_data": get_sent_email_bulk_id_query_parameter(), - "method_name": "get_sent_email_bulks", - }, - "get_all_domains_for_account": { - "response_content": get_all_domains_for_account_response(), - "endpoint": "/email/1/domains", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_query_parameters": "size=20&page=0", - "expected_data": None, - "request_data": get_all_domains_for_account(), - "method_name": "get_all_domains_for_account", - }, - "get_domain_details": { - "response_content": get_domain_response(), - "endpoint": "/email/1/domains/newDomain.com", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_query_parameters": None, - "expected_data": None, - "request_data": get_domain(), - "method_name": "get_domain_details", - }, - "delete_existing_domain": { - "response_content": None, - "endpoint": "/email/1/domains/newDomain.com", - "http_method": "DELETE", - "expected_headers": get_expected_delete_headers(), - "expected_query_parameters": None, - "expected_data": None, - "request_data": get_domain(), - "method_name": "delete_existing_domain", - }, - "verify_domain": { - "response_content": None, - "endpoint": "/email/1/domains/newDomain.com/verify", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_query_parameters": None, - "expected_data": None, - "request_data": get_domain(), - "method_name": "verify_domain", - }, -} - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), status_code=(200, 400, 500)) -def case__supported_status(endpoint_type, status_code): - if endpoint_type == "send_email_message": - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_data"]["attachment"].seek(0) - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_data"]["inlineImage"].seek(0) - - response_content = get_sent_email_response - if endpoint_type == "email_delivery_reports": - response_content = get_email_delivery_reports_response - if endpoint_type == "get_email_logs": - response_content = get_email_logs_response - if endpoint_type == "get_sent_email_bulks": - response_content = get_sent_email_bulks_response - if endpoint_type == "get_all_domains_for_account": - response_content = get_all_domains_for_account_response - if endpoint_type == "get_domain_details": - response_content = get_domain_response - if endpoint_type == "delete_existing_domain" and status_code == 200: - response_content = get_empty_response - status_code = 204 - if endpoint_type == "verify_domain" and status_code == 200: - response_content = get_empty_response - status_code = 202 - if status_code == 400 or status_code == 500: - response_content = get_email_request_error_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_data"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_data"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - if endpoint_type == "send_email_message": - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_data"]["attachment"].seek(0) - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_data"]["inlineImage"].seek(0) - - return ( - 201, - get_email_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_data"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_data"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/email/integration/test_email_with_body_integration.py b/tests/email/integration/test_email_with_body_integration.py deleted file mode 100644 index 52ad112..0000000 --- a/tests/email/integration/test_email_with_body_integration.py +++ /dev/null @@ -1,127 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.email.channel import EmailChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_json, - request_query_parameters, - request_path_parameters, - method_name, -): - message_body_instance = message_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - email_channel = EmailChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - if request_query_parameters is None and request_path_parameters is None: - return getattr(email_channel, method_name)(message_body) - if request_query_parameters is None and request_path_parameters is not None: - return getattr(email_channel, method_name)( - request_path_parameters, message_body - ) - else: - return getattr(email_channel, method_name)( - request_query_parameters, message_body - ) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_query_parameters, expected_json, " - "request_query_parameters, request_path_parameters, method_name", - prefix="case__supported_status", -) -def test_email_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_json, - request_query_parameters, - request_path_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_json, - request_query_parameters, - request_path_parameters, - method_name, - ) - response_dict = EmailChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_query_parameters, expected_json, " - "request_query_parameters, request_path_parameters, method_name", - prefix="case__unsupported_status", -) -def test_email_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_json, - request_query_parameters, - request_path_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_json, - request_query_parameters, - request_path_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/email/integration/test_email_with_body_integration_cases.py b/tests/email/integration/test_email_with_body_integration_cases.py deleted file mode 100644 index 916828d..0000000 --- a/tests/email/integration/test_email_with_body_integration_cases.py +++ /dev/null @@ -1,120 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_post_headers, get_expected_put_headers -from tests.email.conftest import ( - GenerateAddNewDomainFactory, - GenerateRescheduleEmailMessagesFactory, - GenerateUpdateScheduledEmailMessagesStatusFactory, - GenerateUpdateTrackingEventsFactory, - GenerateValidateEmailAddressesFactory, - get_add_new_domain_response, - get_domain, - get_domain_response, - get_email_request_error_response, - get_reschedule_email_messages_response, - get_sent_email_bulk_id_query_parameter, - get_update_scheduled_email_messages_status_response, - get_validate_email_addresses_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "reschedule_email_messages": { - "response_content": get_reschedule_email_messages_response(), - "endpoint": "/email/1/bulks", - "http_method": "PUT", - "expected_headers": get_expected_put_headers(), - "expected_query_parameters": "bulkId=xyz-123-444", - "expected_json": GenerateRescheduleEmailMessagesFactory, - "request_query_parameters": get_sent_email_bulk_id_query_parameter(), - "request_path_parameters": None, - "method_name": "reschedule_email_messages", - }, - "update_scheduled_email_messages": { - "response_content": get_update_scheduled_email_messages_status_response(), - "endpoint": "/email/1/bulks/status", - "http_method": "PUT", - "expected_headers": get_expected_put_headers(), - "expected_query_parameters": "bulkId=xyz-123-444", - "expected_json": GenerateUpdateScheduledEmailMessagesStatusFactory, - "request_query_parameters": get_sent_email_bulk_id_query_parameter(), - "request_path_parameters": None, - "method_name": "update_scheduled_email_messages", - }, - "validate_email_addresses": { - "response_content": get_validate_email_addresses_response(), - "endpoint": "/email/2/validation", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_query_parameters": None, - "expected_json": GenerateValidateEmailAddressesFactory, - "request_query_parameters": None, - "request_path_parameters": None, - "method_name": "validate_email_addresses", - }, - "add_new_domain": { - "response_content": get_add_new_domain_response(), - "endpoint": "/email/1/domains", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_query_parameters": None, - "expected_json": GenerateAddNewDomainFactory, - "request_query_parameters": None, - "request_path_parameters": None, - "method_name": "add_new_domain", - }, - "update_tracking_events": { - "response_content": get_domain_response(), - "endpoint": "/email/1/domains/newDomain.com/tracking", - "http_method": "PUT", - "expected_headers": get_expected_put_headers(), - "expected_query_parameters": None, - "expected_json": GenerateUpdateTrackingEventsFactory, - "request_query_parameters": None, - "request_path_parameters": get_domain(), - "method_name": "update_tracking_events", - }, -} - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), status_code=(200, 400, 500)) -def case__supported_status(endpoint_type, status_code): - response_content = get_reschedule_email_messages_response - if endpoint_type == "update_scheduled_email_messages": - response_content = get_update_scheduled_email_messages_status_response - if endpoint_type == "validate_email_addresses": - response_content = get_validate_email_addresses_response - if endpoint_type == "add_new_domain": - response_content = get_add_new_domain_response - if endpoint_type == "update_tracking_events": - response_content = get_domain_response - if status_code == 400 or status_code == 500: - response_content = get_email_request_error_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_email_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/email/models/test_add_new_domain.py b/tests/email/models/test_add_new_domain.py deleted file mode 100644 index b7e3704..0000000 --- a/tests/email/models/test_add_new_domain.py +++ /dev/null @@ -1,24 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.body.add_new_domain import AddNewDomainMessageBody - - -def test_when_domain_name_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - AddNewDomainMessageBody( - **{ - "domainName": {}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - AddNewDomainMessageBody( - **{ - "domainName": "newDomain.com", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_delete_existing_domain.py b/tests/email/models/test_delete_existing_domain.py deleted file mode 100644 index 036986a..0000000 --- a/tests/email/models/test_delete_existing_domain.py +++ /dev/null @@ -1,26 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.path_parameters.delete_existing_domain import ( - DeleteExistingDomainPathParameter, -) - - -def test_when_bulk_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - DeleteExistingDomainPathParameter( - **{ - "domainName": {}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - DeleteExistingDomainPathParameter( - **{ - "domainName": "newDomain.com", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_delivery_reports.py b/tests/email/models/test_delivery_reports.py deleted file mode 100644 index 541ec1f..0000000 --- a/tests/email/models/test_delivery_reports.py +++ /dev/null @@ -1,46 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.query_parameters.delivery_reports import ( - DeliveryReportsQueryParameters, -) - - -def test_when_bulk_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - DeliveryReportsQueryParameters( - **{ - "bulkId": {}, - } - ) - - -def test_when_message_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - DeliveryReportsQueryParameters( - **{ - "messageId": {}, - } - ) - - -def test_when_limit_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - DeliveryReportsQueryParameters( - **{ - "limit": {}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - DeliveryReportsQueryParameters( - **{ - "bulkId": "BULK-ID-123-xyz", - "messageId": "MESSAGE-ID-123-xyz", - "limit": 2, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_get_all_domains.py b/tests/email/models/test_get_all_domains.py deleted file mode 100644 index d0e8a75..0000000 --- a/tests/email/models/test_get_all_domains.py +++ /dev/null @@ -1,38 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.query_parameters.get_all_domains import ( - GetAllDomainsForAccountQueryParameters, -) - - -@pytest.mark.parametrize("size", ["", {}, 21, 0]) -def test_when_size_is_invalid__validation_error_is_raised(size): - with pytest.raises(ValidationError): - GetAllDomainsForAccountQueryParameters( - **{ - "size": size, - } - ) - - -@pytest.mark.parametrize("page", ["", {}, -1]) -def test_when_page_is_invalid__validation_error_is_raised(page): - with pytest.raises(ValidationError): - GetAllDomainsForAccountQueryParameters( - **{ - "page": page, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetAllDomainsForAccountQueryParameters( - **{ - "size": "20", - "page": "1", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_get_domain_details.py b/tests/email/models/test_get_domain_details.py deleted file mode 100644 index e60de47..0000000 --- a/tests/email/models/test_get_domain_details.py +++ /dev/null @@ -1,26 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.path_parameters.get_domain_details import ( - GetDomainDetailsPathParameter, -) - - -def test_when_domain_name_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetDomainDetailsPathParameter( - **{ - "domainName": {}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetDomainDetailsPathParameter( - **{ - "domainName": "newDomain.com", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_get_logs.py b/tests/email/models/test_get_logs.py deleted file mode 100644 index c71a8ac..0000000 --- a/tests/email/models/test_get_logs.py +++ /dev/null @@ -1,99 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.query_parameters.get_logs import ( - GetLogsQueryParameters, -) - - -def test_when_message_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetLogsQueryParameters( - **{ - "messageId": {}, - } - ) - - -def test_when_from_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetLogsQueryParameters( - **{ - "from": {}, - } - ) - - -def test_when_to_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetLogsQueryParameters( - **{ - "to": {}, - } - ) - - -def test_when_bulk_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetLogsQueryParameters( - **{ - "bulkId": {}, - } - ) - - -@pytest.mark.parametrize("general_status", [{}, "TEST"]) -def test_when_general_status_is_invalid__validation_error_is_raised(general_status): - with pytest.raises(ValidationError): - GetLogsQueryParameters( - **{ - "generalStatus": general_status, - } - ) - - -# @pytest.mark.parametrize("sent_since", [{}, "22-03-2022", date.today()]) -# def test_when_sent_since_is_invalid__validation_error_is_raised(sent_since): -# with pytest.raises(ValidationError): -# GetLogsQueryParameters( -# **{ -# "sentSince": sent_since, -# } -# ) -# -# -# @pytest.mark.parametrize("sent_until", [{}, "22-03-2022", date.today()]) -# def test_when_sent_until_is_invalid__validation_error_is_raised(sent_until): -# with pytest.raises(ValidationError): -# GetLogsQueryParameters( -# **{ -# "sentUntil": sent_until, -# } -# ) - - -def test_when_limit_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetLogsQueryParameters( - **{ - "limit": {}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetLogsQueryParameters( - **{ - "messageId": "MESSAGE-ID-123-xyz", - "from": "from@some.com", - "to": "to@some.com", - "bulkId": "BULK-ID-123-xyz", - "generalStatus": "PENDING", - "sentSince": "2022-03-22", - "sentUntil": "2022-03-26", - "limit": 2, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_get_sent_bulk_status.py b/tests/email/models/test_get_sent_bulk_status.py deleted file mode 100644 index 11d0261..0000000 --- a/tests/email/models/test_get_sent_bulk_status.py +++ /dev/null @@ -1,26 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.query_parameters.get_sent_bulks import ( - GetSentBulksQueryParameters, -) - - -def test_when_bulk_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetSentBulksQueryParameters( - **{ - "bulkId": {}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetSentBulksQueryParameters( - **{ - "bulkId": "BULK-ID-123-xyz", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_get_sent_bulks.py b/tests/email/models/test_get_sent_bulks.py deleted file mode 100644 index 05cd852..0000000 --- a/tests/email/models/test_get_sent_bulks.py +++ /dev/null @@ -1,26 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.query_parameters.get_sent_bulks_status import ( - GetSentBulksStatusQueryParameters, -) - - -def test_when_bulk_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetSentBulksStatusQueryParameters( - **{ - "bulkId": {}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetSentBulksStatusQueryParameters( - **{ - "bulkId": "BULK-ID-123-xyz", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_reschedule_messages.py b/tests/email/models/test_reschedule_messages.py deleted file mode 100644 index 9e3e691..0000000 --- a/tests/email/models/test_reschedule_messages.py +++ /dev/null @@ -1,57 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.body.reschedule_messages import ( - RescheduleMessagesMessageBody, -) -from infobip_channels.email.models.query_parameters.reschedule_messages import ( - RescheduleMessagesQueryParameters, -) - - -def test_when_bulk_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - RescheduleMessagesQueryParameters( - **{ - "bulkId": {}, - } - ) - - -def test_when_input_data_query_is_valid__validation_error_is_not_raised(): - try: - RescheduleMessagesQueryParameters( - **{ - "bulkId": "BULK-ID-123-xyz", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") - - -@pytest.mark.parametrize( - "send_at", - [ - {}, - "Test", - "22-03-2022", - ], -) -def test_when_send_at_is_invalid__validation_error_is_raised(send_at): - with pytest.raises(ValidationError): - RescheduleMessagesMessageBody( - **{ - "sendAt": send_at, - } - ) - - -def test_when_input_data_body_is_valid__validation_error_is_not_raised(): - try: - RescheduleMessagesMessageBody( - **{ - "sendAt": "2022-06-01T18:00:00.00+00:00", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_send_email.py b/tests/email/models/test_send_email.py deleted file mode 100644 index 79b5612..0000000 --- a/tests/email/models/test_send_email.py +++ /dev/null @@ -1,370 +0,0 @@ -from io import open -from tempfile import NamedTemporaryFile - -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.body.send_email import EmailMessageBody -from tests.conftest import get_random_string - - -@pytest.mark.parametrize("from_email", [None, {}]) -def test_when_from_email_is_invalid__validation_error_is_raised(from_email): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": from_email, - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - } - ) - - -@pytest.mark.parametrize("to", [None, {}]) -def test_when_to_is_invalid__validation_error_is_raised(to): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": to, - "subject": "Mail subject text", - } - ) - - -def test_when_cc_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "cc": {}, - } - ) - - -def test_when_bcc_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "bcc": {}, - } - ) - - -def test_when_subject_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": {}, - } - ) - - -def test_when_text_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "text": {}, - } - ) - - -def test_when_bulk_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "bulkId": {}, - } - ) - - -def test_when_message_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "messageId": {}, - } - ) - - -def test_when_templateid_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "templateid": {}, - } - ) - - -@pytest.mark.parametrize("attachment", [[], {}, get_random_string(3)]) -def test_when_attachment_is_invalid__validation_error_is_raised(attachment): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "attachment": attachment, - } - ) - - -@pytest.mark.parametrize("inline_image", [[], {}, get_random_string(3)]) -def test_when_inline_image_is_invalid__validation_error_is_raised(inline_image): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "inlineImage": inline_image, - } - ) - - -def test_when_html_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "HTML": {}, - } - ) - - -def test_when_replyto_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "replyto": {}, - } - ) - - -def test_when_defaultplaceholders_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "defaultplaceholders": {}, - } - ) - - -def test_when_preserverecipients_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "preserverecipients": {}, - } - ) - - -def test_when_tracking_url_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "trackingUrl": {}, - } - ) - - -def test_when_trackclicks_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "trackclicks": {}, - } - ) - - -def test_when_trackopens_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "trackopens": {}, - } - ) - - -def test_when_track_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "track": {}, - } - ) - - -@pytest.mark.parametrize("callback_data", [{}, get_random_string(4001)]) -def test_when_callback_data_is_invalid__validation_error_is_raised(callback_data): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "callbackData": callback_data, - } - ) - - -def test_when_intermediate_report_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "intermediateReport": {}, - } - ) - - -@pytest.mark.parametrize("notify_url", [{}, "string", "ftp://url.com"]) -def test_when_notify_url_is_invalid__validation_error_is_raised(notify_url): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "notifyUrl": notify_url, - } - ) - - -@pytest.mark.parametrize("notify_content_type", [{}, "string"]) -def test_when_notify_content_type_is_invalid__validation_error_is_raised( - notify_content_type, -): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "notifyContentType": notify_content_type, - } - ) - - -@pytest.mark.parametrize("send_at", [{}, "Test", "22-03-2022"]) -def test_when_send_at_is_invalid__validation_error_is_raised(send_at): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "sendAt": send_at, - } - ) - - -def test_when_landing_page_placeholders_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "landingPagePlaceholders": {}, - } - ) - - -def test_when_landing_page_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "subject": "Mail subject text", - "landingPageId": {}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - f = NamedTemporaryFile("wb") - f.write(b"random bytes") - f.flush() - attachment = open(f.name, "rb") - in_line_image = open(f.name, "rb") - - try: - EmailMessageBody( - **{ - "from": "jane.smith@somecompany.com", - "to": "john.smith@somedomain.com", - "cc": "john.smith2@somedomain.com", - "bcc": "john.smith3@somedomain.com", - "subject": "Mail subject text", - "text": "Mail body text", - "bulkId": "BULK-ID-123-xyz", - "messageId": "MESSAGE-ID-123-xyz", - "templateid": 1, - "attachment": attachment, - "inlineImage": in_line_image, - "HTML": "

Mail HTML text

", - "replyto": "john.smith3@somedomain.com", - "defaultplaceholders": "placeholder", - "preserverecipients": True, - "trackingUrl": "https://someurl.com", - "trackclicks": True, - "trackopens": True, - "track": True, - "callbackData": "https://someurl.com", - "intermediateReport": True, - "notifyUrl": "https://someurl.com", - "notifyContentType": "application/json", - "sendAt": "2022-05-06T22:29:17.437992", - "landingPagePlaceholders": "Landing page placeholders", - "landingPageId": "LANDING-PAGE-ID-123-xyz", - } - ) - f.close() - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_update_scheduled_status.py b/tests/email/models/test_update_scheduled_status.py deleted file mode 100644 index 4876d72..0000000 --- a/tests/email/models/test_update_scheduled_status.py +++ /dev/null @@ -1,49 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.body.update_scheduled_status import ( - UpdateScheduledStatusMessageBody, -) -from infobip_channels.email.models.query_parameters.update_scheduled_status import ( - UpdateScheduledStatusQueryParameters, -) - - -def test_when_bulk_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - UpdateScheduledStatusQueryParameters( - **{ - "bulkId": {}, - } - ) - - -def test_when_input_data_query_is_valid__validation_error_is_not_raised(): - try: - UpdateScheduledStatusQueryParameters( - **{ - "bulkId": "BULK-ID-123-xyz", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") - - -def test_when_status_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - UpdateScheduledStatusMessageBody( - **{ - "status": {}, - } - ) - - -def test_when_input_data_body_is_valid__validation_error_is_not_raised(): - try: - UpdateScheduledStatusMessageBody( - **{ - "status": "PAUSED", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_update_tracking_events.py b/tests/email/models/test_update_tracking_events.py deleted file mode 100644 index 6fd2824..0000000 --- a/tests/email/models/test_update_tracking_events.py +++ /dev/null @@ -1,72 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.body.update_tracking_events import ( - UpdateTrackingEventsMessageBody, -) -from infobip_channels.email.models.path_parameters.update_tracking_events import ( - UpdateTrackingEventsPathParameter, -) - - -def test_when_domain_name_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - UpdateTrackingEventsPathParameter( - **{ - "domainName": {}, - } - ) - - -def test_when_input_data_path_is_valid__validation_error_is_not_raised(): - try: - UpdateTrackingEventsPathParameter( - **{ - "domainName": "newDomain.com", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") - - -@pytest.mark.parametrize("open_test", ["", {}, "true", 1]) -def test_when_open_is_invalid__validation_error_is_raised(open_test): - with pytest.raises(ValidationError): - UpdateTrackingEventsMessageBody( - **{ - "open": open_test, - } - ) - - -@pytest.mark.parametrize("clicks", ["", {}, "true", 1]) -def test_when_clicks_is_invalid__validation_error_is_raised(clicks): - with pytest.raises(ValidationError): - UpdateTrackingEventsMessageBody( - **{ - "clicks": clicks, - } - ) - - -@pytest.mark.parametrize("unsubscribe", ["", {}, "true", 1]) -def test_when_unsubscribe_is_invalid__validation_error_is_raised(unsubscribe): - with pytest.raises(ValidationError): - UpdateTrackingEventsMessageBody( - **{ - "unsubscribe": unsubscribe, - } - ) - - -def test_when_input_data_body_is_valid__validation_error_is_not_raised(): - try: - UpdateTrackingEventsMessageBody( - **{ - "open": True, - "clicks": True, - "unsubscribe": True, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/email/models/test_validate_email_adresses.py b/tests/email/models/test_validate_email_adresses.py deleted file mode 100644 index 0ee1c9d..0000000 --- a/tests/email/models/test_validate_email_adresses.py +++ /dev/null @@ -1,26 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.email.models.body.validate_email_addresses import ( - ValidateEmailAddressesMessageBody, -) - - -def test_when_to_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - ValidateEmailAddressesMessageBody( - **{ - "to": {}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - ValidateEmailAddressesMessageBody( - **{ - "to": "test@test.com", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/mms/conftest.py b/tests/mms/conftest.py deleted file mode 100644 index 57732af..0000000 --- a/tests/mms/conftest.py +++ /dev/null @@ -1,126 +0,0 @@ -import os - - -def get_mms_body_request(): - with open("media_file", "wb") as f: - f.write(b"random bytes") - f.flush() - media_file = open(f.name, "rb") - os.remove("media_file") - - return { - "head": { - "from": "38598743321", - "to": "38599876543", - }, - "text": "some text", - "media": media_file, - "externallyHostedMedia": [ - { - "contentType": "application/pdf", - "contentId": "331", - "contentUrl": "https://a.com", - } - ], - "smil": "John", - } - - -def get_mms_body_multipart(): - return ( - b'--mockBoundary\r\nContent-Disposition: form-data; name="head"\r\n' - b"Content-Type: application/json\r\n\r\n" - b'{"from": "38598743321", "to": "38599876543", "id": null, "subject": null, ' - b'"validityPeriodMinutes": null, "callbackData": null, "notifyUrl": null, ' - b'"sendAt": null, "intermediateReport": false, "deliveryTimeWindow": null}\r\n' - b'--mockBoundary\r\nContent-Disposition: form-data; name="text"\r\n' - b"Content-Type: text/plain\r\n\r\nsome text\r\n--mockBoundary\r\n" - b'Content-Disposition: form-data; name="media"; filename="media_file"\r\n' - b"Content-Type: application/octet-stream\r\n\r\nrandom bytes\r\n" - b"--mockBoundary\r\n" - b'Content-Disposition: form-data; name="externallyHostedMedia"\r\n' - b"Content-Type: application/json\r\n\r\n" - b'[{"contentType": "application/pdf", "contentId": "331", ' - b'"contentUrl": "https://a.com"}]\r\n--mockBoundary\r\n' - b'Content-Disposition: form-data; name="smil"\r\n' - b"Content-Type: application/xml\r\n\r\n" - b"John\r\n--mockBoundary--\r\n" - ) - - -def get_send_mms_response(): - return { - "bulkId": "1", - "messages": [ - { - "to": "38599876543", - "status": { - "groupId": 1, - "groupName": "PENDING", - "id": 26, - "name": "PENDING_ACCEPTED", - "description": "Message accepted, pending for delivery.", - }, - "messageId": "2250be2d4219-3af1-78856-aabe-1362af1edfd2", - } - ], - "errorMessage": "string", - } - - -def get_mms_delivery_reports_query_parameters(): - return {"bulk_id": None, "message_id": "abc-123", "limit": 1} - - -def get_mms_delivery_reports_response(): - return { - "results": [ - { - "bulkId": None, - "messageId": "abc-123", - "to": "38598331223", - "from": "38599873331", - "sentAt": "2022-04-02T15:44:12.351Z", - "doneAt": "2022-04-02T15:46:32.931Z", - "mmsCount": 1, - "mccMnc": "28988", - "callbackData": "", - "price": {"pricePerMessage": 4, "currency": "HRK"}, - "status": { - "groupId": 1, - "groupName": "PENDING", - "id": 26, - "name": "PENDING_ACCEPTED", - "description": "Message accepted, pending for delivery.", - }, - "error": { - "groupId": 1, - "groupName": "Group 1", - "id": 1, - "name": "The Name", - "description": "Some error", - }, - } - ] - } - - -def get_inbound_mms_messages_query_parameters(): - return {"limit": 1} - - -def get_inbound_mms_messages_response(): - return { - "results": [ - { - "messageId": "uyx-333", - "to": "38598331223", - "from": "38599873331", - "message": "Hi from MMS!", - "receivedAt": "2022-04-01T16:44:12.351Z", - "mmsCount": 1, - "callbackData": "", - "price": {"pricePerMessage": 4, "currency": "HRK"}, - } - ] - } diff --git a/tests/mms/integration/test_endpoints_integration.py b/tests/mms/integration/test_endpoints_integration.py deleted file mode 100644 index 9d6bbb2..0000000 --- a/tests/mms/integration/test_endpoints_integration.py +++ /dev/null @@ -1,116 +0,0 @@ -from http import HTTPStatus -from unittest.mock import patch - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.mms.channel import MMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_data, - request_data, - method_name, -): - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - data=expected_data, - ).respond_with_response(get_response_object(status_code, response_content)) - - mms_channel = MMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(mms_channel, method_name)(request_data) - - -@patch("urllib3.filepost.choose_boundary", return_value="mockBoundary") -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_query_parameters, expected_data, request_data, method_name", - prefix="case__supported_status", -) -def test_mms_endpoints__supported_status( - mock_boundary, - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_data, - request_data, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_data, - request_data, - method_name, - ) - response_dict = MMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@patch("urllib3.filepost.choose_boundary", return_value="mockBoundary") -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_query_parameters, expected_data, request_data, method_name", - prefix="case__unsupported_status", -) -def test_mms_endpoints__unsupported_status( - mock_boundary, - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_data, - request_data, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_query_parameters, - expected_data, - request_data, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/mms/integration/test_endpoints_integration_cases.py b/tests/mms/integration/test_endpoints_integration_cases.py deleted file mode 100644 index 7333384..0000000 --- a/tests/mms/integration/test_endpoints_integration_cases.py +++ /dev/null @@ -1,83 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_get_headers, get_expected_post_headers -from tests.mms.conftest import ( - get_inbound_mms_messages_query_parameters, - get_inbound_mms_messages_response, - get_mms_body_multipart, - get_mms_body_request, - get_mms_delivery_reports_query_parameters, - get_mms_delivery_reports_response, - get_send_mms_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "send_mms": { - "response_content": get_send_mms_response(), - "endpoint": "/mms/1/single", - "http_method": "POST", - "expected_headers": get_expected_post_headers( - "multipart/form-data; boundary=mockBoundary" - ), - "expected_query_parameters": None, - "expected_data": get_mms_body_multipart(), - "request_data": get_mms_body_request(), - "method_name": "send_mms_message", - }, - "get_mms_delivery_reports": { - "response_content": get_mms_delivery_reports_response(), - "endpoint": "/mms/1/reports", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_query_parameters": "messageId=abc-123&limit=1", - "expected_data": None, - "request_data": get_mms_delivery_reports_query_parameters(), - "method_name": "get_mms_delivery_reports", - }, - "get_inbound_mms_messages": { - "response_content": get_inbound_mms_messages_response(), - "endpoint": "/mms/1/inbox/reports", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_query_parameters": "limit=1", - "expected_data": None, - "request_data": get_inbound_mms_messages_query_parameters(), - "method_name": "get_inbound_mms_messages", - }, -} - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), status_code=(200, 400, 500)) -def case__supported_status(endpoint_type, status_code): - if endpoint_type == "send_mms": - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_data"]["media"].seek(0) - - return ( - status_code, - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["response_content"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_data"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_data"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - if endpoint_type == "send_mms": - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_data"]["media"].seek(0) - - return ( - 201, - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["response_content"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_data"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_data"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/mms/models/test_get_inbound_mms_messages.py b/tests/mms/models/test_get_inbound_mms_messages.py deleted file mode 100644 index 6a9cfc2..0000000 --- a/tests/mms/models/test_get_inbound_mms_messages.py +++ /dev/null @@ -1,19 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.mms.models.query_parameters.get_inbound_mms_messages import ( - GetInboundMMSMessagesQueryParameters, -) - - -@pytest.mark.parametrize("limit", [{}, "ABC"]) -def test_when_limit_is_invalid__validation_error_is_raised(limit): - with pytest.raises(ValidationError): - GetInboundMMSMessagesQueryParameters(**{"limit": limit}) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetInboundMMSMessagesQueryParameters(**{"limit": 2}) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/mms/models/test_get_mms_delivery_reports.py b/tests/mms/models/test_get_mms_delivery_reports.py deleted file mode 100644 index c506787..0000000 --- a/tests/mms/models/test_get_mms_delivery_reports.py +++ /dev/null @@ -1,31 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.mms.models.query_parameters.get_mms_delivery_reports import ( - GetMMSDeliveryReportsQueryParameters, -) - - -def test_when_bulk_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetMMSDeliveryReportsQueryParameters(**{"bulkId": {}}) - - -def test_when_message_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetMMSDeliveryReportsQueryParameters(**{"messageId": {}}) - - -@pytest.mark.parametrize("limit", [{}, "ABC"]) -def test_when_limit_is_invalid__validation_error_is_raised(limit): - with pytest.raises(ValidationError): - GetMMSDeliveryReportsQueryParameters(**{"limit": limit}) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetMMSDeliveryReportsQueryParameters( - **{"bulkId": "abc-123", "messageId": "bcd-334", "limit": 2} - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/mms/models/test_send_mms.py b/tests/mms/models/test_send_mms.py deleted file mode 100644 index ceb0a1e..0000000 --- a/tests/mms/models/test_send_mms.py +++ /dev/null @@ -1,269 +0,0 @@ -from datetime import date -from io import open -from tempfile import NamedTemporaryFile - -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.mms.models.body.send_mms import MMSMessageBody -from tests.conftest import get_random_string - - -@pytest.mark.parametrize( - "head", - [ - None, - "", - {}, - {"from": "38599854312"}, - {"to": "38598764321"}, - ], -) -def test_when_head_is_invalid__validation_error_is_raised(head): - with pytest.raises(ValidationError): - MMSMessageBody(**{"head": head}) - - -@pytest.mark.parametrize("from_number", [None, {}]) -def test_when_from_number_is_invalid__validation_error_is_raised(from_number): - with pytest.raises(ValidationError): - MMSMessageBody(**{"head": {"from": from_number, "to": "38598764321"}}) - - -@pytest.mark.parametrize("to", [None, {}]) -def test_when_to_number_is_invalid__validation_error_is_raised(to): - with pytest.raises(ValidationError): - MMSMessageBody(**{"head": {"from": "38599854312", "to": to}}) - - -@pytest.mark.parametrize("callback_data", [{}, get_random_string(201)]) -def test_when_callback_data_is_invalid__validation_error_is_raised(callback_data): - with pytest.raises(ValidationError): - MMSMessageBody( - **{ - "head": { - "from": "38599854312", - "to": "38598764321", - "callbackData": callback_data, - } - } - ) - - -@pytest.mark.parametrize("notify_url", [{}, "string", "ftp://url.com"]) -def test_when_notify_url_is_invalid__validation_error_is_raised(notify_url): - with pytest.raises(ValidationError): - MMSMessageBody( - **{ - "head": { - "from": "38599854312", - "to": "38598764321", - "notifyUrl": notify_url, - } - } - ) - - -@pytest.mark.parametrize("send_at", [{}, "22-03-2022", date.today()]) -def test_when_send_at_is_invalid__validation_error_is_raised(send_at): - with pytest.raises(ValidationError): - MMSMessageBody( - **{ - "head": { - "from": "38599854312", - "to": "38598764321", - "sendAt": send_at, - } - } - ) - - -@pytest.mark.parametrize("intermediate_report", [{}, "", 0, "True"]) -def test_when_intermediate_report_is_invalid__validation_error_is_raised( - intermediate_report, -): - with pytest.raises(ValidationError): - MMSMessageBody( - **{ - "head": { - "from": "38599854312", - "to": "38598764321", - "intermediateReport": intermediate_report, - } - } - ) - - -@pytest.mark.parametrize( - "delivery_time_window", - [ - {}, - {"from": {"hour": 12, "minute": 0}, "to": {"hour": 14, "minute": 0}}, - {"from": {"hour": 12, "minute": 0}, "days": ["FRIDAY"]}, - {"to": {"hour": 12, "minute": 0}, "days": ["FRIDAY"]}, - { - "from": {"hour": 12, "minute": 0}, - "to": {"hour": 12, "minute": 40}, - "days": ["FRIDAY"], - }, - ], -) -def test_when_delivery_time_window_is_invalid__validation_error_is_raised( - delivery_time_window, -): - with pytest.raises(ValidationError): - MMSMessageBody( - **{ - "head": { - "from": "38599854312", - "to": "38598764321", - "deliveryTimeWindow": delivery_time_window, - } - } - ) - - -@pytest.mark.parametrize( - "externally_hosted_media", - [ - {}, - [{}], - [{"contentType": "test", "contentId": "2"}], - [{"contentType": "test", "contentUrl": "http://url.com"}], - [{"contentId": "3", "contentUrl": "http://url.com"}], - ], -) -def test_when_externally_hosted_media_is_invalid__validation_error_is_raised( - externally_hosted_media, -): - with pytest.raises(ValidationError): - MMSMessageBody( - **{ - "head": { - "from": "38599854312", - "to": "38598764321", - }, - "externallyHostedMedia": externally_hosted_media, - } - ) - - -@pytest.mark.parametrize("content_url", [{}, "string", "ftp://url.com"]) -def test_when_content_url_is_invalid__validation_error_is_raised(content_url): - with pytest.raises(ValidationError): - MMSMessageBody( - **{ - "head": { - "from": "38599854312", - "to": "38598764321", - }, - "externallyHostedMedia": [ - { - "contentType": "test", - "contentId": "3", - "contentUrl": content_url, - } - ], - } - ) - - -@pytest.mark.parametrize("hour", [None, -2, 24]) -def test_when_hour_is_invalid__validation_error_is_raised(hour): - with pytest.raises(ValidationError): - MMSMessageBody( - **{ - "head": { - "from": "38599854312", - "to": "38598764321", - "deliveryTimeWindow": { - "from": {"hour": hour, "minute": 30}, - "to": {"hour": 12, "minute": 30}, - "days": ["MONDAY"], - }, - } - } - ) - - -@pytest.mark.parametrize("minute", [None, -2, 60]) -def test_when_minute_is_invalid__validation_error_is_raised(minute): - with pytest.raises(ValidationError): - MMSMessageBody( - **{ - "head": { - "from": "38599854312", - "to": "38598764321", - "deliveryTimeWindow": { - "to": {"hour": 12, "minute": minute}, - "from": {"hour": 10, "minute": 35}, - "days": ["MONDAY"], - }, - } - } - ) - - -@pytest.mark.parametrize("days", [[], "MONDAY", ["TEST"]]) -def test_when_days_is_invalid__validation_error_is_raised(days): - with pytest.raises(ValidationError): - MMSMessageBody( - **{ - "head": { - "from": "38599854312", - "to": "38598764321", - "deliveryTimeWindow": {"days": days}, - } - } - ) - - -@pytest.mark.parametrize("smil", [{}, "12"]) -def test_when_smil_is_invalid__validation_error_is_raised(smil): - with pytest.raises(ValidationError): - MMSMessageBody( - **{ - "head": { - "from": "38599854312", - "to": "38598764321", - }, - "smil": smil, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - f = NamedTemporaryFile("wb") - f.write(b"random bytes") - f.flush() - media_file = open(f.name, "rb") - - try: - MMSMessageBody( - **{ - "head": { - "from": "38598743321", - "to": "38599876543", - "validityPeriodMinutes": 300, - "callbackData": "test", - "delivery_time_window": { - "days": ["MONDAY", "THURSDAY"], - "from_time": {"hour": 10, "minute": 30}, - "to": {"hour": 12, "minute": 30}, - }, - }, - "text": "some text", - "media": media_file, - "externallyHostedMedia": [ - { - "contentType": "some type", - "contentId": "331", - "contentUrl": "https://someurl.com", - } - ], - "smil": "John", - } - ) - f.close() - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/rcs/conftest.py b/tests/rcs/conftest.py deleted file mode 100644 index c70febf..0000000 --- a/tests/rcs/conftest.py +++ /dev/null @@ -1,250 +0,0 @@ -from pydantic_factories import ModelFactory - -from infobip_channels.rcs.Models.body.send_bulk_rcs_message import RCSMessageBodyList -from infobip_channels.rcs.Models.body.send_rcs_message import RCSMessageBody - - -class RCSMessageBodyModelFactory(ModelFactory): - __model__ = RCSMessageBody - - -class RCSMessageBodyListModelFactory(ModelFactory): - __model__ = RCSMessageBodyList - - -class RcsMessageBodyIntegrationFactory(ModelFactory): - __model__ = RCSMessageBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return RCSMessageBody(**get_rcs_body_send_message()) - - -class RcsMessageBodyIntegrationListFactory(ModelFactory): - __model__ = RCSMessageBodyList - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return RCSMessageBodyList(**get_rcs_body_send_bulk_message()) - - -def get_rcs_body_send_message(): - return { - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "type": "REPLY", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "url": "http://www.example.test", - "type": "OPEN_URL", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "phoneNumber": "385977666618", - "type": "DIAL_PHONE", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "type": "REQUEST_LOCATION", - }, - ], - "type": "TEXT", - }, - "notifyUrl": "https://www.example.com/rcs", - "callbackData": "Callback data", - "messageId": "externalMessageId", - } - - -def get_rcs_body_send_bulk_message(): - return { - "messages": [ - { - "from": "myRcsSender1", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText1", - "suggestions": [ - { - "text": "exampleText1", - "postbackData": "examplePostbackData", - "type": "REPLY", - }, - { - "text": "exampleText1", - "postbackData": "examplePostbackData", - "url": "http://www.example.test", - "type": "OPEN_URL", - }, - { - "text": "exampleText1", - "postbackData": "examplePostbackData", - "phoneNumber": "385977666618", - "type": "DIAL_PHONE", - }, - { - "text": "exampleText1", - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - { - "text": "exampleText1", - "postbackData": "examplePostbackData", - "type": "REQUEST_LOCATION", - }, - ], - "type": "TEXT", - }, - "notifyUrl": "https://www.example.com/rcs", - "callbackData": "Callback data", - "messageId": "externalMessageId", - }, - { - "from": "myRcsSender2", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText2", - "suggestions": [ - { - "text": "exampleText2", - "postbackData": "examplePostbackData", - "type": "REPLY", - }, - { - "text": "exampleText2", - "postbackData": "examplePostbackData", - "url": "http://www.example.test", - "type": "OPEN_URL", - }, - { - "text": "exampleText2", - "postbackData": "examplePostbackData", - "phoneNumber": "385977666618", - "type": "DIAL_PHONE", - }, - { - "text": "exampleText2", - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - { - "text": "exampleText2", - "postbackData": "examplePostbackData", - "type": "REQUEST_LOCATION", - }, - ], - "type": "TEXT", - }, - "notifyUrl": "https://www.example.com/rcs", - "callbackData": "Callback data", - "messageId": "externalMessageId", - }, - ] - } - - -def send_rcs_message_response(): - return { - "messages": [ - { - "to": "385977666618", - "messageCount": 1, - "messageId": "06df139a-7eb5-4a6e-902e-40e892210455", - "status": { - "groupId": 1, - "groupName": "PENDING", - "id": 7, - "name": "PENDING_ENROUTE", - "description": "Message sent to next instance", - "action": "string", - }, - } - ] - } - - -def send_rcs_bulk_message_response(): - return [ - { - "messages": [ - { - "to": "385977666618", - "messageCount": 1, - "messageId": "06df139a-7eb5-4a6e-902e-40e892210455", - "status": { - "groupId": 1, - "groupName": "PENDING", - "id": 7, - "name": "PENDING_ENROUTE", - "description": "Message sent to next instance", - "action": "string", - }, - } - ] - }, - { - "messages": [ - { - "to": "385977666618", - "messageCount": 2, - "messageId": "06df139a-7eb5-4a6e-902e-40e892210455", - "status": { - "groupId": 1, - "groupName": "PENDING", - "id": 8, - "name": "PENDING_ENROUTE", - "description": "Message sent to next instance", - "action": "string", - }, - } - ] - }, - ] - - -def rcs_error_response(): - return { - "requestError": { - "serviceException": { - "messageId": "06df139a-7eb5-4a6e-902e-40e892210455", - "text": "Bad request", - "validationErrors": { - "request.message.content.media.file.url": [ - "is not a valid url", - ] - }, - } - } - } diff --git a/tests/rcs/integration/test_rcs_endpoints.py b/tests/rcs/integration/test_rcs_endpoints.py deleted file mode 100644 index fa80c6f..0000000 --- a/tests/rcs/integration/test_rcs_endpoints.py +++ /dev/null @@ -1,118 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.rcs.channel import RCSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - method_name, -): - message_body_instance = message_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - rcs_channel = RCSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(rcs_channel, method_name)(message_body) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, method_name", - prefix="case__supported_status", -) -def test_rcs_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - method_name, - ) - response_dict = RCSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - - if type(response_content) is list: - response_content = {"list": response_content} - else: - response_content = response_content - - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, method_name", - prefix="case__unsupported_status", -) -def test_rcs_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/rcs/integration/test_rcs_endpoints_cases.py b/tests/rcs/integration/test_rcs_endpoints_cases.py deleted file mode 100644 index 866e774..0000000 --- a/tests/rcs/integration/test_rcs_endpoints_cases.py +++ /dev/null @@ -1,77 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_post_headers -from tests.rcs.conftest import ( - RcsMessageBodyIntegrationFactory, - RcsMessageBodyIntegrationListFactory, - get_rcs_body_send_bulk_message, - get_rcs_body_send_message, - rcs_error_response, - send_rcs_bulk_message_response, - send_rcs_message_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "send_message": { - "endpoint": "/ott/rcs/1/message", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": None, - "expected_query_parameters": None, - "expected_json": RcsMessageBodyIntegrationFactory, - "request_data": get_rcs_body_send_message(), - "method_name": "send_rcs_message", - }, - "send_bulk_message": { - "endpoint": "/ott/rcs/1/message/bulk", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": None, - "expected_query_parameters": None, - "expected_json": RcsMessageBodyIntegrationListFactory, - "request_data": get_rcs_body_send_bulk_message(), - "method_name": "send_bulk_rcs_message", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, send_rcs_message_response], - [400, rcs_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "send_bulk_message" and responses[0] == 200: - response_content = send_rcs_bulk_message_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - send_rcs_message_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/rcs/models/test_send_bulk_rcs_message.py b/tests/rcs/models/test_send_bulk_rcs_message.py deleted file mode 100644 index bec07fa..0000000 --- a/tests/rcs/models/test_send_bulk_rcs_message.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.rcs.Models.body.send_bulk_rcs_message import RCSMessageBodyList -from tests.rcs.conftest import RCSMessageBodyListModelFactory - - -@pytest.mark.parametrize("messages_list", ["", None, {}]) -def test_when_messages_list_is_invalid__validation_error_is_raised(messages_list): - with pytest.raises(ValidationError): - RCSMessageBodyListModelFactory.build(**{"messages": messages_list}) - - -def test_when_input_data_is_valid_text__validation_error_is_not_raised(): - try: - RCSMessageBodyList( - **{ - "messages": [ - { - "from": "myRcsSender 1", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": {"text": "exampleText", "type": "TEXT"}, - }, - { - "from": "myRcsSender 2", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": {"text": "exampleText", "type": "TEXT"}, - }, - ] - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/rcs/models/test_send_rcs_message.py b/tests/rcs/models/test_send_rcs_message.py deleted file mode 100644 index b79ce4a..0000000 --- a/tests/rcs/models/test_send_rcs_message.py +++ /dev/null @@ -1,1238 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.rcs.Models.body.send_rcs_message import RCSMessageBody -from tests.conftest import get_random_numbers, get_random_string -from tests.rcs.conftest import RCSMessageBodyModelFactory - - -@pytest.mark.parametrize("to", [None, {}]) -def test_when_to_is_invalid__validation_error_is_raised(to): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": to, - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "type": "REPLY", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "url": "https://www.example.test", - "type": "OPEN_URL", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "phoneNumber": "385977666618", - "type": "DIAL_PHONE", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "type": "REQUEST_LOCATION", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize("content", ["", None, {}]) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": content, - } - ) - - -@pytest.mark.parametrize("content_text", ["", None, {}]) -def test_when_content_text_is_invalid__validation_error_is_raised(content_text): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": {"text": content_text, "type": "TEXT"}, - } - ) - - -@pytest.mark.parametrize("reply_text", ["", None, {}, get_random_string(26)]) -def test_when_reply_text_is_invalid__validation_error_is_raised(reply_text): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": reply_text, - "postbackData": "examplePostbackData", - "type": "REPLY", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "url": "https://www.example.test", - "type": "OPEN_URL", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "phoneNumber": "385977666618", - "type": "DIAL_PHONE", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "type": "REQUEST_LOCATION", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize("reply_postback_data", ["", None, {}, get_random_string(2049)]) -def test_when_reply_postback_data_is_invalid__validation_error_is_raised( - reply_postback_data, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": reply_postback_data, - "type": "REPLY", - } - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize("open_url_text", ["", None, {}, get_random_string(26)]) -def test_when_open_url_text_is_invalid__validation_error_is_raised(open_url_text): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": open_url_text, - "postbackData": "examplePostbackData", - "url": "https://www.example.test", - "type": "OPEN_URL", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize( - "open_url_postback_data", ["", None, {}, get_random_string(2049)] -) -def test_when_open_url_postback_data_is_invalid__validation_error_is_raised( - open_url_postback_data, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": open_url_postback_data, - "url": "https://www.example.test", - "type": "OPEN_URL", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize( - "open_url_url", - [ - "", - None, - {}, - get_random_string(1000), - "www.example.test", - f"http://myfile.com/{get_random_string(983)}", - ], -) -def test_when_open_url_url_postback_data_is_invalid__validation_error_is_raised( - open_url_url, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "url": open_url_url, - "type": "OPEN_URL", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize("dial_phone_text", ["", None, {}, get_random_string(26)]) -def test_when_dial_phone_text_is_invalid__validation_error_is_raised(dial_phone_text): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": dial_phone_text, - "postbackData": "examplePostbackData", - "phoneNumber": "385977666618", - "type": "DIAL_PHONE", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize( - "dial_phone_postback_data", ["", None, {}, get_random_string(2049)] -) -def test_when_dial_phone_postback_data_is_invalid__validation_error_is_raised( - dial_phone_postback_data, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": dial_phone_postback_data, - "phoneNumber": "385977666618", - "type": "DIAL_PHONE", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize( - "dial_phone_phone_number", - [get_random_string(2049), get_random_numbers(4), "097 888 9191"], -) -def test_when_dial_phone_phone_number_is_invalid__validation_error_is_raised( - dial_phone_phone_number, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "phoneNumber": dial_phone_phone_number, - "type": "DIAL_PHONE", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize("show_location_text", ["", None, {}, get_random_string(26)]) -def test_when_show_location_text_is_invalid__validation_error_is_raised( - show_location_text, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": show_location_text, - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize( - "show_location_postback_data", ["", None, {}, get_random_string(2049)] -) -def test_when_show_location_postback_data_is_invalid__validation_error_is_raised( - show_location_postback_data, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": show_location_postback_data, - "latitude": 45.793418, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize("show_location_latitude", [None, "", {}, -90.001, 90.0001]) -def test_when_show_location_latitude_is_invalid__validation_error_is_raised( - show_location_latitude, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "latitude": show_location_latitude, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize("show_location_longitude", [None, "", {}, -181.0, 181.0]) -def test_when_show_location_longitude_is_invalid__validation_error_is_raised( - show_location_longitude, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": show_location_longitude, - "label": "label", - "type": "SHOW_LOCATION", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize("show_location_label", [{}, get_random_string(101)]) -def test_when_show_location_label_is_invalid__validation_error_is_raised( - show_location_label, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": 15.946297, - "label": show_location_label, - "type": "SHOW_LOCATION", - }, - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize("request_location_text", [None, "", {}, get_random_string(26)]) -def test_when_request_location_text_is_invalid__validation_error_is_raised( - request_location_text, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": request_location_text, - "postbackData": "examplePostbackData", - "type": "REQUEST_LOCATION", - } - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize( - "request_location_postback_data", [None, "", {}, get_random_string(2049)] -) -def test_when_request_location_postback_data_is_invalid__validation_error_is_raised( - request_location_postback_data, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": request_location_postback_data, - "type": "REQUEST_LOCATION", - } - ], - "type": "TEXT", - }, - } - ) - - -@pytest.mark.parametrize("file", [None, "", {}]) -def test_when_file_is_invalid__validation_error_is_raised(file): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "file": file, - "thumbnail": {"url": "http://www.thumbnail.example.url"}, - "type": "FILE", - }, - } - ) - - -@pytest.mark.parametrize( - "file_url", - [ - None, - "", - {}, - "www.example.url", - get_random_string(1000), - f"http://myfile.com/{get_random_string(983)}", - ], -) -def test_when_file_url_is_invalid__validation_error_is_raised(file_url): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "file": {"url": file_url}, - "thumbnail": {"url": "http://www.thumbnail.example.url"}, - "type": "FILE", - }, - } - ) - - -@pytest.mark.parametrize( - "thumbnail_url", - [ - None, - "", - {}, - "www.example.url", - get_random_string(1000), - f"http://myfile.com/{get_random_string(983)}", - ], -) -def test_when_thumbnail_url_is_invalid__validation_error_is_raised(thumbnail_url): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "file": {"url": "http://www.example.url"}, - "thumbnail": {"url": thumbnail_url}, - "type": "FILE", - }, - } - ) - - -@pytest.mark.parametrize("content_type", [None, "", {}, "TEST"]) -def test_when_content_type_is_invalid__validation_error_is_raised(content_type): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "file": {"url": "http://www.example.url"}, - "thumbnail": {"url": "http://www.thumbnail.example.url"}, - "type": content_type, - }, - } - ) - - -@pytest.mark.parametrize("orientation", [None, "", {}, "TEST"]) -def test_when_orientation_is_invalid__validation_error_is_raised(orientation): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "orientation": orientation, - "alignment": "LEFT", - "content": { - "title": "title,", - "description": "description", - "media": { - "file": {"url": "http://www.example.url"}, - "thumbnail": {"url": "http://www.example.url"}, - "height": "MEDIUM", - }, - }, - "type": "CARD", - }, - } - ) - - -@pytest.mark.parametrize("alignment", [None, "", {}, "TEST"]) -def test_when_alignment_is_invalid__validation_error_is_raised(alignment): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "orientation": "HORIZONTAL", - "alignment": alignment, - "content": { - "title": "title,", - "description": "description", - "media": { - "file": {"url": "http://www.example.url"}, - "thumbnail": {"url": "http://www.example.url"}, - "height": "MEDIUM", - }, - }, - "type": "CARD", - }, - } - ) - - -@pytest.mark.parametrize("card_content", [None]) -def test_when_card_content_is_invalid__validation_error_is_raised(card_content): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "orientation": "HORIZONTAL", - "alignment": "LEFT", - "content": card_content, - "type": "CARD", - }, - } - ) - - -@pytest.mark.parametrize("content_height", [None, "", {}, "TEST"]) -def test_when_content_height_is_invalid__validation_error_is_raised(content_height): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "orientation": "HORIZONTAL", - "alignment": "LEFT", - "content": { - "title": "title", - "description": "description", - "media": { - "file": {"url": "http://www.example.url"}, - "height": content_height, - }, - }, - "type": "CARD", - }, - } - ) - - -@pytest.mark.parametrize("content_title", ["", {}, get_random_string(201)]) -def test_when_content_title_is_invalid__validation_error_is_raised(content_title): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "orientation": "HORIZONTAL", - "alignment": "LEFT", - "content": { - "title": content_title, - "description": "description", - "media": { - "file": {"url": "http://www.example.url"}, - "height": "MEDIUM", - }, - }, - "type": "CARD", - }, - } - ) - - -@pytest.mark.parametrize("content_description", ["", {}, get_random_string(2001)]) -def test_when_content_description_is_invalid__validation_error_is_raised( - content_description, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "orientation": "HORIZONTAL", - "alignment": "LEFT", - "content": { - "title": "ExampleTitle", - "description": content_description, - "media": { - "file": {"url": "http://www.example.url"}, - "height": "MEDIUM", - }, - }, - "type": "CARD", - }, - } - ) - - -@pytest.mark.parametrize("content_file", [None, "", {}]) -def test_when_content_file_is_invalid__validation_error_is_raised(content_file): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "orientation": "HORIZONTAL", - "alignment": "LEFT", - "content": { - "title": "title", - "description": "description", - "media": {"file": content_file, "height": "MEDIUM"}, - }, - "type": "CARD", - }, - } - ) - - -@pytest.mark.parametrize("content_file_url", [None, "", {}, "www.example.url"]) -def test_when_content_file_url_is_invalid__validation_error_is_raised(content_file_url): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "orientation": "HORIZONTAL", - "alignment": "LEFT", - "content": { - "title": "title", - "description": "description", - "media": { - "file": {"url": content_file_url}, - "height": "MEDIUM", - }, - }, - "type": "CARD", - }, - } - ) - - -@pytest.mark.parametrize("content_thumbnail_url", [None, "", {}, "www.example.url"]) -def test_when_content_thumbnail_url_is_invalid__validation_error_is_raised( - content_thumbnail_url, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "orientation": "HORIZONTAL", - "alignment": "LEFT", - "content": { - "title": "title", - "description": "description", - "media": { - "file": {"url": "http://www.example.url"}, - "thumbnail": {"url": content_thumbnail_url}, - "height": "MEDIUM", - }, - }, - "type": "CARD", - }, - } - ) - - -@pytest.mark.parametrize( - "suggestions_items", - [ - [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "type": "REPLY", - } - for _ in range(5) - ] - ], -) -def test_when_suggestions_items_is_invalid__validation_error_is_raised( - suggestions_items, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "orientation": "HORIZONTAL", - "alignment": "LEFT", - "content": { - "title": "title", - "description": "description", - "media": { - "file": {"url": "http://www.example.url"}, - "thumbnail": {"url": "http://www.example.url"}, - "height": "MEDIUM", - }, - "suggestions": suggestions_items, - }, - "type": "CARD", - }, - } - ) - - -@pytest.mark.parametrize("carousel_card_with", [None, "", {}, "TEST"]) -def test_when_carousel_card_with_is_invalid__validation_error_is_raised( - carousel_card_with, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "cardWidth": carousel_card_with, - "contents": [ - { - "title": "example title 1", - "description": "example description", - "media": { - "file": {"url": "http://www.example.url"}, - "height": "SHORT", - }, - }, - { - "title": "example title 2", - "description": "example description", - "media": { - "file": {"url": "http://www.example.url"}, - "height": "SHORT", - }, - }, - ], - "type": "CAROUSEL", - }, - } - ) - - -@pytest.mark.parametrize("carousel_contents", [None, "", {}]) -def test_when_carousel_contents_is_invalid__validation_error_is_raised( - carousel_contents, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "cardWidth": "SMALL", - "contents": carousel_contents, - "type": "CAROUSEL", - }, - } - ) - - -@pytest.mark.parametrize( - "carousel_contents_size", - [ - [{"title": "exampleText"} for _ in range(1)], - [{"title": "exampleText"} for _ in range(11)], - ], -) -def test_when_carousel_contents_size_is_invalid__validation_error_is_raised( - carousel_contents_size, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "cardWidth": "SMALL", - "contents": carousel_contents_size, - "type": "CAROUSEL", - }, - } - ) - - -@pytest.mark.parametrize("sms_failover_from", [None, "", {}]) -def test_when_sms_failover_from_is_invalid__validation_error_is_raised( - sms_failover_from, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": {"text": "exampleText", "type": "TEXT"}, - "smsFailover": { - "from": sms_failover_from, - "text": "We could not reach you over RCS messaging.", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - }, - "notifyUrl": "https://www.example.com/rcs", - "callbackData": "Callback data", - "messageId": "externalMessageId", - } - ) - - -@pytest.mark.parametrize("sms_failover_text", [None, "", {}]) -def test_when_sms_failover_text_is_invalid__validation_error_is_raised( - sms_failover_text, -): - with pytest.raises(ValidationError): - RCSMessageBodyModelFactory.build( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": {"text": "exampleText", "type": "TEXT"}, - "smsFailover": { - "from": "myInfoSmsSender", - "text": sms_failover_text, - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - }, - "notifyUrl": "https://www.example.com/rcs", - "callbackData": "Callback data", - "messageId": "externalMessageId", - } - ) - - -def test_when_input_data_carousel_is_valid_card__validation_error_is_not_raised(): - try: - RCSMessageBody( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "cardWidth": "SMALL", - "contents": [ - { - "title": "title 1", - "description": "description 1", - "media": { - "file": {"url": "http://www.example.url"}, - "thumbnail": {"url": "http://www.example.url"}, - "height": "MEDIUM", - }, - "suggestions": [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "type": "REPLY", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "url": "https://www.example.test", - "type": "OPEN_URL", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "phoneNumber": "385977666618", - "type": "DIAL_PHONE", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - ], - }, - { - "title": "title 2", - "description": "description 2", - "media": { - "file": {"url": "http://www.example.url"}, - "thumbnail": {"url": "http://www.example.url"}, - "height": "MEDIUM", - }, - "suggestions": [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "type": "REPLY", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "url": "https://www.example.test", - "type": "OPEN_URL", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "phoneNumber": "385977666618", - "type": "DIAL_PHONE", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - ], - }, - ], - "type": "CAROUSEL", - }, - "notifyUrl": "https://www.example.com/rcs", - "callbackData": "Callback data", - "messageId": "externalMessageId", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") - - -def test_when_input_data_is_valid_card__validation_error_is_not_raised(): - try: - RCSMessageBody( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "orientation": "HORIZONTAL", - "alignment": "LEFT", - "content": { - "title": "title", - "description": "description", - "media": { - "file": {"url": "http://www.example.url"}, - "thumbnail": {"url": "http://www.example.url"}, - "height": "MEDIUM", - }, - "suggestions": [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "type": "REPLY", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "url": "https://www.example.test", - "type": "OPEN_URL", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "phoneNumber": "385977666618", - "type": "DIAL_PHONE", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - ], - }, - "type": "CARD", - }, - "notifyUrl": "https://www.example.com/rcs", - "callbackData": "Callback data", - "messageId": "externalMessageId", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") - - -def test_when_input_data_is_valid_text__validation_error_is_not_raised(): - try: - RCSMessageBody( - **{ - "from": "myRcsSender", - "to": "385977666618", - "validityPeriod": 15, - "validityPeriodTimeUnit": "MINUTES", - "content": { - "text": "exampleText", - "suggestions": [ - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "type": "REPLY", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "url": "https://www.example.test", - "type": "OPEN_URL", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "phoneNumber": "385977666618", - "type": "DIAL_PHONE", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "latitude": 45.793418, - "longitude": 15.946297, - "label": "label", - "type": "SHOW_LOCATION", - }, - { - "text": "exampleText", - "postbackData": "examplePostbackData", - "type": "REQUEST_LOCATION", - }, - ], - "type": "TEXT", - }, - "notifyUrl": "https://www.example.com/rcs", - "callbackData": "Callback data", - "messageId": "externalMessageId", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/conftest.py b/tests/sms/conftest.py deleted file mode 100644 index 0a7db48..0000000 --- a/tests/sms/conftest.py +++ /dev/null @@ -1,660 +0,0 @@ -from pydantic_factories import ModelFactory - -from infobip_channels.sms.models.body.create_tfa_application import ( - CreateTFAApplicationBody, -) -from infobip_channels.sms.models.body.create_tfa_message_template import ( - CreateTFAMessageTemplateBody, -) -from infobip_channels.sms.models.body.preview_message import PreviewSMSMessage -from infobip_channels.sms.models.body.reschedule_sms_messages import ( - RescheduleSMSMessagesMessageBody, -) -from infobip_channels.sms.models.body.resend_pin_over_sms import ResendPINOverSMSBody -from infobip_channels.sms.models.body.resend_pin_over_voice import ( - ResendPINOverVoiceBody, -) -from infobip_channels.sms.models.body.send_binary_message import BinarySMSMessageBody -from infobip_channels.sms.models.body.send_message import SMSMessageBody -from infobip_channels.sms.models.body.send_pin_over_sms import SendPINOverSMSBody -from infobip_channels.sms.models.body.send_pin_over_voice import SendPINOverVoiceBody -from infobip_channels.sms.models.body.update_scheduled_messages_status import ( - UpdateScheduledSMSMessagesMessageBody, -) -from infobip_channels.sms.models.body.update_tfa_application import ( - UpdateTFAApplicationBody, -) -from infobip_channels.sms.models.body.update_tfa_message_template import ( - UpdateTFAMessageTemplateBody, -) -from infobip_channels.sms.models.body.verify_phone_number import VerifyPhoneNumberBody -from infobip_channels.sms.models.response.send_message import SendSMSResponse - - -class GenerateSMSMessageBodyFactory(ModelFactory): - __model__ = SMSMessageBody - - -class GenerateSMSMessageBodyFactoryIntegration(ModelFactory): - __model__ = SMSMessageBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return SMSMessageBody(**get_send_sms_message_body()) - - -class GenerateBinarySMSMessageBodyFactory(ModelFactory): - __model__ = BinarySMSMessageBody - - -class GenerateBinarySMSMessageBodyFactoryIntegration(ModelFactory): - __model__ = BinarySMSMessageBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return BinarySMSMessageBody(**get_send_binary_sms_message_body()) - - -class GenerateSendSMSMessageResponse(ModelFactory): - __model__ = SendSMSResponse - - -class GeneratePreviewSMSMessageBodyFactory(ModelFactory): - __model__ = PreviewSMSMessage - - -class GenerateRescheduleSMSMessagesFactory(ModelFactory): - __model__ = RescheduleSMSMessagesMessageBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return RescheduleSMSMessagesMessageBody( - **get_reschedule_sms_messages_message_body() - ) - - -class GenerateUpdateScheduledSMSMessagesStatusFactory(ModelFactory): - __model__ = UpdateScheduledSMSMessagesMessageBody - - -class GenerateCreateTFAApplicationBodyFactoryIntegration(ModelFactory): - __model__ = CreateTFAApplicationBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return CreateTFAApplicationBody(**get_create_tfa_application_body()) - - -class GenerateUpdateTFAApplicationBodyFactoryIntegration(ModelFactory): - __model__ = UpdateTFAApplicationBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return UpdateTFAApplicationBody(**get_update_tfa_application_body()) - - -class GenerateCreateTFAMessageTemplateBodyFactoryIntegration(ModelFactory): - __model__ = CreateTFAMessageTemplateBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return CreateTFAMessageTemplateBody(**get_create_tfa_message_template_body()) - - -class GenerateUpdateTFAMessageTemplateBodyFactoryIntegration(ModelFactory): - __model__ = UpdateTFAMessageTemplateBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return UpdateTFAMessageTemplateBody(**get_update_tfa_message_template_body()) - - -class GenerateResendPINOverSMSBodyFactoryIntegration(ModelFactory): - __model__ = ResendPINOverSMSBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return ResendPINOverSMSBody(**get_resend_pin_over_sms_response()) - - -class GenerateResendPINOverVoiceBodyFactoryIntegration(ModelFactory): - __model__ = ResendPINOverVoiceBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return ResendPINOverVoiceBody(**get_resend_pin_over_voice_response()) - - -class GenerateSendPINOverSMSBodyFactoryIntegration(ModelFactory): - __model__ = SendPINOverSMSBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return SendPINOverSMSBody(**get_send_pin_over_sms_body()) - - -class GenerateSendPINOverVoiceBodyFactoryIntegration(ModelFactory): - __model__ = SendPINOverVoiceBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return SendPINOverVoiceBody(**get_send_pin_over_voice_body()) - - -class GenerateVerifyPhoneNumberBodyFactoryIntegration(ModelFactory): - __model__ = VerifyPhoneNumberBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return VerifyPhoneNumberBody(**get_verify_phone_number_body()) - - -def get_send_sms_message_body(): - return { - "messages": [ - { - "destinations": [{"to": "41793026727"}], - "from": "InfoSMS", - "text": "This is a sample message", - } - ] - } - - -def get_preview_send_sms_message_body(): - return { - "text": "Ως Μεγαρικό ψήφισμα είναι γνωστή η απόφαση της Εκκλησίας του δήμου " - "των Αθηναίων (πιθανόν γύρω στο 433/2 π.Χ.) να επιβάλει αυστηρό και " - "καθολικό εμπάργκο στα", - "transliteration": "GREEK", - } - - -def get_send_binary_sms_message_body(): - return { - "bulkId": "BULK-ID-123-xyz", - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "callbackData": "DLR callback data", - "destinations": [ - {"messageId": "MESSAGE-ID-123-xyz", "to": "41793026727"}, - {"to": "41793026834"}, - ], - "from": "InfoSMS", - "intermediateReport": True, - "notifyContentType": "application/json", - "notifyUrl": "https://www.example.com/sms/advanced", - "validityPeriod": 720, - }, - ], - } - - -def get_reschedule_sms_messages_query_parameters(): - return {"bulkId": "35122736310703571952"} - - -def get_reschedule_sms_messages_message_body(): - return {"sendAt": "2022-07-20T16:00:00.000+0000"} - - -def get_sms_request_response(): - return { - "bulkId": "2034072219640523072", - "messages": [ - { - "messageId": "41793026727", - "status": { - "description": "Message sent to next instance", - "groupId": 1, - "groupName": "PENDING", - "id": 26, - "name": "MESSAGE_ACCEPTED", - }, - "to": "2250be2d4219-3af1-78856-aabe-1362af1edfd2", - } - ], - } - - -def get_scheduled_sms_messages_response(): - return {"bulkId": "BulkId-xyz-123", "sendAt": "2022-07-20T16:00:00.000+0000"} - - -def get_update_scheduled_sms_messages_status_response(): - return {"bulkId": "BulkId-xyz-123", "status": "PAUSED"} - - -def get_scheduled_sms_messages_status_response(): - return { - "results": [ - { - "bulkId": "BULK-ID-123-xyz", - "messageId": "MESSAGE-ID-123-xyz", - "to": "41793026727", - "sentAt": "2019-11-09T16:00:00.000+0000", - "doneAt": "2019-11-09T16:00:00.000+0000", - "smsCount": 1, - "price": {"pricePerMessage": 0.01, "currency": "EUR"}, - "status": { - "groupId": 3, - "groupName": "DELIVERED", - "id": 5, - "name": "DELIVERED_TO_HANDSET", - "description": "Message delivered to handset", - }, - "error": { - "groupId": 0, - "groupName": "Ok", - "id": 0, - "name": "NO_ERROR", - "description": "No Error", - "permanent": False, - }, - }, - { - "bulkId": "BULK-ID-123-xyz", - "messageId": "12db39c3-7822-4e72-a3ec-c87442c0ffc5", - "to": "41793026834", - "sentAt": "2019-11-09T17:00:00.000+0000", - "doneAt": "2019-11-09T17:00:00.000+0000", - "smsCount": 1, - "price": {"pricePerMessage": 0.01, "currency": "EUR"}, - "status": { - "groupId": 3, - "groupName": "DELIVERED", - "id": 5, - "name": "DELIVERED_TO_HANDSET", - "description": "Message delivered to handset", - }, - "error": { - "groupId": 0, - "groupName": "Ok", - "id": 0, - "name": "NO_ERROR", - "description": "No Error", - "permanent": False, - }, - }, - ] - } - - -def get_sms_request_error_response(): - return { - "requestError": { - "serviceException": { - "messageId": "BAD_REQUEST", - "text": "Bad request", - "validationErrors": { - "content.text": [ - "size must be between 1 and 4096", - "must not be blank", - ] - }, - } - } - } - - -def get_preview_send_sms_response(): - return { - "originalText": "Let's see how many characters will remain unused in this " - "message.", - "previews": [ - { - "textPreview": "ΩΣ MEΓAPIKO ΨHΦIΣMA EINAI ΓNΩΣTH H AΠOΦAΣH THΣ " - "EKKΛHΣIAΣ TOY ΔHMOY TΩN AΘHNAIΩN (ΠIΘANON ΓYPΩ ΣTO " - "433/2 Π.X.) NA EΠIBAΛEI AYΣTHPO KAI KAΘOΛIKO EMΠAPΓKO " - "ΣTA", - "messageCount": 1, - "charactersRemaining": 5, - "configuration": {"transliteration": "GREEK"}, - } - ], - } - - -def get_outbound_sms_delivery_reports_response(): - return { - "results": [ - { - "bulkId": "BULK-ID-123-xyz", - "messageId": "MESSAGE-ID-123-xyz", - "to": "41793026727", - "sentAt": "2019-11-09T16:00:00.000+0000", - "doneAt": "2019-11-09T16:00:00.000+0000", - "smsCount": 1, - "price": {"pricePerMessage": 0.01, "currency": "EUR"}, - "status": { - "groupId": 3, - "groupName": "DELIVERED", - "id": 5, - "name": "DELIVERED_TO_HANDSET", - "description": "Message delivered to handset", - }, - "error": { - "groupId": 0, - "groupName": "Ok", - "id": 0, - "name": "NO_ERROR", - "description": "No Error", - "permanent": False, - }, - }, - ] - } - - -def get_outbound_sms_message_logs_response(): - return { - "results": [ - { - "bulkId": "BULK-ID-123-xyz", - "messageId": "MESSAGE-ID-123-xyz", - "to": "41793026727", - "sentAt": "2019-11-09T16:00:00.000+0000", - "doneAt": "2019-11-09T16:00:00.000+0000", - "smsCount": 1, - "mccMnc": "22801", - "price": {"pricePerMessage": 0.01, "currency": "EUR"}, - "status": { - "groupId": 3, - "groupName": "DELIVERED", - "id": 5, - "name": "DELIVERED_TO_HANDSET", - "description": "Message delivered to handset", - }, - "error": { - "groupId": 0, - "groupName": "Ok", - "id": 0, - "name": "NO_ERROR", - "description": "No Error", - "permanent": False, - }, - }, - { - "bulkId": "BULK-ID-123-xyz", - "messageId": "MESSAGE-ID-ijkl-45", - "to": "41793026834", - "sentAt": "2019-11-09T17:00:00.000+0000", - "doneAt": "2019-11-09T17:00:00.000+0000", - "smsCount": 1, - "mccMnc": "22801", - "price": {"pricePerMessage": 0.01, "currency": "EUR"}, - "status": { - "groupId": 3, - "groupName": "DELIVERED", - "id": 5, - "name": "DELIVERED_TO_HANDSET", - "description": "Message delivered to handset", - }, - "error": { - "groupId": 0, - "groupName": "Ok", - "id": 0, - "name": "NO_ERROR", - "description": "No Error", - "permanent": False, - }, - }, - ] - } - - -def get_inbound_sms_messages_response(): - return { - "results": [ - { - "messageId": "817790313235066447", - "from": "385916242493", - "to": "385921004026", - "text": "QUIZ Correct answer is Paris", - "cleanText": "Correct answer is Paris", - "keyword": "QUIZ", - "receivedAt": "2019-11-09T16:00:00.000+0000", - "smsCount": 1, - "price": {"pricePerMessage": 0.1, "currency": "EUR"}, - "callbackData": "callbackData", - } - ], - "messageCount": 1, - "pendingMessageCount": 0, - } - - -def get_sms_send_message_over_query_parameters(): - return { - "username": "TestUser", - "password": "Pass123", - "to": ["41793026727"], - } - - -def get_outbound_sms_delivery_reports_query_parameters(): - return { - "bulkId": "BULK-ID-123-xyz", - "messageId": "MESSAGE-ID-123-xyz", - "limit": 1, - } - - -def get_outbound_sms_message_logs_query_parameters(): - return { - "from": "41793026999", - "to": "41793026727", - "bulkId": ["BULK-ID-123-xyz"], - } - - -def get_inbound_sms_messages_query_parameters(): - return { - "limit": 2, - } - - -def get_scheduled_sms_messages(): - return { - "bulk_id": "BulkId-xyz-123", - } - - -def get_tfa_application(): - return { - "applicationId": "1234567890", - "name": "Application name", - "configuration": { - "pinAttempts": 5, - "allowMultiplePinVerifications": True, - "pinTimeToLive": "10m", - "verifyPinLimit": "2/4s", - "sendPinPerApplicationLimit": "5000/12h", - "sendPinPerPhoneNumberLimit": "2/1d", - }, - "enabled": True, - } - - -def get_create_tfa_application_body(): - return get_tfa_application() - - -def get_update_tfa_application_body(): - return get_tfa_application() - - -def get_create_tfa_application_response(): - return get_tfa_application() - - -def get_tfa_request_error_response(): - return { - "requestError": { - "serviceException": { - "messageId": "BAD_REQUEST", - "text": "Bad request", - } - } - } - - -def get_update_tfa_application_response(): - return get_tfa_application() - - -def get_tfa_application_response(): - return get_tfa_application() - - -def get_tfa_applications_response(): - return [get_tfa_application()] - - -def get_create_tfa_message_template_response(): - return get_tfa_message_template() - - -def get_update_tfa_message_template_response(): - return get_tfa_message_template() - - -def get_tfa_message_template(): - return { - "pinPlaceholder": "{{pin}}", - "messageText": "Your pin is {{pin}}", - "pinLength": 4, - "pinType": "ALPHANUMERIC", - "language": "en", - "senderId": "Infobip 2FA", - "repeatDTMF": "1#", - "speechRate": 1, - } - - -def get_create_tfa_message_template_body(): - return get_tfa_message_template() - - -def get_update_tfa_message_template_body(): - return get_tfa_message_template() - - -def get_send_pin_body(): - return { - "applicationId": "1234567", - "messageId": "7654321", - "from": "Sender 1", - "to": "41793026727", - "placeholders": {"firstName": "John"}, - } - - -def get_send_pin_over_sms_body(): - return get_send_pin_body() - - -def get_send_pin_over_voice_body(): - return get_send_pin_body() - - -def get_send_pin_over_sms_status(): - return { - "pinId": "9C817C6F8AF3D48F9FE553282AFA2B67", - "to": "41793026727", - "ncStatus": "NC_DESTINATION_REACHABLE", - "smsStatus": "MESSAGE_SENT", - } - - -def get_send_pin_over_voice_status(): - return { - "pinId": "9C817C6F8AF3D48F9FE553282AFA2B67", - "to": "41793026727", - "callStatus": "PENDING_ACCEPTED", - } - - -def get_resend_pin_over_body(): - return {"placeholders": {"firstName": "John"}} - - -def get_resend_pin_over_sms_body(): - return get_resend_pin_over_body() - - -def get_resend_pin_over_voice_body(): - return get_resend_pin_over_body() - - -def get_send_pin_over_sms_response(): - return get_send_pin_over_sms_status() - - -def get_send_pin_over_voice_response(): - return get_send_pin_over_voice_status() - - -def get_resend_pin_over_sms_response(): - return get_send_pin_over_sms_status() - - -def get_resend_pin_over_voice_response(): - return get_send_pin_over_voice_status() - - -def get_verify_phone_number_body(): - return {"pin": "1598"} - - -def get_verify_phone_number_response(): - return { - "pinId": "9C817C6F8AF3D48F9FE553282AFA2B67", - "msisdn": "41793026727", - "verified": True, - "attemptsRemaining": 0, - } - - -def get_get_tfa_verification_status_response(): - return { - "verifications": [ - { - "msisdn": "41793026727", - "verified": True, - "verifiedAt": 1418364366, - "sentAt": 1418364246, - }, - { - "msisdn": "41793026746", - "verified": False, - "verifiedAt": 1418364226, - "sentAt": 1418333246, - }, - ] - } - - -def get_get_tfa_message_templates_response(): - return [get_tfa_message_template()] - - -def get_get_tfa_message_template_response(): - return get_tfa_message_template() diff --git a/tests/sms/integration/test_reschedule_and_update.py b/tests/sms/integration/test_reschedule_and_update.py deleted file mode 100644 index 1f151e6..0000000 --- a/tests/sms/integration/test_reschedule_and_update.py +++ /dev/null @@ -1,119 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - message_body_instance = message_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)(request_query_parameters, message_body) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_reschedule_and_update_cases.py b/tests/sms/integration/test_reschedule_and_update_cases.py deleted file mode 100644 index cfb8c5a..0000000 --- a/tests/sms/integration/test_reschedule_and_update_cases.py +++ /dev/null @@ -1,78 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_put_headers -from tests.sms.conftest import ( - GenerateRescheduleSMSMessagesFactory, - GenerateUpdateScheduledSMSMessagesStatusFactory, - get_reschedule_sms_messages_query_parameters, - get_scheduled_sms_messages_response, - get_sms_request_error_response, - get_update_scheduled_sms_messages_status_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "reschedule_sms_messages": { - "endpoint": "/sms/1/bulks", - "http_method": "PUT", - "expected_headers": get_expected_put_headers(), - "expected_path_parameters": None, - "expected_query_parameters": "bulkId=35122736310703571952", - "expected_json": GenerateRescheduleSMSMessagesFactory, - "request_query_parameters": get_reschedule_sms_messages_query_parameters(), - "method_name": "reschedule_sms_messages", - }, - "update_scheduled_sms_messages_status": { - "endpoint": "/sms/1/bulks/status", - "http_method": "PUT", - "expected_headers": get_expected_put_headers(), - "expected_path_parameters": None, - "expected_query_parameters": "bulkId=35122736310703571952", - "expected_json": GenerateUpdateScheduledSMSMessagesStatusFactory, - "request_query_parameters": get_reschedule_sms_messages_query_parameters(), - "method_name": "update_scheduled_sms_messages_status", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_scheduled_sms_messages_response], - [400, get_sms_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "update_scheduled_sms_messages_status" and responses[0] == 200: - response_content = get_update_scheduled_sms_messages_status_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_sms_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/integration/test_send_sms_body_endpoints.py b/tests/sms/integration/test_send_sms_body_endpoints.py deleted file mode 100644 index bb47dc4..0000000 --- a/tests/sms/integration/test_send_sms_body_endpoints.py +++ /dev/null @@ -1,119 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - message_body_instance = message_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)(message_body) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_send_sms_body_endpoints_cases.py b/tests/sms/integration/test_send_sms_body_endpoints_cases.py deleted file mode 100644 index 83ff037..0000000 --- a/tests/sms/integration/test_send_sms_body_endpoints_cases.py +++ /dev/null @@ -1,91 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_post_headers -from tests.sms.conftest import ( - GenerateBinarySMSMessageBodyFactoryIntegration, - GeneratePreviewSMSMessageBodyFactory, - GenerateSMSMessageBodyFactoryIntegration, - get_preview_send_sms_message_body, - get_preview_send_sms_response, - get_send_binary_sms_message_body, - get_send_sms_message_body, - get_sms_request_error_response, - get_sms_request_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "send_SMS_message": { - "endpoint": "/sms/2/text/advanced", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": None, - "expected_query_parameters": None, - "expected_json": GenerateSMSMessageBodyFactoryIntegration, - "request_parameters": get_send_sms_message_body(), - "method_name": "send_sms_message", - }, - "send_binary_SMS_message": { - "endpoint": "/sms/2/binary/advanced", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": None, - "expected_query_parameters": None, - "expected_json": GenerateBinarySMSMessageBodyFactoryIntegration, - "request_parameters": get_send_binary_sms_message_body(), - "method_name": "send_binary_sms_message", - }, - "preview_SMS_message": { - "endpoint": "/sms/1/preview", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": None, - "expected_query_parameters": None, - "expected_json": GeneratePreviewSMSMessageBodyFactory, - "request_parameters": get_preview_send_sms_message_body(), - "method_name": "preview_sms_message", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_sms_request_response], - [400, get_sms_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "preview_SMS_message" and responses[0] == 200: - response_content = get_preview_send_sms_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_sms_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/integration/test_sms_query_endpoints.py b/tests/sms/integration/test_sms_query_endpoints.py deleted file mode 100644 index 7ecb4df..0000000 --- a/tests/sms/integration/test_sms_query_endpoints.py +++ /dev/null @@ -1,117 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)(request_parameters) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_sms_query_endpoints_cases.py b/tests/sms/integration/test_sms_query_endpoints_cases.py deleted file mode 100644 index 8c3023e..0000000 --- a/tests/sms/integration/test_sms_query_endpoints_cases.py +++ /dev/null @@ -1,139 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_get_headers -from tests.sms.conftest import ( - get_inbound_sms_messages_query_parameters, - get_inbound_sms_messages_response, - get_outbound_sms_delivery_reports_query_parameters, - get_outbound_sms_delivery_reports_response, - get_outbound_sms_message_logs_query_parameters, - get_outbound_sms_message_logs_response, - get_scheduled_sms_messages, - get_scheduled_sms_messages_response, - get_scheduled_sms_messages_status_response, - get_sms_request_error_response, - get_sms_request_response, - get_sms_send_message_over_query_parameters, -) - -ENDPOINT_TEST_ARGUMENTS = { - "get_outbound_sms_delivery_reports": { - "endpoint": "/sms/1/reports", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": None, - "expected_query_parameters": "bulkId=BULK-ID-123-xyz&messageId=MESSAGE-ID-123" - "-xyz&limit=1", - "expected_json": None, - "request_parameters": get_outbound_sms_delivery_reports_query_parameters(), - "method_name": "get_outbound_sms_delivery_reports", - }, - "get_outbound_sms_message_logs": { - "endpoint": "/sms/1/logs", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": None, - "expected_query_parameters": "from=41793026999&to=41793026727&bulkId=BULK-ID" - "-123-xyz", - "expected_json": None, - "request_parameters": get_outbound_sms_message_logs_query_parameters(), - "method_name": "get_outbound_sms_message_logs", - }, - "get_inbound_sms_messages": { - "endpoint": "/sms/1/inbox/reports", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": None, - "expected_query_parameters": "limit=2", - "expected_json": None, - "request_parameters": get_inbound_sms_messages_query_parameters(), - "method_name": "get_inbound_sms_messages", - }, - "send_SMS_message_over_query_parameters": { - "endpoint": "/sms/1/text/query", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": None, - "expected_query_parameters": "username=TestUser&password=Pass123&to" - "=41793026727&flash=False", - "expected_json": None, - "request_parameters": get_sms_send_message_over_query_parameters(), - "method_name": "send_sms_message_over_query_parameters", - }, - "get_scheduled_sms_messages": { - "endpoint": "/sms/1/bulks", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": None, - "expected_query_parameters": "bulkId=BulkId-xyz-123", - "expected_json": None, - "request_parameters": get_scheduled_sms_messages(), - "method_name": "get_scheduled_sms_messages", - }, - "get_scheduled_sms_messages_status": { - "endpoint": "/sms/1/bulks/status", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": None, - "expected_query_parameters": "bulkId=BulkId-xyz-123", - "expected_json": None, - "request_parameters": get_scheduled_sms_messages(), - "method_name": "get_scheduled_sms_messages_status", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_outbound_sms_delivery_reports_response], - [400, get_sms_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "get_outbound_sms_message_logs" and responses[0] == 200: - response_content = get_outbound_sms_message_logs_response - if endpoint_type == "get_inbound_sms_messages" and responses[0] == 200: - response_content = get_inbound_sms_messages_response - if ( - endpoint_type == "send_SMS_message_over_query_parameters" - and responses[0] == 200 - ): - response_content = get_sms_request_response - if endpoint_type == "get_scheduled_sms_messages" and responses[0] == 200: - response_content = get_scheduled_sms_messages_response - - if endpoint_type == "get_scheduled_sms_messages_status" and responses[0] == 200: - response_content = get_scheduled_sms_messages_status_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_sms_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/integration/test_tfa_create_and_update_path.py b/tests/sms/integration/test_tfa_create_and_update_path.py deleted file mode 100644 index 26de19d..0000000 --- a/tests/sms/integration/test_tfa_create_and_update_path.py +++ /dev/null @@ -1,121 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - message_body_instance = request_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)( - expected_path_parameters["appId"], request_body - ) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_tfa_create_and_update_path_cases.py b/tests/sms/integration/test_tfa_create_and_update_path_cases.py deleted file mode 100644 index 2993149..0000000 --- a/tests/sms/integration/test_tfa_create_and_update_path_cases.py +++ /dev/null @@ -1,82 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_post_headers -from tests.sms.conftest import ( - GenerateCreateTFAMessageTemplateBodyFactoryIntegration, - GenerateUpdateTFAApplicationBodyFactoryIntegration, - get_create_tfa_application_response, - get_create_tfa_message_template_body, - get_create_tfa_message_template_response, - get_tfa_request_error_response, - get_update_tfa_application_body, - get_update_tfa_application_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "update_tfa_application": { - "endpoint": "/2fa/2/applications/1234567890", - "http_method": "PUT", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": {"appId": 1234567890}, - "expected_query_parameters": None, - "expected_json": GenerateUpdateTFAApplicationBodyFactoryIntegration, - "request_parameters": get_update_tfa_application_body(), - "method_name": "update_tfa_application", - }, - "create_tfa_message_template": { - "endpoint": "/2fa/2/applications/1234567890/messages", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": {"appId": 1234567890}, - "expected_query_parameters": None, - "expected_json": GenerateCreateTFAMessageTemplateBodyFactoryIntegration, - "request_parameters": get_create_tfa_message_template_body(), - "method_name": "create_tfa_message_template", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_create_tfa_application_response], - [400, get_tfa_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "update_tfa_application" and responses[0] == 200: - response_content = get_update_tfa_application_response - elif endpoint_type == "create_tfa_message_template" and responses[0] == 200: - response_content = get_create_tfa_message_template_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_tfa_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/integration/test_tfa_create_application.py b/tests/sms/integration/test_tfa_create_application.py deleted file mode 100644 index ee0ac5d..0000000 --- a/tests/sms/integration/test_tfa_create_application.py +++ /dev/null @@ -1,119 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - message_body_instance = request_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)(request_body) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_tfa_create_application_cases.py b/tests/sms/integration/test_tfa_create_application_cases.py deleted file mode 100644 index b87c2a5..0000000 --- a/tests/sms/integration/test_tfa_create_application_cases.py +++ /dev/null @@ -1,63 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_post_headers -from tests.sms.conftest import ( - GenerateCreateTFAApplicationBodyFactoryIntegration, - get_create_tfa_application_body, - get_create_tfa_application_response, - get_tfa_request_error_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "create_tfa_application": { - "endpoint": "/2fa/2/applications", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": "", - "expected_query_parameters": None, - "expected_json": GenerateCreateTFAApplicationBodyFactoryIntegration, - "request_parameters": get_create_tfa_application_body(), - "method_name": "create_tfa_application", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_create_tfa_application_response], - [400, get_tfa_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_tfa_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/integration/test_tfa_get.py b/tests/sms/integration/test_tfa_get.py deleted file mode 100644 index 0fb153c..0000000 --- a/tests/sms/integration/test_tfa_get.py +++ /dev/null @@ -1,123 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)() - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - - if type(response_content) is list: - response_content = {"list": response_content} - else: - response_content = response_content - - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_tfa_get_cases.py b/tests/sms/integration/test_tfa_get_cases.py deleted file mode 100644 index acd3538..0000000 --- a/tests/sms/integration/test_tfa_get_cases.py +++ /dev/null @@ -1,64 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_get_headers -from tests.sms.conftest import ( - get_tfa_applications_response, - get_tfa_request_error_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "get_tfa_applications": { - "endpoint": "/2fa/2/applications", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": None, - "expected_query_parameters": None, - "expected_json": None, - "request_parameters": None, - "method_name": "get_tfa_applications", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_tfa_applications_response()], - [400, get_tfa_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "get_tfa_applications" and responses[0] == 200: - response_content = get_tfa_applications_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_tfa_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/integration/test_tfa_get_path.py b/tests/sms/integration/test_tfa_get_path.py deleted file mode 100644 index 1c99446..0000000 --- a/tests/sms/integration/test_tfa_get_path.py +++ /dev/null @@ -1,123 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)(expected_path_parameters["appId"]) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - - if type(response_content) is list: - response_content = {"list": response_content} - else: - response_content = response_content - - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_tfa_get_path_cases.py b/tests/sms/integration/test_tfa_get_path_cases.py deleted file mode 100644 index 2e72e67..0000000 --- a/tests/sms/integration/test_tfa_get_path_cases.py +++ /dev/null @@ -1,78 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_get_headers -from tests.sms.conftest import ( - get_get_tfa_message_templates_response, - get_tfa_application_response, - get_tfa_request_error_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "get_tfa_application": { - "endpoint": "/2fa/2/applications/1234567890", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": {"appId": 1234567890}, - "expected_query_parameters": None, - "expected_json": None, - "request_parameters": None, - "method_name": "get_tfa_application", - }, - "get_tfa_message_templates": { - "endpoint": "/2fa/2/applications/1234567890/messages", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": {"appId": 1234567890}, - "expected_query_parameters": None, - "expected_json": None, - "request_parameters": None, - "method_name": "get_tfa_message_templates", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_tfa_application_response], - [200, get_get_tfa_message_templates_response], - [400, get_tfa_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "get_tfa_application" and responses[0] == 200: - response_content = get_tfa_application_response - if endpoint_type == "get_tfa_message_templates" and responses[0] == 200: - response_content = get_get_tfa_message_templates_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_tfa_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/integration/test_tfa_get_path_query.py b/tests/sms/integration/test_tfa_get_path_query.py deleted file mode 100644 index 33915dd..0000000 --- a/tests/sms/integration/test_tfa_get_path_query.py +++ /dev/null @@ -1,119 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)( - expected_path_parameters["appId"], expected_query_parameters - ) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_tfa_get_path_query_cases.py b/tests/sms/integration/test_tfa_get_path_query_cases.py deleted file mode 100644 index e23a6fb..0000000 --- a/tests/sms/integration/test_tfa_get_path_query_cases.py +++ /dev/null @@ -1,61 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_get_headers -from tests.sms.conftest import ( - get_get_tfa_verification_status_response, - get_tfa_request_error_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "get_tfa_verification_status": { - "endpoint": "/2fa/2/applications/1234567890/verifications", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": {"appId": 1234567890}, - "expected_query_parameters": {"msisdn": "385717284759547"}, - "expected_json": None, - "request_parameters": None, - "method_name": "get_tfa_verification_status", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_get_tfa_verification_status_response], - [400, get_tfa_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_tfa_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/integration/test_tfa_get_template_path.py b/tests/sms/integration/test_tfa_get_template_path.py deleted file mode 100644 index 12b8d1a..0000000 --- a/tests/sms/integration/test_tfa_get_template_path.py +++ /dev/null @@ -1,120 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)( - expected_path_parameters["appId"], - expected_path_parameters["msgId"], - ) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_tfa_get_template_path_cases.py b/tests/sms/integration/test_tfa_get_template_path_cases.py deleted file mode 100644 index 91e9b11..0000000 --- a/tests/sms/integration/test_tfa_get_template_path_cases.py +++ /dev/null @@ -1,61 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_get_headers -from tests.sms.conftest import ( - get_get_tfa_message_template_response, - get_tfa_request_error_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "get_tfa_message_template": { - "endpoint": "/2fa/2/applications/1234567890/messages/1234567890", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": {"appId": 1234567890, "msgId": 1234567890}, - "expected_query_parameters": None, - "expected_json": None, - "request_parameters": None, - "method_name": "get_tfa_message_template", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_get_tfa_message_template_response], - [400, get_tfa_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_tfa_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/integration/test_tfa_resend_verify_pin_path.py b/tests/sms/integration/test_tfa_resend_verify_pin_path.py deleted file mode 100644 index 8f21149..0000000 --- a/tests/sms/integration/test_tfa_resend_verify_pin_path.py +++ /dev/null @@ -1,122 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - message_body_instance = request_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)( - expected_path_parameters["pinId"], - request_body, - ) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_tfa_resend_verify_pin_path_cases.py b/tests/sms/integration/test_tfa_resend_verify_pin_path_cases.py deleted file mode 100644 index 97a5387..0000000 --- a/tests/sms/integration/test_tfa_resend_verify_pin_path_cases.py +++ /dev/null @@ -1,97 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_post_headers -from tests.sms.conftest import ( - GenerateResendPINOverSMSBodyFactoryIntegration, - GenerateResendPINOverVoiceBodyFactoryIntegration, - GenerateVerifyPhoneNumberBodyFactoryIntegration, - get_resend_pin_over_sms_body, - get_resend_pin_over_sms_response, - get_resend_pin_over_voice_body, - get_resend_pin_over_voice_response, - get_tfa_request_error_response, - get_verify_phone_number_body, - get_verify_phone_number_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "resend_pin_over_sms": { - "endpoint": "/2fa/2/pin/1234567890/resend", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": {"pinId": 1234567890}, - "expected_query_parameters": None, - "expected_json": GenerateResendPINOverSMSBodyFactoryIntegration, - "request_parameters": get_resend_pin_over_sms_body(), - "method_name": "resend_pin_over_sms", - }, - "resend_pin_over_voice": { - "endpoint": "/2fa/2/pin/1234567890/resend/voice", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": {"pinId": 1234567890}, - "expected_query_parameters": None, - "expected_json": GenerateResendPINOverVoiceBodyFactoryIntegration, - "request_parameters": get_resend_pin_over_voice_body(), - "method_name": "resend_pin_over_voice", - }, - "verify_phone_number": { - "endpoint": "/2fa/2/pin/1234567890/verify", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": {"pinId": 1234567890}, - "expected_query_parameters": None, - "expected_json": GenerateVerifyPhoneNumberBodyFactoryIntegration, - "request_parameters": get_verify_phone_number_body(), - "method_name": "verify_phone_number", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_resend_pin_over_sms_response], - [200, get_resend_pin_over_voice_response], - [400, get_tfa_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "resend_pin_over_sms" and responses[0] == 200: - response_content = get_resend_pin_over_sms_response - elif endpoint_type == "resend_pin_over_voice" and responses[0] == 200: - response_content = get_resend_pin_over_voice_response - elif endpoint_type == "verify_phone_number" and responses[0] == 200: - response_content = get_verify_phone_number_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_tfa_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/integration/test_tfa_send_pin.py b/tests/sms/integration/test_tfa_send_pin.py deleted file mode 100644 index 5e36948..0000000 --- a/tests/sms/integration/test_tfa_send_pin.py +++ /dev/null @@ -1,119 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - message_body_instance = request_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)(request_query_parameters, request_body) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_tfa_send_pin_cases.py b/tests/sms/integration/test_tfa_send_pin_cases.py deleted file mode 100644 index 4ae61ea..0000000 --- a/tests/sms/integration/test_tfa_send_pin_cases.py +++ /dev/null @@ -1,82 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_post_headers -from tests.sms.conftest import ( - GenerateSendPINOverSMSBodyFactoryIntegration, - GenerateSendPINOverVoiceBodyFactoryIntegration, - get_send_pin_over_sms_body, - get_send_pin_over_sms_response, - get_send_pin_over_voice_body, - get_send_pin_over_voice_response, - get_tfa_request_error_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "send_pin_over_sms": { - "endpoint": "/2fa/2/pin", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": None, - "expected_query_parameters": None, - "expected_json": GenerateSendPINOverSMSBodyFactoryIntegration, - "request_parameters": get_send_pin_over_sms_body(), - "method_name": "send_pin_over_sms", - }, - "send_pin_over_voice": { - "endpoint": "/2fa/2/pin/voice", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": None, - "expected_query_parameters": None, - "expected_json": GenerateSendPINOverVoiceBodyFactoryIntegration, - "request_parameters": get_send_pin_over_voice_body(), - "method_name": "send_pin_over_voice", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_send_pin_over_sms_response], - [200, get_send_pin_over_voice_response], - [400, get_tfa_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "send_pin_over_sms" and responses[0] == 200: - response_content = get_send_pin_over_sms_response - elif endpoint_type == "send_pin_over_voice" and responses[0] == 200: - response_content = get_send_pin_over_voice_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_tfa_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/integration/test_tfa_update_template_path.py b/tests/sms/integration/test_tfa_update_template_path.py deleted file mode 100644 index cd5940b..0000000 --- a/tests/sms/integration/test_tfa_update_template_path.py +++ /dev/null @@ -1,123 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.sms.channel import SMSChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - message_body_instance = request_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - sms_channel = SMSChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - - return getattr(sms_channel, method_name)( - expected_path_parameters["appId"], - expected_path_parameters["msgId"], - request_body, - ) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__supported_status", -) -def test_sms_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - response_dict = SMSChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, " - "request_query_parameters, method_name", - prefix="case__unsupported_status", -) -def test_sms_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - request_query_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/sms/integration/test_tfa_update_template_path_cases.py b/tests/sms/integration/test_tfa_update_template_path_cases.py deleted file mode 100644 index 5c3f03c..0000000 --- a/tests/sms/integration/test_tfa_update_template_path_cases.py +++ /dev/null @@ -1,63 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_post_headers -from tests.sms.conftest import ( - GenerateUpdateTFAMessageTemplateBodyFactoryIntegration, - get_tfa_request_error_response, - get_update_tfa_message_template_body, - get_update_tfa_message_template_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "update_tfa_message_template": { - "endpoint": "/2fa/2/applications/1234567890/messages/1234567890", - "http_method": "PUT", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": {"appId": 1234567890, "msgId": 1234567890}, - "expected_query_parameters": None, - "expected_json": GenerateUpdateTFAMessageTemplateBodyFactoryIntegration, - "request_parameters": get_update_tfa_message_template_body(), - "method_name": "update_tfa_message_template", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_update_tfa_message_template_response], - [400, get_tfa_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_tfa_request_error_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["request_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/sms/models/test_create_tfa_application.py b/tests/sms/models/test_create_tfa_application.py deleted file mode 100644 index 2e8a003..0000000 --- a/tests/sms/models/test_create_tfa_application.py +++ /dev/null @@ -1,27 +0,0 @@ -import pytest -from pydantic import ValidationError - -from infobip_channels.sms.models.body.create_tfa_application import ( - CreateTFAApplicationBody, -) - - -@pytest.mark.parametrize("name", ["", {}]) -def test_when_name_is_none_or_empty__validation_error_is_raised(name): - with pytest.raises(ValidationError): - CreateTFAApplicationBody( - **{ - "name": name, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - CreateTFAApplicationBody( - **{ - "name": "some-application", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_create_tfa_message_template.py b/tests/sms/models/test_create_tfa_message_template.py deleted file mode 100644 index b90ae54..0000000 --- a/tests/sms/models/test_create_tfa_message_template.py +++ /dev/null @@ -1,108 +0,0 @@ -import pytest -from pydantic import ValidationError - -from infobip_channels.sms.models.body.create_tfa_message_template import ( - CreateTFAMessageTemplateBody, -) -from infobip_channels.sms.models.core.tfa_message_template import PINTypeEnum - - -@pytest.mark.parametrize("message_text", ["", {}]) -def test_when_message_text_is_empty__validation_error_is_raised(message_text): - with pytest.raises(ValidationError): - CreateTFAMessageTemplateBody( - **{ - "messageText": message_text, - "pinType": PINTypeEnum.NUMERIC, - "pinPlaceholder": "{{pin}}", - "regional": { - "indiaDlt": { - "principalEntityId": "some-id", - } - }, - } - ) - - -@pytest.mark.parametrize("pin_type", ["", {}, None]) -def test_when_pin_type_is_none_or_empty__validation_error_is_raised(pin_type): - with pytest.raises(ValidationError): - CreateTFAMessageTemplateBody( - **{ - "messageText": "some-message {{pin}}", - "pinType": pin_type, - "pinPlaceholder": "{{pin}}", - "regional": { - "indiaDlt": { - "principalEntityId": "some-id", - } - }, - } - ) - - -@pytest.mark.parametrize("principal_entity_id", ["", {}]) -def test_when_principal_entity_id_is_none_or_empty__validation_error_is_raised( - principal_entity_id, -): - with pytest.raises(ValidationError): - CreateTFAMessageTemplateBody( - **{ - "messageText": "some-message", - "pinType": PINTypeEnum.NUMERIC, - "pinPlaceholder": "{{pin}}", - "regional": { - "indiaDlt": { - "principalEntityId": principal_entity_id, - } - }, - } - ) - - -@pytest.mark.parametrize("pin_placeholder", ["", {}]) -def test_when_pin_placeholder_is_empty__validation_error_is_raised(pin_placeholder): - with pytest.raises(ValidationError): - CreateTFAMessageTemplateBody( - **{ - "messageText": "some-message", - "pinType": PINTypeEnum.NUMERIC, - "pinPlaceholder": pin_placeholder, - "regional": { - "indiaDlt": { - "principalEntityId": "some-id", - } - }, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - CreateTFAMessageTemplateBody( - **{ - "messageText": "some-text", - "pinType": PINTypeEnum.NUMERIC, - "pinPlaceholder": "{{pin}}", - "regional": { - "indiaDlt": { - "principalEntityId": "some-id", - } - }, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") - - -def test_when_input_data_is_valid_no_regional__validation_error_is_not_raised(): - try: - CreateTFAMessageTemplateBody( - **{ - "messageText": "some-text", - "pinType": PINTypeEnum.NUMERIC, - "pinPlaceholder": "{{pin}}", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_get_scheduled_messages.py b/tests/sms/models/test_get_scheduled_messages.py deleted file mode 100644 index f4a681d..0000000 --- a/tests/sms/models/test_get_scheduled_messages.py +++ /dev/null @@ -1,27 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.sms.models.query_parameters.get_scheduled_messages import ( - GetScheduledSMSMessagesQueryParameters, -) - - -@pytest.mark.parametrize("bulk_id", [{}, None]) -def test_when_bulk_id_is_invalid__validation_error_is_raised(bulk_id): - with pytest.raises(ValidationError): - GetScheduledSMSMessagesQueryParameters( - **{ - "bulk_id": bulk_id, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetScheduledSMSMessagesQueryParameters( - **{ - "bulk_id": "BulkId-xyz-123", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_get_scheduled_messages_status.py b/tests/sms/models/test_get_scheduled_messages_status.py deleted file mode 100644 index 7165679..0000000 --- a/tests/sms/models/test_get_scheduled_messages_status.py +++ /dev/null @@ -1,27 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.sms.models.query_parameters.get_scheduled_messages_status import ( - GetScheduledSMSMessagesStatusQueryParameters, -) - - -@pytest.mark.parametrize("bulk_id", [{}, None]) -def test_when_bulk_id_is_invalid__validation_error_is_raised(bulk_id): - with pytest.raises(ValidationError): - GetScheduledSMSMessagesStatusQueryParameters( - **{ - "bulk_id": bulk_id, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetScheduledSMSMessagesStatusQueryParameters( - **{ - "bulk_id": "BulkId-xyz-123", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_inbound_messages.py b/tests/sms/models/test_inbound_messages.py deleted file mode 100644 index e5c9ac6..0000000 --- a/tests/sms/models/test_inbound_messages.py +++ /dev/null @@ -1,27 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.sms.models.query_parameters.get_inbound_messages import ( - GetInboundSMSMessagesQueryParameters, -) - - -@pytest.mark.parametrize("limit", ["", {}, -2, 1001]) -def test_when_limit_is_invalid__validation_error_is_raised(limit): - with pytest.raises(ValidationError): - GetInboundSMSMessagesQueryParameters( - **{ - "limit": limit, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetInboundSMSMessagesQueryParameters( - **{ - "limit": 2, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_outbound_delivery_reports.py b/tests/sms/models/test_outbound_delivery_reports.py deleted file mode 100644 index 5ba326d..0000000 --- a/tests/sms/models/test_outbound_delivery_reports.py +++ /dev/null @@ -1,52 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.sms.models.query_parameters.get_outbound_delivery_reports import ( - GetOutboundSMSDeliveryReportsQueryParameters, -) - - -def test_when_bulk_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetOutboundSMSDeliveryReportsQueryParameters( - **{ - "bulkId": {}, - "messageId": "MESSAGE-ID-123-xyz", - "limit": 2, - } - ) - - -def test_when_message_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetOutboundSMSDeliveryReportsQueryParameters( - **{ - "bulkId": "BULK-ID-123-xyz", - "messageId": {}, - "limit": 2, - } - ) - - -def test_when_limit_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetOutboundSMSDeliveryReportsQueryParameters( - **{ - "bulkId": "BULK-ID-123-xyz", - "messageId": "MESSAGE-ID-123-xyz", - "limit": {}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetOutboundSMSDeliveryReportsQueryParameters( - **{ - "bulkId": "BULK-ID-123-xyz", - "messageId": "MESSAGE-ID-123-xyz", - "limit": 2, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_outbound_logs.py b/tests/sms/models/test_outbound_logs.py deleted file mode 100644 index fe6e34d..0000000 --- a/tests/sms/models/test_outbound_logs.py +++ /dev/null @@ -1,123 +0,0 @@ -from datetime import date, datetime - -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.sms.models.query_parameters.get_outbound_logs import ( - GetOutboundSMSLogsQueryParameters, -) - - -def test_when_from_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetOutboundSMSLogsQueryParameters( - **{ - "from": {}, - } - ) - - -def test_when_to_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetOutboundSMSLogsQueryParameters( - **{ - "to": {}, - } - ) - - -def test_when_bulk_id_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetOutboundSMSLogsQueryParameters( - **{ - "bulkId": {}, - } - ) - - -@pytest.mark.parametrize("message_id", ["", {}]) -def test_when_message_id_invalid__validation_error_is_raised(message_id): - with pytest.raises(ValidationError): - GetOutboundSMSLogsQueryParameters( - **{ - "messageId": message_id, - } - ) - - -@pytest.mark.parametrize("general_status", ["", {}]) -def test_when_general_status_invalid__validation_error_is_raised(general_status): - with pytest.raises(ValidationError): - GetOutboundSMSLogsQueryParameters( - **{ - "generalStatus": general_status, - } - ) - - -@pytest.mark.parametrize("sent_since", [{}, "Test", "22-03-2022", date.today()]) -def test_when_sent_since_invalid__validation_error_is_raised(sent_since): - with pytest.raises(ValidationError): - GetOutboundSMSLogsQueryParameters( - **{ - "sentSince": sent_since, - } - ) - - -@pytest.mark.parametrize("sent_until", [{}, "Test", "22-03-2022", date.today()]) -def test_when_sent_until_invalid__validation_error_is_raised(sent_until): - with pytest.raises(ValidationError): - GetOutboundSMSLogsQueryParameters( - **{ - "sentUntil": sent_until, - } - ) - - -@pytest.mark.parametrize("limit", [{}, -1, 1001]) -def test_when_limit_invalid__validation_error_is_raised(limit): - with pytest.raises(ValidationError): - GetOutboundSMSLogsQueryParameters( - **{ - "limit": limit, - } - ) - - -def test_when_mcc_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetOutboundSMSLogsQueryParameters( - **{ - "mcc": {}, - } - ) - - -def test_when_mnc_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - GetOutboundSMSLogsQueryParameters( - **{ - "mnc": {}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GetOutboundSMSLogsQueryParameters( - **{ - "from": "41793026999", - "to": "41793026727", - "bulkId": ["BULK-ID-123-xyz"], - "messageId": ["MESSAGE-ID-123-xyz"], - "generalStatus": "PENDING", - "sentSince": datetime.now(), - "sentUntil": datetime.now(), - "limit": 2, - "mcc": "22", - "mnc": "11", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_preview.py b/tests/sms/models/test_preview.py deleted file mode 100644 index 6e43e7d..0000000 --- a/tests/sms/models/test_preview.py +++ /dev/null @@ -1,43 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from tests.conftest import get_random_string -from tests.sms.conftest import GeneratePreviewSMSMessageBodyFactory - - -@pytest.mark.parametrize("language_code", [{}, get_random_string(4)]) -def test_when_language_code_is_invalid__validation_error_is_raised(language_code): - with pytest.raises(ValidationError): - GeneratePreviewSMSMessageBodyFactory.build( - **{ - "languageCode": language_code, - "text": "Let's see how many characters remain unused in " - "this message", - "transliteration": "TURKISH", - } - ) - - -@pytest.mark.parametrize("text", [None, {}]) -def test_when_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - GeneratePreviewSMSMessageBodyFactory.build( - **{ - "languageCode": "AUTODETECT", - "text": text, - "transliteration": "TURKISH", - } - ) - - -@pytest.mark.parametrize("transliteration", [{}, "ABC"]) -def test_when_transliteration_is_invalid__validation_error_is_raised(transliteration): - with pytest.raises(ValidationError): - GeneratePreviewSMSMessageBodyFactory.build( - **{ - "languageCode": "AUTODETECT", - "text": "Let's see how many characters remain unused in " - "this message", - "transliteration": transliteration, - } - ) diff --git a/tests/sms/models/test_reschedule_sms_messages.py b/tests/sms/models/test_reschedule_sms_messages.py deleted file mode 100644 index ab10524..0000000 --- a/tests/sms/models/test_reschedule_sms_messages.py +++ /dev/null @@ -1,60 +0,0 @@ -from datetime import date, datetime, timedelta, timezone - -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.sms.models.body.reschedule_sms_messages import ( - RescheduleSMSMessagesMessageBody, -) -from infobip_channels.sms.models.query_parameters.reschedule_messages import ( - RescheduleSMSMessagesQueryParameters, -) - - -@pytest.mark.parametrize("bulk_id", [{}, None]) -def test_when_bulk_id_is_invalid__validation_error_is_raised(bulk_id): - with pytest.raises(ValidationError): - RescheduleSMSMessagesQueryParameters( - **{ - "bulk_id": bulk_id, - } - ) - - -def test_when_input_data_is_valid_query__validation_error_is_not_raised(): - try: - RescheduleSMSMessagesQueryParameters( - **{ - "bulk_id": "BulkId-xyz-123", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") - - -@pytest.mark.parametrize( - "send_at", - [{}, "Test", "22-03-2022", date.today(), datetime.now() + timedelta(days=181)], -) -def test_when_send_at_is_invalid__validation_error_is_raised(send_at): - with pytest.raises(ValidationError): - RescheduleSMSMessagesMessageBody( - **{ - "sendAt": send_at, - } - ) - - -@pytest.mark.parametrize( - "send_at", - [datetime.now(timezone.utc) + timedelta(days=1), "2022-07-20T16:00:00.000+0000"], -) -def test_when_input_data_is_valid_body__validation_error_is_not_raised(send_at): - try: - RescheduleSMSMessagesMessageBody( - **{ - "sendAt": send_at, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_send.py b/tests/sms/models/test_send.py deleted file mode 100644 index b7cd58d..0000000 --- a/tests/sms/models/test_send.py +++ /dev/null @@ -1,295 +0,0 @@ -from datetime import datetime, timedelta, timezone - -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.sms.models.body.send_message import SMSMessageBody -from tests.conftest import get_random_string -from tests.sms.conftest import GenerateSMSMessageBodyFactory - - -@pytest.mark.parametrize("messages", ["", None, {}]) -def test_when_messages_is_invalid__validation_error_is_raised(messages): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build(**{"messages": [messages]}) - - -@pytest.mark.parametrize("destinations", ["", None, {}]) -def test_when_destinations_is_invalid__validation_error_is_raised(destinations): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "destinations": [destinations], - } - ] - } - ) - - -@pytest.mark.parametrize("destinations_to", [None, {}, get_random_string(51)]) -def test_when_destinations_to_is_invalid__validation_error_is_raised(destinations_to): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "destinations": [{"to": destinations_to}], - } - ] - } - ) - - -@pytest.mark.parametrize("callback_data", [{}, get_random_string(4001)]) -def test_when_callback_data_to_is_invalid__validation_error_is_raised(callback_data): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "callbackData": callback_data, - "destinations": [{"to": "41793026727"}], - } - ] - } - ) - - -@pytest.mark.parametrize( - "delivery_time_window", - [ - {}, - {"from": {"hour": 12, "minute": 0}, "to": {"hour": 14, "minute": 0}}, - {"from": {"hour": 12, "minute": 0}, "days": ["FRIDAY"]}, - {"to": {"hour": 12, "minute": 0}, "days": ["FRIDAY"]}, - { - "from": {"hour": 12, "minute": 0}, - "to": {"hour": 12, "minute": 40}, - "days": ["FRIDAY"], - }, - ], -) -def test_when_delivery_time_window_is_invalid__validation_error_is_raised( - delivery_time_window, -): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "deliveryTimeWindow": delivery_time_window, - "destinations": [{"to": "41793026727"}], - } - ] - } - ) - - -@pytest.mark.parametrize("language_code", ["", {}, "Test"]) -def test_when_language_code_is_invalid__validation_error_is_raised(language_code): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - {"destinations": [{"to": "41793026727"}], "language": language_code} - ] - } - ) - - -@pytest.mark.parametrize("flash", ["", {}, "true"]) -def test_when_flash_is_invalid__validation_error_is_raised(flash): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{"messages": [{"destinations": [{"to": "41793026727"}], "flash": flash}]} - ) - - -@pytest.mark.parametrize("notify_content_type", ["", {}, "Test"]) -def test_when_notify_content_type_is_invalid__validation_error_is_raised( - notify_content_type, -): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "destinations": [{"to": "41793026727"}], - "notifyContentType": notify_content_type, - } - ] - } - ) - - -@pytest.mark.parametrize("notify_url", [{}, "myserver.com", "www.myserver.com"]) -def test_when_notify_url_is_invalid__validation_error_is_raised(notify_url): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "destinations": [{"to": "41793026727"}], - "notifyUrl": notify_url, - } - ] - } - ) - - -@pytest.mark.parametrize( - "send_at", - [ - {}, - "Test", - "22-03-2022", - datetime.now(), - datetime.now(timezone.utc) + timedelta(days=181), - ], -) -def test_when_send_at_is_invalid__validation_error_is_raised(send_at): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - {"destinations": [{"to": "41793026727"}], "sendAt": send_at} - ] - } - ) - - -@pytest.mark.parametrize("transliteration", ["", {}, "Test"]) -def test_when_transliteration_is_invalid__validation_error_is_raised(transliteration): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "destinations": [{"to": "41793026727"}], - "transliteration": transliteration, - } - ] - } - ) - - -@pytest.mark.parametrize("validity_period", ["", {}, "Test", 2881]) -def test_when_validity_period_is_invalid__validation_error_is_raised(validity_period): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "destinations": [{"to": "41793026727"}], - "validityPeriod": validity_period, - } - ] - } - ) - - -@pytest.mark.parametrize("principal_entity_id", ["", {}]) -def test_when_principal_entity_id_is_invalid__validation_error_is_raised( - principal_entity_id, -): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "destinations": [{"to": "41793026727"}], - "regional": { - "indiaDlt": {"principalEntityId": principal_entity_id} - }, - } - ] - } - ) - - -@pytest.mark.parametrize("amount", ["", None, {}, "test"]) -def test_when_amount_is_invalid__validation_error_is_raised(amount): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "destinations": [{"to": "41793026727"}], - } - ], - "sendingSpeedLimit": {"amount": amount, "timeUnit": "MINUTE"}, - } - ) - - -@pytest.mark.parametrize("time_unit", ["", {}, "test"]) -def test_when_time_unit_is_invalid__validation_error_is_raised(time_unit): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "destinations": [{"to": "41793026727"}], - } - ], - "sendingSpeedLimit": {"amount": 22, "timeUnit": time_unit}, - } - ) - - -@pytest.mark.parametrize("track", ["", {}, "test"]) -def test_when_track_is_invalid__validation_error_is_raised(track): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "destinations": [{"to": "41793026727"}], - } - ], - "tracking": { - "track": track, - }, - } - ) - - -@pytest.mark.parametrize("tracking_type", ["", {}, "test"]) -def test_when_tracking_type_is_invalid__validation_error_is_raised(tracking_type): - with pytest.raises(ValidationError): - GenerateSMSMessageBodyFactory.build( - **{ - "messages": [ - { - "destinations": [{"to": "41793026727"}], - } - ], - "tracking": { - "type": tracking_type, - }, - } - ) - - -@pytest.mark.parametrize( - "send_at", - [datetime.now(timezone.utc) + timedelta(days=1), "2022-07-20T16:00:00.000+0000"], -) -def test_when_input_data_is_valid__validation_error_is_not_raised(send_at): - try: - SMSMessageBody( - **{ - "messages": [ - { - "destinations": [{"to": "41793026727"}], - "from": "InfoSMS", - "text": "This is a sample message", - "sendAt": datetime.now(timezone.utc) + timedelta(days=1), - } - ] - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_send_binary.py b/tests/sms/models/test_send_binary.py deleted file mode 100644 index c9f2332..0000000 --- a/tests/sms/models/test_send_binary.py +++ /dev/null @@ -1,337 +0,0 @@ -from datetime import date, datetime, timedelta, timezone - -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.sms.models.body.send_binary_message import BinarySMSMessageBody -from tests.conftest import get_random_string -from tests.sms.conftest import GenerateBinarySMSMessageBodyFactory - - -@pytest.mark.parametrize("messages", ["", None, {}]) -def test_when_messages_is_invalid__validation_error_is_raised(messages): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build(**{"messages": [messages]}) - - -@pytest.mark.parametrize("destinations", ["", None, {}]) -def test_when_destinations_is_invalid__validation_error_is_raised(destinations): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "destinations": [destinations], - } - ] - } - ) - - -@pytest.mark.parametrize("destinations_to", [None, {}, get_random_string(51)]) -def test_when_destinations_to_is_invalid__validation_error_is_raised(destinations_to): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "destinations": [ - {"to": destinations_to}, - ], - } - ] - } - ) - - -@pytest.mark.parametrize("callback_data", [{}, get_random_string(4001)]) -def test_when_callback_data_is_invalid__validation_error_is_raised(callback_data): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "callbackData": callback_data, - "destinations": [{"to": "41793026727"}], - } - ] - } - ) - - -@pytest.mark.parametrize( - "delivery_time_window", - [ - {}, - {"from": {"hour": 12, "minute": 0}, "to": {"hour": 14, "minute": 0}}, - {"from": {"hour": 12, "minute": 0}, "days": ["FRIDAY"]}, - {"to": {"hour": 12, "minute": 0}, "days": ["FRIDAY"]}, - { - "from": {"hour": 12, "minute": 0}, - "to": {"hour": 12, "minute": 40}, - "days": ["FRIDAY"], - }, - ], -) -def test_when_delivery_time_window_is_invalid__validation_error_is_raised( - delivery_time_window, -): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "deliveryTimeWindow": delivery_time_window, - "destinations": [{"to": "41793026727"}], - } - ] - } - ) - - -@pytest.mark.parametrize("flash", ["", {}, "true"]) -def test_when_flash_is_invalid__validation_error_is_raised(flash): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "destinations": [{"to": "41793026727"}], - "flash": flash, - } - ] - } - ) - - -@pytest.mark.parametrize("notify_content_type", ["", {}, "Test"]) -def test_when_notify_content_type_is_invalid__validation_error_is_raised( - notify_content_type, -): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "destinations": [{"to": "41793026727"}], - "notifyContentType": notify_content_type, - } - ] - } - ) - - -@pytest.mark.parametrize("notify_url", [{}, "myserver.com", "www.myserver.com"]) -def test_when_notify_url_is_invalid__validation_error_is_raised(notify_url): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "destinations": [{"to": "41793026727"}], - "notifyUrl": notify_url, - } - ] - } - ) - - -@pytest.mark.parametrize( - "send_at", - [{}, "Test", "22-03-2022", date.today(), datetime.now() + timedelta(days=181)], -) -def test_when_send_at_is_invalid__validation_error_is_raised(send_at): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "destinations": [{"to": "41793026727"}], - "sendAt": send_at, - } - ] - } - ) - - -@pytest.mark.parametrize("validity_period", ["", {}, "Test", 2881]) -def test_when_validity_period_is_invalid__validation_error_is_raised(validity_period): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "destinations": [{"to": "41793026727"}], - "validityPeriod": validity_period, - } - ] - } - ) - - -@pytest.mark.parametrize("principal_entity_id", ["", {}]) -def test_when_principal_entity_id_is_invalid__validation_error_is_raised( - principal_entity_id, -): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "destinations": [{"to": "41793026727"}], - "regional": { - "indiaDlt": {"principalEntityId": principal_entity_id} - }, - } - ] - } - ) - - -@pytest.mark.parametrize("amount", ["", None, {}, "test"]) -def test_when_amount_is_invalid__validation_error_is_raised(amount): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "destinations": [{"to": "41793026727"}], - } - ], - "sendingSpeedLimit": {"amount": amount, "timeUnit": "MINUTE"}, - } - ) - - -@pytest.mark.parametrize("time_unit", ["", {}, "test"]) -def test_when_time_unit_is_invalid__validation_error_is_raised(time_unit): - with pytest.raises(ValidationError): - GenerateBinarySMSMessageBodyFactory.build( - **{ - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "destinations": [ - {"to": "41793026727"}, - ], - } - ], - "sendingSpeedLimit": {"amount": 22, "timeUnit": time_unit}, - } - ) - - -@pytest.mark.parametrize( - "send_at", - [datetime.now(timezone.utc) + timedelta(days=1), "2022-07-20T16:00:00.000+0000"], -) -def test_when_input_data_is_valid__validation_error_is_not_raised(send_at): - try: - BinarySMSMessageBody( - **{ - "bulkId": "BULK-ID-123-xyz", - "messages": [ - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "54 65 73 74 20 6d 65 73 73 61 67 65 2e", - }, - "callbackData": "DLR callback data", - "destinations": [ - {"messageId": "MESSAGE-ID-123-xyz", "to": "41793026727"}, - {"to": "41793026834"}, - ], - "from": "InfoSMS", - "intermediateReport": True, - "notifyContentType": "application/json", - "notifyUrl": "https://www.example.com/sms/advanced", - "validityPeriod": 720, - }, - { - "binary": { - "dataCoding": 0, - "esmClass": 0, - "hex": "41 20 6C 6F 6E 67 20 74 20 45 6D 70 69 72 65 2E", - }, - "deliveryTimeWindow": { - "days": [ - "MONDAY", - "TUESDAY", - "WEDNESDAY", - "THURSDAY", - "FRIDAY", - "SATURDAY", - "SUNDAY", - ], - "from": {"hour": 6, "minute": 0}, - "to": {"hour": 15, "minute": 30}, - }, - "destinations": [{"to": "41793026700"}], - "from": "41793026700", - "sendAt": send_at, - }, - ], - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_send_pin.py b/tests/sms/models/test_send_pin.py deleted file mode 100644 index 9d93fd2..0000000 --- a/tests/sms/models/test_send_pin.py +++ /dev/null @@ -1,61 +0,0 @@ -import pytest -from pydantic import ValidationError - -from infobip_channels.sms.models.body.send_pin_over_sms import SendPINOverSMSBody - - -@pytest.mark.parametrize("app_id", ["", {}]) -def test_when_app_id_is_none_or_empty__validation_error_is_raised(app_id): - with pytest.raises(ValidationError): - SendPINOverSMSBody( - **{ - "applicationId": app_id, - "messageId": "7654321", - "from": "Sender 1", - "to": "41793026727", - "placeholders": {"firstName": "John"}, - } - ) - - -@pytest.mark.parametrize("message_id", ["", {}]) -def test_when_message_id_is_none_or_empty__validation_error_is_raised(message_id): - with pytest.raises(ValidationError): - SendPINOverSMSBody( - **{ - "applicationId": "1234567", - "messageId": message_id, - "from": "Sender 1", - "to": "41793026727", - "placeholders": {"firstName": "John"}, - } - ) - - -@pytest.mark.parametrize("to", ["", {}]) -def test_when_to_is_none_or_empty__validation_error_is_raised(to): - with pytest.raises(ValidationError): - SendPINOverSMSBody( - **{ - "applicationId": "1234567", - "messageId": "7654321", - "from": "Sender 1", - "to": to, - "placeholders": {"firstName": "John"}, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - SendPINOverSMSBody( - **{ - "applicationId": "1234567", - "messageId": "7654321", - "from": "Sender 1", - "to": "41793026727", - "placeholders": {"firstName": "John"}, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_send_query.py b/tests/sms/models/test_send_query.py deleted file mode 100644 index 21d58e8..0000000 --- a/tests/sms/models/test_send_query.py +++ /dev/null @@ -1,293 +0,0 @@ -from datetime import date, datetime, timedelta, timezone - -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.sms.models.query_parameters.send_message import ( - SendSMSMessageQueryParameters, -) - - -def test_when_username_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": {}, - "password": "Pass123", - "to": ["41793026727"], - } - ) - - -def test_when_password_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": {}, - "to": ["41793026727"], - } - ) - - -def test_when_bulk_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "bulkId": {}, - } - ) - - -def test_when_from_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "from": {}, - } - ) - - -def test_when_to_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": {}, - } - ) - - -def test_when_text_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "text": {}, - } - ) - - -def test_when_flash_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "flash": {}, - } - ) - - -@pytest.mark.parametrize("transliteration", [{}, "ABC"]) -def test_when_transliteration_is_invalid__validation_error_is_raised(transliteration): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "transliteration": transliteration, - } - ) - - -def test_when_language_code_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "languageCode": {}, - } - ) - - -@pytest.mark.parametrize("intermediate_report", [{}, "true"]) -def test_when_intermediate_report_is_invalid__validation_error_is_raised( - intermediate_report, -): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "intermediateReport": intermediate_report, - } - ) - - -@pytest.mark.parametrize("notify_url", [{}, "ABC", "www.test.com"]) -def test_when_notify_url_is_invalid__validation_error_is_raised(notify_url): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "notifyUrl": notify_url, - } - ) - - -@pytest.mark.parametrize("notify_content_type", [{}, "ABC"]) -def test_when_notify_content_type_is_invalid__validation_error_is_raised( - notify_content_type, -): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "notifyContentType": notify_content_type, - } - ) - - -def test_when_callback_data_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "callbackData": {}, - } - ) - - -@pytest.mark.parametrize("validity_period", [{}, -1, 2881]) -def test_when_validity_period_is_invalid__validation_error_is_raised(validity_period): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "validityPeriod": validity_period, - } - ) - - -@pytest.mark.parametrize( - "send_at", - [{}, "Test", "22-03-2022", date.today(), datetime.now() + timedelta(days=181)], -) -def test_when_send_at_is_invalid__validation_error_is_raised(send_at): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "sendAt": send_at, - } - ) - - -@pytest.mark.parametrize("track", [{}, "ABC"]) -def test_when_track_is_invalid__validation_error_is_raised(track): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "track": track, - } - ) - - -def test_when_process_key_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "processKey": {}, - } - ) - - -def test_when_tracking_type_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "trackingType": {}, - } - ) - - -def test_when_india_dlt_content_template_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "indiaDltContentTemplateId": {}, - } - ) - - -def test_when_india_dlt_principal_entity_id_is_invalid__validation_error_is_raised(): - with pytest.raises(ValidationError): - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "to": ["41793026727"], - "indiaDltPrincipalEntityId": {}, - } - ) - - -@pytest.mark.parametrize( - "send_at", - [datetime.now(timezone.utc) + timedelta(days=1), "2022-07-20T16:00:00.000+0000"], -) -def test_when_input_data_is_valid__validation_error_is_not_raised(send_at): - try: - SendSMSMessageQueryParameters( - **{ - "username": "Test User", - "password": "Pass123", - "bulkId": "1478260834465349756", - "from": "Test message", - "to": ["41793026727"], - "text": "Test text", - "flash": True, - "transliteration": "TURKISH", - "languageCode": "TR", - "intermediateReport": True, - "notifyUrl": "https://www.example.com", - "notifyContentType": "application/json", - "callbackData": "callbackData", - "validityPeriod": 720, - "sendAt": send_at, - "track": "URL", - "processKey": "processKey", - "trackingType": "ONE_TIME_PIN", - "indiaDltContentTemplateId": "indiaDltContentTemplateId", - "indiaDltPrincipalEntityId": "indiaDltPrincipalEntityId", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_update_scheduled_messages_status.py b/tests/sms/models/test_update_scheduled_messages_status.py deleted file mode 100644 index c055887..0000000 --- a/tests/sms/models/test_update_scheduled_messages_status.py +++ /dev/null @@ -1,51 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.sms.models.body.update_scheduled_messages_status import ( - UpdateScheduledSMSMessagesMessageBody, -) -from infobip_channels.sms.models.query_parameters.update_scheduled_messages_status import ( - UpdateScheduledSMSMessagesQueryParameters, -) - - -@pytest.mark.parametrize("bulk_id", [{}, None]) -def test_when_bulk_id_is_invalid__validation_error_is_raised(bulk_id): - with pytest.raises(ValidationError): - UpdateScheduledSMSMessagesQueryParameters( - **{ - "bulk_id": bulk_id, - } - ) - - -def test_when_input_data_is_valid_query__validation_error_is_not_raised(): - try: - UpdateScheduledSMSMessagesQueryParameters( - **{ - "bulk_id": "BulkId-xyz-123", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") - - -@pytest.mark.parametrize("status", [{}, None, "TEST"]) -def test_when_status_is_invalid__validation_error_is_raised(status): - with pytest.raises(ValidationError): - UpdateScheduledSMSMessagesMessageBody( - **{ - "status": status, - } - ) - - -def test_when_input_data_is_valid_body__validation_error_is_not_raised(): - try: - UpdateScheduledSMSMessagesMessageBody( - **{ - "status": "PROCESSING", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_update_tfa_application.py b/tests/sms/models/test_update_tfa_application.py deleted file mode 100644 index 66189c4..0000000 --- a/tests/sms/models/test_update_tfa_application.py +++ /dev/null @@ -1,27 +0,0 @@ -import pytest -from pydantic import ValidationError - -from infobip_channels.sms.models.body.update_tfa_application import ( - UpdateTFAApplicationBody, -) - - -@pytest.mark.parametrize("name", ["", {}]) -def test_when_name_is_empty__validation_error_is_raised(name): - with pytest.raises(ValidationError): - UpdateTFAApplicationBody( - **{ - "name": name, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - UpdateTFAApplicationBody( - **{ - "messageText": "some-text", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/sms/models/test_verify_phone_number.py b/tests/sms/models/test_verify_phone_number.py deleted file mode 100644 index f76a4a4..0000000 --- a/tests/sms/models/test_verify_phone_number.py +++ /dev/null @@ -1,25 +0,0 @@ -import pytest -from pydantic import ValidationError - -from infobip_channels.sms.models.body.verify_phone_number import VerifyPhoneNumberBody - - -@pytest.mark.parametrize("pin", ["", {}]) -def test_when_pin_is_empty__validation_error_is_raised(pin): - with pytest.raises(ValidationError): - VerifyPhoneNumberBody( - **{ - "pin": pin, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - VerifyPhoneNumberBody( - **{ - "pin": "1234", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/test_core.py b/tests/test_core.py deleted file mode 100644 index ad42c2b..0000000 --- a/tests/test_core.py +++ /dev/null @@ -1,70 +0,0 @@ -import os -from unittest.mock import patch - -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.core.models import Authentication -from tests.conftest import UserInfo - - -@pytest.mark.parametrize("base_url", [None, "", "ftp://123.api.infobip.com", {}]) -def test_when_base_url_is_invalid__validation_error_is_raised(base_url): - with pytest.raises(ValidationError): - Authentication(base_url=base_url, api_key="api_key") - - -@pytest.mark.parametrize("api_key", [None, "", {}]) -def test_when_api_key_is_invalid__validation_error_is_raised(api_key): - with pytest.raises(ValidationError): - Authentication(base_url="https://123.api.infobip.com", api_key=api_key) - - -@pytest.mark.parametrize( - "base_url", - [ - "http://123.api.infobip.com", - "https://123.api.infobip.com", - "123.api.infobip.com", - ], -) -def test_base_url_in_different_forms__validation_passes(base_url): - try: - Authentication(base_url=base_url, api_key="api_key") - except ValidationError: - pytest.fail("Unexpected ValidationError raised") - - -@patch("urllib3.filepost.choose_boundary", return_value="ourBoundary12345") -def test_when_model_inherits_multipart_mixin__it_can_export_multipart_data(boundary): - with open("profile_img.jpg", "wb") as f: - f.write(b"X") - f.flush() - profile_img = open(f.name, "rb") - os.remove("profile_img.jpg") - - info = UserInfo( - **{ - "last_name": "Doe", - "address": {"street": "Some st. 1", "city": "Split", "zip_code": 21000}, - "profile_image": profile_img, - } - ) - body, content_type = info.to_multipart() - - assert body == ( - b"--ourBoundary12345\r\n" - b'Content-Disposition: form-data; name="lastName"\r\n' - b"Content-Type: text/plain\r\n\r\n" - b"Doe\r\n" - b"--ourBoundary12345\r\n" - b'Content-Disposition: form-data; name="address"\r\n' - b"Content-Type: application/json\r\n\r\n" - b'{"street": "Some st. 1", "city": "Split", "zipCode": 21000}\r\n' - b"--ourBoundary12345\r\n" - b"Content-Disposition: form-data; " - b'name="profileImage"; filename="profile_img.jpg"\r\n' - b"Content-Type: image/jpeg\r\n\r\nX\r\n" - b"--ourBoundary12345--\r\n" - ) - assert content_type == "multipart/form-data; boundary=ourBoundary12345" diff --git a/tests/test_sms.py b/tests/test_sms.py new file mode 100644 index 0000000..d1f538a --- /dev/null +++ b/tests/test_sms.py @@ -0,0 +1,43 @@ +# Test for validations + +import unittest + +from client import InfobipAPIClient +from http_server_mock import HttpServerMock + + +class TestSMS(unittest.IsolatedAsyncioTestCase): + client = InfobipAPIClient() + + async def test_preview_message(self): + expected_response = { + "bulkId": "2034072219640523072", + "messages": [ + { + "messageId": "2250be2d4219-3af1-78856-aabe-1362af1edfd2", + "status": { + "description": "Message sent to next instance", + "groupId": 1, + "groupName": "PENDING", + "id": 26, + "name": "MESSAGE_ACCEPTED" + }, + "to": "41793026727" + } + ] + } + + # Start the mock server + mock_server = HttpServerMock("localhost", 5000) + + with mock_server.run(): + client = InfobipAPIClient(base_url="http://localhost:5000") + + # Call the endpoint and await returned Coroutine + response = await self.client.SMS.preview_message("test") + + # Do something with the response. + print(response) + + self.assertEquals(response.status_code, 200) + self.assertEquals(response.json(), expected_response) diff --git a/tests/webrtc/conftest.py b/tests/webrtc/conftest.py deleted file mode 100644 index 81c9243..0000000 --- a/tests/webrtc/conftest.py +++ /dev/null @@ -1,137 +0,0 @@ -from pydantic_factories import ModelFactory - -from infobip_channels.web_rtc.models.body.generate_token import GenerateTokenBody -from infobip_channels.web_rtc.models.body.save_application import SaveApplicationBody -from infobip_channels.web_rtc.models.body.update_application import ( - UpdateApplicationBody, -) - - -class GenerateTokenFactory(ModelFactory): - __model__ = GenerateTokenBody - - -class SaveApplicationFactory(ModelFactory): - __model__ = SaveApplicationBody - - -class UpdateApplicationFactory(ModelFactory): - __model__ = UpdateApplicationBody - - -def get_expected_path_parameters(): - return {"id": "894c822b-d7ba-439c-a761-141f591cace7"} - - -def get_webrtc_body_request(): - return { - "name": "Application Name", - "description": "Application Description", - "android": {"fcmServerKey": "test_key"}, - "appToApp": "true", - "appToConversations": "false", - "appToPhone": "false", - } - - -def get_webrtc_body_generate_token(): - return { - "identity": "Alice", - "applicationId": "2277594c-76ea-4b8e-a299-e2b6db41b9dc", - "displayName": "Alice in Wonderland", - "capabilities": {"recording": "ALWAYS"}, - "timeToLive": 43200, - } - - -def get_webrtc_generate_token_response(): - return { - "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZGVk", - "expirationTime": "2020-01-17T19:50:38.488589Z", - } - - -def get_webrtc_application_response(): - return { - "id": "894c822b-d7ba-439c-a761-141f591cace7", - "name": "Application Name", - "description": "Application Description", - "ios": { - "apnsCertificateFileName": "IOS_APNS_certificate.p", - "apnsCertificatePassword": "IOS_APNS_certificate_password", - }, - "android": {"fcmServerKey": "test_key"}, - "appToApp": True, - "appToConversations": True, - "appToPhone": True, - } - - -def get_webrtc_application_request(): - return { - "id": "894c822b-d7ba-439c-a761-141f591cace7", - "name": "Application Name", - "description": "Application Description", - "ios": { - "apnsCertificateFileName": "IOS_APNS_certificate.p", - "apnsCertificatePassword": "IOS_APNS_certificate_password", - }, - "android": {"fcmServerKey": "test_key"}, - "appToApp": "true", - "appToConversations": "true", - "appToPhone": "true", - } - - -def get_webrtc_delete_request(): - return {} - - -def get_webrtc_request_error_response(): - return { - "requestError": { - "serviceException": { - "messageId": "BAD_REQUEST", - "text": "Bad request", - "validationErrors": { - "request.message.content.media.file.url": [ - "is not a valid url", - ] - }, - } - } - } - - -def get_webrtc_get_applications_response(): - return [ - { - "id": "894c822b-d7ba-439c-a761-141f591cace7", - "name": "Application Name 1", - "description": "Application Description", - "ios": { - "apnsCertificateFileName": "IOS_APNS_certificate.p", - "apnsCertificatePassword": "IOS_APNS_certificate_password", - }, - "appToApp": True, - "appToConversations": False, - "appToPhone": True, - }, - { - "id": "988c411a-a2db-227a-c563-245a159dcbe2", - "name": "Application Name 2", - "description": "Application Description", - "android": {"fcmServerKey": "AAAAtm7JlCY:APA91bEe02qZQbfcTtmnPOHlQ431tDPm"}, - "appToApp": True, - "appToConversations": False, - "appToPhone": True, - }, - { - "id": "454d142b-a1ad-239a-d231-227fa335aadc3", - "name": "Application Name 3", - "description": "Application Description", - "appToApp": True, - "appToConversations": False, - "appToPhone": True, - }, - ] diff --git a/tests/webrtc/integration/test_webrtc_endpoints_with_body.py b/tests/webrtc/integration/test_webrtc_endpoints_with_body.py deleted file mode 100644 index 03a70c9..0000000 --- a/tests/webrtc/integration/test_webrtc_endpoints_with_body.py +++ /dev/null @@ -1,116 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.web_rtc.channel import WebRtcChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - method_name, -): - message_body_instance = message_body = expected_json.build() - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - json=message_body_instance.dict(by_alias=True), - ).respond_with_response(get_response_object(status_code, response_content)) - - webrtc_channel = WebRtcChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - if expected_path_parameters is not None: - return getattr(webrtc_channel, method_name)( - expected_path_parameters, message_body - ) - else: - return getattr(webrtc_channel, method_name)(message_body) - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, method_name", - prefix="case__supported_status", -) -def test_webrtc_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - method_name, - ) - response_dict = WebRtcChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, expected_json, method_name", - prefix="case__unsupported_status", -) -def test_webrtc_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - expected_json, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/webrtc/integration/test_webrtc_endpoints_with_body_cases.py b/tests/webrtc/integration/test_webrtc_endpoints_with_body_cases.py deleted file mode 100644 index 6b0b071..0000000 --- a/tests/webrtc/integration/test_webrtc_endpoints_with_body_cases.py +++ /dev/null @@ -1,89 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_post_headers, get_expected_put_headers -from tests.webrtc.conftest import ( - GenerateTokenFactory, - SaveApplicationFactory, - UpdateApplicationFactory, - get_expected_path_parameters, - get_webrtc_application_request, - get_webrtc_application_response, - get_webrtc_body_generate_token, - get_webrtc_generate_token_response, - get_webrtc_request_error_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "generate_token": { - "endpoint": "/webrtc/1/token", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": None, - "expected_query_parameters": None, - "expected_json": GenerateTokenFactory, - "request_data": get_webrtc_body_generate_token(), - "method_name": "generate_token", - }, - "save_application": { - "endpoint": "/webrtc/1/applications", - "http_method": "POST", - "expected_headers": get_expected_post_headers(), - "expected_path_parameters": None, - "expected_query_parameters": None, - "expected_json": SaveApplicationFactory, - "request_data": get_webrtc_application_request, - "method_name": "save_application", - }, - "update_application": { - "endpoint": "/webrtc/1/applications/894c822b-d7ba-439c-a761-141f591cace7", - "http_method": "PUT", - "expected_headers": get_expected_put_headers(), - "expected_path_parameters": get_expected_path_parameters(), - "expected_query_parameters": None, - "expected_json": UpdateApplicationFactory, - "request_data": get_webrtc_application_request, - "method_name": "update_application", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_webrtc_application_response], - [400, get_webrtc_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "generate_token" and responses[0] == 200: - response_content = get_webrtc_generate_token_response - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize(endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys()) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_webrtc_application_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_json"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/webrtc/integration/test_webrtc_endpoints_without_body.py b/tests/webrtc/integration/test_webrtc_endpoints_without_body.py deleted file mode 100644 index f8142c2..0000000 --- a/tests/webrtc/integration/test_webrtc_endpoints_without_body.py +++ /dev/null @@ -1,117 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.web_rtc.channel import WebRtcChannel -from tests.conftest import get_response_object - - -def set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - method_name, -): - httpserver.expect_request( - endpoint, - method=http_method, - query_string=expected_query_parameters, - headers=expected_headers, - ).respond_with_response(get_response_object(status_code, response_content)) - - webrtc_channel = WebRtcChannel.from_auth_params( - {"base_url": httpserver.url_for("/"), "api_key": "secret"} - ) - if expected_path_parameters is not None: - return getattr(webrtc_channel, method_name)(expected_path_parameters) - else: - return getattr(webrtc_channel, method_name)() - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, method_name", - prefix="case__supported_status", -) -def test_webrtc_endpoints__supported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - method_name, - ) - if http_method == "DELETE" and status_code == 200: - assert response is not None - assert response.status_code == status_code - else: - response_dict = WebRtcChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - - if type(response_content) is list: - response_content = {"list": response_content} - else: - response_content = response_content - - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, endpoint, http_method, expected_headers, " - "expected_path_parameters, expected_query_parameters, method_name", - prefix="case__unsupported_status", -) -def test_webrtc_endpoints__unsupported_status( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - method_name, -): - response = set_up_mock_server_and_send_request( - httpserver, - status_code, - response_content, - endpoint, - http_method, - expected_headers, - expected_path_parameters, - expected_query_parameters, - method_name, - ) - assert isinstance(response, ResponseBase) is False - assert response is not None - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/webrtc/integration/test_webrtc_endpoints_without_body_cases.py b/tests/webrtc/integration/test_webrtc_endpoints_without_body_cases.py deleted file mode 100644 index dbdc1c8..0000000 --- a/tests/webrtc/integration/test_webrtc_endpoints_without_body_cases.py +++ /dev/null @@ -1,81 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_expected_delete_headers, get_expected_get_headers -from tests.webrtc.conftest import ( - get_expected_path_parameters, - get_webrtc_application_response, - get_webrtc_delete_request, - get_webrtc_get_applications_response, - get_webrtc_request_error_response, -) - -ENDPOINT_TEST_ARGUMENTS = { - "get_webrtc_applications": { - "endpoint": "/webrtc/1/applications", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": None, - "expected_query_parameters": None, - "method_name": "get_applications", - }, - "get_webrtc_application": { - "endpoint": "/webrtc/1/applications/894c822b-d7ba-439c-a761-141f591cace7", - "http_method": "GET", - "expected_headers": get_expected_get_headers(), - "expected_path_parameters": get_expected_path_parameters(), - "expected_query_parameters": None, - "method_name": "get_application", - }, - "delete_webrtc_application": { - "endpoint": "/webrtc/1/applications/894c822b-d7ba-439c-a761-141f591cace7", - "http_method": "DELETE", - "expected_headers": get_expected_delete_headers(), - "expected_path_parameters": get_expected_path_parameters(), - "expected_query_parameters": None, - "method_name": "delete_application", - }, -} - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), - responses=( - [200, get_webrtc_application_response], - [400, get_webrtc_request_error_response], - ), -) -def case__supported_status(endpoint_type, responses): - status_code = responses[0] - response_content = responses[1] - - if endpoint_type == "get_webrtc_applications" and responses[0] == 200: - response_content = get_webrtc_get_applications_response - if endpoint_type == "delete_webrtc_application" and responses[0] == 200: - response_content = get_webrtc_delete_request - - return ( - status_code, - response_content(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) - - -@parametrize( - endpoint_type=ENDPOINT_TEST_ARGUMENTS.keys(), -) -def case__unsupported_status(endpoint_type): - return ( - 201, - get_webrtc_application_response(), - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["endpoint"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["http_method"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_headers"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_path_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["expected_query_parameters"], - ENDPOINT_TEST_ARGUMENTS[endpoint_type]["method_name"], - ) diff --git a/tests/webrtc/models/test_generate_token.py b/tests/webrtc/models/test_generate_token.py deleted file mode 100644 index 9322968..0000000 --- a/tests/webrtc/models/test_generate_token.py +++ /dev/null @@ -1,79 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.web_rtc.models.body.generate_token import GenerateTokenBody -from tests.conftest import get_random_string -from tests.webrtc.conftest import GenerateTokenFactory - - -@pytest.mark.parametrize( - "identity", [None, "", {}, "Alice W", get_random_string(2), get_random_string(65)] -) -def test_when_identity_is_invalid__validation_error_is_raised(identity): - with pytest.raises(ValidationError): - GenerateTokenFactory.build( - **{ - "identity": identity, - "applicationId": "2277594c-76ea-4b8e-a299-e2b6db41b9dc", - "displayName": "Alice in Wonderland", - "capabilities": {"recording": "ALWAYS"}, - "timeToLive": 43200, - } - ) - - -@pytest.mark.parametrize("recording", [None, "", {}, "INVALID"]) -def test_when_recording_is_invalid__validation_error_is_raised(recording): - with pytest.raises(ValidationError): - GenerateTokenFactory.build( - **{ - "identity": "Alice", - "applicationId": "2277594c-76ea-4b8e-a299-e2b6db41b9dc", - "displayName": "Alice in Wonderland", - "capabilities": {"recording": recording}, - "timeToLive": 43200, - } - ) - - -@pytest.mark.parametrize("display_name", [get_random_string(4), get_random_string(51)]) -def test_when_display_name_is_invalid__validation_error_is_raised(display_name): - with pytest.raises(ValidationError): - GenerateTokenFactory.build( - **{ - "identity": "Alice", - "applicationId": "2277594c-76ea-4b8e-a299-e2b6db41b9dc", - "displayName": display_name, - "capabilities": {"recording": "ALWAYS"}, - "timeToLive": 43200, - } - ) - - -@pytest.mark.parametrize("time_to_live", [-1, 86401]) -def test_when_time_to_live_is_invalid__validation_error_is_raised(time_to_live): - with pytest.raises(ValidationError): - GenerateTokenFactory.build( - **{ - "identity": "Alice", - "applicationId": "2277594c-76ea-4b8e-a299-e2b6db41b9dc", - "displayName": "Alice in Wonderland", - "capabilities": {"recording": "ALWAYS"}, - "timeToLive": time_to_live, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - GenerateTokenBody( - **{ - "identity": "Alice12-_.é=+", - "applicationId": "2277594c-76ea-4b8e-a299-e2b6db41b9dc", - "displayName": "Alice in Wonderland", - "capabilities": {"recording": "ALWAYS"}, - "timeToLive": 43200, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/webrtc/models/test_save_application.py b/tests/webrtc/models/test_save_application.py deleted file mode 100644 index 6f78b62..0000000 --- a/tests/webrtc/models/test_save_application.py +++ /dev/null @@ -1,133 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.web_rtc.models.body.save_application import SaveApplicationBody -from tests.conftest import get_random_string -from tests.webrtc.conftest import SaveApplicationFactory - - -@pytest.mark.parametrize("name", [None, "", {}]) -def test_when_name_is_invalid__validation_error_is_raised(name): - with pytest.raises(ValidationError): - SaveApplicationFactory.build( - **{ - "name": name, - } - ) - - -@pytest.mark.parametrize("description", [get_random_string(161)]) -def test_when_description_is_invalid__validation_error_is_raised(description): - with pytest.raises(ValidationError): - SaveApplicationFactory.build( - **{"name": "Application name", "description": description} - ) - - -@pytest.mark.parametrize("apns_certificate_file_name", [None, "", {}]) -def test_when_apns_certificate_file_name_is_invalid__validation_error_is_raised( - apns_certificate_file_name, -): - with pytest.raises(ValidationError): - SaveApplicationFactory.build( - **{ - "name": "Application name", - "description": "Application Description", - "ios": { - "apnsCertificateFileName": apns_certificate_file_name, - "apnsCertificateFileContent": "APNS certificate content", - }, - } - ) - - -@pytest.mark.parametrize("apns_certificate_file_content", [None, "", {}]) -def test_when_apns_certificate_file_content_is_invalid__validation_error_is_raised( - apns_certificate_file_content, -): - with pytest.raises(ValidationError): - SaveApplicationFactory.build( - **{ - "name": "Application name", - "description": "Application Description", - "ios": { - "apnsCertificateFileName": "IOS_APNS_certificate.p", - "apnsCertificateFileContent": apns_certificate_file_content, - }, - } - ) - - -@pytest.mark.parametrize("fcm_server_key", [None, "", {}]) -def test_when_fcm_server_key_is_invalid__validation_error_is_raised(fcm_server_key): - with pytest.raises(ValidationError): - SaveApplicationFactory.build( - **{ - "name": "Application name", - "description": "Application Description", - "android": {"fcmServerKey": fcm_server_key}, - } - ) - - -@pytest.mark.parametrize("app_to_app", ["", {}, "test"]) -def test_when_app_to_app_is_invalid__validation_error_is_raised(app_to_app): - with pytest.raises(ValidationError): - SaveApplicationFactory.build( - **{"name": "Application name", "appToApp": app_to_app} - ) - - -@pytest.mark.parametrize("app_to_conversations", ["", {}, "test"]) -def test_when_app_to_conversations_is_invalid__validation_error_is_raised( - app_to_conversations, -): - with pytest.raises(ValidationError): - SaveApplicationFactory.build( - **{"name": "Application name", "appToConversations": app_to_conversations} - ) - - -@pytest.mark.parametrize("app_to_phone", ["", {}, "test"]) -def test_when_app_to_phone_is_invalid__validation_error_is_raised(app_to_phone): - with pytest.raises(ValidationError): - SaveApplicationFactory.build( - **{"name": "Application name", "appToPhone": app_to_phone} - ) - - -def test_when_input_data_is_valid_android__validation_error_is_not_raised(): - try: - SaveApplicationBody( - **{ - "name": "Application Name", - "description": "Application Description", - "android": { - "fcmServerKey": "AAAAtm7JlCY:APA91bEe02qZQbfcTtmnPOHlQ431tDPm2GoCjciVmoD3" - }, - "appToApp": "true", - "appToConversations": "false", - "appToPhone": "false", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") - - -def test_when_input_data_is_valid_ios__validation_error_is_not_raised(): - try: - SaveApplicationBody( - **{ - "name": "Application Name", - "description": "Application Description", - "ios": { - "apnsCertificateFileName": "IOS_APNS_certificate.p", - "apnsCertificateFileContent": "APNS certificate content", - }, - "appToApp": "true", - "appToConversations": "false", - "appToPhone": "false", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/conftest.py b/tests/whatsapp/conftest.py deleted file mode 100644 index e2ffb90..0000000 --- a/tests/whatsapp/conftest.py +++ /dev/null @@ -1,328 +0,0 @@ -import json - -import pytest -import urllib3 -from pydantic_factories import ModelFactory - -from infobip_channels import WhatsAppChannel -from infobip_channels.core.models import Authentication -from infobip_channels.whatsapp.models.body.audio_message import AudioMessageBody -from infobip_channels.whatsapp.models.body.buttons_message import ButtonsMessageBody -from infobip_channels.whatsapp.models.body.contact_message import ContactMessageBody -from infobip_channels.whatsapp.models.body.create_template import CreateTemplate -from infobip_channels.whatsapp.models.body.document_message import DocumentMessageBody -from infobip_channels.whatsapp.models.body.image_message import ImageMessageBody -from infobip_channels.whatsapp.models.body.list_message import ListMessageBody -from infobip_channels.whatsapp.models.body.location_message import LocationMessageBody -from infobip_channels.whatsapp.models.body.multi_product_message import ( - MultiProductMessageBody, -) -from infobip_channels.whatsapp.models.body.product_message import ProductMessageBody -from infobip_channels.whatsapp.models.body.sticker_message import StickerMessageBody -from infobip_channels.whatsapp.models.body.template_message import TemplateMessageBody -from infobip_channels.whatsapp.models.body.text_message import TextMessageBody -from infobip_channels.whatsapp.models.body.video_message import VideoMessageBody -from infobip_channels.whatsapp.models.path_parameters.delete_template import ( - DeleteTemplatePathParameters, -) -from infobip_channels.whatsapp.models.path_parameters.manage_templates import ( - ManageTemplatesPathParameters, -) - - -class AuthenticationFactory(ModelFactory): - __model__ = Authentication - - -class TextMessageBodyFactory(ModelFactory): - __model__ = TextMessageBody - - -class DocumentMessageBodyFactory(ModelFactory): - __model__ = DocumentMessageBody - - -class AudioMessageBodyFactory(ModelFactory): - __model__ = AudioMessageBody - - -class ImageMessageBodyFactory(ModelFactory): - __model__ = ImageMessageBody - - -class StickerMessageBodyFactory(ModelFactory): - __model__ = StickerMessageBody - - -class VideoMessageBodyFactory(ModelFactory): - __model__ = VideoMessageBody - - -class LocationMessageBodyFactory(ModelFactory): - __model__ = LocationMessageBody - - -class ContactMessageBodyFactory(ModelFactory): - __model__ = ContactMessageBody - - -class ButtonsMessageBodyFactory(ModelFactory): - __model__ = ButtonsMessageBody - - -class ListMessageBodyFactory(ModelFactory): - __model__ = ListMessageBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": { - "body": {"text": "Body text"}, - "action": { - "title": "Action title", - "sections": [ - { - "title": "section title", - "rows": [ - { - "id": "1", - "title": "row title", - "description": "row description", - } - ], - }, - { - "title": "section title 2", - "rows": [ - { - "id": "2", - "title": "row title 2", - "description": "row description 2", - } - ], - }, - ], - }, - "header": {"type": "TEXT", "text": "header text"}, - "footer": {"text": "footer text"}, - }, - } - ) - - -class TemplateMessageBodyFactory(ModelFactory): - __model__ = TemplateMessageBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because pydantic_factories can't handle regex patterns.""" - return TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "template_name", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "VIDEO", - "media_url": "https://video.com", - }, - "buttons": [ - {"type": "QUICK_REPLY", "parameter": "button 1"}, - ], - }, - "language": "en", - }, - }, - ], - } - ) - - -class ProductMessageBodyFactory(ModelFactory): - __model__ = ProductMessageBody - - -class MultiProductMessageBodyFactory(ModelFactory): - __model__ = MultiProductMessageBody - - @classmethod - def build(cls, *args, **kwargs): - """Needed because factory classes don't play well with custom validation.""" - return MultiProductMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": { - "header": {"type": "TEXT", "text": "Some text"}, - "body": {"text": "Some text"}, - "action": { - "catalogId": "1", - "sections": [ - { - "title": "Title", - "productRetailerIds": ["id 2"], - }, - { - "title": "Title 2", - "productRetailerIds": ["id 2", "id 3"], - }, - ], - }, - }, - } - ) - - -class CreateTemplateBodyFactory(ModelFactory): - __model__ = CreateTemplate - - -class CreateTemplatesPathParametersFactory(ModelFactory): - __model__ = ManageTemplatesPathParameters - - -class DeleteTemplatePathParametersFactory(ModelFactory): - __model__ = DeleteTemplatePathParameters - - -@pytest.fixture -def authentication(): - return AuthenticationFactory.build() - - -class HttpTestClientUnofficial: - def __init__(self, url, headers): - self.pool = urllib3.PoolManager() - self.url = url - self.headers = headers - - def post(self, endpoint, body): - return self.pool.request( - "POST", - url=f"{self.url}" + endpoint, - body=json.dumps(body), - headers=self.headers, - ) - - def get(self, endpoint): - return self.pool.request( - "GET", url=f"{self.url}" + endpoint, headers=self.headers - ) - - def delete(self, endpoint): - return self.pool.request( - "DELETE", url=f"{self.url}" + endpoint, headers=self.headers - ) - - -@pytest.fixture -def http_test_client_unofficial(): - def _get_http_test_client_unofficial(url, headers): - return HttpTestClientUnofficial(url, headers) - - return _get_http_test_client_unofficial - - -def get_response_ok_content(): - return { - "to": "441134960001", - "messageCount": 1, - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "status": { - "groupId": 1, - "groupName": "PENDING", - "id": 7, - "name": "PENDING_ENROUTE", - "description": "Message sent to next instance", - }, - } - - -def get_template_message_response_ok_content(): - return { - "messages": [ - { - "to": "441134960001", - "messageCount": 1, - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "status": { - "groupId": 1, - "groupName": "PENDING", - "id": 7, - "name": "PENDING_ENROUTE", - "description": "Message sent to next instance", - }, - }, - { - "to": "441631451112", - "messageCount": 1, - "messageId": "a2ga3hgc-sa7n-1ach-0df1-9b55aeb3a1na", - "status": { - "groupId": 1, - "groupName": "PENDING", - "id": 7, - "name": "PENDING_ENROUTE", - "description": "Message sent to next instance", - }, - }, - ], - "bulkId": "2034072219640523073", - } - - -def get_response_ok_invalid_content(): - return { - "to": "441134960001", - "messageCount": 1, - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - } - - -class ResponseUnofficial: - def __init__(self, status, content): - self.status = status - self.content = content - - -def get_response_object_unofficial(status_code, content): - return ResponseUnofficial(status_code, json.dumps(content)) - - -def get_response_error_content(): - return { - "requestError": { - "serviceException": { - "messageId": "BAD_REQUEST", - "text": "Bad request", - "validationErrors": { - "content.text": [ - "size must be between 1 and 4096", - "must not be blank", - ] - }, - } - } - } - - -def get_whatsapp_channel_instance(instantiation_type, **kwargs): - if instantiation_type == "auth_params": - return WhatsAppChannel.from_auth_params( - {"base_url": kwargs["server_url"], "api_key": "secret"} - ) - - elif instantiation_type == "auth_instance": - return WhatsAppChannel.from_auth_instance( - Authentication(base_url=kwargs["server_url"], api_key="secret") - ) - - return WhatsAppChannel.from_provided_client(kwargs["client"]) diff --git a/tests/whatsapp/integration/test_create_template_integration.py b/tests/whatsapp/integration/test_create_template_integration.py deleted file mode 100644 index 2d7e967..0000000 --- a/tests/whatsapp/integration/test_create_template_integration.py +++ /dev/null @@ -1,127 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.whatsapp.channel import WhatsAppChannel -from infobip_channels.whatsapp.models.path_parameters.manage_templates import ( - ManageTemplatesPathParameters, -) -from tests.conftest import get_expected_post_headers, get_response_object -from tests.whatsapp.conftest import ( - CreateTemplateBodyFactory, - get_response_object_unofficial, - get_whatsapp_channel_instance, -) - - -def create_template_request( - http_server, - response, - instantiation_type, - path_parameters_type, - message_body_type, - **kwargs, -): - path_parameter_instance = path_parameter = ManageTemplatesPathParameters( - sender="38598765321" - ) - message_body_instance = message_body = CreateTemplateBodyFactory.build() - http_server.expect_request( - "/whatsapp/1/senders/38598765321/templates", - method="POST", - json=message_body_instance.dict(by_alias=True), - headers=get_expected_post_headers(), - ).respond_with_response(response) - - whatsapp_channel = get_whatsapp_channel_instance(instantiation_type, **kwargs) - - if path_parameters_type == "dict": - path_parameter = path_parameter_instance.dict() - if message_body_type == "dict": - message_body = message_body_instance.dict() - - return whatsapp_channel.create_template(path_parameter, message_body) - - -@parametrize_with_cases( - "status_code, response_content, path_parameters_type, " - "message_body_type, whatsapp_channel_instantiation_type", - prefix="from_all_instantiation_types_case__valid_content", -) -def test_create_template_from_all_instantiation_types_case__valid_content( - httpserver, - http_test_client, - status_code, - response_content, - path_parameters_type, - message_body_type, - whatsapp_channel_instantiation_type, -): - response = create_template_request( - http_server=httpserver, - response=get_response_object(status_code, response_content), - instantiation_type=whatsapp_channel_instantiation_type, - path_parameters_type=path_parameters_type, - message_body_type=message_body_type, - server_url=httpserver.url_for("/"), - client=http_test_client( - url=httpserver.url_for("/"), - headers=WhatsAppChannel.build_post_request_headers("secret"), - ), - ) - - response_dict = WhatsAppChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, path_parameters_type, " - "message_body_type, whatsapp_channel_instantiation_type", - prefix="from_all_instantiation_types_case__invalid_content", -) -def test_create_template_from_all_instantiation_types_case__invalid_content( - httpserver, - http_test_client, - http_test_client_unofficial, - status_code, - response_content, - path_parameters_type, - message_body_type, - whatsapp_channel_instantiation_type, -): - if whatsapp_channel_instantiation_type == "client_unofficial": - client = http_test_client_unofficial - response_object = get_response_object_unofficial - else: - client = http_test_client - response_object = get_response_object - - response = create_template_request( - http_server=httpserver, - response=response_object(status_code, response_content), - instantiation_type=whatsapp_channel_instantiation_type, - path_parameters_type=path_parameters_type, - message_body_type=message_body_type, - server_url=httpserver.url_for("/"), - client=client( - url=httpserver.url_for("/"), - headers=WhatsAppChannel.build_post_request_headers("secret"), - ), - ) - - assert isinstance(response, ResponseBase) is False - assert response is not None - - if whatsapp_channel_instantiation_type != "client_unofficial": - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/whatsapp/integration/test_create_template_integration_cases.py b/tests/whatsapp/integration/test_create_template_integration_cases.py deleted file mode 100644 index d20d8ce..0000000 --- a/tests/whatsapp/integration/test_create_template_integration_cases.py +++ /dev/null @@ -1,99 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_response_error_invalid_content -from tests.whatsapp.conftest import get_response_error_content - - -def get_response_ok_content(): - return { - "id": "222", - "businessAccountId": 333, - "name": "exampleName", - "language": "en", - "status": "APPROVED", - "category": "ACCOUNT_UPDATE", - "structure": { - "header": {"format": "IMAGE"}, - "body": "example {{1}} body", - "footer": "exampleFooter", - "type": "MEDIA", - "buttons": [{"type": "URL", "text": "url", "url": "http://someurl.com"}], - }, - } - - -def get_response_ok_invalid_content(): - return { - "businessAccountId": 222, - "name": "exampleName", - "language": "en", - "status": "APPROVED", - "category": "ACCOUNT_UPDATE", - "structure_invalid": { - "header": {"format": "IMAGE"}, - "body": "example {{1}} body", - "footer": "exampleFooter", - "type": "MEDIA", - "buttons": [{"type": "URL", "text": "url", "url": "http://someurl.com"}], - }, - } - - -@parametrize( - path_parameters_type=("path_parameter_instance", "dict"), - message_body_type=("message_body_instance", "dict"), - whatsapp_channel_instantiation_type=("auth_params", "auth_instance", "client"), - responses=( - [200, get_response_ok_content()], - [201, get_response_ok_content()], - [400, get_response_error_content()], - [401, get_response_error_content()], - [403, get_response_error_content()], - [429, get_response_error_content()], - ), -) -def from_all_instantiation_types_case__valid_content( - responses, - path_parameters_type, - message_body_type, - whatsapp_channel_instantiation_type, -): - return ( - responses[0], - responses[1], - path_parameters_type, - message_body_type, - whatsapp_channel_instantiation_type, - ) - - -@parametrize( - path_parameters_type=("path_parameter_instance", "dict"), - message_body_type=("message_body_instance", "dict"), - whatsapp_channel_instantiation_type=( - "auth_params", - "auth_instance", - "client", - "client_unofficial", - ), - responses=( - [201, get_response_ok_invalid_content()], - [202, get_response_ok_content()], - [403, get_response_error_invalid_content()], - [405, get_response_error_content()], - [500, get_response_error_invalid_content()], - ), -) -def from_all_instantiation_types_case__invalid_content( - responses, - path_parameters_type, - message_body_type, - whatsapp_channel_instantiation_type, -): - return ( - responses[0], - responses[1], - path_parameters_type, - message_body_type, - whatsapp_channel_instantiation_type, - ) diff --git a/tests/whatsapp/integration/test_delete_template_integration.py b/tests/whatsapp/integration/test_delete_template_integration.py deleted file mode 100644 index 5b176fd..0000000 --- a/tests/whatsapp/integration/test_delete_template_integration.py +++ /dev/null @@ -1,106 +0,0 @@ -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.whatsapp.channel import WhatsAppChannel -from infobip_channels.whatsapp.models.path_parameters.delete_template import ( - DeleteTemplatePathParameters, -) -from tests.conftest import get_expected_delete_headers, get_response_object -from tests.whatsapp.conftest import ( - get_response_object_unofficial, - get_whatsapp_channel_instance, -) - - -def delete_template_request( - http_server, - response, - instantiation_type, - path_parameters_type, - **kwargs, -): - path_parameter_instance = path_parameter = DeleteTemplatePathParameters( - sender="38598765321", template_name="test" - ) - http_server.expect_request( - "/whatsapp/2/senders/38598765321/templates/test", - method="DELETE", - headers=get_expected_delete_headers(), - ).respond_with_response(response) - - whatsapp_channel = get_whatsapp_channel_instance(instantiation_type, **kwargs) - - if path_parameters_type == "dict": - path_parameter = path_parameter_instance.dict() - - return whatsapp_channel.delete_template(path_parameter) - - -@parametrize_with_cases( - "status_code, response_content, path_parameters_type, " - "whatsapp_channel_instantiation_type", - prefix="from_all_instantiation_types_case__valid_content", -) -def test_delete_template_from_all_instantiation_types_case__valid_content( - httpserver, - http_test_client, - status_code, - response_content, - path_parameters_type, - whatsapp_channel_instantiation_type, -): - response = delete_template_request( - http_server=httpserver, - response=get_response_object(status_code, response_content), - instantiation_type=whatsapp_channel_instantiation_type, - path_parameters_type=path_parameters_type, - server_url=httpserver.url_for("/"), - client=http_test_client( - url=httpserver.url_for("/"), - headers=WhatsAppChannel.build_delete_request_headers("secret"), - ), - ) - - assert response is not None - assert response.status_code == status_code - - -@parametrize_with_cases( - "status_code, response_content, path_parameters_type, " - "whatsapp_channel_instantiation_type", - prefix="from_all_instantiation_types_case__invalid_content", -) -def test_create_template_from_all_instantiation_types_case__invalid_content( - httpserver, - http_test_client, - http_test_client_unofficial, - status_code, - response_content, - path_parameters_type, - whatsapp_channel_instantiation_type, -): - if whatsapp_channel_instantiation_type == "client_unofficial": - client = http_test_client_unofficial - response_object = get_response_object_unofficial - else: - client = http_test_client - response_object = get_response_object - - response = delete_template_request( - http_server=httpserver, - response=response_object(status_code, response_content), - instantiation_type=whatsapp_channel_instantiation_type, - path_parameters_type=path_parameters_type, - server_url=httpserver.url_for("/"), - client=client( - url=httpserver.url_for("/"), - headers=WhatsAppChannel.build_delete_request_headers("secret"), - ), - ) - - assert isinstance(response, ResponseBase) is False - assert response is not None - - if whatsapp_channel_instantiation_type != "client_unofficial": - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/whatsapp/integration/test_delete_template_integration_cases.py b/tests/whatsapp/integration/test_delete_template_integration_cases.py deleted file mode 100644 index 886f3e8..0000000 --- a/tests/whatsapp/integration/test_delete_template_integration_cases.py +++ /dev/null @@ -1,61 +0,0 @@ -from pytest_cases import parametrize - -from tests.whatsapp.conftest import get_response_error_content - - -def get_delete_template_ok_content(): - return {} - - -@parametrize( - path_parameters_type=("path_parameter_instance", "dict"), - whatsapp_channel_instantiation_type=("auth_params", "auth_instance", "client"), - responses=( - [200, get_delete_template_ok_content()], - [202, get_delete_template_ok_content()], - [400, get_response_error_content()], - [401, get_response_error_content()], - [403, get_response_error_content()], - [429, get_response_error_content()], - ), -) -def from_all_instantiation_types_case__valid_content( - responses, - path_parameters_type, - whatsapp_channel_instantiation_type, -): - return ( - responses[0], - responses[1], - path_parameters_type, - whatsapp_channel_instantiation_type, - ) - - -@parametrize( - path_parameters_type=("path_parameter_instance", "dict"), - whatsapp_channel_instantiation_type=( - "auth_params", - "auth_instance", - "client", - "client_unofficial", - ), - responses=( - [201, get_delete_template_ok_content()], - [202, get_delete_template_ok_content()], - [403, get_response_error_content()], - [405, get_response_error_content()], - [500, get_response_error_content()], - ), -) -def from_all_instantiation_types_case__invalid_content( - responses, - path_parameters_type, - whatsapp_channel_instantiation_type, -): - return ( - responses[0], - responses[1], - path_parameters_type, - whatsapp_channel_instantiation_type, - ) diff --git a/tests/whatsapp/integration/test_get_templates.py b/tests/whatsapp/integration/test_get_templates.py deleted file mode 100644 index 15c0ba8..0000000 --- a/tests/whatsapp/integration/test_get_templates.py +++ /dev/null @@ -1,117 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.whatsapp.channel import WhatsAppChannel -from infobip_channels.whatsapp.models.path_parameters.manage_templates import ( - ManageTemplatesPathParameters, -) -from tests.conftest import get_expected_get_headers, get_response_object -from tests.whatsapp.conftest import ( - get_response_object_unofficial, - get_whatsapp_channel_instance, -) - - -def get_templates_request( - http_server, - response, - instantiation_type, - path_parameters_type, - **kwargs, -): - path_parameter_instance = path_parameter = ManageTemplatesPathParameters( - sender="38598765321" - ) - http_server.expect_request( - "/whatsapp/1/senders/38598765321/templates", - method="GET", - headers=get_expected_get_headers(), - ).respond_with_response(response) - - whatsapp_channel = get_whatsapp_channel_instance(instantiation_type, **kwargs) - - if path_parameters_type == "dict": - path_parameter = path_parameter_instance.dict() - - return whatsapp_channel.get_templates(path_parameter) - - -@parametrize_with_cases( - "status_code, response_content, path_parameters_type, " - "whatsapp_channel_instantiation_type", - prefix="from_all_instantiation_types_case__valid_content", -) -def test_get_templates_from_all_instantiation_types_case__valid_content( - httpserver, - http_test_client, - status_code, - response_content, - path_parameters_type, - whatsapp_channel_instantiation_type, -): - response = get_templates_request( - http_server=httpserver, - response=get_response_object(status_code, response_content), - instantiation_type=whatsapp_channel_instantiation_type, - path_parameters_type=path_parameters_type, - server_url=httpserver.url_for("/"), - client=http_test_client( - url=httpserver.url_for("/"), - headers=WhatsAppChannel.build_get_request_headers("secret"), - ), - ) - - response_dict = WhatsAppChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "status_code, response_content, path_parameters_type, " - "whatsapp_channel_instantiation_type", - prefix="from_all_instantiation_types_case__invalid_content", -) -def test_get_templates_from_all_instantiation_types_case__invalid_content( - httpserver, - http_test_client, - http_test_client_unofficial, - status_code, - response_content, - path_parameters_type, - whatsapp_channel_instantiation_type, -): - if whatsapp_channel_instantiation_type == "client_unofficial": - client = http_test_client_unofficial - response_object = get_response_object_unofficial - else: - client = http_test_client - response_object = get_response_object - - response = get_templates_request( - http_server=httpserver, - response=response_object(status_code, response_content), - instantiation_type=whatsapp_channel_instantiation_type, - path_parameters_type=path_parameters_type, - server_url=httpserver.url_for("/"), - client=client( - url=httpserver.url_for("/"), - headers=WhatsAppChannel.build_get_request_headers("secret"), - ), - ) - - assert isinstance(response, ResponseBase) is False - assert response is not None - - if whatsapp_channel_instantiation_type != "client_unofficial": - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/whatsapp/integration/test_get_templates_cases.py b/tests/whatsapp/integration/test_get_templates_cases.py deleted file mode 100644 index bca84ff..0000000 --- a/tests/whatsapp/integration/test_get_templates_cases.py +++ /dev/null @@ -1,102 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_response_error_invalid_content -from tests.whatsapp.conftest import get_response_error_content - - -def get_response_ok_content(): - return { - "templates": [ - { - "id": "111", - "businessAccountId": 222, - "name": "exampleName", - "language": "en", - "status": "APPROVED", - "category": "ACCOUNT_UPDATE", - "structure": { - "header": {"format": "IMAGE"}, - "body": "example {{1}} body", - "footer": "exampleFooter", - "type": "MEDIA", - "buttons": [ - { - "type": "PHONE_NUMBER", - "text": "phone", - "phoneNumber": "38598340098", - } - ], - }, - } - ] - } - - -def get_response_ok_invalid_content(): - return { - "id": "111", - "businessAccountId": 222, - "name": "exampleName", - "language": "en", - "status": "APPROVED", - "category": "ACCOUNT_UPDATE", - "structure": { - "header": {"format": "IMAGE"}, - "body": "example {{1}} body", - "footer": "exampleFooter", - "type": "MEDIA", - "buttons": [ - {"type": "PHONE_NUMBER", "text": "phone", "phoneNumber": "38598340098"} - ], - }, - } - - -@parametrize( - path_parameters_type=("path_parameter_instance", "dict"), - whatsapp_channel_instantiation_type=("auth_params", "auth_instance", "client"), - responses=( - [200, get_response_ok_content()], - [201, get_response_ok_content()], - [400, get_response_error_content()], - [401, get_response_error_content()], - [403, get_response_error_content()], - [429, get_response_error_content()], - ), -) -def from_all_instantiation_types_case__valid_content( - responses, path_parameters_type, whatsapp_channel_instantiation_type -): - return ( - responses[0], - responses[1], - path_parameters_type, - whatsapp_channel_instantiation_type, - ) - - -@parametrize( - path_parameters_type=("path_parameter_instance", "dict"), - whatsapp_channel_instantiation_type=( - "auth_params", - "auth_instance", - "client", - "client_unofficial", - ), - responses=( - [201, get_response_ok_invalid_content()], - [202, get_response_ok_content()], - [403, get_response_error_invalid_content()], - [405, get_response_error_content()], - [500, get_response_error_invalid_content()], - ), -) -def from_all_instantiation_types_case__invalid_content( - responses, path_parameters_type, whatsapp_channel_instantiation_type -): - return ( - responses[0], - responses[1], - path_parameters_type, - whatsapp_channel_instantiation_type, - ) diff --git a/tests/whatsapp/integration/test_send_message.py b/tests/whatsapp/integration/test_send_message.py deleted file mode 100644 index 3251c2a..0000000 --- a/tests/whatsapp/integration/test_send_message.py +++ /dev/null @@ -1,128 +0,0 @@ -from http import HTTPStatus - -from pytest_cases import parametrize_with_cases - -from infobip_channels.core.models import ResponseBase -from infobip_channels.whatsapp.channel import WhatsAppChannel -from tests.conftest import get_expected_post_headers, get_response_object -from tests.whatsapp.conftest import ( - get_response_object_unofficial, - get_whatsapp_channel_instance, -) - - -def set_up_mock_server_and_send_request( - factory, - http_server, - endpoint, - response, - instantiation_type, - message_body_type, - method_name, - **kwargs, -): - message_body_instance = message_body = factory.build() - http_server.expect_request( - endpoint, - method="POST", - json=message_body_instance.dict(by_alias=True), - headers=get_expected_post_headers(), - ).respond_with_response(response) - - whatsapp_channel = get_whatsapp_channel_instance(instantiation_type, **kwargs) - - if message_body_type == "dict": - message_body = message_body_instance.dict() - - return getattr(whatsapp_channel, method_name)(message_body) - - -@parametrize_with_cases( - "endpoint, message_body_factory, method_name, status_code, " - "response_content, message_body_type, whatsapp_channel_instantiation_type", - prefix="from_all_instantiation_types_case__valid_content", -) -def test_send_message_from_all_instantiation_types_case__valid_content( - httpserver, - http_test_client, - endpoint, - message_body_factory, - method_name, - status_code, - response_content, - message_body_type, - whatsapp_channel_instantiation_type, -): - response = set_up_mock_server_and_send_request( - factory=message_body_factory, - http_server=httpserver, - endpoint=endpoint, - response=get_response_object(status_code, response_content), - instantiation_type=whatsapp_channel_instantiation_type, - message_body_type=message_body_type, - method_name=method_name, - server_url=httpserver.url_for("/"), - client=http_test_client( - url=httpserver.url_for("/"), - headers=WhatsAppChannel.build_post_request_headers("secret"), - ), - ) - - response_dict = WhatsAppChannel.convert_model_to_dict(response) - raw_response = response_dict.pop("rawResponse") - expected_response_dict = { - **response_content, - "statusCode": HTTPStatus(status_code), - } - - assert isinstance(response, ResponseBase) is True - assert response.status_code == status_code - assert response_dict == expected_response_dict - assert raw_response is not None - - -@parametrize_with_cases( - "endpoint, message_body_factory, method_name, status_code, " - "response_content, message_body_type, whatsapp_channel_instantiation_type", - prefix="from_all_instantiation_types_case__invalid_content", -) -def test_send_message_from_all_instantiation_types_case__invalid_content( - httpserver, - http_test_client, - http_test_client_unofficial, - endpoint, - message_body_factory, - method_name, - status_code, - response_content, - message_body_type, - whatsapp_channel_instantiation_type, -): - if whatsapp_channel_instantiation_type == "client_unofficial": - client = http_test_client_unofficial - response_object = get_response_object_unofficial - else: - client = http_test_client - response_object = get_response_object - - response = set_up_mock_server_and_send_request( - factory=message_body_factory, - http_server=httpserver, - endpoint=endpoint, - response=response_object(status_code, response_content), - instantiation_type=whatsapp_channel_instantiation_type, - message_body_type=message_body_type, - method_name=method_name, - server_url=httpserver.url_for("/"), - client=client( - url=httpserver.url_for("/"), - headers=WhatsAppChannel.build_post_request_headers("secret"), - ), - ) - - assert isinstance(response, ResponseBase) is False - assert response is not None - - if whatsapp_channel_instantiation_type != "client_unofficial": - assert response.status_code == status_code - assert response.json() == response_content diff --git a/tests/whatsapp/integration/test_send_message_cases.py b/tests/whatsapp/integration/test_send_message_cases.py deleted file mode 100644 index 4cdb91d..0000000 --- a/tests/whatsapp/integration/test_send_message_cases.py +++ /dev/null @@ -1,158 +0,0 @@ -from pytest_cases import parametrize - -from tests.conftest import get_response_error_invalid_content -from tests.whatsapp.conftest import ( - AudioMessageBodyFactory, - ButtonsMessageBodyFactory, - ContactMessageBodyFactory, - DocumentMessageBodyFactory, - ImageMessageBodyFactory, - ListMessageBodyFactory, - LocationMessageBodyFactory, - MultiProductMessageBodyFactory, - ProductMessageBodyFactory, - StickerMessageBodyFactory, - TemplateMessageBodyFactory, - TextMessageBodyFactory, - VideoMessageBodyFactory, - get_response_error_content, - get_response_ok_content, - get_response_ok_invalid_content, - get_template_message_response_ok_content, -) - -MESSAGE_TYPE_ATTRIBUTES = { - "template": { - "message_body_factory": TemplateMessageBodyFactory, - "endpoint": "/whatsapp/1/message/template", - "method_name": "send_template_message", - }, - "text": { - "message_body_factory": TextMessageBodyFactory, - "endpoint": "/whatsapp/1/message/text", - "method_name": "send_text_message", - }, - "document": { - "message_body_factory": DocumentMessageBodyFactory, - "endpoint": "/whatsapp/1/message/document", - "method_name": "send_document_message", - }, - "image": { - "message_body_factory": ImageMessageBodyFactory, - "endpoint": "/whatsapp/1/message/image", - "method_name": "send_image_message", - }, - "audio": { - "message_body_factory": AudioMessageBodyFactory, - "endpoint": "/whatsapp/1/message/audio", - "method_name": "send_audio_message", - }, - "video": { - "message_body_factory": VideoMessageBodyFactory, - "endpoint": "/whatsapp/1/message/video", - "method_name": "send_video_message", - }, - "sticker": { - "message_body_factory": StickerMessageBodyFactory, - "endpoint": "/whatsapp/1/message/sticker", - "method_name": "send_sticker_message", - }, - "location": { - "message_body_factory": LocationMessageBodyFactory, - "endpoint": "/whatsapp/1/message/location", - "method_name": "send_location_message", - }, - "contact": { - "message_body_factory": ContactMessageBodyFactory, - "endpoint": "/whatsapp/1/message/contact", - "method_name": "send_contact_message", - }, - "buttons": { - "message_body_factory": ButtonsMessageBodyFactory, - "endpoint": "/whatsapp/1/message/interactive/buttons", - "method_name": "send_interactive_buttons_message", - }, - "list": { - "message_body_factory": ListMessageBodyFactory, - "endpoint": "/whatsapp/1/message/interactive/list", - "method_name": "send_interactive_list_message", - }, - "product": { - "message_body_factory": ProductMessageBodyFactory, - "endpoint": "/whatsapp/1/message/interactive/product", - "method_name": "send_interactive_product_message", - }, - "multi_product": { - "message_body_factory": MultiProductMessageBodyFactory, - "endpoint": "/whatsapp/1/message/interactive/multi-product", - "method_name": "send_interactive_multi_product_message", - }, -} - - -@parametrize( - message_type=MESSAGE_TYPE_ATTRIBUTES.keys(), - message_body_type=("message_body_instance", "dict"), - whatsapp_channel_instantiation_type=("auth_params", "auth_instance", "client"), - responses=( - [200, get_response_ok_content], - [201, get_response_ok_content], - [400, get_response_error_content], - [401, get_response_error_content], - [403, get_response_error_content], - [429, get_response_error_content], - ), -) -def from_all_instantiation_types_case__valid_content( - message_type, responses, message_body_type, whatsapp_channel_instantiation_type -): - response_content = responses[1] - - if message_type == "template" and responses[0] in (200, 201): - response_content = get_template_message_response_ok_content - - return ( - MESSAGE_TYPE_ATTRIBUTES[message_type]["endpoint"], - MESSAGE_TYPE_ATTRIBUTES[message_type]["message_body_factory"], - MESSAGE_TYPE_ATTRIBUTES[message_type]["method_name"], - responses[0], - response_content(), - message_body_type, - whatsapp_channel_instantiation_type, - ) - - -@parametrize( - message_type=MESSAGE_TYPE_ATTRIBUTES.keys(), - message_body_type=("message_body_instance", "dict"), - whatsapp_channel_instantiation_type=( - "auth_params", - "auth_instance", - "client", - "client_unofficial", - ), - responses=( - [201, get_response_ok_invalid_content], - [202, get_response_ok_content], - [403, get_response_error_invalid_content], - [405, get_response_error_content], - [500, get_response_error_invalid_content], - ), -) -def from_all_instantiation_types_case__invalid_content( - message_type, responses, message_body_type, whatsapp_channel_instantiation_type -): - response_content = responses[1] - - if message_type == "template" and responses[0] == 202: - response_content = get_template_message_response_ok_content - - return ( - MESSAGE_TYPE_ATTRIBUTES[message_type]["endpoint"], - MESSAGE_TYPE_ATTRIBUTES[message_type]["message_body_factory"], - MESSAGE_TYPE_ATTRIBUTES[message_type]["method_name"], - responses[0], - response_content(), - message_body_type, - whatsapp_channel_instantiation_type, - ) diff --git a/tests/whatsapp/models/test_audio_message.py b/tests/whatsapp/models/test_audio_message.py deleted file mode 100644 index c3f7c74..0000000 --- a/tests/whatsapp/models/test_audio_message.py +++ /dev/null @@ -1,40 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.audio_message import AudioMessageBody -from infobip_channels.whatsapp.models.body.core import MessageBody -from tests.conftest import get_random_string -from tests.whatsapp.conftest import AudioMessageBodyFactory - - -def test_audio_message_body__is_an_instance_of_message_body(): - assert isinstance(AudioMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize("content", [None, "", {}]) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - AudioMessageBodyFactory.build(**{"content": content}) - - -@pytest.mark.parametrize( - "media_url", - [None, "", {}, "ftp://myfile.com", f"http://myfile.com/{get_random_string(2031)}"], -) -def test_when_content_media_url_is_invalid__validation_error_is_raised(media_url): - with pytest.raises(ValidationError): - AudioMessageBodyFactory.build(**{"content": {"mediaUrl": media_url}}) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - AudioMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": {"media_url": "https://audio_file.com"}, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_buttons_message.py b/tests/whatsapp/models/test_buttons_message.py deleted file mode 100644 index 1a6170a..0000000 --- a/tests/whatsapp/models/test_buttons_message.py +++ /dev/null @@ -1,327 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.buttons_message import ButtonsMessageBody -from infobip_channels.whatsapp.models.body.core import MessageBody -from tests.conftest import get_random_string -from tests.whatsapp.conftest import ButtonsMessageBodyFactory - - -def test_buttons_message_body__is_an_instance_of_message_body(): - assert isinstance(ButtonsMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize( - "content", - [ - None, - "", - {}, - { - "body": {"text": "test"}, - "header": {"type": "TEXT", "text": "header"}, - "footer": {"text": "footer"}, - }, - { - "action": {"buttons": [{"type": "REPLY", "id": "1", "title": "title"}]}, - "header": {"type": "TEXT", "text": "header"}, - "footer": {"text": "footer"}, - }, - ], -) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build(**{"content": content}) - - -@pytest.mark.parametrize("body", [None, "", {}]) -def test_when_body_is_invalid__validation_error_is_raised(body): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": body, - "action": { - "buttons": [{"type": "REPLY", "id": "1", "title": "title"}] - }, - } - } - ) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(1025)]) -def test_when_body_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": text}, - "action": { - "buttons": [{"type": "REPLY", "id": "1", "title": "title"}] - }, - }, - } - ) - - -@pytest.mark.parametrize("action", [None, "", {}]) -def test_when_action_is_invalid__validation_error_is_raised(action): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{"content": {"body": {"text": "test"}, "action": action}} - ) - - -@pytest.mark.parametrize( - "buttons", - [ - None, - "", - {}, - [], - [{"type": "REPLY", "id": "1", "title": "Yes"} for _ in range(4)], - [{"type": "REPLY", "id": "1"}], - [{"type": "REPLY", "title": "Yes"}], - [{"id": "1", "title": "Yes"}], - ], -) -def test_when_action_buttons_is_invalid__validation_error_is_raised(buttons): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{"content": {"body": {"text": "test"}, "action": {"buttons": buttons}}} - ) - - -@pytest.mark.parametrize("test_type", [None, "", {}, "Test"]) -def test_when_buttons_type_is_invalid__validation_error_is_raised(test_type): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [{"type": test_type, "id": "1", "title": "Yes"}] - }, - } - } - ) - - -@pytest.mark.parametrize("test_id", [None, "", {}, get_random_string(257)]) -def test_when_buttons_id_is_invalid__validation_error_is_raised(test_id): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [{"type": "REPLY", "id": test_id, "title": "Yes"}] - }, - } - } - ) - - -@pytest.mark.parametrize("title", [None, "", {}, get_random_string(21)]) -def test_when_buttons_title_is_invalid__validation_error_is_raised(title): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [{"type": "REPLY", "id": "1", "title": title}] - }, - } - } - ) - - -@pytest.mark.parametrize("test_type", [None, "", {}, "TEST"]) -def test_when_header_type_is_invalid__validation_error_is_raised(test_type): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [{"type": "REPLY", "id": "1", "title": "Yes"}] - }, - "header": {"type": test_type, "text": "Message"}, - } - } - ) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(61)]) -def test_when_header_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [{"type": "REPLY", "id": "1", "title": "Yes"}] - }, - "header": {"type": "TEXT", "text": text}, - } - } - ) - - -@pytest.mark.parametrize( - "media_url", - [ - None, - "", - {}, - "www.infobip.com", - "ftp://myfile.com", - f"http://myfile.com/{get_random_string(2031)}", - ], -) -def test_when_video_media_url_is_invalid__validation_error_is_raised(media_url): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [{"type": "REPLY", "id": "1", "title": "Yes"}] - }, - "header": {"type": "VIDEO", "mediaUrl": media_url}, - } - } - ) - - -@pytest.mark.parametrize( - "media_url", - [ - None, - "", - {}, - "www.infobip.com", - "ftp://myfile.com", - f"http://myfile.com/{get_random_string(2031)}", - ], -) -def test_when_image_media_url_is_invalid__validation_error_is_raised(media_url): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [{"type": "REPLY", "id": "1", "title": "Yes"}] - }, - "header": {"type": "IMAGE", "mediaUrl": media_url}, - } - } - ) - - -@pytest.mark.parametrize( - "media_url", - [ - None, - "", - {}, - "www.infobip.com", - "ftp://myfile.com", - f"http://myfile.com/{get_random_string(2031)}", - ], -) -def test_when_document_media_url_is_invalid__validation_error_is_raised(media_url): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [{"type": "REPLY", "id": "1", "title": "Yes"}] - }, - "header": {"type": "DOCUMENT", "mediaUrl": media_url}, - } - } - ) - - -@pytest.mark.parametrize("filename", [get_random_string(241)]) -def test_when_document_filename_is_invalid__validation_error_is_raised(filename): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [{"type": "REPLY", "id": "1", "title": "Yes"}] - }, - "header": { - "type": "DOCUMENT", - "mediaUrl": "http://infobip.com/docs.pdf", - "filename": filename, - }, - } - } - ) - - -@pytest.mark.parametrize("footer", ["", {}]) -def test_when_footer_is_invalid__validation_error_is_raised(footer): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [{"type": "REPLY", "id": "1", "title": "Yes"}] - }, - "footer": footer, - } - } - ) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(61)]) -def test_when_footer_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - ButtonsMessageBodyFactory.build( - **{ - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [{"type": "REPLY", "id": "1", "title": "Yes"}] - }, - "footer": {"text": text}, - } - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - ButtonsMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": { - "body": {"text": "test"}, - "action": { - "buttons": [ - {"type": "REPLY", "id": "1", "title": "Yes"}, - {"type": "REPLY", "id": "2", "title": "No"}, - ] - }, - "header": { - "type": "DOCUMENT", - "mediaUrl": "http://infobip.com/docs.pdf", - "filename": "file", - }, - "footer": {"text": "footer text"}, - }, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_contact_message.py b/tests/whatsapp/models/test_contact_message.py deleted file mode 100644 index 0a43948..0000000 --- a/tests/whatsapp/models/test_contact_message.py +++ /dev/null @@ -1,267 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.contact_message import ContactMessageBody -from infobip_channels.whatsapp.models.body.core import MessageBody -from tests.whatsapp.conftest import ContactMessageBodyFactory - - -def test_contact_message_body__is_an_instance_of_message_body(): - assert isinstance(ContactMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize("content", [None, "", {}]) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - ContactMessageBodyFactory.build(**{"content": content}) - - -@pytest.mark.parametrize( - "contacts", - [ - None, - "", - {}, - [{}], - [ - { - "addresses": [{"street": "street"}], - "birthday": "1992-02-22", - "emails": [{"email": "some_email@gmail.com"}], - "org": {"company": "company"}, - "phones": [{"phone": "38598765123"}], - "urls": [{"url": "https://url.com"}], - } - ], - ], -) -def test_when_contacts_is_invalid__validation_error_is_raised(contacts): - with pytest.raises(ValidationError): - ContactMessageBodyFactory.build(**{"content": {"contacts": contacts}}) - - -@pytest.mark.parametrize("address_type", ["", {}, "TEST"]) -def test_when_addresses_type_is_invalid__validation_error_is_raised(address_type): - with pytest.raises(ValidationError): - ContactMessageBodyFactory.build( - **{ - "content": { - "contacts": [ - { - "name": { - "firstName": "Art", - "formattedName": "Art Vandelay", - }, - "addresses": [{"type": address_type}], - }, - ] - } - } - ) - - -@pytest.mark.parametrize("test_type", ["", {}, "TEST"]) -def test_when_emails_type_is_invalid__validation_error_is_raised(test_type): - with pytest.raises(ValidationError): - ContactMessageBodyFactory.build( - **{ - "content": { - "contacts": [ - { - "name": { - "firstName": "Art", - "formattedName": "Art Vandelay", - }, - "emails": [{"type": test_type}], - } - ] - } - } - ) - - -@pytest.mark.parametrize( - "name", [None, {}, {"firstName": "test"}, {"formattedName": "text"}] -) -def test_when_name_is_invalid__validation_error_is_raised(name): - with pytest.raises(ValidationError): - ContactMessageBodyFactory.build(**{"content": {"contacts": [{"name": name}]}}) - - -@pytest.mark.parametrize("first_name", [None, {}]) -def test_when_first_name_type_is_invalid__validation_error_is_raised(first_name): - with pytest.raises(ValidationError): - ContactMessageBodyFactory.build( - **{ - "content": { - "contacts": [ - { - "name": { - "firstName": first_name, - "formattedName": "Art Vandelay", - }, - } - ] - } - } - ) - - -@pytest.mark.parametrize("formatted_name", [None, {}]) -def test_when_formatted_name_type_is_invalid__validation_error_is_raised( - formatted_name, -): - with pytest.raises(ValidationError): - ContactMessageBodyFactory.build( - **{ - "content": { - "contacts": [ - { - "name": { - "firstName": "First Name", - "formattedName": formatted_name, - }, - } - ] - } - } - ) - - -@pytest.mark.parametrize("test_type", ["", {}, "TEST"]) -def test_when_phones_type_is_invalid__validation_error_is_raised(test_type): - with pytest.raises(ValidationError): - ContactMessageBodyFactory.build( - **{ - "content": { - "contacts": [ - { - "name": { - "firstName": "Art", - "formattedName": "Art Vandelay", - }, - "phones": [{"type": test_type}], - } - ] - } - } - ) - - -@pytest.mark.parametrize("test_type", ["", {}, "TEST"]) -def test_when_urls_type_is_invalid__validation_error_is_raised(test_type): - with pytest.raises(ValidationError): - ContactMessageBodyFactory.build( - **{ - "content": { - "contacts": [ - { - "name": { - "firstName": "Art", - "formattedName": "Art Vandelay", - }, - "urls": [{"type": test_type}], - } - ] - } - } - ) - - -@pytest.mark.parametrize("birthday", ["10-28-1950", "13-02-1911"]) -def test_when_birthday_is_invalid__validation_error_is_raised(birthday): - with pytest.raises(ValidationError): - ContactMessageBodyFactory.build( - **{ - "content": { - "contacts": [ - { - "name": { - "firstName": "Art", - "formattedName": "Art Vandelay", - }, - "birthday": birthday, - } - ] - } - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - ContactMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": { - "contacts": [ - { - "addresses": [ - { - "street": "Istarska", - "city": "Vodnjan", - "zip": "52215", - "country": "Croatia", - "countryCode": "HR", - "type": "WORK", - }, - { - "street": "Istarska", - "city": "Vodnjan", - "zip": "52215", - "country": "Croatia", - "countryCode": "HR", - "type": "HOME", - }, - ], - "birthday": "2010-01-01", - "emails": [ - {"email": "John.Smith@example.com", "type": "WORK"}, - { - "email": "John.Smith.priv@example.com", - "type": "HOME", - }, - ], - "name": { - "firstName": "John", - "lastName": "Smith", - "middleName": "B", - "namePrefix": "Mr.", - "formattedName": "Mr. John Smith", - }, - "org": { - "company": "Company Name", - "department": "Department", - "title": "Director", - }, - "phones": [ - { - "phone": "+441134960019", - "type": "HOME", - "waId": "441134960019", - }, - { - "phone": "+441134960000", - "type": "WORK", - "waId": "441134960000", - }, - ], - "urls": [ - { - "url": "http://example.com/John.Smith", - "type": "WORK", - }, - { - "url": "http://example.com/home/John.Smith", - "type": "HOME", - }, - ], - } - ], - }, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_core_models.py b/tests/whatsapp/models/test_core_models.py deleted file mode 100644 index c32441d..0000000 --- a/tests/whatsapp/models/test_core_models.py +++ /dev/null @@ -1,56 +0,0 @@ -import pytest -from pydantic import AnyHttpUrl -from pydantic.error_wrappers import ValidationError -from pydantic_factories import ModelFactory - -from infobip_channels.core.models import Authentication -from infobip_channels.whatsapp.channel import WhatsAppChannel -from infobip_channels.whatsapp.models.body.core import MessageBody -from tests.conftest import get_random_string - - -class MessageBodyFactory(ModelFactory): - __model__ = MessageBody - - -@pytest.mark.parametrize( - "base_url", - [AnyHttpUrl("123.api.infobip.com", scheme="http"), "https://123.api.infobip.com"], -) -def test_validate_auth_params_returns_authentication_instance(base_url): - auth_object = WhatsAppChannel.validate_auth_params(base_url, "api_key") - assert isinstance(auth_object, Authentication) is True - - -@pytest.mark.parametrize("from_number", [None, "", {}, get_random_string(25)]) -def test_when_from_number_is_invalid__validation_error_is_raised(from_number): - with pytest.raises(ValidationError): - MessageBodyFactory.build(**{"from": from_number}) - - -@pytest.mark.parametrize("to", [None, "", {}, get_random_string(25)]) -def test_when_to_number_is_invalid__validation_error_is_raised(to): - with pytest.raises(ValidationError): - MessageBodyFactory.build(**{"to": to}) - - -@pytest.mark.parametrize("callback_data", [{}, get_random_string(4001)]) -def test_when_callback_data_is_invalid__validation_error_is_raised( - callback_data, -): - with pytest.raises(ValidationError): - MessageBodyFactory.build(**{"callbackData": callback_data}) - - -@pytest.mark.parametrize("message_id", [{}, get_random_string(51)]) -def test_when_message_id_is_invalid__validation_error_is_raised(message_id): - with pytest.raises(ValidationError): - MessageBodyFactory.build(**{"messageId": message_id}) - - -@pytest.mark.parametrize( - "notify_url", [{}, f"http://myserver.com/{get_random_string(2029)}"] -) -def test_when_notify_url_is_invalid__validation_error_is_raised(notify_url): - with pytest.raises(ValidationError): - MessageBodyFactory.build(**{"notifyUrl": notify_url}) diff --git a/tests/whatsapp/models/test_create_template.py b/tests/whatsapp/models/test_create_template.py deleted file mode 100644 index 8177a30..0000000 --- a/tests/whatsapp/models/test_create_template.py +++ /dev/null @@ -1,354 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.create_template import CreateTemplate -from tests.conftest import get_random_string -from tests.whatsapp.conftest import ( - CreateTemplateBodyFactory, - CreateTemplatesPathParametersFactory, -) - - -@pytest.mark.parametrize("sender", [None, {}]) -def test_when_sender_is_invalid__validation_error_is_raised(sender): - with pytest.raises(ValidationError): - CreateTemplatesPathParametersFactory.build(**{"sender": sender}) - - -@pytest.mark.parametrize( - "name", - [ - None, - "", - {}, - "template name !!", - "template_name_example 2", - "Template_Name_Example", - ], -) -def test_when_name_is_invalid__validation_error_is_raised(name): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": name, - "language": "en", - "category": "OTP", - "structure": { - "body": {"text": "body {{1}} content", "examples": ["example"]} - }, - } - ) - - -@pytest.mark.parametrize("language", [None, "", {}, "bla"]) -def test_when_language_is_invalid__validation_error_is_raised(language): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": language, - "category": "OTP", - "structure": { - "body": {"text": "body {{1}} content", "examples": ["example"]} - }, - } - ) - - -@pytest.mark.parametrize("category", [None, "", {}, "INVALID"]) -def test_when_category_is_invalid__validation_error_is_raised(category): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": category, - "structure": { - "body": {"text": "body {{1}} content", "examples": ["example"]} - }, - } - ) - - -@pytest.mark.parametrize( - "structure", - [ - None, - "", - {}, - { - "header": {"format": "IMAGE"}, - "footer": "text", - "buttons": [{"type": "QUICK_REPLY", "text": "test"}], - }, - ], -) -def test_when_structure_is_invalid__validation_error_is_raised(structure): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": structure, - } - ) - - -@pytest.mark.parametrize("header", ["", {}, {"format": "INVALID"}, {"format": "TEXT"}]) -def test_when_header_is_invalid__validation_error_is_raised(header): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "header": header, - "body": {"text": "body {{1}} content", "examples": ["example"]}, - }, - } - ) - - -@pytest.mark.parametrize("body", [None, {}]) -def test_when_body_is_invalid__validation_error_is_raised(body): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "header": {"format": "TEXT", "text": "Text example"}, - "body": body, - }, - } - ) - - -@pytest.mark.parametrize("body_text", [None, {}]) -def test_when_body_text_is_invalid__validation_error_is_raised(body_text): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "header": {"format": "TEXT", "text": "Text example"}, - "body": { - "text": body_text, - }, - }, - } - ) - - -@pytest.mark.parametrize("footer", [{}]) -def test_when_footer_is_invalid__validation_error_is_raised(footer): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "header": {"format": "TEXT", "text": "Text example"}, - "body": {"text": "body {{1}} content", "examples": ["example"]}, - "footer": footer, - }, - } - ) - - -@pytest.mark.parametrize("footer_text", [{}, get_random_string(61)]) -def test_when_footer_text_is_invalid__validation_error_is_raised(footer_text): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "header": {"format": "TEXT", "text": "Text example"}, - "body": {"text": "body {{1}} content", "examples": ["example"]}, - "footer": {"text": footer_text}, - }, - } - ) - - -@pytest.mark.parametrize( - "buttons", - [ - [{"type": "QUICK_REPLY", "text": "test"} for _ in range(4)], - [ - {"type": "QUICK_REPLY", "text": "test"}, - {"type": "URL", "text": "test url", "url": "http://url.com"}, - ], - [ - {"type": "URL", "text": "test url", "url": "http://url.com"}, - {"type": "URL", "text": "test url 2", "url": "http://url2.com"}, - ], - [ - {"type": "PHONE_NUMBER", "text": "number", "phoneNumber": "456321"}, - {"type": "PHONE_NUMBER", "text": "number 2", "phoneNumber": "456322"}, - ], - ], -) -def test_when_buttons_is_invalid__validation_error_is_raised(buttons): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "body": {"text": "body {{1}} content", "examples": ["example"]}, - "buttons": buttons, - }, - } - ) - - -@pytest.mark.parametrize("button_type", [None, "", {}, "TEST"]) -def test_when_button_type_is_invalid__validation_error_is_raised(button_type): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "body": {"text": "body {{1}} content", "examples": ["example"]}, - "buttons": [{"type": button_type}], - }, - } - ) - - -@pytest.mark.parametrize("text", [None, {}, get_random_string(201)]) -def test_when_quick_reply_button_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "header": {"format": "TEXT", "text": "Text example"}, - "body": {"text": "body {{1}} content", "examples": ["example"]}, - "buttons": [{"type": "QUICK_REPLY", "text": text}], - }, - } - ) - - -@pytest.mark.parametrize("text", [None, {}, get_random_string(201)]) -def test_when_phone_number_button_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "header": {"format": "TEXT", "text": "Text example"}, - "body": {"text": "body {{1}} content", "examples": ["example"]}, - "buttons": [ - {"type": "PHONE_NUMBER", "text": text, "phoneNumber": "324561"} - ], - }, - } - ) - - -@pytest.mark.parametrize("number", [None, {}]) -def test_when_phone_number_button_number_is_invalid__validation_error_is_raised(number): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "header": {"format": "TEXT", "text": "Text example"}, - "body": {"text": "body {{1}} content", "examples": ["example"]}, - "buttons": [ - {"type": "PHONE_NUMBER", "text": "test", "phoneNumber": number} - ], - }, - } - ) - - -@pytest.mark.parametrize("text", [None, {}, get_random_string(201)]) -def test_when_url_button_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "header": {"format": "TEXT", "text": "Text example"}, - "body": {"text": "body {{1}} content", "examples": ["example"]}, - "buttons": [ - {"type": "URL", "text": text, "url": "https://url.com"} - ], - }, - } - ) - - -@pytest.mark.parametrize( - "url", - [ - None, - "", - {}, - "www.infobip.com/test", - f"http://infobip.com/{get_random_string(2030)}", - ], -) -def test_when_url_button_url_is_invalid__validation_error_is_raised(url): - with pytest.raises(ValidationError): - CreateTemplateBodyFactory.build( - **{ - "name": "examplename", - "language": "en", - "category": "OTP", - "structure": { - "header": {"format": "TEXT", "text": "Text example"}, - "body": {"text": "body {{1}} content", "examples": ["example"]}, - "buttons": [{"type": "URL", "text": "Text example", "url": url}], - }, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - CreateTemplate( - **{ - "name": "exampl_ename", - "language": "en", - "category": "OTP", - "structure": { - "header": {"format": "TEXT", "text": "Text example"}, - "body": {"text": "body {{1}} content", "examples": ["example"]}, - "footer": {"text": "footer content"}, - "buttons": [ - {"type": "URL", "text": "url", "url": "http://url.com"}, - { - "type": "PHONE_NUMBER", - "text": "number", - "phone_number": "38595873341", - }, - ], - }, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_delete_template.py b/tests/whatsapp/models/test_delete_template.py deleted file mode 100644 index bf115cb..0000000 --- a/tests/whatsapp/models/test_delete_template.py +++ /dev/null @@ -1,16 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from tests.whatsapp.conftest import DeleteTemplatePathParametersFactory - - -@pytest.mark.parametrize("sender", [None, {}]) -def test_when_sender_is_invalid__validation_error_is_raised(sender): - with pytest.raises(ValidationError): - DeleteTemplatePathParametersFactory.build(**{"sender": sender}) - - -@pytest.mark.parametrize("template_name", [None, {}]) -def test_when_template_name_is_invalid__validation_error_is_raised(template_name): - with pytest.raises(ValidationError): - DeleteTemplatePathParametersFactory.build(**{"templateName": template_name}) diff --git a/tests/whatsapp/models/test_document_message.py b/tests/whatsapp/models/test_document_message.py deleted file mode 100644 index 18c4327..0000000 --- a/tests/whatsapp/models/test_document_message.py +++ /dev/null @@ -1,64 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.core import MessageBody -from infobip_channels.whatsapp.models.body.document_message import DocumentMessageBody -from tests.conftest import get_random_string -from tests.whatsapp.conftest import DocumentMessageBodyFactory - - -def test_document_message_body__is_an_instance_of_message_body(): - assert isinstance(DocumentMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize( - "content", [None, "", {}, {"caption": "caption", "filename": "test"}] -) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - DocumentMessageBodyFactory.build(**{"content": content}) - - -@pytest.mark.parametrize( - "media_url", - [None, "", {}, "ftp://myfile.com", f"http://myfile.com/{get_random_string(2031)}"], -) -def test_when_content_media_url_is_invalid__validation_error_is_raised(media_url): - with pytest.raises(ValidationError): - DocumentMessageBodyFactory.build(**{"content": {"mediaUrl": media_url}}) - - -@pytest.mark.parametrize("caption", [{}, get_random_string(3001)]) -def test_when_content_caption_is_invalid__validation_error_is_raised(caption): - with pytest.raises(ValidationError): - DocumentMessageBodyFactory.build( - **{"content": {"mediaUrl": "http://mymedia.com", "caption": caption}} - ) - - -@pytest.mark.parametrize("filename", [{}, get_random_string(241)]) -def test_when_content_filename_is_invalid__validation_error_is_raised(filename): - with pytest.raises(ValidationError): - DocumentMessageBodyFactory.build( - **{"content": {"mediaUrl": "http://mymedia.com", "filename": filename}} - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - DocumentMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": { - "media_url": "http://document.com", - "caption": "cool tile", - "filename": "doc.pdf", - }, - "notifyUrl": "https://notify.me", - "callbackData": "Some callback data", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_image_message.py b/tests/whatsapp/models/test_image_message.py deleted file mode 100644 index e3b5983..0000000 --- a/tests/whatsapp/models/test_image_message.py +++ /dev/null @@ -1,49 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.core import MessageBody -from infobip_channels.whatsapp.models.body.image_message import ImageMessageBody -from tests.conftest import get_random_string -from tests.whatsapp.conftest import ImageMessageBodyFactory - - -def test_image_message_body__is_an_instance_of_message_body(): - assert isinstance(ImageMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize("content", [None, "", {}, {"caption": "the image"}]) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - ImageMessageBodyFactory.build(**{"content": content}) - - -@pytest.mark.parametrize( - "media_url", - [None, "", {}, "ftp://myfile.com", f"http://myfile.com/{get_random_string(2031)}"], -) -def test_when_content_media_url_is_invalid__validation_error_is_raised(media_url): - with pytest.raises(ValidationError): - ImageMessageBodyFactory.build(**{"content": {"mediaUrl": media_url}}) - - -@pytest.mark.parametrize("caption", [{}, get_random_string(3001)]) -def test_when_content_caption_is_invalid__validation_error_is_raised(caption): - with pytest.raises(ValidationError): - ImageMessageBodyFactory.build( - **{"content": {"mediaUrl": "http://mymedia.com", "caption": caption}} - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - ImageMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": {"media_url": "http://theimage.com"}, - "notifyUrl": "https://notify.me", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_list_message.py b/tests/whatsapp/models/test_list_message.py deleted file mode 100644 index 02944c1..0000000 --- a/tests/whatsapp/models/test_list_message.py +++ /dev/null @@ -1,426 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.core import MessageBody -from infobip_channels.whatsapp.models.body.list_message import ListMessageBody -from tests.conftest import get_random_string -from tests.whatsapp.conftest import ListMessageBodyFactory - - -@pytest.fixture -def valid_action(): - return { - "action": { - "title": "title", - "sections": [ - { - "title": "title", - "rows": [{"id": "200", "title": "row title"}], - } - ], - }, - } - - -def test_list_message_body__is_an_instance_of_message_body(): - assert isinstance(ListMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize( - "content", - [ - None, - "", - {}, - {"body": {"text": "test"}}, - { - "action": { - "title": "title", - "sections": [ - { - "title": "title", - "rows": [{"id": "200", "title": "row title"}], - } - ], - }, - }, - ], -) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - ListMessageBody( - **{"from": "441134960000", "to": "38598451987", "content": content} - ) - - -@pytest.mark.parametrize("body", [None, "", {}]) -def test_when_body_is_invalid__validation_error_is_raised(body, valid_action): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": {"body": body, **valid_action}, - } - ) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(1025)]) -def test_when_body_text_is_invalid__validation_error_is_raised(text, valid_action): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": {"body": {"text": text}, **valid_action}, - } - ) - - -@pytest.mark.parametrize( - "action", - [ - None, - "", - {}, - {"title": "text"}, - { - "sections": [ - { - "title": "title", - "rows": [{"id": "200", "title": "row title"}], - } - ] - }, - ], -) -def test_when_action_is_invalid__validation_error_is_raised(action): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": {"body": {"text": "test"}, "action": action}, - } - ) - - -@pytest.mark.parametrize("title", [None, "", {}, get_random_string(21)]) -def test_when_action_title_is_invalid__validation_error_is_raised(title): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": { - "body": {"text": "test"}, - "action": { - "title": title, - "sections": [ - { - "title": "My title", - "rows": [ - {"id": "myId", "title": "T", "description": "Test"} - ], - } - ], - }, - }, - } - ) - - -@pytest.mark.parametrize( - "sections", - [ - None, - "", - {}, - [], - [ - { - "title": "My title", - "rows": [{"id": "myId", "title": "T", "description": "Test"}], - } - for _ in range(11) - ], - [ - {"title": "", "rows": [{"id": "myId", "title": "T"}]}, - {"title": "Title 1", "rows": [{"id": "myId 2", "title": "T"}]}, - ], - [ - {"title": None, "rows": [{"id": "myId", "title": "T"}]}, - {"title": "Title 1", "rows": [{"id": "myId 2", "title": "T"}]}, - ], - [ - {"title": "Title 1", "rows": [{"id": "myId", "title": "T"}]}, - {"title": "Title 2", "rows": [{"id": "myId", "title": "T"}]}, - ], - [ - { - "title": "Title 1", - "rows": [{"id": f"myId{i}", "title": f"T{i}"} for i in range(7)], - }, - { - "title": "Title 2", - "rows": [{"id": f"myId{i}", "title": f"T{i}"} for i in range(7, 11)], - }, - ], - ], -) -def test_when_action_sections_is_invalid__validation_error_is_raised(sections): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": { - "body": {"text": "test"}, - "action": {"title": "TEST", "sections": sections}, - }, - } - ) - - -@pytest.mark.parametrize("sections_title", [{}, get_random_string(25)]) -def test_when_sections_title_is_invalid__validation_error_is_raised(sections_title): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": { - "body": {"text": "test"}, - "action": { - "title": "TEST", - "sections": [ - { - "title": sections_title, - "rows": [ - {"id": "myId", "title": "T", "description": "Test"} - ], - } - ], - }, - }, - } - ) - - -@pytest.mark.parametrize( - "rows", - [None, "", {}, [], [{}], [{"id": "12", "title": "T"}, {"id": "12", "title": "T"}]], -) -def test_when_sections_rows_is_invalid__validation_error_is_raised(rows): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": { - "body": {"text": "test"}, - "action": { - "title": "TEST", - "sections": [{"title": "My title", "rows": rows}], - }, - }, - } - ) - - -@pytest.mark.parametrize("row_id", [None, "", {}, get_random_string(201)]) -def test_when_row_id_is_invalid__validation_error_is_raised(row_id): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": { - "body": {"text": "test"}, - "action": { - "title": "TEST", - "sections": [ - { - "title": "My title", - "rows": [ - {"id": row_id, "title": "T", "description": "Test"} - ], - } - ], - }, - }, - } - ) - - -@pytest.mark.parametrize("title", [None, "", {}, get_random_string(25)]) -def test_when_row_title_is_invalid__validation_error_is_raised(title): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": { - "body": {"text": "test"}, - "action": { - "title": "TEST", - "sections": [ - { - "title": "My title", - "rows": [{"id": "123", "title": title}], - } - ], - }, - }, - } - ) - - -@pytest.mark.parametrize("description", [{}, get_random_string(73)]) -def test_when_row_description_is_invalid__validation_error_is_raised(description): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": { - "body": {"text": "test"}, - "action": { - "title": "TEST", - "sections": [ - { - "title": "My title", - "rows": [ - { - "id": "123", - "title": "title", - "description": description, - } - ], - } - ], - }, - }, - } - ) - - -@pytest.mark.parametrize("header_type", [None, "", {}, "TEST"]) -def test_when_header_type_is_invalid__validation_error_is_raised(header_type): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": { - "body": {"text": "test"}, - "action": { - "title": "TEST", - "sections": [ - { - "title": "My title", - "rows": [ - { - "id": "123", - "title": "title", - } - ], - } - ], - }, - "header": {"type": header_type, "text": "TEST"}, - }, - } - ) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(61)]) -def test_when_header_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": { - "body": {"text": "test"}, - "action": { - "title": "TEST", - "sections": [ - { - "title": "My title", - "rows": [ - { - "id": "123", - "title": "title", - } - ], - } - ], - }, - "header": {"type": "TEXT", "text": text}, - }, - } - ) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(61)]) -def test_when_footer_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": { - "body": {"text": "test"}, - "action": { - "title": "TEST", - "sections": [ - { - "title": "My title", - "rows": [ - { - "id": "123", - "title": "title", - } - ], - } - ], - }, - "header": {"type": "TEXT", "text": "TEXT"}, - "footer": {"text": text}, - }, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - ListMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": { - "body": {"text": "Body text"}, - "action": { - "title": "Action title", - "sections": [ - { - "title": "section title", - "rows": [ - { - "id": "1", - "title": "row title", - "description": "row description", - } - ], - } - ], - }, - "header": {"type": "TEXT", "text": "header text"}, - "footer": {"text": "footer text"}, - }, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_location_message.py b/tests/whatsapp/models/test_location_message.py deleted file mode 100644 index 5c5d726..0000000 --- a/tests/whatsapp/models/test_location_message.py +++ /dev/null @@ -1,84 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.core import MessageBody -from infobip_channels.whatsapp.models.body.location_message import LocationMessageBody -from tests.conftest import get_random_string -from tests.whatsapp.conftest import LocationMessageBodyFactory - - -def test_location_message_body__is_an_instance_of_message_body(): - assert isinstance(LocationMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize( - "content", - [ - None, - "", - {}, - {"latitude": 42, "name": "test", "address": "address one"}, - {"longitude": 120, "name": "test", "address": "address one"}, - ], -) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - LocationMessageBodyFactory.build(**{"content": content}) - - -@pytest.mark.parametrize("latitude", [None, "", {}, -90.001, 90.0001]) -def test_when_content_latitude_is_invalid__validation_error_is_raised(latitude): - with pytest.raises(ValidationError): - LocationMessageBodyFactory.build( - **{"content": {"latitude": latitude, "longitude": 120.53}} - ) - - -@pytest.mark.parametrize("longitude", [None, "", {}, -181.0, 181.0]) -def test_when_content_longitude_is_invalid__validation_error_is_raised(longitude): - with pytest.raises(ValidationError): - LocationMessageBodyFactory.build( - **{"content": {"longitude": longitude, "latitude": -50.934}} - ) - - -@pytest.mark.parametrize("name", [{}, get_random_string(1001)]) -def test_when_content_name_is_invalid__validation_error_is_raised(name): - with pytest.raises(ValidationError): - LocationMessageBodyFactory.build( - **{"content": {"longitude": 130.5541, "latitude": -50.934, "name": name}} - ) - - -@pytest.mark.parametrize("address", [{}, get_random_string(1001)]) -def test_when_content_address_is_invalid__validation_error_is_raised(address): - with pytest.raises(ValidationError): - LocationMessageBodyFactory.build( - **{ - "content": { - "longitude": -165.33, - "latitude": -89.205, - "address": address, - } - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - LocationMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": { - "latitude": 83, - "longitude": -103, - "name": "test", - "address": "test", - }, - "callbackData": "Callback data", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_multi_product_message.py b/tests/whatsapp/models/test_multi_product_message.py deleted file mode 100644 index 0c154b7..0000000 --- a/tests/whatsapp/models/test_multi_product_message.py +++ /dev/null @@ -1,379 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.core import MessageBody -from infobip_channels.whatsapp.models.body.multi_product_message import ( - MultiProductMessageBody, -) -from tests.conftest import get_random_string -from tests.whatsapp.conftest import MultiProductMessageBodyFactory - - -def test_multi_product_message_body__is_an_instance_of_message_body(): - assert isinstance(MultiProductMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize( - "content", - [ - None, - "", - {}, - { - "header": {"type": "TEXT", "text": "test"}, - "body": {"text": "test"}, - "footer": {"text": "test"}, - }, - { - "header": {"type": "TEXT", "text": "test"}, - "action": { - "catalogId": "1", - "sections": [{"title": "title", "productRetailerIds": ["1"]}], - }, - "footer": {"text": "test"}, - }, - { - "body": {"text": "test"}, - "action": { - "catalogId": "1", - "sections": [{"title": "title", "productRetailerIds": ["1"]}], - }, - "footer": {"text": "test"}, - }, - ], -) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": content, - } - ) - - -@pytest.mark.parametrize("header", [None, "", {}, {"type": "TEXT"}, {"text": "test"}]) -def test_when_header_is_invalid__validation_error_is_raised(header): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": header, - "body": {"text": "Some text"}, - "action": { - "catalogId": "1", - "sections": [ - { - "title": "Title", - "productRetailerIds": ["id 2"], - }, - ], - }, - }, - } - ) - - -@pytest.mark.parametrize("header_type", [None, "", {}, "TEST"]) -def test_when_header_type_is_invalid__validation_error_is_raised(header_type): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": {"type": header_type, "text": "Some text"}, - "body": {"text": "Some text"}, - "action": { - "catalogId": "1", - "sections": [ - { - "title": "Title", - "productRetailerIds": ["id 2"], - }, - { - "title": "Title 2", - "productRetailerIds": ["id 2", "id 3"], - }, - ], - }, - }, - } - ) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(61)]) -def test_when_header_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": {"type": "TEXT", "text": text}, - "body": {"text": "Some text"}, - "action": { - "catalogId": "1", - "sections": [ - { - "title": "Title", - "productRetailerIds": ["id 2"], - }, - { - "title": "Title 2", - "productRetailerIds": ["id 2", "id 3"], - }, - ], - }, - }, - } - ) - - -@pytest.mark.parametrize("body", [None, "", {}]) -def test_when_body_is_invalid__validation_error_is_raised(body): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": {"type": "TEXT", "text": "Some text"}, - "body": body, - "action": { - "catalogId": "1", - "sections": [ - { - "title": "Title", - "productRetailerIds": ["id 2"], - }, - { - "title": "Title 2", - "productRetailerIds": ["id 2", "id 3"], - }, - ], - }, - }, - } - ) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(1025)]) -def test_when_body_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": {"type": "TEXT", "text": "Some text"}, - "body": {"text": text}, - "action": { - "catalogId": "1", - "sections": [ - { - "title": "Title", - "productRetailerIds": ["id 2"], - }, - { - "title": "Title 2", - "productRetailerIds": ["id 2", "id 3"], - }, - ], - }, - }, - } - ) - - -@pytest.mark.parametrize( - "action", - [ - None, - "", - {}, - {"catalogId": "1"}, - {"sections": [{"title": "title", "productRetailerIds": ["1", "2"]}]}, - ], -) -def test_when_action_is_invalid__validation_error_is_raised(action): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": {"type": "TEXT", "text": "Some text"}, - "body": {"text": "Some text"}, - "action": action, - }, - } - ) - - -@pytest.mark.parametrize("catalog_id", [None, {}]) -def test_when_action_catalog_id_is_invalid__validation_error_is_raised(catalog_id): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": {"type": "TEXT", "text": "Some text"}, - "body": {"text": "Some text"}, - "action": { - "catalogId": catalog_id, - "sections": [ - { - "title": "Title", - "productRetailerIds": ["id 2"], - }, - { - "title": "Title 2", - "productRetailerIds": ["id 2", "id 3"], - }, - ], - }, - }, - } - ) - - -@pytest.mark.parametrize( - "sections", - [ - None, - "", - {}, - [], - [{"title": "Title", "productRetailerIds": ["1", "2"]} for _ in range(11)], - [ - {"title": "", "productRetailerIds": ["1", "2"]}, - {"title": "Title 1", "productRetailerIds": ["3", "4"]}, - ], - [ - {"title": None, "productRetailerIds": ["1", "2"]}, - {"title": "Title 1", "productRetailerIds": ["3", "4"]}, - ], - ], -) -def test_when_action_sections_is_invalid__validation_error_is_raised(sections): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": {"type": "TEXT", "text": "Some text"}, - "body": {"text": "Some text"}, - "action": { - "catalogId": "1", - "sections": sections, - }, - }, - } - ) - - -@pytest.mark.parametrize("sections_title", [{}, get_random_string(25)]) -def test_when_sections_title_is_invalid__validation_error_is_raised(sections_title): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": {"type": "TEXT", "text": "Some text"}, - "body": {"text": "Some text"}, - "action": { - "catalogId": "1", - "sections": [ - { - "title": sections_title, - "productRetailerIds": ["id 2"], - }, - ], - }, - }, - } - ) - - -@pytest.mark.parametrize("product_retailer_id", [None, "", {}]) -def test_when_sections_product_retailer_id_is_invalid__validation_error_is_raised( - product_retailer_id, -): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": {"type": "TEXT", "text": "Some text"}, - "body": {"text": "Some text"}, - "action": { - "catalogId": "1", - "sections": [ - { - "title": "Title", - "productRetailerIds": product_retailer_id, - }, - ], - }, - }, - } - ) - - -@pytest.mark.parametrize("footer_text", [None, "", {}, get_random_string(61)]) -def test_when_footer_text_is_invalid__validation_error_is_raised(footer_text): - with pytest.raises(ValidationError): - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": {"type": "TEXT", "text": "Some text"}, - "body": {"text": "Some text"}, - "action": { - "catalogId": "1", - "sections": [ - { - "title": "Title", - "productRetailerIds": ["id 2"], - }, - ], - }, - "footer": {"text": footer_text}, - }, - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - MultiProductMessageBody( - **{ - "from": "1234", - "to": "6789", - "content": { - "header": {"type": "TEXT", "text": "Some text"}, - "body": {"text": "Some text"}, - "action": { - "catalogId": "1", - "sections": [ - { - "title": "Title", - "productRetailerIds": ["id 2"], - }, - ], - }, - "footer": {"text": "footer"}, - }, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_product_message.py b/tests/whatsapp/models/test_product_message.py deleted file mode 100644 index fa4c6dd..0000000 --- a/tests/whatsapp/models/test_product_message.py +++ /dev/null @@ -1,144 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.core import MessageBody -from infobip_channels.whatsapp.models.body.product_message import ProductMessageBody -from tests.conftest import get_random_string -from tests.whatsapp.conftest import ProductMessageBodyFactory - - -def test_product_message_body__is_an_instance_of_message_body(): - assert isinstance(ProductMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize( - "content", - [ - None, - "", - {}, - {"body": {"text": "test"}}, - {"footer": {"text": "footer"}}, - {"body": {"text": "test"}, "footer": {"text": "footer"}}, - ], -) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - ProductMessageBodyFactory.build(**{"content": content}) - - -@pytest.mark.parametrize( - "action", - [ - None, - "", - {}, - {"catalogId": "1"}, - {"productRetailerId": "2"}, - ], -) -def test_when_action_is_invalid__validation_error_is_raised(action): - with pytest.raises(ValidationError): - ProductMessageBodyFactory.build(**{"content": {"action": action}}) - - -@pytest.mark.parametrize("catalog_id", [None, {}]) -def test_when_action_catalog_id_is_invalid__validation_error_is_raised(catalog_id): - with pytest.raises(ValidationError): - ProductMessageBodyFactory.build( - **{ - "content": { - "action": {"catalogId": catalog_id, "productRetailerId": "1"} - } - } - ) - - -@pytest.mark.parametrize("product_retailer_id", [None, {}]) -def test_when_action_product_retailer_id_is_invalid__validation_error_is_raised( - product_retailer_id, -): - with pytest.raises(ValidationError): - ProductMessageBodyFactory.build( - **{ - "content": { - "action": { - "catalogId": "1", - "productRetailerId": product_retailer_id, - } - } - } - ) - - -@pytest.mark.parametrize("body", ["", {}]) -def test_when_body_is_invalid__validation_error_is_raised(body): - with pytest.raises(ValidationError): - ProductMessageBodyFactory.build( - **{ - "content": { - "action": {"catalogId": "1", "productRetailerId": "2"}, - "body": body, - } - } - ) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(1025)]) -def test_when_body_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - ProductMessageBodyFactory.build( - **{ - "content": { - "action": {"catalogId": "1", "productRetailerId": "2"}, - "body": {"text": text}, - } - } - ) - - -@pytest.mark.parametrize("footer", ["", {}]) -def test_when_footer_is_invalid__validation_error_is_raised(footer): - with pytest.raises(ValidationError): - ProductMessageBodyFactory.build( - **{ - "content": { - "action": {"catalogId": "1", "productRetailerId": "2"}, - "footer": footer, - } - } - ) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(61)]) -def test_when_footer_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - ProductMessageBodyFactory.build( - **{ - "content": { - "action": {"catalogId": "1", "productRetailerId": "2"}, - "footer": {"text": text}, - } - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - ProductMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": { - "body": {"text": "Body text"}, - "action": { - "catalogId": "1", - "productRetailerId": "2", - }, - "footer": {"text": "footer text"}, - }, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_sticker_message.py b/tests/whatsapp/models/test_sticker_message.py deleted file mode 100644 index 0903670..0000000 --- a/tests/whatsapp/models/test_sticker_message.py +++ /dev/null @@ -1,42 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.core import MessageBody -from infobip_channels.whatsapp.models.body.sticker_message import StickerMessageBody -from tests.conftest import get_random_string -from tests.whatsapp.conftest import StickerMessageBodyFactory - - -def test_sticker_message_body__is_an_instance_of_message_body(): - assert isinstance(StickerMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize("content", [None, "", {}]) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - StickerMessageBodyFactory.build(**{"content": content}) - - -@pytest.mark.parametrize( - "media_url", - [None, "", {}, "ftp://myfile.com", f"http://myfile.com/{get_random_string(2031)}"], -) -def test_when_content_media_url_is_invalid__validation_error_is_raised(media_url): - with pytest.raises(ValidationError): - StickerMessageBodyFactory.build(**{"content": {"mediaUrl": media_url}}) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - StickerMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": {"media_url": "https://some.file.com"}, - "callbackData": "Callback data", - "notify_url": "https://www.example.com/whatsapp", - }, - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_template_message.py b/tests/whatsapp/models/test_template_message.py deleted file mode 100644 index 2cce54f..0000000 --- a/tests/whatsapp/models/test_template_message.py +++ /dev/null @@ -1,727 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.core import MessageBody -from infobip_channels.whatsapp.models.body.template_message import ( - Message, - TemplateMessageBody, -) -from tests.conftest import get_random_string - - -def test_templates_message_body__is_an_instance_of_message_body(): - assert ( - isinstance( - Message( - **{ - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "template_name", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "buttons": [ - {"type": "QUICK_REPLY", "parameter": "button 1"}, - {"type": "QUICK_REPLY", "parameter": "button 2"}, - ], - }, - "language": "en", - }, - "sms_failover": {"from_number": "38599543122", "text": "help!"}, - }, - ), - MessageBody, - ) - is True - ) - - -@pytest.mark.parametrize("messages", [None, {}, [{}]]) -def test_when_messages_are_invalid__validation_error_is_raised(messages): - with pytest.raises(ValidationError): - TemplateMessageBody(**{"messages": messages}) - - -@pytest.mark.parametrize("bulk_id", [{}, get_random_string(101)]) -def test_when_bulk_id_is_invalid__validation_error_is_raised(bulk_id): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "template_name", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - }, - "language": "en", - }, - }, - ], - "bulkId": bulk_id, - } - ) - - -@pytest.mark.parametrize( - "content", - [ - None, - "", - {}, - {"templateName": "name"}, - {"templateData": {"body": {"placeholders": ["First Value"]}}}, - {"language": "en"}, - { - "templateName": "name", - "templateData": {"body": {"placeholders": ["First Value"]}}, - }, - {"templateName": "name", "language": "en"}, - { - "language": "en", - "templateData": {"body": {"placeholders": ["First Value"]}}, - }, - ], -) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - {"from": "441134960000", "to": "38595671032", "content": content}, - ], - } - ) - - -@pytest.mark.parametrize( - "template_name", - [ - None, - "", - {}, - f"template_{504 * 'a'}", - "template name !!", - "template_name_example 2", - "Template_Name_Example", - ], -) -def test_when_template_name_is_invalid__validation_error_is_raised(template_name): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": template_name, - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize( - "template_data", - [ - None, - "", - {}, - {"header": {"type": "TEXT", "placeholder": "value"}}, - {"buttons": [{"type": "QUICK_REPLY", "parameter": "test"}]}, - ], -) -def test_when_template_data_is_invalid__validation_error_is_raised(template_data): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": template_data, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize("language", [None, "", {}]) -def test_when_language_is_invalid__validation_error_is_raised(language): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - }, - "language": language, - }, - }, - ], - } - ) - - -@pytest.mark.parametrize("body", [None, "", {}]) -def test_when_body_is_invalid__validation_error_is_raised(body): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": {"body": body}, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize("placeholders", [None, "", {}, [""], [None]]) -def test_when_placeholders_is_invalid__validation_error_is_raised(placeholders): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": {"body": {"placeholders": placeholders}}, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize("header_type", [None, "", {}, "INVALID"]) -def test_when_header_type_is_invalid__validation_error_is_raised(header_type): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": header_type, - "mediaUrl": "https://test_file.png", - }, - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize("placeholder", [None, {}]) -def test_when_text_placeholder_is_invalid__validation_error_is_raised(placeholder): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": {"type": "TEXT", "placeholder": placeholder}, - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize( - "media_url", - [ - None, - "", - {}, - "www.missing-scheme.com", - "ftp://myfile.com", - f"http://myfile.com/{get_random_string(2031)}", - ], -) -def test_when_document_media_url_is_invalid__validation_error_is_raised(media_url): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "DOCUMENT", - "mediaUrl": media_url, - "filename": "Test", - }, - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize("filename", [None, "", {}, get_random_string(241)]) -def test_when_document_filename_is_invalid__validation_error_is_raised(filename): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "DOCUMENT", - "mediaUrl": "https://test_file.png", - "filename": filename, - }, - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize( - "media_url", - [ - None, - "", - {}, - "www.missing-scheme.com", - "ftp://myfile.com", - f"http://myfile.com/{get_random_string(2031)}", - ], -) -def test_when_image_media_url_is_invalid__validation_error_is_raised(media_url): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "IMAGE", - "mediaUrl": media_url, - }, - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize( - "media_url", - [ - None, - "", - {}, - "www.missing-scheme.com", - "ftp://myfile.com", - f"http://myfile.com/{get_random_string(2031)}", - ], -) -def test_when_video_media_url_is_invalid__validation_error_is_raised(media_url): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "VIDEO", - "mediaUrl": media_url, - }, - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize("latitude", [None, "", {}, -91, 91]) -def test_when_location_latitude_is_invalid__validation_error_is_raised(latitude): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "LOCATION", - "latitude": latitude, - "longitude": 0, - }, - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize("longitude", [None, "", {}, -181, 181]) -def test_when_location_longitude_is_invalid__validation_error_is_raised(longitude): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "LOCATION", - "latitude": 0, - "longitude": longitude, - }, - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize( - "buttons", - [ - [{"type": "QUICK_REPLY", "parameter": "test"} for _ in range(4)], - [ - {"type": "QUICK_REPLY", "parameter": "test"}, - {"type": "URL", "parameter": "test url"}, - ], - [ - {"type": "URL", "parameter": "test url 1"}, - {"type": "URL", "parameter": "test url 2"}, - ], - ], -) -def test_when_buttons_is_invalid__validation_error_is_raised(buttons): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "IMAGE", - "mediaUrl": "https://test_file.png", - }, - "buttons": buttons, - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize("buttons_type", [None, "", {}, "INVALID"]) -def test_when_buttons_type_is_invalid__validation_error_is_raised(buttons_type): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "IMAGE", - "mediaUrl": "https://test_file.png", - }, - "buttons": [ - { - "type": buttons_type, - "parameter": "https://Test.com", - } - ], - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize("button_parameter", [None, "", {}, get_random_string(129)]) -def test_when_quick_reply_button_parameter_is_invalid__validation_error_is_raised( - button_parameter, -): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "IMAGE", - "mediaUrl": "https://test_file.png", - }, - "buttons": [ - { - "type": "QUICK_REPLY", - "parameter": button_parameter, - } - ], - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize("button_parameter", [None, {}]) -def test_when_url_button_parameter_is_invalid__validation_error_is_raised( - button_parameter, -): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "IMAGE", - "mediaUrl": "https://test_file.png", - }, - "buttons": [ - { - "type": "URL", - "parameter": button_parameter, - } - ], - }, - "language": "en", - }, - }, - ], - } - ) - - -@pytest.mark.parametrize( - "sms_failover", - [{}, {"from": "441134960000"}, {"text": "test text"}], -) -def test_when_sms_failover_is_invalid__validation_error_is_raised(sms_failover): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "IMAGE", - "mediaUrl": "https://test_file.png", - }, - }, - "language": "en", - }, - "smsFailover": sms_failover, - }, - ], - } - ) - - -@pytest.mark.parametrize("sms_failover_from", [None, "", {}, get_random_string(25)]) -def test_when_sms_failover_from_is_invalid__validation_error_is_raised( - sms_failover_from, -): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - }, - "language": "en", - }, - "smsFailover": {"from": sms_failover_from, "text": "Test"}, - }, - ], - } - ) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(4097)]) -def test_when_sms_failover_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "content": { - "template_name": "boarding_pass", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - }, - "language": "en", - }, - "smsFailover": {"from": "441134960000", "text": text}, - }, - ], - } - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - TemplateMessageBody( - **{ - "messages": [ - { - "from": "441134960000", - "to": "38595671032", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": { - "template_name": "template_name", - "template_data": { - "body": {"placeholders": ["value 1", "value 2"]}, - "header": { - "type": "IMAGE", - "media_url": "https://image.com", - }, - "buttons": [ - {"type": "QUICK_REPLY", "parameter": "button 1"}, - {"type": "QUICK_REPLY", "parameter": "button 2"}, - ], - }, - "language": "en", - }, - "sms_failover": {"from_number": "38599543122", "text": "help!"}, - }, - { - "from": "441134960000", - "to": "38598311460", - "content": { - "templateName": "template_name_2", - "templateData": { - "body": {"placeholders": []}, - "header": { - "type": "TEXT", - "placeholder": "placeholder text", - }, - "buttons": [{"type": "URL", "parameter": "url button"}], - }, - "language": "en", - }, - }, - ], - "bulk_id": "123-456-786", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_text_message.py b/tests/whatsapp/models/test_text_message.py deleted file mode 100644 index c63af7c..0000000 --- a/tests/whatsapp/models/test_text_message.py +++ /dev/null @@ -1,45 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.core import MessageBody -from infobip_channels.whatsapp.models.body.text_message import TextMessageBody -from tests.conftest import get_random_string -from tests.whatsapp.conftest import TextMessageBodyFactory - - -def test_text_message_body__is_an_instance_of_message_body(): - assert isinstance(TextMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize("content", [None, "", {}, {"previewUrl": False}]) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - TextMessageBodyFactory.build(**{"content": content}) - - -@pytest.mark.parametrize("text", [None, "", {}, get_random_string(4097)]) -def test_when_content_text_is_invalid__validation_error_is_raised(text): - with pytest.raises(ValidationError): - TextMessageBodyFactory.build(**{"content": {"text": text}}) - - -@pytest.mark.parametrize("preview_url", ["", {}]) -def test_when_content_preview_url_is_invalid__validation_error_is_raised(preview_url): - with pytest.raises(ValidationError): - TextMessageBodyFactory.build( - **{"content": {"text": "text", "previewUrl": preview_url}} - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - TextMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "content": {"text": "a test message", "previewUrl": True}, - "callbackData": "Some data", - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") diff --git a/tests/whatsapp/models/test_video_message.py b/tests/whatsapp/models/test_video_message.py deleted file mode 100644 index 3b37d2a..0000000 --- a/tests/whatsapp/models/test_video_message.py +++ /dev/null @@ -1,48 +0,0 @@ -import pytest -from pydantic.error_wrappers import ValidationError - -from infobip_channels.whatsapp.models.body.core import MessageBody -from infobip_channels.whatsapp.models.body.video_message import VideoMessageBody -from tests.conftest import get_random_string -from tests.whatsapp.conftest import VideoMessageBodyFactory - - -def test_video_message_body__is_an_instance_of_message_body(): - assert isinstance(VideoMessageBodyFactory.build(), MessageBody) is True - - -@pytest.mark.parametrize("content", [None, "", {}, {"caption": "a caption"}]) -def test_when_content_is_invalid__validation_error_is_raised(content): - with pytest.raises(ValidationError): - VideoMessageBodyFactory.build(**{"content": content}) - - -@pytest.mark.parametrize( - "media_url", - [None, "", {}, "ftp://myfile.com", f"http://myfile.com/{get_random_string(2031)}"], -) -def test_when_content_media_url_is_invalid__validation_error_is_raised(media_url): - with pytest.raises(ValidationError): - VideoMessageBodyFactory.build(**{"content": {"mediaUrl": media_url}}) - - -@pytest.mark.parametrize("caption", [{}, get_random_string(3001)]) -def test_when_content_caption_is_invalid__validation_error_is_raised(caption): - with pytest.raises(ValidationError): - VideoMessageBodyFactory.build( - **{"content": {"mediaUrl": "http://mymedia.com", "caption": caption}} - ) - - -def test_when_input_data_is_valid__validation_error_is_not_raised(): - try: - VideoMessageBody( - **{ - "from": "441134960000", - "to": "38598451987", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": {"mediaUrl": "http://wap.com"}, - } - ) - except ValidationError: - pytest.fail("Unexpected ValidationError raised") From e10dffb4c51ab2519d96e31e7b65c7f9548940a0 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Wed, 3 May 2023 16:03:19 -0600 Subject: [PATCH 02/18] Add MMS client and sample endpoint with query params --- api/mms.py | 26 +++++++++ api/sms.py | 4 +- client.py | 3 + models/__init__.py | 4 +- ...s_get_inbound_messages_query_parameters.py | 55 +++++++++++++++++++ models/mms_inbound_report_response.py | 10 ++-- models/sms_advanced_textual_request.py | 10 ++-- samples/test_mms_live.py | 27 +++++++++ samples/test_sms_live.py | 6 +- 9 files changed, 128 insertions(+), 17 deletions(-) create mode 100644 api/mms.py create mode 100644 models/mms_get_inbound_messages_query_parameters.py create mode 100644 samples/test_mms_live.py diff --git a/api/mms.py b/api/mms.py new file mode 100644 index 0000000..ecd5261 --- /dev/null +++ b/api/mms.py @@ -0,0 +1,26 @@ +from collections.abc import Awaitable + +from httpx import Response, AsyncClient + +from models.mms_get_inbound_messages_query_parameters import GetInboundMessagesQueryParameters + + +class MMSClient: + PATH_GET_INBOUND_MESSAGES = "/mms/1/inbox/reports" + + def __init__(self, client: AsyncClient): + self.client = client + + def get_inbound_messages( + self, + query_parameters: GetInboundMessagesQueryParameters, + ) -> Awaitable[Response]: + """Get inbound messages + + :param query_parameters: Query parameters for getting inbound messages + """ + + return self.client.get( + self.PATH_GET_INBOUND_MESSAGES, + params=query_parameters.to_dict(), + ) diff --git a/api/sms.py b/api/sms.py index 3d401c1..f6a4f97 100644 --- a/api/sms.py +++ b/api/sms.py @@ -2,7 +2,7 @@ from httpx import AsyncClient, Response -from models import SendRequestBody +from models import SendSMSRequestBody from models.sms_preview_request import PreviewSMSRequestBody @@ -30,7 +30,7 @@ def preview_message( def send( self, - request_body: SendRequestBody, + request_body: SendSMSRequestBody, ) -> Awaitable[Response]: """Send SMS message diff --git a/client.py b/client.py index dade456..e518aff 100644 --- a/client.py +++ b/client.py @@ -1,5 +1,7 @@ from os import getenv from httpx import AsyncClient + +from api.mms import MMSClient from api.sms import SMSClient @@ -16,3 +18,4 @@ def __init__(self, base_url=None, api_key: str = None): super().__init__(base_url=base_url, headers=headers) self.SMS = SMSClient(self) + self.MMS = MMSClient(self) diff --git a/models/__init__.py b/models/__init__.py index b841123..975e504 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -41,7 +41,7 @@ from models.mms_destination import MmsDestination from models.mms_error import MmsError from models.mms_inbound_report import MmsInboundReport -from models.mms_inbound_report_response import MmsInboundReportResponse +from models.mms_inbound_report_response import MMSInboundReportResponse from models.mms_message_result import MmsMessageResult from models.mms_price import MmsPrice from models.mms_report import MmsReport @@ -203,7 +203,7 @@ ) from models.resource_type import ResourceType from models.sms_advanced_binary_request import SmsAdvancedBinaryRequest -from models.sms_advanced_textual_request import SendRequestBody +from models.sms_advanced_textual_request import SendSMSRequestBody from models.sms_binary_content import SmsBinaryContent from models.sms_binary_message import SmsBinaryMessage from models.sms_bulk_request import SmsBulkRequest diff --git a/models/mms_get_inbound_messages_query_parameters.py b/models/mms_get_inbound_messages_query_parameters.py new file mode 100644 index 0000000..cb205f1 --- /dev/null +++ b/models/mms_get_inbound_messages_query_parameters.py @@ -0,0 +1,55 @@ +from __future__ import annotations + +import json +import pprint +from typing import Optional + +from pydantic import Field +from pydantic.main import BaseModel +from pydantic.types import StrictInt + + +class GetInboundMessagesQueryParameters(BaseModel): + limit: Optional[StrictInt] = Field( + None, + alias="limit", + description="Maximum number of delivery reports that will be returned." + ) + + __properties = [ + "limit", + ] + + class Config: + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> GetInboundMessagesQueryParameters: + """Create an instance of GetInboundMessagesQueryParameters from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, exclude={}, exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> GetInboundMessagesQueryParameters: + """Create an instance of GetInboundMessagesQueryParameters from a dict""" + if obj is None: + return None + + if type(obj) is not dict: + return GetInboundMessagesQueryParameters.parse_obj(obj) + + _obj = GetInboundMessagesQueryParameters.parse_obj({"limit": obj.get("limit")}) + return _obj diff --git a/models/mms_inbound_report_response.py b/models/mms_inbound_report_response.py index 9146096..c013560 100644 --- a/models/mms_inbound_report_response.py +++ b/models/mms_inbound_report_response.py @@ -19,7 +19,7 @@ from models.mms_inbound_report import MmsInboundReport -class MmsInboundReportResponse(BaseModel): +class MMSInboundReportResponse(BaseModel): """NOTE: This class is auto generated by OpenAPI Generator. Ref: https://openapi-generator.tech @@ -42,7 +42,7 @@ def to_json(self) -> str: return json.dumps(self.to_dict()) @classmethod - def from_json(cls, json_str: str) -> MmsInboundReportResponse: + def from_json(cls, json_str: str) -> MMSInboundReportResponse: """Create an instance of MmsInboundReportResponse from a JSON string""" return cls.from_dict(json.loads(json_str)) @@ -59,15 +59,15 @@ def to_dict(self): return _dict @classmethod - def from_dict(cls, obj: dict) -> MmsInboundReportResponse: + def from_dict(cls, obj: dict) -> MMSInboundReportResponse: """Create an instance of MmsInboundReportResponse from a dict""" if obj is None: return None if type(obj) is not dict: - return MmsInboundReportResponse.parse_obj(obj) + return MMSInboundReportResponse.parse_obj(obj) - _obj = MmsInboundReportResponse.parse_obj( + _obj = MMSInboundReportResponse.parse_obj( { "results": [ MmsInboundReport.from_dict(_item) for _item in obj.get("results") diff --git a/models/sms_advanced_textual_request.py b/models/sms_advanced_textual_request.py index bc019fe..3d1ae2d 100644 --- a/models/sms_advanced_textual_request.py +++ b/models/sms_advanced_textual_request.py @@ -22,7 +22,7 @@ from models.sms_url_options import SmsUrlOptions -class SendRequestBody(BaseModel): +class SendSMSRequestBody(BaseModel): """NOTE: This class is auto generated by OpenAPI Generator. Ref: https://openapi-generator.tech @@ -58,7 +58,7 @@ def to_json(self) -> str: return json.dumps(self.to_dict()) @classmethod - def from_json(cls, json_str: str) -> SendRequestBody: + def from_json(cls, json_str: str) -> SendSMSRequestBody: """Create an instance of SmsAdvancedTextualRequest from a JSON string""" return cls.from_dict(json.loads(json_str)) @@ -84,15 +84,15 @@ def to_dict(self): return _dict @classmethod - def from_dict(cls, obj: dict) -> SendRequestBody: + def from_dict(cls, obj: dict) -> SendSMSRequestBody: """Create an instance of SmsAdvancedTextualRequest from a dict""" if obj is None: return None if type(obj) is not dict: - return SendRequestBody.parse_obj(obj) + return SendSMSRequestBody.parse_obj(obj) - _obj = SendRequestBody.parse_obj( + _obj = SendSMSRequestBody.parse_obj( { "bulk_id": obj.get("bulkId"), "messages": [Message.from_dict(_item) for _item in obj.get("messages")] diff --git a/samples/test_mms_live.py b/samples/test_mms_live.py new file mode 100644 index 0000000..79470dc --- /dev/null +++ b/samples/test_mms_live.py @@ -0,0 +1,27 @@ +import unittest + +from client import InfobipAPIClient +from models import MMSInboundReportResponse +from models.mms_get_inbound_messages_query_parameters import GetInboundMessagesQueryParameters + + +class MMSTestCase(unittest.IsolatedAsyncioTestCase): + client = InfobipAPIClient() + + async def test_preview_message(self): + # Create query parameters object and validate its contents. + params = GetInboundMessagesQueryParameters( + limit=10, + ) + + # Call the endpoint and await returned Coroutine + response = await self.client.MMS.get_inbound_messages(params) + + # Parse and validate response if needed. + response_body = MMSInboundReportResponse.from_json(response.text) + + # Do something with the response. + print(response) + print(response_body.results) + + self.assertEqual(response.status_code, 200) diff --git a/samples/test_sms_live.py b/samples/test_sms_live.py index da881a4..5b8d615 100644 --- a/samples/test_sms_live.py +++ b/samples/test_sms_live.py @@ -1,7 +1,7 @@ import unittest from client import InfobipAPIClient -from models import SendRequestBody, Message, Destination +from models import SendSMSRequestBody, Message, Destination from models.sms_preview_request import PreviewSMSRequestBody from models.sms_preview_response import PreviewSMSResponseBody @@ -29,12 +29,12 @@ async def test_preview_message(self): async def test_send_message(self): # Create a request body object and validate its contents. - request_body = SendRequestBody( + request_body = SendSMSRequestBody( messages=[ Message( destinations=[ Destination( - to="523311800428", + to="555555555555", ), ], text="Hello from Infobip Python SDK!", From 2ee94d10cae2b4d255e0f0aadf16908e66ffefa7 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Thu, 4 May 2023 09:01:45 -0600 Subject: [PATCH 03/18] Implement a better structure for better import syntax --- {api => infobip}/__init__.py | 0 infobip/api/__init__.py | 0 {api => infobip/api}/mms.py | 2 +- {api => infobip/api}/sms.py | 4 +- client.py => infobip/client.py | 4 +- infobip/models/__init__.py | 14 + {models => infobip/models}/application.py | 0 {models => infobip/models}/channel.py | 0 {models => infobip/models}/entity.py | 0 {models => infobip/models}/message_error.py | 0 {models => infobip/models}/message_price.py | 0 {models => infobip/models}/message_status.py | 0 .../models}/mms_advanced_message.py | 7 +- .../models}/mms_advanced_message_segment.py | 16 +- .../mms_advanced_message_segment_binary.py | 0 .../mms_advanced_message_segment_link.py | 0 .../mms_advanced_message_segment_smil.py | 0 .../mms_advanced_message_segment_text.py | 0 ...vanced_message_segment_upload_reference.py | 0 .../models}/mms_advanced_request.py | 3 +- .../models}/mms_delivery_day.py | 0 .../models}/mms_delivery_time.py | 0 .../models}/mms_delivery_time_window.py | 5 +- {models => infobip/models}/mms_destination.py | 0 {models => infobip/models}/mms_error.py | 0 ...s_get_inbound_messages_query_parameters.py | 0 .../models}/mms_inbound_report.py | 3 +- .../models}/mms_inbound_report_response.py | 13 +- .../models}/mms_message_result.py | 3 +- {models => infobip/models}/mms_price.py | 0 {models => infobip/models}/mms_report.py | 7 +- .../models}/mms_report_response.py | 3 +- {models => infobip/models}/mms_send_result.py | 3 +- {models => infobip/models}/mms_status.py | 0 .../models}/mms_upload_binary_result.py | 0 .../mms_webhook_inbound_message_segment.py | 4 +- ...ms_webhook_inbound_message_segment_link.py | 0 ...ms_webhook_inbound_message_segment_text.py | 0 .../models}/mms_webhook_inbound_report.py | 5 +- .../mms_webhook_inbound_report_response.py | 3 +- .../models}/mms_webhook_outbound_report.py | 7 +- .../mms_webhook_outbound_report_response.py | 3 +- .../models}/modify_application.py | 0 {models => infobip/models}/modify_entity.py | 0 {models => infobip/models}/number_price.py | 0 .../models}/number_registration_address.py | 0 .../models}/number_registration_brand.py | 3 +- .../number_registration_brand_preview.py | 0 .../number_registration_brand_status.py | 0 .../models}/number_registration_brand_vet.py | 0 ...number_registration_business_identifier.py | 4 +- .../models}/number_registration_campaign.py | 3 +- ..._data_universal_numbering_system_number.py | 5 +- .../number_registration_document_metadata.py | 0 ..._registration_external_ten_dlc_campaign.py | 7 +- ...obal_intermediary_identification_number.py | 5 +- .../number_registration_government_brand.py | 9 +- ...ation_interactive_voice_response_opt_in.py | 0 .../number_registration_keyword_opt_in.py | 0 ...er_registration_legal_entity_identifier.py | 5 +- .../number_registration_network_status.py | 0 .../number_registration_non_profit_brand.py | 9 +- .../number_registration_number_preview.py | 0 .../models}/number_registration_opt_ins.py | 9 +- .../models}/number_registration_page_info.py | 0 ...number_registration_page_response_brand.py | 5 +- ...er_registration_page_response_brand_vet.py | 5 +- ...ber_registration_page_response_campaign.py | 5 +- ...mber_registration_private_company_brand.py | 9 +- ...umber_registration_public_company_brand.py | 9 +- .../number_registration_ten_dlc_campaign.py | 13 +- ...umber_registration_update_brand_request.py | 3 +- ...er_registration_update_campaign_request.py | 0 .../number_registration_verbal_opt_in.py | 0 .../models}/number_registration_web_opt_in.py | 0 {models => infobip/models}/number_response.py | 7 +- .../models}/numbers_auto_response_action.py | 7 +- .../models}/numbers_block_action.py | 5 +- .../models}/numbers_delivery_time_window.py | 0 .../models}/numbers_edit_permissions.py | 0 .../numbers_forward_to_ivr_action_details.py | 5 +- ...numbers_forward_to_subscription_details.py | 5 +- .../models}/numbers_http_forward_action.py | 5 +- .../models}/numbers_mail_forward_action.py | 5 +- .../models}/numbers_mo_action.py | 4 +- .../models}/numbers_mo_configuration.py | 7 +- .../models}/numbers_mo_configurations.py | 3 +- .../models}/numbers_mo_non_forward_action.py | 4 +- .../models}/numbers_no_action.py | 5 +- .../models}/numbers_pull_action.py | 5 +- .../numbers_purchase_number_request.py | 0 .../models}/numbers_response.py | 3 +- .../models}/numbers_smpp_forward_action.py | 5 +- .../numbers_stored_mo_configuration.py | 7 +- .../models}/numbers_use_conversation.py | 0 .../models}/numbers_voice_action_details.py | 4 +- ...ice_call_forward_to_application_details.py | 5 +- ...ers_voice_number_masking_action_details.py | 5 +- .../models}/numbers_voice_setup.py | 3 +- .../models}/page_application.py | 5 +- {models => infobip/models}/page_entity.py | 5 +- {models => infobip/models}/page_info.py | 0 .../models}/page_resource_association.py | 5 +- .../models}/resource_association_request.py | 5 +- .../models}/resource_association_response.py | 5 +- {models => infobip/models}/resource_type.py | 0 .../models}/sms_advanced_binary_request.py | 5 +- .../models}/sms_advanced_textual_request.py | 9 +- .../models}/sms_binary_content.py | 0 .../models}/sms_binary_message.py | 9 +- .../models}/sms_bulk_request.py | 0 .../models}/sms_bulk_response.py | 0 {models => infobip/models}/sms_bulk_status.py | 0 .../models}/sms_bulk_status_response.py | 3 +- .../models}/sms_delivery_day.py | 0 .../models}/sms_delivery_result.py | 3 +- .../models}/sms_delivery_time_from.py | 0 .../models}/sms_delivery_time_to.py | 0 .../models}/sms_delivery_time_window.py | 7 +- {models => infobip/models}/sms_destination.py | 0 {models => infobip/models}/sms_error.py | 0 .../models}/sms_inbound_message.py | 3 +- .../models}/sms_inbound_message_result.py | 3 +- .../models}/sms_india_dlt_options.py | 0 {models => infobip/models}/sms_language.py | 0 .../models}/sms_language_configuration.py | 3 +- {models => infobip/models}/sms_log.py | 7 +- .../models}/sms_logs_response.py | 3 +- {models => infobip/models}/sms_preview.py | 3 +- .../models}/sms_preview_request.py | 0 .../models}/sms_preview_response.py | 3 +- {models => infobip/models}/sms_price.py | 0 .../models}/sms_regional_options.py | 5 +- {models => infobip/models}/sms_report.py | 7 +- {models => infobip/models}/sms_response.py | 3 +- .../models}/sms_response_details.py | 3 +- .../models}/sms_sending_speed_limit.py | 3 +- .../models}/sms_speed_limit_time_unit.py | 0 {models => infobip/models}/sms_status.py | 0 .../models}/sms_textual_message.py | 9 +- {models => infobip/models}/sms_tracking.py | 0 .../models}/sms_turkey_iys_options.py | 0 .../models}/sms_update_status_request.py | 3 +- {models => infobip/models}/sms_url_options.py | 0 .../models}/sms_webhook_inbound_report.py | 3 +- .../sms_webhook_inbound_report_response.py | 3 +- .../models}/sms_webhook_outbound_report.py | 7 +- .../sms_webhook_outbound_report_response.py | 3 +- .../models}/webhook_message_count.py | 0 models/__init__.py | 251 ------------------ samples/test_mms_live.py | 10 +- samples/test_sms_live.py | 10 +- tests/test_sms.py | 2 +- 153 files changed, 198 insertions(+), 526 deletions(-) rename {api => infobip}/__init__.py (100%) create mode 100644 infobip/api/__init__.py rename {api => infobip/api}/mms.py (85%) rename {api => infobip/api}/sms.py (88%) rename client.py => infobip/client.py (87%) create mode 100644 infobip/models/__init__.py rename {models => infobip/models}/application.py (100%) rename {models => infobip/models}/channel.py (100%) rename {models => infobip/models}/entity.py (100%) rename {models => infobip/models}/message_error.py (100%) rename {models => infobip/models}/message_price.py (100%) rename {models => infobip/models}/message_status.py (100%) rename {models => infobip/models}/mms_advanced_message.py (96%) rename {models => infobip/models}/mms_advanced_message_segment.py (93%) rename {models => infobip/models}/mms_advanced_message_segment_binary.py (100%) rename {models => infobip/models}/mms_advanced_message_segment_link.py (100%) rename {models => infobip/models}/mms_advanced_message_segment_smil.py (100%) rename {models => infobip/models}/mms_advanced_message_segment_text.py (100%) rename {models => infobip/models}/mms_advanced_message_segment_upload_reference.py (100%) rename {models => infobip/models}/mms_advanced_request.py (96%) rename {models => infobip/models}/mms_delivery_day.py (100%) rename {models => infobip/models}/mms_delivery_time.py (100%) rename {models => infobip/models}/mms_delivery_time_window.py (95%) rename {models => infobip/models}/mms_destination.py (100%) rename {models => infobip/models}/mms_error.py (100%) rename {models => infobip/models}/mms_get_inbound_messages_query_parameters.py (100%) rename {models => infobip/models}/mms_inbound_report.py (98%) rename {models => infobip/models}/mms_inbound_report_response.py (85%) rename {models => infobip/models}/mms_message_result.py (97%) rename {models => infobip/models}/mms_price.py (100%) rename {models => infobip/models}/mms_report.py (97%) rename {models => infobip/models}/mms_report_response.py (96%) rename {models => infobip/models}/mms_send_result.py (96%) rename {models => infobip/models}/mms_status.py (100%) rename {models => infobip/models}/mms_upload_binary_result.py (100%) rename {models => infobip/models}/mms_webhook_inbound_message_segment.py (97%) rename {models => infobip/models}/mms_webhook_inbound_message_segment_link.py (100%) rename {models => infobip/models}/mms_webhook_inbound_message_segment_text.py (100%) rename {models => infobip/models}/mms_webhook_inbound_report.py (97%) rename {models => infobip/models}/mms_webhook_inbound_report_response.py (96%) rename {models => infobip/models}/mms_webhook_outbound_report.py (96%) rename {models => infobip/models}/mms_webhook_outbound_report_response.py (95%) rename {models => infobip/models}/modify_application.py (100%) rename {models => infobip/models}/modify_entity.py (100%) rename {models => infobip/models}/number_price.py (100%) rename {models => infobip/models}/number_registration_address.py (100%) rename {models => infobip/models}/number_registration_brand.py (99%) rename {models => infobip/models}/number_registration_brand_preview.py (100%) rename {models => infobip/models}/number_registration_brand_status.py (100%) rename {models => infobip/models}/number_registration_brand_vet.py (100%) rename {models => infobip/models}/number_registration_business_identifier.py (98%) rename {models => infobip/models}/number_registration_campaign.py (99%) rename {models => infobip/models}/number_registration_data_universal_numbering_system_number.py (94%) rename {models => infobip/models}/number_registration_document_metadata.py (100%) rename {models => infobip/models}/number_registration_external_ten_dlc_campaign.py (95%) rename {models => infobip/models}/number_registration_global_intermediary_identification_number.py (94%) rename {models => infobip/models}/number_registration_government_brand.py (95%) rename {models => infobip/models}/number_registration_interactive_voice_response_opt_in.py (100%) rename {models => infobip/models}/number_registration_keyword_opt_in.py (100%) rename {models => infobip/models}/number_registration_legal_entity_identifier.py (94%) rename {models => infobip/models}/number_registration_network_status.py (100%) rename {models => infobip/models}/number_registration_non_profit_brand.py (95%) rename {models => infobip/models}/number_registration_number_preview.py (100%) rename {models => infobip/models}/number_registration_opt_ins.py (93%) rename {models => infobip/models}/number_registration_page_info.py (100%) rename {models => infobip/models}/number_registration_page_response_brand.py (95%) rename {models => infobip/models}/number_registration_page_response_brand_vet.py (95%) rename {models => infobip/models}/number_registration_page_response_campaign.py (95%) rename {models => infobip/models}/number_registration_private_company_brand.py (95%) rename {models => infobip/models}/number_registration_public_company_brand.py (96%) rename {models => infobip/models}/number_registration_ten_dlc_campaign.py (96%) rename {models => infobip/models}/number_registration_update_brand_request.py (97%) rename {models => infobip/models}/number_registration_update_campaign_request.py (100%) rename {models => infobip/models}/number_registration_verbal_opt_in.py (100%) rename {models => infobip/models}/number_registration_web_opt_in.py (100%) rename {models => infobip/models}/number_response.py (97%) rename {models => infobip/models}/numbers_auto_response_action.py (93%) rename {models => infobip/models}/numbers_block_action.py (94%) rename {models => infobip/models}/numbers_delivery_time_window.py (100%) rename {models => infobip/models}/numbers_edit_permissions.py (100%) rename {models => infobip/models}/numbers_forward_to_ivr_action_details.py (92%) rename {models => infobip/models}/numbers_forward_to_subscription_details.py (93%) rename {models => infobip/models}/numbers_http_forward_action.py (95%) rename {models => infobip/models}/numbers_mail_forward_action.py (93%) rename {models => infobip/models}/numbers_mo_action.py (99%) rename {models => infobip/models}/numbers_mo_configuration.py (95%) rename {models => infobip/models}/numbers_mo_configurations.py (96%) rename {models => infobip/models}/numbers_mo_non_forward_action.py (98%) rename {models => infobip/models}/numbers_no_action.py (93%) rename {models => infobip/models}/numbers_pull_action.py (93%) rename {models => infobip/models}/numbers_purchase_number_request.py (100%) rename {models => infobip/models}/numbers_response.py (96%) rename {models => infobip/models}/numbers_smpp_forward_action.py (93%) rename {models => infobip/models}/numbers_stored_mo_configuration.py (96%) rename {models => infobip/models}/numbers_use_conversation.py (100%) rename {models => infobip/models}/numbers_voice_action_details.py (99%) rename {models => infobip/models}/numbers_voice_call_forward_to_application_details.py (93%) rename {models => infobip/models}/numbers_voice_number_masking_action_details.py (93%) rename {models => infobip/models}/numbers_voice_setup.py (96%) rename {models => infobip/models}/page_application.py (95%) rename {models => infobip/models}/page_entity.py (96%) rename {models => infobip/models}/page_info.py (100%) rename {models => infobip/models}/page_resource_association.py (95%) rename {models => infobip/models}/resource_association_request.py (96%) rename {models => infobip/models}/resource_association_response.py (96%) rename {models => infobip/models}/resource_type.py (100%) rename {models => infobip/models}/sms_advanced_binary_request.py (95%) rename {models => infobip/models}/sms_advanced_textual_request.py (94%) rename {models => infobip/models}/sms_binary_content.py (100%) rename {models => infobip/models}/sms_binary_message.py (96%) rename {models => infobip/models}/sms_bulk_request.py (100%) rename {models => infobip/models}/sms_bulk_response.py (100%) rename {models => infobip/models}/sms_bulk_status.py (100%) rename {models => infobip/models}/sms_bulk_status_response.py (96%) rename {models => infobip/models}/sms_delivery_day.py (100%) rename {models => infobip/models}/sms_delivery_result.py (96%) rename {models => infobip/models}/sms_delivery_time_from.py (100%) rename {models => infobip/models}/sms_delivery_time_to.py (100%) rename {models => infobip/models}/sms_delivery_time_window.py (93%) rename {models => infobip/models}/sms_destination.py (100%) rename {models => infobip/models}/sms_error.py (100%) rename {models => infobip/models}/sms_inbound_message.py (98%) rename {models => infobip/models}/sms_inbound_message_result.py (97%) rename {models => infobip/models}/sms_india_dlt_options.py (100%) rename {models => infobip/models}/sms_language.py (100%) rename {models => infobip/models}/sms_language_configuration.py (97%) rename {models => infobip/models}/sms_log.py (97%) rename {models => infobip/models}/sms_logs_response.py (97%) rename {models => infobip/models}/sms_preview.py (96%) rename {models => infobip/models}/sms_preview_request.py (100%) rename {models => infobip/models}/sms_preview_response.py (97%) rename {models => infobip/models}/sms_price.py (100%) rename {models => infobip/models}/sms_regional_options.py (94%) rename {models => infobip/models}/sms_report.py (97%) rename {models => infobip/models}/sms_response.py (96%) rename {models => infobip/models}/sms_response_details.py (97%) rename {models => infobip/models}/sms_sending_speed_limit.py (95%) rename {models => infobip/models}/sms_speed_limit_time_unit.py (100%) rename {models => infobip/models}/sms_status.py (100%) rename {models => infobip/models}/sms_textual_message.py (97%) rename {models => infobip/models}/sms_tracking.py (100%) rename {models => infobip/models}/sms_turkey_iys_options.py (100%) rename {models => infobip/models}/sms_update_status_request.py (95%) rename {models => infobip/models}/sms_url_options.py (100%) rename {models => infobip/models}/sms_webhook_inbound_report.py (98%) rename {models => infobip/models}/sms_webhook_inbound_report_response.py (96%) rename {models => infobip/models}/sms_webhook_outbound_report.py (96%) rename {models => infobip/models}/sms_webhook_outbound_report_response.py (96%) rename {models => infobip/models}/webhook_message_count.py (100%) delete mode 100644 models/__init__.py diff --git a/api/__init__.py b/infobip/__init__.py similarity index 100% rename from api/__init__.py rename to infobip/__init__.py diff --git a/infobip/api/__init__.py b/infobip/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/api/mms.py b/infobip/api/mms.py similarity index 85% rename from api/mms.py rename to infobip/api/mms.py index ecd5261..98722e2 100644 --- a/api/mms.py +++ b/infobip/api/mms.py @@ -2,7 +2,7 @@ from httpx import Response, AsyncClient -from models.mms_get_inbound_messages_query_parameters import GetInboundMessagesQueryParameters +from infobip.models.mms_get_inbound_messages_query_parameters import GetInboundMessagesQueryParameters class MMSClient: diff --git a/api/sms.py b/infobip/api/sms.py similarity index 88% rename from api/sms.py rename to infobip/api/sms.py index f6a4f97..ea34e0f 100644 --- a/api/sms.py +++ b/infobip/api/sms.py @@ -2,8 +2,8 @@ from httpx import AsyncClient, Response -from models import SendSMSRequestBody -from models.sms_preview_request import PreviewSMSRequestBody +from infobip.models.sms_advanced_textual_request import SendSMSRequestBody +from infobip.models.sms_preview_request import PreviewSMSRequestBody class SMSClient: diff --git a/client.py b/infobip/client.py similarity index 87% rename from client.py rename to infobip/client.py index e518aff..fb43354 100644 --- a/client.py +++ b/infobip/client.py @@ -1,8 +1,8 @@ from os import getenv from httpx import AsyncClient -from api.mms import MMSClient -from api.sms import SMSClient +from infobip.api.mms import MMSClient +from infobip.api.sms import SMSClient class InfobipAPIClient(AsyncClient): diff --git a/infobip/models/__init__.py b/infobip/models/__init__.py new file mode 100644 index 0000000..0439dcc --- /dev/null +++ b/infobip/models/__init__.py @@ -0,0 +1,14 @@ +# coding: utf-8 + +# flake8: noqa +""" + This class is auto generated from the Infobip OpenAPI specification + through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), + powered by the OpenAPI Generator (https://openapi-generator.tech). +""" + + +from __future__ import absolute_import + +# import models into model package +from infobip.models.entity import Entity diff --git a/models/application.py b/infobip/models/application.py similarity index 100% rename from models/application.py rename to infobip/models/application.py diff --git a/models/channel.py b/infobip/models/channel.py similarity index 100% rename from models/channel.py rename to infobip/models/channel.py diff --git a/models/entity.py b/infobip/models/entity.py similarity index 100% rename from models/entity.py rename to infobip/models/entity.py diff --git a/models/message_error.py b/infobip/models/message_error.py similarity index 100% rename from models/message_error.py rename to infobip/models/message_error.py diff --git a/models/message_price.py b/infobip/models/message_price.py similarity index 100% rename from models/message_price.py rename to infobip/models/message_price.py diff --git a/models/message_status.py b/infobip/models/message_status.py similarity index 100% rename from models/message_status.py rename to infobip/models/message_status.py diff --git a/models/mms_advanced_message.py b/infobip/models/mms_advanced_message.py similarity index 96% rename from models/mms_advanced_message.py rename to infobip/models/mms_advanced_message.py index a4b5ebd..2960e94 100644 --- a/models/mms_advanced_message.py +++ b/infobip/models/mms_advanced_message.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,9 +15,9 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, constr -from models.mms_advanced_message_segment import MmsAdvancedMessageSegment -from models.mms_delivery_time_window import MmsDeliveryTimeWindow -from models.mms_destination import MmsDestination +from infobip.models.mms_advanced_message_segment import MmsAdvancedMessageSegment +from infobip.models.mms_delivery_time_window import MmsDeliveryTimeWindow +from infobip.models.mms_destination import MmsDestination class MmsAdvancedMessage(BaseModel): diff --git a/models/mms_advanced_message_segment.py b/infobip/models/mms_advanced_message_segment.py similarity index 93% rename from models/mms_advanced_message_segment.py rename to infobip/models/mms_advanced_message_segment.py index 9b75378..63f5a69 100644 --- a/models/mms_advanced_message_segment.py +++ b/infobip/models/mms_advanced_message_segment.py @@ -8,30 +8,28 @@ from __future__ import annotations -from inspect import getfullargspec -import json import pprint import re # noqa: F401 from typing import Optional -from pydantic import BaseModel, Field, StrictStr, ValidationError, validator -from models.mms_advanced_message_segment_binary import ( +from pydantic import BaseModel, ValidationError, validator +from infobip.models.mms_advanced_message_segment_binary import ( MmsAdvancedMessageSegmentBinary, ) -from models.mms_advanced_message_segment_link import ( +from infobip.models.mms_advanced_message_segment_link import ( MmsAdvancedMessageSegmentLink, ) -from models.mms_advanced_message_segment_smil import ( +from infobip.models.mms_advanced_message_segment_smil import ( MmsAdvancedMessageSegmentSmil, ) -from models.mms_advanced_message_segment_text import ( +from infobip.models.mms_advanced_message_segment_text import ( MmsAdvancedMessageSegmentText, ) -from models.mms_advanced_message_segment_upload_reference import ( +from infobip.models.mms_advanced_message_segment_upload_reference import ( MmsAdvancedMessageSegmentUploadReference, ) from typing import Any, List -from pydantic import StrictStr, Field +from pydantic import Field MMSADVANCEDMESSAGESEGMENT_ANY_OF_SCHEMAS = [ "MmsAdvancedMessageSegmentBinary", diff --git a/models/mms_advanced_message_segment_binary.py b/infobip/models/mms_advanced_message_segment_binary.py similarity index 100% rename from models/mms_advanced_message_segment_binary.py rename to infobip/models/mms_advanced_message_segment_binary.py diff --git a/models/mms_advanced_message_segment_link.py b/infobip/models/mms_advanced_message_segment_link.py similarity index 100% rename from models/mms_advanced_message_segment_link.py rename to infobip/models/mms_advanced_message_segment_link.py diff --git a/models/mms_advanced_message_segment_smil.py b/infobip/models/mms_advanced_message_segment_smil.py similarity index 100% rename from models/mms_advanced_message_segment_smil.py rename to infobip/models/mms_advanced_message_segment_smil.py diff --git a/models/mms_advanced_message_segment_text.py b/infobip/models/mms_advanced_message_segment_text.py similarity index 100% rename from models/mms_advanced_message_segment_text.py rename to infobip/models/mms_advanced_message_segment_text.py diff --git a/models/mms_advanced_message_segment_upload_reference.py b/infobip/models/mms_advanced_message_segment_upload_reference.py similarity index 100% rename from models/mms_advanced_message_segment_upload_reference.py rename to infobip/models/mms_advanced_message_segment_upload_reference.py diff --git a/models/mms_advanced_request.py b/infobip/models/mms_advanced_request.py similarity index 96% rename from models/mms_advanced_request.py rename to infobip/models/mms_advanced_request.py index 427bb41..42fd955 100644 --- a/models/mms_advanced_request.py +++ b/infobip/models/mms_advanced_request.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictStr -from models.mms_advanced_message import MmsAdvancedMessage +from infobip.models.mms_advanced_message import MmsAdvancedMessage class MmsAdvancedRequest(BaseModel): diff --git a/models/mms_delivery_day.py b/infobip/models/mms_delivery_day.py similarity index 100% rename from models/mms_delivery_day.py rename to infobip/models/mms_delivery_day.py diff --git a/models/mms_delivery_time.py b/infobip/models/mms_delivery_time.py similarity index 100% rename from models/mms_delivery_time.py rename to infobip/models/mms_delivery_time.py diff --git a/models/mms_delivery_time_window.py b/infobip/models/mms_delivery_time_window.py similarity index 95% rename from models/mms_delivery_time_window.py rename to infobip/models/mms_delivery_time_window.py index cc1ab38..fdb2602 100644 --- a/models/mms_delivery_time_window.py +++ b/infobip/models/mms_delivery_time_window.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,8 +15,8 @@ from typing import List, Optional from pydantic import BaseModel, Field -from models.mms_delivery_day import MmsDeliveryDay -from models.mms_delivery_time import MmsDeliveryTime +from infobip.models.mms_delivery_day import MmsDeliveryDay +from infobip.models.mms_delivery_time import MmsDeliveryTime class MmsDeliveryTimeWindow(BaseModel): diff --git a/models/mms_destination.py b/infobip/models/mms_destination.py similarity index 100% rename from models/mms_destination.py rename to infobip/models/mms_destination.py diff --git a/models/mms_error.py b/infobip/models/mms_error.py similarity index 100% rename from models/mms_error.py rename to infobip/models/mms_error.py diff --git a/models/mms_get_inbound_messages_query_parameters.py b/infobip/models/mms_get_inbound_messages_query_parameters.py similarity index 100% rename from models/mms_get_inbound_messages_query_parameters.py rename to infobip/models/mms_get_inbound_messages_query_parameters.py diff --git a/models/mms_inbound_report.py b/infobip/models/mms_inbound_report.py similarity index 98% rename from models/mms_inbound_report.py rename to infobip/models/mms_inbound_report.py index 4d32fee..1bc9801 100644 --- a/models/mms_inbound_report.py +++ b/infobip/models/mms_inbound_report.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from datetime import datetime from typing import Optional from pydantic import BaseModel, Field, StrictInt, StrictStr -from models.mms_price import MmsPrice +from infobip.models.mms_price import MmsPrice class MmsInboundReport(BaseModel): diff --git a/models/mms_inbound_report_response.py b/infobip/models/mms_inbound_report_response.py similarity index 85% rename from models/mms_inbound_report_response.py rename to infobip/models/mms_inbound_report_response.py index c013560..6174e5e 100644 --- a/models/mms_inbound_report_response.py +++ b/infobip/models/mms_inbound_report_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,10 +15,10 @@ from typing import List, Optional from pydantic import BaseModel, Field -from models.mms_inbound_report import MmsInboundReport +from infobip.models.mms_inbound_report import MmsInboundReport -class MMSInboundReportResponse(BaseModel): +class GetInboundMessagesResponseBody(BaseModel): """NOTE: This class is auto generated by OpenAPI Generator. Ref: https://openapi-generator.tech @@ -42,7 +41,7 @@ def to_json(self) -> str: return json.dumps(self.to_dict()) @classmethod - def from_json(cls, json_str: str) -> MMSInboundReportResponse: + def from_json(cls, json_str: str) -> GetInboundMessagesResponseBody: """Create an instance of MmsInboundReportResponse from a JSON string""" return cls.from_dict(json.loads(json_str)) @@ -59,15 +58,15 @@ def to_dict(self): return _dict @classmethod - def from_dict(cls, obj: dict) -> MMSInboundReportResponse: + def from_dict(cls, obj: dict) -> GetInboundMessagesResponseBody: """Create an instance of MmsInboundReportResponse from a dict""" if obj is None: return None if type(obj) is not dict: - return MMSInboundReportResponse.parse_obj(obj) + return GetInboundMessagesResponseBody.parse_obj(obj) - _obj = MMSInboundReportResponse.parse_obj( + _obj = GetInboundMessagesResponseBody.parse_obj( { "results": [ MmsInboundReport.from_dict(_item) for _item in obj.get("results") diff --git a/models/mms_message_result.py b/infobip/models/mms_message_result.py similarity index 97% rename from models/mms_message_result.py rename to infobip/models/mms_message_result.py index 3ac9ce0..6ef46f1 100644 --- a/models/mms_message_result.py +++ b/infobip/models/mms_message_result.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import Optional from pydantic import BaseModel, Field, StrictStr -from models.mms_status import MmsStatus +from infobip.models.mms_status import MmsStatus class MmsMessageResult(BaseModel): diff --git a/models/mms_price.py b/infobip/models/mms_price.py similarity index 100% rename from models/mms_price.py rename to infobip/models/mms_price.py diff --git a/models/mms_report.py b/infobip/models/mms_report.py similarity index 97% rename from models/mms_report.py rename to infobip/models/mms_report.py index 9c3158e..b3c4e3e 100644 --- a/models/mms_report.py +++ b/infobip/models/mms_report.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -17,9 +16,9 @@ from datetime import datetime from typing import Optional from pydantic import BaseModel, Field, StrictInt, StrictStr -from models.mms_error import MmsError -from models.mms_price import MmsPrice -from models.mms_status import MmsStatus +from infobip.models.mms_error import MmsError +from infobip.models.mms_price import MmsPrice +from infobip.models.mms_status import MmsStatus class MmsReport(BaseModel): diff --git a/models/mms_report_response.py b/infobip/models/mms_report_response.py similarity index 96% rename from models/mms_report_response.py rename to infobip/models/mms_report_response.py index 6930b5f..9c220ec 100644 --- a/models/mms_report_response.py +++ b/infobip/models/mms_report_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel -from models.mms_report import MmsReport +from infobip.models.mms_report import MmsReport class MmsReportResponse(BaseModel): diff --git a/models/mms_send_result.py b/infobip/models/mms_send_result.py similarity index 96% rename from models/mms_send_result.py rename to infobip/models/mms_send_result.py index 9dd40dc..31a097e 100644 --- a/models/mms_send_result.py +++ b/infobip/models/mms_send_result.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictStr -from models.mms_message_result import MmsMessageResult +from infobip.models.mms_message_result import MmsMessageResult class MmsSendResult(BaseModel): diff --git a/models/mms_status.py b/infobip/models/mms_status.py similarity index 100% rename from models/mms_status.py rename to infobip/models/mms_status.py diff --git a/models/mms_upload_binary_result.py b/infobip/models/mms_upload_binary_result.py similarity index 100% rename from models/mms_upload_binary_result.py rename to infobip/models/mms_upload_binary_result.py diff --git a/models/mms_webhook_inbound_message_segment.py b/infobip/models/mms_webhook_inbound_message_segment.py similarity index 97% rename from models/mms_webhook_inbound_message_segment.py rename to infobip/models/mms_webhook_inbound_message_segment.py index 6b0494a..88b0cd9 100644 --- a/models/mms_webhook_inbound_message_segment.py +++ b/infobip/models/mms_webhook_inbound_message_segment.py @@ -17,10 +17,10 @@ from pydantic import BaseModel, ValidationError, validator from pydantic import Field -from models.mms_webhook_inbound_message_segment_link import ( +from infobip.models.mms_webhook_inbound_message_segment_link import ( MmsWebhookInboundMessageSegmentLink, ) -from models.mms_webhook_inbound_message_segment_text import ( +from infobip.models.mms_webhook_inbound_message_segment_text import ( MmsWebhookInboundMessageSegmentText, ) diff --git a/models/mms_webhook_inbound_message_segment_link.py b/infobip/models/mms_webhook_inbound_message_segment_link.py similarity index 100% rename from models/mms_webhook_inbound_message_segment_link.py rename to infobip/models/mms_webhook_inbound_message_segment_link.py diff --git a/models/mms_webhook_inbound_message_segment_text.py b/infobip/models/mms_webhook_inbound_message_segment_text.py similarity index 100% rename from models/mms_webhook_inbound_message_segment_text.py rename to infobip/models/mms_webhook_inbound_message_segment_text.py diff --git a/models/mms_webhook_inbound_report.py b/infobip/models/mms_webhook_inbound_report.py similarity index 97% rename from models/mms_webhook_inbound_report.py rename to infobip/models/mms_webhook_inbound_report.py index 196a398..cdc3ab2 100644 --- a/models/mms_webhook_inbound_report.py +++ b/infobip/models/mms_webhook_inbound_report.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,8 +15,8 @@ from datetime import datetime from typing import List, Optional from pydantic import BaseModel, Field, StrictStr -from models.message_price import MessagePrice -from models.mms_webhook_inbound_message_segment import ( +from infobip.models.message_price import MessagePrice +from infobip.models.mms_webhook_inbound_message_segment import ( MmsWebhookInboundMessageSegment, ) diff --git a/models/mms_webhook_inbound_report_response.py b/infobip/models/mms_webhook_inbound_report_response.py similarity index 96% rename from models/mms_webhook_inbound_report_response.py rename to infobip/models/mms_webhook_inbound_report_response.py index 2cd5e63..212ec2a 100644 --- a/models/mms_webhook_inbound_report_response.py +++ b/infobip/models/mms_webhook_inbound_report_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictInt -from models.mms_webhook_inbound_report import MmsWebhookInboundReport +from infobip.models.mms_webhook_inbound_report import MmsWebhookInboundReport class MmsWebhookInboundReportResponse(BaseModel): diff --git a/models/mms_webhook_outbound_report.py b/infobip/models/mms_webhook_outbound_report.py similarity index 96% rename from models/mms_webhook_outbound_report.py rename to infobip/models/mms_webhook_outbound_report.py index c0afc93..ffd4218 100644 --- a/models/mms_webhook_outbound_report.py +++ b/infobip/models/mms_webhook_outbound_report.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,9 +15,9 @@ from datetime import datetime from typing import Optional from pydantic import BaseModel, Field, StrictInt, StrictStr -from models.message_error import MessageError -from models.message_price import MessagePrice -from models.message_status import MessageStatus +from infobip.models.message_error import MessageError +from infobip.models.message_price import MessagePrice +from infobip.models.message_status import MessageStatus class MmsWebhookOutboundReport(BaseModel): diff --git a/models/mms_webhook_outbound_report_response.py b/infobip/models/mms_webhook_outbound_report_response.py similarity index 95% rename from models/mms_webhook_outbound_report_response.py rename to infobip/models/mms_webhook_outbound_report_response.py index 6e06cf8..f5e8b2e 100644 --- a/models/mms_webhook_outbound_report_response.py +++ b/infobip/models/mms_webhook_outbound_report_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel -from models.mms_webhook_outbound_report import MmsWebhookOutboundReport +from infobip.models.mms_webhook_outbound_report import MmsWebhookOutboundReport class MmsWebhookOutboundReportResponse(BaseModel): diff --git a/models/modify_application.py b/infobip/models/modify_application.py similarity index 100% rename from models/modify_application.py rename to infobip/models/modify_application.py diff --git a/models/modify_entity.py b/infobip/models/modify_entity.py similarity index 100% rename from models/modify_entity.py rename to infobip/models/modify_entity.py diff --git a/models/number_price.py b/infobip/models/number_price.py similarity index 100% rename from models/number_price.py rename to infobip/models/number_price.py diff --git a/models/number_registration_address.py b/infobip/models/number_registration_address.py similarity index 100% rename from models/number_registration_address.py rename to infobip/models/number_registration_address.py diff --git a/models/number_registration_brand.py b/infobip/models/number_registration_brand.py similarity index 99% rename from models/number_registration_brand.py rename to infobip/models/number_registration_brand.py index 1d1dfc8..d2fc319 100644 --- a/models/number_registration_brand.py +++ b/infobip/models/number_registration_brand.py @@ -8,11 +8,10 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -import models +from infobip import models from datetime import datetime from typing import Optional diff --git a/models/number_registration_brand_preview.py b/infobip/models/number_registration_brand_preview.py similarity index 100% rename from models/number_registration_brand_preview.py rename to infobip/models/number_registration_brand_preview.py diff --git a/models/number_registration_brand_status.py b/infobip/models/number_registration_brand_status.py similarity index 100% rename from models/number_registration_brand_status.py rename to infobip/models/number_registration_brand_status.py diff --git a/models/number_registration_brand_vet.py b/infobip/models/number_registration_brand_vet.py similarity index 100% rename from models/number_registration_brand_vet.py rename to infobip/models/number_registration_brand_vet.py diff --git a/models/number_registration_business_identifier.py b/infobip/models/number_registration_business_identifier.py similarity index 98% rename from models/number_registration_business_identifier.py rename to infobip/models/number_registration_business_identifier.py index de1757e..9f94e3e 100644 --- a/models/number_registration_business_identifier.py +++ b/infobip/models/number_registration_business_identifier.py @@ -8,12 +8,10 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -import models - +from infobip import models from typing import Optional from pydantic import BaseModel, StrictStr, validator diff --git a/models/number_registration_campaign.py b/infobip/models/number_registration_campaign.py similarity index 99% rename from models/number_registration_campaign.py rename to infobip/models/number_registration_campaign.py index e2e1801..f7015aa 100644 --- a/models/number_registration_campaign.py +++ b/infobip/models/number_registration_campaign.py @@ -8,11 +8,10 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -import models +from infobip import models from datetime import datetime from typing import Optional diff --git a/models/number_registration_data_universal_numbering_system_number.py b/infobip/models/number_registration_data_universal_numbering_system_number.py similarity index 94% rename from models/number_registration_data_universal_numbering_system_number.py rename to infobip/models/number_registration_data_universal_numbering_system_number.py index 88b3c76..3f0c79e 100644 --- a/models/number_registration_data_universal_numbering_system_number.py +++ b/infobip/models/number_registration_data_universal_numbering_system_number.py @@ -8,14 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -from pydantic import BaseModel, Field, constr, validator -from models.number_registration_business_identifier import ( +from pydantic import Field, constr, validator +from infobip.models.number_registration_business_identifier import ( NumberRegistrationBusinessIdentifier, ) diff --git a/models/number_registration_document_metadata.py b/infobip/models/number_registration_document_metadata.py similarity index 100% rename from models/number_registration_document_metadata.py rename to infobip/models/number_registration_document_metadata.py diff --git a/models/number_registration_external_ten_dlc_campaign.py b/infobip/models/number_registration_external_ten_dlc_campaign.py similarity index 95% rename from models/number_registration_external_ten_dlc_campaign.py rename to infobip/models/number_registration_external_ten_dlc_campaign.py index 2f98f2e..4652a66 100644 --- a/models/number_registration_external_ten_dlc_campaign.py +++ b/infobip/models/number_registration_external_ten_dlc_campaign.py @@ -8,18 +8,17 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json from typing import List, Optional -from pydantic import BaseModel, Field, StrictStr, conlist -from models.number_registration_campaign import ( +from pydantic import Field, StrictStr, conlist +from infobip.models.number_registration_campaign import ( NumberRegistrationCampaign, ) -from models.number_registration_number_preview import ( +from infobip.models.number_registration_number_preview import ( NumberRegistrationNumberPreview, ) diff --git a/models/number_registration_global_intermediary_identification_number.py b/infobip/models/number_registration_global_intermediary_identification_number.py similarity index 94% rename from models/number_registration_global_intermediary_identification_number.py rename to infobip/models/number_registration_global_intermediary_identification_number.py index f726eb8..a6de767 100644 --- a/models/number_registration_global_intermediary_identification_number.py +++ b/infobip/models/number_registration_global_intermediary_identification_number.py @@ -8,14 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -from pydantic import BaseModel, Field, constr, validator -from models.number_registration_business_identifier import ( +from pydantic import Field, constr, validator +from infobip.models.number_registration_business_identifier import ( NumberRegistrationBusinessIdentifier, ) diff --git a/models/number_registration_government_brand.py b/infobip/models/number_registration_government_brand.py similarity index 95% rename from models/number_registration_government_brand.py rename to infobip/models/number_registration_government_brand.py index d82d897..44b4429 100644 --- a/models/number_registration_government_brand.py +++ b/infobip/models/number_registration_government_brand.py @@ -8,17 +8,16 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json from typing import Optional -from pydantic import BaseModel, Field, StrictStr, constr, validator -from models.number_registration_address import NumberRegistrationAddress -from models.number_registration_brand import NumberRegistrationBrand -from models.number_registration_business_identifier import ( +from pydantic import Field, StrictStr, constr, validator +from infobip.models.number_registration_address import NumberRegistrationAddress +from infobip.models.number_registration_brand import NumberRegistrationBrand +from infobip.models.number_registration_business_identifier import ( NumberRegistrationBusinessIdentifier, ) diff --git a/models/number_registration_interactive_voice_response_opt_in.py b/infobip/models/number_registration_interactive_voice_response_opt_in.py similarity index 100% rename from models/number_registration_interactive_voice_response_opt_in.py rename to infobip/models/number_registration_interactive_voice_response_opt_in.py diff --git a/models/number_registration_keyword_opt_in.py b/infobip/models/number_registration_keyword_opt_in.py similarity index 100% rename from models/number_registration_keyword_opt_in.py rename to infobip/models/number_registration_keyword_opt_in.py diff --git a/models/number_registration_legal_entity_identifier.py b/infobip/models/number_registration_legal_entity_identifier.py similarity index 94% rename from models/number_registration_legal_entity_identifier.py rename to infobip/models/number_registration_legal_entity_identifier.py index 6dfc477..727a05c 100644 --- a/models/number_registration_legal_entity_identifier.py +++ b/infobip/models/number_registration_legal_entity_identifier.py @@ -8,14 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -from pydantic import BaseModel, Field, constr, validator -from models.number_registration_business_identifier import ( +from pydantic import Field, constr, validator +from infobip.models.number_registration_business_identifier import ( NumberRegistrationBusinessIdentifier, ) diff --git a/models/number_registration_network_status.py b/infobip/models/number_registration_network_status.py similarity index 100% rename from models/number_registration_network_status.py rename to infobip/models/number_registration_network_status.py diff --git a/models/number_registration_non_profit_brand.py b/infobip/models/number_registration_non_profit_brand.py similarity index 95% rename from models/number_registration_non_profit_brand.py rename to infobip/models/number_registration_non_profit_brand.py index 416c6fe..11b8c66 100644 --- a/models/number_registration_non_profit_brand.py +++ b/infobip/models/number_registration_non_profit_brand.py @@ -8,17 +8,16 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json from typing import Optional -from pydantic import BaseModel, Field, StrictStr, constr, validator -from models.number_registration_address import NumberRegistrationAddress -from models.number_registration_brand import NumberRegistrationBrand -from models.number_registration_business_identifier import ( +from pydantic import Field, StrictStr, constr, validator +from infobip.models.number_registration_address import NumberRegistrationAddress +from infobip.models.number_registration_brand import NumberRegistrationBrand +from infobip.models.number_registration_business_identifier import ( NumberRegistrationBusinessIdentifier, ) diff --git a/models/number_registration_number_preview.py b/infobip/models/number_registration_number_preview.py similarity index 100% rename from models/number_registration_number_preview.py rename to infobip/models/number_registration_number_preview.py diff --git a/models/number_registration_opt_ins.py b/infobip/models/number_registration_opt_ins.py similarity index 93% rename from models/number_registration_opt_ins.py rename to infobip/models/number_registration_opt_ins.py index b700cf4..697e30c 100644 --- a/models/number_registration_opt_ins.py +++ b/infobip/models/number_registration_opt_ins.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,16 +15,16 @@ from typing import Optional from pydantic import BaseModel, Field -from models.number_registration_interactive_voice_response_opt_in import ( +from infobip.models.number_registration_interactive_voice_response_opt_in import ( NumberRegistrationInteractiveVoiceResponseOptIn, ) -from models.number_registration_keyword_opt_in import ( +from infobip.models.number_registration_keyword_opt_in import ( NumberRegistrationKeywordOptIn, ) -from models.number_registration_verbal_opt_in import ( +from infobip.models.number_registration_verbal_opt_in import ( NumberRegistrationVerbalOptIn, ) -from models.number_registration_web_opt_in import ( +from infobip.models.number_registration_web_opt_in import ( NumberRegistrationWebOptIn, ) diff --git a/models/number_registration_page_info.py b/infobip/models/number_registration_page_info.py similarity index 100% rename from models/number_registration_page_info.py rename to infobip/models/number_registration_page_info.py diff --git a/models/number_registration_page_response_brand.py b/infobip/models/number_registration_page_response_brand.py similarity index 95% rename from models/number_registration_page_response_brand.py rename to infobip/models/number_registration_page_response_brand.py index 9b3888c..d739372 100644 --- a/models/number_registration_page_response_brand.py +++ b/infobip/models/number_registration_page_response_brand.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,8 +15,8 @@ from typing import List, Optional from pydantic import BaseModel, Field -from models.number_registration_brand import NumberRegistrationBrand -from models.number_registration_page_info import ( +from infobip.models.number_registration_brand import NumberRegistrationBrand +from infobip.models.number_registration_page_info import ( NumberRegistrationPageInfo, ) diff --git a/models/number_registration_page_response_brand_vet.py b/infobip/models/number_registration_page_response_brand_vet.py similarity index 95% rename from models/number_registration_page_response_brand_vet.py rename to infobip/models/number_registration_page_response_brand_vet.py index 0ce2de2..b3afc97 100644 --- a/models/number_registration_page_response_brand_vet.py +++ b/infobip/models/number_registration_page_response_brand_vet.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,10 +15,10 @@ from typing import List, Optional from pydantic import BaseModel, Field -from models.number_registration_brand_vet import ( +from infobip.models.number_registration_brand_vet import ( NumberRegistrationBrandVet, ) -from models.number_registration_page_info import ( +from infobip.models.number_registration_page_info import ( NumberRegistrationPageInfo, ) diff --git a/models/number_registration_page_response_campaign.py b/infobip/models/number_registration_page_response_campaign.py similarity index 95% rename from models/number_registration_page_response_campaign.py rename to infobip/models/number_registration_page_response_campaign.py index ce6ffec..fafbdf1 100644 --- a/models/number_registration_page_response_campaign.py +++ b/infobip/models/number_registration_page_response_campaign.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,10 +15,10 @@ from typing import List, Optional from pydantic import BaseModel, Field -from models.number_registration_campaign import ( +from infobip.models.number_registration_campaign import ( NumberRegistrationCampaign, ) -from models.number_registration_page_info import ( +from infobip.models.number_registration_page_info import ( NumberRegistrationPageInfo, ) diff --git a/models/number_registration_private_company_brand.py b/infobip/models/number_registration_private_company_brand.py similarity index 95% rename from models/number_registration_private_company_brand.py rename to infobip/models/number_registration_private_company_brand.py index 05cc162..fbca0be 100644 --- a/models/number_registration_private_company_brand.py +++ b/infobip/models/number_registration_private_company_brand.py @@ -8,17 +8,16 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json from typing import Optional -from pydantic import BaseModel, Field, StrictStr, constr, validator -from models.number_registration_address import NumberRegistrationAddress -from models.number_registration_brand import NumberRegistrationBrand -from models.number_registration_business_identifier import ( +from pydantic import Field, StrictStr, constr, validator +from infobip.models.number_registration_address import NumberRegistrationAddress +from infobip.models.number_registration_brand import NumberRegistrationBrand +from infobip.models.number_registration_business_identifier import ( NumberRegistrationBusinessIdentifier, ) diff --git a/models/number_registration_public_company_brand.py b/infobip/models/number_registration_public_company_brand.py similarity index 96% rename from models/number_registration_public_company_brand.py rename to infobip/models/number_registration_public_company_brand.py index 2dd0321..509cbb9 100644 --- a/models/number_registration_public_company_brand.py +++ b/infobip/models/number_registration_public_company_brand.py @@ -8,17 +8,16 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json from typing import Optional -from pydantic import BaseModel, Field, StrictStr, constr, validator -from models.number_registration_address import NumberRegistrationAddress -from models.number_registration_brand import NumberRegistrationBrand -from models.number_registration_business_identifier import ( +from pydantic import Field, StrictStr, constr, validator +from infobip.models.number_registration_address import NumberRegistrationAddress +from infobip.models.number_registration_brand import NumberRegistrationBrand +from infobip.models.number_registration_business_identifier import ( NumberRegistrationBusinessIdentifier, ) diff --git a/models/number_registration_ten_dlc_campaign.py b/infobip/models/number_registration_ten_dlc_campaign.py similarity index 96% rename from models/number_registration_ten_dlc_campaign.py rename to infobip/models/number_registration_ten_dlc_campaign.py index c79ce82..f492e4d 100644 --- a/models/number_registration_ten_dlc_campaign.py +++ b/infobip/models/number_registration_ten_dlc_campaign.py @@ -8,27 +8,26 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json from typing import List, Optional -from pydantic import BaseModel, Field, StrictBool, StrictStr, conlist, constr, validator -from models.number_registration_brand_preview import ( +from pydantic import Field, StrictBool, StrictStr, conlist, constr, validator +from infobip.models.number_registration_brand_preview import ( NumberRegistrationBrandPreview, ) -from models.number_registration_campaign import ( +from infobip.models.number_registration_campaign import ( NumberRegistrationCampaign, ) -from models.number_registration_document_metadata import ( +from infobip.models.number_registration_document_metadata import ( NumberRegistrationDocumentMetadata, ) -from models.number_registration_number_preview import ( +from infobip.models.number_registration_number_preview import ( NumberRegistrationNumberPreview, ) -from models.number_registration_opt_ins import NumberRegistrationOptIns +from infobip.models.number_registration_opt_ins import NumberRegistrationOptIns class NumberRegistrationTenDlcCampaign(NumberRegistrationCampaign): diff --git a/models/number_registration_update_brand_request.py b/infobip/models/number_registration_update_brand_request.py similarity index 97% rename from models/number_registration_update_brand_request.py rename to infobip/models/number_registration_update_brand_request.py index f1c0106..1cc2b9e 100644 --- a/models/number_registration_update_brand_request.py +++ b/infobip/models/number_registration_update_brand_request.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import Optional from pydantic import BaseModel, Field, StrictStr -from models.number_registration_address import NumberRegistrationAddress +from infobip.models.number_registration_address import NumberRegistrationAddress class NumberRegistrationUpdateBrandRequest(BaseModel): diff --git a/models/number_registration_update_campaign_request.py b/infobip/models/number_registration_update_campaign_request.py similarity index 100% rename from models/number_registration_update_campaign_request.py rename to infobip/models/number_registration_update_campaign_request.py diff --git a/models/number_registration_verbal_opt_in.py b/infobip/models/number_registration_verbal_opt_in.py similarity index 100% rename from models/number_registration_verbal_opt_in.py rename to infobip/models/number_registration_verbal_opt_in.py diff --git a/models/number_registration_web_opt_in.py b/infobip/models/number_registration_web_opt_in.py similarity index 100% rename from models/number_registration_web_opt_in.py rename to infobip/models/number_registration_web_opt_in.py diff --git a/models/number_response.py b/infobip/models/number_response.py similarity index 97% rename from models/number_response.py rename to infobip/models/number_response.py index a6b62e6..e48ed51 100644 --- a/models/number_response.py +++ b/infobip/models/number_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,9 +15,9 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictBool, StrictStr, constr, validator -from models.number_price import NumberPrice -from models.numbers_edit_permissions import NumbersEditPermissions -from models.numbers_voice_setup import NumbersVoiceSetup +from infobip.models.number_price import NumberPrice +from infobip.models.numbers_edit_permissions import NumbersEditPermissions +from infobip.models.numbers_voice_setup import NumbersVoiceSetup class NumberResponse(BaseModel): diff --git a/models/numbers_auto_response_action.py b/infobip/models/numbers_auto_response_action.py similarity index 93% rename from models/numbers_auto_response_action.py rename to infobip/models/numbers_auto_response_action.py index 009b922..a1cf3a2 100644 --- a/models/numbers_auto_response_action.py +++ b/infobip/models/numbers_auto_response_action.py @@ -8,16 +8,15 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json from typing import Optional -from pydantic import BaseModel, Field, StrictStr, constr -from models.numbers_delivery_time_window import NumbersDeliveryTimeWindow -from models.numbers_mo_non_forward_action import ( +from pydantic import Field, StrictStr, constr +from infobip.models.numbers_delivery_time_window import NumbersDeliveryTimeWindow +from infobip.models.numbers_mo_non_forward_action import ( NumbersMoNonForwardAction, ) diff --git a/models/numbers_block_action.py b/infobip/models/numbers_block_action.py similarity index 94% rename from models/numbers_block_action.py rename to infobip/models/numbers_block_action.py index bc524fc..4651b23 100644 --- a/models/numbers_block_action.py +++ b/infobip/models/numbers_block_action.py @@ -8,14 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -from pydantic import BaseModel, Field, StrictStr, validator -from models.numbers_mo_non_forward_action import ( +from pydantic import Field, StrictStr, validator +from infobip.models.numbers_mo_non_forward_action import ( NumbersMoNonForwardAction, ) diff --git a/models/numbers_delivery_time_window.py b/infobip/models/numbers_delivery_time_window.py similarity index 100% rename from models/numbers_delivery_time_window.py rename to infobip/models/numbers_delivery_time_window.py diff --git a/models/numbers_edit_permissions.py b/infobip/models/numbers_edit_permissions.py similarity index 100% rename from models/numbers_edit_permissions.py rename to infobip/models/numbers_edit_permissions.py diff --git a/models/numbers_forward_to_ivr_action_details.py b/infobip/models/numbers_forward_to_ivr_action_details.py similarity index 92% rename from models/numbers_forward_to_ivr_action_details.py rename to infobip/models/numbers_forward_to_ivr_action_details.py index 331c102..3e94e30 100644 --- a/models/numbers_forward_to_ivr_action_details.py +++ b/infobip/models/numbers_forward_to_ivr_action_details.py @@ -8,14 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -from pydantic import BaseModel, Field, StrictStr -from models.numbers_voice_action_details import NumbersVoiceActionDetails +from pydantic import Field, StrictStr +from infobip.models.numbers_voice_action_details import NumbersVoiceActionDetails class NumbersForwardToIvrActionDetails(NumbersVoiceActionDetails): diff --git a/models/numbers_forward_to_subscription_details.py b/infobip/models/numbers_forward_to_subscription_details.py similarity index 93% rename from models/numbers_forward_to_subscription_details.py rename to infobip/models/numbers_forward_to_subscription_details.py index 62c8a88..8ca7055 100644 --- a/models/numbers_forward_to_subscription_details.py +++ b/infobip/models/numbers_forward_to_subscription_details.py @@ -8,14 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json - -from pydantic import BaseModel -from models.numbers_voice_action_details import NumbersVoiceActionDetails +from infobip.models.numbers_voice_action_details import NumbersVoiceActionDetails class NumbersForwardToSubscriptionDetails(NumbersVoiceActionDetails): diff --git a/models/numbers_http_forward_action.py b/infobip/models/numbers_http_forward_action.py similarity index 95% rename from models/numbers_http_forward_action.py rename to infobip/models/numbers_http_forward_action.py index df8d079..72c6fe4 100644 --- a/models/numbers_http_forward_action.py +++ b/infobip/models/numbers_http_forward_action.py @@ -8,15 +8,14 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json from typing import Optional -from pydantic import BaseModel, Field, StrictStr, validator -from models.numbers_mo_action import NumbersMoAction +from pydantic import Field, StrictStr, validator +from infobip.models.numbers_mo_action import NumbersMoAction class NumbersHttpForwardAction(NumbersMoAction): diff --git a/models/numbers_mail_forward_action.py b/infobip/models/numbers_mail_forward_action.py similarity index 93% rename from models/numbers_mail_forward_action.py rename to infobip/models/numbers_mail_forward_action.py index b02fab3..02c0a04 100644 --- a/models/numbers_mail_forward_action.py +++ b/infobip/models/numbers_mail_forward_action.py @@ -8,14 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -from pydantic import BaseModel, Field, StrictStr -from models.numbers_mo_action import NumbersMoAction +from pydantic import Field, StrictStr +from infobip.models.numbers_mo_action import NumbersMoAction class NumbersMailForwardAction(NumbersMoAction): diff --git a/models/numbers_mo_action.py b/infobip/models/numbers_mo_action.py similarity index 99% rename from models/numbers_mo_action.py rename to infobip/models/numbers_mo_action.py index 32e03bc..5fe4415 100644 --- a/models/numbers_mo_action.py +++ b/infobip/models/numbers_mo_action.py @@ -8,12 +8,10 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -import models - +from infobip import models from typing import Optional from pydantic import BaseModel, Field, StrictStr, validator diff --git a/models/numbers_mo_configuration.py b/infobip/models/numbers_mo_configuration.py similarity index 95% rename from models/numbers_mo_configuration.py rename to infobip/models/numbers_mo_configuration.py index 194f2c5..5f5b033 100644 --- a/models/numbers_mo_configuration.py +++ b/infobip/models/numbers_mo_configuration.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,11 +15,11 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictStr, constr -from models.numbers_mo_action import NumbersMoAction -from models.numbers_mo_non_forward_action import ( +from infobip.models.numbers_mo_action import NumbersMoAction +from infobip.models.numbers_mo_non_forward_action import ( NumbersMoNonForwardAction, ) -from models.numbers_use_conversation import NumbersUseConversation +from infobip.models.numbers_use_conversation import NumbersUseConversation class NumbersMoConfiguration(BaseModel): diff --git a/models/numbers_mo_configurations.py b/infobip/models/numbers_mo_configurations.py similarity index 96% rename from models/numbers_mo_configurations.py rename to infobip/models/numbers_mo_configurations.py index ec34c77..12a4363 100644 --- a/models/numbers_mo_configurations.py +++ b/infobip/models/numbers_mo_configurations.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictInt -from models.numbers_stored_mo_configuration import ( +from infobip.models.numbers_stored_mo_configuration import ( NumbersStoredMoConfiguration, ) diff --git a/models/numbers_mo_non_forward_action.py b/infobip/models/numbers_mo_non_forward_action.py similarity index 98% rename from models/numbers_mo_non_forward_action.py rename to infobip/models/numbers_mo_non_forward_action.py index de620f1..b03681d 100644 --- a/models/numbers_mo_non_forward_action.py +++ b/infobip/models/numbers_mo_non_forward_action.py @@ -8,12 +8,10 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -import models - +from infobip import models from typing import Optional from pydantic import BaseModel, Field, StrictBool, StrictStr, validator diff --git a/models/numbers_no_action.py b/infobip/models/numbers_no_action.py similarity index 93% rename from models/numbers_no_action.py rename to infobip/models/numbers_no_action.py index cb0f2b4..ff90365 100644 --- a/models/numbers_no_action.py +++ b/infobip/models/numbers_no_action.py @@ -8,14 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json - -from pydantic import BaseModel -from models.numbers_mo_action import NumbersMoAction +from infobip.models.numbers_mo_action import NumbersMoAction class NumbersNoAction(NumbersMoAction): diff --git a/models/numbers_pull_action.py b/infobip/models/numbers_pull_action.py similarity index 93% rename from models/numbers_pull_action.py rename to infobip/models/numbers_pull_action.py index 93bff49..b0c1a7a 100644 --- a/models/numbers_pull_action.py +++ b/infobip/models/numbers_pull_action.py @@ -8,14 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json - -from pydantic import BaseModel -from models.numbers_mo_action import NumbersMoAction +from infobip.models.numbers_mo_action import NumbersMoAction class NumbersPullAction(NumbersMoAction): diff --git a/models/numbers_purchase_number_request.py b/infobip/models/numbers_purchase_number_request.py similarity index 100% rename from models/numbers_purchase_number_request.py rename to infobip/models/numbers_purchase_number_request.py diff --git a/models/numbers_response.py b/infobip/models/numbers_response.py similarity index 96% rename from models/numbers_response.py rename to infobip/models/numbers_response.py index c5cf22d..35f62a6 100644 --- a/models/numbers_response.py +++ b/infobip/models/numbers_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictInt -from models.number_response import NumberResponse +from infobip.models.number_response import NumberResponse class NumbersResponse(BaseModel): diff --git a/models/numbers_smpp_forward_action.py b/infobip/models/numbers_smpp_forward_action.py similarity index 93% rename from models/numbers_smpp_forward_action.py rename to infobip/models/numbers_smpp_forward_action.py index a0a29d0..909d020 100644 --- a/models/numbers_smpp_forward_action.py +++ b/infobip/models/numbers_smpp_forward_action.py @@ -8,14 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json - -from pydantic import BaseModel -from models.numbers_mo_action import NumbersMoAction +from infobip.models.numbers_mo_action import NumbersMoAction class NumbersSmppForwardAction(NumbersMoAction): diff --git a/models/numbers_stored_mo_configuration.py b/infobip/models/numbers_stored_mo_configuration.py similarity index 96% rename from models/numbers_stored_mo_configuration.py rename to infobip/models/numbers_stored_mo_configuration.py index a00df12..317c7b0 100644 --- a/models/numbers_stored_mo_configuration.py +++ b/infobip/models/numbers_stored_mo_configuration.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,11 +15,11 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictStr, constr -from models.numbers_mo_action import NumbersMoAction -from models.numbers_mo_non_forward_action import ( +from infobip.models.numbers_mo_action import NumbersMoAction +from infobip.models.numbers_mo_non_forward_action import ( NumbersMoNonForwardAction, ) -from models.numbers_use_conversation import NumbersUseConversation +from infobip.models.numbers_use_conversation import NumbersUseConversation class NumbersStoredMoConfiguration(BaseModel): diff --git a/models/numbers_use_conversation.py b/infobip/models/numbers_use_conversation.py similarity index 100% rename from models/numbers_use_conversation.py rename to infobip/models/numbers_use_conversation.py diff --git a/models/numbers_voice_action_details.py b/infobip/models/numbers_voice_action_details.py similarity index 99% rename from models/numbers_voice_action_details.py rename to infobip/models/numbers_voice_action_details.py index 08619a6..62cdb5f 100644 --- a/models/numbers_voice_action_details.py +++ b/infobip/models/numbers_voice_action_details.py @@ -8,12 +8,10 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -import models - +from infobip import models from typing import Optional from pydantic import BaseModel, StrictStr, validator diff --git a/models/numbers_voice_call_forward_to_application_details.py b/infobip/models/numbers_voice_call_forward_to_application_details.py similarity index 93% rename from models/numbers_voice_call_forward_to_application_details.py rename to infobip/models/numbers_voice_call_forward_to_application_details.py index fd3b2bb..1bc31a0 100644 --- a/models/numbers_voice_call_forward_to_application_details.py +++ b/infobip/models/numbers_voice_call_forward_to_application_details.py @@ -8,14 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -from pydantic import BaseModel, Field, StrictStr -from models.numbers_voice_action_details import NumbersVoiceActionDetails +from pydantic import Field, StrictStr +from infobip.models.numbers_voice_action_details import NumbersVoiceActionDetails class NumbersVoiceCallForwardToApplicationDetails(NumbersVoiceActionDetails): diff --git a/models/numbers_voice_number_masking_action_details.py b/infobip/models/numbers_voice_number_masking_action_details.py similarity index 93% rename from models/numbers_voice_number_masking_action_details.py rename to infobip/models/numbers_voice_number_masking_action_details.py index 0865e54..7907f2a 100644 --- a/models/numbers_voice_number_masking_action_details.py +++ b/infobip/models/numbers_voice_number_masking_action_details.py @@ -8,14 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json -from pydantic import BaseModel, Field, StrictStr -from models.numbers_voice_action_details import NumbersVoiceActionDetails +from pydantic import Field, StrictStr +from infobip.models.numbers_voice_action_details import NumbersVoiceActionDetails class NumbersVoiceNumberMaskingActionDetails(NumbersVoiceActionDetails): diff --git a/models/numbers_voice_setup.py b/infobip/models/numbers_voice_setup.py similarity index 96% rename from models/numbers_voice_setup.py rename to infobip/models/numbers_voice_setup.py index a665702..42c0bc1 100644 --- a/models/numbers_voice_setup.py +++ b/infobip/models/numbers_voice_setup.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import Optional from pydantic import BaseModel, Field, constr -from models.numbers_voice_action_details import NumbersVoiceActionDetails +from infobip.models.numbers_voice_action_details import NumbersVoiceActionDetails class NumbersVoiceSetup(BaseModel): diff --git a/models/page_application.py b/infobip/models/page_application.py similarity index 95% rename from models/page_application.py rename to infobip/models/page_application.py index fd6dd08..8cf49d3 100644 --- a/models/page_application.py +++ b/infobip/models/page_application.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,8 +15,8 @@ from typing import List, Optional from pydantic import BaseModel -from models.application import Application -from models.page_info import PageInfo +from infobip.models.application import Application +from infobip.models.page_info import PageInfo class PageApplication(BaseModel): diff --git a/models/page_entity.py b/infobip/models/page_entity.py similarity index 96% rename from models/page_entity.py rename to infobip/models/page_entity.py index 224aa67..cd0366a 100644 --- a/models/page_entity.py +++ b/infobip/models/page_entity.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,8 +15,8 @@ from typing import List, Optional from pydantic import BaseModel -from models.entity import Entity -from models.page_info import PageInfo +from infobip.models.entity import Entity +from infobip.models.page_info import PageInfo class PageEntity(BaseModel): diff --git a/models/page_info.py b/infobip/models/page_info.py similarity index 100% rename from models/page_info.py rename to infobip/models/page_info.py diff --git a/models/page_resource_association.py b/infobip/models/page_resource_association.py similarity index 95% rename from models/page_resource_association.py rename to infobip/models/page_resource_association.py index 4ea9027..08977cc 100644 --- a/models/page_resource_association.py +++ b/infobip/models/page_resource_association.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,8 +15,8 @@ from typing import List, Optional from pydantic import BaseModel -from models.page_info import PageInfo -from models.resource_association_response import ( +from infobip.models.page_info import PageInfo +from infobip.models.resource_association_response import ( ResourceAssociationResponse, ) diff --git a/models/resource_association_request.py b/infobip/models/resource_association_request.py similarity index 96% rename from models/resource_association_request.py rename to infobip/models/resource_association_request.py index 430d28a..2ba4273 100644 --- a/models/resource_association_request.py +++ b/infobip/models/resource_association_request.py @@ -8,15 +8,14 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json from pydantic import BaseModel, Field, constr -from models.channel import Channel -from models.resource_type import ResourceType +from infobip.models.channel import Channel +from infobip.models.resource_type import ResourceType class ResourceAssociationRequest(BaseModel): diff --git a/models/resource_association_response.py b/infobip/models/resource_association_response.py similarity index 96% rename from models/resource_association_response.py rename to infobip/models/resource_association_response.py index d42b4a5..5368586 100644 --- a/models/resource_association_response.py +++ b/infobip/models/resource_association_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,8 +15,8 @@ from typing import Optional from pydantic import BaseModel, Field, constr -from models.channel import Channel -from models.resource_type import ResourceType +from infobip.models.channel import Channel +from infobip.models.resource_type import ResourceType class ResourceAssociationResponse(BaseModel): diff --git a/models/resource_type.py b/infobip/models/resource_type.py similarity index 100% rename from models/resource_type.py rename to infobip/models/resource_type.py diff --git a/models/sms_advanced_binary_request.py b/infobip/models/sms_advanced_binary_request.py similarity index 95% rename from models/sms_advanced_binary_request.py rename to infobip/models/sms_advanced_binary_request.py index 5806199..9613422 100644 --- a/models/sms_advanced_binary_request.py +++ b/infobip/models/sms_advanced_binary_request.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,8 +15,8 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictStr -from models.sms_binary_message import SmsBinaryMessage -from models.sms_sending_speed_limit import SmsSendingSpeedLimit +from infobip.models.sms_binary_message import SmsBinaryMessage +from infobip.models.sms_sending_speed_limit import SmsSendingSpeedLimit class SmsAdvancedBinaryRequest(BaseModel): diff --git a/models/sms_advanced_textual_request.py b/infobip/models/sms_advanced_textual_request.py similarity index 94% rename from models/sms_advanced_textual_request.py rename to infobip/models/sms_advanced_textual_request.py index 3d1ae2d..478c008 100644 --- a/models/sms_advanced_textual_request.py +++ b/infobip/models/sms_advanced_textual_request.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,10 +15,10 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictStr -from models.sms_sending_speed_limit import SmsSendingSpeedLimit -from models.sms_textual_message import Message -from models.sms_tracking import SmsTracking -from models.sms_url_options import SmsUrlOptions +from infobip.models.sms_sending_speed_limit import SmsSendingSpeedLimit +from infobip.models.sms_textual_message import Message +from infobip.models.sms_tracking import SmsTracking +from infobip.models.sms_url_options import SmsUrlOptions class SendSMSRequestBody(BaseModel): diff --git a/models/sms_binary_content.py b/infobip/models/sms_binary_content.py similarity index 100% rename from models/sms_binary_content.py rename to infobip/models/sms_binary_content.py diff --git a/models/sms_binary_message.py b/infobip/models/sms_binary_message.py similarity index 96% rename from models/sms_binary_message.py rename to infobip/models/sms_binary_message.py index 99fedf7..8c7085b 100644 --- a/models/sms_binary_message.py +++ b/infobip/models/sms_binary_message.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,10 +15,10 @@ from datetime import datetime from typing import List, Optional from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, constr -from models.sms_binary_content import SmsBinaryContent -from models.sms_delivery_time_window import SmsDeliveryTimeWindow -from models.sms_destination import Destination -from models.sms_regional_options import SmsRegionalOptions +from infobip.models.sms_binary_content import SmsBinaryContent +from infobip.models.sms_delivery_time_window import SmsDeliveryTimeWindow +from infobip.models.sms_destination import Destination +from infobip.models.sms_regional_options import SmsRegionalOptions class SmsBinaryMessage(BaseModel): diff --git a/models/sms_bulk_request.py b/infobip/models/sms_bulk_request.py similarity index 100% rename from models/sms_bulk_request.py rename to infobip/models/sms_bulk_request.py diff --git a/models/sms_bulk_response.py b/infobip/models/sms_bulk_response.py similarity index 100% rename from models/sms_bulk_response.py rename to infobip/models/sms_bulk_response.py diff --git a/models/sms_bulk_status.py b/infobip/models/sms_bulk_status.py similarity index 100% rename from models/sms_bulk_status.py rename to infobip/models/sms_bulk_status.py diff --git a/models/sms_bulk_status_response.py b/infobip/models/sms_bulk_status_response.py similarity index 96% rename from models/sms_bulk_status_response.py rename to infobip/models/sms_bulk_status_response.py index 5802f38..660b26c 100644 --- a/models/sms_bulk_status_response.py +++ b/infobip/models/sms_bulk_status_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import Optional from pydantic import BaseModel, Field, StrictStr -from models.sms_bulk_status import SmsBulkStatus +from infobip.models.sms_bulk_status import SmsBulkStatus class SmsBulkStatusResponse(BaseModel): diff --git a/models/sms_delivery_day.py b/infobip/models/sms_delivery_day.py similarity index 100% rename from models/sms_delivery_day.py rename to infobip/models/sms_delivery_day.py diff --git a/models/sms_delivery_result.py b/infobip/models/sms_delivery_result.py similarity index 96% rename from models/sms_delivery_result.py rename to infobip/models/sms_delivery_result.py index a60f239..51ba773 100644 --- a/models/sms_delivery_result.py +++ b/infobip/models/sms_delivery_result.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel -from models.sms_report import SmsReport +from infobip.models.sms_report import SmsReport class SmsDeliveryResult(BaseModel): diff --git a/models/sms_delivery_time_from.py b/infobip/models/sms_delivery_time_from.py similarity index 100% rename from models/sms_delivery_time_from.py rename to infobip/models/sms_delivery_time_from.py diff --git a/models/sms_delivery_time_to.py b/infobip/models/sms_delivery_time_to.py similarity index 100% rename from models/sms_delivery_time_to.py rename to infobip/models/sms_delivery_time_to.py diff --git a/models/sms_delivery_time_window.py b/infobip/models/sms_delivery_time_window.py similarity index 93% rename from models/sms_delivery_time_window.py rename to infobip/models/sms_delivery_time_window.py index a5e8031..92caa02 100644 --- a/models/sms_delivery_time_window.py +++ b/infobip/models/sms_delivery_time_window.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,9 +15,9 @@ from typing import List, Optional from pydantic import BaseModel, Field -from models.sms_delivery_day import SmsDeliveryDay -from models.sms_delivery_time_from import SmsDeliveryTimeFrom -from models.sms_delivery_time_to import SmsDeliveryTimeTo +from infobip.models.sms_delivery_day import SmsDeliveryDay +from infobip.models.sms_delivery_time_from import SmsDeliveryTimeFrom +from infobip.models.sms_delivery_time_to import SmsDeliveryTimeTo class SmsDeliveryTimeWindow(BaseModel): diff --git a/models/sms_destination.py b/infobip/models/sms_destination.py similarity index 100% rename from models/sms_destination.py rename to infobip/models/sms_destination.py diff --git a/models/sms_error.py b/infobip/models/sms_error.py similarity index 100% rename from models/sms_error.py rename to infobip/models/sms_error.py diff --git a/models/sms_inbound_message.py b/infobip/models/sms_inbound_message.py similarity index 98% rename from models/sms_inbound_message.py rename to infobip/models/sms_inbound_message.py index bfba2c7..cb86548 100644 --- a/models/sms_inbound_message.py +++ b/infobip/models/sms_inbound_message.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from datetime import datetime from typing import Optional from pydantic import BaseModel, Field, StrictInt, StrictStr -from models.sms_price import SmsPrice +from infobip.models.sms_price import SmsPrice class SmsInboundMessage(BaseModel): diff --git a/models/sms_inbound_message_result.py b/infobip/models/sms_inbound_message_result.py similarity index 97% rename from models/sms_inbound_message_result.py rename to infobip/models/sms_inbound_message_result.py index a7e06f3..fe64e65 100644 --- a/models/sms_inbound_message_result.py +++ b/infobip/models/sms_inbound_message_result.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictInt -from models.sms_inbound_message import SmsInboundMessage +from infobip.models.sms_inbound_message import SmsInboundMessage class SmsInboundMessageResult(BaseModel): diff --git a/models/sms_india_dlt_options.py b/infobip/models/sms_india_dlt_options.py similarity index 100% rename from models/sms_india_dlt_options.py rename to infobip/models/sms_india_dlt_options.py diff --git a/models/sms_language.py b/infobip/models/sms_language.py similarity index 100% rename from models/sms_language.py rename to infobip/models/sms_language.py diff --git a/models/sms_language_configuration.py b/infobip/models/sms_language_configuration.py similarity index 97% rename from models/sms_language_configuration.py rename to infobip/models/sms_language_configuration.py index a6238f7..07ee0c7 100644 --- a/models/sms_language_configuration.py +++ b/infobip/models/sms_language_configuration.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import Optional from pydantic import BaseModel, Field, StrictStr -from models.sms_language import SmsLanguage +from infobip.models.sms_language import SmsLanguage class SmsLanguageConfiguration(BaseModel): diff --git a/models/sms_log.py b/infobip/models/sms_log.py similarity index 97% rename from models/sms_log.py rename to infobip/models/sms_log.py index 12614c0..9f86d7c 100644 --- a/models/sms_log.py +++ b/infobip/models/sms_log.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,9 +15,9 @@ from datetime import datetime from typing import Optional from pydantic import BaseModel, Field, StrictInt, StrictStr -from models.sms_error import SmsError -from models.sms_price import SmsPrice -from models.sms_status import SmsStatus +from infobip.models.sms_error import SmsError +from infobip.models.sms_price import SmsPrice +from infobip.models.sms_status import SmsStatus class SmsLog(BaseModel): diff --git a/models/sms_logs_response.py b/infobip/models/sms_logs_response.py similarity index 97% rename from models/sms_logs_response.py rename to infobip/models/sms_logs_response.py index 2d2d178..07ff6f2 100644 --- a/models/sms_logs_response.py +++ b/infobip/models/sms_logs_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel, Field -from models.sms_log import SmsLog +from infobip.models.sms_log import SmsLog class SmsLogsResponse(BaseModel): diff --git a/models/sms_preview.py b/infobip/models/sms_preview.py similarity index 96% rename from models/sms_preview.py rename to infobip/models/sms_preview.py index 3f91759..36fd30a 100644 --- a/models/sms_preview.py +++ b/infobip/models/sms_preview.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import Optional from pydantic import BaseModel, Field, StrictInt, StrictStr -from models.sms_language_configuration import SmsLanguageConfiguration +from infobip.models.sms_language_configuration import SmsLanguageConfiguration class SmsPreview(BaseModel): diff --git a/models/sms_preview_request.py b/infobip/models/sms_preview_request.py similarity index 100% rename from models/sms_preview_request.py rename to infobip/models/sms_preview_request.py diff --git a/models/sms_preview_response.py b/infobip/models/sms_preview_response.py similarity index 97% rename from models/sms_preview_response.py rename to infobip/models/sms_preview_response.py index 3109eba..60e4fa2 100644 --- a/models/sms_preview_response.py +++ b/infobip/models/sms_preview_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictStr -from models.sms_preview import SmsPreview +from infobip.models.sms_preview import SmsPreview class PreviewSMSResponseBody(BaseModel): diff --git a/models/sms_price.py b/infobip/models/sms_price.py similarity index 100% rename from models/sms_price.py rename to infobip/models/sms_price.py diff --git a/models/sms_regional_options.py b/infobip/models/sms_regional_options.py similarity index 94% rename from models/sms_regional_options.py rename to infobip/models/sms_regional_options.py index 253ffce..46d758b 100644 --- a/models/sms_regional_options.py +++ b/infobip/models/sms_regional_options.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,8 +15,8 @@ from typing import Optional from pydantic import BaseModel, Field -from models.sms_india_dlt_options import SmsIndiaDltOptions -from models.sms_turkey_iys_options import SmsTurkeyIysOptions +from infobip.models.sms_india_dlt_options import SmsIndiaDltOptions +from infobip.models.sms_turkey_iys_options import SmsTurkeyIysOptions class SmsRegionalOptions(BaseModel): diff --git a/models/sms_report.py b/infobip/models/sms_report.py similarity index 97% rename from models/sms_report.py rename to infobip/models/sms_report.py index 3ec835b..9d116d8 100644 --- a/models/sms_report.py +++ b/infobip/models/sms_report.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,9 +15,9 @@ from datetime import datetime from typing import Optional from pydantic import BaseModel, Field, StrictInt, StrictStr -from models.sms_error import SmsError -from models.sms_price import SmsPrice -from models.sms_status import SmsStatus +from infobip.models.sms_error import SmsError +from infobip.models.sms_price import SmsPrice +from infobip.models.sms_status import SmsStatus class SmsReport(BaseModel): diff --git a/models/sms_response.py b/infobip/models/sms_response.py similarity index 96% rename from models/sms_response.py rename to infobip/models/sms_response.py index a8361ac..218097c 100644 --- a/models/sms_response.py +++ b/infobip/models/sms_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictStr -from models.sms_response_details import SmsResponseDetails +from infobip.models.sms_response_details import SmsResponseDetails class SmsResponse(BaseModel): diff --git a/models/sms_response_details.py b/infobip/models/sms_response_details.py similarity index 97% rename from models/sms_response_details.py rename to infobip/models/sms_response_details.py index 3f20f55..c393478 100644 --- a/models/sms_response_details.py +++ b/infobip/models/sms_response_details.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import Optional from pydantic import BaseModel, Field, StrictStr -from models.sms_status import SmsStatus +from infobip.models.sms_status import SmsStatus class SmsResponseDetails(BaseModel): diff --git a/models/sms_sending_speed_limit.py b/infobip/models/sms_sending_speed_limit.py similarity index 95% rename from models/sms_sending_speed_limit.py rename to infobip/models/sms_sending_speed_limit.py index 1d8c7c9..2d8ab6a 100644 --- a/models/sms_sending_speed_limit.py +++ b/infobip/models/sms_sending_speed_limit.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import Optional from pydantic import BaseModel, Field, StrictInt -from models.sms_speed_limit_time_unit import SmsSpeedLimitTimeUnit +from infobip.models.sms_speed_limit_time_unit import SmsSpeedLimitTimeUnit class SmsSendingSpeedLimit(BaseModel): diff --git a/models/sms_speed_limit_time_unit.py b/infobip/models/sms_speed_limit_time_unit.py similarity index 100% rename from models/sms_speed_limit_time_unit.py rename to infobip/models/sms_speed_limit_time_unit.py diff --git a/models/sms_status.py b/infobip/models/sms_status.py similarity index 100% rename from models/sms_status.py rename to infobip/models/sms_status.py diff --git a/models/sms_textual_message.py b/infobip/models/sms_textual_message.py similarity index 97% rename from models/sms_textual_message.py rename to infobip/models/sms_textual_message.py index b76a71e..1ae4018 100644 --- a/models/sms_textual_message.py +++ b/infobip/models/sms_textual_message.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,10 +15,10 @@ from datetime import datetime from typing import List, Optional from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, constr -from models.sms_delivery_time_window import SmsDeliveryTimeWindow -from models.sms_destination import Destination -from models.sms_language import SmsLanguage -from models.sms_regional_options import SmsRegionalOptions +from infobip.models.sms_delivery_time_window import SmsDeliveryTimeWindow +from infobip.models.sms_destination import Destination +from infobip.models.sms_language import SmsLanguage +from infobip.models.sms_regional_options import SmsRegionalOptions class Message(BaseModel): diff --git a/models/sms_tracking.py b/infobip/models/sms_tracking.py similarity index 100% rename from models/sms_tracking.py rename to infobip/models/sms_tracking.py diff --git a/models/sms_turkey_iys_options.py b/infobip/models/sms_turkey_iys_options.py similarity index 100% rename from models/sms_turkey_iys_options.py rename to infobip/models/sms_turkey_iys_options.py diff --git a/models/sms_update_status_request.py b/infobip/models/sms_update_status_request.py similarity index 95% rename from models/sms_update_status_request.py rename to infobip/models/sms_update_status_request.py index de9a9af..fd95c28 100644 --- a/models/sms_update_status_request.py +++ b/infobip/models/sms_update_status_request.py @@ -8,14 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json from pydantic import BaseModel -from models.sms_bulk_status import SmsBulkStatus +from infobip.models.sms_bulk_status import SmsBulkStatus class SmsUpdateStatusRequest(BaseModel): diff --git a/models/sms_url_options.py b/infobip/models/sms_url_options.py similarity index 100% rename from models/sms_url_options.py rename to infobip/models/sms_url_options.py diff --git a/models/sms_webhook_inbound_report.py b/infobip/models/sms_webhook_inbound_report.py similarity index 98% rename from models/sms_webhook_inbound_report.py rename to infobip/models/sms_webhook_inbound_report.py index f2fedc5..6ae4820 100644 --- a/models/sms_webhook_inbound_report.py +++ b/infobip/models/sms_webhook_inbound_report.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from datetime import datetime from typing import Optional from pydantic import BaseModel, Field, StrictInt, StrictStr -from models.message_price import MessagePrice +from infobip.models.message_price import MessagePrice class SmsWebhookInboundReport(BaseModel): diff --git a/models/sms_webhook_inbound_report_response.py b/infobip/models/sms_webhook_inbound_report_response.py similarity index 96% rename from models/sms_webhook_inbound_report_response.py rename to infobip/models/sms_webhook_inbound_report_response.py index 412a5c7..f085875 100644 --- a/models/sms_webhook_inbound_report_response.py +++ b/infobip/models/sms_webhook_inbound_report_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel, Field, StrictInt -from models.sms_webhook_inbound_report import SmsWebhookInboundReport +from infobip.models.sms_webhook_inbound_report import SmsWebhookInboundReport class SmsWebhookInboundReportResponse(BaseModel): diff --git a/models/sms_webhook_outbound_report.py b/infobip/models/sms_webhook_outbound_report.py similarity index 96% rename from models/sms_webhook_outbound_report.py rename to infobip/models/sms_webhook_outbound_report.py index d3bc8dd..4b51493 100644 --- a/models/sms_webhook_outbound_report.py +++ b/infobip/models/sms_webhook_outbound_report.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,9 +15,9 @@ from datetime import datetime from typing import Optional from pydantic import BaseModel, Field, StrictInt, StrictStr -from models.message_error import MessageError -from models.message_price import MessagePrice -from models.message_status import MessageStatus +from infobip.models.message_error import MessageError +from infobip.models.message_price import MessagePrice +from infobip.models.message_status import MessageStatus class SmsWebhookOutboundReport(BaseModel): diff --git a/models/sms_webhook_outbound_report_response.py b/infobip/models/sms_webhook_outbound_report_response.py similarity index 96% rename from models/sms_webhook_outbound_report_response.py rename to infobip/models/sms_webhook_outbound_report_response.py index 8f7df8a..b941cf1 100644 --- a/models/sms_webhook_outbound_report_response.py +++ b/infobip/models/sms_webhook_outbound_report_response.py @@ -8,7 +8,6 @@ from __future__ import annotations -from inspect import getfullargspec import pprint import re # noqa: F401 import json @@ -16,7 +15,7 @@ from typing import List, Optional from pydantic import BaseModel, Field -from models.sms_webhook_outbound_report import SmsWebhookOutboundReport +from infobip.models.sms_webhook_outbound_report import SmsWebhookOutboundReport class SmsWebhookOutboundReportResponse(BaseModel): diff --git a/models/webhook_message_count.py b/infobip/models/webhook_message_count.py similarity index 100% rename from models/webhook_message_count.py rename to infobip/models/webhook_message_count.py diff --git a/models/__init__.py b/models/__init__.py deleted file mode 100644 index 975e504..0000000 --- a/models/__init__.py +++ /dev/null @@ -1,251 +0,0 @@ -# coding: utf-8 - -# flake8: noqa -""" - This class is auto generated from the Infobip OpenAPI specification - through the OpenAPI Specification Client API libraries (Re)Generator (OSCAR), - powered by the OpenAPI Generator (https://openapi-generator.tech). -""" - - -from __future__ import absolute_import - -# import models into model package -from models.application import Application -from models.channel import Channel -from models.entity import Entity -from models.message_error import MessageError -from models.message_price import MessagePrice -from models.message_status import MessageStatus -from models.mms_advanced_message import MmsAdvancedMessage -from models.mms_advanced_message_segment import MmsAdvancedMessageSegment -from models.mms_advanced_message_segment_binary import ( - MmsAdvancedMessageSegmentBinary, -) -from models.mms_advanced_message_segment_link import ( - MmsAdvancedMessageSegmentLink, -) -from models.mms_advanced_message_segment_smil import ( - MmsAdvancedMessageSegmentSmil, -) -from models.mms_advanced_message_segment_text import ( - MmsAdvancedMessageSegmentText, -) -from models.mms_advanced_message_segment_upload_reference import ( - MmsAdvancedMessageSegmentUploadReference, -) -from models.mms_advanced_request import MmsAdvancedRequest -from models.mms_delivery_day import MmsDeliveryDay -from models.mms_delivery_time import MmsDeliveryTime -from models.mms_delivery_time_window import MmsDeliveryTimeWindow -from models.mms_destination import MmsDestination -from models.mms_error import MmsError -from models.mms_inbound_report import MmsInboundReport -from models.mms_inbound_report_response import MMSInboundReportResponse -from models.mms_message_result import MmsMessageResult -from models.mms_price import MmsPrice -from models.mms_report import MmsReport -from models.mms_report_response import MmsReportResponse -from models.mms_send_result import MmsSendResult -from models.mms_status import MmsStatus -from models.mms_upload_binary_result import MmsUploadBinaryResult -from models.mms_webhook_inbound_message_segment import ( - MmsWebhookInboundMessageSegment, -) -from models.mms_webhook_inbound_message_segment_link import ( - MmsWebhookInboundMessageSegmentLink, -) -from models.mms_webhook_inbound_message_segment_text import ( - MmsWebhookInboundMessageSegmentText, -) -from models.mms_webhook_inbound_report import MmsWebhookInboundReport -from models.mms_webhook_inbound_report_response import ( - MmsWebhookInboundReportResponse, -) -from models.mms_webhook_outbound_report import MmsWebhookOutboundReport -from models.mms_webhook_outbound_report_response import ( - MmsWebhookOutboundReportResponse, -) -from models.modify_application import ModifyApplication -from models.modify_entity import ModifyEntity -from models.number_price import NumberPrice -from models.number_registration_address import NumberRegistrationAddress -from models.number_registration_brand import NumberRegistrationBrand -from models.number_registration_brand_preview import ( - NumberRegistrationBrandPreview, -) -from models.number_registration_brand_status import ( - NumberRegistrationBrandStatus, -) -from models.number_registration_brand_vet import ( - NumberRegistrationBrandVet, -) -from models.number_registration_business_identifier import ( - NumberRegistrationBusinessIdentifier, -) -from models.number_registration_campaign import ( - NumberRegistrationCampaign, -) -from models.number_registration_data_universal_numbering_system_number import ( - NumberRegistrationDataUniversalNumberingSystemNumber, -) -from models.number_registration_document_metadata import ( - NumberRegistrationDocumentMetadata, -) -from models.number_registration_external_ten_dlc_campaign import ( - NumberRegistrationExternalTenDlcCampaign, -) -from models.number_registration_global_intermediary_identification_number import ( - NumberRegistrationGlobalIntermediaryIdentificationNumber, -) -from models.number_registration_government_brand import ( - NumberRegistrationGovernmentBrand, -) -from models.number_registration_interactive_voice_response_opt_in import ( - NumberRegistrationInteractiveVoiceResponseOptIn, -) -from models.number_registration_keyword_opt_in import ( - NumberRegistrationKeywordOptIn, -) -from models.number_registration_legal_entity_identifier import ( - NumberRegistrationLegalEntityIdentifier, -) -from models.number_registration_network_status import ( - NumberRegistrationNetworkStatus, -) -from models.number_registration_non_profit_brand import ( - NumberRegistrationNonProfitBrand, -) -from models.number_registration_number_preview import ( - NumberRegistrationNumberPreview, -) -from models.number_registration_opt_ins import NumberRegistrationOptIns -from models.number_registration_page_info import ( - NumberRegistrationPageInfo, -) -from models.number_registration_page_response_brand import ( - NumberRegistrationPageResponseBrand, -) -from models.number_registration_page_response_brand_vet import ( - NumberRegistrationPageResponseBrandVet, -) -from models.number_registration_page_response_campaign import ( - NumberRegistrationPageResponseCampaign, -) -from models.number_registration_private_company_brand import ( - NumberRegistrationPrivateCompanyBrand, -) -from models.number_registration_public_company_brand import ( - NumberRegistrationPublicCompanyBrand, -) -from models.number_registration_ten_dlc_campaign import ( - NumberRegistrationTenDlcCampaign, -) -from models.number_registration_update_brand_request import ( - NumberRegistrationUpdateBrandRequest, -) -from models.number_registration_update_campaign_request import ( - NumberRegistrationUpdateCampaignRequest, -) -from models.number_registration_verbal_opt_in import ( - NumberRegistrationVerbalOptIn, -) -from models.number_registration_web_opt_in import ( - NumberRegistrationWebOptIn, -) -from models.number_response import NumberResponse -from models.numbers_auto_response_action import NumbersAutoResponseAction -from models.numbers_block_action import NumbersBlockAction -from models.numbers_delivery_time_window import NumbersDeliveryTimeWindow -from models.numbers_edit_permissions import NumbersEditPermissions -from models.numbers_forward_to_ivr_action_details import ( - NumbersForwardToIvrActionDetails, -) -from models.numbers_forward_to_subscription_details import ( - NumbersForwardToSubscriptionDetails, -) -from models.numbers_http_forward_action import NumbersHttpForwardAction -from models.numbers_mail_forward_action import NumbersMailForwardAction -from models.numbers_mo_action import NumbersMoAction -from models.numbers_mo_configuration import NumbersMoConfiguration -from models.numbers_mo_configurations import NumbersMoConfigurations -from models.numbers_mo_non_forward_action import ( - NumbersMoNonForwardAction, -) -from models.numbers_no_action import NumbersNoAction -from models.numbers_pull_action import NumbersPullAction -from models.numbers_purchase_number_request import ( - NumbersPurchaseNumberRequest, -) -from models.numbers_response import NumbersResponse -from models.numbers_smpp_forward_action import NumbersSmppForwardAction -from models.numbers_stored_mo_configuration import ( - NumbersStoredMoConfiguration, -) -from models.numbers_use_conversation import NumbersUseConversation -from models.numbers_voice_action_details import NumbersVoiceActionDetails -from models.numbers_voice_call_forward_to_application_details import ( - NumbersVoiceCallForwardToApplicationDetails, -) -from models.numbers_voice_number_masking_action_details import ( - NumbersVoiceNumberMaskingActionDetails, -) -from models.numbers_voice_setup import NumbersVoiceSetup -from models.page_application import PageApplication -from models.page_entity import PageEntity -from models.page_info import PageInfo -from models.page_resource_association import PageResourceAssociation -from models.resource_association_request import ( - ResourceAssociationRequest, -) -from models.resource_association_response import ( - ResourceAssociationResponse, -) -from models.resource_type import ResourceType -from models.sms_advanced_binary_request import SmsAdvancedBinaryRequest -from models.sms_advanced_textual_request import SendSMSRequestBody -from models.sms_binary_content import SmsBinaryContent -from models.sms_binary_message import SmsBinaryMessage -from models.sms_bulk_request import SmsBulkRequest -from models.sms_bulk_response import SmsBulkResponse -from models.sms_bulk_status import SmsBulkStatus -from models.sms_bulk_status_response import SmsBulkStatusResponse -from models.sms_delivery_day import SmsDeliveryDay -from models.sms_delivery_result import SmsDeliveryResult -from models.sms_delivery_time_from import SmsDeliveryTimeFrom -from models.sms_delivery_time_to import SmsDeliveryTimeTo -from models.sms_delivery_time_window import SmsDeliveryTimeWindow -from models.sms_destination import Destination -from models.sms_error import SmsError -from models.sms_inbound_message import SmsInboundMessage -from models.sms_inbound_message_result import SmsInboundMessageResult -from models.sms_india_dlt_options import SmsIndiaDltOptions -from models.sms_language import SmsLanguage -from models.sms_language_configuration import SmsLanguageConfiguration -from models.sms_log import SmsLog -from models.sms_logs_response import SmsLogsResponse -from models.sms_preview import SmsPreview -from models.sms_preview_request import PreviewSMSRequestBody -from models.sms_preview_response import PreviewSMSResponseBody -from models.sms_price import SmsPrice -from models.sms_regional_options import SmsRegionalOptions -from models.sms_report import SmsReport -from models.sms_response import SmsResponse -from models.sms_response_details import SmsResponseDetails -from models.sms_sending_speed_limit import SmsSendingSpeedLimit -from models.sms_speed_limit_time_unit import SmsSpeedLimitTimeUnit -from models.sms_status import SmsStatus -from models.sms_textual_message import Message -from models.sms_tracking import SmsTracking -from models.sms_turkey_iys_options import SmsTurkeyIysOptions -from models.sms_update_status_request import SmsUpdateStatusRequest -from models.sms_url_options import SmsUrlOptions -from models.sms_webhook_inbound_report import SmsWebhookInboundReport -from models.sms_webhook_inbound_report_response import ( - SmsWebhookInboundReportResponse, -) -from models.sms_webhook_outbound_report import SmsWebhookOutboundReport -from models.sms_webhook_outbound_report_response import ( - SmsWebhookOutboundReportResponse, -) -from models.webhook_message_count import WebhookMessageCount diff --git a/samples/test_mms_live.py b/samples/test_mms_live.py index 79470dc..e150a64 100644 --- a/samples/test_mms_live.py +++ b/samples/test_mms_live.py @@ -1,14 +1,14 @@ import unittest -from client import InfobipAPIClient -from models import MMSInboundReportResponse -from models.mms_get_inbound_messages_query_parameters import GetInboundMessagesQueryParameters +from infobip.client import InfobipAPIClient +from infobip.models.mms_get_inbound_messages_query_parameters import GetInboundMessagesQueryParameters +from infobip.models.mms_inbound_report_response import GetInboundMessagesResponseBody class MMSTestCase(unittest.IsolatedAsyncioTestCase): client = InfobipAPIClient() - async def test_preview_message(self): + async def test_get_inbound_messages(self): # Create query parameters object and validate its contents. params = GetInboundMessagesQueryParameters( limit=10, @@ -18,7 +18,7 @@ async def test_preview_message(self): response = await self.client.MMS.get_inbound_messages(params) # Parse and validate response if needed. - response_body = MMSInboundReportResponse.from_json(response.text) + response_body = GetInboundMessagesResponseBody.from_json(response.text) # Do something with the response. print(response) diff --git a/samples/test_sms_live.py b/samples/test_sms_live.py index 5b8d615..cf70cf4 100644 --- a/samples/test_sms_live.py +++ b/samples/test_sms_live.py @@ -1,9 +1,11 @@ import unittest -from client import InfobipAPIClient -from models import SendSMSRequestBody, Message, Destination -from models.sms_preview_request import PreviewSMSRequestBody -from models.sms_preview_response import PreviewSMSResponseBody +from infobip.client import InfobipAPIClient +from infobip.models.sms_advanced_textual_request import SendSMSRequestBody +from infobip.models.sms_destination import Destination +from infobip.models.sms_preview_request import PreviewSMSRequestBody +from infobip.models.sms_preview_response import PreviewSMSResponseBody +from infobip.models.sms_textual_message import Message class SMSTestCase(unittest.IsolatedAsyncioTestCase): diff --git a/tests/test_sms.py b/tests/test_sms.py index d1f538a..43d586c 100644 --- a/tests/test_sms.py +++ b/tests/test_sms.py @@ -2,7 +2,7 @@ import unittest -from client import InfobipAPIClient +from infobip.client import InfobipAPIClient from http_server_mock import HttpServerMock From e6952ff0c63672615df71045498bd658a6aded11 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Fri, 5 May 2023 13:24:04 -0600 Subject: [PATCH 04/18] Update Readme to use new SDK design --- README.md | 84 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index f76dc98..345d833 100644 --- a/README.md +++ b/README.md @@ -40,11 +40,11 @@ once more authentication methods are included. To install infobip SDK you will need to run: ```bash -pip install infobip-api-python-sdk +pip install infobip ``` Details of the package can be found -in the [PyPI page](https://pypi.org/project/infobip-api-python-sdk/). +in the [PyPI page](https://pypi.org/project/infobip/). ## 🚀 Usage @@ -53,45 +53,51 @@ To use the package you'll need an Infobip account. If you don't already have one, you can create a free trial account [here](https://www.infobip.com/signup). -In this example, we will show how to send a WhatsApp text message. +In this example, we will show how to send an SMS message. Other channels can be used in a similar way. -The first step is to import the necessary channel, in this case WhatsApp channel. +The first step is to import the Infobip API Client and needed models. +Then you can use a context manager to create the client, and use it to call the API. +After calling the endpoint, you can parse the response into a response body object. +This code ```python -from infobip_channels.whatsapp.channel import WhatsAppChannel -``` - -Now you can create instance of `WhatsAppChannel` with your `base_url` and `api_key`. - -```python -c = WhatsAppChannel.from_auth_params({ - "base_url": "", - "api_key": "" -}) -``` - -Alternatively, you can create the instance from the environment, having the `IB_BASE_URL` and `IB_API_KEY` variables -set, like this: - -```python -c = WhatsAppChannel.from_env() -``` - -After that you can access all the methods from `WhatsAppChannel`. -To send text message you can use `send_text_message` method and add correct payload: -```python -response = c.send_text_message( - { - "from": "", - "to": "", - "messageId": "a28dd97c-1ffb-4fcf-99f1-0b557ed381da", - "content": { - "text": "Some text" - }, - "callbackData": "Callback data", - "notifyUrl": "https://www.example.com/whatsapp" - } -) +import asyncio +from infobip.client import APIClient +from infobip.models.sms_advanced_textual_request import SendSMSRequestBody +from infobip.models.sms_textual_message import Message +from infobip.models.sms_destination import Destination +from infobip.models.sms_response import SendSMSResponseBody + + +async def main(): + with APIClient() as client: + # Create a request body object and validate its contents. + request_body = SendSMSRequestBody( + messages=[ + Message( + destinations=[ + Destination( + to="555555555555", + ), + ], + text="Hello from Infobip Python SDK!", + ) + ] + ) + + # Call the endpoint and await returned Coroutine + response = await client.SMS.send(request_body) + + # (Optional) Parse and validate response. + response_body = SendSMSResponseBody.from_json(response.text) + + # Do something with the response. + print(response) + print(response_body) + + +if __name__ == "__main__": + asyncio.run(main()) ``` ### Samples @@ -101,7 +107,7 @@ with real payloads. ## 🗒️ Notes -For `infobip-api-python-sdk` versioning we use +For SDK versioning we use [Semantic Versioning](https://semver.org) scheme. Python 3.6 is the minimum supported version by this library. From 823d840e46f35782b8a46e710386034516f6cd39 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Fri, 5 May 2023 13:25:07 -0600 Subject: [PATCH 05/18] Improve naming, add initial mock test --- infobip/api/mms.py | 8 +- infobip/client.py | 2 +- ...s_get_inbound_messages_query_parameters.py | 2 +- infobip/models/sms_response.py | 10 +-- requirements.txt | 3 +- samples/test_mms_live.py | 8 +- samples/test_sms_live.py | 7 +- setup.cfg | 6 +- tests/common.py | 8 ++ tests/test_sms.py | 80 +++++++++---------- 10 files changed, 70 insertions(+), 64 deletions(-) create mode 100644 tests/common.py diff --git a/infobip/api/mms.py b/infobip/api/mms.py index 98722e2..c519428 100644 --- a/infobip/api/mms.py +++ b/infobip/api/mms.py @@ -2,7 +2,9 @@ from httpx import Response, AsyncClient -from infobip.models.mms_get_inbound_messages_query_parameters import GetInboundMessagesQueryParameters +from infobip.models.mms_get_inbound_messages_query_parameters import ( + GetInboundMessagesQueryParameters, +) class MMSClient: @@ -12,8 +14,8 @@ def __init__(self, client: AsyncClient): self.client = client def get_inbound_messages( - self, - query_parameters: GetInboundMessagesQueryParameters, + self, + query_parameters: GetInboundMessagesQueryParameters, ) -> Awaitable[Response]: """Get inbound messages diff --git a/infobip/client.py b/infobip/client.py index fb43354..63453fc 100644 --- a/infobip/client.py +++ b/infobip/client.py @@ -5,7 +5,7 @@ from infobip.api.sms import SMSClient -class InfobipAPIClient(AsyncClient): +class APIClient(AsyncClient): def __init__(self, base_url=None, api_key: str = None): if base_url is None: base_url = getenv("IB_BASE_URL") diff --git a/infobip/models/mms_get_inbound_messages_query_parameters.py b/infobip/models/mms_get_inbound_messages_query_parameters.py index cb205f1..02ebedb 100644 --- a/infobip/models/mms_get_inbound_messages_query_parameters.py +++ b/infobip/models/mms_get_inbound_messages_query_parameters.py @@ -13,7 +13,7 @@ class GetInboundMessagesQueryParameters(BaseModel): limit: Optional[StrictInt] = Field( None, alias="limit", - description="Maximum number of delivery reports that will be returned." + description="Maximum number of delivery reports that will be returned.", ) __properties = [ diff --git a/infobip/models/sms_response.py b/infobip/models/sms_response.py index 218097c..68fa173 100644 --- a/infobip/models/sms_response.py +++ b/infobip/models/sms_response.py @@ -18,7 +18,7 @@ from infobip.models.sms_response_details import SmsResponseDetails -class SmsResponse(BaseModel): +class SendSMSResponseBody(BaseModel): """NOTE: This class is auto generated by OpenAPI Generator. Ref: https://openapi-generator.tech @@ -49,7 +49,7 @@ def to_json(self) -> str: return json.dumps(self.to_dict()) @classmethod - def from_json(cls, json_str: str) -> SmsResponse: + def from_json(cls, json_str: str) -> SendSMSResponseBody: """Create an instance of SmsResponse from a JSON string""" return cls.from_dict(json.loads(json_str)) @@ -66,15 +66,15 @@ def to_dict(self): return _dict @classmethod - def from_dict(cls, obj: dict) -> SmsResponse: + def from_dict(cls, obj: dict) -> SendSMSResponseBody: """Create an instance of SmsResponse from a dict""" if obj is None: return None if type(obj) is not dict: - return SmsResponse.parse_obj(obj) + return SendSMSResponseBody.parse_obj(obj) - _obj = SmsResponse.parse_obj( + _obj = SendSMSResponseBody.parse_obj( { "bulk_id": obj.get("bulkId"), "messages": [ diff --git a/requirements.txt b/requirements.txt index 657d93c..aae8069 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ pydantic~=1.10.7 httpx~=0.24.0 -aenum~=3.1.12 \ No newline at end of file +aenum~=3.1.12 +pytest~=7.3.1 \ No newline at end of file diff --git a/samples/test_mms_live.py b/samples/test_mms_live.py index e150a64..d254662 100644 --- a/samples/test_mms_live.py +++ b/samples/test_mms_live.py @@ -1,12 +1,14 @@ import unittest -from infobip.client import InfobipAPIClient -from infobip.models.mms_get_inbound_messages_query_parameters import GetInboundMessagesQueryParameters +from infobip.client import APIClient +from infobip.models.mms_get_inbound_messages_query_parameters import ( + GetInboundMessagesQueryParameters, +) from infobip.models.mms_inbound_report_response import GetInboundMessagesResponseBody class MMSTestCase(unittest.IsolatedAsyncioTestCase): - client = InfobipAPIClient() + client = APIClient() async def test_get_inbound_messages(self): # Create query parameters object and validate its contents. diff --git a/samples/test_sms_live.py b/samples/test_sms_live.py index cf70cf4..a396958 100644 --- a/samples/test_sms_live.py +++ b/samples/test_sms_live.py @@ -1,15 +1,16 @@ import unittest -from infobip.client import InfobipAPIClient +from infobip.client import APIClient from infobip.models.sms_advanced_textual_request import SendSMSRequestBody from infobip.models.sms_destination import Destination from infobip.models.sms_preview_request import PreviewSMSRequestBody from infobip.models.sms_preview_response import PreviewSMSResponseBody +from infobip.models.sms_response import SendSMSResponseBody from infobip.models.sms_textual_message import Message class SMSTestCase(unittest.IsolatedAsyncioTestCase): - client = InfobipAPIClient() + client = APIClient() async def test_preview_message(self): # Create a request body object and validate its contents. @@ -48,7 +49,7 @@ async def test_send_message(self): response = await self.client.SMS.send(request_body) # (Optional) Parse and validate response if needed. - response_body = PreviewSMSResponseBody.from_json(response.text) + response_body = SendSMSResponseBody.from_json(response.text) # Do something with the response. print(response) diff --git a/setup.cfg b/setup.cfg index 0e813fa..3e7d56a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [metadata] -name = infobip-api-python-sdk +name = infobip version = 5.0.0 author = Luka Kilic, Dino Lozina, Erick Corona author_email = DevRel@infobip.com @@ -21,9 +21,7 @@ package_dir = packages = find: python_requires = >=3.6 install_requires = - pydantic==1.9.0 - requests==2.27.1 - regex==2022.3.15 + pydantic~=1.9.0 [options.packages.find] where = . diff --git a/tests/common.py b/tests/common.py new file mode 100644 index 0000000..8de4ce4 --- /dev/null +++ b/tests/common.py @@ -0,0 +1,8 @@ +from infobip.client import APIClient + +TEST_URL = "https://some.url" +TEST_API_KEY = "some-api-key" + + +def get_test_client(): + return APIClient(base_url=TEST_URL, api_key=TEST_API_KEY) diff --git a/tests/test_sms.py b/tests/test_sms.py index 43d586c..9c9aec9 100644 --- a/tests/test_sms.py +++ b/tests/test_sms.py @@ -1,43 +1,37 @@ -# Test for validations - -import unittest - -from infobip.client import InfobipAPIClient -from http_server_mock import HttpServerMock - - -class TestSMS(unittest.IsolatedAsyncioTestCase): - client = InfobipAPIClient() - - async def test_preview_message(self): - expected_response = { - "bulkId": "2034072219640523072", - "messages": [ - { - "messageId": "2250be2d4219-3af1-78856-aabe-1362af1edfd2", - "status": { - "description": "Message sent to next instance", - "groupId": 1, - "groupName": "PENDING", - "id": 26, - "name": "MESSAGE_ACCEPTED" - }, - "to": "41793026727" - } - ] - } - - # Start the mock server - mock_server = HttpServerMock("localhost", 5000) - - with mock_server.run(): - client = InfobipAPIClient(base_url="http://localhost:5000") - - # Call the endpoint and await returned Coroutine - response = await self.client.SMS.preview_message("test") - - # Do something with the response. - print(response) - - self.assertEquals(response.status_code, 200) - self.assertEquals(response.json(), expected_response) +import pytest + +from common import TEST_URL, get_test_client +from infobip.models.sms_preview_request import PreviewSMSRequestBody +from infobip.models.sms_preview_response import PreviewSMSResponseBody + + +@pytest.mark.asyncio +async def test_preview_message(httpx_mock): + expected_response = { + "originalText": "Let's see how many characters remain unused in this message.", + "previews": [ + { + "textPreview": "Let's see how many characters remain unused in this message.", + "messageCount": 1, + "charactersRemaining": 96, + "configuration": {}, + } + ], + } + + async with get_test_client() as client: + httpx_mock.add_response( + url=f"{TEST_URL}{client.SMS.PATH_PREVIEW_SMS}", + method="POST", + json=expected_response, + status_code=200, + ) + + request_body = PreviewSMSRequestBody( + text="Let's see how many characters remain unused in this message.", + ) + + response = await client.SMS.preview_message(request_body) + + assert PreviewSMSResponseBody.from_json(response.text).to_dict() == expected_response + assert response.status_code == 200 From e6de0b3ee7150848532c7c343ccbad76f7ca8f42 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Fri, 5 May 2023 15:49:24 -0600 Subject: [PATCH 06/18] Add async to with statement --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 345d833..1a758ff 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Other channels can be used in a similar way. The first step is to import the Infobip API Client and needed models. Then you can use a context manager to create the client, and use it to call the API. After calling the endpoint, you can parse the response into a response body object. -This code +This code needs that you previously set the environment variables `IB_BASE_URL` and `IB_API_KEY`. ```python import asyncio @@ -70,7 +70,7 @@ from infobip.models.sms_response import SendSMSResponseBody async def main(): - with APIClient() as client: + async with APIClient() as client: # Create a request body object and validate its contents. request_body = SendSMSRequestBody( messages=[ From a6eb88192624e2ffe12bdff68e3fefd1d3fe3ad1 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Fri, 5 May 2023 15:49:52 -0600 Subject: [PATCH 07/18] Add send sms mock test --- tests/test_sms.py | 49 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/tests/test_sms.py b/tests/test_sms.py index 9c9aec9..949ea0e 100644 --- a/tests/test_sms.py +++ b/tests/test_sms.py @@ -1,8 +1,12 @@ import pytest from common import TEST_URL, get_test_client +from infobip.models.sms_advanced_textual_request import SendSMSRequestBody +from infobip.models.sms_destination import Destination from infobip.models.sms_preview_request import PreviewSMSRequestBody from infobip.models.sms_preview_response import PreviewSMSResponseBody +from infobip.models.sms_response import SendSMSResponseBody +from infobip.models.sms_textual_message import Message @pytest.mark.asyncio @@ -30,8 +34,51 @@ async def test_preview_message(httpx_mock): request_body = PreviewSMSRequestBody( text="Let's see how many characters remain unused in this message.", ) - response = await client.SMS.preview_message(request_body) + assert response.status_code == 200 assert PreviewSMSResponseBody.from_json(response.text).to_dict() == expected_response + +@pytest.mark.asyncio +async def test_send_sms_message(httpx_mock): + expected_response = { + "bulkId": "2034072219640523072", + "messages": [ + { + "messageId": "2250be2d4219-3af1-78856-aabe-1362af1edfd2", + "status": { + "description": "Message sent to next instance", + "groupId": 1, + "groupName": "PENDING", + "id": 26, + "name": "MESSAGE_ACCEPTED" + }, + "to": "41793026727" + } + ] + } + + async with get_test_client() as client: + httpx_mock.add_response( + url=f"{TEST_URL}{client.SMS.PATH_SEND_SMS}", + method="POST", + json=expected_response, + status_code=200, + ) + + request_body = SendSMSRequestBody( + messages=[ + Message( + destinations=[ + Destination( + to="555555555555", + ), + ], + text="Hello from Infobip Python SDK!", + ) + ] + ) + response = await client.SMS.send(request_body) + assert response.status_code == 200 + assert SendSMSResponseBody.from_json(response.text).to_dict() == expected_response From 2cb3675d16b4b05903edebcb9719064eb720e95c Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Mon, 8 May 2023 08:42:25 -0600 Subject: [PATCH 08/18] Add mms inbound report test --- tests/test_mms.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++ tests/test_sms.py | 38 +++++++++++++++++++-------------- 2 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 tests/test_mms.py diff --git a/tests/test_mms.py b/tests/test_mms.py new file mode 100644 index 0000000..c1cc9ca --- /dev/null +++ b/tests/test_mms.py @@ -0,0 +1,53 @@ +import urllib.parse + +import pytest + +from infobip.models.mms_get_inbound_messages_query_parameters import ( + GetInboundMessagesQueryParameters, +) +from infobip.models.mms_inbound_report_response import GetInboundMessagesResponseBody +from tests.common import TEST_URL, get_test_client + + +@pytest.mark.asyncio +async def test_get_inbound_messages(httpx_mock): + expected_response = { + "results": [ + { + "messageId": "817790313235066447", + "to": "25256", + "from": "41793026727", + "message": '{"mms_parts":[{"origin":"text","contentType":"text/plain; charset=utf-8",' + '"contentId":"content0","value":"Sample text"}],"userAgent":"motogstylus5g",' + '"priority":null,"subject":null}', + "receivedAt": "2016-10-06T09:28:39.220+0000", + "mmsCount": 1, + "callbackData": "Some custom data", + "price": {"pricePerMessage": 0.0, "currency": "EUR"}, + } + ] + } + + async with get_test_client() as client: + query_parameters = GetInboundMessagesQueryParameters( + limit=10, + ) + url_params = urllib.parse.urlencode(query_parameters.to_dict()) + + httpx_mock.add_response( + url=f"{TEST_URL}{client.MMS.PATH_GET_INBOUND_MESSAGES}?{url_params}", + method="GET", + json=expected_response, + status_code=200, + ) + + query_parameters = GetInboundMessagesQueryParameters( + limit=10, + ) + response = await client.MMS.get_inbound_messages(query_parameters) + + response_body = GetInboundMessagesResponseBody.from_json( + response.text + ).to_dict() + assert response.status_code == 200 + assert response_body["results"][0]["messageId"] == "817790313235066447" diff --git a/tests/test_sms.py b/tests/test_sms.py index 949ea0e..5bf386b 100644 --- a/tests/test_sms.py +++ b/tests/test_sms.py @@ -37,25 +37,29 @@ async def test_preview_message(httpx_mock): response = await client.SMS.preview_message(request_body) assert response.status_code == 200 - assert PreviewSMSResponseBody.from_json(response.text).to_dict() == expected_response + assert ( + PreviewSMSResponseBody.from_json(response.text).to_dict() + == expected_response + ) + @pytest.mark.asyncio async def test_send_sms_message(httpx_mock): expected_response = { - "bulkId": "2034072219640523072", - "messages": [ - { - "messageId": "2250be2d4219-3af1-78856-aabe-1362af1edfd2", - "status": { - "description": "Message sent to next instance", - "groupId": 1, - "groupName": "PENDING", - "id": 26, - "name": "MESSAGE_ACCEPTED" - }, - "to": "41793026727" - } - ] + "bulkId": "2034072219640523072", + "messages": [ + { + "messageId": "2250be2d4219-3af1-78856-aabe-1362af1edfd2", + "status": { + "description": "Message sent to next instance", + "groupId": 1, + "groupName": "PENDING", + "id": 26, + "name": "MESSAGE_ACCEPTED", + }, + "to": "41793026727", + } + ], } async with get_test_client() as client: @@ -81,4 +85,6 @@ async def test_send_sms_message(httpx_mock): response = await client.SMS.send(request_body) assert response.status_code == 200 - assert SendSMSResponseBody.from_json(response.text).to_dict() == expected_response + assert ( + SendSMSResponseBody.from_json(response.text).to_dict() == expected_response + ) From 57e15eb62093f16f1f5b542efd93b0b8fa074b07 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Mon, 8 May 2023 16:02:25 -0600 Subject: [PATCH 09/18] Fix format, config adjustments --- .pre-commit-config.yaml | 2 +- infobip/api/mms.py | 2 +- infobip/client.py | 1 + infobip/models/application.py | 8 ++++---- infobip/models/channel.py | 3 ++- infobip/models/entity.py | 8 ++++---- infobip/models/message_error.py | 8 ++++---- infobip/models/message_price.py | 8 ++++---- infobip/models/message_status.py | 8 ++++---- infobip/models/mms_advanced_message.py | 7 ++++--- infobip/models/mms_advanced_message_segment.py | 8 ++++---- .../models/mms_advanced_message_segment_binary.py | 8 ++++---- .../models/mms_advanced_message_segment_link.py | 8 ++++---- .../models/mms_advanced_message_segment_smil.py | 8 ++++---- .../models/mms_advanced_message_segment_text.py | 8 ++++---- ...s_advanced_message_segment_upload_reference.py | 8 ++++---- infobip/models/mms_advanced_request.py | 7 ++++--- infobip/models/mms_delivery_day.py | 3 ++- infobip/models/mms_delivery_time.py | 8 ++++---- infobip/models/mms_delivery_time_window.py | 7 ++++--- infobip/models/mms_destination.py | 8 ++++---- infobip/models/mms_error.py | 8 ++++---- infobip/models/mms_inbound_report.py | 6 ++++-- infobip/models/mms_inbound_report_response.py | 7 ++++--- infobip/models/mms_message_result.py | 7 ++++--- infobip/models/mms_price.py | 8 ++++---- infobip/models/mms_report.py | 7 ++++--- infobip/models/mms_report_response.py | 7 ++++--- infobip/models/mms_send_result.py | 7 ++++--- infobip/models/mms_status.py | 6 +++--- infobip/models/mms_upload_binary_result.py | 8 ++++---- .../models/mms_webhook_inbound_message_segment.py | 6 ++---- infobip/models/mms_webhook_inbound_report.py | 6 ++++-- .../models/mms_webhook_inbound_report_response.py | 7 ++++--- infobip/models/mms_webhook_outbound_report.py | 6 ++++-- .../mms_webhook_outbound_report_response.py | 7 ++++--- infobip/models/modify_application.py | 8 ++++---- infobip/models/modify_entity.py | 8 ++++---- infobip/models/number_price.py | 8 ++++---- infobip/models/number_registration_address.py | 8 ++++---- infobip/models/number_registration_brand.py | 8 +++++--- .../models/number_registration_brand_preview.py | 8 ++++---- .../models/number_registration_brand_status.py | 8 ++++---- infobip/models/number_registration_brand_vet.py | 7 ++++--- .../number_registration_business_identifier.py | 8 +++++--- infobip/models/number_registration_campaign.py | 8 +++++--- ...tion_data_universal_numbering_system_number.py | 5 +++-- .../number_registration_document_metadata.py | 8 ++++---- ...mber_registration_external_ten_dlc_campaign.py | 11 +++++------ ...n_global_intermediary_identification_number.py | 5 +++-- .../number_registration_government_brand.py | 7 ++++--- ...istration_interactive_voice_response_opt_in.py | 6 +++--- .../models/number_registration_keyword_opt_in.py | 8 ++++---- ...number_registration_legal_entity_identifier.py | 5 +++-- .../models/number_registration_network_status.py | 8 ++++---- .../number_registration_non_profit_brand.py | 7 ++++--- .../models/number_registration_number_preview.py | 8 ++++---- infobip/models/number_registration_opt_ins.py | 11 +++++------ infobip/models/number_registration_page_info.py | 6 +++--- .../number_registration_page_response_brand.py | 11 +++++------ ...number_registration_page_response_brand_vet.py | 15 ++++++--------- .../number_registration_page_response_campaign.py | 15 ++++++--------- .../number_registration_private_company_brand.py | 7 ++++--- .../number_registration_public_company_brand.py | 7 ++++--- .../number_registration_ten_dlc_campaign.py | 11 +++++------ .../number_registration_update_brand_request.py | 7 ++++--- ...number_registration_update_campaign_request.py | 6 +++--- .../models/number_registration_verbal_opt_in.py | 6 +++--- infobip/models/number_registration_web_opt_in.py | 6 +++--- infobip/models/number_response.py | 7 ++++--- infobip/models/numbers_auto_response_action.py | 11 +++++------ infobip/models/numbers_block_action.py | 9 ++++----- infobip/models/numbers_delivery_time_window.py | 8 ++++---- infobip/models/numbers_edit_permissions.py | 8 ++++---- .../numbers_forward_to_ivr_action_details.py | 5 +++-- .../numbers_forward_to_subscription_details.py | 3 ++- infobip/models/numbers_http_forward_action.py | 7 ++++--- infobip/models/numbers_mail_forward_action.py | 5 +++-- infobip/models/numbers_mo_action.py | 8 +++++--- infobip/models/numbers_mo_configuration.py | 11 +++++------ infobip/models/numbers_mo_configurations.py | 11 +++++------ infobip/models/numbers_mo_non_forward_action.py | 8 +++++--- infobip/models/numbers_no_action.py | 3 ++- infobip/models/numbers_pull_action.py | 3 ++- infobip/models/numbers_purchase_number_request.py | 8 ++++---- infobip/models/numbers_response.py | 7 ++++--- infobip/models/numbers_smpp_forward_action.py | 3 ++- infobip/models/numbers_stored_mo_configuration.py | 11 +++++------ infobip/models/numbers_use_conversation.py | 8 ++++---- infobip/models/numbers_voice_action_details.py | 8 +++++--- ...s_voice_call_forward_to_application_details.py | 5 +++-- ...numbers_voice_number_masking_action_details.py | 5 +++-- infobip/models/numbers_voice_setup.py | 7 ++++--- infobip/models/page_application.py | 7 ++++--- infobip/models/page_entity.py | 7 ++++--- infobip/models/page_info.py | 6 +++--- infobip/models/page_resource_association.py | 11 +++++------ infobip/models/resource_association_request.py | 5 +++-- infobip/models/resource_association_response.py | 7 ++++--- infobip/models/resource_type.py | 3 ++- infobip/models/sms_advanced_binary_request.py | 7 ++++--- infobip/models/sms_advanced_textual_request.py | 7 ++++--- infobip/models/sms_binary_content.py | 8 ++++---- infobip/models/sms_binary_message.py | 6 ++++-- infobip/models/sms_bulk_request.py | 6 +++--- infobip/models/sms_bulk_response.py | 7 ++++--- infobip/models/sms_bulk_status.py | 3 ++- infobip/models/sms_bulk_status_response.py | 7 ++++--- infobip/models/sms_delivery_day.py | 3 ++- infobip/models/sms_delivery_result.py | 7 ++++--- infobip/models/sms_delivery_time_from.py | 6 +++--- infobip/models/sms_delivery_time_to.py | 6 +++--- infobip/models/sms_delivery_time_window.py | 7 ++++--- infobip/models/sms_destination.py | 8 ++++---- infobip/models/sms_error.py | 8 ++++---- infobip/models/sms_inbound_message.py | 6 ++++-- infobip/models/sms_inbound_message_result.py | 7 ++++--- infobip/models/sms_india_dlt_options.py | 8 ++++---- infobip/models/sms_language.py | 8 ++++---- infobip/models/sms_language_configuration.py | 7 ++++--- infobip/models/sms_log.py | 6 ++++-- infobip/models/sms_logs_response.py | 7 ++++--- infobip/models/sms_preview.py | 7 ++++--- infobip/models/sms_preview_request.py | 8 ++++---- infobip/models/sms_preview_response.py | 7 ++++--- infobip/models/sms_price.py | 8 ++++---- infobip/models/sms_regional_options.py | 7 ++++--- infobip/models/sms_report.py | 6 ++++-- infobip/models/sms_response.py | 7 ++++--- infobip/models/sms_response_details.py | 7 ++++--- infobip/models/sms_sending_speed_limit.py | 7 ++++--- infobip/models/sms_speed_limit_time_unit.py | 3 ++- infobip/models/sms_status.py | 8 ++++---- infobip/models/sms_textual_message.py | 6 ++++-- infobip/models/sms_tracking.py | 8 ++++---- infobip/models/sms_turkey_iys_options.py | 8 ++++---- infobip/models/sms_update_status_request.py | 5 +++-- infobip/models/sms_url_options.py | 8 ++++---- infobip/models/sms_webhook_inbound_report.py | 6 ++++-- .../models/sms_webhook_inbound_report_response.py | 7 ++++--- infobip/models/sms_webhook_outbound_report.py | 6 ++++-- .../sms_webhook_outbound_report_response.py | 7 ++++--- infobip/models/webhook_message_count.py | 8 ++++---- requirements.txt | 2 +- samples/test_sms_live.py | 1 + setup.cfg | 2 +- tests/test_sms.py | 2 +- tox.ini | 14 ++++++-------- 148 files changed, 551 insertions(+), 478 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ab05ab1..695b7cb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: rev: 23.1.0 hooks: - id: black - args: ["--line-length", "88", "--target-version", "py39"] + args: ["--line-length", "88", "--target-version", "py310"] - repo: https://github.com/pycqa/flake8 rev: 4.0.1 hooks: diff --git a/infobip/api/mms.py b/infobip/api/mms.py index c519428..a9ccd9f 100644 --- a/infobip/api/mms.py +++ b/infobip/api/mms.py @@ -1,6 +1,6 @@ from collections.abc import Awaitable -from httpx import Response, AsyncClient +from httpx import AsyncClient, Response from infobip.models.mms_get_inbound_messages_query_parameters import ( GetInboundMessagesQueryParameters, diff --git a/infobip/client.py b/infobip/client.py index 63453fc..2f54e15 100644 --- a/infobip/client.py +++ b/infobip/client.py @@ -1,4 +1,5 @@ from os import getenv + from httpx import AsyncClient from infobip.api.mms import MMSClient diff --git a/infobip/models/application.py b/infobip/models/application.py index e5efc2b..f18bce8 100644 --- a/infobip/models/application.py +++ b/infobip/models/application.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, constr diff --git a/infobip/models/channel.py b/infobip/models/channel.py index ea5afd9..385225d 100644 --- a/infobip/models/channel.py +++ b/infobip/models/channel.py @@ -7,9 +7,10 @@ """ -from inspect import getfullargspec import pprint import re # noqa: F401 +from inspect import getfullargspec + from aenum import Enum, no_arg diff --git a/infobip/models/entity.py b/infobip/models/entity.py index 2b685a2..a5e735a 100644 --- a/infobip/models/entity.py +++ b/infobip/models/entity.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, constr diff --git a/infobip/models/message_error.py b/infobip/models/message_error.py index 0e6b4b9..f596a73 100644 --- a/infobip/models/message_error.py +++ b/infobip/models/message_error.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr diff --git a/infobip/models/message_price.py b/infobip/models/message_price.py index e980260..b0331ee 100644 --- a/infobip/models/message_price.py +++ b/infobip/models/message_price.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictFloat, StrictStr diff --git a/infobip/models/message_status.py b/infobip/models/message_status.py index 916b80b..d8a3cef 100644 --- a/infobip/models/message_status.py +++ b/infobip/models/message_status.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr diff --git a/infobip/models/mms_advanced_message.py b/infobip/models/mms_advanced_message.py index 2960e94..8c40f66 100644 --- a/infobip/models/mms_advanced_message.py +++ b/infobip/models/mms_advanced_message.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, constr + from infobip.models.mms_advanced_message_segment import MmsAdvancedMessageSegment from infobip.models.mms_delivery_time_window import MmsDeliveryTimeWindow from infobip.models.mms_destination import MmsDestination diff --git a/infobip/models/mms_advanced_message_segment.py b/infobip/models/mms_advanced_message_segment.py index 63f5a69..bf7f4c3 100644 --- a/infobip/models/mms_advanced_message_segment.py +++ b/infobip/models/mms_advanced_message_segment.py @@ -8,11 +8,13 @@ from __future__ import annotations + import pprint import re # noqa: F401 +from typing import Any, List, Optional + +from pydantic import BaseModel, Field, ValidationError, validator -from typing import Optional -from pydantic import BaseModel, ValidationError, validator from infobip.models.mms_advanced_message_segment_binary import ( MmsAdvancedMessageSegmentBinary, ) @@ -28,8 +30,6 @@ from infobip.models.mms_advanced_message_segment_upload_reference import ( MmsAdvancedMessageSegmentUploadReference, ) -from typing import Any, List -from pydantic import Field MMSADVANCEDMESSAGESEGMENT_ANY_OF_SCHEMAS = [ "MmsAdvancedMessageSegmentBinary", diff --git a/infobip/models/mms_advanced_message_segment_binary.py b/infobip/models/mms_advanced_message_segment_binary.py index 2a11bb6..e035cf2 100644 --- a/infobip/models/mms_advanced_message_segment_binary.py +++ b/infobip/models/mms_advanced_message_segment_binary.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/mms_advanced_message_segment_link.py b/infobip/models/mms_advanced_message_segment_link.py index befa8bc..3092946 100644 --- a/infobip/models/mms_advanced_message_segment_link.py +++ b/infobip/models/mms_advanced_message_segment_link.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/mms_advanced_message_segment_smil.py b/infobip/models/mms_advanced_message_segment_smil.py index a729204..02ffe0c 100644 --- a/infobip/models/mms_advanced_message_segment_smil.py +++ b/infobip/models/mms_advanced_message_segment_smil.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/mms_advanced_message_segment_text.py b/infobip/models/mms_advanced_message_segment_text.py index 8c921a1..a7dbb2d 100644 --- a/infobip/models/mms_advanced_message_segment_text.py +++ b/infobip/models/mms_advanced_message_segment_text.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/mms_advanced_message_segment_upload_reference.py b/infobip/models/mms_advanced_message_segment_upload_reference.py index 813eddf..937a3c2 100644 --- a/infobip/models/mms_advanced_message_segment_upload_reference.py +++ b/infobip/models/mms_advanced_message_segment_upload_reference.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/mms_advanced_request.py b/infobip/models/mms_advanced_request.py index 42fd955..a6f84d4 100644 --- a/infobip/models/mms_advanced_request.py +++ b/infobip/models/mms_advanced_request.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.mms_advanced_message import MmsAdvancedMessage diff --git a/infobip/models/mms_delivery_day.py b/infobip/models/mms_delivery_day.py index 4db5cbb..90c2ad2 100644 --- a/infobip/models/mms_delivery_day.py +++ b/infobip/models/mms_delivery_day.py @@ -7,9 +7,10 @@ """ -from inspect import getfullargspec import pprint import re # noqa: F401 +from inspect import getfullargspec + from aenum import Enum, no_arg diff --git a/infobip/models/mms_delivery_time.py b/infobip/models/mms_delivery_time.py index 1344f9e..e88c6c2 100644 --- a/infobip/models/mms_delivery_time.py +++ b/infobip/models/mms_delivery_time.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, conint diff --git a/infobip/models/mms_delivery_time_window.py b/infobip/models/mms_delivery_time_window.py index fdb2602..7a5b34e 100644 --- a/infobip/models/mms_delivery_time_window.py +++ b/infobip/models/mms_delivery_time_window.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field + from infobip.models.mms_delivery_day import MmsDeliveryDay from infobip.models.mms_delivery_time import MmsDeliveryTime diff --git a/infobip/models/mms_destination.py b/infobip/models/mms_destination.py index 745332e..56daac6 100644 --- a/infobip/models/mms_destination.py +++ b/infobip/models/mms_destination.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr, constr diff --git a/infobip/models/mms_error.py b/infobip/models/mms_error.py index e72ba85..5d73db5 100644 --- a/infobip/models/mms_error.py +++ b/infobip/models/mms_error.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr diff --git a/infobip/models/mms_inbound_report.py b/infobip/models/mms_inbound_report.py index 1bc9801..d96364e 100644 --- a/infobip/models/mms_inbound_report.py +++ b/infobip/models/mms_inbound_report.py @@ -8,13 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr + from infobip.models.mms_price import MmsPrice diff --git a/infobip/models/mms_inbound_report_response.py b/infobip/models/mms_inbound_report_response.py index 6174e5e..d36311a 100644 --- a/infobip/models/mms_inbound_report_response.py +++ b/infobip/models/mms_inbound_report_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field + from infobip.models.mms_inbound_report import MmsInboundReport diff --git a/infobip/models/mms_message_result.py b/infobip/models/mms_message_result.py index 6ef46f1..44097fe 100644 --- a/infobip/models/mms_message_result.py +++ b/infobip/models/mms_message_result.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.mms_status import MmsStatus diff --git a/infobip/models/mms_price.py b/infobip/models/mms_price.py index c7220d0..a8822f2 100644 --- a/infobip/models/mms_price.py +++ b/infobip/models/mms_price.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictFloat, StrictStr diff --git a/infobip/models/mms_report.py b/infobip/models/mms_report.py index b3c4e3e..9926694 100644 --- a/infobip/models/mms_report.py +++ b/infobip/models/mms_report.py @@ -8,14 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from datetime import datetime from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr + from infobip.models.mms_error import MmsError from infobip.models.mms_price import MmsPrice from infobip.models.mms_status import MmsStatus diff --git a/infobip/models/mms_report_response.py b/infobip/models/mms_report_response.py index 9c220ec..fd5f631 100644 --- a/infobip/models/mms_report_response.py +++ b/infobip/models/mms_report_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel + from infobip.models.mms_report import MmsReport diff --git a/infobip/models/mms_send_result.py b/infobip/models/mms_send_result.py index 31a097e..0654754 100644 --- a/infobip/models/mms_send_result.py +++ b/infobip/models/mms_send_result.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.mms_message_result import MmsMessageResult diff --git a/infobip/models/mms_status.py b/infobip/models/mms_status.py index 98ea834..6216fb0 100644 --- a/infobip/models/mms_status.py +++ b/infobip/models/mms_status.py @@ -8,11 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - +from inspect import getfullargspec from pydantic import BaseModel, Field, StrictInt, StrictStr diff --git a/infobip/models/mms_upload_binary_result.py b/infobip/models/mms_upload_binary_result.py index 6a68f46..3e9e267 100644 --- a/infobip/models/mms_upload_binary_result.py +++ b/infobip/models/mms_upload_binary_result.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/mms_webhook_inbound_message_segment.py b/infobip/models/mms_webhook_inbound_message_segment.py index 88b0cd9..2ac2dab 100644 --- a/infobip/models/mms_webhook_inbound_message_segment.py +++ b/infobip/models/mms_webhook_inbound_message_segment.py @@ -11,11 +11,9 @@ import pprint import re # noqa: F401 -from typing import Any, List -from typing import Optional +from typing import Any, List, Optional -from pydantic import BaseModel, ValidationError, validator -from pydantic import Field +from pydantic import BaseModel, Field, ValidationError, validator from infobip.models.mms_webhook_inbound_message_segment_link import ( MmsWebhookInboundMessageSegmentLink, diff --git a/infobip/models/mms_webhook_inbound_report.py b/infobip/models/mms_webhook_inbound_report.py index cdc3ab2..340355a 100644 --- a/infobip/models/mms_webhook_inbound_report.py +++ b/infobip/models/mms_webhook_inbound_report.py @@ -8,13 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime from typing import List, Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.message_price import MessagePrice from infobip.models.mms_webhook_inbound_message_segment import ( MmsWebhookInboundMessageSegment, diff --git a/infobip/models/mms_webhook_inbound_report_response.py b/infobip/models/mms_webhook_inbound_report_response.py index 212ec2a..cd76f13 100644 --- a/infobip/models/mms_webhook_inbound_report_response.py +++ b/infobip/models/mms_webhook_inbound_report_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictInt + from infobip.models.mms_webhook_inbound_report import MmsWebhookInboundReport diff --git a/infobip/models/mms_webhook_outbound_report.py b/infobip/models/mms_webhook_outbound_report.py index ffd4218..24cac98 100644 --- a/infobip/models/mms_webhook_outbound_report.py +++ b/infobip/models/mms_webhook_outbound_report.py @@ -8,13 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr + from infobip.models.message_error import MessageError from infobip.models.message_price import MessagePrice from infobip.models.message_status import MessageStatus diff --git a/infobip/models/mms_webhook_outbound_report_response.py b/infobip/models/mms_webhook_outbound_report_response.py index f5e8b2e..bd7245b 100644 --- a/infobip/models/mms_webhook_outbound_report_response.py +++ b/infobip/models/mms_webhook_outbound_report_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel + from infobip.models.mms_webhook_outbound_report import MmsWebhookOutboundReport diff --git a/infobip/models/modify_application.py b/infobip/models/modify_application.py index 4ff2e8e..a28f57d 100644 --- a/infobip/models/modify_application.py +++ b/infobip/models/modify_application.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, constr diff --git a/infobip/models/modify_entity.py b/infobip/models/modify_entity.py index f6e984d..85d13f8 100644 --- a/infobip/models/modify_entity.py +++ b/infobip/models/modify_entity.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, constr diff --git a/infobip/models/number_price.py b/infobip/models/number_price.py index 4b4ebec..f27f3db 100644 --- a/infobip/models/number_price.py +++ b/infobip/models/number_price.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictFloat, StrictStr diff --git a/infobip/models/number_registration_address.py b/infobip/models/number_registration_address.py index aef9b26..b010b96 100644 --- a/infobip/models/number_registration_address.py +++ b/infobip/models/number_registration_address.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, constr diff --git a/infobip/models/number_registration_brand.py b/infobip/models/number_registration_brand.py index d2fc319..91fef4c 100644 --- a/infobip/models/number_registration_brand.py +++ b/infobip/models/number_registration_brand.py @@ -8,15 +8,17 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json -from infobip import models - from datetime import datetime from typing import Optional + from pydantic import BaseModel, Field, StrictStr, constr, validator +from infobip import models + class NumberRegistrationBrand(BaseModel): """NOTE: This class is auto generated by OpenAPI Generator. diff --git a/infobip/models/number_registration_brand_preview.py b/infobip/models/number_registration_brand_preview.py index f4b2e33..51206ff 100644 --- a/infobip/models/number_registration_brand_preview.py +++ b/infobip/models/number_registration_brand_preview.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/number_registration_brand_status.py b/infobip/models/number_registration_brand_status.py index c2c4e86..dd0c503 100644 --- a/infobip/models/number_registration_brand_status.py +++ b/infobip/models/number_registration_brand_status.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr, validator diff --git a/infobip/models/number_registration_brand_vet.py b/infobip/models/number_registration_brand_vet.py index 522401a..58e9199 100644 --- a/infobip/models/number_registration_brand_vet.py +++ b/infobip/models/number_registration_brand_vet.py @@ -8,13 +8,14 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr, validator diff --git a/infobip/models/number_registration_business_identifier.py b/infobip/models/number_registration_business_identifier.py index 9f94e3e..4a627f7 100644 --- a/infobip/models/number_registration_business_identifier.py +++ b/infobip/models/number_registration_business_identifier.py @@ -8,14 +8,16 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json -from infobip import models - from typing import Optional + from pydantic import BaseModel, StrictStr, validator +from infobip import models + class NumberRegistrationBusinessIdentifier(BaseModel): """NOTE: This class is auto generated by OpenAPI Generator. diff --git a/infobip/models/number_registration_campaign.py b/infobip/models/number_registration_campaign.py index f7015aa..d64286d 100644 --- a/infobip/models/number_registration_campaign.py +++ b/infobip/models/number_registration_campaign.py @@ -8,15 +8,17 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json -from infobip import models - from datetime import datetime from typing import Optional + from pydantic import BaseModel, Field, StrictStr, constr, validator +from infobip import models + class NumberRegistrationCampaign(BaseModel): """NOTE: This class is auto generated by OpenAPI Generator. diff --git a/infobip/models/number_registration_data_universal_numbering_system_number.py b/infobip/models/number_registration_data_universal_numbering_system_number.py index 3f0c79e..d16a54b 100644 --- a/infobip/models/number_registration_data_universal_numbering_system_number.py +++ b/infobip/models/number_registration_data_universal_numbering_system_number.py @@ -8,12 +8,13 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from pydantic import Field, constr, validator + from infobip.models.number_registration_business_identifier import ( NumberRegistrationBusinessIdentifier, ) diff --git a/infobip/models/number_registration_document_metadata.py b/infobip/models/number_registration_document_metadata.py index fa760cd..37f0409 100644 --- a/infobip/models/number_registration_document_metadata.py +++ b/infobip/models/number_registration_document_metadata.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr diff --git a/infobip/models/number_registration_external_ten_dlc_campaign.py b/infobip/models/number_registration_external_ten_dlc_campaign.py index 4652a66..a17431f 100644 --- a/infobip/models/number_registration_external_ten_dlc_campaign.py +++ b/infobip/models/number_registration_external_ten_dlc_campaign.py @@ -8,16 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import Field, StrictStr, conlist -from infobip.models.number_registration_campaign import ( - NumberRegistrationCampaign, -) + +from infobip.models.number_registration_campaign import NumberRegistrationCampaign from infobip.models.number_registration_number_preview import ( NumberRegistrationNumberPreview, ) diff --git a/infobip/models/number_registration_global_intermediary_identification_number.py b/infobip/models/number_registration_global_intermediary_identification_number.py index a6de767..b7c1f98 100644 --- a/infobip/models/number_registration_global_intermediary_identification_number.py +++ b/infobip/models/number_registration_global_intermediary_identification_number.py @@ -8,12 +8,13 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from pydantic import Field, constr, validator + from infobip.models.number_registration_business_identifier import ( NumberRegistrationBusinessIdentifier, ) diff --git a/infobip/models/number_registration_government_brand.py b/infobip/models/number_registration_government_brand.py index 44b4429..75ba224 100644 --- a/infobip/models/number_registration_government_brand.py +++ b/infobip/models/number_registration_government_brand.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import Field, StrictStr, constr, validator + from infobip.models.number_registration_address import NumberRegistrationAddress from infobip.models.number_registration_brand import NumberRegistrationBrand from infobip.models.number_registration_business_identifier import ( diff --git a/infobip/models/number_registration_interactive_voice_response_opt_in.py b/infobip/models/number_registration_interactive_voice_response_opt_in.py index 5a47aa6..335be69 100644 --- a/infobip/models/number_registration_interactive_voice_response_opt_in.py +++ b/infobip/models/number_registration_interactive_voice_response_opt_in.py @@ -8,11 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - +from inspect import getfullargspec from pydantic import BaseModel, Field, constr diff --git a/infobip/models/number_registration_keyword_opt_in.py b/infobip/models/number_registration_keyword_opt_in.py index 6d4e008..2547b9f 100644 --- a/infobip/models/number_registration_keyword_opt_in.py +++ b/infobip/models/number_registration_keyword_opt_in.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import List + from pydantic import BaseModel, Field, StrictStr, constr diff --git a/infobip/models/number_registration_legal_entity_identifier.py b/infobip/models/number_registration_legal_entity_identifier.py index 727a05c..2c1a602 100644 --- a/infobip/models/number_registration_legal_entity_identifier.py +++ b/infobip/models/number_registration_legal_entity_identifier.py @@ -8,12 +8,13 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from pydantic import Field, constr, validator + from infobip.models.number_registration_business_identifier import ( NumberRegistrationBusinessIdentifier, ) diff --git a/infobip/models/number_registration_network_status.py b/infobip/models/number_registration_network_status.py index c7b0648..48e423b 100644 --- a/infobip/models/number_registration_network_status.py +++ b/infobip/models/number_registration_network_status.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr, validator diff --git a/infobip/models/number_registration_non_profit_brand.py b/infobip/models/number_registration_non_profit_brand.py index 11b8c66..3392933 100644 --- a/infobip/models/number_registration_non_profit_brand.py +++ b/infobip/models/number_registration_non_profit_brand.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import Field, StrictStr, constr, validator + from infobip.models.number_registration_address import NumberRegistrationAddress from infobip.models.number_registration_brand import NumberRegistrationBrand from infobip.models.number_registration_business_identifier import ( diff --git a/infobip/models/number_registration_number_preview.py b/infobip/models/number_registration_number_preview.py index 76c00ab..88467fc 100644 --- a/infobip/models/number_registration_number_preview.py +++ b/infobip/models/number_registration_number_preview.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/number_registration_opt_ins.py b/infobip/models/number_registration_opt_ins.py index 697e30c..e471cbc 100644 --- a/infobip/models/number_registration_opt_ins.py +++ b/infobip/models/number_registration_opt_ins.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import BaseModel, Field + from infobip.models.number_registration_interactive_voice_response_opt_in import ( NumberRegistrationInteractiveVoiceResponseOptIn, ) @@ -24,9 +25,7 @@ from infobip.models.number_registration_verbal_opt_in import ( NumberRegistrationVerbalOptIn, ) -from infobip.models.number_registration_web_opt_in import ( - NumberRegistrationWebOptIn, -) +from infobip.models.number_registration_web_opt_in import NumberRegistrationWebOptIn class NumberRegistrationOptIns(BaseModel): diff --git a/infobip/models/number_registration_page_info.py b/infobip/models/number_registration_page_info.py index b115344..fb411e8 100644 --- a/infobip/models/number_registration_page_info.py +++ b/infobip/models/number_registration_page_info.py @@ -8,11 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - +from inspect import getfullargspec from pydantic import BaseModel, Field, conint diff --git a/infobip/models/number_registration_page_response_brand.py b/infobip/models/number_registration_page_response_brand.py index d739372..01ed6cd 100644 --- a/infobip/models/number_registration_page_response_brand.py +++ b/infobip/models/number_registration_page_response_brand.py @@ -8,17 +8,16 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field + from infobip.models.number_registration_brand import NumberRegistrationBrand -from infobip.models.number_registration_page_info import ( - NumberRegistrationPageInfo, -) +from infobip.models.number_registration_page_info import NumberRegistrationPageInfo class NumberRegistrationPageResponseBrand(BaseModel): diff --git a/infobip/models/number_registration_page_response_brand_vet.py b/infobip/models/number_registration_page_response_brand_vet.py index b3afc97..a719ae1 100644 --- a/infobip/models/number_registration_page_response_brand_vet.py +++ b/infobip/models/number_registration_page_response_brand_vet.py @@ -8,19 +8,16 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field -from infobip.models.number_registration_brand_vet import ( - NumberRegistrationBrandVet, -) -from infobip.models.number_registration_page_info import ( - NumberRegistrationPageInfo, -) + +from infobip.models.number_registration_brand_vet import NumberRegistrationBrandVet +from infobip.models.number_registration_page_info import NumberRegistrationPageInfo class NumberRegistrationPageResponseBrandVet(BaseModel): diff --git a/infobip/models/number_registration_page_response_campaign.py b/infobip/models/number_registration_page_response_campaign.py index fafbdf1..7c49564 100644 --- a/infobip/models/number_registration_page_response_campaign.py +++ b/infobip/models/number_registration_page_response_campaign.py @@ -8,19 +8,16 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field -from infobip.models.number_registration_campaign import ( - NumberRegistrationCampaign, -) -from infobip.models.number_registration_page_info import ( - NumberRegistrationPageInfo, -) + +from infobip.models.number_registration_campaign import NumberRegistrationCampaign +from infobip.models.number_registration_page_info import NumberRegistrationPageInfo class NumberRegistrationPageResponseCampaign(BaseModel): diff --git a/infobip/models/number_registration_private_company_brand.py b/infobip/models/number_registration_private_company_brand.py index fbca0be..d9ea1bf 100644 --- a/infobip/models/number_registration_private_company_brand.py +++ b/infobip/models/number_registration_private_company_brand.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import Field, StrictStr, constr, validator + from infobip.models.number_registration_address import NumberRegistrationAddress from infobip.models.number_registration_brand import NumberRegistrationBrand from infobip.models.number_registration_business_identifier import ( diff --git a/infobip/models/number_registration_public_company_brand.py b/infobip/models/number_registration_public_company_brand.py index 509cbb9..744a0cd 100644 --- a/infobip/models/number_registration_public_company_brand.py +++ b/infobip/models/number_registration_public_company_brand.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import Field, StrictStr, constr, validator + from infobip.models.number_registration_address import NumberRegistrationAddress from infobip.models.number_registration_brand import NumberRegistrationBrand from infobip.models.number_registration_business_identifier import ( diff --git a/infobip/models/number_registration_ten_dlc_campaign.py b/infobip/models/number_registration_ten_dlc_campaign.py index f492e4d..7c56acb 100644 --- a/infobip/models/number_registration_ten_dlc_campaign.py +++ b/infobip/models/number_registration_ten_dlc_campaign.py @@ -8,19 +8,18 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import Field, StrictBool, StrictStr, conlist, constr, validator + from infobip.models.number_registration_brand_preview import ( NumberRegistrationBrandPreview, ) -from infobip.models.number_registration_campaign import ( - NumberRegistrationCampaign, -) +from infobip.models.number_registration_campaign import NumberRegistrationCampaign from infobip.models.number_registration_document_metadata import ( NumberRegistrationDocumentMetadata, ) diff --git a/infobip/models/number_registration_update_brand_request.py b/infobip/models/number_registration_update_brand_request.py index 1cc2b9e..8d4ec3e 100644 --- a/infobip/models/number_registration_update_brand_request.py +++ b/infobip/models/number_registration_update_brand_request.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.number_registration_address import NumberRegistrationAddress diff --git a/infobip/models/number_registration_update_campaign_request.py b/infobip/models/number_registration_update_campaign_request.py index 4a128bc..d747f42 100644 --- a/infobip/models/number_registration_update_campaign_request.py +++ b/infobip/models/number_registration_update_campaign_request.py @@ -8,11 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - +from inspect import getfullargspec from pydantic import BaseModel, Field, StrictStr, conlist diff --git a/infobip/models/number_registration_verbal_opt_in.py b/infobip/models/number_registration_verbal_opt_in.py index 2b9d861..2a9e8ad 100644 --- a/infobip/models/number_registration_verbal_opt_in.py +++ b/infobip/models/number_registration_verbal_opt_in.py @@ -8,11 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - +from inspect import getfullargspec from pydantic import BaseModel, Field, constr diff --git a/infobip/models/number_registration_web_opt_in.py b/infobip/models/number_registration_web_opt_in.py index 92e39ce..84cfe88 100644 --- a/infobip/models/number_registration_web_opt_in.py +++ b/infobip/models/number_registration_web_opt_in.py @@ -8,11 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - +from inspect import getfullargspec from pydantic import BaseModel, Field, constr diff --git a/infobip/models/number_response.py b/infobip/models/number_response.py index e48ed51..dad3c79 100644 --- a/infobip/models/number_response.py +++ b/infobip/models/number_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictBool, StrictStr, constr, validator + from infobip.models.number_price import NumberPrice from infobip.models.numbers_edit_permissions import NumbersEditPermissions from infobip.models.numbers_voice_setup import NumbersVoiceSetup diff --git a/infobip/models/numbers_auto_response_action.py b/infobip/models/numbers_auto_response_action.py index a1cf3a2..abd8ad7 100644 --- a/infobip/models/numbers_auto_response_action.py +++ b/infobip/models/numbers_auto_response_action.py @@ -8,17 +8,16 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import Field, StrictStr, constr + from infobip.models.numbers_delivery_time_window import NumbersDeliveryTimeWindow -from infobip.models.numbers_mo_non_forward_action import ( - NumbersMoNonForwardAction, -) +from infobip.models.numbers_mo_non_forward_action import NumbersMoNonForwardAction class NumbersAutoResponseAction(NumbersMoNonForwardAction): diff --git a/infobip/models/numbers_block_action.py b/infobip/models/numbers_block_action.py index 4651b23..a67044c 100644 --- a/infobip/models/numbers_block_action.py +++ b/infobip/models/numbers_block_action.py @@ -8,15 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from pydantic import Field, StrictStr, validator -from infobip.models.numbers_mo_non_forward_action import ( - NumbersMoNonForwardAction, -) + +from infobip.models.numbers_mo_non_forward_action import NumbersMoNonForwardAction class NumbersBlockAction(NumbersMoNonForwardAction): diff --git a/infobip/models/numbers_delivery_time_window.py b/infobip/models/numbers_delivery_time_window.py index 86e52db..0a3d4ab 100644 --- a/infobip/models/numbers_delivery_time_window.py +++ b/infobip/models/numbers_delivery_time_window.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr, conlist, validator diff --git a/infobip/models/numbers_edit_permissions.py b/infobip/models/numbers_edit_permissions.py index 008a3a3..55a4491 100644 --- a/infobip/models/numbers_edit_permissions.py +++ b/infobip/models/numbers_edit_permissions.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictBool diff --git a/infobip/models/numbers_forward_to_ivr_action_details.py b/infobip/models/numbers_forward_to_ivr_action_details.py index 3e94e30..f41304a 100644 --- a/infobip/models/numbers_forward_to_ivr_action_details.py +++ b/infobip/models/numbers_forward_to_ivr_action_details.py @@ -8,12 +8,13 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from pydantic import Field, StrictStr + from infobip.models.numbers_voice_action_details import NumbersVoiceActionDetails diff --git a/infobip/models/numbers_forward_to_subscription_details.py b/infobip/models/numbers_forward_to_subscription_details.py index 8ca7055..5513d41 100644 --- a/infobip/models/numbers_forward_to_subscription_details.py +++ b/infobip/models/numbers_forward_to_subscription_details.py @@ -8,9 +8,10 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json from infobip.models.numbers_voice_action_details import NumbersVoiceActionDetails diff --git a/infobip/models/numbers_http_forward_action.py b/infobip/models/numbers_http_forward_action.py index 72c6fe4..df405a9 100644 --- a/infobip/models/numbers_http_forward_action.py +++ b/infobip/models/numbers_http_forward_action.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import Field, StrictStr, validator + from infobip.models.numbers_mo_action import NumbersMoAction diff --git a/infobip/models/numbers_mail_forward_action.py b/infobip/models/numbers_mail_forward_action.py index 02c0a04..836f065 100644 --- a/infobip/models/numbers_mail_forward_action.py +++ b/infobip/models/numbers_mail_forward_action.py @@ -8,12 +8,13 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from pydantic import Field, StrictStr + from infobip.models.numbers_mo_action import NumbersMoAction diff --git a/infobip/models/numbers_mo_action.py b/infobip/models/numbers_mo_action.py index 5fe4415..3667518 100644 --- a/infobip/models/numbers_mo_action.py +++ b/infobip/models/numbers_mo_action.py @@ -8,14 +8,16 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json -from infobip import models - from typing import Optional + from pydantic import BaseModel, Field, StrictStr, validator +from infobip import models + class NumbersMoAction(BaseModel): """NOTE: This class is auto generated by OpenAPI Generator. diff --git a/infobip/models/numbers_mo_configuration.py b/infobip/models/numbers_mo_configuration.py index 5f5b033..69e6474 100644 --- a/infobip/models/numbers_mo_configuration.py +++ b/infobip/models/numbers_mo_configuration.py @@ -8,17 +8,16 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictStr, constr + from infobip.models.numbers_mo_action import NumbersMoAction -from infobip.models.numbers_mo_non_forward_action import ( - NumbersMoNonForwardAction, -) +from infobip.models.numbers_mo_non_forward_action import NumbersMoNonForwardAction from infobip.models.numbers_use_conversation import NumbersUseConversation diff --git a/infobip/models/numbers_mo_configurations.py b/infobip/models/numbers_mo_configurations.py index 12a4363..d8dd248 100644 --- a/infobip/models/numbers_mo_configurations.py +++ b/infobip/models/numbers_mo_configurations.py @@ -8,16 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictInt -from infobip.models.numbers_stored_mo_configuration import ( - NumbersStoredMoConfiguration, -) + +from infobip.models.numbers_stored_mo_configuration import NumbersStoredMoConfiguration class NumbersMoConfigurations(BaseModel): diff --git a/infobip/models/numbers_mo_non_forward_action.py b/infobip/models/numbers_mo_non_forward_action.py index b03681d..bf9efd2 100644 --- a/infobip/models/numbers_mo_non_forward_action.py +++ b/infobip/models/numbers_mo_non_forward_action.py @@ -8,14 +8,16 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json -from infobip import models - from typing import Optional + from pydantic import BaseModel, Field, StrictBool, StrictStr, validator +from infobip import models + class NumbersMoNonForwardAction(BaseModel): """NOTE: This class is auto generated by OpenAPI Generator. diff --git a/infobip/models/numbers_no_action.py b/infobip/models/numbers_no_action.py index ff90365..c89c0dc 100644 --- a/infobip/models/numbers_no_action.py +++ b/infobip/models/numbers_no_action.py @@ -8,9 +8,10 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json from infobip.models.numbers_mo_action import NumbersMoAction diff --git a/infobip/models/numbers_pull_action.py b/infobip/models/numbers_pull_action.py index b0c1a7a..f5618cb 100644 --- a/infobip/models/numbers_pull_action.py +++ b/infobip/models/numbers_pull_action.py @@ -8,9 +8,10 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json from infobip.models.numbers_mo_action import NumbersMoAction diff --git a/infobip/models/numbers_purchase_number_request.py b/infobip/models/numbers_purchase_number_request.py index 6ce4222..a11c9e6 100644 --- a/infobip/models/numbers_purchase_number_request.py +++ b/infobip/models/numbers_purchase_number_request.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr, constr diff --git a/infobip/models/numbers_response.py b/infobip/models/numbers_response.py index 35f62a6..8ce0240 100644 --- a/infobip/models/numbers_response.py +++ b/infobip/models/numbers_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictInt + from infobip.models.number_response import NumberResponse diff --git a/infobip/models/numbers_smpp_forward_action.py b/infobip/models/numbers_smpp_forward_action.py index 909d020..6711fc7 100644 --- a/infobip/models/numbers_smpp_forward_action.py +++ b/infobip/models/numbers_smpp_forward_action.py @@ -8,9 +8,10 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json from infobip.models.numbers_mo_action import NumbersMoAction diff --git a/infobip/models/numbers_stored_mo_configuration.py b/infobip/models/numbers_stored_mo_configuration.py index 317c7b0..d592ad7 100644 --- a/infobip/models/numbers_stored_mo_configuration.py +++ b/infobip/models/numbers_stored_mo_configuration.py @@ -8,17 +8,16 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictStr, constr + from infobip.models.numbers_mo_action import NumbersMoAction -from infobip.models.numbers_mo_non_forward_action import ( - NumbersMoNonForwardAction, -) +from infobip.models.numbers_mo_non_forward_action import NumbersMoNonForwardAction from infobip.models.numbers_use_conversation import NumbersUseConversation diff --git a/infobip/models/numbers_use_conversation.py b/infobip/models/numbers_use_conversation.py index 13f5d0d..be4afa6 100644 --- a/infobip/models/numbers_use_conversation.py +++ b/infobip/models/numbers_use_conversation.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictBool diff --git a/infobip/models/numbers_voice_action_details.py b/infobip/models/numbers_voice_action_details.py index 62cdb5f..40bd16b 100644 --- a/infobip/models/numbers_voice_action_details.py +++ b/infobip/models/numbers_voice_action_details.py @@ -8,14 +8,16 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json -from infobip import models - from typing import Optional + from pydantic import BaseModel, StrictStr, validator +from infobip import models + class NumbersVoiceActionDetails(BaseModel): """NOTE: This class is auto generated by OpenAPI Generator. diff --git a/infobip/models/numbers_voice_call_forward_to_application_details.py b/infobip/models/numbers_voice_call_forward_to_application_details.py index 1bc31a0..7ee0028 100644 --- a/infobip/models/numbers_voice_call_forward_to_application_details.py +++ b/infobip/models/numbers_voice_call_forward_to_application_details.py @@ -8,12 +8,13 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from pydantic import Field, StrictStr + from infobip.models.numbers_voice_action_details import NumbersVoiceActionDetails diff --git a/infobip/models/numbers_voice_number_masking_action_details.py b/infobip/models/numbers_voice_number_masking_action_details.py index 7907f2a..4cd48ff 100644 --- a/infobip/models/numbers_voice_number_masking_action_details.py +++ b/infobip/models/numbers_voice_number_masking_action_details.py @@ -8,12 +8,13 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from pydantic import Field, StrictStr + from infobip.models.numbers_voice_action_details import NumbersVoiceActionDetails diff --git a/infobip/models/numbers_voice_setup.py b/infobip/models/numbers_voice_setup.py index 42c0bc1..521af17 100644 --- a/infobip/models/numbers_voice_setup.py +++ b/infobip/models/numbers_voice_setup.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import BaseModel, Field, constr + from infobip.models.numbers_voice_action_details import NumbersVoiceActionDetails diff --git a/infobip/models/page_application.py b/infobip/models/page_application.py index 8cf49d3..b821873 100644 --- a/infobip/models/page_application.py +++ b/infobip/models/page_application.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel + from infobip.models.application import Application from infobip.models.page_info import PageInfo diff --git a/infobip/models/page_entity.py b/infobip/models/page_entity.py index cd0366a..012e3a4 100644 --- a/infobip/models/page_entity.py +++ b/infobip/models/page_entity.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel + from infobip.models.entity import Entity from infobip.models.page_info import PageInfo diff --git a/infobip/models/page_info.py b/infobip/models/page_info.py index 349a826..d166b0f 100644 --- a/infobip/models/page_info.py +++ b/infobip/models/page_info.py @@ -8,11 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - +from inspect import getfullargspec from pydantic import BaseModel, Field, conint diff --git a/infobip/models/page_resource_association.py b/infobip/models/page_resource_association.py index 08977cc..3217763 100644 --- a/infobip/models/page_resource_association.py +++ b/infobip/models/page_resource_association.py @@ -8,17 +8,16 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel + from infobip.models.page_info import PageInfo -from infobip.models.resource_association_response import ( - ResourceAssociationResponse, -) +from infobip.models.resource_association_response import ResourceAssociationResponse class PageResourceAssociation(BaseModel): diff --git a/infobip/models/resource_association_request.py b/infobip/models/resource_association_request.py index 2ba4273..f6e3f58 100644 --- a/infobip/models/resource_association_request.py +++ b/infobip/models/resource_association_request.py @@ -8,12 +8,13 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from pydantic import BaseModel, Field, constr + from infobip.models.channel import Channel from infobip.models.resource_type import ResourceType diff --git a/infobip/models/resource_association_response.py b/infobip/models/resource_association_response.py index 5368586..62210e7 100644 --- a/infobip/models/resource_association_response.py +++ b/infobip/models/resource_association_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import BaseModel, Field, constr + from infobip.models.channel import Channel from infobip.models.resource_type import ResourceType diff --git a/infobip/models/resource_type.py b/infobip/models/resource_type.py index 7298f67..b84ac0d 100644 --- a/infobip/models/resource_type.py +++ b/infobip/models/resource_type.py @@ -7,9 +7,10 @@ """ -from inspect import getfullargspec import pprint import re # noqa: F401 +from inspect import getfullargspec + from aenum import Enum, no_arg diff --git a/infobip/models/sms_advanced_binary_request.py b/infobip/models/sms_advanced_binary_request.py index 9613422..34f92b3 100644 --- a/infobip/models/sms_advanced_binary_request.py +++ b/infobip/models/sms_advanced_binary_request.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.sms_binary_message import SmsBinaryMessage from infobip.models.sms_sending_speed_limit import SmsSendingSpeedLimit diff --git a/infobip/models/sms_advanced_textual_request.py b/infobip/models/sms_advanced_textual_request.py index 478c008..43794f6 100644 --- a/infobip/models/sms_advanced_textual_request.py +++ b/infobip/models/sms_advanced_textual_request.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.sms_sending_speed_limit import SmsSendingSpeedLimit from infobip.models.sms_textual_message import Message from infobip.models.sms_tracking import SmsTracking diff --git a/infobip/models/sms_binary_content.py b/infobip/models/sms_binary_content.py index c978b03..6c25594 100644 --- a/infobip/models/sms_binary_content.py +++ b/infobip/models/sms_binary_content.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr diff --git a/infobip/models/sms_binary_message.py b/infobip/models/sms_binary_message.py index 8c7085b..8cafd9c 100644 --- a/infobip/models/sms_binary_message.py +++ b/infobip/models/sms_binary_message.py @@ -8,13 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime from typing import List, Optional + from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, constr + from infobip.models.sms_binary_content import SmsBinaryContent from infobip.models.sms_delivery_time_window import SmsDeliveryTimeWindow from infobip.models.sms_destination import Destination diff --git a/infobip/models/sms_bulk_request.py b/infobip/models/sms_bulk_request.py index 231f3ed..1685149 100644 --- a/infobip/models/sms_bulk_request.py +++ b/infobip/models/sms_bulk_request.py @@ -8,12 +8,12 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime +from inspect import getfullargspec from pydantic import BaseModel, Field diff --git a/infobip/models/sms_bulk_response.py b/infobip/models/sms_bulk_response.py index 2345e57..9f6bcc9 100644 --- a/infobip/models/sms_bulk_response.py +++ b/infobip/models/sms_bulk_response.py @@ -8,13 +8,14 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/sms_bulk_status.py b/infobip/models/sms_bulk_status.py index e406975..6b6c7a9 100644 --- a/infobip/models/sms_bulk_status.py +++ b/infobip/models/sms_bulk_status.py @@ -7,9 +7,10 @@ """ -from inspect import getfullargspec import pprint import re # noqa: F401 +from inspect import getfullargspec + from aenum import Enum, no_arg diff --git a/infobip/models/sms_bulk_status_response.py b/infobip/models/sms_bulk_status_response.py index 660b26c..8bd787a 100644 --- a/infobip/models/sms_bulk_status_response.py +++ b/infobip/models/sms_bulk_status_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.sms_bulk_status import SmsBulkStatus diff --git a/infobip/models/sms_delivery_day.py b/infobip/models/sms_delivery_day.py index dee1839..c6d7f97 100644 --- a/infobip/models/sms_delivery_day.py +++ b/infobip/models/sms_delivery_day.py @@ -7,9 +7,10 @@ """ -from inspect import getfullargspec import pprint import re # noqa: F401 +from inspect import getfullargspec + from aenum import Enum, no_arg diff --git a/infobip/models/sms_delivery_result.py b/infobip/models/sms_delivery_result.py index 51ba773..c045196 100644 --- a/infobip/models/sms_delivery_result.py +++ b/infobip/models/sms_delivery_result.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel + from infobip.models.sms_report import SmsReport diff --git a/infobip/models/sms_delivery_time_from.py b/infobip/models/sms_delivery_time_from.py index 7130e1d..99e4650 100644 --- a/infobip/models/sms_delivery_time_from.py +++ b/infobip/models/sms_delivery_time_from.py @@ -8,11 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - +from inspect import getfullargspec from pydantic import BaseModel, Field, conint diff --git a/infobip/models/sms_delivery_time_to.py b/infobip/models/sms_delivery_time_to.py index 29de300..059ca1d 100644 --- a/infobip/models/sms_delivery_time_to.py +++ b/infobip/models/sms_delivery_time_to.py @@ -8,11 +8,11 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - +from inspect import getfullargspec from pydantic import BaseModel, Field, conint diff --git a/infobip/models/sms_delivery_time_window.py b/infobip/models/sms_delivery_time_window.py index 92caa02..466122d 100644 --- a/infobip/models/sms_delivery_time_window.py +++ b/infobip/models/sms_delivery_time_window.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field + from infobip.models.sms_delivery_day import SmsDeliveryDay from infobip.models.sms_delivery_time_from import SmsDeliveryTimeFrom from infobip.models.sms_delivery_time_to import SmsDeliveryTimeTo diff --git a/infobip/models/sms_destination.py b/infobip/models/sms_destination.py index 87a4fd4..9a3fe78 100644 --- a/infobip/models/sms_destination.py +++ b/infobip/models/sms_destination.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr, constr diff --git a/infobip/models/sms_error.py b/infobip/models/sms_error.py index 3187f13..fe9b069 100644 --- a/infobip/models/sms_error.py +++ b/infobip/models/sms_error.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr diff --git a/infobip/models/sms_inbound_message.py b/infobip/models/sms_inbound_message.py index cb86548..d430e65 100644 --- a/infobip/models/sms_inbound_message.py +++ b/infobip/models/sms_inbound_message.py @@ -8,13 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr + from infobip.models.sms_price import SmsPrice diff --git a/infobip/models/sms_inbound_message_result.py b/infobip/models/sms_inbound_message_result.py index fe64e65..f90a433 100644 --- a/infobip/models/sms_inbound_message_result.py +++ b/infobip/models/sms_inbound_message_result.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictInt + from infobip.models.sms_inbound_message import SmsInboundMessage diff --git a/infobip/models/sms_india_dlt_options.py b/infobip/models/sms_india_dlt_options.py index ddee82a..08ed94f 100644 --- a/infobip/models/sms_india_dlt_options.py +++ b/infobip/models/sms_india_dlt_options.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/sms_language.py b/infobip/models/sms_language.py index c4877e5..cbbb89a 100644 --- a/infobip/models/sms_language.py +++ b/infobip/models/sms_language.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/sms_language_configuration.py b/infobip/models/sms_language_configuration.py index 07ee0c7..a8404c9 100644 --- a/infobip/models/sms_language_configuration.py +++ b/infobip/models/sms_language_configuration.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.sms_language import SmsLanguage diff --git a/infobip/models/sms_log.py b/infobip/models/sms_log.py index 9f86d7c..b25af50 100644 --- a/infobip/models/sms_log.py +++ b/infobip/models/sms_log.py @@ -8,13 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr + from infobip.models.sms_error import SmsError from infobip.models.sms_price import SmsPrice from infobip.models.sms_status import SmsStatus diff --git a/infobip/models/sms_logs_response.py b/infobip/models/sms_logs_response.py index 07ff6f2..cd3ba66 100644 --- a/infobip/models/sms_logs_response.py +++ b/infobip/models/sms_logs_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field + from infobip.models.sms_log import SmsLog diff --git a/infobip/models/sms_preview.py b/infobip/models/sms_preview.py index 36fd30a..db0be23 100644 --- a/infobip/models/sms_preview.py +++ b/infobip/models/sms_preview.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr + from infobip.models.sms_language_configuration import SmsLanguageConfiguration diff --git a/infobip/models/sms_preview_request.py b/infobip/models/sms_preview_request.py index 8860f1d..b5917f9 100644 --- a/infobip/models/sms_preview_request.py +++ b/infobip/models/sms_preview_request.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr, constr, validator diff --git a/infobip/models/sms_preview_response.py b/infobip/models/sms_preview_response.py index 60e4fa2..8bca9c1 100644 --- a/infobip/models/sms_preview_response.py +++ b/infobip/models/sms_preview_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.sms_preview import SmsPreview diff --git a/infobip/models/sms_price.py b/infobip/models/sms_price.py index 1488aa5..eb49301 100644 --- a/infobip/models/sms_price.py +++ b/infobip/models/sms_price.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictFloat, StrictStr diff --git a/infobip/models/sms_regional_options.py b/infobip/models/sms_regional_options.py index 46d758b..533a518 100644 --- a/infobip/models/sms_regional_options.py +++ b/infobip/models/sms_regional_options.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import BaseModel, Field + from infobip.models.sms_india_dlt_options import SmsIndiaDltOptions from infobip.models.sms_turkey_iys_options import SmsTurkeyIysOptions diff --git a/infobip/models/sms_report.py b/infobip/models/sms_report.py index 9d116d8..fbc1533 100644 --- a/infobip/models/sms_report.py +++ b/infobip/models/sms_report.py @@ -8,13 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr + from infobip.models.sms_error import SmsError from infobip.models.sms_price import SmsPrice from infobip.models.sms_status import SmsStatus diff --git a/infobip/models/sms_response.py b/infobip/models/sms_response.py index 68fa173..de8a37c 100644 --- a/infobip/models/sms_response.py +++ b/infobip/models/sms_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.sms_response_details import SmsResponseDetails diff --git a/infobip/models/sms_response_details.py b/infobip/models/sms_response_details.py index c393478..358b057 100644 --- a/infobip/models/sms_response_details.py +++ b/infobip/models/sms_response_details.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import BaseModel, Field, StrictStr + from infobip.models.sms_status import SmsStatus diff --git a/infobip/models/sms_sending_speed_limit.py b/infobip/models/sms_sending_speed_limit.py index 2d8ab6a..ae490ca 100644 --- a/infobip/models/sms_sending_speed_limit.py +++ b/infobip/models/sms_sending_speed_limit.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import Optional + from pydantic import BaseModel, Field, StrictInt + from infobip.models.sms_speed_limit_time_unit import SmsSpeedLimitTimeUnit diff --git a/infobip/models/sms_speed_limit_time_unit.py b/infobip/models/sms_speed_limit_time_unit.py index 42c05ff..ddc5bbb 100644 --- a/infobip/models/sms_speed_limit_time_unit.py +++ b/infobip/models/sms_speed_limit_time_unit.py @@ -7,9 +7,10 @@ """ -from inspect import getfullargspec import pprint import re # noqa: F401 +from inspect import getfullargspec + from aenum import Enum, no_arg diff --git a/infobip/models/sms_status.py b/infobip/models/sms_status.py index b73857a..27309de 100644 --- a/infobip/models/sms_status.py +++ b/infobip/models/sms_status.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr diff --git a/infobip/models/sms_textual_message.py b/infobip/models/sms_textual_message.py index 1ae4018..b9621b5 100644 --- a/infobip/models/sms_textual_message.py +++ b/infobip/models/sms_textual_message.py @@ -8,13 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime from typing import List, Optional + from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, constr + from infobip.models.sms_delivery_time_window import SmsDeliveryTimeWindow from infobip.models.sms_destination import Destination from infobip.models.sms_language import SmsLanguage diff --git a/infobip/models/sms_tracking.py b/infobip/models/sms_tracking.py index a58dd02..2f4cc86 100644 --- a/infobip/models/sms_tracking.py +++ b/infobip/models/sms_tracking.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictStr diff --git a/infobip/models/sms_turkey_iys_options.py b/infobip/models/sms_turkey_iys_options.py index 8366bfb..694c757 100644 --- a/infobip/models/sms_turkey_iys_options.py +++ b/infobip/models/sms_turkey_iys_options.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr, validator diff --git a/infobip/models/sms_update_status_request.py b/infobip/models/sms_update_status_request.py index fd95c28..70127b7 100644 --- a/infobip/models/sms_update_status_request.py +++ b/infobip/models/sms_update_status_request.py @@ -8,12 +8,13 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from pydantic import BaseModel + from infobip.models.sms_bulk_status import SmsBulkStatus diff --git a/infobip/models/sms_url_options.py b/infobip/models/sms_url_options.py index 23f2c3c..21949fd 100644 --- a/infobip/models/sms_url_options.py +++ b/infobip/models/sms_url_options.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictBool, StrictStr diff --git a/infobip/models/sms_webhook_inbound_report.py b/infobip/models/sms_webhook_inbound_report.py index 6ae4820..45a9c5a 100644 --- a/infobip/models/sms_webhook_inbound_report.py +++ b/infobip/models/sms_webhook_inbound_report.py @@ -8,13 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr + from infobip.models.message_price import MessagePrice diff --git a/infobip/models/sms_webhook_inbound_report_response.py b/infobip/models/sms_webhook_inbound_report_response.py index f085875..df60f47 100644 --- a/infobip/models/sms_webhook_inbound_report_response.py +++ b/infobip/models/sms_webhook_inbound_report_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field, StrictInt + from infobip.models.sms_webhook_inbound_report import SmsWebhookInboundReport diff --git a/infobip/models/sms_webhook_outbound_report.py b/infobip/models/sms_webhook_outbound_report.py index 4b51493..b9204f4 100644 --- a/infobip/models/sms_webhook_outbound_report.py +++ b/infobip/models/sms_webhook_outbound_report.py @@ -8,13 +8,15 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - from datetime import datetime from typing import Optional + from pydantic import BaseModel, Field, StrictInt, StrictStr + from infobip.models.message_error import MessageError from infobip.models.message_price import MessagePrice from infobip.models.message_status import MessageStatus diff --git a/infobip/models/sms_webhook_outbound_report_response.py b/infobip/models/sms_webhook_outbound_report_response.py index b941cf1..29eab82 100644 --- a/infobip/models/sms_webhook_outbound_report_response.py +++ b/infobip/models/sms_webhook_outbound_report_response.py @@ -8,13 +8,14 @@ from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json - - from typing import List, Optional + from pydantic import BaseModel, Field + from infobip.models.sms_webhook_outbound_report import SmsWebhookOutboundReport diff --git a/infobip/models/webhook_message_count.py b/infobip/models/webhook_message_count.py index 84b5351..0329a9c 100644 --- a/infobip/models/webhook_message_count.py +++ b/infobip/models/webhook_message_count.py @@ -8,13 +8,13 @@ from __future__ import annotations -from inspect import getfullargspec + +import json import pprint import re # noqa: F401 -import json - - +from inspect import getfullargspec from typing import Optional + from pydantic import BaseModel, Field, StrictInt diff --git a/requirements.txt b/requirements.txt index aae8069..17ca5c1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pydantic~=1.10.7 httpx~=0.24.0 aenum~=3.1.12 -pytest~=7.3.1 \ No newline at end of file +pytest~=7.3.1 diff --git a/samples/test_sms_live.py b/samples/test_sms_live.py index a396958..afea658 100644 --- a/samples/test_sms_live.py +++ b/samples/test_sms_live.py @@ -53,5 +53,6 @@ async def test_send_message(self): # Do something with the response. print(response) + print(response_body) self.assertEqual(response.status_code, 200) diff --git a/setup.cfg b/setup.cfg index 3e7d56a..e1ea382 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = infobip -version = 5.0.0 +version = 6.0.0 author = Luka Kilic, Dino Lozina, Erick Corona author_email = DevRel@infobip.com description = Python sdk for Infobip's API diff --git a/tests/test_sms.py b/tests/test_sms.py index 5bf386b..909a221 100644 --- a/tests/test_sms.py +++ b/tests/test_sms.py @@ -1,6 +1,6 @@ import pytest - from common import TEST_URL, get_test_client + from infobip.models.sms_advanced_textual_request import SendSMSRequestBody from infobip.models.sms_destination import Destination from infobip.models.sms_preview_request import PreviewSMSRequestBody diff --git a/tox.ini b/tox.ini index 879fa21..8dec4ab 100644 --- a/tox.ini +++ b/tox.ini @@ -14,19 +14,17 @@ python = [testenv] deps = + aenum==3.1.0 + httpx==0.24.0 pydantic==1.9.0 - requests==2.27.1 - pytest==6.2.5 + pytest-asyncio==0.21.0 pytest-cov==3.0.0 - pytest-httpserver==1.0.4 - pydantic-factories==1.2.3 - pytest-cases==3.6.8 - pytest-cov==3.0.0 - regex==2022.3.15 + pytest-httpx==0.22.0 + pytest==7.3.1 depends = {py38, py39, py310}: clean report: py38, py39, py310 -commands = python -m pytest --cov-append --cov=infobip_channels --cov=infobip_platform tests/ +commands = python -m pytest --cov-append --cov=./infobip/api/ tests/ [testenv:report] deps = coverage From 5486798b3a412b8ef3b63936fa1fa7b638ac389a Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Tue, 9 May 2023 13:17:02 -0600 Subject: [PATCH 10/18] CI fixes, doc improvements --- .pre-commit-config.yaml | 1 + README.md | 2 +- infobip/api/sms.py | 4 +++- infobip/client.py | 18 +++++++++++++++++- requirements.txt => requirements/common.txt | 0 requirements/dev.txt | 4 ++++ samples/test_mms_live.py | 5 +++-- samples/test_sms_live.py | 10 ++++++---- tox.ini | 10 ++++++---- 9 files changed, 41 insertions(+), 13 deletions(-) rename requirements.txt => requirements/common.txt (100%) create mode 100644 requirements/dev.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 695b7cb..22c15f6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,4 +21,5 @@ repos: - id: flake8 args: - "--ignore=E501, W503" + exclude: "infobip/models/" additional_dependencies: [flake8-print] diff --git a/README.md b/README.md index 1a758ff..9bea8af 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ with real payloads. For SDK versioning we use [Semantic Versioning](https://semver.org) scheme. -Python 3.6 is the minimum supported version by this library. +Python 3.8 is the minimum supported version by this library. ## 🧡 Want to help and improve this open-source SDK? diff --git a/infobip/api/sms.py b/infobip/api/sms.py index ea34e0f..ac85156 100644 --- a/infobip/api/sms.py +++ b/infobip/api/sms.py @@ -32,7 +32,9 @@ def send( self, request_body: SendSMSRequestBody, ) -> Awaitable[Response]: - """Send SMS message + """Send an SMS message. You can send a simple single message to a single destination, up to batch sending of + personalized messages to the thousands of recipients with a single API request. Language, transliteration, + scheduling and every advanced feature you can think of is supported. :param request_body: Request body for sending an SMS message """ diff --git a/infobip/client.py b/infobip/client.py index 2f54e15..dcdd9bc 100644 --- a/infobip/client.py +++ b/infobip/client.py @@ -1,3 +1,5 @@ +import importlib.metadata +import sys from os import getenv from httpx import AsyncClient @@ -14,9 +16,23 @@ def __init__(self, base_url=None, api_key: str = None): api_key = getenv("IB_API_KEY") headers = {"Authorization": f"App {api_key}"} - headers.update({"User-Agent": "infobip-api-python-sdk/6.0.0"}) + headers.update({"User-Agent": self.__get_user_agent()}) super().__init__(base_url=base_url, headers=headers) self.SMS = SMSClient(self) self.MMS = MMSClient(self) + + def __get_user_agent(cls) -> str: + return f"@infobip/python-sdk{cls.__get_package_version()} python/{sys.version.split(' ')[0]}" + + def __get_package_version(cls) -> str: + sdk_version = "" + if "infobip_channels" in sys.modules: + try: + sdk_version = "/" + importlib.metadata.distribution("infobip").version + except importlib.metadata.PackageNotFoundError: + # Ignore as package is not installed in development environment. + pass + + return sdk_version diff --git a/requirements.txt b/requirements/common.txt similarity index 100% rename from requirements.txt rename to requirements/common.txt diff --git a/requirements/dev.txt b/requirements/dev.txt new file mode 100644 index 0000000..7430699 --- /dev/null +++ b/requirements/dev.txt @@ -0,0 +1,4 @@ +pytest-asyncio~=0.21.0 +pytest-cov~=3.0.0 +pytest-httpx~=0.22.0 +pytest~=7.3.1 diff --git a/samples/test_mms_live.py b/samples/test_mms_live.py index d254662..58d06f8 100644 --- a/samples/test_mms_live.py +++ b/samples/test_mms_live.py @@ -23,7 +23,8 @@ async def test_get_inbound_messages(self): response_body = GetInboundMessagesResponseBody.from_json(response.text) # Do something with the response. - print(response) - print(response_body.results) + # print(response) + # print(response_body.results) self.assertEqual(response.status_code, 200) + self.assertIsNotNone(response_body.results) diff --git a/samples/test_sms_live.py b/samples/test_sms_live.py index afea658..cbff9bd 100644 --- a/samples/test_sms_live.py +++ b/samples/test_sms_live.py @@ -25,10 +25,11 @@ async def test_preview_message(self): response_body = PreviewSMSResponseBody.from_json(response.text) # Do something with the response. - print(response) - print(response_body.previews) + # print(response) + # print(response_body.previews) self.assertEqual(response.status_code, 200) + self.assertIsNotNone(response_body.previews) async def test_send_message(self): # Create a request body object and validate its contents. @@ -52,7 +53,8 @@ async def test_send_message(self): response_body = SendSMSResponseBody.from_json(response.text) # Do something with the response. - print(response) - print(response_body) + # print(response) + # print(response_body) self.assertEqual(response.status_code, 200) + self.assertIsNotNone(response_body.messages) diff --git a/tox.ini b/tox.ini index 8dec4ab..23cdb5d 100644 --- a/tox.ini +++ b/tox.ini @@ -4,6 +4,7 @@ env_list = py38 py39 py310 + py311 report [gh-actions] @@ -11,20 +12,21 @@ python = 3.8: py38 3.9: py39 3.10: py310 + 3.11: py311 [testenv] deps = aenum==3.1.0 httpx==0.24.0 - pydantic==1.9.0 + pydantic==1.10.7 pytest-asyncio==0.21.0 pytest-cov==3.0.0 pytest-httpx==0.22.0 pytest==7.3.1 depends = - {py38, py39, py310}: clean - report: py38, py39, py310 -commands = python -m pytest --cov-append --cov=./infobip/api/ tests/ + {py38, py39, py310, py311}: clean + report: py38, py39, py310, py311 +commands = python -m pytest --cov=./infobip/api/ tests/ [testenv:report] deps = coverage From 91a186da5caef821422a53799fdbe103d0457ec7 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Tue, 9 May 2023 13:31:00 -0600 Subject: [PATCH 11/18] Add spelling exceptions --- .cspell.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.cspell.json b/.cspell.json index 697985d..40a81bf 100644 --- a/.cspell.json +++ b/.cspell.json @@ -11,38 +11,60 @@ "misc" ], "words": [ + "AUTORESPONSE", "AYΣTHPO", "AΘHNAIΩN", "AΠOΦAΣH", "BIREYSEL", + "CLEARSKY", "EINAI", "EKKΛHΣIAΣ", "EMΠAPΓKO", "ENROUTE", "EΠIBAΛEI", + "GIIN", + "ICEX", "KAΘOΛIKO", "Kilic", "Lozina", "Luka", "MEΓAPIKO", + "MMSADVANCEDMESSAGESEGMENT", + "MMSWEBHOOKINBOUNDMESSAGESEGMENT", + "PSTN", + "SEHK", + "SMIL", + "SMPP", + "SZSE", + "Smil", + "Smpp", "Snyk", "TACIR", + "TENDLC", + "TWSE", + "USSD", "WABA", "aabe", + "aenum", "conint", "conlist", "defaultplaceholders", "dtmf", "formdata", + "httpx", "ibsso", "ijkl", "infobip", "intermediatereport", + "klass", + "motogstylus", "msisdn", "preserverecipients", + "pstn", "pydantic", "replyto", "setuptools", + "smil", "somexternal", "templateid", "testenv", From f63833b7b8c723b55300c52bee31e7e3c2bbd6be Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Wed, 10 May 2023 12:55:22 -0600 Subject: [PATCH 12/18] Fix Awaitable imports --- infobip/api/mms.py | 2 +- infobip/api/sms.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/infobip/api/mms.py b/infobip/api/mms.py index a9ccd9f..ef21b05 100644 --- a/infobip/api/mms.py +++ b/infobip/api/mms.py @@ -1,4 +1,4 @@ -from collections.abc import Awaitable +from typing import Awaitable from httpx import AsyncClient, Response diff --git a/infobip/api/sms.py b/infobip/api/sms.py index ac85156..48be970 100644 --- a/infobip/api/sms.py +++ b/infobip/api/sms.py @@ -1,4 +1,4 @@ -from collections.abc import Awaitable +from typing import Awaitable from httpx import AsyncClient, Response From de94d6e4ed83a56d8d5eb237c7d16f7061bad1e7 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Wed, 10 May 2023 13:03:21 -0600 Subject: [PATCH 13/18] Add python 3.11 to workflows --- .github/workflows/python-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 2a8e8ce..08c55cd 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.8', '3.9', '3.10'] + python-version: ['3.8', '3.9', '3.10', '3.11'] steps: - uses: actions/checkout@v2 From 4a2c4a5aefb3e6d9b5fbd1ca169ef043f825e996 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Mon, 15 May 2023 12:55:33 -0600 Subject: [PATCH 14/18] Remove unneeded requirement --- requirements/common.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements/common.txt b/requirements/common.txt index 17ca5c1..a5a63d4 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -1,4 +1,3 @@ pydantic~=1.10.7 httpx~=0.24.0 aenum~=3.1.12 -pytest~=7.3.1 From f4f81b4e915352d9edeac2c5437b540ee61e87ef Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Tue, 23 May 2023 16:13:45 -0600 Subject: [PATCH 15/18] Remove 3.11 from ci tests --- .github/workflows/python-package.yml | 2 +- setup.cfg | 5 +++++ tox.ini | 6 ++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 08c55cd..2a8e8ce 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.8', '3.9', '3.10', '3.11'] + python-version: ['3.8', '3.9', '3.10'] steps: - uses: actions/checkout@v2 diff --git a/setup.cfg b/setup.cfg index e1ea382..3859942 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,6 +12,11 @@ project_urls = Bug Tracker = https://github.com/infobip-community/infobip-api-python-sdk/issues classifiers = Programming Language :: Python :: 3 + Programming Language :: Python :: 3 :: Only + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 License :: OSI Approved :: MIT License Operating System :: OS Independent diff --git a/tox.ini b/tox.ini index 23cdb5d..72289dc 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,6 @@ env_list = py38 py39 py310 - py311 report [gh-actions] @@ -12,7 +11,6 @@ python = 3.8: py38 3.9: py39 3.10: py310 - 3.11: py311 [testenv] deps = @@ -24,8 +22,8 @@ deps = pytest-httpx==0.22.0 pytest==7.3.1 depends = - {py38, py39, py310, py311}: clean - report: py38, py39, py310, py311 + {py38, py39, py310}: clean + report: py38, py39, py310 commands = python -m pytest --cov=./infobip/api/ tests/ [testenv:report] From c8c29f6dc8afe9cb9eb57d7c0686247eb09ddf30 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Wed, 24 May 2023 19:11:20 -0600 Subject: [PATCH 16/18] Update pydantic to be compatible with py311 --- .github/workflows/python-package.yml | 2 +- requirements/common.txt | 2 +- tox.ini | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 2a8e8ce..08c55cd 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.8', '3.9', '3.10'] + python-version: ['3.8', '3.9', '3.10', '3.11'] steps: - uses: actions/checkout@v2 diff --git a/requirements/common.txt b/requirements/common.txt index a5a63d4..2376760 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -1,3 +1,3 @@ -pydantic~=1.10.7 +pydantic~=1.10.8 httpx~=0.24.0 aenum~=3.1.12 diff --git a/tox.ini b/tox.ini index 72289dc..99125d6 100644 --- a/tox.ini +++ b/tox.ini @@ -4,6 +4,7 @@ env_list = py38 py39 py310 + py311 report [gh-actions] @@ -11,19 +12,20 @@ python = 3.8: py38 3.9: py39 3.10: py310 + 3.11: py311 [testenv] deps = aenum==3.1.0 httpx==0.24.0 - pydantic==1.10.7 + pydantic==1.10.8 pytest-asyncio==0.21.0 pytest-cov==3.0.0 pytest-httpx==0.22.0 pytest==7.3.1 depends = - {py38, py39, py310}: clean - report: py38, py39, py310 + {py38, py39, py310, py311}: clean + report: py38, py39, py310, py311 commands = python -m pytest --cov=./infobip/api/ tests/ [testenv:report] From 2cc0f662207c6761f313d55a05b55d64566005bd Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Wed, 24 May 2023 19:16:02 -0600 Subject: [PATCH 17/18] Update pydantic dep --- setup.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 3859942..99bb87e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,7 +26,8 @@ package_dir = packages = find: python_requires = >=3.6 install_requires = - pydantic~=1.9.0 + pydantic~=1.10.8 + httpx~=0.24.1 [options.packages.find] where = . From d0330075b51fa6acda2d8d2380ac87632ad063e9 Mon Sep 17 00:00:00 2001 From: Erick Daniel Corona Date: Mon, 5 Jun 2023 11:48:38 -0600 Subject: [PATCH 18/18] Add sync client endpoints and tests --- infobip/api/sms.py | 34 ++++++++++++++++++++++++--------- infobip/client.py | 34 +++++++++++++++++---------------- infobip/sync_client.py | 21 ++++++++++++++++++++ samples/test_sms_live.py | 26 ++++++++++++++++++++++++- tests/common.py | 5 +++++ tests/test_sms.py | 41 ++++++++++++++++++++++++++++++++++++---- 6 files changed, 131 insertions(+), 30 deletions(-) create mode 100644 infobip/sync_client.py diff --git a/infobip/api/sms.py b/infobip/api/sms.py index 48be970..7f88a10 100644 --- a/infobip/api/sms.py +++ b/infobip/api/sms.py @@ -1,22 +1,20 @@ from typing import Awaitable -from httpx import AsyncClient, Response +from httpx import AsyncClient, Client, Response from infobip.models.sms_advanced_textual_request import SendSMSRequestBody from infobip.models.sms_preview_request import PreviewSMSRequestBody +PATH_PREVIEW_SMS = "/sms/1/preview" +PATH_SEND_SMS = "/sms/2/text/advanced" -class SMSClient: - PATH_PREVIEW_SMS = "/sms/1/preview" - PATH_SEND_SMS = "/sms/2/text/advanced" +class SMSClient: def __init__(self, client: AsyncClient): self.client = client self.client.headers.update({"content-type": "application/json"}) - def preview_message( - self, request_body: PreviewSMSRequestBody - ) -> Awaitable[Response]: + def preview(self, request_body: PreviewSMSRequestBody) -> Awaitable[Response]: """Check how different message configurations will affect your message text, number of characters and message parts. @@ -24,7 +22,7 @@ def preview_message( """ return self.client.post( - self.PATH_PREVIEW_SMS, + PATH_PREVIEW_SMS, json=request_body.to_dict(), ) @@ -40,6 +38,24 @@ def send( """ return self.client.post( - self.PATH_SEND_SMS, + PATH_SEND_SMS, + json=request_body.to_dict(), + ) + + +class SyncSMSClient: + def __init__(self, client: Client): + self._client = client + self._client.headers.update({"content-type": "application/json"}) + + def preview(self, request_body: PreviewSMSRequestBody) -> Response: + """Check how different message configurations will affect your message text, number of characters and message + parts. This is a synchronous version of the method. + + :param request_body: Request body for previewing an SMS message + """ + + return self._client.post( + PATH_PREVIEW_SMS, json=request_body.to_dict(), ) diff --git a/infobip/client.py b/infobip/client.py index dcdd9bc..7ce0865 100644 --- a/infobip/client.py +++ b/infobip/client.py @@ -8,31 +8,33 @@ from infobip.api.sms import SMSClient +def _get_user_agent() -> str: + return f"@infobip/python-sdk{_get_package_version()} python/{sys.version.split(' ')[0]}" + + +def _get_package_version() -> str: + sdk_version = "" + if "infobip_channels" in sys.modules: + try: + sdk_version = "/" + importlib.metadata.distribution("infobip").version + except importlib.metadata.PackageNotFoundError: + # Ignore as package is not installed in development environment. + pass + + return sdk_version + + class APIClient(AsyncClient): - def __init__(self, base_url=None, api_key: str = None): + def __init__(self, base_url: str = None, api_key: str = None): if base_url is None: base_url = getenv("IB_BASE_URL") if api_key is None: api_key = getenv("IB_API_KEY") headers = {"Authorization": f"App {api_key}"} - headers.update({"User-Agent": self.__get_user_agent()}) + headers.update({"User-Agent": _get_user_agent()}) super().__init__(base_url=base_url, headers=headers) self.SMS = SMSClient(self) self.MMS = MMSClient(self) - - def __get_user_agent(cls) -> str: - return f"@infobip/python-sdk{cls.__get_package_version()} python/{sys.version.split(' ')[0]}" - - def __get_package_version(cls) -> str: - sdk_version = "" - if "infobip_channels" in sys.modules: - try: - sdk_version = "/" + importlib.metadata.distribution("infobip").version - except importlib.metadata.PackageNotFoundError: - # Ignore as package is not installed in development environment. - pass - - return sdk_version diff --git a/infobip/sync_client.py b/infobip/sync_client.py new file mode 100644 index 0000000..cacea53 --- /dev/null +++ b/infobip/sync_client.py @@ -0,0 +1,21 @@ +from os import getenv + +from httpx import Client + +from infobip.api.sms import SyncSMSClient +from infobip.client import _get_user_agent + + +class SyncAPIClient: + def __init__(self, base_url: str = None, api_key: str = None): + if base_url is None: + base_url = getenv("IB_BASE_URL") + if api_key is None: + api_key = getenv("IB_API_KEY") + + headers = {"Authorization": f"App {api_key}"} + headers.update({"User-Agent": _get_user_agent()}) + + client = Client(base_url=base_url, headers=headers) + + self.SMS = SyncSMSClient(client) diff --git a/samples/test_sms_live.py b/samples/test_sms_live.py index cbff9bd..b7cf5a5 100644 --- a/samples/test_sms_live.py +++ b/samples/test_sms_live.py @@ -7,6 +7,7 @@ from infobip.models.sms_preview_response import PreviewSMSResponseBody from infobip.models.sms_response import SendSMSResponseBody from infobip.models.sms_textual_message import Message +from infobip.sync_client import SyncAPIClient class SMSTestCase(unittest.IsolatedAsyncioTestCase): @@ -19,7 +20,7 @@ async def test_preview_message(self): ) # Call the endpoint and await returned Coroutine - response = await self.client.SMS.preview_message(request_body) + response = await self.client.SMS.preview(request_body) # Parse and validate response if needed. response_body = PreviewSMSResponseBody.from_json(response.text) @@ -58,3 +59,26 @@ async def test_send_message(self): self.assertEqual(response.status_code, 200) self.assertIsNotNone(response_body.messages) + + +class SyncSMSTestCase(unittest.TestCase): + client = SyncAPIClient() + + def test_preview_message(self): + # Create a request body object and validate its contents. + request_body = PreviewSMSRequestBody( + text="Let's see how many characters remain unused in this message." + ) + + # Call the endpoint and await returned Coroutine + response = self.client.SMS.preview(request_body) + + # Parse and validate response if needed. + response_body = PreviewSMSResponseBody.from_json(response.text) + + # Do something with the response. + # print(response) + # print(response_body.previews) + + self.assertEqual(response.status_code, 200) + self.assertIsNotNone(response_body.previews) diff --git a/tests/common.py b/tests/common.py index 8de4ce4..c3ef687 100644 --- a/tests/common.py +++ b/tests/common.py @@ -1,4 +1,5 @@ from infobip.client import APIClient +from infobip.sync_client import SyncAPIClient TEST_URL = "https://some.url" TEST_API_KEY = "some-api-key" @@ -6,3 +7,7 @@ def get_test_client(): return APIClient(base_url=TEST_URL, api_key=TEST_API_KEY) + + +def get_test_sync_client(): + return SyncAPIClient(base_url=TEST_URL, api_key=TEST_API_KEY) diff --git a/tests/test_sms.py b/tests/test_sms.py index 909a221..2c9f8fe 100644 --- a/tests/test_sms.py +++ b/tests/test_sms.py @@ -1,6 +1,7 @@ import pytest -from common import TEST_URL, get_test_client +from common import TEST_URL, get_test_client, get_test_sync_client +from infobip.api.sms import PATH_PREVIEW_SMS, PATH_SEND_SMS from infobip.models.sms_advanced_textual_request import SendSMSRequestBody from infobip.models.sms_destination import Destination from infobip.models.sms_preview_request import PreviewSMSRequestBody @@ -25,7 +26,7 @@ async def test_preview_message(httpx_mock): async with get_test_client() as client: httpx_mock.add_response( - url=f"{TEST_URL}{client.SMS.PATH_PREVIEW_SMS}", + url=f"{TEST_URL}{PATH_PREVIEW_SMS}", method="POST", json=expected_response, status_code=200, @@ -34,7 +35,7 @@ async def test_preview_message(httpx_mock): request_body = PreviewSMSRequestBody( text="Let's see how many characters remain unused in this message.", ) - response = await client.SMS.preview_message(request_body) + response = await client.SMS.preview(request_body) assert response.status_code == 200 assert ( @@ -64,7 +65,7 @@ async def test_send_sms_message(httpx_mock): async with get_test_client() as client: httpx_mock.add_response( - url=f"{TEST_URL}{client.SMS.PATH_SEND_SMS}", + url=f"{TEST_URL}{PATH_SEND_SMS}", method="POST", json=expected_response, status_code=200, @@ -88,3 +89,35 @@ async def test_send_sms_message(httpx_mock): assert ( SendSMSResponseBody.from_json(response.text).to_dict() == expected_response ) + + +def test_sync_preview(httpx_mock): + expected_response = { + "originalText": "Let's see how many characters remain unused in this message.", + "previews": [ + { + "textPreview": "Let's see how many characters remain unused in this message.", + "messageCount": 1, + "charactersRemaining": 96, + "configuration": {}, + } + ], + } + + client = get_test_sync_client() + httpx_mock.add_response( + url=f"{TEST_URL}{PATH_PREVIEW_SMS}", + method="POST", + json=expected_response, + status_code=200, + ) + + request_body = PreviewSMSRequestBody( + text="Let's see how many characters remain unused in this message.", + ) + response = client.SMS.preview(request_body) + + assert response.status_code == 200 + assert ( + PreviewSMSResponseBody.from_json(response.text).to_dict() == expected_response + )