├── voipms ├── entities │ ├── __init__.py │ ├── general.py │ ├── lnp.py │ ├── clients.py │ ├── calls.py │ ├── accounts.py │ ├── voicemail.py │ ├── faxunconnect.py │ ├── didsunconnect.py │ ├── fax.py │ ├── didsremove.py │ ├── accountsadd.py │ ├── dids.py │ ├── clientsassign.py │ ├── faxcancel.py │ ├── faxmail.py │ ├── accountsdelete.py │ ├── callssend.py │ ├── faxmove.py │ ├── faxsearch.py │ ├── callsdelete.py │ ├── voicemailmove.py │ ├── voicemailsend.py │ ├── faxdelete.py │ ├── voicemaildelete.py │ ├── faxconnect.py │ ├── didscancel.py │ ├── faxsend.py │ ├── didsconnect.py │ ├── callsset.py │ ├── didssend.py │ ├── voicemailmark.py │ ├── faxorder.py │ ├── lnpget.py │ ├── clientsget.py │ ├── didssearch.py │ ├── voicemailset.py │ ├── voicemailcreate.py │ ├── voicemailget.py │ ├── didsback_order.py │ ├── clientsadd.py │ ├── faxget.py │ ├── accountsset.py │ ├── accountscreate.py │ ├── generalget.py │ └── accountsget.py ├── baseapi.py ├── voipmsclient.py └── __init__.py ├── setup.cfg ├── pytest.ini ├── Makefile ├── Pipfile ├── tests ├── test_accountsget.py ├── test_generalget.py └── test_didsget.py ├── LICENSE ├── .gitignore └── setup.py /voipms/entities/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal = 1 -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = -p no:warnings --doctest-modules 3 | doctest_optionflags= NORMALIZE_WHITESPACE ELLIPSIS -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build 2 | 3 | init: 4 | pipenv install --dev 5 | 6 | clean: 7 | rm -r dist/* 8 | 9 | build: 10 | pipenv run python -m build 11 | 12 | test: 13 | pipenv run pytest tests/ 14 | 15 | deploy: 16 | TWINE_USERNAME=__token__ pipenv run python -m twine upload --repository pypi dist/* 17 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | voipms = {editable = true, path = "."} 8 | 9 | [dev-packages] 10 | pytest = "*" 11 | autopep8 = "*" 12 | build = "*" 13 | twine = "*" 14 | 15 | [requires] 16 | python_version = "3.7" 17 | -------------------------------------------------------------------------------- /tests/test_accountsget.py: -------------------------------------------------------------------------------- 1 | import os 2 | from voipms import VoipMs 3 | 4 | 5 | class TestAccountsGet: 6 | client = VoipMs(os.environ["VOIPMS_USERNAME"], 7 | os.environ["VOIPMS_PASSWORD"]) 8 | 9 | def test_sub_accounts(self): 10 | result = self.client.accounts.get.sub_accounts() 11 | assert result["status"] == "success" 12 | assert "accounts" in result 13 | assert len(result["accounts"]) > 0 14 | -------------------------------------------------------------------------------- /voipms/baseapi.py: -------------------------------------------------------------------------------- 1 | class BaseApi(object): 2 | """ 3 | Simple class to buid path for entities 4 | """ 5 | def __init__(self, voipms_client): 6 | """ 7 | Initialize the class with your voip_user and voip_api_password 8 | 9 | :param mc_client: The mailchimp client connection 10 | :type mc_client: :mod:`voipms.voipmsclient.VoipMsClient` 11 | """ 12 | super(BaseApi, self).__init__() 13 | self._voipms_client = voipms_client 14 | -------------------------------------------------------------------------------- /voipms/entities/general.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The General API endpoint 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.entities.generalget import GeneralGet 9 | 10 | 11 | class General(BaseApi): 12 | def __init__(self, *args, **kwargs): 13 | """ 14 | Initialize the endpoint 15 | """ 16 | super(General, self).__init__(*args, **kwargs) 17 | self.endoint = 'general' 18 | self.get = GeneralGet(self) 19 | -------------------------------------------------------------------------------- /tests/test_generalget.py: -------------------------------------------------------------------------------- 1 | import os 2 | from voipms import VoipMs 3 | 4 | 5 | class TestGeneralGet: 6 | client = VoipMs(os.environ["VOIPMS_USERNAME"], 7 | os.environ["VOIPMS_PASSWORD"]) 8 | 9 | def test_servers_info(self): 10 | result = self.client.general.get.servers_info() 11 | assert result["status"] == "success" 12 | assert "servers" in result 13 | assert len(result["servers"]) > 0 14 | assert "San Jose-2" in [s["server_shortname"] 15 | for s in result["servers"]] 16 | -------------------------------------------------------------------------------- /voipms/entities/lnp.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Local Number Portability (LNP) API endpoint 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.entities.lnpadd import LNPAdd 9 | from voipms.entities.lnpget import LNPGet 10 | 11 | 12 | class LNP(BaseApi): 13 | def __init__(self, *args, **kwargs): 14 | """ 15 | Initialize the endpoint 16 | """ 17 | super(LNP, self).__init__(*args, **kwargs) 18 | self.endoint = 'lnp' 19 | self.add = LNPAdd(self) 20 | self.get = LNPGet(self) 21 | -------------------------------------------------------------------------------- /voipms/entities/clients.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Clients API endpoint 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.entities.clientsadd import ClientsAdd 9 | from voipms.entities.clientsget import ClientsGet 10 | from voipms.entities.clientsset import ClientsSet 11 | 12 | 13 | class Clients(BaseApi): 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(Clients, self).__init__(*args, **kwargs) 19 | self.endoint = 'clients' 20 | self.add = ClientsAdd(self) 21 | self.get = ClientsGet(self) 22 | self.set = ClientsSet(self) 23 | -------------------------------------------------------------------------------- /voipms/entities/calls.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Calls API endpoint 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.entities.callsdelete import CallsDelete 9 | from voipms.entities.callsget import CallsGet 10 | from voipms.entities.callssend import CallsSend 11 | from voipms.entities.callsset import CallsSet 12 | 13 | 14 | class Calls(BaseApi): 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(Calls, self).__init__(*args, **kwargs) 20 | self.endoint = 'calls' 21 | self.delete = CallsDelete(self) 22 | self.get = CallsGet(self) 23 | self.send = CallsSend(self) 24 | self.set = CallsSet(self) 25 | -------------------------------------------------------------------------------- /voipms/entities/accounts.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Accounts API endpoint 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.entities.accountsadd import AccountsAdd 9 | from voipms.entities.accountscreate import AccountsCreate 10 | from voipms.entities.accountsdelete import AccountsDelete 11 | from voipms.entities.accountsget import AccountsGet 12 | from voipms.entities.accountsset import AccountsSet 13 | 14 | 15 | class Accounts(BaseApi): 16 | def __init__(self, *args, **kwargs): 17 | """ 18 | Initialize the endpoint 19 | """ 20 | super(Accounts, self).__init__(*args, **kwargs) 21 | self.endoint = 'accounts' 22 | self.add = AccountsAdd(self) 23 | self.create = AccountsCreate(self) 24 | self.delete = AccountsDelete(self) 25 | self.get = AccountsGet(self) 26 | self.set = AccountsSet(self) 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 maxebert 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /voipms/entities/voicemail.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The General API endpoint 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.entities.voicemailcreate import VoicemailCreate 9 | from voipms.entities.voicemaildelete import VoicemailDelete 10 | from voipms.entities.voicemailget import VoicemailGet 11 | from voipms.entities.voicemailmark import VoicemailMark 12 | from voipms.entities.voicemailmove import VoicemailMove 13 | from voipms.entities.voicemailsend import VoicemailSend 14 | from voipms.entities.voicemailset import VoicemailSet 15 | 16 | 17 | class Voicemail(BaseApi): 18 | def __init__(self, *args, **kwargs): 19 | """ 20 | Initialize the endpoint 21 | """ 22 | super(Voicemail, self).__init__(*args, **kwargs) 23 | self.endoint = 'voicemail' 24 | self.create = VoicemailCreate(self) 25 | self.delete = VoicemailDelete(self) 26 | self.get = VoicemailGet(self) 27 | self.mark = VoicemailMark(self) 28 | self.move = VoicemailMove(self) 29 | self.send = VoicemailSend(self) 30 | self.set = VoicemailSet(self) 31 | -------------------------------------------------------------------------------- /voipms/entities/faxunconnect.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Fax API endpoint unconnect 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class FaxUnconnect(BaseApi): 11 | """ 12 | Unconnect for the Fax endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(FaxUnconnect, self).__init__(*args, **kwargs) 19 | self.endpoint = 'fax' 20 | 21 | def fax(self, fax): 22 | """ 23 | Updates a specific FAX DID from Reseller Client Sub Account 24 | 25 | :param did: [Required] FAX DID to be Unconnected from Reseller Sub Account(Example: 5551234567) 26 | :type did: :py:class:`int` 27 | 28 | :returns: :py:class:`dict` 29 | """ 30 | method = "unconnectFAX" 31 | 32 | if not isinstance(did, int): 33 | raise ValueError("[Required] FAX DID to be Unconnected from Reseller Sub Account(Example: 5551234567)") 34 | 35 | parameters = { 36 | "did": did, 37 | } 38 | 39 | return self._voipms_client._get(method, parameters) 40 | -------------------------------------------------------------------------------- /voipms/entities/didsunconnect.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Dids API endpoint unconnect 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class DidsUnconnect(BaseApi): 11 | """ 12 | Unconnect for the Dids endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(DidsUnconnect, self).__init__(*args, **kwargs) 19 | self.endpoint = 'dids' 20 | 21 | def did(self, did): 22 | """ 23 | Updates a specific Time Condition if a time condition code is provided 24 | 25 | - Adds a new Time Condition entry if no time condition code is provided 26 | 27 | :param did: [Required] DID to be Unconnected from Reseller Sub Account(Example: 5551234567) 28 | :type did: :py:class:`str` 29 | 30 | :returns: :py:class:`dict` 31 | """ 32 | method = "unconnectDID" 33 | 34 | if not isinstance(did, int): 35 | raise ValueError("DID to be Unconnected from Reseller Sub Account needs to be an int (Example: 5551234567)") 36 | 37 | parameters = { 38 | "did": did, 39 | } 40 | 41 | return self._voipms_client._get(method, parameters) 42 | -------------------------------------------------------------------------------- /voipms/entities/fax.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Fax API endpoint 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.entities.faxcancel import FaxCancel 9 | from voipms.entities.faxconnect import FaxConnect 10 | from voipms.entities.faxdelete import FaxDelete 11 | from voipms.entities.faxget import FaxGet 12 | from voipms.entities.faxmail import FaxMail 13 | from voipms.entities.faxmove import FaxMove 14 | from voipms.entities.faxorder import FaxOrder 15 | from voipms.entities.faxsearch import FaxSearch 16 | from voipms.entities.faxsend import FaxSend 17 | from voipms.entities.faxset import FaxSet 18 | from voipms.entities.faxunconnect import FaxUnconnect 19 | 20 | 21 | class Fax(BaseApi): 22 | def __init__(self, *args, **kwargs): 23 | """ 24 | Initialize the endpoint 25 | """ 26 | super(Fax, self).__init__(*args, **kwargs) 27 | self.endoint = 'fax' 28 | self.cancel = FaxCancel(self) 29 | self.connect = FaxConnect(self) 30 | self.delete = FaxDelete(self) 31 | self.get = FaxGet(self) 32 | self.mail = FaxMail(self) 33 | self.move = FaxMove(self) 34 | self.order = FaxOrder(self) 35 | self.search = FaxSearch(self) 36 | self.send = FaxSend(self) 37 | self.set = FaxSet(self) 38 | self.unconnect = FaxUnconnect(self) 39 | -------------------------------------------------------------------------------- /voipms/entities/didsremove.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Dids API endpoint remove 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class DidsRemove(BaseApi): 11 | """ 12 | Remove for the Dids endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(DidsRemove, self).__init__(*args, **kwargs) 19 | self.endpoint = 'dids' 20 | 21 | def did_vpri(self, did, vpri=None): 22 | """ 23 | Removes a DID from a VPRI 24 | 25 | :param vpri: Id for specific Vpri 26 | :type vpri: :py:class:`int` 27 | :param did: [Required] DID Number to be remove from our Vpri (Example: 561115) 28 | :type did: :py:class:`int` 29 | 30 | :returns: :py:class:`dict` 31 | """ 32 | method = "removeDIDvPRI" 33 | 34 | parameters = {} 35 | if vpri: 36 | if not isinstance(callback, int): 37 | raise ValueError("ID for a specific Callback needs to be an int (Example: 19183)") 38 | parameters["vpri"] = vpri 39 | if not isinstance(callback, int): 40 | raise ValueError("ID for a specific Callback needs to be an int (Example: 19183)") 41 | parameters["did"] = did 42 | 43 | return self._voipms_client._get(method, parameters) 44 | -------------------------------------------------------------------------------- /voipms/entities/accountsadd.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Accounts API endpoint add 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class AccountsAdd(BaseApi): 11 | """ 12 | Add for the Accounts endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(AccountsAdd, self).__init__(*args, **kwargs) 19 | self.endpoint = 'accounts' 20 | 21 | def member_to_conference(self, member, conference): 22 | """ 23 | Add member to a Conference 24 | 25 | :param music_on_hold: [Required] Specific Member ID (Example: 6547) 26 | :type music_on_hold: :py:class:`int` 27 | :param music_on_hold: [Required] Specific Conference ID (Example: 234) 28 | :type music_on_hold: :py:class:`int` 29 | :returns: :py:class:`dict` 30 | """ 31 | method = "addMemberToConference" 32 | 33 | parameters = {} 34 | 35 | if not isinstance(member, str): 36 | raise ValueError("[Required] Specific Member ID (Example: 6547)") 37 | parameters["member"] = member 38 | 39 | if not isinstance(conference, str): 40 | raise ValueError("[Required] Specific Conference ID (Example: 234)") 41 | parameters["conference"] = conference 42 | 43 | return self._voipms_client._get(conference, parameters) 44 | -------------------------------------------------------------------------------- /voipms/entities/dids.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Dids API endpoint 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.entities.didsback_order import DidsBackOrder 9 | from voipms.entities.didscancel import DidsCancel 10 | from voipms.entities.didsconnect import DidsConnect 11 | from voipms.entities.didsdelete import DidsDelete 12 | from voipms.entities.didsget import DidsGet 13 | from voipms.entities.didsorder import DidsOrder 14 | from voipms.entities.didsremove import DidsRemove 15 | from voipms.entities.didssearch import DidsSearch 16 | from voipms.entities.didssend import DidsSend 17 | from voipms.entities.didsset import DidsSet 18 | from voipms.entities.didsunconnect import DidsUnconnect 19 | 20 | 21 | class Dids(BaseApi): 22 | def __init__(self, *args, **kwargs): 23 | """ 24 | Initialize the endpoint 25 | """ 26 | super(Dids, self).__init__(*args, **kwargs) 27 | self.endoint = 'dids' 28 | self.back_order = DidsBackOrder(self) 29 | self.cancel = DidsCancel(self) 30 | self.connect = DidsConnect(self) 31 | self.delete = DidsDelete(self) 32 | self.get = DidsGet(self) 33 | self.order = DidsOrder(self) 34 | self.remove = DidsRemove(self) 35 | self.search = DidsSearch(self) 36 | self.send = DidsSend(self) 37 | self.set = DidsSet(self) 38 | self.unconnect = DidsUnconnect(self) 39 | -------------------------------------------------------------------------------- /voipms/entities/clientsassign.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Clients API endpoint assign 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import convert_bool, validate_email 9 | 10 | 11 | class ClientsAssign(BaseApi): 12 | """ 13 | Assign for the Clients endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(ClientsAssign, self).__init__(*args, **kwargs) 20 | self.endpoint = 'clients' 21 | 22 | def did_vpri(self, did, vpri): 23 | """ 24 | Assigns a Per Minute DID to a VPRI (Flat Rate DIDs can't be assigned) 25 | 26 | :param did: [Required] DID Number to be assigned into our Vpri (Example: 561115) 27 | :type did: :py:class:`int` 28 | :param vpri: [Required] Id for specific Vpri 29 | :type vpri: :py:class:`int` 30 | :returns: :py:class:`dict` 31 | """ 32 | method = "assignDIDvPRI" 33 | 34 | if not isinstance(did, int): 35 | raise ValueError("[Required] DID Number to be assigned into our Vpri (Example: 561115)") 36 | 37 | if not isinstance(vpri, int): 38 | raise ValueError("[Required] Id for specific Vpri") 39 | 40 | parameters = { 41 | "did": did, 42 | "vpri": vpri, 43 | } 44 | 45 | return self._voipms_client._get(method, parameters) 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | voip.py 2 | .DS_Store 3 | .vscode 4 | 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | env/ 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *,cover 50 | .hypothesis/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | local_settings.py 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # IPython Notebook 74 | .ipynb_checkpoints 75 | 76 | # pyenv 77 | .python-version 78 | 79 | # celery beat schedule file 80 | celerybeat-schedule 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | venv/ 87 | ENV/ 88 | 89 | # Spyder project settings 90 | .spyderproject 91 | 92 | # Rope project settings 93 | .ropeproject 94 | -------------------------------------------------------------------------------- /voipms/entities/faxcancel.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Fax API endpoint cancel 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import convert_bool 9 | 10 | 11 | class FaxCancel(BaseApi): 12 | """ 13 | Cancel for the Fax endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(FaxCancel, self).__init__(*args, **kwargs) 20 | self.endpoint = 'fax' 21 | 22 | def fax_number(self, fax_id, test=None): 23 | """ 24 | Deletes a specific Fax Number from your Account 25 | 26 | :param fax_id: [Required] ID for a specific Fax Number (Example: 923) 27 | :type fax_id: :py:class:`int` 28 | 29 | :param test: Set to true if testing how cancel a Fax Number (True/False) 30 | :type test: :py:class:`bool` 31 | 32 | :returns: :py:class:`dict` 33 | """ 34 | method = "cancelFaxNumber" 35 | 36 | if not isinstance(fax_id, int): 37 | raise ValueError("ID for a specific Fax Number needs to be an int (Example: 923)") 38 | 39 | parameters = { 40 | "id": fax_id, 41 | } 42 | 43 | if test: 44 | if not isinstance(test, bool): 45 | raise ValueError("Set to true if testing how cancel a Fax Number needs to be a bool (True/False)") 46 | else: 47 | parameters["test"] = convert_bool(test) 48 | 49 | return self._voipms_client._get(method, parameters) 50 | -------------------------------------------------------------------------------- /voipms/entities/faxmail.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Fax API endpoint mail 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import validate_email 9 | 10 | 11 | class FaxMail(BaseApi): 12 | """ 13 | Mail for the Fax endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(FaxMail, self).__init__(*args, **kwargs) 20 | self.endpoint = 'fax' 21 | 22 | def fax_message_pdf(self, fax_id, email): 23 | """ 24 | Send a Fax Message attached as a PDF file to an email destination 25 | 26 | :param fax_id: [Required] ID of the Fax Message requested (Values from fax.get_fax_messages) 27 | :type fax_id: :py:class:`int` 28 | :param email: [Required] Destination email address (example: yourname@company.com) 29 | :type email: :py:class:`str` 30 | 31 | :returns: :py:class:`dict` 32 | """ 33 | method = "mailFaxMessagePDF" 34 | 35 | if not isinstance(fax_id, int): 36 | raise ValueError("ID of the Fax Message requested needs to be an int (Values from fax.get_fax_messages)") 37 | 38 | if not isinstance(email, str): 39 | raise ValueError("Destination email address needs to be a str(example: yourname@company.com)") 40 | elif not validate_email(email): 41 | raise ValueError("Destination email address is not a correct email syntax") 42 | 43 | parameters = { 44 | "id": fax_id, 45 | "email": email, 46 | } 47 | 48 | return self._voipms_client._get(method, parameters) 49 | -------------------------------------------------------------------------------- /voipms/entities/accountsdelete.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Accounts API endpoint delete 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class AccountsDelete(BaseApi): 11 | """ 12 | Delete for the Accounts endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(AccountsDelete, self).__init__(*args, **kwargs) 19 | self.endpoint = 'accounts' 20 | 21 | def music_on_hold(self, music_on_hold): 22 | """ 23 | Deletes a specific custom Music on Hold 24 | 25 | :param music_on_hold: [Required] Music on Hold Name (Values from getMusicOnHold) 26 | :type music_on_hold: :py:class:`str` 27 | :returns: :py:class:`dict` 28 | """ 29 | method = "delMusicOnHold" 30 | 31 | parameters = {} 32 | if not isinstance(music_on_hold, str): 33 | raise ValueError("[Required] Music on Hold Name (Values from getMusicOnHold)") 34 | parameters["music_on_hold"] = music_on_hold 35 | return self._voipms_client._get(method, parameters) 36 | 37 | def sub_account(self, account_id): 38 | """ 39 | Deletes a specific Sub Account from your Account 40 | 41 | :param account_id: [Required] ID for a specific Sub Account (Example: 99785) 42 | :type account_id: :py:class:`str` 43 | :returns: :py:class:`dict` 44 | """ 45 | method = "delSubAccount" 46 | 47 | parameters = {} 48 | if not isinstance(account_id, int): 49 | raise ValueError("ID for a specific Sub Account as int (Example: 99785) ") 50 | parameters["id"] = account_id 51 | return self._voipms_client._get(method, parameters) 52 | -------------------------------------------------------------------------------- /voipms/entities/callssend.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Calls API endpoint send 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from datetime import datetime 8 | 9 | from voipms.baseapi import BaseApi 10 | from voipms.helpers import validate_date, convert_bool 11 | 12 | 13 | class CallsSend(BaseApi): 14 | """ 15 | Send for the Calls endpoint. 16 | """ 17 | def __init__(self, *args, **kwargs): 18 | """ 19 | Initialize the endpoint 20 | """ 21 | super(CallsSend, self).__init__(*args, **kwargs) 22 | self.endpoint = 'calls' 23 | 24 | def recording_email(self, client=None): 25 | """ 26 | Send information and audio file to email account 27 | 28 | :param acount: [Required] Filter Call Recordings by Account (Values from getCallAccounts) 29 | :type acount: :py:class:`int` 30 | :param email: [Required] Email to send call recording 31 | :type email: :py:class:`str` 32 | :param callrecording: [Required] Call Recording (Values from getCallRecordings) 33 | :type callrecording: :py:class:`str` 34 | :returns: :py:class:`dict` 35 | """ 36 | method = "sendCallRecordingEmail" 37 | 38 | if not isinstance(account, int): 39 | raise ValueError("[Required] Filter Call Recordings by Account (Values from getCallAccounts)") 40 | 41 | if not isinstance(email, str): 42 | raise ValueError("[Required] Email to send call recording") 43 | 44 | if not isinstance(callrecording, str): 45 | raise ValueError("[Required] Call Recording (Values from getCallRecordings)") 46 | 47 | parameters = { 48 | "account": account, 49 | "email": email, 50 | "callrecording": callrecording, 51 | } 52 | return self._voipms_client._get(method, parameters) 53 | -------------------------------------------------------------------------------- /tests/test_didsget.py: -------------------------------------------------------------------------------- 1 | import os 2 | from voipms import VoipMs 3 | 4 | 5 | class TestDidsGet: 6 | client = VoipMs(os.environ["VOIPMS_USERNAME"], 7 | os.environ["VOIPMS_PASSWORD"]) 8 | 9 | def test_dids_can(self): 10 | rate_center = self.client.dids.get.rate_centers_can("BC")[ 11 | "ratecenters"][0] 12 | result = self.client.dids.get.dids_can("BC", rate_center["ratecenter"]) 13 | assert result["status"] == "success" 14 | assert "dids" in result 15 | assert len(result["dids"]) > 0 16 | 17 | def test_dids_info(self): 18 | result = self.client.dids.get.dids_info() 19 | assert result["status"] == "success" 20 | assert "dids" in result 21 | assert len(result["dids"]) > 0 22 | 23 | def test_dids_usa(self): 24 | rate_center = self.client.dids.get.rate_centers_usa("CO")[ 25 | "ratecenters"][0] 26 | result = self.client.dids.get.dids_usa("CO", rate_center["ratecenter"]) 27 | assert result["status"] == "success" 28 | assert "dids" in result 29 | assert len(result["dids"]) > 0 30 | 31 | def test_provinces(self): 32 | result = self.client.dids.get.provinces() 33 | assert result["status"] == "success" 34 | assert "provinces" in result 35 | assert len(result["provinces"]) == 13 36 | assert "AB" in [p["province"] for p in result["provinces"]] 37 | 38 | def test_recordings(self): 39 | result = self.client.dids.get.recordings() 40 | assert result["status"] == "success" 41 | assert "recordings" in result 42 | assert len(result["recordings"]) > 0 43 | 44 | def test_sip_uris(self): 45 | result = self.client.dids.get.sip_uris() 46 | assert result["status"] == "success" 47 | assert "sipuris" in result 48 | assert len(result["sipuris"]) > 0 49 | -------------------------------------------------------------------------------- /voipms/entities/faxmove.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Fax API endpoint move 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import convert_bool 9 | 10 | 11 | class FaxMove(BaseApi): 12 | """ 13 | Move for the Fax endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(FaxMove, self).__init__(*args, **kwargs) 20 | self.endpoint = 'fax' 21 | 22 | def fax_message(self, fax_id, folder_id, test=None): 23 | """ 24 | Moves a Fax Message to a different folder 25 | 26 | :param fax_id: [Required] ID of the Fax Message requested (Values from fax.get_fax_messages) 27 | :type fax_id: :py:class:`int` 28 | :param folder_id: [Required] ID of the destination Fax Folder (Values from fax.get_fax_folders) 29 | :type folder_id: :py:class:`int` 30 | 31 | :param test: Set to true if testing how cancel a Fax Folder (True/False) 32 | :type test: :py:class:`bool` 33 | 34 | :returns: :py:class:`dict` 35 | """ 36 | method = "moveFaxMessage" 37 | 38 | if not isinstance(fax_id, int): 39 | raise ValueError("ID for a specific \"Email To Fax Configuration\" needs to be an int (Example: 923)") 40 | if not isinstance(folder_id, int): 41 | raise ValueError("ID for a specific \"Email To Fax Configuration\" needs to be an int (Example: 923)") 42 | 43 | parameters = { 44 | "fax_id": fax_id, 45 | "folder_id": folder_id, 46 | } 47 | 48 | if test: 49 | if not isinstance(test, bool): 50 | raise ValueError("Set to true if testing how cancel a Fax Folder needs to be a bool (True/False)") 51 | else: 52 | parameters["test"] = convert_bool(test) 53 | 54 | return self._voipms_client._get(method, parameters) 55 | -------------------------------------------------------------------------------- /voipms/entities/faxsearch.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Fax API endpoint search 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class FaxSearch(BaseApi): 11 | """ 12 | Search for the Fax endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(FaxSearch, self).__init__(*args, **kwargs) 19 | self.endpoint = 'fax' 20 | 21 | def fax_area_code_can(self, area_code): 22 | """ 23 | Retrieves a list of Canadian Ratecenters searched by Area Code 24 | 25 | :param area_code: [Required] Area code number, as the initial of the Fax Number you looking for (values from fax.get_fax_rate_centers_can) 26 | :type area_code: :py:class:`int` 27 | 28 | :returns: :py:class:`dict` 29 | """ 30 | method = "searchFaxAreaCodeCAN" 31 | 32 | if not isinstance(area_code, int): 33 | raise ValueError("Area code number, as the initial of the Fax Number you looking for needs to be an int (values from fax.get_fax_rate_centers_can)") 34 | 35 | parameters = { 36 | "area_code": area_code, 37 | } 38 | 39 | return self._voipms_client._get(method, parameters) 40 | 41 | def fax_area_code_usa(self, area_code): 42 | """ 43 | Retrieves a list of USA Ratecenters searched by Area Code 44 | 45 | :param area_code: [Required] Area code number, as the initial of the Fax Number you looking for (values from fax.get_fax_rate_centers_usa) 46 | :type area_code: :py:class:`int` 47 | 48 | :returns: :py:class:`dict` 49 | """ 50 | method = "searchFaxAreaCodeUSA" 51 | 52 | if not isinstance(area_code, int): 53 | raise ValueError("Area code number, as the initial of the Fax Number you looking for needs to be an int (values from fax.get_fax_rate_centers_usa)") 54 | 55 | parameters = { 56 | "area_code": area_code, 57 | } 58 | 59 | return self._voipms_client._get(method, parameters) 60 | -------------------------------------------------------------------------------- /voipms/entities/callsdelete.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Calls API endpoint delete 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from datetime import datetime 8 | 9 | from voipms.baseapi import BaseApi 10 | from voipms.helpers import validate_date, convert_bool 11 | 12 | 13 | class CallsDelete(BaseApi): 14 | """ 15 | Delete for the Calls endpoint. 16 | """ 17 | def __init__(self, *args, **kwargs): 18 | """ 19 | Initialize the endpoint 20 | """ 21 | super(CallsDelete, self).__init__(*args, **kwargs) 22 | self.endpoint = 'calls' 23 | 24 | def recording(self, account, callrecording): 25 | """ 26 | Delete specific call recording, audio file and information related 27 | 28 | :param account: [Required] Filter Call Recordings by Account (Values from getCallAccounts) 29 | :type account: :py:class:`int` 30 | :param callrecording: [Required] Call Recording (Values from getCallRecordings) 31 | :type callrecording: :py:class:`str` 32 | :returns: :py:class:`dict` 33 | """ 34 | method = "delCallRecording" 35 | 36 | if not isinstance(account, int): 37 | raise ValueError("[Required] Filter Call Recordings by Account (Values from getCallAccounts)") 38 | 39 | if not isinstance(callrecording, str): 40 | raise ValueError("[Required] Call Recording (Values from getCallRecordings)") 41 | 42 | parameters = { 43 | "account": account, 44 | "callrecording": callrecording, 45 | } 46 | return self._voipms_client._get(method, parameters) 47 | 48 | def parking(self, callparking): 49 | """ 50 | Deletes a specific Call Parking entry from your Account 51 | 52 | :param callparking: ID for a specific Call Parking (Example: 323) 53 | :type callparking: :py:class:`int` 54 | :returns: :py:class:`dict` 55 | """ 56 | method = "delCallParking" 57 | 58 | if not isinstance(callparking, int): 59 | raise ValueError("ID for a specific Call Parking (Example: 323)") 60 | 61 | parameters = { 62 | "callparking": callparking, 63 | } 64 | return self._voipms_client._get(method, parameters) 65 | -------------------------------------------------------------------------------- /voipms/entities/voicemailmove.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Voicemail API endpoint move 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class VoicemailMove(BaseApi): 11 | """ 12 | Move for the Voicemail endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(VoicemailMove, self).__init__(*args, **kwargs) 19 | self.endpoint = 'voicemail' 20 | 21 | def folder_voicemail_message(self, mailbox, folder, message_num, new_folder): 22 | """ 23 | Move Voicemail Message to a Destination Folder 24 | 25 | :param mailbox: [Required] ID for a specific Mailbox (Example: 1001) 26 | :type mailbox: :py:class:`int` 27 | :param folder: [required] Name for specific Folder (Required if message id is passed, Example: 'INBOX', values from: voicemail.get_voicemail_folders) 28 | :type folder: :py:class:`str` 29 | :param message_num: [required] ID for specific Voicemail Message (Required if folder is passed, Example: 1) 30 | :type message_num: :py:class:`int` 31 | :param new_folder: [required] Destination Folder (Example: 'Urgent', values from: voicemail.get_voicemail_folders) 32 | :type new_folder: :py:class:`str` 33 | 34 | :returns: :py:class:`dict` 35 | """ 36 | method = "moveFolderVoicemailMessage" 37 | 38 | if not isinstance(mailbox, int): 39 | raise ValueError("ID for a specific Mailbox needs to be an int (Example: 1001)") 40 | 41 | if not isinstance(folder, str): 42 | raise ValueError("Name for specific Folder needs to be a str (Required if message id is passed, Example: 'INBOX', values from: voicemail.get_voicemail_folders)") 43 | 44 | if not isinstance(message_num, int): 45 | raise ValueError("ID for specific Voicemail Message needs to be an int (Required if folder is passed, Example: 1)") 46 | 47 | if not isinstance(new_folder, str): 48 | raise ValueError("Destination Folder needs to be a str (Example: 'Urgent', values from: voicemail.get_voicemail_folders)") 49 | 50 | parameters = { 51 | "mailbox": mailbox, 52 | "folder": folder, 53 | "message_num": message_num, 54 | "new_folder": new_folder, 55 | } 56 | 57 | return self._voipms_client._get(method, parameters) 58 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import re 4 | import codecs 5 | 6 | from setuptools import setup, find_packages 7 | 8 | ################################################################### 9 | 10 | PACKAGES = find_packages() 11 | META_PATH = os.path.join("voipms", "__init__.py") 12 | KEYWORDS = ["voip.ms", "voips", "api", "client", "wrapper"] 13 | CLASSIFIERS = [ 14 | 'Development Status :: 3 - Alpha', 15 | 'Intended Audience :: Developers', 16 | 'Topic :: Software Development :: Libraries :: Python Modules', 17 | 'License :: OSI Approved :: MIT License', 18 | 'Programming Language :: Python :: 2.7', 19 | 'Programming Language :: Python :: 3.4', 20 | 'Programming Language :: Python :: 3.5', 21 | 'Programming Language :: Python :: 3.6', 22 | 'Programming Language :: Python :: 3.7', 23 | ] 24 | INSTALL_REQUIRES = [ 25 | 'requests>=2.7.0', 26 | 'validators>=0.21.2', 27 | ] 28 | 29 | ################################################################### 30 | 31 | HERE = os.path.abspath(os.path.dirname(__file__)) 32 | 33 | 34 | def read(*parts): 35 | """ 36 | Build an absolute path from *parts* and and return the contents of the 37 | resulting file. Assume UTF-8 encoding. 38 | """ 39 | with codecs.open(os.path.join(HERE, *parts), "rb", "utf-8") as f: 40 | return f.read() 41 | 42 | 43 | META_FILE = read(META_PATH) 44 | 45 | 46 | def find_meta(meta): 47 | """ 48 | Extract __*meta*__ from META_FILE. 49 | """ 50 | meta_match = re.search( 51 | r"^__{meta}__ = ['\"]([^'\"]*)['\"]".format(meta=meta), 52 | META_FILE, re.M 53 | ) 54 | if meta_match: 55 | return meta_match.group(1) 56 | raise RuntimeError("Unable to find __{meta}__ string.".format(meta=meta)) 57 | 58 | 59 | if __name__ == "__main__": 60 | setup( 61 | name=find_meta("title"), 62 | description=find_meta("description"), 63 | license=find_meta("license"), 64 | url=find_meta("uri"), 65 | version=find_meta("version"), 66 | author=find_meta("author"), 67 | author_email=find_meta("email"), 68 | maintainer=find_meta("author"), 69 | maintainer_email=find_meta("email"), 70 | keywords=KEYWORDS, 71 | long_description=read("README.md"), 72 | long_description_content_type="text/markdown", 73 | packages=PACKAGES, 74 | zip_safe=False, 75 | classifiers=CLASSIFIERS, 76 | install_requires=INSTALL_REQUIRES, 77 | ) 78 | -------------------------------------------------------------------------------- /voipms/entities/voicemailsend.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Voicemail API endpoint send 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import validate_email 9 | 10 | 11 | class VoicemailSend(BaseApi): 12 | """ 13 | Send for the Voicemail endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(VoicemailSend, self).__init__(*args, **kwargs) 20 | self.endpoint = 'voicemail' 21 | 22 | def voicemail_email(self, mailbox, folder, message_num, email_address): 23 | """ 24 | Move Voicemail Message to a Destination Folder 25 | 26 | :param mailbox: [Required] ID for a specific Mailbox (Example: 1001) 27 | :type mailbox: :py:class:`int` 28 | :param folder: [required] Name for specific Folder (Required if message id is passed, Example: 'INBOX', values from: voicemail.get_voicemail_folders) 29 | :type folder: :py:class:`str` 30 | :param message_num: [required] ID for specific Voicemail Message (Required if folder is passed, Example: 1) 31 | :type message_num: :py:class:`int` 32 | :param email_address: [required] Destination Email address (Example: john.doe@my-domain.com) 33 | :type email_address: :py:class:`str` 34 | 35 | :returns: :py:class:`dict` 36 | """ 37 | method = "sendVoicemailEmail" 38 | 39 | if not isinstance(mailbox, int): 40 | raise ValueError("ID for a specific Mailbox needs to be an int (Example: 1001)") 41 | 42 | if not isinstance(folder, str): 43 | raise ValueError("Name for specific Folder needs to be a str (Required if message id is passed, Example: 'INBOX', values from: voicemail.get_voicemail_folders)") 44 | 45 | if not isinstance(message_num, int): 46 | raise ValueError("ID for specific Voicemail Message needs to be an int (Required if folder is passed, Example: 1)") 47 | 48 | if not isinstance(email_address, str): 49 | raise ValueError("Destination Email address needs to be a str (Example: john.doe@my-domain.com)") 50 | elif not validate_email(email_address): 51 | raise ValueError("Destination Email address is not a correct email syntax") 52 | 53 | parameters = { 54 | "mailbox": mailbox, 55 | "folder": folder, 56 | "message_num": message_num, 57 | "email_address": email_address, 58 | } 59 | 60 | return self._voipms_client._get(method, parameters) 61 | -------------------------------------------------------------------------------- /voipms/entities/faxdelete.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Fax API endpoint delete 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import convert_bool 9 | 10 | 11 | class FaxDelete(BaseApi): 12 | """ 13 | Delete for the Fax endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(FaxDelete, self).__init__(*args, **kwargs) 20 | self.endpoint = 'fax' 21 | 22 | def fax_message(self, fax_id, test=None): 23 | """ 24 | Deletes a specific Fax Message from your Account 25 | 26 | :param fax_id: [Required] ID for a specific Fax Number (Example: 923) 27 | :type fax_id: :py:class:`int` 28 | 29 | :param test: Set to true if testing how cancel a Fax Number (True/False) 30 | :type test: :py:class:`bool` 31 | 32 | :returns: :py:class:`dict` 33 | """ 34 | method = "deleteFaxMessage" 35 | 36 | if not isinstance(fax_id, int): 37 | raise ValueError("ID for a specific Fax Number needs to be an int (Example: 923)") 38 | 39 | parameters = { 40 | "id": fax_id, 41 | } 42 | 43 | if test: 44 | if not isinstance(test, bool): 45 | raise ValueError("Set to true if testing how cancel a Fax Number needs to be a bool (True/False)") 46 | else: 47 | parameters["test"] = convert_bool(test) 48 | 49 | return self._voipms_client._get(method, parameters) 50 | 51 | def email_to_fax(self, fax_id, test=None): 52 | """ 53 | Deletes a specific "Email to Fax configuration" from your Account 54 | 55 | :param fax_id: [Required] ID for a specific "Email To Fax Configuration" (Example: 923) 56 | :type fax_id: :py:class:`int` 57 | 58 | :param test: Set to true if testing how cancel a "Email To Fax Configuration" (True/False) 59 | :type test: :py:class:`bool` 60 | 61 | :returns: :py:class:`dict` 62 | """ 63 | method = "delEmailToFax" 64 | 65 | if not isinstance(fax_id, int): 66 | raise ValueError("ID for a specific \"Email To Fax Configuration\" needs to be an int (Example: 923)") 67 | 68 | parameters = { 69 | "id": fax_id, 70 | } 71 | 72 | if test: 73 | if not isinstance(test, bool): 74 | raise ValueError("Set to true if testing how cancel a \"Email To Fax Configuration\" needs to be a bool (True/False)") 75 | else: 76 | parameters["test"] = convert_bool(test) 77 | 78 | return self._voipms_client._get(method, parameters) 79 | 80 | def fax_folder(self, folder_id, test=None): 81 | """ 82 | Deletes a specific Fax Folder from your Account 83 | 84 | :param folder_id: [Required] ID for a specific Fax Folder (Example: 923) 85 | :type folder_id: :py:class:`int` 86 | 87 | :param test: Set to true if testing how cancel a Fax Folder (True/False) 88 | :type test: :py:class:`bool` 89 | 90 | :returns: :py:class:`dict` 91 | """ 92 | method = "delFaxFolder" 93 | 94 | if not isinstance(folder_id, int): 95 | raise ValueError("ID for a specific Fax Folder needs to be an int (Example: 923)") 96 | 97 | parameters = { 98 | "id": folder_id, 99 | } 100 | 101 | if test: 102 | if not isinstance(test, bool): 103 | raise ValueError("Set to true if testing how cancel a Fax Folder needs to be a bool (True/False)") 104 | else: 105 | parameters["test"] = convert_bool(test) 106 | 107 | return self._voipms_client._get(method, parameters) 108 | -------------------------------------------------------------------------------- /voipms/voipmsclient.py: -------------------------------------------------------------------------------- 1 | import requests, json 2 | 3 | # Handle library reorganisation Python 2 > Python 3. 4 | try: 5 | from urllib.parse import urlencode 6 | except ImportError: 7 | from urllib import urlencode 8 | 9 | from .helpers import ERROR_CODES 10 | 11 | 12 | class VoipMsClient(object): 13 | """ 14 | Voip.ms class to communicate with the v1 REST API 15 | """ 16 | def __init__(self, voip_user, voip_api_password): 17 | """ 18 | Initialize the class with you voip_user and voip_api_password. 19 | 20 | :param voip_user: voip.ms user id (email) 21 | :type voip_user: :py:class:`str` 22 | :param voip_api_password: voip.ms API Password 23 | :type voip_api_password: :py:class:`str` 24 | """ 25 | super(VoipMsClient, self).__init__() 26 | self.base_url = 'https://voip.ms/api/v1/rest.php?api_username={}&api_password={}&'.format(voip_user, voip_api_password) 27 | self.post_url = 'https://voip.ms/api/v1/rest.php' 28 | self.voip_user = voip_user 29 | self.voip_api_password = voip_api_password 30 | 31 | def _error_code(self, status): 32 | """ 33 | Verify if query responded with error 34 | 35 | :param status: status from the voip.ms API 36 | :type voip_user: :py:class:`str` 37 | :returns: True 38 | """ 39 | if status in ERROR_CODES: 40 | raise TypeError(ERROR_CODES[status]) 41 | return None 42 | 43 | def _get(self, method, parameters=None): 44 | """ 45 | Handle authenticated GET requests 46 | 47 | :param method: The method call for the API 48 | :type method: :py:class:`str` 49 | :param parameters: The query string parameters 50 | :type parameters: :py:class:`str` 51 | :returns: The JSON output from the API 52 | """ 53 | 54 | # The `method` param can be passed in as a tuple containing both 55 | # params - unpack in that case. 56 | if isinstance(method, tuple): 57 | method, parameters = method 58 | 59 | query_set = { 60 | "method": method 61 | } 62 | if parameters: 63 | query_set.update(parameters) 64 | url = self.base_url + urlencode(query_set, safe='@:').replace('%2F', '/').replace('%3A', ':').replace('%0D%0A', '+').replace('%0A', '+').replace('%21', '+') 65 | 66 | try: 67 | r = requests.get(url) 68 | except requests.exceptions.RequestException as e: 69 | raise e 70 | else: 71 | r.raise_for_status() 72 | if r.status_code == 204: 73 | return None 74 | r_json = r.json() 75 | status = r_json["status"] 76 | if status != "success": 77 | self._error_code(status) 78 | return r_json 79 | 80 | def _post(self, method, parameters=None): 81 | """ 82 | Handle authenticated POST requests 83 | 84 | :param method: The method call for the API 85 | :type method: :py:class:`str` 86 | :param parameters: The POST parameters 87 | :type parameters: :py:class:`str` 88 | :returns: The JSON output from the API 89 | """ 90 | url = self.post_url 91 | headers = { 92 | 'api_username' : self.voip_user, 93 | 'api_password' : self.voip_api_password, 94 | "method" : method 95 | } 96 | parameters.update(headers) 97 | 98 | try: 99 | r = requests.post(url, data=parameters) 100 | except requests.exceptions.RequestException as e: 101 | raise e 102 | else: 103 | r.raise_for_status() 104 | if r.status_code == 204: 105 | return None 106 | r_json = r.json() 107 | status = r_json["status"] 108 | if status != "success": 109 | self._error_code(status) 110 | return r_json 111 | -------------------------------------------------------------------------------- /voipms/entities/voicemaildelete.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Voicemail API endpoint delete 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class VoicemailDelete(BaseApi): 11 | """ 12 | Delete for the Voicemail endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(VoicemailDelete, self).__init__(*args, **kwargs) 19 | self.endpoint = 'voicemail' 20 | 21 | def member_from_conference(self, member, conference=None): 22 | """ 23 | Removes a member profile from a specific Conference from your Account 24 | 25 | :param member: [Required] ID for a specific Member (Example: 101) 26 | :type member: :py:class:`int` 27 | :param conference: ID for a specific Conference (Example: 3829) 28 | :type conference: :py:class:`int` 29 | 30 | :returns: :py:class:`dict` 31 | """ 32 | method = "delMemberFromConference" 33 | 34 | if not isinstance(member, int): 35 | raise ValueError("[Required] ID for a specific Member (Example: 101)") 36 | parameters = { 37 | "member": member, 38 | } 39 | 40 | if conference: 41 | if not isinstance(conference, int): 42 | raise ValueError("ID for a specific Conference (Example: 3829)") 43 | parameters["conference"] = conference 44 | 45 | return self._voipms_client._get(method, parameters) 46 | 47 | def messages(self, mailbox, **kwargs): 48 | """ 49 | Deletes all messages in all servers from a specific Voicemail from your Account 50 | 51 | :param mailbox: [Required] ID for a specific Mailbox (Example: 1001) 52 | :type mailbox: :py:class:`int` 53 | 54 | :param folder: Name for specific Folder (Required if message id is passed, Example: 'INBOX', values from: voicemail.get_voicemail_folders) 55 | :type folder: :py:class:`str` 56 | :param message_num: ID for specific Voicemail Message (Required if folder is passed, Example: 1) 57 | :type message_num: :py:class:`int` 58 | 59 | :returns: :py:class:`dict` 60 | """ 61 | method = "delMessages" 62 | 63 | if not isinstance(mailbox, int): 64 | raise ValueError("ID for a specific Mailbox needs to be an int (Example: 1001)") 65 | 66 | parameters = { 67 | "mailbox": mailbox, 68 | } 69 | 70 | if "folder" in kwargs: 71 | if not isinstance(kwargs["folder"], str): 72 | raise ValueError("Name for specific Folder needs to be a str (Required if message id is passed, Example: 'INBOX', values from: voicemail.get_voicemail_folders)") 73 | parameters["folder"] = kwargs.pop("folder") 74 | 75 | if "message_num" in kwargs: 76 | if not isinstance(kwargs["message_num"], int): 77 | raise ValueError("ID for specific Voicemail Message needs to be an int (Required if folder is passed, Example: 1)") 78 | parameters["message_num"] = kwargs.pop("message_num") 79 | 80 | if len(kwargs) > 0: 81 | not_allowed_parameters = "" 82 | for key, value in kwargs.items(): 83 | not_allowed_parameters += key + " " 84 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 85 | 86 | return self._voipms_client._get(method, parameters) 87 | 88 | def voicemail(self, mailbox): 89 | """ 90 | Deletes a specific Voicemail from your Account 91 | 92 | :param mailbox: [Required] ID for a specific Mailbox (Example: 1001) 93 | :type mailbox: :py:class:`int` 94 | 95 | :returns: :py:class:`dict` 96 | """ 97 | method = "delVoicemail" 98 | 99 | if not isinstance(mailbox, int): 100 | raise ValueError("ID for a specific Mailbox needs to be an int (Example: 1001)") 101 | 102 | parameters = { 103 | "mailbox": mailbox, 104 | } 105 | 106 | return self._voipms_client._get(method, parameters) 107 | -------------------------------------------------------------------------------- /voipms/entities/faxconnect.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Fax API endpoint connect 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import validate_date, convert_bool 9 | 10 | 11 | class FaxConnect(BaseApi): 12 | """ 13 | Connect for the Fax endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(FaxConnect, self).__init__(*args, **kwargs) 20 | self.endpoint = 'fax' 21 | 22 | def connect_fax(self, fax, account, monthly, setup, minute, **kwargs): 23 | """ 24 | Connects a specific FAX DID to a specific Reseller Client Sub Account 25 | 26 | :param fax: [Required] FAX DID to be Connected to Reseller Sub Account (Example: 5551234567) 27 | :type fax: :py:class:`str` or `int` 28 | :param account: [Required] Reseller Sub Account (Example: '100001_VoIP') 29 | :type account: :py:class:`str` 30 | :param monthly: [Required] Montly Fee for Reseller Client (Example: 3.50) 31 | :type monthly: :py:class:`float` 32 | :param setup: [Required] Setup Fee for Reseller Client (Example: 1.99) 33 | :type setup: :py:class:`float` 34 | :param minute: [Required] Minute Rate for Reseller Client (Example: 0.03) 35 | :type minute: :py:class:`float` 36 | :param **kwargs: All optional parameters 37 | :type **kwargs: :py:class:`dict` 38 | 39 | :param next_billing: Next billing date (Example: '2014-03-30') 40 | :type next_billing: :py:class:`str` 41 | :param dont_charge_setup: If set to true, the setup value will not be charged after Connect 42 | :type dont_charge_setup: :py:class:`bool` 43 | :param dont_charge_monthly: If set to true, the monthly value will not be charged after Connect 44 | :type dont_charge_monthly: :py:class:`bool` 45 | 46 | :returns: :py:class:`dict` 47 | """ 48 | method = "connectFAX" 49 | 50 | if not isinstance(fax, int): 51 | raise ValueError("FAX to be canceled and deleted needs to be an int (Example: 5551234567)") 52 | 53 | if not isinstance(account, str): 54 | raise ValueError("Reseller Sub Account needs to be a str (Example: '100001_VoIP')") 55 | 56 | if not isinstance(monthly, float): 57 | raise ValueError("Montly Fee for Reseller Client needs to be a float (Example: 3.50)") 58 | 59 | if not isinstance(setup, float): 60 | raise ValueError("Setup Fee for Reseller Client needs to be a float (Example: 1.99)") 61 | 62 | if not isinstance(minute, float): 63 | raise ValueError("Minute Rate for Reseller Client needs to be a float (Example: 0.03)") 64 | 65 | parameters = { 66 | "fax": fax, 67 | "account": account, 68 | "monthly": monthly, 69 | "setup": setup, 70 | "minute": minute, 71 | } 72 | 73 | if "next_billing" in kwargs: 74 | if not isinstance(kwargs["next_billing"], str): 75 | raise ValueError("Next billing date needs to be a str (Example: '2014-03-30')") 76 | validate_date(kwargs["next_billing"]) 77 | parameters["next_billing"] = kwargs.pop("next_billing") 78 | 79 | if "dont_charge_setup" in kwargs: 80 | if not isinstance(kwargs["dont_charge_setup"], bool): 81 | raise ValueError("If set to True, the setup value will not be charged after Connect (needs to be bool)") 82 | parameters["dont_charge_setup"] = convert_bool(kwargs.pop("dont_charge_setup")) 83 | 84 | if "dont_charge_monthly" in kwargs: 85 | if not isinstance(kwargs["dont_charge_monthly"], bool): 86 | raise ValueError("If set to True, the monthly value will not be charged after Connect (needs to be bool)") 87 | parameters["dont_charge_monthly"] = convert_bool(kwargs.pop("dont_charge_monthly")) 88 | 89 | if len(kwargs) > 0: 90 | not_allowed_parameters = "" 91 | for key, value in kwargs.items(): 92 | not_allowed_parameters += key + " " 93 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 94 | 95 | return self._voipms_client._get(method, parameters) 96 | -------------------------------------------------------------------------------- /voipms/entities/didscancel.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Dids API endpoint cancel 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import convert_bool 9 | 10 | 11 | class DidsCancel(BaseApi): 12 | """ 13 | Cancel for the Dids endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(DidsCancel, self).__init__(*args, **kwargs) 20 | self.endpoint = 'dids' 21 | 22 | def did(self, did, **kwargs): 23 | """ 24 | Deletes a specific DID from your Account 25 | 26 | :param did: [Required] DID to be canceled and deleted (Example: 5551234567) 27 | :type did: :py:class:`str` or `int` 28 | :param **kwargs: All optional parameters 29 | :type **kwargs: :py:class:`dict` 30 | 31 | :param cancelcomment: Comment for DID cancellation 32 | :type cancelcomment: :py:class:`str` 33 | :param portout: Set to True if the DID is being ported out 34 | :type portout: :py:class:`bool` 35 | :param test: Set to True if testing how cancellation works 36 | - Cancellation can not be undone 37 | - When testing, no changes are made 38 | :type test: :py:class:`bool` 39 | 40 | :returns: :py:class:`dict` 41 | 42 | routing, failover_busy, failover_unreachable and failover_noanswer 43 | can receive values in the following format => header:record_id 44 | Where header could be: account, fwd, vm, sip, grp, ivr, sys, recording, queue, cb, tc, disa, none. 45 | Examples: 46 | 47 | account Used for routing calls to Sub Accounts 48 | You can get all sub accounts using the accounts.get.sub_accounts function 49 | 50 | fwd Used for routing calls to Forwarding entries. 51 | You can get the ID right after creating a Forwarding with dids.set.forwarding 52 | or by requesting all forwardings entries with getForwardings. 53 | 54 | vm Used for routing calls to a Voicemail. 55 | You can get all voicemails and their IDs using the voicemail.get.voicemails function 56 | 57 | sys System Options: 58 | hangup = Hangup the Call 59 | busy = Busy tone 60 | noservice = System Recording: Number not in service 61 | disconnected = System Recording: Number has been disconnected 62 | dtmf = DTMF Test 63 | echo = ECHO Test 64 | 65 | 66 | none Used to route calls to no action 67 | 68 | Examples: 69 | 'account:100001_VoIP' 70 | 'fwd:1026' 71 | 'vm:101' 72 | 'none:' 73 | 'sys:echo' 74 | """ 75 | method = "cancelDID" 76 | 77 | if isinstance(did, str): 78 | did = did.replace('.', '') 79 | try: 80 | did = int(did) 81 | except: 82 | raise ValueError("DID to be canceled and deleted needs to be an int or str of numbers (Example: 555.123.4567 or 5551234567)") 83 | if not isinstance(did, int): 84 | raise ValueError("DID to be canceled and deleted needs to be an int (Example: 5551234567)") 85 | parameters = { 86 | "did": did 87 | } 88 | 89 | if "portout" in kwargs: 90 | if not isinstance(kwargs["portout"], bool): 91 | raise ValueError("Set to True if the DID is being ported out") 92 | parameters["portout"] = convert_bool(kwargs.pop("portout")) 93 | 94 | if "test" in kwargs: 95 | if not isinstance(kwargs["test"], bool): 96 | raise ValueError("Set to True if testing how cancellation works") 97 | parameters["test"] = convert_bool(kwargs.pop("test")) 98 | 99 | if len(kwargs) > 0: 100 | not_allowed_parameters = "" 101 | for key, value in kwargs.items(): 102 | not_allowed_parameters += key + " " 103 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 104 | 105 | return self._voipms_client._get(method, parameters) 106 | -------------------------------------------------------------------------------- /voipms/entities/faxsend.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Fax API endpoint send 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import validate_email, convert_bool 9 | 10 | 11 | class FaxSend(BaseApi): 12 | """ 13 | Send for the Fax endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(FaxSend, self).__init__(*args, **kwargs) 20 | self.endpoint = 'fax' 21 | 22 | def fax_message(self, to_number, from_name, from_number, file, **kwargs): 23 | """ 24 | Send a Fax message to a Destination Number 25 | 26 | :param to_number: [Required] Destination DID Number (Example: 5552341234) 27 | :type to_number: :py:class:`int` 28 | :param from_name: [Required] Name of the sender 29 | :type from_name: :py:class:`str` 30 | :param from_number: [Required] DID number of the Fax sender (Example: 5552341234) 31 | :type from_number: :py:class:`int` 32 | :param file: [Required] The file must be encoded in Base64 and in one of the following formats: pdf, txt, jpg, gif, png, tif 33 | :type file: :py:class:`str` 34 | 35 | :param send_email_enabled: Flag to enable the send of a copy of your Fax via email (True/False default False) 36 | :type send_email_enabled: :py:class:`bool` 37 | :param send_email: Email address where you want send a copy of your Fax. 38 | :type send_email: :py:class:`str` 39 | :param station_id: A word to identify a equipment or department sending the Fax 40 | :type station_id: :py:class:`str` 41 | :param test: Set to true if testing how cancel a Fax Folder (True/False) 42 | :type test: :py:class:`bool` 43 | 44 | :returns: :py:class:`dict` 45 | """ 46 | method = "sendFaxMessage" 47 | 48 | if not isinstance(to_number, int): 49 | raise ValueError("Destination DID Number needs to be an int (Example: 5552341234)") 50 | 51 | if not isinstance(from_name, str): 52 | raise ValueError("Name of the sender needs to be a str") 53 | 54 | if not isinstance(from_number, int): 55 | raise ValueError("DID number of the Fax sender needs to be an int (Example: 5552341234)") 56 | 57 | if not isinstance(file, str): 58 | raise ValueError("The file must be encoded in Base64 and in one of the following formats: pdf, txt, jpg, gif, png, tif and needs to be a str") 59 | 60 | parameters = { 61 | "to_number": to_number, 62 | "from_name": from_name, 63 | "from_number": from_number, 64 | "file": file, 65 | } 66 | 67 | if "send_email_enabled" in kwargs: 68 | if not isinstance(kwargs["send_email_enabled"], bool): 69 | raise ValueError("Flag to enable the send of a copy of your Fax via email needs to be a bool (True/False default False)") 70 | parameters["send_email_enabled"] = convert_bool(kwargs.pop("send_email_enabled")) 71 | 72 | if "send_email" in kwargs: 73 | send_email = kwargs.pop("send_email") 74 | if not isinstance(send_email, str): 75 | raise ValueError("Email address where you want send a copy of your Fax needs to be a str (Example: yourname@company.com)") 76 | elif not validate_email(send_email): 77 | raise ValueError("Email address where you want send a copy of your Fax is not a correct email syntax") 78 | parameters["send_email"] = send_email 79 | 80 | if "station_id" in kwargs: 81 | if not isinstance(kwargs["station_id"], str): 82 | raise ValueError("A word to identify a equipment or department sending the Fax needs to be a str") 83 | parameters["station_id"] = kwargs.pop("station_id") 84 | 85 | if "test" in kwargs: 86 | if not isinstance(kwargs["test"], bool): 87 | raise ValueError("Set to true if testing how cancel a Fax Folder needs to be a bool (True/False)") 88 | else: 89 | parameters["test"] = convert_bool(kwargs.pop("test")) 90 | 91 | if len(kwargs) > 0: 92 | not_allowed_parameters = "" 93 | for key, value in kwargs.items(): 94 | not_allowed_parameters += key + " " 95 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 96 | 97 | return self._voipms_client._get(method, parameters) 98 | -------------------------------------------------------------------------------- /voipms/entities/didsconnect.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Dids API endpoint connect 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import validate_date, convert_bool 9 | 10 | 11 | class DidsConnect(BaseApi): 12 | """ 13 | Connect for the Dids endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(DidsConnect, self).__init__(*args, **kwargs) 20 | self.endpoint = 'dids' 21 | 22 | def connect_did(self, did, account, monthly, setup, minute, **kwargs): 23 | """ 24 | Connects a specific DID to a specific Reseller Client Sub Account 25 | 26 | :param did: [Required] DID to be canceled and deleted (Example: 5551234567) 27 | :type did: :py:class:`str` or `int` 28 | :param account: [Required] Reseller Sub Account (Example: '100001_VoIP') 29 | :type account: :py:class:`str` 30 | :param monthly: [Required] Montly Fee for Reseller Client (Example: 3.50) 31 | :type monthly: :py:class:`float` 32 | :param setup: [Required] Setup Fee for Reseller Client (Example: 1.99) 33 | :type setup: :py:class:`float` 34 | :param minute: [Required] Minute Rate for Reseller Client (Example: 0.03) 35 | :type minute: :py:class:`float` 36 | :param **kwargs: All optional parameters 37 | :type **kwargs: :py:class:`dict` 38 | 39 | :param next_billing: Next billing date (Example: '2014-03-30') 40 | :type next_billing: :py:class:`str` 41 | :param dont_charge_setup: If set to true, the setup value will not be charged after Connect 42 | :type dont_charge_setup: :py:class:`bool` 43 | :param dont_charge_monthly: If set to true, the monthly value will not be charged after Connect 44 | :type dont_charge_monthly: :py:class:`bool` 45 | 46 | :returns: :py:class:`dict` 47 | """ 48 | method = "connectDID" 49 | 50 | if isinstance(did, str): 51 | did = did.replace('.', '') 52 | try: 53 | did = int(did) 54 | except: 55 | raise ValueError("DID to be canceled and deleted needs to be an int or str of numbers (Example: 555.123.4567 or 5551234567)") 56 | if not isinstance(did, int): 57 | raise ValueError("DID to be canceled and deleted needs to be an int (Example: 5551234567)") 58 | 59 | if not isinstance(account, str): 60 | raise ValueError("Reseller Sub Account needs to be a str (Example: '100001_VoIP')") 61 | 62 | if not isinstance(monthly, float): 63 | raise ValueError("Montly Fee for Reseller Client needs to be a float (Example: 3.50)") 64 | 65 | if not isinstance(setup, float): 66 | raise ValueError("Setup Fee for Reseller Client needs to be a float (Example: 1.99)") 67 | 68 | if not isinstance(minute, float): 69 | raise ValueError("Minute Rate for Reseller Client needs to be a float (Example: 0.03)") 70 | 71 | parameters = { 72 | "did": did, 73 | "account": account, 74 | "monthly": monthly, 75 | "setup": setup, 76 | "minute": minute, 77 | } 78 | 79 | if "next_billing" in kwargs: 80 | if not isinstance(kwargs["next_billing"], str): 81 | raise ValueError("Next billing date needs to be a str (Example: '2014-03-30')") 82 | validate_date(kwargs["next_billing"]) 83 | parameters["next_billing"] = kwargs.pop("next_billing") 84 | 85 | if "dont_charge_setup" in kwargs: 86 | if not isinstance(kwargs["dont_charge_setup"], bool): 87 | raise ValueError("If set to True, the setup value will not be charged after Connect (needs to be bool)") 88 | parameters["dont_charge_setup"] = convert_bool(kwargs.pop("dont_charge_setup")) 89 | 90 | if "dont_charge_monthly" in kwargs: 91 | if not isinstance(kwargs["dont_charge_monthly"], bool): 92 | raise ValueError("If set to True, the monthly value will not be charged after Connect (needs to be bool)") 93 | parameters["dont_charge_monthly"] = convert_bool(kwargs.pop("dont_charge_monthly")) 94 | 95 | if len(kwargs) > 0: 96 | not_allowed_parameters = "" 97 | for key, value in kwargs.items(): 98 | not_allowed_parameters += key + " " 99 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 100 | 101 | return self._voipms_client._get(method, parameters) 102 | -------------------------------------------------------------------------------- /voipms/entities/callsset.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Calls API endpoint set 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from datetime import datetime 8 | 9 | from voipms.baseapi import BaseApi 10 | from voipms.helpers import validate_date, convert_bool 11 | 12 | 13 | class CallsSet(BaseApi): 14 | """ 15 | Set for the Calls endpoint. 16 | """ 17 | def __init__(self, *args, **kwargs): 18 | """ 19 | Initialize the endpoint 20 | """ 21 | super(CallsSet, self).__init__(*args, **kwargs) 22 | self.endpoint = 'calls' 23 | 24 | def call_parking(self, name, timeout, music, failover, language, destination, delay, 25 | blf_lamps, callparking=None): 26 | """ 27 | Updates a specific Call Parking entry if a Call Parking ID is provided 28 | 29 | - Adds a new Call Parking entry if no Call Parking ID is provided 30 | 31 | :param callparking: ID for a specific Call Parking (Example: 235 / Leave empty to create a new one) 32 | :type callparking: :py:class:`int` 33 | :param name: [Required] Name for the Call Parking 34 | :type name: :py:class:`str` 35 | :param timeout: [Required] The number of seconds a call will stay parked before it is forwarded to the Failover Destination 36 | :type timeout: :py:class:`int` 37 | :param music: [Required] Music on Hold Code (Values from getMusicOnHold) 38 | :type music: :py:class:`int` 39 | :param failover: [Required] Final destination where the call will be forwarded if it isn’t answered. (Values: callback, system:hangup, vm:mailbox) 40 | :type failover: :py:class:`str` 41 | :param language: [Required] Language for the Call Parking (values from getLanguages) 42 | :type language: :py:class:`str` 43 | :param destination: [Required] The system will make an automatic call to this destination to announce the extension of the parked call. (Values: parker, main account or sub-accounts) 44 | :type destination: :py:class:`str` 45 | :param delay: [Required] The number of seconds before the Announce Destination receives an automatic call from the system to announce the extension of the parked call 46 | :type delay: :py:class:`int` 47 | :param blf_lamps: [Required] You can enable BLF for your Parking Lot and select the amount of BLF Lamps that you require. (Values: 0 to 10) 48 | :type blf_lamps: :py:class:`int` 49 | 50 | :returns: :py:class:`dict` 51 | """ 52 | method = "setCallParking" 53 | 54 | if not isinstance(name, str): 55 | raise ValueError("ID for a specific Call Parking (Example: 235 / Leave empty to create a new one)") 56 | 57 | if not isinstance(timeout, int): 58 | raise ValueError("[Required] The number of seconds a call will stay parked before it is forwarded to the Failover Destination") 59 | 60 | if not isinstance(music, int): 61 | raise ValueError("[Required] Music on Hold Code (Values from getMusicOnHold) ") 62 | 63 | if not isinstance(failover, str): 64 | raise ValueError("[Required] Final destination where the call will be forwarded if it isn’t answered. (Values: callback, system:hangup, vm:mailbox)") 65 | 66 | if not isinstance(language, str): 67 | raise ValueError("[Required] Language for the Call Parking (values from getLanguages)") 68 | 69 | if not isinstance(destination, str): 70 | raise ValueError("[Required] The system will make an automatic call to this destination to announce the extension of the parked call. (Values: parker, main account or sub-accounts)") 71 | 72 | if not isinstance(delay, int): 73 | raise ValueError("[Required] The number of seconds before the Announce Destination receives an automatic call from the system to announce the extension of the parked call") 74 | 75 | if not isinstance(blf_lamps, int): 76 | raise ValueError("[Required] You can enable BLF for your Parking Lot and select the amount of BLF Lamps that you require. (Values: 0 to 10)") 77 | 78 | parameters = { 79 | "name": name, 80 | "timeout": timeout, 81 | "music": music, 82 | "failover": failover, 83 | "language": language, 84 | "destination": destination, 85 | "delay": delay, 86 | "blf_lamp": blf_lamp, 87 | } 88 | 89 | if callparking: 90 | if not isinstance(callparking, int): 91 | raise ValueError("ID for a specific Call Parking (Example: 235 / Leave empty to create a new one)") 92 | parameters["callparking"] = callparking 93 | 94 | return self._voipms_client._get(method, parameters) 95 | -------------------------------------------------------------------------------- /voipms/entities/didssend.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Dids API endpoint send 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | import validators 9 | from validators import ValidationError 10 | import base64 11 | 12 | def isBase64(s): 13 | try: 14 | return base64.b64encode(base64.b64decode(s)) == s 15 | except Exception: 16 | return False 17 | 18 | def valid_url(url_string: str) -> bool: 19 | result = validators.url(url_string) 20 | 21 | if isinstance(result, ValidationError): 22 | return False 23 | 24 | return result 25 | 26 | class DidsSend(BaseApi): 27 | """ 28 | Send for the Dids endpoint. 29 | """ 30 | def __init__(self, *args, **kwargs): 31 | """ 32 | Initialize the endpoint 33 | """ 34 | super(DidsSend, self).__init__(*args, **kwargs) 35 | self.endpoint = 'dids' 36 | 37 | def sms(self, did, dst, message): 38 | """ 39 | Send a SMS message to a Destination Number 40 | 41 | :param did: [Required] DID Numbers which is sending the message (Example: 5551234567) 42 | :type did: :py:class:`int` 43 | :param dst: [Required] Destination Number (Example: 5551234568) 44 | :type dst: :py:class:`int` 45 | :param message: [Required] Message to be sent (Example: 'hello John Smith' max chars: 160) 46 | :type message: :py:class:`str` 47 | 48 | :returns: :py:class:`dict` 49 | """ 50 | method = "sendSMS" 51 | 52 | if not isinstance(did, int): 53 | raise ValueError("DID Numbers which is sending the message needs to be an int (Example: 5551234567)") 54 | 55 | if not isinstance(dst, int): 56 | raise ValueError("Destination Number needs to be an int (Example: 5551234568) ") 57 | 58 | if not isinstance(message, str): 59 | raise ValueError("Message to be sent needs to be a str (Example: 'hello John Smith' max chars: 160)") 60 | else: 61 | if len(message) > 160: 62 | raise ValueError("Message to be sent can only have 160 chars") 63 | 64 | parameters = { 65 | "did": did, 66 | "dst": dst, 67 | "message": message, 68 | } 69 | 70 | return self._voipms_client._get(method, parameters) 71 | 72 | def mms(self, did, dst, message, media1=None, media2=None): 73 | """ 74 | Send a MMS message to a Destination Number 75 | 76 | :param did: [Required] DID Numbers which is sending the message (Example: 5551234567) 77 | :type did: :py:class:`int` 78 | :param dst: [Required] Destination Number (Example: 5551234568) 79 | :type dst: :py:class:`int` 80 | :param message: [Required] Message to be sent (Example: 'hello John Smith' max chars: 1600) 81 | :type message: :py:class:`str` 82 | :param media1: [Optional] Url to media file (Example: 'https://voip.ms/themes/voipms/assets/img/talent.jpg?v=2' 83 | :type media1: :py:class:`str` 84 | :param media2: [Optional] Base 64 image encode (Example: data:image/png;base64,iVBORw0KGgoAAAANSUh...) 85 | :type media2: :py:class:`str` 86 | 87 | :returns: :py:class:`dict` 88 | """ 89 | method = "sendMMS" 90 | 91 | if not isinstance(did, int): 92 | raise ValueError("DID Numbers which is sending the message needs to be an int (Example: 5551234567)") 93 | 94 | if not isinstance(dst, int): 95 | raise ValueError("Destination Number needs to be an int (Example: 5551234568) ") 96 | 97 | if not isinstance(message, str): 98 | raise ValueError("Message to be sent needs to be a str (Example: 'hello John Smith' max chars: 1600)") 99 | 100 | if media1: 101 | if not valid_url(media1): 102 | raise ValueError("Media1 to be sent needs to be a valid url to media file (Example: 'https://voip.ms/themes/voipms/assets/img/talent.jpg?v=2' ") 103 | 104 | if media2: 105 | if not isBase64(media2): 106 | raise ValueError("Media2 to be sent needs to be a base 64 image encode (Example: data:image/png;base64,iVBORw0KGgoAAAANSUh...)") 107 | else: 108 | if len(message) > 1600: 109 | raise ValueError("Message to be sent can only have 1600 chars") 110 | 111 | if media1: 112 | parameters = { 113 | "did": did, 114 | "dst": dst, 115 | "message": message, 116 | "media1": media1, 117 | } 118 | elif media2: 119 | parameters = { 120 | "did": did, 121 | "dst": dst, 122 | "message": message, 123 | "media2": media2, 124 | } 125 | else: 126 | parameters = { 127 | "did": did, 128 | "dst": dst, 129 | "message": message, 130 | } 131 | 132 | return self._voipms_client._get(method, parameters) 133 | -------------------------------------------------------------------------------- /voipms/entities/voicemailmark.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Voicemail API endpoint mark 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class VoicemailMark(BaseApi): 11 | """ 12 | Mark for the Voicemail endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(VoicemailMark, self).__init__(*args, **kwargs) 19 | self.endpoint = 'voicemail' 20 | 21 | def listened_voicemail_message(self, mailbox, folder, message_num, listened): 22 | """ 23 | Mark a Voicemail Message as Listened or Unlistened 24 | 25 | - If value is 'yes', the voicemail message will be marked as listened and will be moved to the Old Folder 26 | - If value is 'no', the voicemail message will be marked as not-listened and will be moved to the INBOX Folder 27 | 28 | :param mailbox: [Required] ID for a specific Mailbox (Example: 1001) 29 | :type mailbox: :py:class:`int` 30 | :param folder: [required] Name for specific Folder (Required if message id is passed, Example: 'INBOX', values from: voicemail.get_voicemail_folders) 31 | :type folder: :py:class:`str` 32 | :param message_num: [required] ID for specific Voicemail Message (Required if folder is passed, Example: 1) 33 | :type message_num: :py:class:`int` 34 | :param listened: [required] Code for mark voicemail as listened or not-listened (Values: 'yes'/'no') 35 | :type listened: :py:class:`str` 36 | 37 | :returns: :py:class:`dict` 38 | """ 39 | method = "markListenedVoicemailMessage" 40 | 41 | if not isinstance(mailbox, int): 42 | raise ValueError("ID for a specific Mailbox needs to be an int (Example: 1001)") 43 | 44 | if not isinstance(folder, str): 45 | raise ValueError("Name for specific Folder needs to be a str (Required if message id is passed, Example: 'INBOX', values from: voicemail.get_voicemail_folders)") 46 | 47 | if not isinstance(message_num, int): 48 | raise ValueError("ID for specific Voicemail Message needs to be an int (Required if folder is passed, Example: 1)") 49 | 50 | if not isinstance(listened, str): 51 | raise ValueError("Code for mark voicemail as listened or not-listened needs to be a str (Values: 'yes'/'no')") 52 | elif listened not in ("yes", "no"): 53 | raise ValueError("Code for mark voicemail as listened or not-listened only allows values: 'yes'/'no'") 54 | 55 | parameters = { 56 | "mailbox": mailbox, 57 | "folder": folder, 58 | "message_num": message_num, 59 | "listened": listened, 60 | } 61 | 62 | return self._voipms_client._get(method, parameters) 63 | 64 | def urgent_voicemail_message(self, mailbox, folder, message_num, urgent): 65 | """ 66 | Mark Voicemail Message as Urgent or not Urgent 67 | 68 | - If value is 'yes', the voicemail message will be marked as urgent and will be moved to the Urgent Folder 69 | - If value is 'no', the voicemail message will be unmarked as urgent and will be moved to the INBOX Folder 70 | 71 | :param mailbox: [Required] ID for a specific Mailbox (Example: 1001) 72 | :type mailbox: :py:class:`int` 73 | :param folder: [required] Name for specific Folder (Required if message id is passed, Example: 'INBOX', values from: voicemail.get_voicemail_folders) 74 | :type folder: :py:class:`str` 75 | :param message_num: [required] ID for specific Voicemail Message (Required if folder is passed, Example: 1) 76 | :type message_num: :py:class:`int` 77 | :param listened: [required] Code for mark voicemail as urgent or not-urgent (Values: 'yes'/'no') 78 | :type listened: :py:class:`str` 79 | 80 | :returns: :py:class:`dict` 81 | """ 82 | method = "markUrgentVoicemailMessage" 83 | 84 | if not isinstance(mailbox, int): 85 | raise ValueError("ID for a specific Mailbox needs to be an int (Example: 1001)") 86 | 87 | if not isinstance(folder, str): 88 | raise ValueError("Name for specific Folder needs to be a str (Required if message id is passed, Example: 'INBOX', values from: voicemail.get_voicemail_folders)") 89 | 90 | if not isinstance(message_num, int): 91 | raise ValueError("ID for specific Voicemail Message needs to be an int (Required if folder is passed, Example: 1)") 92 | 93 | if not isinstance(urgent, str): 94 | raise ValueError("Code for mark voicemail as urgent or not-urgent needs to be a str (Values: 'yes'/'no')") 95 | elif urgent not in ("yes", "no"): 96 | raise ValueError("Code for mark voicemail as urgent or not-urgent only allows values: 'yes'/'no'") 97 | 98 | parameters = { 99 | "mailbox": mailbox, 100 | "folder": folder, 101 | "message_num": message_num, 102 | "urgent": urgent, 103 | } 104 | 105 | return self._voipms_client._get(method, parameters) 106 | -------------------------------------------------------------------------------- /voipms/entities/faxorder.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Fax API endpoint order 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import convert_bool, validate_email 9 | 10 | 11 | class FaxOrder(BaseApi): 12 | """ 13 | Order for the Fax endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(FaxOrder, self).__init__(*args, **kwargs) 20 | self.endpoint = 'fax' 21 | 22 | def fax_number(self, location, quantity, **kwargs): 23 | """ 24 | Orders and Adds a new Fax Number to the Account 25 | 26 | :param location: [Required] Location ID of the Fax Number (Values from fax.get_fax_rate_centers_can/fax.get_fax_rate_centers_usa) 27 | :type location: :py:class:`int` 28 | :param quantity: [Required] Quantity of Fax Numbers to order (Example: 3) 29 | :type quantity: :py:class:`int` 30 | 31 | :param email: Email address where send notifications when receive Fax Messages (Example: yourname@company.com) 32 | :type email: :py:class:`str` 33 | :param email_enable: Flag to enable the email notifications (True/False default False) 34 | :type email_enable: :py:class:`bool` 35 | :param email_attach_file: Flag to enable attach the Fax Message as a PDF file in the notifications (True/False default False) 36 | :type email_attach_file: :py:class:`bool` 37 | :param url_callback: URL where make a POST when you receive a Fax Message 38 | :type url_callback: :py:class:`str` 39 | :param url_callback_enable: Flag to enable the URL Callback functionality (True/False default False) 40 | :type url_callback_enable: :py:class:`bool` 41 | :param url_callback_retry: Flag to enable retry the POST action in case we don't receive "ok" (True/False default False) 42 | :type url_callback_retry: :py:class:`bool` 43 | :param test: Set to true if testing how cancel a Fax Folder (True/False) 44 | :type test: :py:class:`bool` 45 | 46 | :returns: :py:class:`dict` 47 | """ 48 | method = "orderFaxNumber" 49 | 50 | if not isinstance(location, int): 51 | raise ValueError("Location ID of the Fax Number needs to be an int (Values from fax.get_fax_rate_centers_can/fax.get_fax_rate_centers_usa)") 52 | 53 | if not isinstance(quantity, int): 54 | raise ValueError("Quantity of Fax Numbers to order needs to be an int (Example: 3)") 55 | 56 | parameters = { 57 | "location": location, 58 | "quantity": quantity, 59 | } 60 | 61 | if "email" in kwargs: 62 | email = kwargs.pop("email") 63 | if not isinstance(email, str): 64 | raise ValueError("Email address where send notifications when receive Fax Messages needs to be a str (Example: yourname@company.com)") 65 | elif not validate_email(email): 66 | raise ValueError("Email address where send notifications when receive Fax Messages is not a correct email syntax") 67 | parameters["email"] = email 68 | 69 | if "email_enabled" in kwargs: 70 | if not isinstance(kwargs["email_enabled"], bool): 71 | raise ValueError("Flag to enable the email notifications needs to be a bool (True/False default False)") 72 | parameters["email_enabled"] = convert_bool(kwargs.pop("email_enabled")) 73 | 74 | if "email_attach_file" in kwargs: 75 | if not isinstance(kwargs["email_attach_file"], bool): 76 | raise ValueError("Flag to enable attach the Fax Message as a PDF file in the notifications needs to be a bool (True/False default False)") 77 | parameters["email_attach_file"] = convert_bool(kwargs.pop("email_attach_file")) 78 | 79 | if "url_callback" in kwargs: 80 | if not isinstance(kwargs["url_callback"], str): 81 | raise ValueError("URL where make a POST when you receive a Fax Message needs to be a str") 82 | parameters["url_callback"] = convert_bool(kwargs.pop("url_callback")) 83 | 84 | if "url_callback_enable" in kwargs: 85 | if not isinstance(kwargs["url_callback_enable"], bool): 86 | raise ValueError("Flag to enable the URL Callback functionality needs to be a bool (True/False default False)") 87 | parameters["url_callback_enable"] = convert_bool(kwargs.pop("url_callback_enable")) 88 | 89 | if "url_callback_retry" in kwargs: 90 | if not isinstance(kwargs["url_callback_retry"], bool): 91 | raise ValueError("Flag to enable retry the POST action in case we don't receive \"ok\" (True/False default False)") 92 | parameters["url_callback_retry"] = convert_bool(kwargs.pop("url_callback_retry")) 93 | 94 | if "test" in kwargs: 95 | if not isinstance(kwargs["test"], bool): 96 | raise ValueError("Set to true if testing how cancel a Fax Folder needs to be a bool (True/False)") 97 | else: 98 | parameters["test"] = convert_bool(kwargs.pop("test")) 99 | 100 | if len(kwargs) > 0: 101 | not_allowed_parameters = "" 102 | for key, value in kwargs.items(): 103 | not_allowed_parameters += key + " " 104 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 105 | 106 | return self._voipms_client._get(method, parameters) 107 | -------------------------------------------------------------------------------- /voipms/entities/lnpget.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Local Number Portability (LNP) API endpoint get 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import validate_date 9 | 10 | 11 | class LNPGet(BaseApi): 12 | """ 13 | Get for the Local Number Portability (LNP) endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(LNPGet, self).__init__(*args, **kwargs) 20 | self.endpoint = 'lnp' 21 | 22 | def attach(self, portid, attachid): 23 | """ 24 | Retrieve the details of an attached invoice. 25 | 26 | :param portid: [Required] ID of the port previously created 27 | :type portid: :py:class:`str` 28 | :param attachid: [Required] ID of the invoice (attachment) previously uploaded 29 | :type attachid: :py:class:`str` 30 | 31 | :returns: :py:class:`dict` 32 | """ 33 | method = "getLNPAttach" 34 | 35 | if not isinstance(portid, str): 36 | raise ValueError("") 37 | 38 | if not isinstance(attachid, str): 39 | raise ValueError("") 40 | 41 | parameters = { 42 | "portid": portid, 43 | "attachid": attachid 44 | } 45 | 46 | return self._voipms_client._get(method, parameters) 47 | 48 | def attach_list(self, portid): 49 | """ 50 | Retrieve the list of invoice (attached) files from a given portability process. 51 | 52 | :param portid: [Required] ID of the port previously created 53 | :type portid: :py:class:`str` 54 | 55 | :returns: :py:class:`dict` 56 | """ 57 | method = "getLNPAttachList" 58 | 59 | if not isinstance(portid, str): 60 | raise ValueError("") 61 | 62 | parameters = { 63 | "portid": portid 64 | } 65 | 66 | return self._voipms_client._get(method, parameters) 67 | 68 | def details(self, portid): 69 | """ 70 | Retrieve the details of a given portability process. 71 | 72 | :param portid: [Required] ID of the port previously created 73 | :type portid: :py:class:`str` 74 | 75 | :returns: :py:class:`dict` 76 | """ 77 | method = "getLNPDetails" 78 | 79 | if not isinstance(portid, str): 80 | raise ValueError("ID for a specific backorder DID") 81 | 82 | parameters = { 83 | "portid": portid 84 | } 85 | 86 | return self._voipms_client._get(method, parameters) 87 | 88 | def list(self, portid, portStatus=None, startDate=None, endDate=None): 89 | """ 90 | Retrieve the full list of all your portability processes. 91 | 92 | :param portid: [Required] ID of the port previously created 93 | :type portid: :py:class:`int` 94 | :param partStatus: Status code to filtering Ports. Example: precessing. (You can use values returned by the method getLNPListStatus) 95 | :type partStatus: :py:class:`str` 96 | :param startDate: Start Date for filtering Ports. (Example: '2014-03-30') 97 | :type startDate: :py:class:`str` 98 | :param endDate: End Date for filtering Ports. (Example: '2014-03-30') 99 | :type endDate: :py:class:`str` 100 | 101 | :returns: :py:class:`dict` 102 | """ 103 | method = "getLNPList" 104 | 105 | if not isinstance(portid, str): 106 | raise ValueError("[Required] ID of the port previously created") 107 | 108 | parameters = { 109 | "portid": portid 110 | } 111 | 112 | if portStatus: 113 | if not isinstance(portStatus, str): 114 | raise ValueError("Status code to filtering Ports. Example: precessing. (You can use values returned by the method getLNPListStatus)") 115 | parameters["portStatus"] = portStatus 116 | 117 | if startDate: 118 | if not isinstance(startDate, str): 119 | raise ValueError("Start Date for filtering Ports. (Example: '2014-03-30')") 120 | parameters["startDate"] = startDate 121 | 122 | if endDate: 123 | if not isinstance(endDate, str): 124 | raise ValueError("End Date for filtering Ports. (Example: '2014-03-30')") 125 | parameters["endDate"] = endDate 126 | 127 | return self._voipms_client._get(method, parameters) 128 | 129 | def list_status(self): 130 | """ 131 | Retrieve the list of possible status of a portability process. 132 | 133 | No Parameters 134 | 135 | :returns: :py:class:`dict` 136 | """ 137 | method = "getLNPListStatus" 138 | 139 | parameters = {} 140 | 141 | return self._voipms_client._get(method, parameters) 142 | 143 | def notes(self, portid): 144 | """ 145 | Retrieve the list of notes from the given portability process. 146 | 147 | :param portid: [Required] ID of the port previously created 148 | :type portid: :py:class:`str` 149 | 150 | :returns: :py:class:`dict` 151 | """ 152 | method = "getLNPNotes" 153 | 154 | if not isinstance(portid, str): 155 | raise ValueError("ID for a specific backorder DID") 156 | 157 | parameters = { 158 | "portid": portid 159 | } 160 | 161 | return self._voipms_client._get(method, parameters) 162 | 163 | def status(self, portid): 164 | """ 165 | Retrieve the current status of a given portability process. 166 | 167 | :param portid: [Required] ID of the port previously created 168 | :type portid: :py:class:`int` 169 | 170 | :returns: :py:class:`dict` 171 | """ 172 | method = "getLNPStatus" 173 | 174 | if not isinstance(portid, str): 175 | raise ValueError("[Required] ID of the port previously created") 176 | 177 | parameters = { 178 | "portid": portid 179 | } 180 | 181 | return self._voipms_client._get(method, parameters) 182 | -------------------------------------------------------------------------------- /voipms/entities/clientsget.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Clients API endpoint get 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class ClientsGet(BaseApi): 11 | """ 12 | Get for the Clients endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(ClientsGet, self).__init__(*args, **kwargs) 19 | self.endpoint = 'clients' 20 | 21 | def balance_management(self, balance_management=None): 22 | """ 23 | Retrieves a list of Balance Management Options if no additional parameter is provided 24 | 25 | - Retrieves a specific Balance Management Option if a code is provided 26 | 27 | :param balance_management: Code for a specific Balance Management Setting (Example: 1) 28 | :type balance_management: :py:class:`int` 29 | :returns: :py:class:`dict` 30 | """ 31 | method = "getBalanceManagement" 32 | 33 | parameters = {} 34 | if balance_management: 35 | if not isinstance(balance_management, int): 36 | raise ValueError("Code for a specific Balance Management Setting needs to be an int (Example: 1)") 37 | parameters["balance_management"] = balance_management 38 | 39 | return self._voipms_client._get(method, parameters) 40 | 41 | def charges(self, client): 42 | """ 43 | Retrieves Charges made to a specific Reseller Client 44 | 45 | :param client: [Required] ID for a specific Reseller Client (Example: 561115) 46 | :type client: :py:class:`int` 47 | :returns: :py:class:`dict` 48 | """ 49 | method = "getCharges" 50 | 51 | parameters = {} 52 | if client: 53 | if not isinstance(client, int): 54 | raise ValueError("ID for a specific Reseller Client needs to be an int (Example: 561115)") 55 | parameters["client"] = client 56 | 57 | return self._voipms_client._get(method, parameters) 58 | 59 | def client_packages(self, client): 60 | """ 61 | Retrieves a list of Packages for a specific Reseller Client 62 | 63 | :param client: [Required] ID for a specific Reseller Client (Example: 561115) 64 | :type client: :py:class:`int` 65 | :returns: :py:class:`dict` 66 | """ 67 | method = "getClientPackages" 68 | 69 | parameters = {} 70 | if client: 71 | if not isinstance(client, int): 72 | raise ValueError("ID for a specific Reseller Client needs to be an int (Example: 561115)") 73 | parameters["client"] = client 74 | 75 | return self._voipms_client._get(method, parameters) 76 | 77 | def clients(self, client=None): 78 | """ 79 | Retrieves a list of all Clients if no additional parameter is provided 80 | 81 | - Retrieves a specific Reseller Client if a Reseller Client ID is provided 82 | - Retrieves a specific Reseller Client if a Reseller Client e-mail is provided 83 | 84 | :param client: Parameter could have the following values: 85 | * Empty Value [Not Required] 86 | * Specific Reseller Client ID (Example: 561115) 87 | * Specific Reseller Client e-mail (Example: 'john.doe@mydomain.com') 88 | :type client: :py:class:`int` or `str` or `` 89 | :returns: :py:class:`dict` 90 | """ 91 | method = "getClients" 92 | 93 | if not client: 94 | client = "" 95 | 96 | parameters = { 97 | "client": client, 98 | } 99 | 100 | return self._voipms_client._get(method, parameters) 101 | 102 | def client_threshold(self, client): 103 | """ 104 | Retrieves the Threshold Information for a specific Reseller Client 105 | 106 | :param client: [Required] ID for a specific Reseller Client (Example: 561115) 107 | :type client: :py:class:`int` 108 | :returns: :py:class:`dict` 109 | """ 110 | method = "getClientThreshold" 111 | 112 | parameters = {} 113 | if client: 114 | if not isinstance(client, int): 115 | raise ValueError("ID for a specific Reseller Client needs to be an int (Example: 561115)") 116 | parameters["client"] = client 117 | 118 | return self._voipms_client._get(method, parameters) 119 | 120 | def deposits(self, client): 121 | """ 122 | Retrieves Deposits made for a specific Reseller Client 123 | 124 | :param client: [Required] ID for a specific Reseller Client (Example: 561115) 125 | :type client: :py:class:`int` 126 | :returns: :py:class:`dict` 127 | """ 128 | method = "getDeposits" 129 | 130 | parameters = {} 131 | if client: 132 | if not isinstance(client, int): 133 | raise ValueError("ID for a specific Reseller Client needs to be an int (Example: 561115)") 134 | parameters["client"] = client 135 | 136 | return self._voipms_client._get(method, parameters) 137 | 138 | def packages(self, package=None): 139 | """ 140 | Retrieves Deposits made for a specific Reseller Client 141 | 142 | :param package: Code for a specific Package (Example: 8378) 143 | :type package: :py:class:`int` 144 | :returns: :py:class:`dict` 145 | """ 146 | method = "getPackages" 147 | 148 | parameters = {} 149 | if package: 150 | if not isinstance(package, int): 151 | raise ValueError("Code for a specific Package needs to be an int (Example: 8378)") 152 | parameters["package"] = package 153 | 154 | return self._voipms_client._get(method, parameters) 155 | 156 | def reseller_balance(self, client): 157 | """ 158 | Retrieves Balance and Calls Statistics for a specific Reseller Client for the last 30 days and current day 159 | 160 | :param client: [Required] ID for a specific Reseller Client (Example: 561115) 161 | :type client: :py:class:`int` 162 | :returns: :py:class:`dict` 163 | """ 164 | method = "getResellerBalance" 165 | 166 | parameters = {} 167 | if client: 168 | if not isinstance(client, int): 169 | raise ValueError("ID for a specific Reseller Client needs to be an int (Example: 561115)") 170 | parameters["client"] = client 171 | 172 | return self._voipms_client._get(method, parameters) 173 | -------------------------------------------------------------------------------- /voipms/__init__.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | voip.ms v1 REST API SDK 4 | 5 | Documentation at https://voip.ms/m/apidocs.php 6 | """ 7 | 8 | # META 9 | __version__ = "0.2.6" 10 | __title__ = "voipms" 11 | __description__ = "Complete REST API for the voip.ms service" 12 | __uri__ = "https://github.com/4doom4/python-voipms" 13 | __doc__ = __description__ + " <" + __uri__ + ">" 14 | 15 | __author__ = "Maximilian Ebert and Andrew Langemann" 16 | __email__ = "max.ebert@me.com" 17 | 18 | __license__ = "MIT" 19 | __copyright__ = "Copyright (c) 2022" 20 | 21 | 22 | # API Client 23 | from voipms.voipmsclient import VoipMsClient 24 | # General 25 | from voipms.entities.general import General 26 | from voipms.entities.generalget import GeneralGet 27 | # Accounts 28 | from voipms.entities.accounts import Accounts 29 | from voipms.entities.accountsadd import AccountsAdd 30 | from voipms.entities.accountscreate import AccountsCreate 31 | from voipms.entities.accountsdelete import AccountsDelete 32 | from voipms.entities.accountsget import AccountsGet 33 | from voipms.entities.accountsset import AccountsSet 34 | # Call Detail Records 35 | from voipms.entities.calls import Calls 36 | from voipms.entities.callsdelete import CallsDelete 37 | from voipms.entities.callsget import CallsGet 38 | from voipms.entities.callssend import CallsSend 39 | from voipms.entities.callsset import CallsSet 40 | # Clients 41 | from voipms.entities.clients import Clients 42 | from voipms.entities.clientsadd import ClientsAdd 43 | from voipms.entities.clientsassign import ClientsAssign 44 | from voipms.entities.clientsget import ClientsGet 45 | from voipms.entities.clientsset import ClientsSet 46 | # DIDs 47 | from voipms.entities.dids import Dids 48 | from voipms.entities.didsback_order import DidsBackOrder 49 | from voipms.entities.didscancel import DidsCancel 50 | from voipms.entities.didsconnect import DidsConnect 51 | from voipms.entities.didsdelete import DidsDelete 52 | from voipms.entities.didsget import DidsGet 53 | from voipms.entities.didsorder import DidsOrder 54 | from voipms.entities.didsremove import DidsRemove 55 | from voipms.entities.didssearch import DidsSearch 56 | from voipms.entities.didssend import DidsSend 57 | from voipms.entities.didsset import DidsSet 58 | from voipms.entities.didsunconnect import DidsUnconnect 59 | # E911 60 | from voipms.entities.e911 import E911 61 | # Fax 62 | from voipms.entities.fax import Fax 63 | from voipms.entities.faxcancel import FaxCancel 64 | from voipms.entities.faxconnect import FaxConnect 65 | from voipms.entities.faxdelete import FaxDelete 66 | from voipms.entities.faxget import FaxGet 67 | from voipms.entities.faxmail import FaxMail 68 | from voipms.entities.faxmove import FaxMove 69 | from voipms.entities.faxorder import FaxOrder 70 | from voipms.entities.faxsearch import FaxSearch 71 | from voipms.entities.faxsend import FaxSend 72 | from voipms.entities.faxset import FaxSet 73 | from voipms.entities.faxunconnect import FaxUnconnect 74 | # Local Number Portability (LNP) 75 | from voipms.entities.lnp import LNP 76 | from voipms.entities.lnpadd import LNPAdd 77 | from voipms.entities.lnpget import LNPGet 78 | # Voicemail 79 | from voipms.entities.voicemail import Voicemail 80 | from voipms.entities.voicemailcreate import VoicemailCreate 81 | from voipms.entities.voicemaildelete import VoicemailDelete 82 | from voipms.entities.voicemailget import VoicemailGet 83 | from voipms.entities.voicemailmark import VoicemailMark 84 | from voipms.entities.voicemailmove import VoicemailMove 85 | from voipms.entities.voicemailsend import VoicemailSend 86 | from voipms.entities.voicemailset import VoicemailSet 87 | 88 | 89 | class VoipMs(VoipMsClient): 90 | """ 91 | VoipMS class to communicate with the v1 REST API 92 | """ 93 | def __init__(self, *args, **kwargs): 94 | """ 95 | Initialize the class with your voip_user and voip_api_password and attach all 96 | of the endpoints 97 | """ 98 | super(VoipMs, self).__init__(*args, **kwargs) 99 | # General 100 | self.general = General(self) 101 | self.general.get = GeneralGet(self) 102 | # Accounts 103 | self.accounts = Accounts(self) 104 | self.accounts.add = AccountsAdd(self) 105 | self.accounts.create = AccountsCreate(self) 106 | self.accounts.delete = AccountsDelete(self) 107 | self.accounts.get = AccountsGet(self) 108 | self.accounts.set = AccountsSet(self) 109 | # Calls 110 | self.calls = Calls(self) 111 | self.calls.delete = CallsDelete(self) 112 | self.calls.get = CallsGet(self) 113 | self.calls.send = CallsSend(self) 114 | self.calls.set = CallsSet(self) 115 | # Clients 116 | self.clients = Clients(self) 117 | self.clients.add = ClientsAdd(self) 118 | self.clients.assign = ClientsAssign(self) 119 | self.clients.get = ClientsGet(self) 120 | self.clients.set = ClientsSet(self) 121 | # E911 122 | self.e911 = E911(self) 123 | # Dids 124 | self.dids = Dids(self) 125 | self.dids.back_order = DidsBackOrder(self) 126 | self.dids.cancel = DidsCancel(self) 127 | self.dids.connect = DidsConnect(self) 128 | self.dids.delete = DidsDelete(self) 129 | self.dids.get = DidsGet(self) 130 | self.dids.order = DidsOrder(self) 131 | self.dids.remove = DidsRemove(self) 132 | self.dids.search = DidsSearch(self) 133 | self.dids.send = DidsSend(self) 134 | self.dids.set = DidsSet(self) 135 | self.dids.unconnect = DidsUnconnect(self) 136 | # Fax 137 | self.fax = Fax(self) 138 | self.fax.cancel = FaxCancel(self) 139 | self.fax.connect = FaxConnect(self) 140 | self.fax.delete = FaxDelete(self) 141 | self.fax.get = FaxGet(self) 142 | self.fax.mail = FaxMail(self) 143 | self.fax.move = FaxMove(self) 144 | self.fax.order = FaxOrder(self) 145 | self.fax.search = FaxSearch(self) 146 | self.fax.send = FaxSend(self) 147 | self.fax.set = FaxSet(self) 148 | self.fax.unconnect = FaxUnconnect(self) 149 | # Local Number Portability (LNP) 150 | self.lnp = LNP(self) 151 | self.lnp.add = LNPAdd(self) 152 | self.lnp.get = LNPGet(self) 153 | # Voicemail 154 | self.voicemail = Voicemail(self) 155 | self.voicemail.create = VoicemailCreate(self) 156 | self.voicemail.delete = VoicemailDelete(self) 157 | self.voicemail.get = VoicemailGet(self) 158 | self.voicemail.mark = VoicemailMark(self) 159 | self.voicemail.move = VoicemailMove(self) 160 | self.voicemail.send = VoicemailSend(self) 161 | self.voicemail.set = VoicemailSet(self) 162 | -------------------------------------------------------------------------------- /voipms/entities/didssearch.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Dids API endpoint search 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class DidsSearch(BaseApi): 11 | """ 12 | Search for the Dids endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(DidsSearch, self).__init__(*args, **kwargs) 19 | self.endpoint = 'dids' 20 | 21 | def dids_can(self, search_type, query, province=None): 22 | """ 23 | Searches for Canadian DIDs by Province using a Search Criteria 24 | 25 | :param search_type: [Required] Type of search (Values: 'starts', 'contains', 'ends') 26 | :type search_type: :py:class:`str` 27 | :param query: [Required] Query for searching (Examples: 'JOHN', '555', '123ABC') 28 | :type query: :py:class:`str` 29 | 30 | :param province: Canadian Province (Values from dids.get_provinces) 31 | :type province: :py:class:`str` 32 | 33 | :returns: :py:class:`dict` 34 | """ 35 | method = "searchDIDsCAN" 36 | 37 | if not isinstance(search_type, str): 38 | raise ValueError("Type of search needs to be a str (Values: 'starts', 'contains', 'ends')") 39 | 40 | if not isinstance(query, str): 41 | raise ValueError("Query for searching needs to be a str (Examples: 'JOHN', '555', '123ABC')") 42 | 43 | parameters = { 44 | "type": search_type, 45 | "query": query 46 | } 47 | 48 | if province: 49 | if not isinstance(province, str): 50 | raise ValueError("Canadian Province needs to be a str (Values from dids.get_provinces)") 51 | else: 52 | parameters["province"] = province 53 | 54 | return self._voipms_client._get(method, parameters) 55 | 56 | def dids_usa(self, search_type, query, state=None): 57 | """ 58 | Searches for USA DIDs by State using a Search Criteria 59 | 60 | :param search_type: [Required] Type of search (Values: 'starts', 'contains', 'ends') 61 | :type search_type: :py:class:`str` 62 | :param query: [Required] Query for searching (Examples: 'JOHN', '555', '123ABC') 63 | :type query: :py:class:`str` 64 | 65 | :param state: Canadian Province (Values from dids.get_states) 66 | :type state: :py:class:`str` 67 | 68 | :returns: :py:class:`dict` 69 | """ 70 | method = "searchDIDsUSA" 71 | 72 | if not isinstance(search_type, str): 73 | raise ValueError("Type of search needs to be a str (Values: 'starts', 'contains', 'ends')") 74 | 75 | if not isinstance(query, str): 76 | raise ValueError("Query for searching needs to be a str (Examples: 'JOHN', '555', '123ABC')") 77 | 78 | parameters = { 79 | "type": search_type, 80 | "query": query 81 | } 82 | 83 | if state: 84 | if not isinstance(state, str): 85 | raise ValueError("United States State needs to be a str (Values from dids.get_states)") 86 | else: 87 | parameters["state"] = state 88 | 89 | return self._voipms_client._get(method, parameters) 90 | 91 | def toll_free_can_us(self, search_type=None, query=None): 92 | """ 93 | Searches for USA/Canada Toll Free Numbers using a Search Criteria 94 | 95 | - Shows all USA/Canada Toll Free Numbers available if no criteria is provided. 96 | 97 | :param search_type: Type of search (Values: 'starts', 'contains', 'ends') 98 | :type search_type: :py:class:`str` 99 | :param query: Query for searching (Examples: 'JOHN', '555', '123ABC') 100 | :type query: :py:class:`str` 101 | 102 | :returns: :py:class:`dict` 103 | """ 104 | method = "searchTollFreeCanUS" 105 | 106 | parameters = {} 107 | 108 | if search_type: 109 | if not isinstance(search_type, str): 110 | raise ValueError("Type of search needs to be a str (Values: 'starts', 'contains', 'ends')") 111 | else: 112 | parameters["type"] = search_type 113 | 114 | if query: 115 | if not isinstance(query, str): 116 | raise ValueError("Query for searching needs to be a str (Examples: 'JOHN', '555', '123ABC')") 117 | else: 118 | parameters["query"] = query 119 | 120 | return self._voipms_client._get(method, parameters) 121 | 122 | def toll_free_usa(self, search_type=None, query=None): 123 | """ 124 | Searches for USA Toll Free Numbers using a Search Criteria 125 | 126 | - Shows all USA Toll Free Numbers available if no criteria is provided. 127 | 128 | :param search_type: Type of search (Values: 'starts', 'contains', 'ends') 129 | :type search_type: :py:class:`str` 130 | :param query: Query for searching (Examples: 'JOHN', '555', '123ABC') 131 | :type query: :py:class:`str` 132 | 133 | :returns: :py:class:`dict` 134 | """ 135 | method = "searchTollFreeUSA" 136 | 137 | parameters = {} 138 | 139 | if search_type: 140 | if not isinstance(search_type, str): 141 | raise ValueError("Type of search needs to be a str (Values: 'starts', 'contains', 'ends')") 142 | else: 143 | parameters["type"] = search_type 144 | 145 | if query: 146 | if not isinstance(query, str): 147 | raise ValueError("Query for searching needs to be a str (Examples: 'JOHN', '555', '123ABC')") 148 | else: 149 | parameters["query"] = query 150 | 151 | return self._voipms_client._get(method, parameters) 152 | 153 | def vanity(self, search_type, query): 154 | """ 155 | Searches for USA DIDs by State using a Search Criteria 156 | 157 | :param search_type: [Required] Type of Vanity Number (Values: '8**', '800', '855', '866', '877', '888') 158 | :type search_type: :py:class:`str` 159 | :param query: [Required] Query for searching : 7 Chars (Examples: '***JHON', '**555**', '**HELLO') 160 | :type query: :py:class:`str` 161 | 162 | :returns: :py:class:`dict` 163 | """ 164 | method = "searchVanity" 165 | 166 | if not isinstance(search_type, str): 167 | raise ValueError("Type of Vanity Number needs to be a str (Values: '8**', '800', '855', '866', '877', '888')") 168 | 169 | if not isinstance(query, str): 170 | raise ValueError("Query for searching : 7 Chars needs to be a str (Examples: '***JHON', '**555**', '**HELLO')") 171 | 172 | parameters = { 173 | "type": search_type, 174 | "query": query 175 | } 176 | 177 | return self._voipms_client._get(method, parameters) 178 | -------------------------------------------------------------------------------- /voipms/entities/voicemailset.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Voicemail API endpoint set 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import validate_email, convert_bool 9 | 10 | 11 | class VoicemailSet(BaseApi): 12 | """ 13 | Set for the Voicemail endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(VoicemailSet, self).__init__(*args, **kwargs) 20 | self.endpoint = 'voicemail' 21 | 22 | def voicemail(self, mailbox, name, password, skip_password, attach_message, delete_message, 23 | say_time, timezone, say_callerid, play_instructions, language, **kwargs): 24 | """ 25 | Updates the information from a specific Voicemail 26 | 27 | :param mailbox: [Required] ID for a specific Mailbox (Example: 1001) 28 | :type mailbox: :py:class:`int` 29 | :param name: [Required] Name for the Mailbox 30 | :type name: :py:class:`str` 31 | :param password: [Required] Password for the Mailbox 32 | :type password: :py:class:`int` 33 | :param skip_password: [Required] True if Skipping Password (True/False) 34 | :type skip_password: :py:class:`bool` 35 | :param attach_message: [Required] Yes for Attaching WAV files to Message (Values: 'yes'/'no') 36 | :type attach_message: :py:class:`str` 37 | :param delete_message: [Required] Yes for Deleting Messages (Values: 'yes'/'no') 38 | :type delete_message: :py:class:`str` 39 | :param say_time: [Required] Yes for Saying Time Stamp (Values: 'yes'/'no') 40 | :type say_time: :py:class:`str` 41 | :param timezone: [Required] Time Zone for Mailbox (Values from voicemail.get_time_zones) 42 | :type timezone: :py:class:`str` 43 | :param say_callerid: [Required] Yes for Saying the Caller ID (Values: 'yes'/'no') 44 | :type say_callerid: :py:class:`str` 45 | :param play_instructions: [Required] Code for Play Instructions Setting (Values from voicemail.get_play_instructions) 46 | :type play_instructions: :py:class:`str` 47 | :param language: [Required] Code for Language (Values from general.get_languages) 48 | :type language: :py:class:`str` 49 | 50 | :param email: Client's e-mail address for receiving Messages 51 | :type email: :py:class:`str` 52 | :param email_attachment_format: Code for Email Attachment format (Values from voicemail.get_voicemail_attachment_formats) 53 | :type email_attachment_format: :py:class:`str` 54 | :param unavailable_message_recording: Recording for the Unavailable Message (values from dids.get_recordings) 55 | :type unavailable_message_recording: :py:class:`int` 56 | 57 | :returns: :py:class:`dict` 58 | """ 59 | method = "setVoicemail" 60 | 61 | if not isinstance(mailbox, int): 62 | raise ValueError("ID for a specific Mailbox needs to be an int (Example: 1001)") 63 | 64 | if not isinstance(name, str): 65 | raise ValueError("Name for the Mailbox needs to be a str") 66 | 67 | if not isinstance(password, int): 68 | raise ValueError("Password for the Mailbox needs to be an int") 69 | 70 | if not isinstance(skip_password, bool): 71 | raise ValueError("True if Skipping Password needs to be a bool (True/False)") 72 | 73 | if not isinstance(attach_message, str): 74 | raise ValueError("Yes for Attaching WAV files to Message needs to be a str (Values: 'yes'/'no')") 75 | elif attach_message not in ("yes", "no"): 76 | raise ValueError("Attaching WAV files to Message only allows values: 'yes'/'no'") 77 | 78 | if not isinstance(delete_message, str): 79 | raise ValueError("Yes for Deleting Messages needs to be a str (Values: 'yes'/'no')") 80 | elif delete_message not in ("yes", "no"): 81 | raise ValueError("Deleting Messages only allows values: 'yes'/'no'") 82 | 83 | if not isinstance(say_time, str): 84 | raise ValueError("Yes for Saying Time Stamp needs to be a str (Values: 'yes'/'no')") 85 | elif say_time not in ("yes", "no"): 86 | raise ValueError("Saying Time Stamp only allows values: 'yes'/'no'") 87 | 88 | if not isinstance(timezone, str): 89 | raise ValueError("Time Zone for Mailbox needs to be a str (Values from voicemail.get_time_zones)") 90 | 91 | if not isinstance(say_callerid, str): 92 | raise ValueError("Yes for Saying the Caller ID needs to be a str (Values: 'yes'/'no')") 93 | elif say_callerid not in ("yes", "no"): 94 | raise ValueError("Saying the Caller ID only allows values: 'yes'/'no'") 95 | 96 | if not isinstance(play_instructions, str): 97 | raise ValueError("Code for Play Instructions Setting needs to be a str (Values from voicemail.get_play_instructions)") 98 | 99 | if not isinstance(language, str): 100 | raise ValueError("Code for Language needs to be a str (Values from general.get_languages)") 101 | 102 | parameters = { 103 | "mailbox": mailbox, 104 | "name": name, 105 | "password": password, 106 | "skip_password": convert_bool(skip_password), 107 | "attach_message": attach_message, 108 | "attach_message": attach_message, 109 | "delete_message": delete_message, 110 | "say_time": say_time, 111 | "timezone": timezone, 112 | "say_callerid": say_callerid, 113 | "play_instructions": play_instructions, 114 | "language": language, 115 | } 116 | 117 | if "email" in kwargs: 118 | email = kwargs.pop("email") 119 | if not isinstance(email, str): 120 | raise ValueError("Client's e-mail address for receiving Messages needs to be a str") 121 | elif not validate_email(email): 122 | raise ValueError("Client's e-mail address is not a correct email syntax") 123 | parameters["email"] = email 124 | 125 | if "email_attachment_format" in kwargs: 126 | if not isinstance(kwargs["email_attachment_format"], str): 127 | raise ValueError("Code for Email Attachment format needs to be a str (Values from voicemail.get_voicemail_attachment_formats)") 128 | parameters["email_attachment_format"] = kwargs.pop("email_attachment_format") 129 | 130 | if "unavailable_message_recording" in kwargs: 131 | if not isinstance(kwargs["unavailable_message_recording"], int): 132 | raise ValueError("Recording for the Unavailable Message needs to be an int (values from dids.get_recordings)") 133 | parameters["unavailable_message_recording"] = kwargs.pop("unavailable_message_recording") 134 | 135 | if len(kwargs) > 0: 136 | not_allowed_parameters = "" 137 | for key, value in kwargs.items(): 138 | not_allowed_parameters += key + " " 139 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 140 | 141 | return self._voipms_client._get(method, parameters) 142 | -------------------------------------------------------------------------------- /voipms/entities/voicemailcreate.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Voicemail API endpoint create 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import validate_email, convert_bool 9 | 10 | 11 | class VoicemailCreate(BaseApi): 12 | """ 13 | Create for the Voicemail endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(VoicemailCreate, self).__init__(*args, **kwargs) 20 | self.endpoint = 'voicemail' 21 | 22 | def voicemail(self, digits, name, password, skip_password, attach_message, delete_message, 23 | say_time, timezone, say_callerid, play_instructions, language, **kwargs): 24 | """ 25 | Adds a new Voicemail entry to your Account 26 | 27 | :param digits: [Required] Digits used to create the voicemail (Example: 01) Minimum 1 digit, maximum 10 digits 28 | :type digits: :py:class:`int` 29 | :param name: [Required] Name for the Mailbox 30 | :type name: :py:class:`str` 31 | :param password: [Required] Password for the Mailbox 32 | :type password: :py:class:`int` 33 | :param skip_password: [Required] True if Skipping Password (True/False) 34 | :type skip_password: :py:class:`bool` 35 | :param attach_message: [Required] Yes for Attaching WAV files to Message (Values: 'yes'/'no') 36 | :type attach_message: :py:class:`str` 37 | :param delete_message: [Required] Yes for Deleting Messages (Values: 'yes'/'no') 38 | :type delete_message: :py:class:`str` 39 | :param say_time: [Required] Yes for Saying Time Stamp (Values: 'yes'/'no') 40 | :type say_time: :py:class:`str` 41 | :param timezone: [Required] Time Zone for Mailbox (Values from voicemail.get_time_zones) 42 | :type timezone: :py:class:`str` 43 | :param say_callerid: [Required] Yes for Saying the Caller ID (Values: 'yes'/'no') 44 | :type say_callerid: :py:class:`str` 45 | :param play_instructions: [Required] Code for Play Instructions Setting (Values from voicemail.get_play_instructions) 46 | :type play_instructions: :py:class:`str` 47 | :param language: [Required] Code for Language (Values from general.get_languages) 48 | :type language: :py:class:`str` 49 | 50 | :param email: Client's e-mail address for receiving Messages 51 | :type email: :py:class:`str` 52 | :param email_attachment_format: Code for Email Attachment format (Values from voicemail.get_voicemail_attachment_formats) 53 | :type email_attachment_format: :py:class:`str` 54 | :param unavailable_message_recording: Recording for the Unavailable Message (values from dids.get_recordings) 55 | :type unavailable_message_recording: :py:class:`int` 56 | 57 | :returns: :py:class:`dict` 58 | """ 59 | method = "createVoicemail" 60 | 61 | if not isinstance(digits, int): 62 | raise ValueError("Digits used to create the voicemail needs to be an int (Example: 01) Minimum 1 digit, maximum 10 digits") 63 | elif len(str(digits)) > 10: 64 | raise ValueError("Digits used to create the voicemail can only have a maximum of 10 digits") 65 | 66 | if not isinstance(name, str): 67 | raise ValueError("Name for the Mailbox needs to be a str") 68 | 69 | if not isinstance(password, int): 70 | raise ValueError("Password for the Mailbox needs to be an int") 71 | 72 | if not isinstance(skip_password, bool): 73 | raise ValueError("True if Skipping Password needs to be a bool (True/False)") 74 | 75 | if not isinstance(attach_message, str): 76 | raise ValueError("Yes for Attaching WAV files to Message needs to be a str (Values: 'yes'/'no')") 77 | elif attach_message not in ("yes", "no"): 78 | raise ValueError("Attaching WAV files to Message only allows values: 'yes'/'no'") 79 | 80 | if not isinstance(delete_message, str): 81 | raise ValueError("Yes for Deleting Messages needs to be a str (Values: 'yes'/'no')") 82 | elif delete_message not in ("yes", "no"): 83 | raise ValueError("Deleting Messages only allows values: 'yes'/'no'") 84 | 85 | if not isinstance(say_time, str): 86 | raise ValueError("Yes for Saying Time Stamp needs to be a str (Values: 'yes'/'no')") 87 | elif say_time not in ("yes", "no"): 88 | raise ValueError("Saying Time Stamp only allows values: 'yes'/'no'") 89 | 90 | if not isinstance(timezone, str): 91 | raise ValueError("Time Zone for Mailbox needs to be a str (Values from voicemail.get_time_zones)") 92 | 93 | if not isinstance(say_callerid, str): 94 | raise ValueError("Yes for Saying the Caller ID needs to be a str (Values: 'yes'/'no')") 95 | elif say_callerid not in ("yes", "no"): 96 | raise ValueError("Saying the Caller ID only allows values: 'yes'/'no'") 97 | 98 | if not isinstance(play_instructions, str): 99 | raise ValueError("Code for Play Instructions Setting needs to be a str (Values from voicemail.get_play_instructions)") 100 | 101 | if not isinstance(language, str): 102 | raise ValueError("Code for Language needs to be a str (Values from general.get_languages)") 103 | 104 | parameters = { 105 | "digits": digits, 106 | "name": name, 107 | "password": password, 108 | "skip_password": convert_bool(skip_password), 109 | "attach_message": attach_message, 110 | "attach_message": attach_message, 111 | "delete_message": delete_message, 112 | "say_time": say_time, 113 | "timezone": timezone, 114 | "say_callerid": say_callerid, 115 | "play_instructions": play_instructions, 116 | "language": language, 117 | } 118 | 119 | if "email" in kwargs: 120 | email = kwargs.pop("email") 121 | if not isinstance(email, str): 122 | raise ValueError("Client's e-mail address for receiving Messages needs to be a str") 123 | elif not validate_email(email): 124 | raise ValueError("Client's e-mail address is not a correct email syntax") 125 | parameters["email"] = email 126 | 127 | if "email_attachment_format" in kwargs: 128 | if not isinstance(kwargs["email_attachment_format"], str): 129 | raise ValueError("Code for Email Attachment format needs to be a str (Values from voicemail.get_voicemail_attachment_formats)") 130 | parameters["email_attachment_format"] = kwargs.pop("email_attachment_format") 131 | 132 | if "unavailable_message_recording" in kwargs: 133 | if not isinstance(kwargs["unavailable_message_recording"], int): 134 | raise ValueError("Recording for the Unavailable Message needs to be an int (values from dids.get_recordings)") 135 | parameters["unavailable_message_recording"] = kwargs.pop("unavailable_message_recording") 136 | 137 | if len(kwargs) > 0: 138 | not_allowed_parameters = "" 139 | for key, value in kwargs.items(): 140 | not_allowed_parameters += key + " " 141 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 142 | 143 | return self._voipms_client._get(method, parameters) 144 | -------------------------------------------------------------------------------- /voipms/entities/voicemailget.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Voicemail API endpoint get 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import validate_date 9 | 10 | 11 | class VoicemailGet(BaseApi): 12 | """ 13 | Get for the Voicemail endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(VoicemailGet, self).__init__(*args, **kwargs) 20 | self.endpoint = 'voicemail' 21 | 22 | def play_instructions(self, play_instructions=None): 23 | """ 24 | Retrieves a list of Play Instructions modes if no additional parameter is provided 25 | 26 | - Retrieves a specific Play Instructions mode if a play code is provided 27 | 28 | :param play_instructions: Code for a specific Play Instructions setting (Example: 'u') 29 | :type play_instructions: :py:class:`str` 30 | 31 | :returns: :py:class:`dict` 32 | """ 33 | method = "getPlayInstructions" 34 | 35 | parameters = { 36 | } 37 | 38 | if play_instructions: 39 | if not isinstance(play_instructions, str): 40 | raise ValueError("Code for a specific Play Instructions setting needs to be a str (Example: 'u')") 41 | else: 42 | parameters["play_instructions"] = play_instructions 43 | 44 | return self._voipms_client._get(method, parameters) 45 | 46 | def timezones(self, timezone=None): 47 | """ 48 | Retrieves a list of Timezones if no additional parameter is provided 49 | 50 | - Retrieves a specific Timezone if a timezone code is provided 51 | 52 | :param timezone: Code for a specific Time Zone (Example: 'America/Buenos_Aires') 53 | :type timezone: :py:class:`str` 54 | 55 | :returns: :py:class:`dict` 56 | """ 57 | method = "getTimezones" 58 | 59 | parameters = { 60 | } 61 | 62 | if timezone: 63 | if not isinstance(timezone, str): 64 | raise ValueError("Code for a specific Time Zone needs to be a str (Example: 'America/Buenos_Aires')") 65 | else: 66 | parameters["timezone"] = timezone 67 | 68 | return self._voipms_client._get(method, parameters) 69 | 70 | def voicemails(self, mailbox=None): 71 | """ 72 | Retrieves a list of Voicemails if no additional parameter is provided 73 | 74 | - Retrieves a specific Voicemail if a voicemail code is provided 75 | 76 | :param mailbox: ID for specific Mailbox (Example: 1001) 77 | :type mailbox: :py:class:`int` 78 | 79 | :returns: :py:class:`dict` 80 | """ 81 | method = "getVoicemails" 82 | 83 | parameters = { 84 | } 85 | 86 | if mailbox: 87 | if not isinstance(mailbox, int): 88 | raise ValueError("ID for specific Mailbox needs to be an int (Example: 1001)") 89 | else: 90 | parameters["mailbox"] = mailbox 91 | 92 | return self._voipms_client._get(method, parameters) 93 | 94 | def voicemail_folders(self, folder=None): 95 | """ 96 | Retrieves a list of your Voicemail Folders if no additional parameter is provided 97 | 98 | - Retrieves a specific Folder if a folder name is provided 99 | 100 | :param folder: Folder Name (Example: 'INBOX') 101 | :type folder: :py:class:`str` 102 | 103 | :returns: :py:class:`dict` 104 | """ 105 | method = "getVoicemailFolders" 106 | 107 | parameters = { 108 | } 109 | 110 | if folder: 111 | if not isinstance(folder, str): 112 | raise ValueError("Folder Name needs to be a str (Example: 'INBOX')") 113 | else: 114 | parameters["folder"] = folder 115 | 116 | return self._voipms_client._get(method, parameters) 117 | 118 | def voicemail_message_file(self, mailbox, folder, message_num): 119 | """ 120 | Retrieves a specific Voicemail Message File in Base64 format 121 | 122 | :param mailbox: [Required] ID for a specific Mailbox (Example: 1001) 123 | :type mailbox: :py:class:`int` 124 | :param folder: [required] Name for specific Folder (Required if message id is passed, Example: 'INBOX', values from: voicemail.voicemail_folders) 125 | :type folder: :py:class:`str` 126 | :param message_num: [required] ID for specific Voicemail Message (Required if folder is passed, Example: 1) 127 | :type message_num: :py:class:`int` 128 | 129 | :returns: :py:class:`dict` 130 | """ 131 | method = "getVoicemailMessageFile" 132 | 133 | if not isinstance(mailbox, int): 134 | raise ValueError("ID for a specific Mailbox needs to be an int (Example: 1001)") 135 | 136 | if not isinstance(folder, str): 137 | raise ValueError("Name for specific Folder needs to be a str (Required if message id is passed, Example: 'INBOX', values from: voicemail.voicemail_folders)") 138 | 139 | if not isinstance(message_num, int): 140 | raise ValueError("ID for specific Voicemail Message needs to be an int (Required if folder is passed, Example: 1)") 141 | 142 | parameters = { 143 | "mailbox": mailbox, 144 | "folder": folder, 145 | "message_num": message_num, 146 | } 147 | 148 | return self._voipms_client._get(method, parameters) 149 | 150 | def voicemail_messages(self, mailbox, **kwargs): 151 | """ 152 | Retrieves a list of Voicemail Messages if mailbox parameter is provided 153 | 154 | - Retrieves a list of Voicemail Messages in a Folder if a folder is provided 155 | - Retrieves a list of Voicemail Messages in a date range if a from and to are provided 156 | 157 | :param mailbox: [Required] ID for a specific vpri (Example: 1001) 158 | :type mailbox: :py:class:`int` 159 | :returns: :py:class:`dict` 160 | """ 161 | method = "getVPRIs" 162 | 163 | if not isinstance(mailbox, int): 164 | raise ValueError("") 165 | 166 | parameters = { 167 | "mailbox": mailbox, 168 | } 169 | 170 | return self._voipms_client._get(method, parameters) 171 | 172 | def vpris(self, vpri): 173 | """ 174 | Retrieves a list of vpri 175 | 176 | :param vpri: [Required] ID for a specific Mailbox (Example: 1001) 177 | :type vpri: :py:class:`int` 178 | 179 | :param folder: Name for specific Folder (Required if message id is passed, Example: 'INBOX', values from: voicemail.voicemail_folders) 180 | :type folder: :py:class:`str` 181 | :param date_from: Start Date for Filtering Voicemail Messages (Example: '2016-01-30') 182 | :type date_from: :py:class:`str` 183 | :param date_to: End Date for Filtering Voicemail Messages (Example: '2016-01-30') 184 | :type date_to: :py:class:`str` 185 | 186 | :returns: :py:class:`dict` 187 | """ 188 | method = "getVoicemailMessages" 189 | 190 | if not isinstance(vpri, int): 191 | raise ValueError("ID for a specific Mailbox needs to be an int (Example: 1001)") 192 | 193 | parameters = { 194 | "vpri": vpri, 195 | } 196 | 197 | if "folder" in kwargs: 198 | if not isinstance(kwargs["folder"], str): 199 | raise ValueError("Name for specific Folder needs to be a str (Required if message id is passed, Example: 'INBOX', values from: voicemail.voicemail_folders)") 200 | parameters["folder"] = kwargs.pop("folder") 201 | 202 | if "date_from" in kwargs: 203 | if not isinstance(kwargs["date_from"], str): 204 | raise ValueError("Start Date for Filtering Voicemail Messages needs to be a str (Example: '2014-03-30')") 205 | validate_date(kwargs["date_from"]) 206 | parameters["date_from"] = kwargs.pop("date_from") 207 | 208 | if "date_to" in kwargs: 209 | if not isinstance(kwargs["date_to"], str): 210 | raise ValueError("End Date for Filtering Voicemail Messages needs to be a str (Example: '2014-03-30')") 211 | validate_date(kwargs["date_to"]) 212 | parameters["date_to"] = kwargs.pop("date_to") 213 | 214 | if len(kwargs) > 0: 215 | not_allowed_parameters = "" 216 | for key, value in kwargs.items(): 217 | not_allowed_parameters += key + " " 218 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 219 | 220 | return self._voipms_client._get(method, parameters) 221 | -------------------------------------------------------------------------------- /voipms/entities/didsback_order.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Dids API endpoint back_order 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import order 9 | 10 | 11 | class DidsBackOrder(BaseApi): 12 | """ 13 | BackOrder for the Dids endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(DidsBackOrder, self).__init__(*args, **kwargs) 20 | self.endpoint = 'dids' 21 | 22 | def back_order_did_can(self, quantity, province, ratecenter, routing, pop, dialtime, cnam, billing_type, **kwargs): 23 | """ 24 | Backorder DID (USA) from a specific ratecenter and state 25 | 26 | :param quantity: [Required] Number of DIDs to be Ordered (Example: 3) 27 | :type quantity: :py:class:`int` 28 | :param province: [Required] Canadian Province (values from dids.get_provinces) 29 | :type province: :py:class:`str` 30 | :param ratecenter: [Required] Canadian Ratecenter (Values from dids.get_rate_centers_can) 31 | :type ratecenter: :py:class:`str` 32 | :param routing: [Required] Main Routing for the DID 33 | :type routing: :py:class:`str` 34 | :param pop: [Required] Point of Presence for the DID (Example: 5) 35 | :type pop: :py:class:`int` 36 | :param dialtime: [Required] Dial Time Out for the DID (Example: 60 -> in seconds) 37 | :type dialtime: :py:class:`int` 38 | :param cnam: [Required] CNAM for the DID (Boolean: True/False) 39 | :type cnam: :py:class:`bool` 40 | :param billing_type: [Required] Billing type for the DID (1 = Per Minute, 2 = Flat) 41 | :type billing_type: :py:class:`int` 42 | :param **kwargs: All optional parameters 43 | :type **kwargs: :py:class:`dict` 44 | 45 | :param failover_busy: Busy Routing for the DID 46 | :type failover_busy: :py:class:`str` 47 | :param failover_unreachable: Unreachable Routing for the DID 48 | :type failover_unreachable: :py:class:`str` 49 | :param failover_noanswer: NoAnswer Routing for the DID 50 | :type failover_noanswer: :py:class:`str` 51 | :param voicemail: Voicemail for the DID (Example: 101) 52 | :type voicemail: :py:class:`int` 53 | :param callerid_prefix: Caller ID Prefix for the DID 54 | :type callerid_prefix: :py:class:`str` 55 | :param note: Note for the DID 56 | :type note: :py:class:`str` 57 | :param test: Set to True if testing how Orders work 58 | - Orders can not be undone 59 | - When testing, no Orders are made 60 | :type test: :py:class:`bool` 61 | 62 | :returns: :py:class:`dict` 63 | 64 | routing, failover_busy, failover_unreachable and failover_noanswer 65 | can receive values in the following format => header:record_id 66 | Where header could be: account, fwd, vm, sip, grp, ivr, sys, recording, queue, cb, tc, disa, none. 67 | Examples: 68 | 69 | account Used for routing calls to Sub Accounts 70 | You can get all sub accounts using the accounts.get_sub_accounts function 71 | 72 | fwd Used for routing calls to Forwarding entries. 73 | You can get the ID right after creating a Forwarding with setForwarding 74 | or by requesting all forwardings entries with getForwardings. 75 | 76 | vm Used for routing calls to a Voicemail. 77 | You can get all voicemails and their IDs using the voicemail.get_voicemails function 78 | 79 | sys System Options: 80 | hangup = Hangup the Call 81 | busy = Busy tone 82 | noservice = System Recording: Number not in service 83 | disconnected = System Recording: Number has been disconnected 84 | dtmf = DTMF Test 85 | echo = ECHO Test 86 | 87 | 88 | none Used to route calls to no action 89 | 90 | Examples: 91 | 'account:100001_VoIP' 92 | 'fwd:1026' 93 | 'vm:101' 94 | 'none:' 95 | 'sys:echo' 96 | """ 97 | method = "backOrderDIDCAN" 98 | 99 | kwargs.update({ 100 | "method": method, 101 | "quantity": quantity, 102 | "province": province, 103 | "ratecenter": ratecenter, 104 | "routing": routing, 105 | "pop": pop, 106 | "dialtime": dialtime, 107 | "cnam": cnam, 108 | "billing_type": billing_type, 109 | }) 110 | 111 | return self._voipms_client._get(order(**kwargs)) 112 | 113 | def back_order_did_usa(self, quantity, state, ratecenter, routing, pop, dialtime, cnam, billing_type, **kwargs): 114 | """ 115 | Backorder DID (USA) from a specific ratecenter and state 116 | 117 | :param quantity: [Required] Number of DIDs to be Ordered (Example: 3) 118 | :type quantity: :py:class:`int` 119 | :param state: [Required] USA State (values from dids.get_states) 120 | :type state: :py:class:`str` 121 | :param ratecenter: [Required] USA Ratecenter (Values from dids.get_rate_centers_usa) 122 | :type ratecenter: :py:class:`str` 123 | :param routing: [Required] Main Routing for the DID 124 | :type routing: :py:class:`str` 125 | :param pop: [Required] Point of Presence for the DID (Example: 5) 126 | :type pop: :py:class:`int` 127 | :param dialtime: [Required] Dial Time Out for the DID (Example: 60 -> in seconds) 128 | :type dialtime: :py:class:`int` 129 | :param cnam: [Required] CNAM for the DID (Boolean: True/False) 130 | :type cnam: :py:class:`bool` 131 | :param billing_type: [Required] Billing type for the DID (1 = Per Minute, 2 = Flat) 132 | :type billing_type: :py:class:`int` 133 | :param **kwargs: All optional parameters 134 | :type **kwargs: :py:class:`dict` 135 | 136 | :param failover_busy: Busy Routing for the DID 137 | :type failover_busy: :py:class:`str` 138 | :param failover_unreachable: Unreachable Routing for the DID 139 | :type failover_unreachable: :py:class:`str` 140 | :param failover_noanswer: NoAnswer Routing for the DID 141 | :type failover_noanswer: :py:class:`str` 142 | :param voicemail: Voicemail for the DID (Example: 101) 143 | :type voicemail: :py:class:`int` 144 | :param callerid_prefix: Caller ID Prefix for the DID 145 | :type callerid_prefix: :py:class:`str` 146 | :param note: Note for the DID 147 | :type note: :py:class:`str` 148 | :param test: Set to True if testing how Orders work 149 | - Orders can not be undone 150 | - When testing, no Orders are made 151 | :type test: :py:class:`bool` 152 | 153 | :returns: :py:class:`dict` 154 | 155 | routing, failover_busy, failover_unreachable and failover_noanswer 156 | can receive values in the following format => header:record_id 157 | Where header could be: account, fwd, vm, sip, grp, ivr, sys, recording, queue, cb, tc, disa, none. 158 | Examples: 159 | 160 | account Used for routing calls to Sub Accounts 161 | You can get all sub accounts using the accounts.get_sub_accounts function 162 | 163 | fwd Used for routing calls to Forwarding entries. 164 | You can get the ID right after creating a Forwarding with setForwarding 165 | or by requesting all forwardings entries with getForwardings. 166 | 167 | vm Used for routing calls to a Voicemail. 168 | You can get all voicemails and their IDs using the voicemail.get_voicemails function 169 | 170 | sys System Options: 171 | hangup = Hangup the Call 172 | busy = Busy tone 173 | noservice = System Recording: Number not in service 174 | disconnected = System Recording: Number has been disconnected 175 | dtmf = DTMF Test 176 | echo = ECHO Test 177 | 178 | 179 | none Used to route calls to no action 180 | 181 | Examples: 182 | 'account:100001_VoIP' 183 | 'fwd:1026' 184 | 'vm:101' 185 | 'none:' 186 | 'sys:echo' 187 | """ 188 | method = "backOrderDIDUSA" 189 | 190 | kwargs.update({ 191 | "method": method, 192 | "quantity": quantity, 193 | "state": state, 194 | "ratecenter": ratecenter, 195 | "routing": routing, 196 | "pop": pop, 197 | "dialtime": dialtime, 198 | "cnam": cnam, 199 | "billing_type": billing_type, 200 | }) 201 | 202 | return self._voipms_client._get(order(**kwargs)) 203 | -------------------------------------------------------------------------------- /voipms/entities/clientsadd.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Clients API endpoint add 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import convert_bool, validate_email 9 | 10 | 11 | class ClientsAdd(BaseApi): 12 | """ 13 | Add for the Clients endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(ClientsAdd, self).__init__(*args, **kwargs) 20 | self.endpoint = 'clients' 21 | 22 | def charge(self, client, charge, description=None, test=False): 23 | """ 24 | Adds a Charge to a specific Reseller Client 25 | 26 | :param client: [Required] ID for a specific Reseller Client (Example: 561115) 27 | :type client: :py:class:`int` 28 | :param charge: [Required] Amount of money that will be Debited from the customer (Example: 4.99) 29 | :type charge: :py:class:`float` 30 | :param description: Charge Description 31 | :type description: :py:class:`str` 32 | :param test: Set to true if testing how adding charges works 33 | :type test: :py:class:`str` 34 | :returns: :py:class:`dict` 35 | """ 36 | method = "addCharge" 37 | 38 | if not isinstance(client, int): 39 | raise ValueError("ID for a specific Reseller Client needs to be an int (Example: 561115)") 40 | 41 | if not isinstance(charge, float): 42 | raise ValueError("Amount of money that will be Debited from the customer needs to be a float (Example: 4.99)") 43 | 44 | parameters = { 45 | "client": client, 46 | "charge": charge, 47 | } 48 | 49 | if description: 50 | if not isinstance(description, str): 51 | raise ValueError("Charge Description needs to be a str") 52 | parameters["description"] = description 53 | 54 | if test: 55 | if not isinstance(test, bool): 56 | raise ValueError("Set to True if testing how adding charges works") 57 | parameters["test"] = convert_bool(test) 58 | 59 | return self._voipms_client._get(method, parameters) 60 | 61 | def client(self, firstname, lastname, address, city, state, country, 62 | zip_code, phone_number, email, confirm_email, password, 63 | confirm_password, **kwargs): 64 | """ 65 | Signs a new Reseller Client to your Reseller Account 66 | 67 | :param firstname: [Required] Client's Firstname 68 | :type firstname: :py:class:`str` 69 | :param lastname: [Required] Client's Lastname 70 | :type lastname: :py:class:`str` 71 | :param address: Client's Address 72 | :type address: :py:class:`str` 73 | :param city: Client's City 74 | :type city: :py:class:`str` 75 | :param state: Client's State 76 | :type state: :py:class:`str` 77 | :param country: Client's Country (Values from general.get_countries) 78 | :type country: :py:class:`str` 79 | :param zip_code: Client's Zip Code 80 | :type zip_code: :py:class:`str` 81 | :param phone_number: [Required] Client's Phone Number 82 | :type phone_number: :py:class:`str` 83 | :param email: [Required] Client's e-mail 84 | :type email: :py:class:`str` 85 | :param confirm_email: [Required] Client's Confirmation e-mail 86 | :type confirm_email: :py:class:`str` 87 | :param password: [Required] Client's Password 88 | :type password: :py:class:`str` 89 | :param confirm_password: [Required] Client's Password 90 | :type confirm_password: :py:class:`str` 91 | :param **kwargs: All optional parameters 92 | :type **kwargs: :py:class:`dict` 93 | 94 | :param company: Client's Company 95 | :type company: :py:class:`str` 96 | :param activate: Activates Client (Boolean: True/False) 97 | :type activate: :py:class:`bool` 98 | :param balance_management: Balance Management for Client (Values from clients.get_balance_management) 99 | :type balance_management: :py:class:`str` 100 | 101 | :returns: :py:class:`dict` 102 | """ 103 | method = "signupClient" 104 | 105 | if not isinstance(firstname, str): 106 | raise ValueError("Client's Firstname needs to be a str") 107 | 108 | if not isinstance(lastname, str): 109 | raise ValueError("Client's Lastname needs to be a str") 110 | 111 | if not isinstance(address, str): 112 | raise ValueError("Client's Address needs to be a str") 113 | 114 | if not isinstance(city, str): 115 | raise ValueError("Client's City needs to be a str") 116 | 117 | if not isinstance(state, str): 118 | raise ValueError("Client's State needs to be a str") 119 | 120 | if not isinstance(country, str): 121 | raise ValueError("Client's Country needs to be a str (Values from general.get_countries)") 122 | 123 | if not isinstance(zip_code, str): 124 | raise ValueError("Client's Zip Code needs to be a str") 125 | 126 | if not isinstance(phone_number, str): 127 | raise ValueError("Client's Phone Number needs to be a str") 128 | 129 | if not isinstance(email, str): 130 | raise ValueError("Client's e-mail needs to be a str") 131 | else: 132 | if not validate_email(email): 133 | raise ValueError("Client's e-mail is not a correct email syntax") 134 | 135 | if not isinstance(confirm_email, str): 136 | raise ValueError("Client's Confirmation e-mail needs to be a str") 137 | else: 138 | if not validate_email(confirm_email): 139 | raise ValueError("Client's Confirmation e-mail is not a correct email syntax") 140 | 141 | if email != confirm_email: 142 | raise ValueError("The two provided e-mails do not match") 143 | 144 | if not isinstance(password, str): 145 | raise ValueError("Client's Password needs to be a str") 146 | 147 | if not isinstance(confirm_password, str): 148 | raise ValueError("Client's Confirmation Password needs to be a str") 149 | 150 | if password != confirm_password: 151 | raise ValueError("The two provided passwords do not match") 152 | 153 | parameters = { 154 | "firstname": firstname, 155 | "lastname": lastname, 156 | "address": address, 157 | "city": city, 158 | "state": state, 159 | "country": country, 160 | "zip": zip_code, 161 | "phone_number": phone_number, 162 | "email": email, 163 | "confirm_email": confirm_email, 164 | "password": password, 165 | "confirm_password": confirm_password, 166 | } 167 | 168 | if "activate" in kwargs: 169 | if not isinstance(kwargs["activate"], bool): 170 | raise ValueError("Activates Client needs to be a bool") 171 | parameters["activate"] = convert_bool(kwargs.pop("activate")) 172 | 173 | if "balance_management" in kwargs: 174 | if not isinstance(kwargs["balance_management"], str): 175 | raise ValueError("Balance Management for Client (Values from clients.get_balance_management)") 176 | parameters["balance_management"] = kwargs.pop("balance_management") 177 | 178 | if len(kwargs) > 0: 179 | not_allowed_parameters = "" 180 | for key, value in kwargs.items(): 181 | not_allowed_parameters += key + " " 182 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 183 | 184 | return self._voipms_client._get(method, parameters) 185 | 186 | def payment(self, client, payment, description=None, test=False): 187 | """ 188 | Adds a Payment to a specific Reseller Client 189 | 190 | :param client: [Required] ID for a specific Reseller Client (Example: 561115) 191 | :type client: :py:class:`int` 192 | :param payment: [Required] Amount of money that will be Credited to the customer (Example: 4.99) 193 | :type payment: :py:class:`float` 194 | :param description: Charge Description 195 | :type description: :py:class:`str` 196 | :param test: Set to true if testing how adding charges works 197 | :type test: :py:class:`str` 198 | :returns: :py:class:`dict` 199 | """ 200 | method = "addPayment" 201 | 202 | if not isinstance(client, int): 203 | raise ValueError("ID for a specific Reseller Client needs to be an int (Example: 561115)") 204 | 205 | if not isinstance(payment, float): 206 | raise ValueError("Amount of money that will be Credited to the customer needs to be a float (Example: 4.99)") 207 | 208 | parameters = { 209 | "client": client, 210 | "payment": payment, 211 | } 212 | 213 | if description: 214 | if not isinstance(description, str): 215 | raise ValueError("Charge Description needs to be a str") 216 | parameters["description"] = description 217 | 218 | if test: 219 | if not isinstance(test, bool): 220 | raise ValueError("Set to True if testing how adding charges works") 221 | parameters["test"] = convert_bool(test) 222 | 223 | return self._voipms_client._get(method, parameters) 224 | -------------------------------------------------------------------------------- /voipms/entities/faxget.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Fax API endpoint get 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | from voipms.helpers import validate_date 9 | 10 | 11 | class FaxGet(BaseApi): 12 | """ 13 | Get for the Fax endpoint. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | """ 17 | Initialize the endpoint 18 | """ 19 | super(FaxGet, self).__init__(*args, **kwargs) 20 | self.endpoint = 'fax' 21 | 22 | def backorders(self, backorder_id=None): 23 | """ 24 | Retrieves a list of backorder DIDs if no additional parameter is provided 25 | 26 | - Retrieves a specific backorder DID if a backorder DID code is provided 27 | 28 | :param backorder_id: ID for a specific backorder DID 29 | :type backorder_id: :py:class:`str` 30 | 31 | :returns: :py:class:`dict` 32 | """ 33 | method = "getBackOrders" 34 | 35 | parameters = { 36 | } 37 | 38 | if backorder_id: 39 | if not isinstance(backorder_id, str): 40 | raise ValueError("ID for a specific backorder DID") 41 | else: 42 | parameters["backorder_id"] = backorder_id 43 | 44 | return self._voipms_client._get(method, parameters) 45 | 46 | def fax_provinces(self, province=None): 47 | """ 48 | Retrieves a list of Canadian Fax Provinces if no additional parameter is provided 49 | 50 | - Retrieves a specific Canadian Fax Province if a province code is provided 51 | 52 | :param province: CODE for a specific Province (Example: AB) 53 | :type province: :py:class:`str` 54 | 55 | :returns: :py:class:`dict` 56 | """ 57 | method = "getFaxProvinces" 58 | 59 | parameters = { 60 | } 61 | 62 | if province: 63 | if not isinstance(province, str): 64 | raise ValueError("CODE for a specific Province needs to be a str (Example: AB)") 65 | else: 66 | parameters["province"] = province 67 | 68 | return self._voipms_client._get(method, parameters) 69 | 70 | def fax_states(self, state=None): 71 | """ 72 | Retrieves a list of American Fax States if no additional parameter is provided 73 | 74 | - Retrieves a specific American Fax State if a state code is provided 75 | 76 | :param state: CODE for a specific State (Example: AL) 77 | :type state: :py:class:`str` 78 | 79 | :returns: :py:class:`dict` 80 | """ 81 | method = "getFaxStates" 82 | 83 | parameters = { 84 | } 85 | 86 | if state: 87 | if not isinstance(state, str): 88 | raise ValueError("CODE for a specific State needs to be a str (Example: AL)") 89 | else: 90 | parameters["state"] = state 91 | 92 | return self._voipms_client._get(method, parameters) 93 | 94 | def fax_rate_centers_can(self, province): 95 | """ 96 | Retrieves a list of Canadian Ratecenters by Province 97 | 98 | :param province: [Required] Province two letters code (Example: AB) 99 | :type province: :py:class:`str` 100 | 101 | :returns: :py:class:`dict` 102 | """ 103 | method = "getFaxRateCentersCAN" 104 | 105 | if not isinstance(province, str): 106 | raise ValueError("Province two letters code needs to be a str (Example: AB)") 107 | 108 | parameters = { 109 | "province": province, 110 | } 111 | 112 | return self._voipms_client._get(method, parameters) 113 | 114 | def fax_rate_centers_usa(self, state): 115 | """ 116 | Retrieves a list of USA Ratecenters by State 117 | 118 | :param state: [Required] State two letters code (Example: AL) 119 | :type state: :py:class:`str` 120 | 121 | :returns: :py:class:`dict` 122 | """ 123 | method = "getFaxRateCentersUSA" 124 | 125 | if not isinstance(state, str): 126 | raise ValueError("State two letters code needs to be a str (Example: AL)") 127 | 128 | parameters = { 129 | "state": state, 130 | } 131 | 132 | return self._voipms_client._get(method, parameters) 133 | 134 | def fax_numbers_info(self, did=None): 135 | """ 136 | Retrieves a list of Fax Numbers 137 | 138 | :param did: Fax Number to retrieves the information of a single number, or not send if you want retrieves the information of all your Fax Numbers. 139 | :type did: :py:class:`int` 140 | 141 | :returns: :py:class:`dict` 142 | """ 143 | method = "getFaxNumbersInfo" 144 | 145 | parameters = { 146 | } 147 | 148 | if did: 149 | if not isinstance(did, int): 150 | raise ValueError("Fax Number to retrieves the information of a single number, or not send if you want retrieves the information of all your Fax Numbers needs to be an int") 151 | else: 152 | parameters["did"] = did 153 | 154 | return self._voipms_client._get(method, parameters) 155 | 156 | def fax_numbers_portability(self, did): 157 | """ 158 | Shows if a Fax Number can be ported into our network 159 | 160 | :param did: [Required] DID Number to be ported into our network (Example: 5552341234) 161 | :type did: :py:class:`int` 162 | 163 | :returns: :py:class:`dict` 164 | """ 165 | method = "getFaxNumbersPortability" 166 | 167 | if not isinstance(did, int): 168 | raise ValueError("DID Number to be ported into our network needs to be an int (Example: 5552341234)") 169 | 170 | parameters = { 171 | "did": did, 172 | } 173 | 174 | return self._voipms_client._get(method, parameters) 175 | 176 | def fax_messages(self, **kwargs): 177 | """ 178 | Retrieves a list of Fax Messages 179 | 180 | :param date_from: Start Date for Filtering Fax Messages (Example: '2014-03-30') 181 | - Default value: Today 182 | :type date_from: :py:class:`str` 183 | :param date_to: End Date for Filtering Fax Messages (Example: '2014-03-30') 184 | - Default value: Today 185 | :type date_to: :py:class:`str` 186 | :param folder: Name of specific Fax Folder (Example: SENT) 187 | - Default value: ALL 188 | :type folder: :py:class:`str` 189 | 190 | :returns: :py:class:`dict` 191 | """ 192 | method = "getFaxMessages" 193 | 194 | parameters = { 195 | } 196 | 197 | if "date_from" in kwargs: 198 | if not isinstance(kwargs["date_from"], str): 199 | raise ValueError("Start Date for Filtering Fax Messages needs to be a str (Example: '2014-03-30')") 200 | validate_date(kwargs["date_from"]) 201 | parameters["from"] = kwargs.pop("date_from") 202 | 203 | if "date_to" in kwargs: 204 | if not isinstance(kwargs["date_to"], str): 205 | raise ValueError("End Date for Filtering Fax Messages needs to be a str (Example: '2014-03-30')") 206 | validate_date(kwargs["date_to"]) 207 | parameters["to"] = kwargs.pop("date_to") 208 | 209 | if "folder" in kwargs: 210 | if not isinstance(kwargs["folder"], str): 211 | raise ValueError("Name of specific Fax Folder needs to be a str (Example: SENT)") 212 | parameters["folder"] = kwargs.pop("folder") 213 | 214 | if len(kwargs) > 0: 215 | not_allowed_parameters = "" 216 | for key, value in kwargs.items(): 217 | not_allowed_parameters += key + " " 218 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 219 | 220 | return self._voipms_client._get(method, parameters) 221 | 222 | def fax_message_pdf(self, fax_id): 223 | """ 224 | Retrieves a Base64 code of the Fax Message to create a PDF file 225 | 226 | :param fax_id: [Required] ID of the Fax Message requested (Values from fax.get.fax_messages) 227 | :type fax_id: :py:class:`int` 228 | 229 | :returns: :py:class:`dict` 230 | """ 231 | method = "getFaxMessagePDF" 232 | 233 | if not isinstance(fax_id, int): 234 | raise ValueError("ID of the Fax Message requested needs to be an int (Values from fax.get.fax_messages)") 235 | 236 | parameters = { 237 | "id": fax_id, 238 | } 239 | 240 | return self._voipms_client._get(method, parameters) 241 | 242 | def fax_folders(self): 243 | """ 244 | Retrieves a list of Fax Folders from your account 245 | 246 | :returns: :py:class:`dict` 247 | """ 248 | method = "getFaxFolders" 249 | 250 | parameters = { 251 | } 252 | 253 | return self._voipms_client._get(method, parameters) 254 | 255 | def email_to_fax(self, fax_id=None): 256 | """ 257 | Retrieves a list of "Email to Fax configurations" from your account if no additional parameter is provided 258 | 259 | - Retrieves a specific "Email to Fax configuration" from your account if a ID is provided 260 | 261 | :param fax_id: ID of the "Email to Fax" configuration 262 | :type fax_id: :py:class:`int` 263 | 264 | :returns: :py:class:`dict` 265 | """ 266 | method = "getEmailToFax" 267 | 268 | parameters = { 269 | } 270 | 271 | if fax_id: 272 | if not isinstance(fax_id, int): 273 | raise ValueError("ID of the \"Email to Fax\" configuration needs to be an int") 274 | else: 275 | parameters["id"] = fax_id 276 | 277 | return self._voipms_client._get(method, parameters) 278 | -------------------------------------------------------------------------------- /voipms/entities/accountsset.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Accounts API endpoint set 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | import socket 8 | 9 | from voipms.baseapi import BaseApi 10 | from voipms.helpers import validate_date 11 | 12 | 13 | class AccountsSet(BaseApi): 14 | """ 15 | Set for the Accounts endpoint. 16 | """ 17 | def __init__(self, *args, **kwargs): 18 | """ 19 | Initialize the endpoint 20 | """ 21 | super(AccountsSet, self).__init__(*args, **kwargs) 22 | self.endpoint = 'accounts' 23 | 24 | def sub_account(self, account_id, password, auth_type, device_type, 25 | lock_international, international_route, music_on_hold, 26 | allowed_codecs, dtmf_mode, nat, **kwargs): 27 | """ 28 | Updates Sub Account information 29 | 30 | :param account_id: [Required] Sub Account ID (Example: 10236) 31 | :type account_id: :py:class:`int` 32 | :param password: [Required] Sub Account Password (For Password Authentication) 33 | :type password: :py:class:`str` 34 | :param auth_type: [Required] Authorization Type Code (Values from accounts.get_auth_types) 35 | :type auth_type: :py:class:`int` 36 | :param device_type: [Required] Device Type Code (Values from accounts.get_device_types) 37 | :type device_type: :py:class:`int` 38 | :param lock_international: [Required] Lock International Code (Values from accounts.get_lock_international) 39 | :type lock_international: :py:class:`int` 40 | :param international_route: [Required] Route Code (Values from accounts.get_routes) 41 | :type international_route: :py:class:`int` 42 | :param music_on_hold: [Required] Music on Hold Code (Values from accounts.get_music_on_hold) 43 | :type music_on_hold: :py:class:`str` 44 | :param allowed_codecs: [Required] List of Allowed Codecs (Values from accounts.get_allowed_codecs) 45 | Codecs separated by semicolon (Example: ulaw;g729;gsm) 46 | :type allowed_codecs: :py:class:`str` 47 | :param dtmf_mode: [Required] DTMF Mode Code (Values from accounts.get_dtmf_modes) 48 | :type dtmf_mode: :py:class:`str` 49 | :param nat: [Required] NAT Mode Code (Values from accounts.get_nat) 50 | :type nat: :py:class:`str` 51 | :param **kwargs: All optional parameters 52 | :type **kwargs: :py:class:`dict` 53 | 54 | :param description: Sub Account Description (Example: 'VoIP Account') 55 | :type description: :py:class:`str` 56 | :param ip: Sub Account IP (For IP Authentication) 57 | :type ip: :py:class:`str` 58 | :param callerid_number: Caller ID Override 59 | :type callerid_number: :py:class:`str` 60 | :param canada_routing: Route Code (Values from accounts.get_routes) 61 | :type canada_routing: :py:class:`int` 62 | :param internal_extension: Sub Account Internal Extension (Example: 1 -> Creates 101) 63 | :type internal_extension: :py:class:`int` 64 | :param internal_voicemail: Sub Account Internal Voicemail (Example: 101) 65 | :type internal_voicemail: :py:class:`str` 66 | :param internal_dialtime: Sub Account Internal Dialtime (Example: 60 -> seconds) 67 | :type internal_dialtime: :py:class:`int` 68 | :param reseller_client: Reseller Account ID (Example: 561115) 69 | :type reseller_client: :py:class:`int` 70 | :param reseller_package: Reseller Package (Example: 92364) 71 | :type reseller_package: :py:class:`int` 72 | :param reseller_nextbilling: Reseller Next Billing Date (Example: '2012-12-31') 73 | :type reseller_nextbilling: :py:class:`str` 74 | :param reseller_chargesetup: True if you want to charge Package Setup Fee after Save 75 | :type reseller_chargesetup: :py:class:`bool` 76 | 77 | :returns: :py:class:`dict` 78 | """ 79 | method = "setSubAccount" 80 | 81 | if not isinstance(account_id, int): 82 | raise ValueError("Sub Account ID needs to be an int (Example: 10236)") 83 | 84 | if not isinstance(password, str): 85 | raise ValueError("Sub Account Password needs to be a str (For Password Authentication)") 86 | 87 | if not isinstance(auth_type, int): 88 | raise ValueError("Auth type value needs to be an int (Values from accounts.get_auth_types)") 89 | 90 | if not isinstance(device_type, int): 91 | raise ValueError("Device type value needs to be an int (Values from accounts.get_device_types)") 92 | 93 | if not isinstance(lock_international, int): 94 | raise ValueError("Lock International Code value needs to be an int (Values from accounts.get_lock_international)") 95 | 96 | if not isinstance(international_route, int): 97 | raise ValueError("Route Code value needs to be an int (Values from accounts.get_routes)") 98 | 99 | if not isinstance(music_on_hold, str): 100 | raise ValueError("Music on Hold Code value needs to be str (Values from accounts.get_music_on_hold)") 101 | 102 | if not isinstance(allowed_codecs, str): 103 | raise ValueError("List of Allowed Codecs value needs to be str (Values from accounts.get_allowed_codecs)") 104 | 105 | if not isinstance(dtmf_mode, str): 106 | raise ValueError("DTMF Mode Code (Values from needs to be str accounts.get_dtmf_modes)") 107 | 108 | if not isinstance(nat, str): 109 | raise ValueError("DTMF Mode Code (Values from needs to be str accounts.get_nat)") 110 | 111 | parameters = { 112 | "id": account_id, 113 | "password": password, 114 | "auth_type": auth_type, 115 | "device_type": device_type, 116 | "lock_international": lock_international, 117 | "international_route": international_route, 118 | "music_on_hold": music_on_hold, 119 | "allowed_codecs": allowed_codecs, 120 | "dtmf_mode": dtmf_mode, 121 | "nat": nat, 122 | } 123 | 124 | if "description" in kwargs: 125 | if not isinstance(kwargs["description"], str): 126 | raise ValueError("Sub Account Description needs to be a str (Example: 'VoIP Account')") 127 | parameters["description"] = kwargs.pop("description") 128 | 129 | if "ip" in kwargs: 130 | ip = kwargs["ip"] 131 | if not isinstance(ip, str): 132 | raise ValueError("Sub Account IP needs to be a str (For IP Authentication)") 133 | try: 134 | socket.inet_aton(ip) 135 | except socket.error: 136 | raise ValueError("The provided IP: {} is not in the correct format (Example: 127.0.0.1)".format(ip)) 137 | parameters["ip"] = kwargs.pop("ip") 138 | 139 | if "callerid_number" in kwargs: 140 | if not isinstance(kwargs["callerid_number"], str): 141 | raise ValueError("Caller ID Override needs to be a str") 142 | parameters["callerid_number"] = kwargs.pop("callerid_number") 143 | 144 | if "canada_routing" in kwargs: 145 | if not isinstance(kwargs["canada_routing"], int): 146 | raise ValueError("Route Code needs to be an int (Values from accounts.get_routes)") 147 | parameters["canada_routing"] = kwargs.pop("canada_routing") 148 | 149 | if "internal_extension" in kwargs: 150 | if not isinstance(kwargs["internal_extension"], int): 151 | raise ValueError("Sub Account Internal Extension needs to be an int (Example: 1 -> Creates 101)") 152 | parameters["internal_extension"] = kwargs.pop("internal_extension") 153 | 154 | if "internal_voicemail" in kwargs: 155 | if not isinstance(kwargs["internal_voicemail"], int): 156 | raise ValueError("Sub Account Internal Voicemail needs to be an int (Example: 101)") 157 | parameters["internal_voicemail"] = kwargs.pop("internal_voicemail") 158 | 159 | if "internal_dialtime" in kwargs: 160 | if not isinstance(kwargs["internal_dialtime"], int): 161 | raise ValueError("Sub Account Internal Dialtime needs to be an int (Example: 60 -> seconds)") 162 | parameters["internal_dialtime"] = kwargs.pop("internal_dialtime") 163 | 164 | if "reseller_client" in kwargs: 165 | if not isinstance(kwargs["reseller_client"], int): 166 | raise ValueError("Reseller Account ID needs to be an int (Example: 561115)") 167 | parameters["reseller_client"] = kwargs.pop("reseller_client") 168 | 169 | if "reseller_package" in kwargs: 170 | if not isinstance(kwargs["reseller_package"], int): 171 | raise ValueError("Reseller Package needs to be an int (Example: 92364)") 172 | parameters["reseller_package"] = kwargs.pop("reseller_package") 173 | 174 | if "reseller_nextbilling" in kwargs: 175 | reseller_nextbilling = kwargs["reseller_nextbilling"] 176 | if not isinstance(reseller_nextbilling, int): 177 | raise ValueError("Reseller Next Billing Date needs to be a string (Example: '2012-12-31')") 178 | validate_date(reseller_nextbilling) 179 | parameters["reseller_nextbilling"] = kwargs.pop("reseller_nextbilling") 180 | 181 | if "reseller_chargesetup" in kwargs: 182 | if not isinstance(kwargs["reseller_chargesetup"], bool): 183 | raise ValueError("True if you want to charge Package Setup Fee after Save") 184 | parameters["reseller_chargesetup"] = kwargs.pop("reseller_chargesetup") 185 | 186 | if len(kwargs) > 0: 187 | not_allowed_parameters = "" 188 | for key, value in kwargs.items(): 189 | not_allowed_parameters += key + " " 190 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 191 | 192 | return self._voipms_client._get(method, parameters) 193 | -------------------------------------------------------------------------------- /voipms/entities/accountscreate.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Accounts API endpoint create 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | import socket 8 | 9 | from voipms.baseapi import BaseApi 10 | from voipms.helpers import validate_date, convert_bool 11 | 12 | 13 | class AccountsCreate(BaseApi): 14 | """ 15 | Create for the Accounts endpoint. 16 | """ 17 | def __init__(self, *args, **kwargs): 18 | """ 19 | Initialize the endpoint 20 | """ 21 | super(AccountsCreate, self).__init__(*args, **kwargs) 22 | self.endpoint = 'accounts' 23 | 24 | def sub_account(self, username, password, protocol, auth_type, device_type, 25 | lock_international, international_route, music_on_hold, 26 | allowed_codecs, dtmf_mode, nat, **kwargs): 27 | """ 28 | Adds a new Sub Account entry to your Account 29 | 30 | :param username: [Required] Username for the Sub Account (Example: 'VoIP') 31 | :type username: :py:class:`str` 32 | :param password: [Required] Sub Account Password (For Password Authentication) 33 | :type password: :py:class:`str` 34 | :param protocol: [Required] Protocol used for the Sub Account (Values from accounts.get_protocols) 35 | :type protocol: :py:class:`int` 36 | :param auth_type: [Required] Authorization Type Code (Values from accounts.get_auth_types) 37 | :type auth_type: :py:class:`int` 38 | :param device_type: [Required] Device Type Code (Values from accounts.get_device_types) 39 | :type device_type: :py:class:`int` 40 | :param lock_international: [Required] Lock International Code (Values from accounts.get_lock_international) 41 | :type lock_international: :py:class:`int` 42 | :param international_route: [Required] Route Code (Values from accounts.get_routes) 43 | :type international_route: :py:class:`int` 44 | :param music_on_hold: [Required] Music on Hold Code (Values from accounts.get_music_on_hold) 45 | :type music_on_hold: :py:class:`str` 46 | :param allowed_codecs: [Required] List of Allowed Codecs (Values from accounts.get_allowed_codecs) 47 | Codecs separated by semicolon (Example: ulaw;g729;gsm) 48 | :type allowed_codecs: :py:class:`str` 49 | :param dtmf_mode: [Required] DTMF Mode Code (Values from accounts.get_dtmf_modes) 50 | :type dtmf_mode: :py:class:`str` 51 | :param nat: [Required] NAT Mode Code (Values from accounts.get_nat) 52 | :type nat: :py:class:`str` 53 | :param **kwargs: All optional parameters 54 | :type **kwargs: :py:class:`dict` 55 | 56 | :param description: Sub Account Description (Example: 'VoIP Account') 57 | :type description: :py:class:`str` 58 | :param ip: Sub Account IP (For IP Authentication) 59 | :type ip: :py:class:`str` 60 | :param callerid_number: Caller ID Override 61 | :type callerid_number: :py:class:`str` 62 | :param canada_routing: Route Code (Values from accounts.get_routes) 63 | :type canada_routing: :py:class:`int` 64 | :param internal_extension: Sub Account Internal Extension (Example: 1 -> Creates 101) 65 | :type internal_extension: :py:class:`int` 66 | :param internal_voicemail: Sub Account Internal Voicemail (Example: 101) 67 | :type internal_voicemail: :py:class:`str` 68 | :param internal_dialtime: Sub Account Internal Dialtime (Example: 60 -> seconds) 69 | :type internal_dialtime: :py:class:`int` 70 | :param reseller_client: Reseller Account ID (Example: 561115) 71 | :type reseller_client: :py:class:`int` 72 | :param reseller_package: Reseller Package (Example: 92364) 73 | :type reseller_package: :py:class:`int` 74 | :param reseller_nextbilling: Reseller Next Billing Date (Example: '2012-12-31') 75 | :type reseller_nextbilling: :py:class:`str` 76 | :param reseller_chargesetup: True if you want to charge Package Setup Fee after Save 77 | :type reseller_chargesetup: :py:class:`bool` 78 | 79 | :returns: :py:class:`dict` 80 | """ 81 | method = "createSubAccount" 82 | 83 | if not isinstance(username, str): 84 | raise ValueError("Username needs to be a str") 85 | 86 | if not isinstance(password, str): 87 | raise ValueError("Sub Account Password needs to be a str (For Password Authentication)") 88 | 89 | if not isinstance(protocol, int): 90 | raise ValueError("Protocol value needs to be an int (Values from accounts.get_protocols)") 91 | 92 | if not isinstance(auth_type, int): 93 | raise ValueError("Auth type value needs to be an int (Values from accounts.get_auth_types)") 94 | 95 | if not isinstance(device_type, int): 96 | raise ValueError("Device type value needs to be an int (Values from accounts.get_device_types)") 97 | 98 | if not isinstance(lock_international, int): 99 | raise ValueError("Lock International Code value needs to be an int (Values from accounts.get_lock_international)") 100 | 101 | if not isinstance(international_route, int): 102 | raise ValueError("Route Code value needs to be an int (Values from accounts.get_routes)") 103 | 104 | if not isinstance(music_on_hold, str): 105 | raise ValueError("Music on Hold Code value needs to be str (Values from accounts.get_music_on_hold)") 106 | 107 | if not isinstance(allowed_codecs, str): 108 | raise ValueError("List of Allowed Codecs value needs to be str (Values from accounts.get_allowed_codecs)") 109 | 110 | if not isinstance(dtmf_mode, str): 111 | raise ValueError("DTMF Mode Code (Values from needs to be str accounts.get_dtmf_modes)") 112 | 113 | if not isinstance(nat, str): 114 | raise ValueError("DTMF Mode Code (Values from needs to be str accounts.get_nat)") 115 | 116 | parameters = { 117 | "username": username, 118 | "password": password, 119 | "protocol": protocol, 120 | "auth_type": auth_type, 121 | "device_type": device_type, 122 | "lock_international": lock_international, 123 | "international_route": international_route, 124 | "music_on_hold": music_on_hold, 125 | "allowed_codecs": allowed_codecs, 126 | "dtmf_mode": dtmf_mode, 127 | "nat": nat, 128 | } 129 | 130 | if "description" in kwargs: 131 | if not isinstance(kwargs["description"], str): 132 | raise ValueError("Sub Account Description needs to be a str (Example: 'VoIP Account')") 133 | parameters["description"] = kwargs.pop("description") 134 | 135 | if "ip" in kwargs: 136 | ip = kwargs["ip"] 137 | if not isinstance(ip, str): 138 | raise ValueError("Sub Account IP needs to be a str (For IP Authentication)") 139 | try: 140 | socket.inet_aton(ip) 141 | except socket.error: 142 | raise ValueError("The provided IP: {} is not in the correct format (Example: 127.0.0.1)".format(ip)) 143 | parameters["ip"] = kwargs.pop("ip") 144 | 145 | if "callerid_number" in kwargs: 146 | if not isinstance(kwargs["callerid_number"], str): 147 | raise ValueError("Caller ID Override needs to be a str") 148 | parameters["callerid_number"] = kwargs.pop("callerid_number") 149 | 150 | if "canada_routing" in kwargs: 151 | if not isinstance(kwargs["canada_routing"], int): 152 | raise ValueError("Route Code needs to be an int (Values from accounts.get_routes)") 153 | parameters["canada_routing"] = kwargs.pop("canada_routing") 154 | 155 | if "internal_extension" in kwargs: 156 | if not isinstance(kwargs["internal_extension"], int): 157 | raise ValueError("Sub Account Internal Extension needs to be an int (Example: 1 -> Creates 101)") 158 | parameters["internal_extension"] = kwargs.pop("internal_extension") 159 | 160 | if "internal_voicemail" in kwargs: 161 | if not isinstance(kwargs["internal_voicemail"], int): 162 | raise ValueError("Sub Account Internal Voicemail needs to be an int (Example: 101)") 163 | parameters["internal_voicemail"] = kwargs.pop("internal_voicemail") 164 | 165 | if "internal_dialtime" in kwargs: 166 | if not isinstance(kwargs["internal_dialtime"], int): 167 | raise ValueError("Sub Account Internal Dialtime needs to be an int (Example: 60 -> seconds)") 168 | parameters["internal_dialtime"] = kwargs.pop("internal_dialtime") 169 | 170 | if "reseller_client" in kwargs: 171 | if not isinstance(kwargs["reseller_client"], int): 172 | raise ValueError("Reseller Account ID needs to be an int (Example: 561115)") 173 | parameters["reseller_client"] = kwargs.pop("reseller_client") 174 | 175 | if "reseller_package" in kwargs: 176 | if not isinstance(kwargs["reseller_package"], int): 177 | raise ValueError("Reseller Package needs to be an int (Example: 92364)") 178 | parameters["reseller_package"] = kwargs.pop("reseller_package") 179 | 180 | if "reseller_nextbilling" in kwargs: 181 | reseller_nextbilling = kwargs.pop("reseller_nextbilling") 182 | if not isinstance(reseller_nextbilling, int): 183 | raise ValueError("Reseller Next Billing Date needs to be a string (Example: '2012-12-31')") 184 | validate_date(reseller_nextbilling) 185 | parameters["reseller_nextbilling"] = reseller_nextbilling 186 | 187 | if "reseller_chargesetup" in kwargs: 188 | if not isinstance(kwargs["reseller_chargesetup"], bool): 189 | raise ValueError("True if you want to charge Package Setup Fee after Save") 190 | parameters["reseller_chargesetup"] = convert_bool(kwargs.pop("reseller_chargesetup")) 191 | 192 | if len(kwargs) > 0: 193 | not_allowed_parameters = "" 194 | for key, value in kwargs.items(): 195 | not_allowed_parameters += key + " " 196 | raise ValueError("Parameters not allowed: {}".format(not_allowed_parameters)) 197 | 198 | return self._voipms_client._get(method, parameters) 199 | -------------------------------------------------------------------------------- /voipms/entities/generalget.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The General API endpoint get 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from datetime import datetime 8 | 9 | from voipms.baseapi import BaseApi 10 | from voipms.helpers import validate_date, convert_bool 11 | 12 | 13 | class GeneralGet(BaseApi): 14 | """ 15 | Get for the General endpoint. 16 | """ 17 | def __init__(self, *args, **kwargs): 18 | """ 19 | Initialize the endpoint 20 | """ 21 | super(GeneralGet, self).__init__(*args, **kwargs) 22 | self.endpoint = 'general' 23 | 24 | def balance(self, advanced=False): 25 | """ 26 | Retrieves Balance for your Account if no additional parameter is provided 27 | 28 | - Retrieves Balance and Calls Statistics for your Account if "advanced" parameter is true 29 | 30 | :param advanced: True for Calls Statistics 31 | :type advanced: :py:class:`bool` 32 | :returns: :py:class:`dict` 33 | """ 34 | method = "getBalance" 35 | 36 | parameters = {} 37 | if advanced: 38 | if not isinstance(advanced, bool): 39 | raise ValueError("To retrieve Balance and Calls Statistics use True") 40 | parameters["advanced"] = convert_bool(advanced) 41 | return self._voipms_client._get(method, parameters) 42 | 43 | def conference(self, conference=None): 44 | """ 45 | Retrieves a list of Conferences if no additional parameter is provided 46 | 47 | - Retrieves a specific Conference if a conference code is provided 48 | 49 | :param conference: Code for a specific Conference (Example: 1599) 50 | :type conference: :py:class:`int` 51 | :returns: :py:class:`dict` 52 | """ 53 | method = "getConference" 54 | 55 | parameters = {} 56 | if conference: 57 | if not isinstance(conference, int): 58 | raise ValueError("Code for a specific Conference (Example: 1599)") 59 | parameters["conference"] = conference 60 | return self._voipms_client._get(method, parameters) 61 | 62 | def conference_members(self, member=None): 63 | """ 64 | Retrieves a list of Member profiles if no additional parameter is provided 65 | 66 | - Retrieves a specific member if a member code is provided 67 | 68 | :param member: Code for a specific Member profile (Example: 1599) 69 | :type member: :py:class:`int` 70 | :returns: :py:class:`dict` 71 | """ 72 | method = "getConferenceMembers" 73 | 74 | parameters = {} 75 | if member: 76 | if not isinstance(member, int): 77 | raise ValueError("Code for a specific Member profile (Example: 1599)") 78 | parameters["member"] = member 79 | return self._voipms_client._get(method, parameters) 80 | 81 | def conference_recordings(self, conference, **kwargs): 82 | """ 83 | Retrieves a list of recordings of a specific conference 84 | 85 | :param conference: [Required] ID for a specific Conference (Example: 5356) 86 | :type conference: :py:class:`int` 87 | :param date_from: Start Date for Filtering Transactions (Example: '2016-06-03') 88 | :type date_from: :py:class:`str` 89 | :param date_to: End Date for Filtering Transactions (Example: '2016-06-04') 90 | :type date_to: :py:class:`str` 91 | :returns: :py:class:`dict` 92 | """ 93 | method = "getConferenceRecordings" 94 | 95 | parameters = {} 96 | 97 | if not isinstance(conference, int): 98 | raise ValueError("[Required] ID for a specific Conference (Example: 5356)") 99 | parameters["conference"] = conference 100 | 101 | if "date_from" in kwargs: 102 | if not isinstance(kwargs["date_from"], str): 103 | raise ValueError("Start Date for Filtering SMSs needs to be a str (Example: '2014-03-30')") 104 | validate_date(kwargs["date_from"]) 105 | parameters["date_from"] = kwargs.pop("date_from") 106 | 107 | if "date_to" in kwargs: 108 | if not isinstance(kwargs["date_to"], str): 109 | raise ValueError("End Date for Filtering SMSs needs to be a str (Example: '2014-03-30')") 110 | validate_date(kwargs["date_to"]) 111 | parameters["date_to"] = kwargs.pop("date_to") 112 | 113 | if parameters.get("date_from", None) != None and parameters.get("date_to", None) != None: 114 | if date_from_object > date_to_object: 115 | raise ValueError("The start date needs to be ealier or the same as the end date.") 116 | if date_to_object > datetime.now(): 117 | raise ValueError("The end date can't be in the future.") 118 | 119 | return self._voipms_client._get(method, parameters) 120 | 121 | def conference_recording_file(self, conference, recording): 122 | """ 123 | Retrieves a specific Recording File data in Base64 format 124 | 125 | :param conference: [Required] ID for a specific Conference (Example: 5356) 126 | :type conference: :py:class:`int` 127 | :param recording: [Required] ID for a specific Conference Recording (Example: 1543338379) 128 | :type recording: :py:class:`int` 129 | :returns: :py:class:`dict` 130 | """ 131 | method = "getConferenceRecordingFile" 132 | 133 | parameters = {} 134 | 135 | if not isinstance(conference, int): 136 | raise ValueError("[Required] ID for a specific Conference (Example: 5356)") 137 | parameters["conference"] = conference 138 | 139 | if not isinstance(recording, int): 140 | raise ValueError("[Required] ID for a specific Conference Recording (Example: 1543338379)") 141 | parameters["recording"] = recording 142 | 143 | return self._voipms_client._get(method, parameters) 144 | 145 | def countries(self, country=None): 146 | """ 147 | Retrieves a list of Countries if no additional parameter is provided 148 | 149 | - Retrieves a specific Country if a country code is provided 150 | 151 | :param country: Code for a specific Country (Example: 'CA') 152 | :type country: :py:class:`str` 153 | :returns: :py:class:`dict` 154 | """ 155 | method = "getCountries" 156 | 157 | parameters = {} 158 | if country: 159 | if not isinstance(country, str): 160 | raise ValueError("Code for a specific Country as string (Example: CA)") 161 | parameters["country"] = country 162 | return self._voipms_client._get(method, parameters) 163 | 164 | def ip(self): 165 | """ 166 | Shows the IP used by the client application requesting information from the API 167 | 168 | - this is the only function not using the IP for authentication. 169 | - the IP returned should be the one used in the API Configuration. 170 | 171 | :returns: :py:class:`dict` 172 | """ 173 | method = "getIP" 174 | return self._voipms_client._get(method) 175 | 176 | def languages(self, language=None): 177 | """ 178 | Retrieves a list of Languages if no additional parameter is provided 179 | 180 | - Retrieves a specific Language if a language code is provided 181 | 182 | :param language: Code for a specific Language (Example: 'en') 183 | :type language: :py:class:`str` 184 | :returns: :py:class:`dict` 185 | """ 186 | method = "getLanguages" 187 | 188 | parameters = {} 189 | if language: 190 | if not isinstance(language, str): 191 | raise ValueError("Code for a specific Language as string (Example: 'en')") 192 | parameters["language"] = language 193 | return self._voipms_client._get(method, parameters) 194 | 195 | def locales(self, locales=None): 196 | """ 197 | Retrieves a list of locale codes if no additional parameter is provided 198 | 199 | - Retrieves a specific locale code if a language code is provided 200 | 201 | :param locale: Code for a specific Locale Code (Example: 'en-US') 202 | :type locale: :py:class:`str` 203 | :returns: :py:class:`dict` 204 | """ 205 | method = "getLocales" 206 | 207 | parameters = {} 208 | if locale: 209 | if not isinstance(locale, str): 210 | raise ValueError("Code for a specific Locale Code (Example: 'en-US')") 211 | parameters["locale"] = locale 212 | return self._voipms_client._get(method, parameters) 213 | 214 | def servers_info(self, server_pop=None): 215 | """ 216 | Retrieves a list of Servers with their info if no additional parameter is provided 217 | 218 | - Retrieves a specific Server with its info if a Server POP is provided. 219 | 220 | :param server_pop: POP for a specific Server (Example: 1). 221 | :type server_pop: :py:class:`int` 222 | :returns: :py:class:`dict` 223 | """ 224 | method = "getServersInfo" 225 | parameters = {} 226 | if server_pop: 227 | if not isinstance(server_pop, int): 228 | raise ValueError("To select a specific server use an integer (Example: 1)") 229 | parameters["server_pop"] = server_pop 230 | return self._voipms_client._get(method, parameters) 231 | 232 | def sequences(self, sequences=None, client=None): 233 | """ 234 | Retrieves a list of Sequences if no Sequence ID is provided 235 | 236 | - Retrieves a specific Sequence if a Sequence ID is provided 237 | 238 | :param sequences: ID for a specific Sequence (Example: 5356) 239 | :type sequences: :py:class:`int` 240 | :param sequences: [Optional] ID for a specific Reseller Client (Example: 561115) 241 | :type sequences: :py:class:`int` 242 | :returns: :py:class:`dict` 243 | """ 244 | method = "getSequences" 245 | 246 | parameters = {} 247 | if sequences: 248 | if not isinstance(sequences, int): 249 | raise ValueError("ID for a specific Sequence (Example: 5356)") 250 | parameters["sequences"] = sequences 251 | 252 | if client: 253 | if not isinstance(client, int): 254 | raise ValueError("[Optional] ID for a specific Reseller Client (Example: 561115)") 255 | parameters["client"] = client 256 | return self._voipms_client._get(method, parameters) 257 | 258 | def transaction_history(self, date_from, date_to): 259 | """ 260 | Retrieves the Transaction History records between two dates 261 | 262 | :param date_from: [Required] Start Date for Filtering Transactions (Example: '2016-06-03') 263 | :type date_from: :py:class:`str` 264 | :param date_to: [Required] End Date for Filtering Transactions (Example: '2016-06-04') 265 | :type date_to: :py:class:`str` 266 | :returns: :py:class:`dict` 267 | """ 268 | method = "getTransactionHistory" 269 | 270 | if not isinstance(date_from, str): 271 | raise ValueError("Start Date for Filtering Transactions needs to be str (Example: '2016-06-03')") 272 | 273 | if not isinstance(date_to, str): 274 | raise ValueError("End Date for Filtering Transactions needs to be str (Example: '2016-06-04')") 275 | 276 | date_from_object = validate_date(date_from) 277 | date_to_object = validate_date(date_to) 278 | if date_from_object > date_to_object: 279 | raise ValueError("The start date needs to be ealier or the same as the end date.") 280 | if date_to_object > datetime.now(): 281 | raise ValueError("The end date can't be in the future.") 282 | 283 | parameters = { 284 | "date_from": date_from, 285 | "date_to": date_to, 286 | } 287 | return self._voipms_client._get(method, parameters) 288 | -------------------------------------------------------------------------------- /voipms/entities/accountsget.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | The Accounts API endpoint get 4 | 5 | Documentation: https://voip.ms/m/apidocs.php 6 | """ 7 | from voipms.baseapi import BaseApi 8 | 9 | 10 | class AccountsGet(BaseApi): 11 | """ 12 | Get for the Accounts endpoint. 13 | """ 14 | def __init__(self, *args, **kwargs): 15 | """ 16 | Initialize the endpoint 17 | """ 18 | super(AccountsGet, self).__init__(*args, **kwargs) 19 | self.endpoint = 'accounts' 20 | 21 | def allowed_codecs(self, codec=None): 22 | """ 23 | Retrieves a list of Allowed Codecs if no additional parameter is provided 24 | 25 | - Retrieves a specific Allowed Codec if a codec code is provided 26 | 27 | :param auth_type: Code for a specific Codec (Example: 'ulaw;g729;gsm') 28 | :type auth_type: :py:class:`str` 29 | :returns: :py:class:`dict` 30 | """ 31 | method = "getAllowedCodecs" 32 | 33 | parameters = {} 34 | if codec: 35 | if not isinstance(codec, str): 36 | raise ValueError("Code for a specific Codec as str (Example: 'ulaw')") 37 | parameters["codec"] = codec 38 | return self._voipms_client._get(method, parameters) 39 | 40 | def auth_types(self, auth_type=None): 41 | """ 42 | Retrieves a list of Authentication Types if no additional parameter is provided 43 | 44 | - Retrieves a specific Authentication Type if an auth type code is provided 45 | 46 | :param auth_type: Code for a specific Authorization Type (Example: 2) 47 | :type auth_type: :py:class:`int` 48 | :returns: :py:class:`dict` 49 | """ 50 | method = "getAuthTypes" 51 | 52 | parameters = {} 53 | if auth_type: 54 | if not isinstance(auth_type, int): 55 | raise ValueError("Code for a specific Authorization Type as int (Example: 2)") 56 | parameters["type"] = auth_type 57 | return self._voipms_client._get(method, parameters) 58 | 59 | def device_types(self, device_type=None): 60 | """ 61 | Retrieves a list of Device Types if no additional parameter is provided 62 | 63 | - Retrieves a specific Device Type if a device type code is provided 64 | 65 | :param device_type: Code for a specific Device Type (Example: 1) 66 | :type device_type: :py:class:`int` 67 | :returns: :py:class:`dict` 68 | """ 69 | method = "getDeviceTypes" 70 | 71 | parameters = {} 72 | if device_type: 73 | if not isinstance(device_type, int): 74 | raise ValueError("Code for a specific Device Type as int (Example: 1)") 75 | parameters["device_type"] = device_type 76 | return self._voipms_client._get(method, parameters) 77 | 78 | def dtmf_modes(self, dtmf_mode=None): 79 | """ 80 | Retrieves a list of DTMF Modes if no additional parameter is provided 81 | 82 | - Retrieves a specific DTMF Mode if a DTMF mode code is provided 83 | 84 | :param dtmf_mode: Code for a specific DTMF Mode (Example: 'inband') 85 | :type dtmf_mode: :py:class:`str` 86 | :returns: :py:class:`dict` 87 | """ 88 | method = "getDTMFModes" 89 | 90 | parameters = {} 91 | if dtmf_mode: 92 | if not isinstance(dtmf_mode, str): 93 | raise ValueError("Code for a specific DTMF Mode as str (Example: 'inband')") 94 | parameters["dtmf_mode"] = dtmf_mode 95 | return self._voipms_client._get(method, parameters) 96 | 97 | def invoice(self, date_from=None, date_to=None, time_range=None, country_type=None): 98 | """ 99 | Retrieves a URL to download the invoice in a PDF file. 100 | 101 | :param date_from: Start Date to generate invoice. (Example: '2020-11-25') 102 | :type date_from: :py:class:`str` 103 | :param date_to: End Date to generate invoice. (Example: '2020-12-25') 104 | :type date_to: :py:class:`str` 105 | :param time_range: Predefined ranges of dates to generate invoice: 106 | 1 = Last Month: 1st day of previous month to last day of previous month 107 | 2 = Last 2 Months: 1st day of the previous 2 months to last day of previous month. 108 | 3 = Last 3 Months: 1st day of the previous 3 months to last day of the previous month. 109 | 4 = Current Month: 1st day of this month until today 110 | 5 = Last Week: Monday of last week to Sunday of last week. 111 | 6 = Current Week: Monday of this week until today. 112 | :type time_range: :py:class:`int` 113 | :param country_type: Type of invoice to be generated, possible values: 0 = US, 1 = CAN 114 | :type country_type: :py:class:`int` 115 | :returns: :py:class:`dict` 116 | """ 117 | method = "getInvoice" 118 | 119 | parameters = {} 120 | 121 | if date_from: 122 | if not isinstance(date_from, str): 123 | raise ValueError("Start Date to generate invoice. (Example: '2020-11-25')") 124 | parameters["from"] = date_from 125 | 126 | if date_to: 127 | if not isinstance(date_to, str): 128 | raise ValueError("End Date to generate invoice. (Example: '2020-12-25')") 129 | parameters["to"] = date_to 130 | 131 | if time_range: 132 | if not isinstance(time_range, str): 133 | raise ValueError("""Predefined ranges of dates to generate invoice: 134 | 1 = Last Month: 1st day of previous month to last day of previous month 135 | 2 = Last 2 Months: 1st day of the previous 2 months to last day of previous month. 136 | 3 = Last 3 Months: 1st day of the previous 3 months to last day of the previous month. 137 | 4 = Current Month: 1st day of this month until today 138 | 5 = Last Week: Monday of last week to Sunday of last week. 139 | 6 = Current Week: Monday of this week until today.""") 140 | parameters["range"] = time_range 141 | 142 | if country_type: 143 | if not isinstance(country_type, str): 144 | raise ValueError("Type of invoice to be generated, possible values: 0 = US, 1 = CAN") 145 | parameters["type"] = country_type 146 | 147 | return self._voipms_client._get(method, parameters) 148 | 149 | def lock_international(self, lock_international=None): 150 | """ 151 | Retrieves a list of Lock Modes if no additional parameter is provided 152 | 153 | - Retrieves a specific Lock Mode if a lock code is provided 154 | 155 | :param lock_international: Code for a specific Lock International Mode (Example: 1) 156 | :type lock_international: :py:class:`int` 157 | :returns: :py:class:`dict` 158 | """ 159 | method = "getLockInternational" 160 | 161 | parameters = {} 162 | if lock_international: 163 | if not isinstance(lock_international, int): 164 | raise ValueError("Code for a specific Lock International Mode as int (Example: 1)") 165 | parameters["lock_international"] = lock_international 166 | return self._voipms_client._get(method, parameters) 167 | 168 | def music_on_hold(self, music_on_hold=None): 169 | """ 170 | Retrieves a list of Music on Hold Options if no additional parameter is provided 171 | 172 | - Retrieves a specific Music on Hold Option if a MOH code is provided 173 | 174 | :param music_on_hold: Code for a specific Music on Hold (Example: 'jazz') 175 | :type music_on_hold: :py:class:`str` 176 | :returns: :py:class:`dict` 177 | """ 178 | method = "getMusicOnHold" 179 | 180 | parameters = {} 181 | if music_on_hold: 182 | if not isinstance(music_on_hold, str): 183 | raise ValueError("Code for a specific Music on Hold as str (Example: 'jazz')") 184 | parameters["music_on_hold"] = music_on_hold 185 | return self._voipms_client._get(method, parameters) 186 | 187 | def nat(self, nat=None): 188 | """ 189 | Retrieves a list of NAT Options if no additional parameter is provided 190 | 191 | - Retrieves a specific NAT Option if a NAT code is provided 192 | 193 | :param nat: Code for a specific NAT Option (Example: 'route') 194 | :type nat: :py:class:`str` 195 | :returns: :py:class:`dict` 196 | """ 197 | method = "getNAT" 198 | 199 | parameters = {} 200 | if nat: 201 | if not isinstance(nat, str): 202 | raise ValueError("Code for a specific NAT Option as str (Example: 'route')") 203 | parameters["nat"] = nat 204 | return self._voipms_client._get(method, parameters) 205 | 206 | def protocols(self, protocol=None): 207 | """ 208 | Retrieves a list of Protocols if no additional parameter is provided 209 | 210 | - Retrieves a specific Protocol if a protocol code is provided 211 | 212 | :param protocol: Code for a specific Protocol (Example: 3) 213 | :type protocol: :py:class:`int` 214 | :returns: :py:class:`dict` 215 | """ 216 | method = "getProtocols" 217 | 218 | parameters = {} 219 | if protocol: 220 | if not isinstance(protocol, int): 221 | raise ValueError("Code for a specific Protocol as int (Example: 3)") 222 | parameters["protocol"] = protocol 223 | return self._voipms_client._get(method, parameters) 224 | 225 | def registration_status(self, account): 226 | """ 227 | Retrieves the Registration Status of a specific account 228 | 229 | :param account: Specific Account (Example: '100001_VoIP') 230 | :type account: :py:class:`str` 231 | :returns: :py:class:`dict` 232 | """ 233 | method = "getRegistrationStatus" 234 | 235 | parameters = {} 236 | if account: 237 | if not isinstance(account, str): 238 | raise ValueError("Specific Account as str (Example: '100001_VoIP')") 239 | parameters["account"] = account 240 | else: 241 | raise ValueError("Specific Account (Example: '100001_VoIP')") 242 | return self._voipms_client._get(method, parameters) 243 | 244 | def report_estimated_hold_time(self, time_type=None): 245 | """ 246 | Retrieves a list of 'ReportEstimateHoldTime' Types if no additional parameter is provided 247 | 248 | - Retrieves a specific 'ReportEstimateHoldTime' Type if a type code is provided 249 | 250 | :param time_type: Code for a specific 'ReportEstimatedHoldTime' Type (Example: 'yes') 251 | :type time_type: :py:class:`str` 252 | :returns: :py:class:`dict` 253 | """ 254 | method = "getReportEstimatedHoldTime" 255 | 256 | parameters = {} 257 | if time_type: 258 | if not isinstance(time_type, str): 259 | raise ValueError("Code for a specific ReportEstimatedHoldTime Type as str (Example: 'yes')") 260 | parameters["type"] = time_type 261 | return self._voipms_client._get(method, parameters) 262 | 263 | def routes(self, route=None): 264 | """ 265 | Retrieves a list of Route Options if no additional parameter is provided 266 | 267 | - Retrieves a specific Route Option if a route code is provided 268 | 269 | :param route: Code for a specific Route (Example: 2) 270 | :type route: :py:class:`int` 271 | :returns: :py:class:`dict` 272 | """ 273 | method = "getRoutes" 274 | 275 | parameters = {} 276 | if route: 277 | if not isinstance(route, int): 278 | raise ValueError("Code for a specific Route as int (Example: 2)") 279 | parameters["route"] = route 280 | return self._voipms_client._get(method, parameters) 281 | 282 | def sub_accounts(self, account=None): 283 | """ 284 | Retrieves all Sub Accounts if no additional parameter is provided 285 | 286 | - Retrieves Reseller Client Accounts if Reseller Client ID is provided 287 | - Retrieves a specific Sub Account if a Sub Account is provided 288 | 289 | :param account: Parameter could have the following values: 290 | * Empty Value [Not Required] 291 | * Specific Sub Account (Example: '100000_VoIP') 292 | * Specific Reseller Client ID (Example: 561115) 293 | :type account: :py:class:`str` 294 | :returns: :py:class:`dict` 295 | """ 296 | method = "getSubAccounts" 297 | 298 | parameters = {} 299 | if account: 300 | if not isinstance(account, str): 301 | raise ValueError("Parameter could have the following values: Empty Value, Specific Sub Account (Example: '100000_VoIP'), Specific Reseller Client ID (Example: 561115)") 302 | parameters["account"] = account 303 | return self._voipms_client._get(method, parameters) 304 | --------------------------------------------------------------------------------