diff --git a/docs/usage/messages.rst b/docs/usage/messages.rst index bc8c1f3..3dc2669 100755 --- a/docs/usage/messages.rst +++ b/docs/usage/messages.rst @@ -2,7 +2,7 @@ SMS Messages ============ -For more information, see the `SMS Message REST Resource `_ documentation. +For more information, see the `SMS Message REST Resource `_ documentation. Sending a Text Message ---------------------- @@ -20,11 +20,33 @@ Send a text message in only a few lines of code. 'From' => '+15555555555', 'Body' => 'Hello!' }; - TwilioSMS message = client.getAccount().getSmsMessages().create(properties); + TwilioMessage message = client.getAccount().getMessages().create(properties); .. note:: The message body must be less than 160 characters in length +Sending a MMS +---------------------- + +Send a MMS in only a few lines of code. + +.. code-block:: javascript + + String ACCOUNT_SID = 'AXXXXXXXXXXXXXXXXX'; + String AUTH_TOKEN = 'YYYYYYYYYYYYYYYYYY'; + TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN); + + List properties = new List(); + properties.add(new TwilioNameValuePair('To','+13216851234')); + properties.add(new TwilioNameValuePair('From','+15555555555')); + properties.add(new TwilioNameValuePair('MediaUrl','https://www.twilio.com/packages/company/img/logos_downloadable_round.png')); + + TwilioMessage message = client.getAccount().getMessages().create(properties); + + +.. note:: The message body must be less than 160 characters in length + + If you want to send a message from a `short code `_ on Twilio, just set :attr:`From` to your short code's number. diff --git a/src/classes/TwilioAccount.cls b/src/classes/TwilioAccount.cls index 2648cdb..aa7576c 100644 --- a/src/classes/TwilioAccount.cls +++ b/src/classes/TwilioAccount.cls @@ -28,541 +28,567 @@ OTHER DEALINGS IN THE SOFTWARE. */ global class TwilioAccount extends TwilioResource.InstanceResource { - /* property keys */ - private static final String DATE_UPDATED_PROPERTY = 'date_updated'; - private static final String DATE_CREATED_PROPERTY = 'date_created'; - private static final String STATUS_PROPERTY = 'status'; - private static final String FRIENDLY_NAME_PROPERTY = 'friendly_name'; - private static final String ACCOUNT_SID_PROPERTY = 'sid'; - private static final String AUTH_TOKEN_PROPERTY = 'auth_token'; - private static final String TYPE_PROPERTY = 'type'; - private static final String OWNER_ACCOUNT_SID_PROPERTY = 'owner_account_sid'; - private static final String CONNECT_APP_SID_PROPERTY = 'connect_app_sid'; - - /* Constructor */ - public TwilioAccount(TwilioRestClient client) { - super(client); - } - - /* Constructor, using predefined set of property values */ - public TwilioAccount(TwilioRestClient client, Map properties) { - super(client, properties); - Object ac = properties.get(ACCOUNT_SID_PROPERTY); - if (ac != null && ac instanceof String) { - String accountSid = (String) ac; - this.setRequestAccountSid(accountSid); - } - } - - /* Sid field accessor */ - public String getSid() { - if (this.getRequestAccountSid() != null) - return this.getRequestAccountSid(); - else - return this.getProperty(ACCOUNT_SID_PROPERTY); - } - - /* Sid field accessor */ - public void setSid(String accountSid) { - this.setRequestAccountSid(accountSid); - this.setProperty(ACCOUNT_SID_PROPERTY, accountSid); - - } - - /** Returns the sid for the ConnectApp using this Account */ - public String getConnectAppSid() { - return this.getProperty(CONNECT_APP_SID_PROPERTY); - } - - /** Returns the AccountSid of the primary account */ - public String getOwnerAccountSid() { - return this.getProperty(OWNER_ACCOUNT_SID_PROPERTY); - } - - /** Returns the API auth token (secret) for this account */ - public String getAuthToken() { - return this.getProperty(AUTH_TOKEN_PROPERTY); - } - - /** Sets the API auth token (secret) for this account */ - public void setAuthToken(String authToken) { - this.setProperty(AUTH_TOKEN_PROPERTY, authToken); - } - - /** Returns the human-readable label for this account */ - public String getFriendlyName() { - return this.getProperty(FRIENDLY_NAME_PROPERTY); - } - - /** Returns the status value for this account */ - public String getStatus() { - return this.getProperty(STATUS_PROPERTY); - } - - /** Returns the date and time this account was created */ - public Datetime getDateCreated() { - return this.getPropertyDatetime(DATE_CREATED_PROPERTY); - } - - /** Returns the date and time this account was last updated */ - public Datetime getDateUpdated() { - return this.getPropertyDatetime(DATE_UPDATED_PROPERTY); - } - - /** Returns the account type */ - public String getType() { - return this.getProperty(TYPE_PROPERTY); - } - - /** Return the Twilio URI for this resource. */ - public String getUri() { - return this.getProperty('uri'); - } - - /** Returns the URIs for resources under this account */ - public Map getSubresourceUris() { - return (Map)this.getObject('subresource_uris'); - } - - /** Constructs a Twilio API resource URI for this Account. Overrides method from TwilioResource. */ - public override String getResourceLocation() { - return '/' + TwilioRestClient.DEFAULT_VERSION + '/Accounts/' - + this.getRequestAccountSid() + '.json'; - } - - - /* SUBRESOURCE METHODS */ - - /* Returns the calls list resource without any filters. - * See http://www.twilio.com/docs/api/rest/call - */ - public TwilioCallList getCalls() { - return this.getCalls(new Map()); - } - - /* Returns the calls list resource with the given filters. - * See http://www.twilio.com/docs/api/rest/call - */ - public TwilioCallList getCalls(Map filters) { - TwilioCallList calls = new TwilioCallList(this.getClient(), filters); - calls.setRequestAccountSid(this.getRequestAccountSid()); - - return calls; - } - - /** Returns a given call instance by sid */ - public TwilioCall getCall(String sid) { - TwilioCall call = new TwilioCall(this.getClient(), sid); - call.setRequestAccountSid(this.getRequestAccountSid()); - return call; - } - - - /** - * Returns the sms message list. - * See http://www.twilio.com/docs/api/rest/sms - */ - public TwilioSmsList getSmsMessages() { - return this.getSmsMessages(new Map()); - } - - /** - * Returns the SMS messages list, applying the supplied filters. - * See http://www.twilio.com/docs/api/rest/sms - */ - public TwilioSmsList getSmsMessages(Map filters) { - TwilioSmsList sms = new TwilioSmsList(this.getClient(), filters); - sms.setRequestAccountSid(this.getRequestAccountSid()); - - return sms; - } - - /** Returns a given SMS message by sid */ - public TwilioSms getSms(String sid) { - TwilioSms sms = new TwilioSms(this.getClient(), sid); - sms.setRequestAccountSid(this.getRequestAccountSid()); - return sms; - } - - /** - * Suspend a subaccount. - * - * @return the account - * @throws TwilioRestException the twilio rest exception - */ - public TwilioAccount suspend() { - Map vars = new Map - { 'Status'=> 'suspended' }; - - TwilioRestResponse response = this.getClient().safeRequest( - this.getResourceLocation(), 'POST', vars); - - TwilioAccount a = new TwilioAccount(this.getClient(), response.toMap()); - a.setRequestAccountSid(this.getRequestAccountSid()); - return a; - } - - /** - * Activate a suspended subaccount. - * - * @return the account - * @throws TwilioRestException the twilio rest exception - */ - public TwilioAccount activate() { - Map vars = new Map - { 'Status'=> 'active' }; - - TwilioRestResponse response = this.getClient().safeRequest( - this.getResourceLocation(), 'POST', vars); - - TwilioAccount a = new TwilioAccount(this.getClient(), response.toMap()); - a.setRequestAccountSid(this.getRequestAccountSid()); - return a; - } - - /** - * Close a subaccount. WARNING: This cannot be undone. - * - * @return the account - * @throws TwilioRestException the twilio rest exception - */ - public TwilioAccount close() { - Map vars = new Map - { 'Status'=> 'closed' }; - - TwilioRestResponse response = this.getClient().safeRequest( - this.getResourceLocation(), 'POST', vars); - - TwilioAccount a = new TwilioAccount(this.getClient(), response.toMap()); - a.setRequestAccountSid(this.getRequestAccountSid()); - return a; - } - - /** - * Returns the list of Applications in this account. - * See http://www.twilio.com/docs/api/rest/applications - */ - public TwilioApplicationList getApplications() { - return this.getApplications(new Map()); - } - - /** - * Returns a list of Applications in this account, applying the supplied filters. - * See http://www.twilio.com/docs/api/rest/applications - */ - public TwilioApplicationList getApplications(Map filters) { - TwilioApplicationList twlist = new TwilioApplicationList(this.getClient(), filters); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns a given Application instance by sid. - */ - public TwilioApplication getApplication(String sid) { - TwilioApplication app = new TwilioApplication(this.getClient(), sid); - app.setRequestAccountSid(this.getRequestAccountSid()); - return app; - } - - /** - * Returns the available phone numbers. Defaults to US/Local. - * See http://www.twilio.com/docs/api/rest/available-phone-numbers - */ - public TwilioAvailablePhoneNumberList getAvailablePhoneNumbers() { - return this.getAvailablePhoneNumbers(new Map()); - } - - /** - * Returns the available phone numbers. With the given search filters. Defaults - * to US/Local numbers. - * See http://www.twilio.com/docs/api/rest/available-phone-numbers - */ - public TwilioAvailablePhoneNumberList getAvailablePhoneNumbers(Map filters) { - TwilioAvailablePhoneNumberList twlist = new TwilioAvailablePhoneNumberList( - this.getClient(), filters); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns the available phone numbers with the given iso country and type. - * See http://www.twilio.com/docs/api/rest/available-phone-numbers - * - * @param filters - * the filters - * @param isoCountry - * the Iso Country code you are searching in - * @param type - * the type of phone number. Possible values are - * AvailablePhoneNumber.TYPE_LOCAL or - * AvailablePhoneNumber.TYPE_TOLLFREE - * - * @return the available phone numbers - */ - public TwilioAvailablePhoneNumberList getAvailablePhoneNumbers( - Map filters, String isoCountry, String type) { - TwilioAvailablePhoneNumberList twlist = new TwilioAvailablePhoneNumberList( - this.getClient(), filters, isoCountry, type); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - - return twlist; - } - - /** - * Returns the conference list. - * See http://www.twilio.com/docs/api/rest/conference - */ - public TwilioConferenceList getConferences() { - return this.getConferences(new Map()); - } - - /** - * Returns the conferences list with the given filters. - * See http://www.twilio.com/docs/api/rest/conference - */ - public TwilioConferenceList getConferences(Map filters) { - TwilioConferenceList twlist = new TwilioConferenceList(this.getClient(), filters); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns a given conference instance by sid. - */ - public TwilioConference getConference(String sid) { - TwilioConference conf = new TwilioConference(this.getClient(), sid); - conf.setRequestAccountSid(this.getRequestAccountSid()); - return conf; - } - - /** - * Get the participant list - * - * @return - */ - public TwilioParticipantList getParticipants(String conferenceSid) { - TwilioParticipantList twlist = new TwilioParticipantList(this.getClient(), conferenceSid); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns the incoming phone numbers list. - * See http://www.twilio.com/docs/api/rest/incoming-phone-numbers - */ - public TwilioIncomingPhoneNumberList getIncomingPhoneNumbers() { - return this.getIncomingPhoneNumbers(new Map()); - } - - /** - * Returns the incoming phone numbers list with the given filters. - * See http://www.twilio.com/docs/api/rest/incoming-phone-numbers - */ - public TwilioIncomingPhoneNumberList getIncomingPhoneNumbers( - Map filters) { - TwilioIncomingPhoneNumberList twlist = new TwilioIncomingPhoneNumberList( - this.getClient(), filters); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns a given incoming phone number instance by sid. - */ - public TwilioIncomingPhoneNumber getIncomingPhoneNumber(String sid) { - TwilioIncomingPhoneNumber pn = new TwilioIncomingPhoneNumber(this.getClient(), sid); - pn.setRequestAccountSid(this.getRequestAccountSid()); - return pn; - } - - /** - * Returns the Short Code list. - */ - public TwilioShortCodeList getShortCodes() { - return this.getShortCodes(new Map()); - } - - /** - * Returns the Short Code list with filters. - */ - public TwilioShortCodeList getShortCodes(Map filters) { - TwilioShortCodeList twlist = new TwilioShortCodeList(this.getClient(), filters); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns a given Short Code instance by sid. - */ - public TwilioShortCode getShortCode(String sid) { - TwilioShortCode sc = new TwilioShortCode(this.getClient(), sid); - sc.setRequestAccountSid(this.getRequestAccountSid()); - return sc; - } - - /** - * Returns the notifications. - * - * @return the notifications - */ - public TwilioNotificationList getNotifications() { - return this.getNotifications(new Map()); - } - - /** - * Returns the notifications. - */ - public TwilioNotificationList getNotifications(Map filters) { - TwilioNotificationList twlist = new TwilioNotificationList(this.getClient(), filters); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns a given notification instance by sid - */ - public TwilioNotification getNotification(String sid) { - TwilioNotification n = new TwilioNotification(this.getClient(), sid); - n.setRequestAccountSid(this.getRequestAccountSid()); - return n; - } - - /** - * Returns the outgoing caller ids. - * See http://www.twilio.com/docs/api/rest/outgoing-caller-ids - */ - public TwilioOutgoingCallerIdList getOutgoingCallerIds() { - return this.getOutgoingCallerIds(null); - } - - /** - * Returns the outgoing caller ids. - * See http://www.twilio.com/docs/api/rest/outgoing-caller-ids - */ - public TwilioOutgoingCallerIdList getOutgoingCallerIds(Map filters) { - TwilioOutgoingCallerIdList twlist; - if (filters==null) { - twlist = new TwilioOutgoingCallerIdList(this.getClient()); - } else { - twlist = new TwilioOutgoingCallerIdList(this.getClient(), filters); - } - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns a given outgoing caller id instance by sid. - */ - public TwilioOutgoingCallerId getOutgoingCallerId(String sid) { - TwilioOutgoingCallerId cid = new TwilioOutgoingCallerId(this.getClient(), sid); - cid.setRequestAccountSid(this.getRequestAccountSid()); - return cid; - } - - - /** - * Returns the recordings list. - * See http://www.twilio.com/docs/api/rest/recording - */ - public TwilioRecordingList getRecordings() { - return this.getRecordings(new Map()); - } - - /** - * Returns the recordings list. - * See http://www.twilio.com/docs/api/rest/recording - */ - public TwilioRecordingList getRecordings(Map filters) { - TwilioRecordingList twlist = new TwilioRecordingList(this.getClient(), filters); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns a given recording instance by sid. - */ - public TwilioRecording getRecording(String sid) { - TwilioRecording r = new TwilioRecording(this.getClient(), sid); - r.setRequestAccountSid(this.getRequestAccountSid()); - return r; - } - - /** - * Returns the transcriptions list. - * See http://www.twilio.com/docs/api/rest/transcription - */ - public TwilioTranscriptionList getTranscriptions() { - return this.getTranscriptions(new Map()); - } - - /** - * Returns the transcriptions list with the given filters. - * See http://www.twilio.com/docs/api/rest/transcription - */ - public TwilioTranscriptionList getTranscriptions(Map filters) { - TwilioTranscriptionList twlist = new TwilioTranscriptionList(this.getClient(), - filters); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns a given transcription instance by sid - */ - public TwilioTranscription getTranscription(String sid) { - TwilioTranscription tr = new TwilioTranscription(this.getClient(), sid); - tr.setRequestAccountSid(this.getRequestAccountSid()); - return tr; - } - - - /** - * Returns the connect app list with the given filters. - * See http://www.twilio.com/docs/api/rest/connect-apps - */ - public TwilioConnectAppList getConnectApps(Map filters) { - TwilioConnectAppList twlist = new TwilioConnectAppList(this.getClient(), - filters); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns a given connect app instance by sid - */ - public TwilioConnectApp getConnectApp(String sid) { - TwilioConnectApp cn = new TwilioConnectApp(this.getClient(), sid); - cn.setRequestAccountSid(this.getRequestAccountSid()); - return cn; - } - - /** - * Returns the connect app list with the given filters. - * See http://www.twilio.com/docs/api/rest/connect-apps - */ - public TwilioAuthorizedConnectAppList getAuthorizedConnectApps(Map filters) { - TwilioAuthorizedConnectAppList twlist = new TwilioAuthorizedConnectAppList(this.getClient(), - filters); - twlist.setRequestAccountSid(this.getRequestAccountSid()); - return twlist; - } - - /** - * Returns a given connect app instance by sid. - */ - public TwilioAuthorizedConnectApp getAuthorizedConnectApp(String sid) { - TwilioAuthorizedConnectApp cn = new TwilioAuthorizedConnectApp(this.getClient(), sid); - cn.setRequestAccountSid(this.getRequestAccountSid()); - return cn; - } - - /** - * Returns the developer sandbox. - */ - public TwilioSandbox getSandbox() { - TwilioSandbox sb = new TwilioSandbox(this.getClient()); - sb.setRequestAccountSid(this.getRequestAccountSid()); - return sb; - } + /* property keys */ + private static final String DATE_UPDATED_PROPERTY = 'date_updated'; + private static final String DATE_CREATED_PROPERTY = 'date_created'; + private static final String STATUS_PROPERTY = 'status'; + private static final String FRIENDLY_NAME_PROPERTY = 'friendly_name'; + private static final String ACCOUNT_SID_PROPERTY = 'sid'; + private static final String AUTH_TOKEN_PROPERTY = 'auth_token'; + private static final String TYPE_PROPERTY = 'type'; + private static final String OWNER_ACCOUNT_SID_PROPERTY = 'owner_account_sid'; + private static final String CONNECT_APP_SID_PROPERTY = 'connect_app_sid'; + + /* Constructor */ + public TwilioAccount(TwilioRestClient client) { + super(client); + } + + /* Constructor, using predefined set of property values */ + public TwilioAccount(TwilioRestClient client, Map properties) { + super(client, properties); + Object ac = properties.get(ACCOUNT_SID_PROPERTY); + if (ac != null && ac instanceof String) { + String accountSid = (String) ac; + this.setRequestAccountSid(accountSid); + } + } + + /* Sid field accessor */ + public String getSid() { + if (this.getRequestAccountSid() != null) + return this.getRequestAccountSid(); + else + return this.getProperty(ACCOUNT_SID_PROPERTY); + } + + /* Sid field accessor */ + public void setSid(String accountSid) { + this.setRequestAccountSid(accountSid); + this.setProperty(ACCOUNT_SID_PROPERTY, accountSid); + + } + + /** Returns the sid for the ConnectApp using this Account */ + public String getConnectAppSid() { + return this.getProperty(CONNECT_APP_SID_PROPERTY); + } + + /** Returns the AccountSid of the primary account */ + public String getOwnerAccountSid() { + return this.getProperty(OWNER_ACCOUNT_SID_PROPERTY); + } + + /** Returns the API auth token (secret) for this account */ + public String getAuthToken() { + return this.getProperty(AUTH_TOKEN_PROPERTY); + } + + /** Sets the API auth token (secret) for this account */ + public void setAuthToken(String authToken) { + this.setProperty(AUTH_TOKEN_PROPERTY, authToken); + } + + /** Returns the human-readable label for this account */ + public String getFriendlyName() { + return this.getProperty(FRIENDLY_NAME_PROPERTY); + } + + /** Returns the status value for this account */ + public String getStatus() { + return this.getProperty(STATUS_PROPERTY); + } + + /** Returns the date and time this account was created */ + public Datetime getDateCreated() { + return this.getPropertyDatetime(DATE_CREATED_PROPERTY); + } + + /** Returns the date and time this account was last updated */ + public Datetime getDateUpdated() { + return this.getPropertyDatetime(DATE_UPDATED_PROPERTY); + } + + /** Returns the account type */ + public String getType() { + return this.getProperty(TYPE_PROPERTY); + } + + /** Return the Twilio URI for this resource. */ + public String getUri() { + return this.getProperty('uri'); + } + + /** Returns the URIs for resources under this account */ + public Map getSubresourceUris() { + return (Map)this.getObject('subresource_uris'); + } + + /** Constructs a Twilio API resource URI for this Account. Overrides method from TwilioResource. */ + public override String getResourceLocation() { + return '/' + TwilioRestClient.DEFAULT_VERSION + '/Accounts/' + + this.getRequestAccountSid() + '.json'; + } + + + /* SUBRESOURCE METHODS */ + + /* Returns the calls list resource without any filters. + * See http://www.twilio.com/docs/api/rest/call + */ + public TwilioCallList getCalls() { + return this.getCalls(new Map()); + } + + /* Returns the calls list resource with the given filters. + * See http://www.twilio.com/docs/api/rest/call + */ + public TwilioCallList getCalls(Map filters) { + TwilioCallList calls = new TwilioCallList(this.getClient(), filters); + calls.setRequestAccountSid(this.getRequestAccountSid()); + + return calls; + } + + /** Returns a given call instance by sid */ + public TwilioCall getCall(String sid) { + TwilioCall call = new TwilioCall(this.getClient(), sid); + call.setRequestAccountSid(this.getRequestAccountSid()); + return call; + } + + + /** + * Returns the sms message list. + * See http://www.twilio.com/docs/api/rest/sms + */ + public TwilioSmsList getSmsMessages() { + return this.getSmsMessages(new Map()); + } + + /** + * Returns the SMS messages list, applying the supplied filters. + * See http://www.twilio.com/docs/api/rest/sms + */ + public TwilioSmsList getSmsMessages(Map filters) { + TwilioSmsList sms = new TwilioSmsList(this.getClient(), filters); + sms.setRequestAccountSid(this.getRequestAccountSid()); + + return sms; + } + + /** Returns a given SMS message by sid */ + public TwilioSms getSms(String sid) { + TwilioSms sms = new TwilioSms(this.getClient(), sid); + sms.setRequestAccountSid(this.getRequestAccountSid()); + return sms; + } + + /** + * Returns the message list. + * See http://www.twilio.com/docs/api/rest/message + */ + public TwilioMessageList getMessages() { + return this.getMessages(new Map()); + } + + /** + * Returns the messages list, applying the supplied filters. + * See http://www.twilio.com/docs/api/rest/message + */ + public TwilioMessageList getMessages(Map filters) { + TwilioMessageList message = new TwilioMessageList(this.getClient(), filters); + message.setRequestAccountSid(this.getRequestAccountSid()); + + return message; + } + + /** Returns a given message by sid */ + public TwilioMessage getMessage(String sid) { + TwilioMessage message = new TwilioMessage(this.getClient(), sid); + message.setRequestAccountSid(this.getRequestAccountSid()); + return message; + } + + /** + * Suspend a subaccount. + * + * @return the account + * @throws TwilioRestException the twilio rest exception + */ + public TwilioAccount suspend() { + Map vars = new Map + { 'Status'=> 'suspended' }; + + TwilioRestResponse response = this.getClient().safeRequest( + this.getResourceLocation(), 'POST', vars); + + TwilioAccount a = new TwilioAccount(this.getClient(), response.toMap()); + a.setRequestAccountSid(this.getRequestAccountSid()); + return a; + } + + /** + * Activate a suspended subaccount. + * + * @return the account + * @throws TwilioRestException the twilio rest exception + */ + public TwilioAccount activate() { + Map vars = new Map + { 'Status'=> 'active' }; + + TwilioRestResponse response = this.getClient().safeRequest( + this.getResourceLocation(), 'POST', vars); + + TwilioAccount a = new TwilioAccount(this.getClient(), response.toMap()); + a.setRequestAccountSid(this.getRequestAccountSid()); + return a; + } + + /** + * Close a subaccount. WARNING: This cannot be undone. + * + * @return the account + * @throws TwilioRestException the twilio rest exception + */ + public TwilioAccount close() { + Map vars = new Map + { 'Status'=> 'closed' }; + + TwilioRestResponse response = this.getClient().safeRequest( + this.getResourceLocation(), 'POST', vars); + + TwilioAccount a = new TwilioAccount(this.getClient(), response.toMap()); + a.setRequestAccountSid(this.getRequestAccountSid()); + return a; + } + + /** + * Returns the list of Applications in this account. + * See http://www.twilio.com/docs/api/rest/applications + */ + public TwilioApplicationList getApplications() { + return this.getApplications(new Map()); + } + + /** + * Returns a list of Applications in this account, applying the supplied filters. + * See http://www.twilio.com/docs/api/rest/applications + */ + public TwilioApplicationList getApplications(Map filters) { + TwilioApplicationList twlist = new TwilioApplicationList(this.getClient(), filters); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns a given Application instance by sid. + */ + public TwilioApplication getApplication(String sid) { + TwilioApplication app = new TwilioApplication(this.getClient(), sid); + app.setRequestAccountSid(this.getRequestAccountSid()); + return app; + } + + /** + * Returns the available phone numbers. Defaults to US/Local. + * See http://www.twilio.com/docs/api/rest/available-phone-numbers + */ + public TwilioAvailablePhoneNumberList getAvailablePhoneNumbers() { + return this.getAvailablePhoneNumbers(new Map()); + } + + /** + * Returns the available phone numbers. With the given search filters. Defaults + * to US/Local numbers. + * See http://www.twilio.com/docs/api/rest/available-phone-numbers + */ + public TwilioAvailablePhoneNumberList getAvailablePhoneNumbers(Map filters) { + TwilioAvailablePhoneNumberList twlist = new TwilioAvailablePhoneNumberList( + this.getClient(), filters); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns the available phone numbers with the given iso country and type. + * See http://www.twilio.com/docs/api/rest/available-phone-numbers + * + * @param filters + * the filters + * @param isoCountry + * the Iso Country code you are searching in + * @param type + * the type of phone number. Possible values are + * AvailablePhoneNumber.TYPE_LOCAL or + * AvailablePhoneNumber.TYPE_TOLLFREE + * + * @return the available phone numbers + */ + public TwilioAvailablePhoneNumberList getAvailablePhoneNumbers( + Map filters, String isoCountry, String type) { + TwilioAvailablePhoneNumberList twlist = new TwilioAvailablePhoneNumberList( + this.getClient(), filters, isoCountry, type); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + + return twlist; + } + + /** + * Returns the conference list. + * See http://www.twilio.com/docs/api/rest/conference + */ + public TwilioConferenceList getConferences() { + return this.getConferences(new Map()); + } + + /** + * Returns the conferences list with the given filters. + * See http://www.twilio.com/docs/api/rest/conference + */ + public TwilioConferenceList getConferences(Map filters) { + TwilioConferenceList twlist = new TwilioConferenceList(this.getClient(), filters); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns a given conference instance by sid. + */ + public TwilioConference getConference(String sid) { + TwilioConference conf = new TwilioConference(this.getClient(), sid); + conf.setRequestAccountSid(this.getRequestAccountSid()); + return conf; + } + + /** + * Get the participant list + * + * @return + */ + public TwilioParticipantList getParticipants(String conferenceSid) { + TwilioParticipantList twlist = new TwilioParticipantList(this.getClient(), conferenceSid); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns the incoming phone numbers list. + * See http://www.twilio.com/docs/api/rest/incoming-phone-numbers + */ + public TwilioIncomingPhoneNumberList getIncomingPhoneNumbers() { + return this.getIncomingPhoneNumbers(new Map()); + } + + /** + * Returns the incoming phone numbers list with the given filters. + * See http://www.twilio.com/docs/api/rest/incoming-phone-numbers + */ + public TwilioIncomingPhoneNumberList getIncomingPhoneNumbers( + Map filters) { + TwilioIncomingPhoneNumberList twlist = new TwilioIncomingPhoneNumberList( + this.getClient(), filters); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns a given incoming phone number instance by sid. + */ + public TwilioIncomingPhoneNumber getIncomingPhoneNumber(String sid) { + TwilioIncomingPhoneNumber pn = new TwilioIncomingPhoneNumber(this.getClient(), sid); + pn.setRequestAccountSid(this.getRequestAccountSid()); + return pn; + } + + /** + * Returns the Short Code list. + */ + public TwilioShortCodeList getShortCodes() { + return this.getShortCodes(new Map()); + } + + /** + * Returns the Short Code list with filters. + */ + public TwilioShortCodeList getShortCodes(Map filters) { + TwilioShortCodeList twlist = new TwilioShortCodeList(this.getClient(), filters); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns a given Short Code instance by sid. + */ + public TwilioShortCode getShortCode(String sid) { + TwilioShortCode sc = new TwilioShortCode(this.getClient(), sid); + sc.setRequestAccountSid(this.getRequestAccountSid()); + return sc; + } + + /** + * Returns the notifications. + * + * @return the notifications + */ + public TwilioNotificationList getNotifications() { + return this.getNotifications(new Map()); + } + + /** + * Returns the notifications. + */ + public TwilioNotificationList getNotifications(Map filters) { + TwilioNotificationList twlist = new TwilioNotificationList(this.getClient(), filters); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns a given notification instance by sid + */ + public TwilioNotification getNotification(String sid) { + TwilioNotification n = new TwilioNotification(this.getClient(), sid); + n.setRequestAccountSid(this.getRequestAccountSid()); + return n; + } + + /** + * Returns the outgoing caller ids. + * See http://www.twilio.com/docs/api/rest/outgoing-caller-ids + */ + public TwilioOutgoingCallerIdList getOutgoingCallerIds() { + return this.getOutgoingCallerIds(null); + } + + /** + * Returns the outgoing caller ids. + * See http://www.twilio.com/docs/api/rest/outgoing-caller-ids + */ + public TwilioOutgoingCallerIdList getOutgoingCallerIds(Map filters) { + TwilioOutgoingCallerIdList twlist; + if (filters==null) { + twlist = new TwilioOutgoingCallerIdList(this.getClient()); + } else { + twlist = new TwilioOutgoingCallerIdList(this.getClient(), filters); + } + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns a given outgoing caller id instance by sid. + */ + public TwilioOutgoingCallerId getOutgoingCallerId(String sid) { + TwilioOutgoingCallerId cid = new TwilioOutgoingCallerId(this.getClient(), sid); + cid.setRequestAccountSid(this.getRequestAccountSid()); + return cid; + } + + + /** + * Returns the recordings list. + * See http://www.twilio.com/docs/api/rest/recording + */ + public TwilioRecordingList getRecordings() { + return this.getRecordings(new Map()); + } + + /** + * Returns the recordings list. + * See http://www.twilio.com/docs/api/rest/recording + */ + public TwilioRecordingList getRecordings(Map filters) { + TwilioRecordingList twlist = new TwilioRecordingList(this.getClient(), filters); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns a given recording instance by sid. + */ + public TwilioRecording getRecording(String sid) { + TwilioRecording r = new TwilioRecording(this.getClient(), sid); + r.setRequestAccountSid(this.getRequestAccountSid()); + return r; + } + + /** + * Returns the transcriptions list. + * See http://www.twilio.com/docs/api/rest/transcription + */ + public TwilioTranscriptionList getTranscriptions() { + return this.getTranscriptions(new Map()); + } + + /** + * Returns the transcriptions list with the given filters. + * See http://www.twilio.com/docs/api/rest/transcription + */ + public TwilioTranscriptionList getTranscriptions(Map filters) { + TwilioTranscriptionList twlist = new TwilioTranscriptionList(this.getClient(), + filters); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns a given transcription instance by sid + */ + public TwilioTranscription getTranscription(String sid) { + TwilioTranscription tr = new TwilioTranscription(this.getClient(), sid); + tr.setRequestAccountSid(this.getRequestAccountSid()); + return tr; + } + + + /** + * Returns the connect app list with the given filters. + * See http://www.twilio.com/docs/api/rest/connect-apps + */ + public TwilioConnectAppList getConnectApps(Map filters) { + TwilioConnectAppList twlist = new TwilioConnectAppList(this.getClient(), + filters); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns a given connect app instance by sid + */ + public TwilioConnectApp getConnectApp(String sid) { + TwilioConnectApp cn = new TwilioConnectApp(this.getClient(), sid); + cn.setRequestAccountSid(this.getRequestAccountSid()); + return cn; + } + + /** + * Returns the connect app list with the given filters. + * See http://www.twilio.com/docs/api/rest/connect-apps + */ + public TwilioAuthorizedConnectAppList getAuthorizedConnectApps(Map filters) { + TwilioAuthorizedConnectAppList twlist = new TwilioAuthorizedConnectAppList(this.getClient(), + filters); + twlist.setRequestAccountSid(this.getRequestAccountSid()); + return twlist; + } + + /** + * Returns a given connect app instance by sid. + */ + public TwilioAuthorizedConnectApp getAuthorizedConnectApp(String sid) { + TwilioAuthorizedConnectApp cn = new TwilioAuthorizedConnectApp(this.getClient(), sid); + cn.setRequestAccountSid(this.getRequestAccountSid()); + return cn; + } + + /** + * Returns the developer sandbox. + */ + public TwilioSandbox getSandbox() { + TwilioSandbox sb = new TwilioSandbox(this.getClient()); + sb.setRequestAccountSid(this.getRequestAccountSid()); + return sb; + } } \ No newline at end of file diff --git a/src/classes/TwilioCapability.cls b/src/classes/TwilioCapability.cls index 52fd607..8500c6e 100644 --- a/src/classes/TwilioCapability.cls +++ b/src/classes/TwilioCapability.cls @@ -29,176 +29,176 @@ OTHER DEALINGS IN THE SOFTWARE. */ global class TwilioCapability { - private class IllegalStateException extends Exception {} + private class IllegalStateException extends Exception {} - private String accountSid; - private String authToken; - private List scopes; + private String accountSid; + private String authToken; + private List scopes; - // Incoming Parameter holding until generate token time - private boolean buildIncomingScope = false; - private String incomingClientName = null; + // Incoming Parameter holding until generate token time + private boolean buildIncomingScope = false; + private String incomingClientName = null; - // Outgoing Paramater holding until generate token time - private boolean buildOutgoingScope = false; - private String appSid = null; - private Map outgoingParams = null; + // Outgoing Paramater holding until generate token time + private boolean buildOutgoingScope = false; + private String appSid = null; + private Map outgoingParams = null; - /** - * Create a new TwilioCapability with zero permissions. Next steps are to - * grant access to resources by configuring this token through the functions - * allowXXXX. - * - * @param accountSid the account sid to which this token is granted access - * @param authToken the secret key used to sign the token. Note, this auth token is not visible to the user of the token. - */ - global TwilioCapability(String accountSid, String authToken) { - this.accountSid = accountSid; - this.authToken = authToken; - this.scopes = new List(); + /** + * Create a new TwilioCapability with zero permissions. Next steps are to + * grant access to resources by configuring this token through the functions + * allowXXXX. + * + * @param accountSid the account sid to which this token is granted access + * @param authToken the secret key used to sign the token. Note, this auth token is not visible to the user of the token. + */ + global TwilioCapability(String accountSid, String authToken) { + this.accountSid = accountSid; + this.authToken = authToken; + this.scopes = new List(); - } + } - /** - * Allow the user of this token to make outgoing connections. - * - * @param applicationSid - * the application to which this token grants access - */ - global void allowClientOutgoing(String appSid) { - allowClientOutgoing(appSid, null); - } + /** + * Allow the user of this token to make outgoing connections. + * + * @param applicationSid + * the application to which this token grants access + */ + global void allowClientOutgoing(String appSid) { + allowClientOutgoing(appSid, null); + } - /** - * Allow the user of this token to make outgoing connections. - * - * @param applicationSid - * the application to which this token grants access - * @param params - * signed parameters that the user of this token cannot - * overwrite. - */ - global void allowClientOutgoing(String appSid, Map params) { - this.buildOutgoingScope = true; - this.outgoingParams = params; - this.appSid = appSid; - } - - /** - * If the user of this token should be allowed to accept incoming - * connections then configure the TwilioCapability through this method and - * specify the client name. - * - * @param clientName - */ - global void allowClientIncoming(String clientName) { - // Save the default client name - this.incomingClientName = clientName; - this.buildIncomingScope = true; - } + /** + * Allow the user of this token to make outgoing connections. + * + * @param applicationSid + * the application to which this token grants access + * @param params + * signed parameters that the user of this token cannot + * overwrite. + */ + global void allowClientOutgoing(String appSid, Map params) { + this.buildOutgoingScope = true; + this.outgoingParams = params; + this.appSid = appSid; + } + + /** + * If the user of this token should be allowed to accept incoming + * connections then configure the TwilioCapability through this method and + * specify the client name. + * + * @param clientName + */ + global void allowClientIncoming(String clientName) { + // Save the default client name + this.incomingClientName = clientName; + this.buildIncomingScope = true; + } - /** - * Allow the user of this token to access their event stream. - * - * @param filters - * key/value filters to apply to the event stream - */ - global void allowEventStream(Map filters) { - Map value = new Map(); - value.put('path', '/2010-04-01/Events'); - if (filters != null) { - value.put('params', generateParamString(filters)); - } - this.scopes.add(buildScopeString('stream', 'subscribe', value)); - } + /** + * Allow the user of this token to access their event stream. + * + * @param filters + * key/value filters to apply to the event stream + */ + global void allowEventStream(Map filters) { + Map value = new Map(); + value.put('path', '/2010-04-01/Events'); + if (filters != null) { + value.put('params', generateParamString(filters)); + } + this.scopes.add(buildScopeString('stream', 'subscribe', value)); + } - /** - * Generates a new token based on the credentials and permissions that - * previously has been granted to this token. - * - * @return the newly generated token that is valid for 3600 seconds - */ - global String generateToken() { - return generateToken(System.currentTimeMillis() + 3600); - } + /** + * Generates a new token based on the credentials and permissions that + * previously has been granted to this token. + * + * @return the newly generated token that is valid for 3600 seconds + */ + global String generateToken() { + return generateToken(System.currentTimeMillis() + 3600); + } - /** - * Generates a new token based on the credentials and permissions that - * previously has been granted to this token. - * - * @param expiresAt - * the expiration instance of the token. - * @return the newly generated token that is valid for ttl seconds - */ - global String generateToken(long ttl) { - // Build these scopes lazily when we generate tokens so we know - // if we have a default or incoming client name to use - buildIncomingScope(); - buildOutgoingScope(); - Map payload = new Map(); - payload.put('iss', this.accountSid); - payload.put('exp', String.valueOf(System.currentTimeMillis() + ttl)); - payload.put('scope', join(this.scopes, ' ')); - return jwtEncode(payload, this.authToken); - } + /** + * Generates a new token based on the credentials and permissions that + * previously has been granted to this token. + * + * @param expiresAt + * the expiration instance of the token. + * @return the newly generated token that is valid for ttl seconds + */ + global String generateToken(long ttl) { + // Build these scopes lazily when we generate tokens so we know + // if we have a default or incoming client name to use + buildIncomingScope(); + buildOutgoingScope(); + Map payload = new Map(); + payload.put('iss', this.accountSid); + payload.put('exp', String.valueOf(System.currentTimeMillis() + ttl)); + payload.put('scope', join(this.scopes, ' ')); + return jwtEncode(payload, this.authToken); + } - /* PRIVATE METHODS */ - - /** - * Construct the scope string for outgoing calls - */ - private void buildOutgoingScope() { - if (this.buildOutgoingScope) { - Map values = new Map { 'appSid' => appSid }; + /* PRIVATE METHODS */ + + /** + * Construct the scope string for outgoing calls + */ + private void buildOutgoingScope() { + if (this.buildOutgoingScope) { + Map values = new Map { 'appSid' => appSid }; - if (this.incomingClientName != null) { - values.put('clientName', this.incomingClientName); - } + if (this.incomingClientName != null) { + values.put('clientName', this.incomingClientName); + } - // Build outgoing scopes - if (this.outgoingParams != null && !this.outgoingParams.isEmpty()) { - values.put('appParams', generateParamString(this.outgoingParams)); - } - this.scopes.add(buildScopeString('client', 'outgoing', values)); - } - } - - /** - * Construct the scope string for incoming calls - */ - private void buildIncomingScope() { - if (this.buildIncomingScope) { - Map value = new Map(); + // Build outgoing scopes + if (this.outgoingParams != null && !this.outgoingParams.isEmpty()) { + values.put('appParams', generateParamString(this.outgoingParams)); + } + this.scopes.add(buildScopeString('client', 'outgoing', values)); + } + } + + /** + * Construct the scope string for incoming calls + */ + private void buildIncomingScope() { + if (this.buildIncomingScope) { + Map value = new Map(); - // Incoming name, which takes precedence over the default client name. - // However, we do NOT accept a null clientName here. - if (this.incomingClientName != null) { - value.put('clientName', this.incomingClientName); - } else { - throw new IllegalStateException('No client name set'); - } - this.scopes.add(buildScopeString('client', 'incoming', value)); - } - } - - /** - * Construct JWT scope string in the format "scope::?" - */ - private static String buildScopeString(String service, String privilege, - Map params) { - String scope = 'scope:'+service+':'+privilege; - if (params!=null && !params.isEmpty()) { - scope += '?'+generateParamString(params); - } - return scope; - } + // Incoming name, which takes precedence over the default client name. + // However, we do NOT accept a null clientName here. + if (this.incomingClientName != null) { + value.put('clientName', this.incomingClientName); + } else { + throw new IllegalStateException('No client name set'); + } + this.scopes.add(buildScopeString('client', 'incoming', value)); + } + } + + /** + * Construct JWT scope string in the format "scope::?" + */ + private static String buildScopeString(String service, String privilege, + Map params) { + String scope = 'scope:'+service+':'+privilege; + if (params!=null && !params.isEmpty()) { + scope += '?'+generateParamString(params); + } + return scope; + } - /** - * Construct URL-style query param string, e.g. key1=val1&key2=val2&...keyN=valN - */ - private static String generateParamString(Map params) { - String queryString = ''; + /** + * Construct URL-style query param string, e.g. key1=val1&key2=val2&...keyN=valN + */ + private static String generateParamString(Map params) { + String queryString = ''; Set keySet = params.keySet(); for (String key : keySet) { @@ -206,44 +206,44 @@ global class TwilioCapability { queryString += '&'; } queryString += EncodingUtil.urlEncode(key, 'UTF-8') + '=' - + EncodingUtil.urlEncode(params.get(key), 'UTF-8'); + + EncodingUtil.urlEncode(params.get(key), 'UTF-8'); } return queryString; - } + } - /** - * Construct JWT token consisting of header, payload, and signature - * - * See http://self-issued.info/docs/draft-jones-json-web-token.html - */ - private static String jwtEncode(Map payload, String key) { - Map header = new Map(); - header.put('typ', 'JWT'); - header.put('alg', 'HS256'); + /** + * Construct JWT token consisting of header, payload, and signature + * + * See http://self-issued.info/docs/draft-jones-json-web-token.html + */ + private static String jwtEncode(Map payload, String key) { + Map header = new Map(); + header.put('typ', 'JWT'); + header.put('alg', 'HS256'); - List segments = new List(); - segments.add(urlSafeEncodeBase64(JSON.serialize(header))); - segments.add(urlSafeEncodeBase64(JSON.serialize(payload))); + List segments = new List(); + segments.add(urlSafeEncodeBase64(JSON.serialize(header))); + segments.add(urlSafeEncodeBase64(JSON.serialize(payload))); - String signature = sign(join(segments, '.'), key); - segments.add(signature); + String signature = sign(join(segments, '.'), key); + segments.add(signature); - return join(segments, '.'); - } + return join(segments, '.'); + } - private static String urlSafeEncodeBase64(String data) { + private static String urlSafeEncodeBase64(String data) { return urlSafeEncodeBase64(Blob.valueOf(data)); } - private static String urlSafeEncodeBase64(Blob data) { + private static String urlSafeEncodeBase64(Blob data) { String encodedString = EncodingUtil.base64Encode(data); return encodedString.replace('+','-').replace('/','_').replace('=', ''); // make URL-safe } - - /** - * Construct a String containing the contents of 'vals' separated by 'sep' - */ - private static String join(List vals, String sep) { + + /** + * Construct a String containing the contents of 'vals' separated by 'sep' + */ + private static String join(List vals, String sep) { String sb = ''; for (Iterator it=vals.iterator(); it.hasNext(); ) { String value = it.next(); @@ -254,75 +254,75 @@ global class TwilioCapability { return sb; } - /** - * Generate a signature for the token - * - * See http://self-issued.info/docs/draft-jones-json-web-signature.html - * and http://discussion.forum.nokia.com/forum/showthread.php?130974-Help-required-How-to-generate-a-MAC-(HMAC-SHA1)-with-Java - */ - private static String sign(String data, String key) { - Blob mac = Crypto.generateMac('hmacSHA256', Blob.valueOf(data), Blob.valueOf(key)); + /** + * Generate a signature for the token + * + * See http://self-issued.info/docs/draft-jones-json-web-signature.html + * and http://discussion.forum.nokia.com/forum/showthread.php?130974-Help-required-How-to-generate-a-MAC-(HMAC-SHA1)-with-Java + */ + private static String sign(String data, String key) { + Blob mac = Crypto.generateMac('hmacSHA256', Blob.valueOf(data), Blob.valueOf(key)); String result = urlSafeEncodeBase64(mac); - return result; - } - - /* UNIT TESTS FOR PRIVATE METHODS */ - static testMethod void testGenerateParamString() { - System.assertEquals('', generateParamString(new Map())); - System.assertEquals('a=b', generateParamString(new Map {'a'=>'b'} )); - System.assertEquals('cat=dog&foo=bar', generateParamString(new Map {'foo'=>'bar', 'cat' => 'dog'} )); - System.assertEquals('e=f&c=d&a=b', generateParamString(new Map {'a'=>'b', 'c'=>'d', 'e'=>'f' } )); - System.assertEquals('split%2Bkey2=split%2Bval2&split+key1=split+val1', generateParamString(new Map {'split key1'=>'split val1', 'split+key2'=>'split+val2'} )); + return result; + } + + /* UNIT TESTS FOR PRIVATE METHODS */ + static testMethod void testGenerateParamString() { + System.assertEquals('', generateParamString(new Map())); + System.assertEquals('a=b', generateParamString(new Map {'a'=>'b'} )); + System.assertEquals('cat=dog&foo=bar', generateParamString(new Map {'foo'=>'bar', 'cat' => 'dog'} )); + System.assertEquals('e=f&c=d&a=b', generateParamString(new Map {'a'=>'b', 'c'=>'d', 'e'=>'f' } )); + System.assertEquals('split+key2=split+val2&split+key1=split+val1', generateParamString(new Map {'split key1'=>'split val1', 'split key2'=>'split val2'} )); } static testMethod void testEncodeBase64() { - System.assertEquals('',urlSafeEncodeBase64('')); - System.assertEquals('QQ',urlSafeEncodeBase64('A')); - System.assertEquals('QUI',urlSafeEncodeBase64('AB')); - System.assertEquals('QUJDRA',urlSafeEncodeBase64('ABCD')); + System.assertEquals('',urlSafeEncodeBase64('')); + System.assertEquals('QQ',urlSafeEncodeBase64('A')); + System.assertEquals('QUI',urlSafeEncodeBase64('AB')); + System.assertEquals('QUJDRA',urlSafeEncodeBase64('ABCD')); } static testMethod void testJoin() { - System.assertEquals('', join(new List(),',')); - System.assertEquals('a', join(new List{'a'},',')); - System.assertEquals('a,b,c,d,e', join(new List{'a','b','c','d','e'},',')); + System.assertEquals('', join(new List(),',')); + System.assertEquals('a', join(new List{'a'},',')); + System.assertEquals('a,b,c,d,e', join(new List{'a','b','c','d','e'},',')); } /* ACCESSOR METHODS FOR EXTERNAL TESTS */ public boolean test_buildOutgoingScope { - get { - if (!Test.isRunningTest()) throw new TestOnlyException('Test must be running to use this method'); - return this.buildOutgoingScope; - } + get { + if (!Test.isRunningTest()) throw new TestOnlyException('Test must be running to use this method'); + return this.buildOutgoingScope; + } } public String test_appSid { - get { - if (!Test.isRunningTest()) throw new TestOnlyException('Test must be running to use this method'); - return this.appSid; - } + get { + if (!Test.isRunningTest()) throw new TestOnlyException('Test must be running to use this method'); + return this.appSid; + } } public Map test_outgoingParams { - get { - if (!Test.isRunningTest()) throw new TestOnlyException('Test must be running to use this method'); - return this.outgoingParams; - } + get { + if (!Test.isRunningTest()) throw new TestOnlyException('Test must be running to use this method'); + return this.outgoingParams; + } } public List test_scopes { - get { - if (!Test.isRunningTest()) throw new TestOnlyException('Test must be running to use this method'); - return this.scopes; - } + get { + if (!Test.isRunningTest()) throw new TestOnlyException('Test must be running to use this method'); + return this.scopes; + } } public String test_incomingClientName { - get { - if (!Test.isRunningTest()) throw new TestOnlyException('Test must be running to use this method'); - return this.incomingClientName; - } + get { + if (!Test.isRunningTest()) throw new TestOnlyException('Test must be running to use this method'); + return this.incomingClientName; + } } private class TestOnlyException extends Exception {} diff --git a/src/classes/TwilioIterator.cls b/src/classes/TwilioIterator.cls index 86bf85c..b343b20 100644 --- a/src/classes/TwilioIterator.cls +++ b/src/classes/TwilioIterator.cls @@ -24,189 +24,209 @@ OTHER DEALINGS IN THE SOFTWARE. */ global class TwilioIterator { - /** - * The Class ObjectIteratorSupport - */ - global abstract class ObjectIteratorSupport { + /** + * The Class ObjectIteratorSupport + */ + global abstract class ObjectIteratorSupport { - /** The itr. */ - private Iterator itr; - - private TwilioResource.ListResource twlist; + /** The itr. */ + private Iterator itr; + + private TwilioResource.ListResource twlist; - protected ObjectIteratorSupport(TwilioResource.ListResource twlist) { - this.itr = twlist.getObjectPageData().iterator(); - this.twlist = twlist; - } + protected ObjectIteratorSupport(TwilioResource.ListResource twlist) { + this.itr = twlist.getObjectPageData().iterator(); + this.twlist = twlist; + } - global boolean hasNext() { - return itr.hasNext() || twlist.hasNextPage(); - } + global boolean hasNext() { + return itr.hasNext() || twlist.hasNextPage(); + } - protected Object getNext() { - // If we still have results on this page - if (itr.hasNext()) { - return itr.next(); - } + protected Object getNext() { + // If we still have results on this page + if (itr.hasNext()) { + return itr.next(); + } - // Otherwise fetch the next page - twlist.fetchNextPage(); - - itr = twlist.getObjectPageData().iterator(); - return itr.next(); - } - } - - - global class AccountIterator extends ObjectIteratorSupport implements Iterator { - global AccountIterator(TwilioAccountList twlist) { - super(twlist); - } - - global TwilioAccount next() { - return (TwilioAccount)getNext(); - } - } - - global class ApplicationIterator extends ObjectIteratorSupport implements Iterator { - global ApplicationIterator(TwilioApplicationList twlist) { - super(twlist); - } - - global TwilioApplication next() { - return (TwilioApplication)getNext(); - } - } - - global class AuthorizedConnectAppIterator extends ObjectIteratorSupport implements Iterator { - global AuthorizedConnectAppIterator(TwilioAuthorizedConnectAppList twlist) { - super(twlist); - } - - global TwilioAuthorizedConnectApp next() { - return (TwilioAuthorizedConnectApp)getNext(); - } - } - - global class AvailablePhoneNumberIterator extends ObjectIteratorSupport implements Iterator { - global AvailablePhoneNumberIterator(TwilioAvailablePhoneNumberList twlist) { - super(twlist); - } - - global TwilioAvailablePhoneNumber next() { - return (TwilioAvailablePhoneNumber)getNext(); - } - } - - global class CallIterator extends ObjectIteratorSupport implements Iterator { - global CallIterator(TwilioCallList twlist) { - super(twlist); - } - - global TwilioCall next() { - return (TwilioCall)getNext(); - } - } - - global class ConferenceIterator extends ObjectIteratorSupport implements Iterator { - global ConferenceIterator(TwilioConferenceList twlist) { - super(twlist); - } - - global TwilioConference next() { - return (TwilioConference)getNext(); - } - } - - global class ConnectAppIterator extends ObjectIteratorSupport implements Iterator { - global ConnectAppIterator(TwilioConnectAppList twlist) { - super(twlist); - } - - global TwilioConnectApp next() { - return (TwilioConnectApp)getNext(); - } - } - - global class IncomingPhoneNumberIterator extends ObjectIteratorSupport implements Iterator { - global IncomingPhoneNumberIterator(TwilioIncomingPhoneNumberList twlist) { - super(twlist); - } - - global TwilioIncomingPhoneNumber next() { - return (TwilioIncomingPhoneNumber)getNext(); - } - } - - global class NotificationIterator extends ObjectIteratorSupport implements Iterator { - global NotificationIterator(TwilioNotificationList twlist) { - super(twlist); - } - - global TwilioNotification next() { - return (TwilioNotification)getNext(); - } - } - - global class OutgoingCallerIdIterator extends ObjectIteratorSupport implements Iterator { - global OutgoingCallerIdIterator(TwilioOutgoingCallerIdList twlist) { - super(twlist); - } - - global TwilioOutgoingCallerId next() { - return (TwilioOutgoingCallerId)getNext(); - } - } - - global class ParticipantIterator extends ObjectIteratorSupport implements Iterator { - global ParticipantIterator(TwilioParticipantList twlist) { - super(twlist); - } - - global TwilioParticipant next() { - return (TwilioParticipant)getNext(); - } - } - - global class RecordingIterator extends ObjectIteratorSupport implements Iterator { - global RecordingIterator(TwilioRecordingList twlist) { - super(twlist); - } - - global TwilioRecording next() { - return (TwilioRecording)getNext(); - } - } - - global class ShortCodeIterator extends ObjectIteratorSupport implements Iterator { - global ShortCodeIterator(TwilioShortCodeList twlist) { - super(twlist); - } - - global TwilioShortCode next() { - return (TwilioShortCode)getNext(); - } - } - - global class SmsIterator extends ObjectIteratorSupport implements Iterator { - global SmsIterator(TwilioSmsList twlist) { - super(twlist); - } - - global TwilioSms next() { - return (TwilioSms)getNext(); - } - } - - global class TranscriptionIterator extends ObjectIteratorSupport implements Iterator { - global TranscriptionIterator(TwilioTranscriptionList twlist) { - super(twlist); - } - - global TwilioTranscription next() { - return (TwilioTranscription)getNext(); - } - } - - global class TwilioUnsupportedOperationException extends Exception {} + // Otherwise fetch the next page + twlist.fetchNextPage(); + + itr = twlist.getObjectPageData().iterator(); + return itr.next(); + } + } + + + global class AccountIterator extends ObjectIteratorSupport implements Iterator { + global AccountIterator(TwilioAccountList twlist) { + super(twlist); + } + + global TwilioAccount next() { + return (TwilioAccount)getNext(); + } + } + + global class ApplicationIterator extends ObjectIteratorSupport implements Iterator { + global ApplicationIterator(TwilioApplicationList twlist) { + super(twlist); + } + + global TwilioApplication next() { + return (TwilioApplication)getNext(); + } + } + + global class AuthorizedConnectAppIterator extends ObjectIteratorSupport implements Iterator { + global AuthorizedConnectAppIterator(TwilioAuthorizedConnectAppList twlist) { + super(twlist); + } + + global TwilioAuthorizedConnectApp next() { + return (TwilioAuthorizedConnectApp)getNext(); + } + } + + global class AvailablePhoneNumberIterator extends ObjectIteratorSupport implements Iterator { + global AvailablePhoneNumberIterator(TwilioAvailablePhoneNumberList twlist) { + super(twlist); + } + + global TwilioAvailablePhoneNumber next() { + return (TwilioAvailablePhoneNumber)getNext(); + } + } + + global class CallIterator extends ObjectIteratorSupport implements Iterator { + global CallIterator(TwilioCallList twlist) { + super(twlist); + } + + global TwilioCall next() { + return (TwilioCall)getNext(); + } + } + + global class ConferenceIterator extends ObjectIteratorSupport implements Iterator { + global ConferenceIterator(TwilioConferenceList twlist) { + super(twlist); + } + + global TwilioConference next() { + return (TwilioConference)getNext(); + } + } + + global class ConnectAppIterator extends ObjectIteratorSupport implements Iterator { + global ConnectAppIterator(TwilioConnectAppList twlist) { + super(twlist); + } + + global TwilioConnectApp next() { + return (TwilioConnectApp)getNext(); + } + } + + global class IncomingPhoneNumberIterator extends ObjectIteratorSupport implements Iterator { + global IncomingPhoneNumberIterator(TwilioIncomingPhoneNumberList twlist) { + super(twlist); + } + + global TwilioIncomingPhoneNumber next() { + return (TwilioIncomingPhoneNumber)getNext(); + } + } + + global class NotificationIterator extends ObjectIteratorSupport implements Iterator { + global NotificationIterator(TwilioNotificationList twlist) { + super(twlist); + } + + global TwilioNotification next() { + return (TwilioNotification)getNext(); + } + } + + global class OutgoingCallerIdIterator extends ObjectIteratorSupport implements Iterator { + global OutgoingCallerIdIterator(TwilioOutgoingCallerIdList twlist) { + super(twlist); + } + + global TwilioOutgoingCallerId next() { + return (TwilioOutgoingCallerId)getNext(); + } + } + + global class ParticipantIterator extends ObjectIteratorSupport implements Iterator { + global ParticipantIterator(TwilioParticipantList twlist) { + super(twlist); + } + + global TwilioParticipant next() { + return (TwilioParticipant)getNext(); + } + } + + global class RecordingIterator extends ObjectIteratorSupport implements Iterator { + global RecordingIterator(TwilioRecordingList twlist) { + super(twlist); + } + + global TwilioRecording next() { + return (TwilioRecording)getNext(); + } + } + + global class ShortCodeIterator extends ObjectIteratorSupport implements Iterator { + global ShortCodeIterator(TwilioShortCodeList twlist) { + super(twlist); + } + + global TwilioShortCode next() { + return (TwilioShortCode)getNext(); + } + } + + global class SmsIterator extends ObjectIteratorSupport implements Iterator { + global SmsIterator(TwilioSmsList twlist) { + super(twlist); + } + + global TwilioSms next() { + return (TwilioSms)getNext(); + } + } + + global class MessageIterator extends ObjectIteratorSupport implements Iterator { + global MessageIterator(TwilioMessageList twlist) { + super(twlist); + } + + global TwilioMessage next() { + return (TwilioMessage)getNext(); + } + } + + global class MediaIterator extends ObjectIteratorSupport implements Iterator { + global MediaIterator(TwilioMediaList twlist) { + super(twlist); + } + + global TwilioMedia next() { + return (TwilioMedia)getNext(); + } + } + + global class TranscriptionIterator extends ObjectIteratorSupport implements Iterator { + global TranscriptionIterator(TwilioTranscriptionList twlist) { + super(twlist); + } + + global TwilioTranscription next() { + return (TwilioTranscription)getNext(); + } + } + + global class TwilioUnsupportedOperationException extends Exception {} } \ No newline at end of file diff --git a/src/classes/TwilioMedia.cls b/src/classes/TwilioMedia.cls new file mode 100644 index 0000000..7dc6d71 --- /dev/null +++ b/src/classes/TwilioMedia.cls @@ -0,0 +1,172 @@ +global class TwilioMedia extends TwilioResource.InstanceResource +{ + /** The Constant SID_PROPERTY. */ + private static final String SID_PROPERTY = 'sid'; + private static String requestMessageSid; + + /** + * Instantiates a new Media. + * + * @param client the client + */ + public TwilioMedia(TwilioRestClient client) { + super(client); + } + + /** + * Instantiates a new Media. + * + * @param client the client + * @param sid the sid + */ + public TwilioMedia(TwilioRestClient client, String sid) { + super(client); + this.setProperty(SID_PROPERTY, sid); + } + + /** + * Instantiates a new media instance. + * + * @param client the client + * @param messageSid the sid of the parent message + * @param mediaSid the sid + */ + + public TwilioMedia(TwilioRestClient client, String messageSid, String mediaSid) { + super(client); + requestMessageSid = messageSid; + this.setProperty(SID_PROPERTY, mediaSid); + } + + /** + * Instantiates a new Media. + * + * @param client the client + * @param properties the properties + */ + public TwilioMedia(TwilioRestClient client, Map properties) { + super(client, properties); + } + + public override String getResourceLocation() + { + if (this.getRequestMessageSid() != null) + { + return '/' + TwilioRestClient.DEFAULT_VERSION + + '/Accounts/' + this.getRequestAccountSid() + + '/Messages/' + this.getRequestMessageSid() + + '/Media/' + this.getSid() + '.json'; + } + else + { + return '/' + TwilioRestClient.DEFAULT_VERSION + + '/Accounts/' + this.getRequestAccountSid() + + '/Media/' + this.getSid() + '.json'; + } + } + + /** + * Gets the sid. + * + * @return the sid + */ + + public String getSid() { + return this.getProperty(SID_PROPERTY); + } + + /** + * Gets the sid of the requesting message + * + * @return the sid of the requesting message + */ + public String getRequestMessageSid() { + return this.getProperty(requestMessageSid); + } + + /** + * Gets the date created. + * + * @return the date created + */ + public Datetime getDateCreated() { + return this.getPropertyDatetime('date_created'); + } + + /** + * Gets the date updated. + * + * @return the date updated + */ + public Datetime getDateUpdated() { + return this.getPropertyDatetime('date_updated'); + } + + /** + * Gets the account sid. + * + * @return the account sid + */ + public String getAccountSid() { + return this.getProperty('account_sid'); + } + + /** + * Gets the parent sid. + * + * @return the account sid + */ + public String getParentSid() { + return this.getProperty('parent_sid'); + } + + /** + * Gets the content type + * + * @return the content type + */ + public String getContentType() { + return this.getProperty('content_type'); + } + + /** + * Gets the duration + * + * @return the duration + */ + public Integer getDuration() + { + Integer duration = (Integer) this.getObject('duration'); + return duration; + } + + /** + * Gets the api version. + * + * @return the api version + */ + public String getApiVersion() { + return this.getProperty('api_version'); + } + + /** + * Gets the uri of this media + * + * @return the uri + */ + public String getUri() { + return this.getProperty('uri'); + } + + /** + * Delete this Media + * + * @return true, if successful + * @throws TwilioRestException the twilio rest exception + */ + public Boolean deleteMedia() + { + TwilioRestResponse response = this.getClient().safeRequest(this.getResourceLocation(),'DELETE',null); + return !response.isError(); + } +} \ No newline at end of file diff --git a/src/classes/TwilioMedia.cls-meta.xml b/src/classes/TwilioMedia.cls-meta.xml new file mode 100644 index 0000000..f165265 --- /dev/null +++ b/src/classes/TwilioMedia.cls-meta.xml @@ -0,0 +1,5 @@ + + + 29.0 + Active + diff --git a/src/classes/TwilioMediaList.cls b/src/classes/TwilioMediaList.cls new file mode 100644 index 0000000..3356f43 --- /dev/null +++ b/src/classes/TwilioMediaList.cls @@ -0,0 +1,72 @@ +global class TwilioMediaList extends TwilioResource.ListResource implements Iterable +{ + + private String requestMessageSid; + + /** + * Instantiates a new media list. + * + * @param client the client + */ + public TwilioMediaList(TwilioRestClient client) { + super(client); + } + + /** + * Instantiates a new media list. + * + * @param client the client + * @param messageSid the sid of the parent message requesting media + */ + public TwilioMediaList(TwilioRestClient client, String messageSid) { + super(client); + this.requestMessageSid = messageSid; + } + + /** + * Instantiates a new media list. + * + * @param client the client + * @param properties the properties + */ + public TwilioMediaList(TwilioRestClient client, Map properties) { + super(client, properties); + } + + + /* implements method from TwilioResource.ListResource */ + public override Object makeNew(TwilioRestClient client, Map params) { + return new TwilioMedia(client, params); + } + + /* implements method from TwilioResource.ListResource */ + public override String getListKey() { + return 'media_list'; + } + + /* implements method from TwilioResource */ + public override String getResourceLocation() + { + if (this.requestMessageSid != null) + { + return '/' + TwilioRestClient.DEFAULT_VERSION + + '/Accounts/' + this.getRequestAccountSid() + + '/Messages/' + this.getRequestMessageSid() + + '/Media.json'; + + } else { + return '/' + TwilioRestClient.DEFAULT_VERSION + + '/Accounts/' + this.getRequestAccountSid() + + '/Media.json'; + } + } + + public String getRequestMessageSid() { + return this.requestMessageSid; + } + + global Iterator iterator() + { + return new TwilioIterator.MediaIterator(this); + } +} \ No newline at end of file diff --git a/src/classes/TwilioMediaList.cls-meta.xml b/src/classes/TwilioMediaList.cls-meta.xml new file mode 100644 index 0000000..f165265 --- /dev/null +++ b/src/classes/TwilioMediaList.cls-meta.xml @@ -0,0 +1,5 @@ + + + 29.0 + Active + diff --git a/src/classes/TwilioMember.cls b/src/classes/TwilioMember.cls new file mode 100644 index 0000000..5115734 --- /dev/null +++ b/src/classes/TwilioMember.cls @@ -0,0 +1,3 @@ +global class TwilioMember { + +} \ No newline at end of file diff --git a/src/classes/TwilioMember.cls-meta.xml b/src/classes/TwilioMember.cls-meta.xml new file mode 100644 index 0000000..f165265 --- /dev/null +++ b/src/classes/TwilioMember.cls-meta.xml @@ -0,0 +1,5 @@ + + + 29.0 + Active + diff --git a/src/classes/TwilioMemberList.cls b/src/classes/TwilioMemberList.cls new file mode 100644 index 0000000..22f36f3 --- /dev/null +++ b/src/classes/TwilioMemberList.cls @@ -0,0 +1,3 @@ +global class TwilioMemberList { + +} \ No newline at end of file diff --git a/src/classes/TwilioMemberList.cls-meta.xml b/src/classes/TwilioMemberList.cls-meta.xml new file mode 100644 index 0000000..f165265 --- /dev/null +++ b/src/classes/TwilioMemberList.cls-meta.xml @@ -0,0 +1,5 @@ + + + 29.0 + Active + diff --git a/src/classes/TwilioMessage.cls b/src/classes/TwilioMessage.cls new file mode 100644 index 0000000..7a4b874 --- /dev/null +++ b/src/classes/TwilioMessage.cls @@ -0,0 +1,187 @@ +/** + * The class TwilioMessage. + * + * For more information see https://www.twilio.com/docs/api/rest/message + */ +global class TwilioMessage extends TwilioResource.InstanceResource { + + /** The Constant SID_PROPERTY. */ + private static final String SID_PROPERTY = 'sid'; + + /** + * Instantiates a new sms. + * + * @param client the client + */ + public TwilioMessage(TwilioRestClient client) { + super(client); + } + + /** + * Instantiates a new sms. + * + * @param client the client + * @param sid the sid + */ + public TwilioMessage(TwilioRestClient client, String sid) { + super(client); + this.setProperty(SID_PROPERTY, sid); + } + + /** + * Instantiates a new sms. + * + * @param client the client + * @param properties the properties + */ + public TwilioMessage(TwilioRestClient client, Map properties) { + super(client, properties); + } + + /* implements method from TwilioResource */ + public override String getResourceLocation() { + return '/' + TwilioRestClient.DEFAULT_VERSION + '/Accounts/' + + this.getRequestAccountSid() + '/Messages/' + this.getSid() + '.json'; + } + + /* + * Property getters + */ + /** + * Gets the sid. + * + * @return the sid + */ + public String getSid() { + return this.getProperty(SID_PROPERTY); + } + + /* DateCreated field accessor */ + public Datetime getDateCreated() { + return this.getPropertyDatetime('date_created'); + } + + /* DateUpdated field accessor */ + public Datetime getDateUpdated() { + return this.getPropertyDatetime('date_updated'); + } + + /* DateUpdated field accessor */ + public Datetime getDateSent() { + return this.getPropertyDatetime('date_sent'); + } + + /** + * Gets the account sid. + * + * @return the account sid + */ + public String getAccountSid() { + return this.getProperty('account_sid'); + } + + /** + * Gets the to. + * + * @return the to + */ + public String getTo() { + return this.getProperty('to'); + } + + /** + * Gets the from. + * + * @return the from + */ + public String getFrom() { + return this.getProperty('from'); + } + + /** + * Gets the body. + * + * @return the body + */ + public String getBody() { + return this.getProperty('body'); + } + + /** + * Gets the status. + * + * @return the status + */ + public String getStatus() { + return this.getProperty('status'); + } + + /** + * Gets the price. + * + * @return the price + */ + public String getPrice() { + return this.getProperty('price'); + } + + /** + * Gets the price. + * + * @return the price + */ + public String getPriceUnit() { + return this.getProperty('price_unit'); + } + + /** + * Gets the direction. + * + * @return the direction + */ + public String getDirection() { + return this.getProperty('direction'); + } + + /** + * Gets the api version. + * + * @return the api version + */ + public String getApiVersion() { + return this.getProperty('api_version'); + } + + public String getNumSegments() { + return this.getProperty('num_segments'); + } + + public String getNumMedia() { + return this.getProperty('num_media'); + } + + /** + * Returns the a list of media. + * + * @param the sid of a media instance associated with this message + * @return the MediaList associated with this message + */ + + public TwilioMedia getMedia(String mediaSid) + { + TwilioMedia media = new TwilioMedia(this.getClient(), this.getSid(), mediaSid); + media.setRequestAccountSid(this.getRequestAccountSid()); + return media; + } + + /** + * Returns the a list of media. + * + * @return the MediaList associated with this message + */ + public TwilioMediaList getMedia() { + TwilioMediaList media = new TwilioMediaList(this.getClient(), this.getSid()); + media.setRequestAccountSid(this.getRequestAccountSid()); + return media; + } +} \ No newline at end of file diff --git a/src/classes/TwilioMessage.cls-meta.xml b/src/classes/TwilioMessage.cls-meta.xml new file mode 100644 index 0000000..f165265 --- /dev/null +++ b/src/classes/TwilioMessage.cls-meta.xml @@ -0,0 +1,5 @@ + + + 29.0 + Active + diff --git a/src/classes/TwilioMessageList.cls b/src/classes/TwilioMessageList.cls new file mode 100644 index 0000000..14655bc --- /dev/null +++ b/src/classes/TwilioMessageList.cls @@ -0,0 +1,72 @@ +/** + * The class TwilioMessageList. + * + * For more information see http://www.twilio.com/docs/api/rest/message + */ +global class TwilioMessageList extends TwilioResource.ListResource implements Iterable { + + /** + * Instantiates a new sms list. + * + * @param client the client + */ + public TwilioMessageList(TwilioRestClient client) { + super(client); + } + + /** + * Instantiates a new sms list. + * + * @param client the client + * @param filters the filters + */ + public TwilioMessageList(TwilioRestClient client, Map filters) { + super(client, filters); + } + + /* implements method from TwilioResource */ + public override String getResourceLocation() { + return '/' + TwilioRestClient.DEFAULT_VERSION + '/Accounts/' + + this.getRequestAccountSid() + '/Messages.json'; + } + + /* implements method from TwilioResource.ListResource */ + public override Object makeNew(TwilioRestClient client, Map params) { + return new TwilioMessage(client, params); + } + + /* implements method from TwilioResource.ListResource */ + public override String getListKey() { + return 'messages'; + } + + /** + * Send a new message using the supplied parameters + * + * See http://www.twilio.com/docs/api/rest/sending-messages + * for a list of parameters + */ + public TwilioMessage create(Map params) { + return (TwilioMessage)this.createInstance(params); + } + + public TwilioMessage create(List params) { + return (TwilioMessage) this.createInstance(params); + } + + public List getPageData() { + List returnList = new List(); + + for (Object o : this.getObjectPageData()) { + if (o instanceof TwilioMessage) { + returnList.add((TwilioMessage) o); + } + } + return returnList; + } + + global Iterator iterator() { + return new TwilioIterator.MessageIterator(this); + } + +} \ No newline at end of file diff --git a/src/classes/TwilioMessageList.cls-meta.xml b/src/classes/TwilioMessageList.cls-meta.xml new file mode 100644 index 0000000..f165265 --- /dev/null +++ b/src/classes/TwilioMessageList.cls-meta.xml @@ -0,0 +1,5 @@ + + + 29.0 + Active + diff --git a/src/classes/TwilioNameValuePair.cls b/src/classes/TwilioNameValuePair.cls new file mode 100644 index 0000000..fd13256 --- /dev/null +++ b/src/classes/TwilioNameValuePair.cls @@ -0,0 +1,23 @@ +/** + * This class is used to hold a key/value POST param. + */ +global class TwilioNameValuePair { + + private String name; + + private String value; + + public TwilioNameValuePair(String name, String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + +} \ No newline at end of file diff --git a/src/classes/TwilioNameValuePair.cls-meta.xml b/src/classes/TwilioNameValuePair.cls-meta.xml new file mode 100644 index 0000000..f165265 --- /dev/null +++ b/src/classes/TwilioNameValuePair.cls-meta.xml @@ -0,0 +1,5 @@ + + + 29.0 + Active + diff --git a/src/classes/TwilioQueue.cls b/src/classes/TwilioQueue.cls new file mode 100644 index 0000000..d38eab2 --- /dev/null +++ b/src/classes/TwilioQueue.cls @@ -0,0 +1,3 @@ +global class TwilioQueue { + +} \ No newline at end of file diff --git a/src/classes/TwilioQueue.cls-meta.xml b/src/classes/TwilioQueue.cls-meta.xml new file mode 100644 index 0000000..f165265 --- /dev/null +++ b/src/classes/TwilioQueue.cls-meta.xml @@ -0,0 +1,5 @@ + + + 29.0 + Active + diff --git a/src/classes/TwilioQueueList.cls b/src/classes/TwilioQueueList.cls new file mode 100644 index 0000000..c08008e --- /dev/null +++ b/src/classes/TwilioQueueList.cls @@ -0,0 +1,3 @@ +global class TwilioQueueList { + +} \ No newline at end of file diff --git a/src/classes/TwilioQueueList.cls-meta.xml b/src/classes/TwilioQueueList.cls-meta.xml new file mode 100644 index 0000000..f165265 --- /dev/null +++ b/src/classes/TwilioQueueList.cls-meta.xml @@ -0,0 +1,5 @@ + + + 29.0 + Active + diff --git a/src/classes/TwilioResource.cls b/src/classes/TwilioResource.cls index bf60398..052bfd7 100644 --- a/src/classes/TwilioResource.cls +++ b/src/classes/TwilioResource.cls @@ -442,6 +442,12 @@ public abstract class TwilioResource return makeNew(this.getClient(), response.toMap()); } + /* implements method from TwilioResource.ListResource */ + public Object createInstance(List params) { + TwilioRestResponse response = this.getClient().safeRequestPair( + this.getResourceLocation(), 'POST', params); + return makeNew(this.getClient(), response.toMap()); + } /** * Gets the page data. diff --git a/src/classes/TwilioRestClient.cls b/src/classes/TwilioRestClient.cls index 85947cb..dc7a5c3 100644 --- a/src/classes/TwilioRestClient.cls +++ b/src/classes/TwilioRestClient.cls @@ -27,554 +27,739 @@ OTHER DEALINGS IN THE SOFTWARE. */ public class TwilioRestClient { - /** The Constant VERSION. */ - private static final String VERSION = '3.0'; + /** The Constant VERSION. */ + private static final String VERSION = '3.0'; - /** The endpoint. */ - private String endpoint = 'https://api.twilio.com'; + /** The endpoint. */ + private String endpoint = 'https://api.twilio.com'; - /** The Constant DEFAULT_VERSION. */ - public static final String DEFAULT_VERSION = '2010-04-01'; + /** The Constant DEFAULT_VERSION. */ + public static final String DEFAULT_VERSION = '2010-04-01'; - /** The account sid. */ - private String accountSid; + /** The account sid. */ + private String accountSid; - /** The auth token. */ - private String authToken; + /** The auth token. */ + private String authToken; - /** The num retries. */ - private Integer numRetries = 3; + /** The num retries. */ + private Integer numRetries = 3; - /** The auth account. */ - private TwilioAccount authAccount; - - /** - * Explcitly construct a TwilioRestClient with the given API credentials. - * - * @param accountSid - * the 34 character Account identifier (starting with 'AC'). This - * can be found on your Twilio dashboard page. - * @param authToken - * the 32 character AuthToken. This can be found on your Twilio - * dashboard page. - * - */ - public TwilioRestClient(String accountSid, String authToken) { - this(accountSid, authToken, null); - } - - /** - * Explcitly construct a TwilioRestClient with the given API credentials and - * endpoint. - * - * @param accountSid - * the 34 character Account identifier (starting with 'AC'). This - * can be found on your Twilio dashboard page. - * @param authToken - * the 32 character AuthToken. This can be found on your Twilio - * dashboard page. - * @param endpoint - * the url of API endpoint you wish to use. (e.g. - - * 'https://api.twilio.com') - */ - public TwilioRestClient(String accountSid, String authToken, String endpoint) { - - validateAccountSid(accountSid); - validateAuthToken(authToken); - - this.accountSid = accountSid; - this.authToken = authToken; - - if ((endpoint != null) && (!endpoint.equals(''))) { - this.endpoint = endpoint; - } - this.authAccount = new TwilioAccount(this); - this.authAccount.setSid(this.accountSid); - this.authAccount.setAuthToken(this.authToken); - - } - - /** - * Gets the num retries. - * - * @return the num retries - */ - public Integer getNumRetries() { - return numRetries; - } - - /** - * Sets the num retries. - * - * @param numRetries - * the new num retries - */ - public void setNumRetries(Integer numRetries) { - this.numRetries = numRetries; - } - - // Check for a valid 32 character auth token - /** - * Validate auth token. - * - * @param authToken - * the auth token - */ - private void validateAuthToken(String authToken) { - if (authToken == null || authToken.length() != 32) - throw new TwilioRestException('AuthToken \'' + authToken + '\' is not valid.'); - } - - // Check for a valid 34 character account sid starting with 'AC' - /** - * Validate account sid. - * - * @param accountSid - * the account sid - */ - private void validateAccountSid(String accountSid) { - if (accountSid == null || !accountSid.startsWith('AC') || accountSid.length() != 34) - throw new TwilioRestException('AccountSid \'' + accountSid + '\' is not valid. It should be the 34 character unique identifier starting with \'AC\''); - } - - - /* - * - * Method builders - */ - /** - * Builds the method. - * - * @param method - * the method - * @param path - * the path - * @param params - * the params - * @return the http uri request - */ - private HttpRequest buildMethod(String method, String path, - Map params) { - if (method.equalsIgnoreCase('GET')) { - return generateGetRequest(path, params); - } else if (method.equalsIgnoreCase('POST')) { - return generatePostRequest(path, params); - } else if (method.equalsIgnoreCase('PUT')) { - return generatePutRequest(path, params); - } else if (method.equalsIgnoreCase('DELETE')) { - return generateDeleteRequest(path, params); - } else { - throw new TwilioRestException('Unknown Method: ' + method); - } - } - - /** - * Generate get request. - * - * @param path - * the path - * @param params - * the params - * @return the http get - */ - private HttpRequest generateGetRequest(String path, Map params) { - - URL uri = buildUri(path, params); - HttpRequest req = new HttpRequest(); - req.setEndpoint(uri.toExternalForm()); - req.setMethod('GET'); - return req; - } - - /** - * Generate post request. - * - * @param path - * the path - * @param params - * the params - * @return the http post - */ - private HttpRequest generatePostRequest(String path, Map params) { - URL uri = buildUri(path); - - String entity = buildEntityBody(params); - - HttpRequest req = new HttpRequest(); - req.setEndpoint(uri.toExternalForm()); - req.setMethod('POST'); - req.setBody(entity); - - return req; - } - - /** - * Generate put request. - * - * @param path - * the path - * @param params - * the params - * @return the http put - */ - private HttpRequest generatePutRequest(String path, Map params) { - URL uri = buildUri(path); - - String entity = buildEntityBody(params); - - HttpRequest req = new HttpRequest(); - req.setEndpoint(uri.toExternalForm()); - req.setMethod('PUT'); - req.setBody(entity); - - return req; - } - - /** - * Generate delete request. - * - * @param path - * the path - * @param params - * the params - * @return the http delete - */ - private HttpRequest generateDeleteRequest(String path, - Map params) { - URL uri = buildUri(path); - - HttpRequest req = new HttpRequest(); - req.setEndpoint(uri.toExternalForm()); - req.setMethod('DELETE'); - return req; - } - - /* - * - * Helper functions for building methods - */ - /** - * Builds the entity body. - * - * @param params - * the params - * @return the url encoded form entity - */ - private String buildEntityBody(Map params) { - String entityBody=''; - if (params != null) { - for (String key : params.keySet()) { - try { - entityBody += (entityBody=='' ? '' : '&') - + key + '=' + EncodingUtil.urlEncode(params.get(key), 'UTF-8'); - } catch (Exception e) { - System.debug('ERROR: ' + e); - } - } - } - return entityBody; - } - - /** - * Builds the uri. - * - * @param path - * the path - * @return the uRI - */ - private URL buildUri(String path) { - return buildUri(path, null); - } - - /** - * Builds the uri. - * - * @param path - * the path - * @param queryStringParams - * the query string params - * @return the uRI - */ - private URL buildUri(String path, Map queryStringParams) { - String sb = path; - - if (queryStringParams != null && queryStringParams.size() > 0) { - sb += '?'; - sb += buildEntityBody(queryStringParams); - } - - URL uri; - try { - uri = new URL(sb); - } catch (Exception e) { - throw new TwilioRestException('Invalid uri: '+sb, e); - } - - return uri; - } - - /** - * sendRequst Sends a REST Request to the Twilio REST API. - * - * @param path - * the URL (absolute w.r.t. the endpoint URL - i.e. - * /2010-04-01/Accounts) - * @param method - * the HTTP method to use, defaults to GET - * @param vars - * for POST or PUT, a map of data to send, for GET will be - * appended to the URL as querystring params - * - * This method is public for backwards compatibility with the old - * twilio helper library - * @return the twilio rest response - */ - public TwilioRestResponse request(String path, String method, - Map vars) { - - HttpRequest request = setupRequest(path, method, vars); - - String responseBody; - Integer statusCode; - String contentType; - if (Test.isRunningTest()) { - // can't execute HTTP requests during test execution - Twilio_TestHTTPMock.Response responseMock = Twilio_TestHTTPMock.getInstance().send(request); - responseBody = (responseMock.getBody()==null)?'':responseMock.getBody(); - statusCode = responseMock.getStatusCode(); - contentType = responseMock.getHeader('Content-Type'); - } else { - // execute HTTP request - HttpResponse response = (new Http()).send(request); - responseBody = (response.getBody()==null)?'':response.getBody(); - system.debug(responseBody+'-----------------------------------------'+response); - statusCode = response.getStatusCode(); - contentType = response.getHeader('Content-Type'); - } - TwilioRestResponse restResponse = new TwilioRestResponse(request.getEndpoint(), - responseBody, statusCode); - restResponse.setContentType(contentType); - - return restResponse; - } - - /** - * Setup request. - * - * @param path - * the path - * @param method - * the method - * @param vars - * the vars - * @return the http uri request - */ - private HttpRequest setupRequest(String path, String method, - Map params) { - - String normalizedPath = path.toLowerCase(); - String sb = ''; - - // If we've given a fully qualified uri then skip building the endpoint - if (normalizedPath.startsWith('http://') - || normalizedPath.startsWith('https://')) { - sb += path; - } else { - sb += this.getEndpoint(); - - if (!normalizedPath.startsWith('/')) { - sb += '/'; - } - sb += path; - } - - path = sb; - - HttpRequest request = buildMethod(method, path, params); - - request.setHeader('X-Twilio-Client', 'salesforce-' + VERSION); - request.setHeader('User-Agent', 'twilio-salesforce-' + VERSION); - request.setHeader('Accept', 'application/json'); - - request.setHeader('Authorization', - 'Basic '+EncodingUtil.base64Encode(Blob.valueOf(this.accountSid + ':' + this.authToken))); - - return request; - } - - /** - * Make a request, handles retries + back-off for server/network errors - * - * @param path - * the URL (absolute w.r.t. the endpoint URL - i.e. - * /2010-04-01/Accounts) - * @param method - * the HTTP method to use, defaults to GET - * @param vars - * for POST or PUT, a map of data to send, for GET will be - * appended to the URL as querystring params - * @return The response - */ - public TwilioRestResponse safeRequest(String path, String method, - Map vars) { - TwilioRestResponse response = null; - for (Integer retry = 0; retry < this.numRetries; retry++) { - response = request(path, method, vars); - if (response.isClientError()) { - System.debug('Twilio REST API Client Error: '+response.getResponseText()); - throw new TwilioRestException(response); - } else if (response.isServerError()) { - // TODO handle backoff scenario - //try { - // Thread.sleep(100 * retry); // Backoff on our sleep - //} catch (Exception e) { - //} - continue; - } - - return response; - } - Integer errorCode = response == null ? -1 : response.getHttpStatus(); - throw new TwilioRestException('Cannot fetch: ' + method + ' ' + path, - errorCode); - } - - /** - * Perform a GET request against the given fully qualified uri. - * - * @param fullUri the full uri, including protocol://hostname/path - * @return the response from the query - */ - public TwilioRestResponse get(String fullUri) { - TwilioRestResponse response = null; - - for (Integer retry = 0; retry < this.numRetries; retry++) { - response = request(fullUri, 'GET', null); - if (response.isClientError()) { - throw new TwilioRestException(response); - } else if (response.isServerError()) { - //try { - // Thread.sleep(100 * retry); // Backoff on our sleep - //} catch (InterruptedException e) { - //} - continue; - } - - return response; - } - Integer errorCode = response == null ? -1 : response.getHttpStatus(); - throw new TwilioRestException('Cannot fetch: ' + fullUri + ' ', - errorCode); - } - - /** - * Get the current endpoint this client is pointed at. - * - * @return String the api endpoint - */ - public String getEndpoint() { - return endpoint; - } - - /** - * Set the endpoint this rest client uses. - * - * @param endpoint - * The location of the endpoint (e.g. https://api.twilio.com) - */ - public void setEndpoint(String endpoint) { - this.endpoint = endpoint; - } - - /* - * Resource related methods - */ - /** - * Get a list of Account objects. - * - * For more info see http://www.twilio.com/docs/api/rest/account - * - * @param params - * Filter the list with the given params. See the Twilio docs for - * available filters. - * @return the list of accounts. - */ - public TwilioAccountList getAccounts(Map params) { - TwilioAccountList aclist = new TwilioAccountList(this, params); - aclist.setRequestAccountSid(this.accountSid); - return aclist; - } - - /** - * Get all accounts. - * - * For more info see http://www.twilio.com/docs/api/rest/account - * - * @return the list of accounts. - */ - public TwilioAccountList getAccounts() { - return this.getAccounts(new Map()); - } - - /** - * A shortcut for the most common case, returning the Account object for - * this authenticated client. - * - * @return Account that maps to the authenticated account. - */ - public TwilioAccount getAccount() { - return this.authAccount; - } + /** The auth account. */ + private TwilioAccount authAccount; + + /** + * Explcitly construct a TwilioRestClient with the given API credentials. + * + * @param accountSid + * the 34 character Account identifier (starting with 'AC'). This + * can be found on your Twilio dashboard page. + * @param authToken + * the 32 character AuthToken. This can be found on your Twilio + * dashboard page. + * + */ + public TwilioRestClient(String accountSid, String authToken) { + this(accountSid, authToken, null); + } + + /** + * Explcitly construct a TwilioRestClient with the given API credentials and + * endpoint. + * + * @param accountSid + * the 34 character Account identifier (starting with 'AC'). This + * can be found on your Twilio dashboard page. + * @param authToken + * the 32 character AuthToken. This can be found on your Twilio + * dashboard page. + * @param endpoint + * the url of API endpoint you wish to use. (e.g. - + * 'https://api.twilio.com') + */ + public TwilioRestClient(String accountSid, String authToken, String endpoint) { + + validateAccountSid(accountSid); + validateAuthToken(authToken); + + this.accountSid = accountSid; + this.authToken = authToken; + + if ((endpoint != null) && (!endpoint.equals(''))) { + this.endpoint = endpoint; + } + this.authAccount = new TwilioAccount(this); + this.authAccount.setSid(this.accountSid); + this.authAccount.setAuthToken(this.authToken); + + } + + /** + * Gets the num retries. + * + * @return the num retries + */ + public Integer getNumRetries() { + return numRetries; + } + + /** + * Sets the num retries. + * + * @param numRetries + * the new num retries + */ + public void setNumRetries(Integer numRetries) { + this.numRetries = numRetries; + } + + // Check for a valid 32 character auth token + /** + * Validate auth token. + * + * @param authToken + * the auth token + */ + private void validateAuthToken(String authToken) { + if (authToken == null || authToken.length() != 32) + throw new TwilioRestException('AuthToken \'' + authToken + '\' is not valid.'); + } + + // Check for a valid 34 character account sid starting with 'AC' + /** + * Validate account sid. + * + * @param accountSid + * the account sid + */ + private void validateAccountSid(String accountSid) { + if (accountSid == null || !accountSid.startsWith('AC') || accountSid.length() != 34) + throw new TwilioRestException('AccountSid \'' + accountSid + '\' is not valid. It should be the 34 character unique identifier starting with \'AC\''); + } + + + /* + * + * Method builders + */ + /** + * Builds the method. + * + * @param method + * the method + * @param path + * the path + * @param params + * the params + * @return the http uri request + */ + private HttpRequest buildMethod(String method, String path, + Map params) { + if (method.equalsIgnoreCase('GET')) { + return generateGetRequest(path, params); + } else if (method.equalsIgnoreCase('POST')) { + return generatePostRequest(path, params); + } else if (method.equalsIgnoreCase('PUT')) { + return generatePutRequest(path, params); + } else if (method.equalsIgnoreCase('DELETE')) { + return generateDeleteRequest(path, params); + } else { + throw new TwilioRestException('Unknown Method: ' + method); + } + } + + private HttpRequest buildMethod(String method, String path, List params) + { + if (method.equalsIgnoreCase('GET')) { + return generateGetRequest(path, params); + } else if (method.equalsIgnoreCase('POST')) { + return generatePostRequest(path, params); + } else if (method.equalsIgnoreCase('PUT')) { + return generatePutRequest(path, params); + } else if (method.equalsIgnoreCase('DELETE')) { + return generateDeleteRequest(path, params); + } else { + throw new TwilioRestException('Unknown Method: ' + method); + } + } + + /** + * Generate get request. + * + * @param path + * the path + * @param params + * the params + * @return the http get + */ + private HttpRequest generateGetRequest(String path, Map params) { + + URL uri = buildUri(path, params); + HttpRequest req = new HttpRequest(); + req.setEndpoint(uri.toExternalForm()); + req.setMethod('GET'); + return req; + } + + private HttpRequest generateGetRequest(String path, List params) { + + URL uri = buildUri(path, params); + HttpRequest req = new HttpRequest(); + req.setEndpoint(uri.toExternalForm()); + req.setMethod('GET'); + return req; + } + + /** + * Generate post request. + * + * @param path + * the path + * @param params + * the params + * @return the http post + */ + private HttpRequest generatePostRequest(String path, Map params) { + URL uri = buildUri(path); + + String entity = buildEntityBody(params); + + HttpRequest req = new HttpRequest(); + req.setEndpoint(uri.toExternalForm()); + req.setMethod('POST'); + req.setBody(entity); + + return req; + } + + private HttpRequest generatePostRequest(String path, List params) { + URL uri = buildUri(path); + + String entity = buildEntityBody(params); + + HttpRequest req = new HttpRequest(); + req.setEndpoint(uri.toExternalForm()); + req.setMethod('POST'); + req.setBody(entity); + + return req; + } + /** + * Generate put request. + * + * @param path + * the path + * @param params + * the params + * @return the http put + */ + private HttpRequest generatePutRequest(String path, Map params) { + URL uri = buildUri(path); + + String entity = buildEntityBody(params); + + HttpRequest req = new HttpRequest(); + req.setEndpoint(uri.toExternalForm()); + req.setMethod('PUT'); + req.setBody(entity); + + return req; + } + + private HttpRequest generatePutRequest(String path, List params) { + URL uri = buildUri(path); + + String entity = buildEntityBody(params); + + HttpRequest req = new HttpRequest(); + req.setEndpoint(uri.toExternalForm()); + req.setMethod('PUT'); + req.setBody(entity); + + return req; + } + /** + * Generate delete request. + * + * @param path + * the path + * @param params + * the params + * @return the http delete + */ + private HttpRequest generateDeleteRequest(String path, + Map params) { + URL uri = buildUri(path); + + HttpRequest req = new HttpRequest(); + req.setEndpoint(uri.toExternalForm()); + req.setMethod('DELETE'); + return req; + } + + private HttpRequest generateDeleteRequest(String path,List params) { + URL uri = buildUri(path); + + HttpRequest req = new HttpRequest(); + req.setEndpoint(uri.toExternalForm()); + req.setMethod('DELETE'); + return req; + } + /* + * + * Helper functions for building methods + */ + /** + * Builds the entity body. + * + * @param params + * the params + * @return the url encoded form entity + */ + private String buildEntityBody(Map params) { + String entityBody=''; + if (params != null) { + for (String key : params.keySet()) { + try { + entityBody += (entityBody=='' ? '' : '&') + + key + '=' + EncodingUtil.urlEncode(params.get(key), 'UTF-8'); + } catch (Exception e) { + System.debug('ERROR: ' + e); + } + } + } + return entityBody; + } + + private String buildEntityBody(List params) { + String entityBody=''; + if (params != null) { + for (TwilioNameValuePair param : params) { + try { + entityBody += (entityBody=='' ? '' : '&') + + param.getName() + '=' + EncodingUtil.urlEncode(param.getValue(), 'UTF-8'); + } catch (Exception e) { + System.debug('ERROR: ' + e); + } + } + } + return entityBody; + } + /** + * Builds the uri. + * + * @param path + * the path + * @return the uRI + */ + private URL buildUri(String path) { + return buildUri(path, new Map()); + } + + /** + * Builds the uri. + * + * @param path + * the path + * @param queryStringParams + * the query string params + * @return the uRI + */ + private URL buildUri(String path, Map queryStringParams) { + String sb = path; + + if (queryStringParams != null && queryStringParams.size() > 0) { + sb += '?'; + sb += buildEntityBody(queryStringParams); + } + + URL uri; + try { + uri = new URL(sb); + } catch (Exception e) { + throw new TwilioRestException('Invalid uri: '+sb, e); + } + + return uri; + } + + private URL buildUri(String path, List queryStringParams) { + String sb = path; + + if (queryStringParams != null && queryStringParams.size() > 0) { + sb += '?'; + sb += buildEntityBody(queryStringParams); + } + + URL uri; + try { + uri = new URL(sb); + } catch (Exception e) { + throw new TwilioRestException('Invalid uri: '+sb, e); + } + + return uri; + } + /** + * sendRequst Sends a REST Request to the Twilio REST API. + * + * @param path + * the URL (absolute w.r.t. the endpoint URL - i.e. + * /2010-04-01/Accounts) + * @param method + * the HTTP method to use, defaults to GET + * @param vars + * for POST or PUT, a map of data to send, for GET will be + * appended to the URL as querystring params + * + * This method is public for backwards compatibility with the old + * twilio helper library + * @return the twilio rest response + */ + public TwilioRestResponse request(String path, String method, + Map vars) { + + HttpRequest request = setupRequest(path, method, vars); + + String responseBody; + Integer statusCode; + String contentType; + if (Test.isRunningTest()) { + // can't execute HTTP requests during test execution + system.debug('Request :'+request); + Twilio_TestHTTPMock.Response responseMock = Twilio_TestHTTPMock.getInstance().send(request); + system.debug(responseMock); + responseBody = (responseMock.getBody()==null)?'':responseMock.getBody(); + statusCode = responseMock.getStatusCode(); + contentType = responseMock.getHeader('Content-Type'); + } else { + // execute HTTP request + HttpResponse response = (new Http()).send(request); + responseBody = (response.getBody()==null)?'':response.getBody(); + system.debug(responseBody+'-----------------------------------------'+response); + statusCode = response.getStatusCode(); + contentType = response.getHeader('Content-Type'); + } + TwilioRestResponse restResponse = new TwilioRestResponse(request.getEndpoint(), + responseBody, statusCode); + restResponse.setContentType(contentType); + + return restResponse; + } + + private static List generateParameters(Map vars) + { + List qparams = new List(); + + if (vars != null) + { + for (String var : vars.keySet()) + { + qparams.add(new TwilioNameValuePair(var, vars.get(var))); + } + } + + return qparams; + } + + public TwilioRestResponse request(String path, String method,List paramList) { + + HttpRequest request = setupRequest(path, method, paramList); + + String responseBody; + Integer statusCode; + String contentType; + if (Test.isRunningTest()) { + // can't execute HTTP requests during test execution + Twilio_TestHTTPMock.Response responseMock = Twilio_TestHTTPMock.getInstance().send(request); + responseBody = (responseMock.getBody()==null)?'':responseMock.getBody(); + statusCode = responseMock.getStatusCode(); + contentType = responseMock.getHeader('Content-Type'); + } else { + // execute HTTP request + HttpResponse response = (new Http()).send(request); + responseBody = (response.getBody()==null)?'':response.getBody(); + system.debug(responseBody+'-----------------------------------------'+response); + statusCode = response.getStatusCode(); + contentType = response.getHeader('Content-Type'); + } + TwilioRestResponse restResponse = new TwilioRestResponse(request.getEndpoint(), + responseBody, statusCode); + restResponse.setContentType(contentType); + + return restResponse; + } + /** + * Setup request. + * + * @param path + * the path + * @param method + * the method + * @param vars + * the vars + * @return the http uri request + */ + private HttpRequest setupRequest(String path, String method, + Map params) { + + String normalizedPath = path.toLowerCase(); + String sb = ''; + + // If we've given a fully qualified uri then skip building the endpoint + if (normalizedPath.startsWith('http://') + || normalizedPath.startsWith('https://')) { + sb += path; + } else { + sb += this.getEndpoint(); + + if (!normalizedPath.startsWith('/')) { + sb += '/'; + } + sb += path; + } + + path = sb; + + HttpRequest request = buildMethod(method, path, params); + + request.setHeader('X-Twilio-Client', 'salesforce-' + VERSION); + request.setHeader('User-Agent', 'twilio-salesforce-' + VERSION); + request.setHeader('Accept', 'application/json'); + + request.setHeader('Authorization', + 'Basic '+EncodingUtil.base64Encode(Blob.valueOf(this.accountSid + ':' + this.authToken))); + + return request; + } + + private HttpRequest setupRequest(String path, String method, + List params) { + + String normalizedPath = path.toLowerCase(); + String sb = ''; + + // If we've given a fully qualified uri then skip building the endpoint + if (normalizedPath.startsWith('http://') + || normalizedPath.startsWith('https://')) { + sb += path; + } else { + sb += this.getEndpoint(); + + if (!normalizedPath.startsWith('/')) { + sb += '/'; + } + sb += path; + } + + path = sb; + + HttpRequest request = buildMethod(method, path, params); + + request.setHeader('X-Twilio-Client', 'salesforce-' + VERSION); + request.setHeader('User-Agent', 'twilio-salesforce-' + VERSION); + request.setHeader('Accept', 'application/json'); + + request.setHeader('Authorization', + 'Basic '+EncodingUtil.base64Encode(Blob.valueOf(this.accountSid + ':' + this.authToken))); + + return request; + } + + /** + * Make a request, handles retries + back-off for server/network errors + * + * @param path + * the URL (absolute w.r.t. the endpoint URL - i.e. + * /2010-04-01/Accounts) + * @param method + * the HTTP method to use, defaults to GET + * @param vars + * for POST or PUT, a map of data to send, for GET will be + * appended to the URL as querystring params + * @return The response + */ + public TwilioRestResponse safeRequest(String path, String method, + Map vars) { + TwilioRestResponse response = null; + for (Integer retry = 0; retry < this.numRetries; retry++) { + response = request(path, method, vars); + if (response.isClientError()) { + System.debug('Twilio REST API Client Error: '+response.getResponseText()); + throw new TwilioRestException(response); + } else if (response.isServerError()) { + // TODO handle backoff scenario + //try { + // Thread.sleep(100 * retry); // Backoff on our sleep + //} catch (Exception e) { + //} + continue; + } + + return response; + } + Integer errorCode = response == null ? -1 : response.getHttpStatus(); + throw new TwilioRestException('Cannot fetch: ' + method + ' ' + path, + errorCode); + } + + public TwilioRestResponse safeRequestPair(String path, String method, + List paramList) + { + TwilioRestResponse response = null; + for (Integer retry = 0; retry < this.numRetries; retry++) + { + response = request(path, method, paramList); + if (response.isClientError()) { + System.debug('Twilio REST API Client Error: '+response.getResponseText()); + throw new TwilioRestException(response); + } else if (response.isServerError()) { + continue; + } + + return response; + } + Integer errorCode = response == null ? -1 : response.getHttpStatus(); + throw new TwilioRestException('Cannot fetch: ' + method + ' ' + path, + errorCode); + } + + /** + * Perform a GET request against the given fully qualified uri. + * + * @param fullUri the full uri, including protocol://hostname/path + * @return the response from the query + */ + public TwilioRestResponse get(String fullUri) { + TwilioRestResponse response = null; + + for (Integer retry = 0; retry < this.numRetries; retry++) { + response = request(fullUri, 'GET', new Map()); + if (response.isClientError()) { + throw new TwilioRestException(response); + } else if (response.isServerError()) { + //try { + // Thread.sleep(100 * retry); // Backoff on our sleep + //} catch (InterruptedException e) { + //} + continue; + } + + return response; + } + Integer errorCode = response == null ? -1 : response.getHttpStatus(); + throw new TwilioRestException('Cannot fetch: ' + fullUri + ' ', + errorCode); + } + + /** + * Get the current endpoint this client is pointed at. + * + * @return String the api endpoint + */ + public String getEndpoint() { + return endpoint; + } + + /** + * Set the endpoint this rest client uses. + * + * @param endpoint + * The location of the endpoint (e.g. https://api.twilio.com) + */ + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + /* + * Resource related methods + */ + /** + * Get a list of Account objects. + * + * For more info see http://www.twilio.com/docs/api/rest/account + * + * @param params + * Filter the list with the given params. See the Twilio docs for + * available filters. + * @return the list of accounts. + */ + public TwilioAccountList getAccounts(Map params) { + TwilioAccountList aclist = new TwilioAccountList(this, params); + aclist.setRequestAccountSid(this.accountSid); + return aclist; + } + + /** + * Get all accounts. + * + * For more info see http://www.twilio.com/docs/api/rest/account + * + * @return the list of accounts. + */ + public TwilioAccountList getAccounts() { + return this.getAccounts(new Map()); + } + + /** + * A shortcut for the most common case, returning the Account object for + * this authenticated client. + * + * @return Account that maps to the authenticated account. + */ + public TwilioAccount getAccount() { + return this.authAccount; + } /*shs - public TwilioAccount getAccount(map s) { - TwilioAccount account = new TwilioAccount(this,s); - - return account; - } - */ - /** - * Get an account by account sid. - * - * @param sid - * The sid of the account you want to fetch. - * @return the account - */ - public TwilioAccount getAccount(String sid) { - TwilioAccount account = new TwilioAccount(this); - account.setSid(sid); - account.setRequestAccountSid(sid); - - return account; - } - - public String getAccountSid() { - return this.accountSid; - } - - /** - * Validate the signature on an incoming call from Twilio - * - * @param expectedSignature - * The received signature. In an Apex REST method, this will be - * RestContext.request.headers.get('X-Twilio-Signature'). - * - * @param url - * The endpoint URL, for example - * https://mysite.force.com/services/apexrest/twiliosms. - * In an Apex REST method, this will be 'https://' + - * RestContext.request.headers.get('Host') + '/services/apexrest' + - * RestContext.request.requestURI. - * - * @param params - * The params map from the incoming message. In an Apex REST method, - * this will be RestContext.request.params. - * - * @return true if the signature is valid, false otherwise - */ - public boolean validateRequest(String expectedSignature, String url, Map params) { - try { - // sort the params alphabetically, and append the key and value of each to the url - String data = url; + public TwilioAccount getAccount(map s) { + TwilioAccount account = new TwilioAccount(this,s); + + return account; + } + */ + /** + * Get an account by account sid. + * + * @param sid + * The sid of the account you want to fetch. + * @return the account + */ + public TwilioAccount getAccount(String sid) { + TwilioAccount account = new TwilioAccount(this); + account.setSid(sid); + account.setRequestAccountSid(sid); + + return account; + } + + public String getAccountSid() { + return this.accountSid; + } + + /** + * Validate the signature on an incoming call from Twilio + * + * @param expectedSignature + * The received signature. In an Apex REST method, this will be + * RestContext.request.headers.get('X-Twilio-Signature'). + * + * @param url + * The endpoint URL, for example + * https://mysite.force.com/services/apexrest/twiliosms. + * In an Apex REST method, this will be 'https://' + + * RestContext.request.headers.get('Host') + '/services/apexrest' + + * RestContext.request.requestURI. + * + * @param params + * The params map from the incoming message. In an Apex REST method, + * this will be RestContext.request.params. + * + * @return true if the signature is valid, false otherwise + */ + public boolean validateRequest(String expectedSignature, String url, Map params) { + try { + // sort the params alphabetically, and append the key and value of each to the url + String data = url; if(params!=null){ List sortedKeys = new List(params.keySet()); sortedKeys.sort(); @@ -588,15 +773,15 @@ public class TwilioRestClient { } } - //compute the hmac on input data bytes, with AuthToken as key + //compute the hmac on input data bytes, with AuthToken as key Blob mac = Crypto.generateMac('hmacSHA1', Blob.valueOf(data), Blob.valueOf(authToken)); //base64-encode the hmac - String signature = EncodingUtil.base64Encode(mac); + String signature = EncodingUtil.base64Encode(mac); return signature.equals(expectedSignature); - } catch (Exception e) { - return false; - } - } + } catch (Exception e) { + return false; + } + } } \ No newline at end of file diff --git a/src/classes/Twilio_TestHTTPMock.cls b/src/classes/Twilio_TestHTTPMock.cls index 8218713..37d441f 100644 --- a/src/classes/Twilio_TestHTTPMock.cls +++ b/src/classes/Twilio_TestHTTPMock.cls @@ -29,101 +29,103 @@ OTHER DEALINGS IN THE SOFTWARE. * * Usage: * Twilio_TestHTTPMock.getInstance().putResponse( - * 'GET', - * 'https://api.twilio.com/2010-04-01/Accounts/ACbaabc55eacf55afdae555e555c5cc55a.json', - * new Twilio_TestHTTPMock.Response( - * '{ "sid": "ACbaabc55eacf55afdae555e555c5cc55a","friendly_name": "My Test Account" }', - * 200) - * ); + * 'GET', + * 'https://api.twilio.com/2010-04-01/Accounts/ACbaabc55eacf55afdae555e555c5cc55a.json', + * new Twilio_TestHTTPMock.Response( + * '{ "sid": "ACbaabc55eacf55afdae555e555c5cc55a","friendly_name": "My Test Account" }', + * 200) + * ); */ public class Twilio_TestHTTPMock { - /** singleton */ - private final static Twilio_TestHTTPMock instance = new Twilio_TestHTTPMock(); - /** get singleton */ - public static Twilio_TestHTTPMock getInstance() { return Twilio_TestHTTPMock.instance; } + /** singleton */ + private final static Twilio_TestHTTPMock instance = new Twilio_TestHTTPMock(); + /** get singleton */ + public static Twilio_TestHTTPMock getInstance() { return Twilio_TestHTTPMock.instance; } - /** 404 NOT FOUND error */ - private static Response response404 = new Response('{"status": 404, "message": "The requested resource was not found"}', 404); + /** 404 NOT FOUND error */ + private static Response response404 = new Response('{"status": 404, "message": "The requested resource was not found"}', 404); - /** instance methods */ - private Map> methodMap = new Map>(); - - /** Mock HTTP.send(HTTPRequest) function, returns a preregistered Response or a 404 */ - public Response send(HTTPRequest req) { - System.debug('Twilio_TestHTTPMock::send() Request.Method: '+req.getMethod()); - System.debug('Twilio_TestHTTPMock::send() Request.Endpoint: '+req.getEndpoint()); + /** instance methods */ + private Map> methodMap = new Map>(); + + /** Mock HTTP.send(HTTPRequest) function, returns a preregistered Response or a 404 */ + public Response send(HTTPRequest req) { + System.debug('Twilio_TestHTTPMock::send() Request.Method: '+req.getMethod()); + System.debug('Twilio_TestHTTPMock::send() Request.Endpoint: '+req.getEndpoint()); - Response res = getResponse(req.getMethod(), req.getEndpoint()); - if (res==null) { - res = response404; - } - System.debug('Twilio_TestHTTPMock::send() Response.Body: '+res.getBody()); + Response res = getResponse(req.getMethod(), req.getEndpoint()); + if (res==null) { + res = response404; + } + System.debug('Twilio_TestHTTPMock::send() Response.Body: '+res.getBody()); - return res; - } - - /** Looks up the response for a specific HTTP method and URI. Returns null if none found. */ - public Response getResponse(String method, String uri) { - Response res = null; - Map resourceMap = this.methodMap.get(method.toUpperCase()); - if (resourceMap!=null) { - res = resourceMap.get(uri.toUpperCase()); - - if (res!=null) { - System.debug('Twilio_TestHTTPMock::getResponse() Found Resource for '+method+' '+uri+' = '+res); - } else { - System.debug('Twilio_TestHTTPMock::getResponse() Did not find Resource for '+method+' '+uri); - } - } else { - System.debug('Twilio_TestHTTPMock::getResponse() Did not find Resource Map for '+method); - } - return res; - } - - /** Registers a response to be returned for a particular HTTP method and URI */ - public void putResponse(String method, String uri, Response res) { - String methodKey = method.toUpperCase(); - String uriKey = uri.toUpperCase(); - - Map resourceMap = this.methodMap.get(methodKey); - if (resourceMap==null) { - resourceMap = new Map(); - this.methodMap.put(methodKey, resourceMap); - } - resourceMap.put(uriKey,res); - System.debug('Twilio_TestHTTPMock::putResponse() Added resource '+methodKey+' '+uriKey); - - } - - /** Response class - mock equivalent to HTTPResponse */ - public class Response { - - private String body; - private final Map headers = new Map(); - private Integer statusCode; - - public Response(String body, Integer statusCode) { - this.body = body; - this.statusCode = statusCode; - this.headers.put('Content-Type','application/json'); // default - } - - public void setHeader(String key, String value) - { - this.headers.put(key,value); - } - - public Integer getStatusCode() { - return this.statusCode; - } - - public String getBody() { - return this.body; - } - - public String getHeader(String name) { - return headers.get(name); - } - } + return res; + } + + /** Looks up the response for a specific HTTP method and URI. Returns null if none found. */ + public Response getResponse(String method, String uri) { + Response res = null; + Map resourceMap = this.methodMap.get(method.toUpperCase()); + if (resourceMap!=null) { + res = resourceMap.get(uri.toUpperCase()); + system.debug('Resource Map:'+resourceMap+' , Keys :'+resourceMap.keySet()); + if (res!=null) { + System.debug('Twilio_TestHTTPMock::getResponse() Found Resource for '+method+' '+uri+' = '+res); + } else { + System.debug('Twilio_TestHTTPMock::getResponse() Did not find Resource for '+method+' '+uri); + } + } else { + System.debug('Twilio_TestHTTPMock::getResponse() Did not find Resource Map for '+method); + } + return res; + } + + /** Registers a response to be returned for a particular HTTP method and URI */ + public void putResponse(String method, String uri, Response res) { + String methodKey = method.toUpperCase(); + String uriKey = uri.toUpperCase(); + + Map resourceMap = this.methodMap.get(methodKey); + if (resourceMap==null) { + resourceMap = new Map(); + this.methodMap.put(methodKey, resourceMap); + + } + resourceMap.put(uriKey,res); + system.debug('Put ResourceMap:'+resourceMap); + System.debug('Twilio_TestHTTPMock::putResponse() Added resource '+methodKey+' '+uriKey); + + } + + /** Response class - mock equivalent to HTTPResponse */ + public class Response { + + private String body; + private final Map headers = new Map(); + private Integer statusCode; + + public Response(String body, Integer statusCode) { + this.body = body; + this.statusCode = statusCode; + this.headers.put('Content-Type','application/json'); // default + } + + public void setHeader(String key, String value) + { + this.headers.put(key,value); + } + + public Integer getStatusCode() { + return this.statusCode; + } + + public String getBody() { + return this.body; + } + + public String getHeader(String name) { + return headers.get(name); + } + } } \ No newline at end of file diff --git a/src/classes/Twilio_TestMessage.cls b/src/classes/Twilio_TestMessage.cls new file mode 100644 index 0000000..20e1d09 --- /dev/null +++ b/src/classes/Twilio_TestMessage.cls @@ -0,0 +1,162 @@ +@isTest +private class Twilio_TestMessage +{ + + final static String authToken = '12345678901234567890123456789012'; + + static testmethod void testTwilioMessage_send() + { + string accountJsonResponseBody='{' + +'"account_sid": "AC03c2fcd60e144e7cbeee413fcbf812a3",' + +'"api_version": "2010-04-01",' + +'"body": "Test sending MMS from twilio",' + +'"num_segments": "1",' + +'"num_media": "1",' + +'"date_created": "Mon, 1 Feb 2012 10:49:17 +0000",' + +'"date_sent": "Mon, 1 Feb 2012 10:49:17 +0000",' + +'"date_updated": "Mon, 1 Feb 2012 10:49:17 +0000",' + +'"direction": "outbound-api",' + +'"from": "+14158141829",' + +'"price": "null",' + +'"price_unit":"usd",' + +'"sid": "MM90c6fc909d8504d45ecdb3a3d5b3556e",' + +'"status": "queued",' + +'"to": "+14159978453",' + +'"uri": "/2010-04-01/Accounts/AC03c2fcd60e144e7cbeee413fcbf812a3/MM90c6fc909d8504d45ecdb3a3d5b3556e.json",' + +'"subresource_uris": ' + +'{"media":"/2010-04-01/Accounts/ACadfb5891c0e4f8c6c34be620a8ec1ef3/Messages/MMbd2135c6d10f417faf1e03fac4e8397b/Media.json"}' + +'}'; + + Twilio_TestHTTPMock.getInstance().putResponse('POST', + 'https://api.twilio.com/2010-04-01/Accounts/ACadfb5891c0e4f8c6c34be620a8ec1ef3/Messages.json', + new Twilio_TestHTTPMock.Response(accountJsonResponseBody,200)); + + + // Get an API client and request the Twilio Account + TwilioRestClient client = new TwilioRestClient('ACadfb5891c0e4f8c6c34be620a8ec1ef3', authToken); + Map properties = new Map { + 'To' => '+14506007431', + 'From' => '+14509000405', + 'Body' => 'Test sending MMS from twilio' + }; + TwilioMessage sms = client.getAccount().getMessages().create(properties); + sms.getMedia(); + sms.getMedia('MM90c6fc909d8504d45ecdb3a3d5b3556e'); + sms.getResourceLocation(); + + System.assertEquals('MM90c6fc909d8504d45ecdb3a3d5b3556e', sms.getsid()); + System.assertEquals('AC03c2fcd60e144e7cbeee413fcbf812a3', sms.getaccountsid()); + System.assertEquals('+14159978453',sms.getto()); + System.assertEquals('+14158141829',sms.getfrom()); + System.assertEquals('Test sending MMS from twilio',sms.getbody()); + System.assertEquals('1',sms.getnumSegments()); + System.assertEquals('1',sms.getnumMedia()); + System.assertEquals('queued',sms.getStatus()); + System.assertEquals('null',sms.getPrice()); + System.assertEquals('usd',sms.getPriceUnit()); + System.assertEquals('outbound-api',sms.getDirection()); + System.assertEquals('2010-04-01',sms.getApiVersion()); + System.assertEquals(Datetime.newInstanceGmt(2012,2,1,10,49,17),sms.getDateCreated()); + System.assertEquals(Datetime.newInstanceGmt(2012,2,1,10,49,17),sms.getDateUpdated()); + System.assertEquals(Datetime.newInstanceGmt(2012,2,1,10,49,17),sms.getDatesent()); + } + + static testmethod void testTwilioMessageKeyPair_send() + { + string accountJsonResponseBody='{' + +'"account_sid": "AC03c2fcd60e144e7cbeee413fcbf812a3",' + +'"api_version": "2010-04-01",' + +'"body": "Test sending MMS from twilio",' + +'"num_segments": "1",' + +'"num_media": "1",' + +'"date_created": "Mon, 1 Feb 2012 10:49:17 +0000",' + +'"date_sent": "Mon, 1 Feb 2012 10:49:17 +0000",' + +'"date_updated": "Mon, 1 Feb 2012 10:49:17 +0000",' + +'"direction": "outbound-api",' + +'"from": "+14158141829",' + +'"price": "null",' + +'"sid": "MM90c6fc909d8504d45ecdb3a3d5b3556e",' + +'"status": "queued",' + +'"to": "+14159978453",' + +'"uri": "/2010-04-01/Accounts/AC03c2fcd60e144e7cbeee413fcbf812a3/MM90c6fc909d8504d45ecdb3a3d5b3556e.json"' + +'}'; + + Twilio_TestHTTPMock.getInstance().putResponse('POST', + 'https://api.twilio.com/2010-04-01/Accounts/AC03c2fcd60e144e7cbeee413fcbf812a3/Messages.json', + new Twilio_TestHTTPMock.Response(accountJsonResponseBody,200)); + + + // Get an API client and request the Twilio Account + TwilioRestClient client = new TwilioRestClient('AC03c2fcd60e144e7cbeee413fcbf812a3', authToken); + + List properties = new List(); + properties.add(new TwilioNameValuePair('To','4506007431')); + properties.add(new TwilioNameValuePair('From','4509000405')); + properties.add(new TwilioNameValuePair('MediaUrl','https://www.google.com/images/srpr/logo11w.png')); + properties.add(new TwilioNameValuePair('MediaUrl','https://www.twilio.com/packages/company/img/logos_downloadable_round.png')); + properties.add(new TwilioNameValuePair('Body','Raghu Testing Multiple MMS')); + + TwilioMessage mms = client.getAccount().getMessages().create(properties); + + + System.assertEquals('MM90c6fc909d8504d45ecdb3a3d5b3556e', mms.getsid()); + System.assertEquals('AC03c2fcd60e144e7cbeee413fcbf812a3', mms.getaccountsid()); + System.assertEquals('+14159978453',mms.getto()); + System.assertEquals('+14158141829',mms.getfrom()); + System.assertEquals('Test sending MMS from twilio',mms.getbody()); + System.assertEquals('1',mms.getnumSegments()); + System.assertEquals('1',mms.getnumMedia()); + System.assertEquals('queued',mms.getStatus()); + System.assertEquals('null',mms.getPrice()); + System.assertEquals('outbound-api',mms.getDirection()); + System.assertEquals('2010-04-01',mms.getApiVersion()); + System.assertEquals(Datetime.newInstanceGmt(2012,2,1,10,49,17),mms.getDateCreated()); + System.assertEquals(Datetime.newInstanceGmt(2012,2,1,10,49,17),mms.getDateUpdated()); + System.assertEquals(Datetime.newInstanceGmt(2012,2,1,10,49,17),mms.getDatesent()); + } + + static testmethod void testTwilioMessage_get() { + string accountJsonResponseBody='{' + +'"account_sid": "AC03c2fcd60e144e7cbeee413fcbf812a3",' + +'"api_version": "2008-08-01",' + +'"body": "Test sending mms from twilio",' + +'"date_created": "Mon, 1 Feb 2012 10:49:17 +0000",' + +'"date_sent": "Mon, 1 Feb 2012 10:49:17 +0000",' + +'"date_updated": "Mon, 1 Feb 2012 10:49:17 +0000",' + +'"direction": "outbound-api",' + +'"from": "+14158141829",' + +'"price": "-0.02000",' + +'"sid": "SM800f449d0399ed014aae2bcc0cc2f2ec",' + +'"status": "queued",' + +'"to": "+14159978453",' + +'"uri": "/2010-04-01/Accounts/AC5ef872f6da5a21de157d80997a64bd33/Messages/SM800f449d0399ed014aae2bcc0cc2f2ec.json",' + +'"subresource_uris": ' + +'{"media":"/2010-04-01/Accounts/ACadfb5891c0e4f8c6c34be620a8ec1ef3/Messages/MMbd2135c6d10f417faf1e03fac4e8397b/Media.json"}' + +'}'; + + + Twilio_TestHTTPMock.getInstance().putResponse( + 'GET', + 'https://api.twilio.com/2010-04-01/Accounts/AC03c2fcd60e144e7cbeee413fcbf812a3/Messages/SM800f449d0399ed014aae2bcc0cc2f2ec.json', + new Twilio_TestHTTPMock.Response(accountJsonResponseBody,200) + ); + + + // Get an API client and request the Twilio Account + TwilioRestClient client = new TwilioRestClient('AC03c2fcd60e144e7cbeee413fcbf812a3', authToken); + TwilioMessage sms= client.getAccount().getMessage('SM800f449d0399ed014aae2bcc0cc2f2ec'); + System.assertEquals('SM800f449d0399ed014aae2bcc0cc2f2ec', sms.getsid()); + System.assertEquals('AC03c2fcd60e144e7cbeee413fcbf812a3', sms.getaccountsid()); + System.assertEquals('+14159978453',sms.getto()); + System.assertEquals('+14158141829',sms.getfrom()); + System.assertEquals('Test sending mms from twilio',sms.getbody()); + System.assertEquals('queued',sms.getStatus()); + System.assertEquals('-0.02000',sms.getPrice()); + System.assertEquals('outbound-api',sms.getDirection()); + System.assertEquals('2008-08-01',sms.getApiVersion()); + System.assertEquals(Datetime.newInstanceGmt(2012,2,1,10,49,17),sms.getDateCreated()); + System.assertEquals(Datetime.newInstanceGmt(2012,2,1,10,49,17),sms.getDateUpdated()); + System.assertEquals(Datetime.newInstanceGmt(2012,2,1,10,49,17),sms.getDatesent()); + + } +} \ No newline at end of file diff --git a/src/classes/Twilio_TestMessage.cls-meta.xml b/src/classes/Twilio_TestMessage.cls-meta.xml new file mode 100644 index 0000000..f165265 --- /dev/null +++ b/src/classes/Twilio_TestMessage.cls-meta.xml @@ -0,0 +1,5 @@ + + + 29.0 + Active + diff --git a/src/package.xml b/src/package.xml old mode 100644 new mode 100755 index 00f3ff0..b6c91c4 --- a/src/package.xml +++ b/src/package.xml @@ -21,6 +21,13 @@ TwilioIncomingPhoneNumber TwilioIncomingPhoneNumberList TwilioIterator + TwilioMedia + TwilioMediaList + TwilioMember + TwilioMemberList + TwilioMessage + TwilioMessageList + TwilioNameValuePair TwilioNotification TwilioNotificationList TwilioOutgoingCallerId @@ -28,6 +35,8 @@ TwilioParser TwilioParticipant TwilioParticipantList + TwilioQueue + TwilioQueueList TwilioRecording TwilioRecordingList TwilioResource @@ -49,6 +58,7 @@ Twilio_TestConference Twilio_TestConnectApps Twilio_TestHTTPMock + Twilio_TestMessage Twilio_TestNotification Twilio_TestPhoneNumbers Twilio_TestRecording diff --git a/twilio-salesforce b/twilio-salesforce new file mode 160000 index 0000000..8aa7834 --- /dev/null +++ b/twilio-salesforce @@ -0,0 +1 @@ +Subproject commit 8aa7834d44308dc0a64b386a7c90de299e8b0fdf