001/*
002 * Copyright (c) 2011-2017 Nexmo Inc
003 *
004 * Permission is hereby granted, free of charge, to any person obtaining a copy
005 * of this software and associated documentation files (the "Software"), to deal
006 * in the Software without restriction, including without limitation the rights
007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008 * copies of the Software, and to permit persons to whom the Software is
009 * furnished to do so, subject to the following conditions:
010 *
011 * The above copyright notice and this permission notice shall be included in
012 * all copies or substantial portions of the Software.
013 *
014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
020 * THE SOFTWARE.
021 */
022package com.nexmo.client.voice;
023
024
025import com.nexmo.client.AbstractClient;
026import com.nexmo.client.HttpWrapper;
027import com.nexmo.client.NexmoClient;
028import com.nexmo.client.NexmoClientException;
029import com.nexmo.client.voice.endpoints.*;
030
031import java.io.IOException;
032
033/**
034 * A client for talking to the Nexmo Voice API. The standard way to obtain an instance of this class is to use
035 * {@link NexmoClient#getVoiceClient()}.
036 */
037public class VoiceClient extends AbstractClient {
038    protected final CallsEndpoint calls;
039    protected final StreamsEndpoint streams;
040    protected final TalkEndpoint talk;
041    protected final DtmfEndpoint dtmf;
042    protected final DownloadRecordingEndpoint downloadRecording;
043
044    /**
045     * Constructor.
046     *
047     * @param httpWrapper (required) shared HTTP wrapper object used for making REST calls.
048     */
049    public VoiceClient(HttpWrapper httpWrapper) {
050        super(httpWrapper);
051
052        calls = new CallsEndpoint(httpWrapper);
053        streams = new StreamsEndpoint(httpWrapper);
054        talk = new TalkEndpoint(httpWrapper);
055        dtmf = new DtmfEndpoint(httpWrapper);
056        downloadRecording = new DownloadRecordingEndpoint(httpWrapper);
057    }
058
059    /**
060     * Begin a call to a phone number.
061     *
062     * @param callRequest Describing the call to be made.
063     * @return A CallEvent describing the initial state of the call, containing the <tt>uuid</tt> required to
064     * interact with the ongoing phone call.
065     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
066     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
067     */
068    public CallEvent createCall(Call callRequest) throws IOException, NexmoClientException {
069        return calls.post(callRequest);
070    }
071
072    /**
073     * Obtain the first page of CallInfo objects, representing the most recent calls initiated by
074     * {@link #createCall(Call)}.
075     *
076     * @return A CallInfoPage representing the response from the Nexmo Voice API.
077     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
078     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
079     */
080    public CallInfoPage listCalls() throws IOException, NexmoClientException {
081        return this.listCalls(null);
082    }
083
084    /**
085     * Obtain the first page of CallInfo objects matching the query described by <tt>filter</tt>, representing the most
086     * recent calls initiated by {@link #createCall(Call)}.
087     *
088     * @param filter (optional) A filter describing which calls to be listed.
089     * @return A CallInfoPage representing the response from the Nexmo Voice API.
090     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
091     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
092     */
093    public CallInfoPage listCalls(CallsFilter filter) throws IOException, NexmoClientException {
094        return calls.get(filter);
095    }
096
097    /**
098     * Look up the status of a single call initiated by {@link #createCall(Call)}.
099     *
100     * @param uuid (required) The UUID of the call, obtained from the object returned by {@link #createCall(Call)}.
101     *             This value can be obtained with {@link CallEvent#getUuid()}
102     * @return A CallInfo object, representing the response from the Nexmo Voice API.
103     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
104     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
105     */
106    public CallInfo getCallDetails(String uuid) throws IOException, NexmoClientException {
107        return calls.get(uuid);
108    }
109
110    /**
111     * Send DTMF codes to an ongoing call.
112     *
113     * @param uuid   (required) The UUID of the call, obtained from the object returned by {@link #createCall(Call)}.
114     *               This value can be obtained with {@link CallEvent#getUuid()}
115     * @param digits (required) A string specifying the digits to be sent to the call. Valid characters are the digits
116     *               <tt>1-9</tt>, <tt>#</tt>, <tt>*</tt>, with the special character <tt>p</tt> indicating a short
117     *               pause between tones.
118     * @return A CallInfo object, representing the response from the Nexmo Voice API.
119     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
120     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
121     */
122    public DtmfResponse sendDtmf(String uuid, String digits) throws IOException, NexmoClientException {
123        return dtmf.put(uuid, digits);
124    }
125
126    /**
127     * Modify an ongoing call.
128     * <p>
129     * This method modifies an ongoing call, identified by "uuid". Modifications to the call can be one of:
130     * <ul>
131     * <li>Terminate the call (hangup)
132     * <li>Mute a call leg (mute)
133     * <li>Unmute a call leg (unmute)
134     * <li>Earmuff a call leg (earmuff)
135     * <li>Unearmuff a call leg (unearmuff)
136     * </ul>
137     *
138     * @param uuid   The UUID of the call, obtained from the object returned by {@link #createCall(Call)}.
139     *               This value can be obtained with {@link CallEvent#getUuid()}
140     * @param action One of: "hangup", "mute", "unmute", "earmuff", "unearmuff"
141     * @return A ModifyCallResponse object, representing the response from the Nexmo Voice API.
142     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
143     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
144     */
145    public ModifyCallResponse modifyCall(String uuid, ModifyCallAction action) throws IOException, NexmoClientException {
146        return this.modifyCall(new CallModifier(uuid, action));
147    }
148
149    /**
150     * Modify an ongoing call using a CallModifier object.
151     * <p>
152     * In most cases, you will want to use {@link #modifyCall(String, ModifyCallAction)} or {@link #transferCall(String, String)}
153     * instead of this method.
154     *
155     * @param modifier A CallModifier describing the modification to be made.
156     * @return A ModifyCallResponse object, representing the response from the Nexmo Voice API.
157     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
158     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
159     */
160    public ModifyCallResponse modifyCall(CallModifier modifier) throws IOException, NexmoClientException {
161        return calls.put(modifier);
162    }
163
164    /**
165     * Transfer a call to a different NCCO endpoint.
166     *
167     * @param uuid    The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
168     *                be obtained with {@link CallEvent#getUuid()}
169     * @param nccoUrl The URL of the NCCO endpoint the call should be transferred to
170     * @return A ModifyCallResponse object, representing the response from the Nexmo Voice API.
171     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
172     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
173     */
174    public ModifyCallResponse transferCall(String uuid, String nccoUrl) throws IOException, NexmoClientException {
175        return this.modifyCall(CallModifier.transferCall(uuid, nccoUrl));
176    }
177
178    /**
179     * Stream audio to an ongoing call.
180     *
181     * @param uuid      The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
182     *                  be obtained with {@link CallEvent#getUuid()}
183     * @param streamUrl A URL of an audio file in MP3 or 16-bit WAV format, to be streamed to the call.
184     * @param loop      The number of times to repeat the audio. The default value is <tt>1</tt>, or you can use
185     *                  <tt>0</tt> to indicate that the audio should be repeated indefinitely.
186     * @return The data returned from the Voice API
187     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
188     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
189     */
190    public StreamResponse startStream(String uuid, String streamUrl, int loop) throws IOException, NexmoClientException {
191        return streams.put(new StreamRequest(uuid, streamUrl, loop));
192    }
193
194    /**
195     * Stream audio to an ongoing call.
196     *
197     * @param uuid      The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
198     *                  be obtained with {@link CallEvent#getUuid()}
199     * @param streamUrl A URL of an audio file in MP3 or 16-bit WAV format, to be streamed to the call.
200     * @return The data returned from the Voice API.
201     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
202     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
203     */
204    public StreamResponse startStream(String uuid, String streamUrl) throws IOException, NexmoClientException {
205        return streams.put(new StreamRequest(uuid, streamUrl, 1));
206    }
207
208    /**
209     * Stop the audio being streamed into a call.
210     *
211     * @param uuid The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
212     *             be obtained with {@link CallEvent#getUuid()}
213     * @return The data returned from the Voice API
214     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
215     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
216     */
217    public StreamResponse stopStream(String uuid) throws IOException, NexmoClientException {
218        return streams.delete(uuid);
219    }
220
221    /**
222     * Send a synthesized speech message to an ongoing call.
223     * <p>
224     * The message will only play once, spoken with the default voice of Kimberly.
225     *
226     * @param uuid The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
227     *             be obtained with {@link CallEvent#getUuid()}
228     * @param text The message to be spoken to the call participants.
229     * @return The data returned from the Voice API.
230     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
231     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
232     */
233    public TalkResponse startTalk(String uuid, String text) throws IOException, NexmoClientException {
234        return talk.put(new TalkRequest(uuid, text));
235    }
236
237    /**
238     * Send a synthesized speech message to an ongoing call.
239     *
240     * @param uuid      The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
241     *                  be obtained with {@link CallEvent#getUuid()}
242     * @param text      The message to be spoken to the call participants.
243     * @param voiceName The voice to be used to speak the message.
244     * @return The data returned from the Voice API.
245     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
246     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
247     */
248    public TalkResponse startTalk(String uuid, String text, VoiceName voiceName) throws IOException, NexmoClientException {
249        return talk.put(new TalkRequest(uuid, text, voiceName));
250    }
251
252    /**
253     * Send a synthesized speech message to an ongoing call.
254     * <p>
255     * The message will be spoken with the default voice of Kimberly.
256     *
257     * @param uuid The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
258     *             be obtained with {@link CallEvent#getUuid()}
259     * @param text The message to be spoken to the call participants.
260     * @param loop The number of times to repeat the message. The default value is <tt>1</tt>, or you can use
261     *             <tt>0</tt> to indicate that the message should be repeated indefinitely.
262     * @return The data returned from the Voice API.
263     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
264     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
265     */
266    public TalkResponse startTalk(String uuid, String text, int loop) throws IOException, NexmoClientException {
267        return talk.put(new TalkRequest(uuid, text, loop));
268    }
269
270    /**
271     * Send a synthesized speech message to an ongoing call.
272     *
273     * @param uuid      The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
274     *                  be obtained with {@link CallEvent#getUuid()}
275     * @param text      The message to be spoken to the call participants.
276     * @param voiceName The voice to be used to speak the message.
277     * @param loop      The number of times to repeat the message. The default value is <tt>1</tt>, or you can use
278     *                  <tt>0</tt> to indicate that the message should be repeated indefinitely.
279     * @return The data returned from the Voice API.
280     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
281     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
282     */
283    public TalkResponse startTalk(String uuid, String text, VoiceName voiceName, int loop) throws IOException, NexmoClientException {
284        return talk.put(new TalkRequest(uuid, text, voiceName, loop));
285    }
286
287    /**
288     * Stop the message being spoken into a call.
289     *
290     * @param uuid The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
291     *             be obtained with {@link CallEvent#getUuid()}
292     * @return The data returned from the Voice API
293     * @throws IOException          if a network error occurred contacting the Nexmo Voice API.
294     * @throws NexmoClientException if there was a problem with the Nexmo request or response objects.
295     */
296    public TalkResponse stopTalk(String uuid) throws IOException, NexmoClientException {
297        return talk.delete(uuid);
298    }
299
300    /**
301     * Download a recording, given the recordingUrl provided from the webhook callback.
302     * <p>
303     * This returns a {@link Recording} object which can provide an InputStream of the byte data, or can be used to
304     * save directly to file.
305     *
306     * @param recordingUrl The recordingUrl provided by the webhook callback
307     * @return A Recording object, providing access to the recording's bytes
308     * @throws IOException If an error occurred while downloading the data
309     */
310    public Recording downloadRecording(String recordingUrl) throws IOException, NexmoClientException {
311        return this.downloadRecording.execute(recordingUrl);
312    }
313}