Skip to main content

ippanel_sms/
error.rs

1
2use std::fmt;
3
4/// Error codes returned by IPPanel API.
5///
6/// Each variant represents a specific error code and its meaning.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[repr(i32)]
9pub enum ErrorCode {
10    Success = 0,
11    MessageBodyIsEmpty = 1,
12    UserLimited = 2,
13    NumberNotAssignedToYou = 3,
14    RecipientsEmpty = 4,
15    CreditNotEnough = 5,
16    NumberNotProfitForBulkSend = 7,
17    NumberCannotSendAtThisHour = 9,
18    MaxRecipientsExceeded = 98,
19    OperatorLineDisconnected = 99,
20    AudioFileExtensionInvalid = 21,
21    AudioFileSizeInvalid = 22,
22    AudioMessageRetryInvalid = 23,
23    PhonebookContactInvalid = 100,
24    ContactExists = 101,
25    ContactSaved = 102,
26    MaxRecipientsVoiceNotMet = 111,
27    VoiceRetryMustBeOne = 131,
28    AudioFileAddressNotEntered = 132,
29    UsernameSpecialChar = 301,
30    PricingNotSet = 302,
31    UsernameNotEntered = 303,
32    UsernameAlreadyChosen = 304,
33    NationalCodeNotEntered = 306,
34    NationalCodeInvalid = 307,
35    BirthCertInvalid = 308,
36    BirthCertNotEntered = 309,
37    EmailNotEntered = 310,
38    PhoneNotEntered = 311,
39    PhoneIncorrect = 312,
40    AddressNotEntered = 313,
41    MobileNotEntered = 314,
42    MobileIncorrect = 315,
43    AccessLevelIncorrect = 316,
44    PasswordNotEntered = 317,
45    FutureBulkCanceled = 455,
46    BulkCodeInvalid = 456,
47    TicketCodeInvalid = 458,
48    NoAgencyAccess = 964,
49    UsernameOrPasswordIncorrect = 962,
50    AccessInvalid = 963,
51    PatternInvalid = 971,
52    PatternParamsInvalid = 970,
53    PatternRecipientInvalid = 972,
54    SendTimeInvalid = 992,
55    PhonebookNotArray = 993,
56    NeedBankCardImage = 994,
57    NeedBankCardNumber = 995,
58    PatternNotActive = 996,
59    PatternNotAllowed = 997,
60    NationalIdOrCardNotApproved = 998,
61    UsernameFormatInvalid = 1001,
62    PasswordTooSimple = 1002,
63    RegistrationError = 1003,
64    RegistrationError2 = 1004,
65    RegistrationError3 = 1005,
66    Unknown = -1,
67}
68
69impl ErrorCode {
70    pub fn from_i32(code: i32) -> Self {
71        use ErrorCode::*;
72        match code {
73            0 => Success,
74            1 => MessageBodyIsEmpty,
75            2 => UserLimited,
76            3 => NumberNotAssignedToYou,
77            4 => RecipientsEmpty,
78            5 => CreditNotEnough,
79            7 => NumberNotProfitForBulkSend,
80            9 => NumberCannotSendAtThisHour,
81            98 => MaxRecipientsExceeded,
82            99 => OperatorLineDisconnected,
83            21 => AudioFileExtensionInvalid,
84            22 => AudioFileSizeInvalid,
85            23 => AudioMessageRetryInvalid,
86            100 => PhonebookContactInvalid,
87            101 => ContactExists,
88            102 => ContactSaved,
89            111 => MaxRecipientsVoiceNotMet,
90            131 => VoiceRetryMustBeOne,
91            132 => AudioFileAddressNotEntered,
92            301 => UsernameSpecialChar,
93            302 => PricingNotSet,
94            303 => UsernameNotEntered,
95            304 => UsernameAlreadyChosen,
96            305 => UsernameNotEntered,
97            306 => NationalCodeNotEntered,
98            307 => NationalCodeInvalid,
99            308 => BirthCertInvalid,
100            309 => BirthCertNotEntered,
101            310 => EmailNotEntered,
102            311 => PhoneNotEntered,
103            312 => PhoneIncorrect,
104            313 => AddressNotEntered,
105            314 => MobileNotEntered,
106            315 => MobileIncorrect,
107            316 => AccessLevelIncorrect,
108            317 => PasswordNotEntered,
109            455 => FutureBulkCanceled,
110            456 => BulkCodeInvalid,
111            458 => TicketCodeInvalid,
112            964 => NoAgencyAccess,
113            962 => UsernameOrPasswordIncorrect,
114            963 => AccessInvalid,
115            971 => PatternInvalid,
116            970 => PatternParamsInvalid,
117            972 => PatternRecipientInvalid,
118            992 => SendTimeInvalid,
119            993 => PhonebookNotArray,
120            994 => NeedBankCardImage,
121            995 => NeedBankCardNumber,
122            996 => PatternNotActive,
123            997 => PatternNotAllowed,
124            998 => NationalIdOrCardNotApproved,
125            1001 => UsernameFormatInvalid,
126            1002 => PasswordTooSimple,
127            1003 => RegistrationError,
128            1004 => RegistrationError2,
129            1005 => RegistrationError3,
130            _ => Unknown,
131        }
132    }
133
134    pub fn code(&self) -> i32 {
135        *self as i32
136    }
137
138    pub fn english_message(&self) -> &'static str {
139        match self {
140            ErrorCode::Success => "Operation completed successfully.",
141            ErrorCode::MessageBodyIsEmpty => "Message body is empty.",
142            ErrorCode::UserLimited => "User is limited.",
143            ErrorCode::NumberNotAssignedToYou => "Number not assigned to you.",
144            ErrorCode::RecipientsEmpty => "Recipients is empty.",
145            ErrorCode::CreditNotEnough => "Credit not enough.",
146            ErrorCode::NumberNotProfitForBulkSend => "Number not profit for bulk send.",
147            ErrorCode::NumberCannotSendAtThisHour => "Number cannot send at this hour.",
148            ErrorCode::MaxRecipientsExceeded => "Maximum recipients number exceeded.",
149            ErrorCode::OperatorLineDisconnected => "Operator line is disconnected.",
150            ErrorCode::AudioFileExtensionInvalid => "Audio file extension is invalid.",
151            ErrorCode::AudioFileSizeInvalid => "Audio file size is invalid.",
152            ErrorCode::AudioMessageRetryInvalid => "Audio message retry count is invalid.",
153            ErrorCode::PhonebookContactInvalid => "Phonebook contact number is invalid.",
154            ErrorCode::ContactExists => "Contact already exists in phonebook.",
155            ErrorCode::ContactSaved => "Contact saved successfully in phonebook.",
156            ErrorCode::MaxRecipientsVoiceNotMet => "Maximum recipients for voice message not met.",
157            ErrorCode::VoiceRetryMustBeOne => "Voice message retry count must be one.",
158            ErrorCode::AudioFileAddressNotEntered => "Audio file address not entered.",
159            ErrorCode::UsernameSpecialChar => "Special character used in username.",
160            ErrorCode::PricingNotSet => "Pricing not set.",
161            ErrorCode::UsernameNotEntered => "Username not entered.",
162            ErrorCode::UsernameAlreadyChosen => "Username already chosen.",
163            ErrorCode::NationalCodeNotEntered => "National code not entered.",
164            ErrorCode::NationalCodeInvalid => "National code entered incorrectly.",
165            ErrorCode::BirthCertInvalid => "Birth certificate number is invalid.",
166            ErrorCode::BirthCertNotEntered => "Birth certificate number not entered.",
167            ErrorCode::EmailNotEntered => "User email not entered.",
168            ErrorCode::PhoneNotEntered => "Phone number not entered.",
169            ErrorCode::PhoneIncorrect => "Phone entered incorrectly.",
170            ErrorCode::AddressNotEntered => "Address not entered.",
171            ErrorCode::MobileNotEntered => "Mobile number not entered.",
172            ErrorCode::MobileIncorrect => "Mobile number entered incorrectly.",
173            ErrorCode::AccessLevelIncorrect => "Access level entered incorrectly.",
174            ErrorCode::PasswordNotEntered => "Password not entered.",
175            ErrorCode::FutureBulkCanceled => "Future sending for bulk code canceled.",
176            ErrorCode::BulkCodeInvalid => "Bulk code is invalid.",
177            ErrorCode::TicketCodeInvalid => "Ticket code is invalid.",
178            ErrorCode::NoAgencyAccess => "You do not have agency access.",
179            ErrorCode::UsernameOrPasswordIncorrect => "Username or password is incorrect.",
180            ErrorCode::AccessInvalid => "Access is invalid.",
181            ErrorCode::PatternInvalid => "Pattern is invalid.",
182            ErrorCode::PatternParamsInvalid => "Pattern parameters are invalid.",
183            ErrorCode::PatternRecipientInvalid => "Recipient for pattern is invalid.",
184            ErrorCode::SendTimeInvalid => "Messages can be sent from 8 to 23.",
185            ErrorCode::PhonebookNotArray => "Phonebook must be an array.",
186            ErrorCode::NeedBankCardImage => "Please upload a picture of your bank card from the documents menu.",
187            ErrorCode::NeedBankCardNumber => "To send with shared lines, please register your bank card number for identity verification.",
188            ErrorCode::PatternNotActive => "Pattern is not active.",
189            ErrorCode::PatternNotAllowed => "You are not allowed to send from this pattern.",
190            ErrorCode::NationalIdOrCardNotApproved => "Your national ID or bank card is not approved.",
191            ErrorCode::UsernameFormatInvalid => "Username format is incorrect, at least 5 characters (letters and numbers only).",
192            ErrorCode::PasswordTooSimple => "Password is too simple.",
193            ErrorCode::RegistrationError | ErrorCode::RegistrationError2 | ErrorCode::RegistrationError3 => "Registration error, contact support.",
194            ErrorCode::Unknown => "Unknown error.",
195        }
196    }
197
198    pub fn persian_message(&self) -> &'static str {
199        match self {
200            ErrorCode::Success => "عملیات با موفقیت انجام شده است.",
201            ErrorCode::MessageBodyIsEmpty => "متن پیام خالی می باشد.",
202            ErrorCode::UserLimited => "کاربر محدود گردیده است.",
203            ErrorCode::NumberNotAssignedToYou => "خط به شما تعلق ندارد.",
204            ErrorCode::RecipientsEmpty => "گیرندگان خالی است.",
205            ErrorCode::CreditNotEnough => "اعتبار کافی نیست.",
206            ErrorCode::NumberNotProfitForBulkSend => "خط مورد نظر برای ارسال انبوه مناسب نمی‌باشد.",
207            ErrorCode::NumberCannotSendAtThisHour => "خط مورد نظر در این ساعت امکان ارسال ندارد.",
208            ErrorCode::MaxRecipientsExceeded => "حداکثر تعداد گیرنده رعایت نشده است.",
209            ErrorCode::OperatorLineDisconnected => "اپراتور خط ارسالی قطع می‌باشد.",
210            ErrorCode::AudioFileExtensionInvalid => "پسوند فایل صوتی نامعتبر است.",
211            ErrorCode::AudioFileSizeInvalid => "سایز فایل صوتی نامعتبر است.",
212            ErrorCode::AudioMessageRetryInvalid => "تعداد تلاش در پیام صوتی نامعتبر است.",
213            ErrorCode::PhonebookContactInvalid => "شماره مخاطب دفترچه تلفن نامعتبر می‌باشد.",
214            ErrorCode::ContactExists => "شماره مخاطب در دفترچه تلفن وجود دارد.",
215            ErrorCode::ContactSaved => "شماره مخاطب با موفقیت در دفترچه تلفن ذخیره گردید.",
216            ErrorCode::MaxRecipientsVoiceNotMet => "حداکثر تعداد گیرنده برای ارسال پیام صوتی رعایت نشده است.",
217            ErrorCode::VoiceRetryMustBeOne => "تعداد تلاش در پیام صوتی باید یکبار باشد.",
218            ErrorCode::AudioFileAddressNotEntered => "آدرس فایل صوتی وارد نگردیده است.",
219            ErrorCode::UsernameSpecialChar => "از حرف ویژه در نام کاربری استفاده گردیده است.",
220            ErrorCode::PricingNotSet => "قیمت گذاری انجام نشده است.",
221            ErrorCode::UsernameNotEntered => "نام کاربری وارد نگردیده است.",
222            ErrorCode::UsernameAlreadyChosen => "نام کاربری قبلا انتخاب گردیده است.",
223            ErrorCode::NationalCodeNotEntered => "کد ملی وارد نشده است.",
224            ErrorCode::NationalCodeInvalid => "کد ملی به خطا وارد شده است.",
225            ErrorCode::BirthCertInvalid => "شماره شناسنامه نا معتبر است.",
226            ErrorCode::BirthCertNotEntered => "شماره شناسنامه وارد نگردیده است.",
227            ErrorCode::EmailNotEntered => "ایمیل کاربر وارد نگردیده است.",
228            ErrorCode::PhoneNotEntered => "شماره تلفن وارد نگردیده است.",
229            ErrorCode::PhoneIncorrect => "تلفن به درستی وارد نگردیده است.",
230            ErrorCode::AddressNotEntered => "آدرس شما وارد نگردیده است.",
231            ErrorCode::MobileNotEntered => "شماره موبایل را وارد نکرده اید.",
232            ErrorCode::MobileIncorrect => "شماره موبایل به نادرستی وارد گردیده است.",
233            ErrorCode::AccessLevelIncorrect => "سطح دسترسی به نادرستی وارد گردیده است.",
234            ErrorCode::PasswordNotEntered => "کلمه عبور وارد نشده است.",
235            ErrorCode::FutureBulkCanceled => "ارسال در آینده برای کد بالک ارسالی لغو شد.",
236            ErrorCode::BulkCodeInvalid => "کد بالک ارسالی نامعتبر است.",
237            ErrorCode::TicketCodeInvalid => "کد تیکت نامعتبر است.",
238            ErrorCode::NoAgencyAccess => "شما دسترسی نمایندگی ندارید.",
239            ErrorCode::UsernameOrPasswordIncorrect => "نام کاربری یا کلمه عبور نادرست می باشد.",
240            ErrorCode::AccessInvalid => "دسترسی نامعتبر می باشد.",
241            ErrorCode::PatternInvalid => "پترن ارسالی نامعتبر است.",
242            ErrorCode::PatternParamsInvalid => "پارامتر های ارسالی برای پترن نامعتبر است.",
243            ErrorCode::PatternRecipientInvalid => "دریافت کننده برای ارسال پترن نامعتبر می باشد.",
244            ErrorCode::SendTimeInvalid => "ارسال پیام از ساعت 8 تا 23 می باشد.",
245            ErrorCode::PhonebookNotArray => "دفترچه تلفن باید یک آرایه باشد",
246            ErrorCode::NeedBankCardImage => "لطفا تصویری از کارت بانکی خود را از منو مدارک ارسال کنید",
247            ErrorCode::NeedBankCardNumber => "جهت ارسال با خطوط اشتراکی سامانه، لطفا شماره کارت بانکی خود را به دلیل تکمیل فرایند احراز هویت از بخش ارسال مدارک ثبت نمایید.",
248            ErrorCode::PatternNotActive => "پترن فعال نیست.",
249            ErrorCode::PatternNotAllowed => "شما اجازه ارسال از این پترن را ندارید.",
250            ErrorCode::NationalIdOrCardNotApproved => "کارت ملی یا کارت بانکی شما تایید نشده است.",
251            ErrorCode::UsernameFormatInvalid => "فرمت نام کاربری درست نمی باشد،حداقل ۵ کاراکتر(فقط حروف و اعداد)",
252            ErrorCode::PasswordTooSimple => "گذرواژه خیلی ساده می باشد.",
253            ErrorCode::RegistrationError | ErrorCode::RegistrationError2 | ErrorCode::RegistrationError3 => "مشکل در ثبت، با پشتیبانی تماس بگیرید.",
254            ErrorCode::Unknown => "خطای ناشناخته",
255        }
256    }
257}
258
259impl fmt::Display for ErrorCode {
260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261        write!(f, "{}", self.english_message())
262    }
263}
264
265/// Represents an error returned by the IPPanel API or client.
266///
267/// Contains the error message and the error code as an `ErrorCode` enum.
268#[derive(Debug)]
269pub struct IppanelError {
270    pub message: String,
271    pub code: ErrorCode,
272}
273
274impl fmt::Display for IppanelError {
275    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276        write!(f, "IppanelError(code: {}, message: {})", self.code.code(), self.message)
277    }
278}
279
280impl std::error::Error for IppanelError {}
281
282impl IppanelError {
283    pub fn new(message: impl Into<String>, code: i32) -> Self {
284        Self { message: message.into(), code: ErrorCode::from_i32(code) }
285    }
286
287    pub fn unwrap(&self) -> &str {
288        &self.message
289    }
290
291    pub fn code(&self) -> ErrorCode {
292        self.code
293    }
294
295    pub fn parse_api_error(response: &serde_json::Value) -> Option<IppanelError> {
296        if let Some(data) = response.get("data") {
297            if let Some(error) = data.get("error") {
298                let code = response.get("code").and_then(|c| c.as_i64()).unwrap_or(0) as i32;
299                return Some(IppanelError::new(error.to_string(), code));
300            }
301        }
302        None
303    }
304
305    pub fn to_persian_message(&self) -> &'static str {
306        self.code.persian_message()
307    }
308    pub fn to_english_message(&self) -> &'static str {
309        self.code.english_message()
310    }
311}