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.*;
026
027/**
028 * A client for talking to the Nexmo Voice API. The standard way to obtain an instance of this class is to use {@link
029 * NexmoClient#getVoiceClient()}.
030 */
031public class VoiceClient extends AbstractClient {
032    protected final CallsEndpoint calls;
033    protected final StreamsEndpoint streams;
034    protected final TalkEndpoint talk;
035    protected final DtmfEndpoint dtmf;
036    protected final DownloadRecordingEndpoint downloadRecording;
037
038    /**
039     * Constructor.
040     *
041     * @param httpWrapper (required) shared HTTP wrapper object used for making REST calls.
042     */
043    public VoiceClient(HttpWrapper httpWrapper) {
044        super(httpWrapper);
045
046        calls = new CallsEndpoint(httpWrapper);
047        streams = new StreamsEndpoint(httpWrapper);
048        talk = new TalkEndpoint(httpWrapper);
049        dtmf = new DtmfEndpoint(httpWrapper);
050        downloadRecording = new DownloadRecordingEndpoint(httpWrapper);
051    }
052
053    /**
054     * Begin a call to a phone number.
055     *
056     * @param callRequest Describing the call to be made.
057     *
058     * @return A CallEvent describing the initial state of the call, containing the {@code uuid} required to interact
059     * with the ongoing phone call.
060     *
061     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
062     * @throws NexmoResponseParseException if the response from the API could not be parsed.
063     */
064    public CallEvent createCall(Call callRequest) throws NexmoResponseParseException, NexmoClientException {
065        return calls.post(callRequest);
066    }
067
068    /**
069     * Obtain the first page of CallInfo objects, representing the most recent calls initiated by {@link
070     * #createCall(Call)}.
071     *
072     * @return A CallInfoPage representing the response from the Nexmo Voice API.
073     *
074     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
075     * @throws NexmoResponseParseException if the response from the API could not be parsed.
076     */
077    public CallInfoPage listCalls() throws NexmoResponseParseException, NexmoClientException {
078        return this.listCalls(null);
079    }
080
081    /**
082     * Obtain the first page of CallInfo objects matching the query described by {@code filter}, representing the most
083     * recent calls initiated by {@link #createCall(Call)}.
084     *
085     * @param filter (optional) A filter describing which calls to be listed.
086     *
087     * @return A CallInfoPage representing the response from the Nexmo Voice API.
088     *
089     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
090     * @throws NexmoResponseParseException if the response from the API could not be parsed.
091     */
092    public CallInfoPage listCalls(CallsFilter filter) throws NexmoResponseParseException, NexmoClientException {
093        return calls.get(filter);
094    }
095
096    /**
097     * Look up the status of a single call initiated by {@link #createCall(Call)}.
098     *
099     * @param uuid (required) The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This
100     *             value can be obtained with {@link CallEvent#getUuid()}
101     *
102     * @return A CallInfo object, representing the response from the Nexmo Voice API.
103     *
104     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
105     * @throws NexmoResponseParseException if the response from the API could not be parsed.
106     */
107    public CallInfo getCallDetails(String uuid) throws NexmoResponseParseException, NexmoClientException {
108        return calls.get(uuid);
109    }
110
111    /**
112     * Send DTMF codes to an ongoing call.
113     *
114     * @param uuid   (required) The UUID of the call, obtained from the object returned by {@link #createCall(Call)}.
115     *               This value can be obtained with {@link CallEvent#getUuid()}
116     * @param digits (required) A string specifying the digits to be sent to the call. Valid characters are the digits
117     *               {@code 1-9</tt>, <tt>#</tt>, <tt>*</tt>, with the special character <tt>p} indicating a short pause
118     *               between tones.
119     *
120     * @return A CallInfo object, representing the response from the Nexmo Voice API.
121     *
122     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
123     * @throws NexmoResponseParseException if the response from the API could not be parsed.
124     */
125    public DtmfResponse sendDtmf(String uuid, String digits) throws NexmoResponseParseException, NexmoClientException {
126        return dtmf.put(uuid, digits);
127    }
128
129    /**
130     * Modify an ongoing call.
131     * <p>
132     * This method modifies an ongoing call, identified by "uuid". Modifications to the call can be one of:
133     * <ul>
134     * <li>Terminate the call (hangup)
135     * <li>Mute a call leg (mute)
136     * <li>Unmute a call leg (unmute)
137     * <li>Earmuff a call leg (earmuff)
138     * <li>Unearmuff a call leg (unearmuff)
139     * </ul>
140     *
141     * @param uuid   The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value
142     *               can be obtained with {@link CallEvent#getUuid()}
143     * @param action One of: "hangup", "mute", "unmute", "earmuff", "unearmuff"
144     *
145     * @return A ModifyCallResponse object, representing the response from the Nexmo Voice API.
146     *
147     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
148     * @throws NexmoResponseParseException if the response from the API could not be parsed.
149     */
150    public ModifyCallResponse modifyCall(String uuid, ModifyCallAction action) throws NexmoResponseParseException, NexmoClientException {
151        return this.modifyCall(new CallModifier(uuid, action));
152    }
153
154    /**
155     * Modify an ongoing call using a CallModifier object.
156     * <p>
157     * In most cases, you will want to use {@link #modifyCall(String, ModifyCallAction)} or {@link #transferCall(String,
158     * String)} instead of this method.
159     *
160     * @param modifier A CallModifier describing the modification to be made.
161     *
162     * @return A ModifyCallResponse object, representing the response from the Nexmo Voice API.
163     *
164     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
165     * @throws NexmoResponseParseException if the response from the API could not be parsed.
166     */
167    public ModifyCallResponse modifyCall(CallModifier modifier) throws NexmoResponseParseException, NexmoClientException {
168        return calls.put(modifier);
169    }
170
171    /**
172     * Transfer a call to a different NCCO endpoint.
173     *
174     * @param uuid    The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value
175     *                can be obtained with {@link CallEvent#getUuid()}
176     * @param nccoUrl The URL of the NCCO endpoint the call should be transferred to
177     *
178     * @return A ModifyCallResponse object, representing the response from the Nexmo Voice API.
179     *
180     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
181     * @throws NexmoResponseParseException if the response from the API could not be parsed.
182     */
183    public ModifyCallResponse transferCall(String uuid, String nccoUrl) throws NexmoResponseParseException, NexmoClientException {
184        return this.modifyCall(CallModifier.transferCall(uuid, nccoUrl));
185    }
186
187    /**
188     * Stream audio to an ongoing call.
189     *
190     * @param uuid      The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value
191     *                  can be obtained with {@link CallEvent#getUuid()}
192     * @param streamUrl A URL of an audio file in MP3 or 16-bit WAV format, to be streamed to the call.
193     * @param loop      The number of times to repeat the audio. The default value is {@code 1}, or you can use {@code
194     *                  0} to indicate that the audio should be repeated indefinitely.
195     *
196     * @return The data returned from the Voice API
197     *
198     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
199     * @throws NexmoResponseParseException if the response from the API could not be parsed.
200     */
201    public StreamResponse startStream(String uuid, String streamUrl, int loop) throws NexmoResponseParseException, NexmoClientException {
202        return streams.put(new StreamRequest(uuid, streamUrl, loop));
203    }
204
205    /**
206     * Stream audio to an ongoing call.
207     *
208     * @param uuid      The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value
209     *                  can be obtained with {@link CallEvent#getUuid()}
210     * @param streamUrl A URL of an audio file in MP3 or 16-bit WAV format, to be streamed to the call.
211     *
212     * @return The data returned from the Voice API.
213     *
214     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
215     * @throws NexmoResponseParseException if the response from the API could not be parsed.
216     */
217    public StreamResponse startStream(String uuid, String streamUrl) throws NexmoResponseParseException, NexmoClientException {
218        return streams.put(new StreamRequest(uuid, streamUrl, 1));
219    }
220
221    /**
222     * Stop the audio being streamed into a call.
223     *
224     * @param uuid The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
225     *             be obtained with {@link CallEvent#getUuid()}
226     *
227     * @return The data returned from the Voice API
228     *
229     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
230     * @throws NexmoResponseParseException if the response from the API could not be parsed.
231     */
232    public StreamResponse stopStream(String uuid) throws NexmoResponseParseException, NexmoClientException {
233        return streams.delete(uuid);
234    }
235
236    /**
237     * Send a synthesized speech message to an ongoing call.
238     * <p>
239     * The message will only play once, spoken with the default voice of Kimberly.
240     *
241     * @param uuid The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
242     *             be obtained with {@link CallEvent#getUuid()}
243     * @param text The message to be spoken to the call participants.
244     *
245     * @return The data returned from the Voice API.
246     *
247     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
248     * @throws NexmoResponseParseException if the response from the API could not be parsed.
249     */
250    public TalkResponse startTalk(String uuid, String text) throws NexmoResponseParseException, NexmoClientException {
251        return talk.put(new TalkRequest(uuid, text));
252    }
253
254    /**
255     * Send a synthesized speech message to an ongoing call.
256     *
257     * @param uuid      The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value
258     *                  can be obtained with {@link CallEvent#getUuid()}
259     * @param text      The message to be spoken to the call participants.
260     * @param voiceName The voice to be used to speak the message.
261     *
262     * @return The data returned from the Voice API.
263     *
264     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
265     * @throws NexmoResponseParseException if the response from the API could not be parsed.
266     */
267    public TalkResponse startTalk(String uuid, String text, VoiceName voiceName) throws NexmoResponseParseException, NexmoClientException {
268        return talk.put(new TalkRequest(uuid, text, voiceName));
269    }
270
271    /**
272     * Send a synthesized speech message to an ongoing call.
273     * <p>
274     * The message will be spoken with the default voice of Kimberly.
275     *
276     * @param uuid The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
277     *             be obtained with {@link CallEvent#getUuid()}
278     * @param text The message to be spoken to the call participants.
279     * @param loop The number of times to repeat the message. The default value is {@code 1}, or you can use {@code 0}
280     *             to indicate that the message should be repeated indefinitely.
281     *
282     * @return The data returned from the Voice API.
283     *
284     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
285     * @throws NexmoResponseParseException if the response from the API could not be parsed.
286     */
287    public TalkResponse startTalk(String uuid, String text, int loop) throws NexmoResponseParseException, NexmoClientException {
288        return talk.put(new TalkRequest(uuid, text, loop));
289    }
290
291    /**
292     * Send a synthesized speech message to an ongoing call.
293     *
294     * @param uuid      The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value
295     *                  can be obtained with {@link CallEvent#getUuid()}
296     * @param text      The message to be spoken to the call participants.
297     * @param voiceName The voice to be used to speak the message.
298     * @param loop      The number of times to repeat the message. The default value is {@code 1}, or you can use {@code
299     *                  0} to indicate that the message should be repeated indefinitely.
300     *
301     * @return The data returned from the Voice API.
302     *
303     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
304     * @throws NexmoResponseParseException if the response from the API could not be parsed.
305     */
306    public TalkResponse startTalk(String uuid, String text, VoiceName voiceName, int loop) throws NexmoResponseParseException, NexmoClientException {
307        return talk.put(new TalkRequest(uuid, text, voiceName, loop));
308    }
309
310    /**
311     * Stop the message being spoken into a call.
312     *
313     * @param uuid The UUID of the call, obtained from the object returned by {@link #createCall(Call)}. This value can
314     *             be obtained with {@link CallEvent#getUuid()}
315     *
316     * @return The data returned from the Voice API
317     *
318     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
319     * @throws NexmoResponseParseException if the response from the API could not be parsed.
320     */
321    public TalkResponse stopTalk(String uuid) throws NexmoResponseParseException, NexmoClientException {
322        return talk.delete(uuid);
323    }
324
325    /**
326     * Download a recording, given the recordingUrl provided from the webhook callback.
327     * <p>
328     * This returns a {@link Recording} object which can provide an InputStream of the byte data, or can be used to save
329     * directly to file.
330     *
331     * @param recordingUrl The recordingUrl provided by the webhook callback
332     *
333     * @return A Recording object, providing access to the recording's bytes
334     *
335     * @throws NexmoClientException        if there was a problem with the Nexmo request or response objects.
336     * @throws NexmoResponseParseException if the response from the API could not be parsed.
337     */
338    public Recording downloadRecording(String recordingUrl) throws NexmoResponseParseException, NexmoClientException {
339        return this.downloadRecording.execute(recordingUrl);
340    }
341}