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