From 37e595b4d7b62583280b0a4dfe8bf24306f2e7be Mon Sep 17 00:00:00 2001 From: Jim Rogers Date: Thu, 23 Mar 2017 13:05:47 -0700 Subject: [PATCH 1/6] Add samples for live chat --- java/README.md | 34 ++- java/pom.xml | 2 +- .../cmdline/live/DeleteLiveChatMessage.java | 98 +++++++ .../youtube/cmdline/live/GetLiveChatId.java | 134 +++++++++ .../cmdline/live/InsertLiveChatMessage.java | 116 ++++++++ .../cmdline/live/ListLiveChatMessages.java | 272 ++++++++++++++++++ 6 files changed, 653 insertions(+), 3 deletions(-) create mode 100644 java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/DeleteLiveChatMessage.java create mode 100644 java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java create mode 100644 java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/InsertLiveChatMessage.java create mode 100644 java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java diff --git a/java/README.md b/java/README.md index 4246fafe..bd7e0862 100644 --- a/java/README.md +++ b/java/README.md @@ -11,9 +11,13 @@ To build this code sample from the command line, type: mvn compile -To run the code sample from the command line, enter the following: +To run a code sample from the command line, enter the following: - mvn exec:java -Dexec.mainClass="FULL_CLASS_NAME" + mvn exec:java -Dexec.mainClass="FULL_CLASS_NAME" + +For samples that require arguments, also specify -Dexec.args, e.g.: + + mvn exec:java -Dexec.mainClass="FULL_CLASS_NAME" -Dexec.args="arg1 arg2" For more instructions about how to set up Maven and/or your IDE to run YouTube API samples, see this video: @@ -236,3 +240,29 @@ also specify a value for the --broadcast-status option to only retr Method: youtube.liveStreams.list
Description: This sample calls the API's liveStreams.list method to retrieve a list of video stream settings that a channel can use to broadcast live events on YouTube. + + +### [Get a live chat id](/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java) + +Methods: youtube.videos.list, youtube.liveBroadcasts.list
+Description: This sample retrieves a live chat id from either a videoId parameter +or the current user's live broadcast. The liveChatId is required for other samples +that interact with live chat. + +### [Insert a live chat message](/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/InsertLiveChatMessage.java) + +Method: youtube.liveChatMessages.insert
+Description: This sample inserts a live chat message into the live chat specified by either +a videoId parameter or the current user's live broadcast. + +### [Delete a live chat message](/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/DeleteLiveChatMessage.java) + +Method: youtube.liveChatMessages.delete
+Description: This sample deletes a live chat message from the live chat specified by either +a videoId parameter or the current user's live broadcast. + +### [List live chat messages](/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java) + +Method: youtube.liveChatMessages.list
+Description: This sample lists live chat messages from the chat specified by either +a videoId parameter or the current user's live broadcast. diff --git a/java/pom.xml b/java/pom.xml index 6de21773..200ffec1 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -11,7 +11,7 @@ http://maven.apache.org - v3-rev179-1.22.0 + v3-rev182-1.22.0 v1-rev63-1.22.0 v1-rev10-1.22.0 1.20.0 diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/DeleteLiveChatMessage.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/DeleteLiveChatMessage.java new file mode 100644 index 00000000..a081fb12 --- /dev/null +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/DeleteLiveChatMessage.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.services.samples.youtube.cmdline.live; + +import com.google.api.client.auth.oauth2.Credential; +import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.services.samples.youtube.cmdline.Auth; +import com.google.api.services.youtube.YouTube; +import com.google.api.services.youtube.YouTubeScopes; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Delets a message from a live broadcast, using OAuth 2.0 to authorize API requests. + * + * @author Jim Rogers + */ +public class DeleteLiveChatMessage { + + /** + * Define a global instance of a Youtube object, which will be used + * to make YouTube Data API requests. + */ + private static YouTube youtube; + + /** + * Deletes a message from a live broadcast. + * + * @param args The message id to delete (required) followed by the videoId (optional). If the + * videoId is given, live chat messages will be retrieved from the chat associated with this + * video. If the videoId is not specified, the signed in user's current live broadcast will be + * used instead. + */ + public static void main(String[] args) { + // Get the message id to delete + if (args.length == 0) { + System.err.println("No message id specified"); + System.exit(1); + } + String messageId = args[0]; + + // This OAuth 2.0 access scope allows for read-only access to the + // authenticated user's account, but not other types of account access. + List scopes = new ArrayList(); + scopes.add(YouTubeScopes.YOUTUBE_FORCE_SSL); + scopes.add(YouTubeScopes.YOUTUBE); + + try { + // Authorize the request. + Credential credential = Auth.authorize(scopes, "deletelivechatmessage"); + + // This object is used to make YouTube Data API requests. + youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, credential) + .setApplicationName("youtube-cmdline-deletechatmessages-sample").build(); + + // Get the liveChatId + String liveChatId = GetLiveChatId.getLiveChatId( + youtube, + args.length == 2 ? args[1] : null); + if (liveChatId != null) { + System.out.println("Live chat id: " + liveChatId); + } else { + System.err.println("Unable to find a live chat id"); + System.exit(1); + } + + // Delete the message from live chat + YouTube.LiveChatMessages.Delete liveChatDelete = + youtube.liveChatMessages().delete(messageId); + liveChatDelete.execute(); + System.out.println("Deleted message id " + messageId); + } catch (GoogleJsonResponseException e) { + System.err + .println("GoogleJsonResponseException code: " + e.getDetails().getCode() + " : " + + e.getDetails().getMessage()); + e.printStackTrace(); + } catch (IOException e) { + System.err.println("IOException: " + e.getMessage()); + e.printStackTrace(); + } catch (Throwable t) { + System.err.println("Throwable: " + t.getMessage()); + t.printStackTrace(); + } + } +} diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java new file mode 100644 index 00000000..0a5b71a0 --- /dev/null +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2017 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.services.samples.youtube.cmdline.live; + +import com.google.api.client.auth.oauth2.Credential; +import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.services.samples.youtube.cmdline.Auth; +import com.google.api.services.youtube.YouTube; +import com.google.api.services.youtube.YouTubeScopes; +import com.google.api.services.youtube.model.LiveBroadcast; +import com.google.api.services.youtube.model.LiveBroadcastListResponse; +import com.google.api.services.youtube.model.Video; +import com.google.api.services.youtube.model.VideoListResponse; +import com.google.common.collect.Lists; +import java.io.IOException; +import java.util.List; + +/** + * Gets a live chat id from a video id or current signed in user. + * + * The videoId is often included in the video's url, e.g.: + * https://www.youtube.com/watch?v=L5Xc93_ZL60 + * ^ videoId + * The video URL may be found in the browser address bar, or by right-clicking a video and selecting + * Copy video URL from the context menu. + * + * @author Jim Rogers + */ +public class GetLiveChatId { + + /** + * Define a global instance of a Youtube object, which will be used + * to make YouTube Data API requests. + */ + private static YouTube youtube; + + /** + * Poll live chat messages and SuperChat details from a live broadcast. + * + * @param args videoId (optional). If the videoId is given, live chat messages will be retrieved + * from the chat associated with this video. If the videoId is not specified, the signed in + * user's current live broadcast will be used instead. + */ + public static void main(String[] args) { + + // This OAuth 2.0 access scope allows for read-only access to the + // authenticated user's account, but not other types of account access. + List scopes = Lists.newArrayList(YouTubeScopes.YOUTUBE_READONLY); + + try { + // Authorize the request. + Credential credential = Auth.authorize(scopes, "getlivechatid"); + + // This object is used to make YouTube Data API requests. + youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, credential) + .setApplicationName("youtube-cmdline-getlivechatid-sample").build(); + + // Get the liveChatId + String liveChatId = getLiveChatId(youtube, args.length == 1 ? args[0] : null); + if (liveChatId != null) { + System.out.println("Live chat id: " + liveChatId); + } else { + System.err.println("Unable to find a live chat id"); + System.exit(1); + } + } catch (GoogleJsonResponseException e) { + System.err + .println("GoogleJsonResponseException code: " + e.getDetails().getCode() + " : " + + e.getDetails().getMessage()); + e.printStackTrace(); + + } catch (IOException e) { + System.err.println("IOException: " + e.getMessage()); + e.printStackTrace(); + } catch (Throwable t) { + System.err.println("Throwable: " + t.getMessage()); + t.printStackTrace(); + } + } + + /** + * Retrieves the liveChatId from the videoId, if specified. If not specified, will find the + * liveChatId for the signed in user's live broadcast. + * + * @param youtube The object is used to make YouTube Data API requests. + * @param videoId The videoId associated with the live chat (optional). + * @return A liveChatId, or null if not found. + */ + static String getLiveChatId(YouTube youtube, String videoId) throws IOException { + if (videoId != null && !videoId.isEmpty()) { + // Get liveChatId from the video + YouTube.Videos.List videoList = youtube.videos() + .list("liveStreamingDetails") + .setFields("items/liveStreamingDetails/activeLiveChatId") + .setId(videoId); + VideoListResponse response = videoList.execute(); + for (Video v : response.getItems()) { + String liveChatId = v.getLiveStreamingDetails().getActiveLiveChatId(); + if (liveChatId != null && !liveChatId.isEmpty()) { + return liveChatId; + } + } + } else { + // Get signed in user's liveChatId + YouTube.LiveBroadcasts.List broadcastList = youtube + .liveBroadcasts() + .list("snippet") + .setFields("items/snippet/liveChatId") + .setBroadcastType("all") + .setBroadcastStatus("active"); + LiveBroadcastListResponse broadcastListResponse = broadcastList.execute(); + for (LiveBroadcast b : broadcastListResponse.getItems()) { + String liveChatId = b.getSnippet().getLiveChatId(); + if (liveChatId != null && !liveChatId.isEmpty()) { + return liveChatId; + } + } + } + + return null; + } +} diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/InsertLiveChatMessage.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/InsertLiveChatMessage.java new file mode 100644 index 00000000..e8e66f62 --- /dev/null +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/InsertLiveChatMessage.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2017 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.services.samples.youtube.cmdline.live; + +import com.google.api.client.auth.oauth2.Credential; +import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.services.samples.youtube.cmdline.Auth; +import com.google.api.services.youtube.YouTube; +import com.google.api.services.youtube.YouTubeScopes; +import com.google.api.services.youtube.model.LiveChatMessage; +import com.google.api.services.youtube.model.LiveChatMessageSnippet; +import com.google.api.services.youtube.model.LiveChatTextMessageDetails; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Inserts a message into a live broadcast of the current user or a video specified by id. + * + * The videoId is often included in the video's url, e.g.: + * https://www.youtube.com/watch?v=L5Xc93_ZL60 + * ^ videoId + * The video URL may be found in the browser address bar, or by right-clicking a video and selecting + * Copy video URL from the context menu. + * + * @author Jim Rogers + */ +public class InsertLiveChatMessage { + + /** + * Define a global instance of a Youtube object, which will be used + * to make YouTube Data API requests. + */ + private static YouTube youtube; + + /** + * Inserts a message into a live broadcast. + * + * @param args The message to insert (required) followed by the videoId (optional). + * If the videoId is given, live chat messages will be retrieved from the chat associated with + * this video. If the videoId is not specified, the signed in user's current live broadcast will + * be used instead. + */ + public static void main(String[] args) { + // Get the chat message to insert + if (args.length == 0) { + System.err.println("No message specified"); + System.exit(1); + } + String message = args[0]; + + // This OAuth 2.0 access scope allows for read-only access to the + // authenticated user's account, but not other types of account access. + List scopes = new ArrayList(); + scopes.add(YouTubeScopes.YOUTUBE_FORCE_SSL); + scopes.add(YouTubeScopes.YOUTUBE); + + try { + // Authorize the request. + Credential credential = Auth.authorize(scopes, "insertlivechatmessage"); + + // This object is used to make YouTube Data API requests. + youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, credential) + .setApplicationName("youtube-cmdline-insertchatmessage-sample").build(); + + // Get the liveChatId + String liveChatId = GetLiveChatId.getLiveChatId( + youtube, + args.length == 2 ? args[1] : null); + if (liveChatId != null) { + System.out.println("Live chat id: " + liveChatId); + } else { + System.err.println("Unable to find a live chat id"); + System.exit(1); + } + + // Insert the message into live chat + LiveChatMessage liveChatMessage = new LiveChatMessage(); + LiveChatMessageSnippet snippet = new LiveChatMessageSnippet(); + snippet.setType("textMessageEvent"); + snippet.setLiveChatId(liveChatId); + snippet.setDisplayMessage(message); + LiveChatTextMessageDetails details = new LiveChatTextMessageDetails(); + details.setMessageText(message); + snippet.setTextMessageDetails(details); + liveChatMessage.setSnippet(snippet); + YouTube.LiveChatMessages.Insert liveChatInsert = + youtube.liveChatMessages().insert("snippet", liveChatMessage); + LiveChatMessage response = liveChatInsert.execute(); + System.out.println("Inserted message id " + response.getId()); + } catch (GoogleJsonResponseException e) { + System.err + .println("GoogleJsonResponseException code: " + e.getDetails().getCode() + " : " + + e.getDetails().getMessage()); + e.printStackTrace(); + } catch (IOException e) { + System.err.println("IOException: " + e.getMessage()); + e.printStackTrace(); + } catch (Throwable t) { + System.err.println("Throwable: " + t.getMessage()); + t.printStackTrace(); + } + } +} diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java new file mode 100644 index 00000000..223915c0 --- /dev/null +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2017 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.services.samples.youtube.cmdline.live; + +import com.google.api.client.auth.oauth2.Credential; +import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.services.samples.youtube.cmdline.Auth; +import com.google.api.services.youtube.YouTube; +import com.google.api.services.youtube.YouTubeScopes; +import com.google.api.services.youtube.model.LiveChatMessage; +import com.google.api.services.youtube.model.LiveChatMessageAuthorDetails; +import com.google.api.services.youtube.model.LiveChatMessageListResponse; +import com.google.api.services.youtube.model.LiveChatMessageSnippet; +import com.google.api.services.youtube.model.LiveChatSuperChatDetails; +import com.google.common.collect.Lists; +import java.io.IOException; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +/** + * Lists live chat messages and SuperChat details from a live broadcast. + * + * The videoId is often included in the video's url, e.g.: + * https://www.youtube.com/watch?v=L5Xc93_ZL60 + * ^ videoId + * The video URL may be found in the browser address bar, or by right-clicking a video and selecting + * Copy video URL from the context menu. + * + * @author Jim Rogers + */ +public class ListLiveChatMessages { + + /** + * Common fields to retrieve for chat messages + */ + private static final String LIVE_CHAT_FIELDS = + "items(authorDetails(channelId,displayName,isChatModerator,isChatOwner,isChatSponsor," + + "profileImageUrl),snippet(displayMessage,superChatDetails,publishedAt))," + + "nextPageToken,pollingIntervalMillis"; + + /** + * Define a global instance of a Youtube object, which will be used + * to make YouTube Data API requests. + */ + private static YouTube youtube; + + /** + * A timer used to schedule message retrieval. + */ + private static Timer pollTimer; + + /** + * Lists live chat messages and SuperChat details from a live broadcast. + * + * @param args videoId (optional). If the videoId is given, live chat messages will be retrieved + * from the chat associated with this video. If the videoId is not specified, the signed in + * user's current live broadcast will be used instead. + */ + public static void main(String[] args) { + + // This OAuth 2.0 access scope allows for read-only access to the + // authenticated user's account, but not other types of account access. + List scopes = Lists.newArrayList(YouTubeScopes.YOUTUBE_READONLY); + + try { + // Authorize the request. + Credential credential = Auth.authorize(scopes, "listlivechatmessages"); + + // This object is used to make YouTube Data API requests. + youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, credential) + .setApplicationName("youtube-cmdline-listchatmessages-sample").build(); + + // Get the liveChatId + String liveChatId = GetLiveChatId.getLiveChatId( + youtube, + args.length == 1 ? args[0] : null); + if (liveChatId != null) { + System.out.println("Live chat id: " + liveChatId); + } else { + System.err.println("Unable to find a live chat id"); + System.exit(1); + } + + /** + * List live chat messages with poll interval from server. Alternatively, messages + * may be requested at a fixed interval with listChatMessagesFixedPeriod, e.g. + * listChatMessagesFixedPeriod(liveChatId, 1000, 0) + */ + listChatMessages(liveChatId, null, 0); + } catch (GoogleJsonResponseException e) { + System.err + .println("GoogleJsonResponseException code: " + e.getDetails().getCode() + " : " + + e.getDetails().getMessage()); + e.printStackTrace(); + + } catch (IOException e) { + System.err.println("IOException: " + e.getMessage()); + e.printStackTrace(); + } catch (Throwable t) { + System.err.println("Throwable: " + t.getMessage()); + t.printStackTrace(); + } + } + + /** + * Lists live chat messages, polling at the server supplied interval. + * + * @param liveChatId The live chat id to list messages from. + * @param nextPageToken The page token from the previous request, if any. + * @param delayMs The delay in milliseconds before making the request. + */ + private static void listChatMessages( + final String liveChatId, + final String nextPageToken, + long delayMs) { + System.out.println( + String.format("Getting chat messages in %1$.3f seconds...", delayMs * 0.001)); + pollTimer = new Timer(); + pollTimer.schedule( + new TimerTask() { + @Override + public void run() { + try { + // Get chat messages from YouTube + LiveChatMessageListResponse response = youtube + .liveChatMessages() + .list(liveChatId, "snippet, authorDetails") + .setPageToken(nextPageToken) + .setFields(LIVE_CHAT_FIELDS) + .execute(); + + // Display messages and super chat details + List messages = response.getItems(); + for (int i = 0; i < messages.size(); i++) { + LiveChatMessage message = messages.get(i); + LiveChatMessageSnippet snippet = message.getSnippet(); + System.out.println(buildOutput( + snippet.getDisplayMessage(), + message.getAuthorDetails(), + snippet.getSuperChatDetails())); + } + + // Request the next page of messages + listChatMessages( + liveChatId, + response.getNextPageToken(), + response.getPollingIntervalMillis()); + } catch (Throwable t) { + System.err.println("Throwable: " + t.getMessage()); + t.printStackTrace(); + } + } + }, delayMs); + } + + /** + * Lists live chat messages, polling at the client supplied interval. This method is not + * recommended because it will consume more API usage, but it may be necessary in some + * applications that require lower latency. Page tokens do not work when polling faster than the + * server supplied interval, so we need to keep track of the publish time to avoid duplicate + * message output. Message ids will not work for tracking the last received message because + * messages may be removed from chat. + * + * @param liveChatId The live chat id to list messages from. + * @param periodMs The fixed interval to poll messages. + * @param minPublishTime The minimum message time to output. + */ + private static void listChatMessagesFixedPeriod( + final String liveChatId, + final long periodMs, + final long minPublishTime) { + System.out.println( + String.format("Getting chat messages in %1$.3f seconds...", periodMs * 0.001)); + pollTimer = new Timer(); + pollTimer.schedule( + new TimerTask() { + @Override + public void run() { + try { + // Get chat messages from YouTube + LiveChatMessageListResponse response = youtube + .liveChatMessages() + .list(liveChatId, "snippet, authorDetails") + .setFields(LIVE_CHAT_FIELDS) + .execute(); + + // Display messages and super chat details + long maxPublishTime = minPublishTime; + List messages = response.getItems(); + for (int i = 0; i < messages.size(); i++) { + LiveChatMessage message = messages.get(i); + LiveChatMessageSnippet snippet = message.getSnippet(); + long publishTime = snippet.getPublishedAt().getValue(); + if (publishTime >= minPublishTime) { + System.out.println(buildOutput( + snippet.getDisplayMessage(), + message.getAuthorDetails(), + snippet.getSuperChatDetails())); + } + maxPublishTime = Math.max(maxPublishTime, publishTime); + } + + // Request the next page of messages + listChatMessagesFixedPeriod(liveChatId, periodMs, maxPublishTime + 1); + } catch (Throwable t) { + System.err.println("Throwable: " + t.getMessage()); + t.printStackTrace(); + } + } + }, periodMs); + } + + /** + * Formats a chat message for console output. + * + * @param message The display message to output. + * @param author The author of the message. + * @param superChatDetails SuperChat details associated with the message. + * @return A formatted string for console output. + */ + private static String buildOutput( + String message, + LiveChatMessageAuthorDetails author, + LiveChatSuperChatDetails superChatDetails) { + StringBuilder output = new StringBuilder(); + if (superChatDetails != null) { + output.append(superChatDetails.getAmountDisplayString()); + output.append("SUPERCHAT RECEIVED FROM "); + } + output.append(author.getDisplayName()); + if (author.getIsChatOwner() || author.getIsChatOwner() || author.getIsChatSponsor()) { + output.append(" ("); + boolean appendComma = false; + if (author.getIsChatOwner()) { + output.append("OWNER"); + appendComma = true; + } + if (author.getIsChatModerator()) { + if (appendComma) { + output.append(", "); + } + output.append("MODERATOR"); + appendComma = true; + } + if (author.getIsChatSponsor()) { + if (appendComma) { + output.append(", "); + } + output.append("SPONSER"); + } + output.append(")"); + } + if (message != null && !message.isEmpty()) { + output.append(": "); + output.append(message); + } + return output.toString(); + } +} From 045e729e3eb1a1b7dc617eb7678ff6d40f50f1f5 Mon Sep 17 00:00:00 2001 From: Jim Rogers Date: Thu, 23 Mar 2017 13:32:02 -0700 Subject: [PATCH 2/6] Fix typo --- .../samples/youtube/cmdline/live/ListLiveChatMessages.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java index 223915c0..8bae1583 100644 --- a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java @@ -259,7 +259,7 @@ private static String buildOutput( if (appendComma) { output.append(", "); } - output.append("SPONSER"); + output.append("SPONSOR"); } output.append(")"); } From cb3a3813bf5e9b1efa39aa7223a4b79d01d50755 Mon Sep 17 00:00:00 2001 From: Jim Rogers Date: Thu, 23 Mar 2017 13:54:55 -0700 Subject: [PATCH 3/6] Apply formatting --- java/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/README.md b/java/README.md index bd7e0862..92256d2c 100644 --- a/java/README.md +++ b/java/README.md @@ -9,7 +9,7 @@ client ID and client secret. You can create an ID/secret pair at: To build this code sample from the command line, type: - mvn compile + mvn compile To run a code sample from the command line, enter the following: From e741fc278302a7b35058c80a2648af4a0e7181f4 Mon Sep 17 00:00:00 2001 From: Jim Rogers Date: Fri, 24 Mar 2017 14:45:57 -0700 Subject: [PATCH 4/6] Remove fixed period poll sample --- .../cmdline/live/ListLiveChatMessages.java | 73 +------------------ 1 file changed, 4 insertions(+), 69 deletions(-) diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java index 8bae1583..e9aac0a0 100644 --- a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java @@ -57,11 +57,6 @@ public class ListLiveChatMessages { */ private static YouTube youtube; - /** - * A timer used to schedule message retrieval. - */ - private static Timer pollTimer; - /** * Lists live chat messages and SuperChat details from a live broadcast. * @@ -94,11 +89,7 @@ public static void main(String[] args) { System.exit(1); } - /** - * List live chat messages with poll interval from server. Alternatively, messages - * may be requested at a fixed interval with listChatMessagesFixedPeriod, e.g. - * listChatMessagesFixedPeriod(liveChatId, 1000, 0) - */ + // Get live chat messages listChatMessages(liveChatId, null, 0); } catch (GoogleJsonResponseException e) { System.err @@ -116,7 +107,8 @@ public static void main(String[] args) { } /** - * Lists live chat messages, polling at the server supplied interval. + * Lists live chat messages, polling at the server supplied interval. Owners and moderators of a + * live chat will poll at a faster rate. * * @param liveChatId The live chat id to list messages from. * @param nextPageToken The page token from the previous request, if any. @@ -128,7 +120,7 @@ private static void listChatMessages( long delayMs) { System.out.println( String.format("Getting chat messages in %1$.3f seconds...", delayMs * 0.001)); - pollTimer = new Timer(); + Timer pollTimer = new Timer(); pollTimer.schedule( new TimerTask() { @Override @@ -166,63 +158,6 @@ public void run() { }, delayMs); } - /** - * Lists live chat messages, polling at the client supplied interval. This method is not - * recommended because it will consume more API usage, but it may be necessary in some - * applications that require lower latency. Page tokens do not work when polling faster than the - * server supplied interval, so we need to keep track of the publish time to avoid duplicate - * message output. Message ids will not work for tracking the last received message because - * messages may be removed from chat. - * - * @param liveChatId The live chat id to list messages from. - * @param periodMs The fixed interval to poll messages. - * @param minPublishTime The minimum message time to output. - */ - private static void listChatMessagesFixedPeriod( - final String liveChatId, - final long periodMs, - final long minPublishTime) { - System.out.println( - String.format("Getting chat messages in %1$.3f seconds...", periodMs * 0.001)); - pollTimer = new Timer(); - pollTimer.schedule( - new TimerTask() { - @Override - public void run() { - try { - // Get chat messages from YouTube - LiveChatMessageListResponse response = youtube - .liveChatMessages() - .list(liveChatId, "snippet, authorDetails") - .setFields(LIVE_CHAT_FIELDS) - .execute(); - - // Display messages and super chat details - long maxPublishTime = minPublishTime; - List messages = response.getItems(); - for (int i = 0; i < messages.size(); i++) { - LiveChatMessage message = messages.get(i); - LiveChatMessageSnippet snippet = message.getSnippet(); - long publishTime = snippet.getPublishedAt().getValue(); - if (publishTime >= minPublishTime) { - System.out.println(buildOutput( - snippet.getDisplayMessage(), - message.getAuthorDetails(), - snippet.getSuperChatDetails())); - } - maxPublishTime = Math.max(maxPublishTime, publishTime); - } - - // Request the next page of messages - listChatMessagesFixedPeriod(liveChatId, periodMs, maxPublishTime + 1); - } catch (Throwable t) { - System.err.println("Throwable: " + t.getMessage()); - t.printStackTrace(); - } - } - }, periodMs); - } - /** * Formats a chat message for console output. * From 518a2d355aaf7ce235b912ab72a6ae8df46ae223 Mon Sep 17 00:00:00 2001 From: Jim Rogers Date: Fri, 24 Mar 2017 15:12:07 -0700 Subject: [PATCH 5/6] Fix output for moderators --- .../samples/youtube/cmdline/live/ListLiveChatMessages.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java index e9aac0a0..8954ffaa 100644 --- a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java @@ -176,7 +176,7 @@ private static String buildOutput( output.append("SUPERCHAT RECEIVED FROM "); } output.append(author.getDisplayName()); - if (author.getIsChatOwner() || author.getIsChatOwner() || author.getIsChatSponsor()) { + if (author.getIsChatOwner() || author.getIsChatModerator() || author.getIsChatSponsor()) { output.append(" ("); boolean appendComma = false; if (author.getIsChatOwner()) { From cf7f9b3159c93f127fac853397e519004a250897 Mon Sep 17 00:00:00 2001 From: Jim Rogers Date: Tue, 28 Mar 2017 11:02:08 -0700 Subject: [PATCH 6/6] Clean up from CR feedback --- java/README.md | 17 +++-- .../cmdline/live/DeleteLiveChatMessage.java | 20 +----- .../youtube/cmdline/live/GetLiveChatId.java | 71 +++++++++++-------- .../cmdline/live/InsertLiveChatMessage.java | 16 ++--- .../cmdline/live/ListLiveChatMessages.java | 40 +++++------ 5 files changed, 76 insertions(+), 88 deletions(-) diff --git a/java/README.md b/java/README.md index 92256d2c..d9baaf89 100644 --- a/java/README.md +++ b/java/README.md @@ -218,7 +218,7 @@ job. Method: youtubeReporting.jobs.list, youtubeReporting.reports.list
Description: This sample demonstrates how to retrieve reports created by a specific job. It calls the jobs.list method to retrieve reporting jobs. It then calls the reports.list method with the -jobId parameter set to a specific job id to retrieve reports created by that job. Finally, the sample +jobId parameter set to a specific job ID to retrieve reports created by that job. Finally, the sample prints out the download URL for each report. ### [Create a broadcast and stream](/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/CreateBroadcast.java) @@ -245,24 +245,23 @@ that a channel can use to broadcast live events on YouTube. ### [Get a live chat id](/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java) Methods: youtube.videos.list, youtube.liveBroadcasts.list
-Description: This sample retrieves a live chat id from either a videoId parameter -or the current user's live broadcast. The liveChatId is required for other samples +Description: This sample retrieves the live chat ID from either a videoId parameter +or the live broadcast for the authorized user's channel. The liveChatId is required for other samples that interact with live chat. ### [Insert a live chat message](/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/InsertLiveChatMessage.java) Method: youtube.liveChatMessages.insert
-Description: This sample inserts a live chat message into the live chat specified by either -a videoId parameter or the current user's live broadcast. +Description: This sample inserts a live chat message into the the specified video or the live broadcast for +the authorized user's channel. ### [Delete a live chat message](/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/DeleteLiveChatMessage.java) Method: youtube.liveChatMessages.delete
-Description: This sample deletes a live chat message from the live chat specified by either -a videoId parameter or the current user's live broadcast. +Description: This sample deletes the specified live chat message. ### [List live chat messages](/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java) Method: youtube.liveChatMessages.list
-Description: This sample lists live chat messages from the chat specified by either -a videoId parameter or the current user's live broadcast. +Description: This sample lists live chat messages from the specified video or from the live broadcast for +the authorized user's channel. diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/DeleteLiveChatMessage.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/DeleteLiveChatMessage.java index a081fb12..51721623 100644 --- a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/DeleteLiveChatMessage.java +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/DeleteLiveChatMessage.java @@ -19,8 +19,8 @@ import com.google.api.services.samples.youtube.cmdline.Auth; import com.google.api.services.youtube.YouTube; import com.google.api.services.youtube.YouTubeScopes; +import com.google.common.collect.Lists; import java.io.IOException; -import java.util.ArrayList; import java.util.List; /** @@ -52,11 +52,8 @@ public static void main(String[] args) { } String messageId = args[0]; - // This OAuth 2.0 access scope allows for read-only access to the - // authenticated user's account, but not other types of account access. - List scopes = new ArrayList(); - scopes.add(YouTubeScopes.YOUTUBE_FORCE_SSL); - scopes.add(YouTubeScopes.YOUTUBE); + // This OAuth 2.0 access scope allows for write access to the authenticated user's account. + List scopes = Lists.newArrayList(YouTubeScopes.YOUTUBE_FORCE_SSL); try { // Authorize the request. @@ -66,17 +63,6 @@ public static void main(String[] args) { youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, credential) .setApplicationName("youtube-cmdline-deletechatmessages-sample").build(); - // Get the liveChatId - String liveChatId = GetLiveChatId.getLiveChatId( - youtube, - args.length == 2 ? args[1] : null); - if (liveChatId != null) { - System.out.println("Live chat id: " + liveChatId); - } else { - System.err.println("Unable to find a live chat id"); - System.exit(1); - } - // Delete the message from live chat YouTube.LiveChatMessages.Delete liveChatDelete = youtube.liveChatMessages().delete(messageId); diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java index 0a5b71a0..31602a05 100644 --- a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java @@ -68,7 +68,9 @@ public static void main(String[] args) { .setApplicationName("youtube-cmdline-getlivechatid-sample").build(); // Get the liveChatId - String liveChatId = getLiveChatId(youtube, args.length == 1 ? args[0] : null); + String liveChatId = args.length == 1 + ? getLiveChatId(youtube, args[0]) + : getLiveChatId(youtube); if (liveChatId != null) { System.out.println("Live chat id: " + liveChatId); } else { @@ -91,41 +93,48 @@ public static void main(String[] args) { } /** - * Retrieves the liveChatId from the videoId, if specified. If not specified, will find the - * liveChatId for the signed in user's live broadcast. + * Retrieves the liveChatId from the authenticated user's live broadcast. * * @param youtube The object is used to make YouTube Data API requests. - * @param videoId The videoId associated with the live chat (optional). * @return A liveChatId, or null if not found. */ - static String getLiveChatId(YouTube youtube, String videoId) throws IOException { - if (videoId != null && !videoId.isEmpty()) { - // Get liveChatId from the video - YouTube.Videos.List videoList = youtube.videos() - .list("liveStreamingDetails") - .setFields("items/liveStreamingDetails/activeLiveChatId") - .setId(videoId); - VideoListResponse response = videoList.execute(); - for (Video v : response.getItems()) { - String liveChatId = v.getLiveStreamingDetails().getActiveLiveChatId(); - if (liveChatId != null && !liveChatId.isEmpty()) { - return liveChatId; - } + static String getLiveChatId(YouTube youtube) throws IOException { + // Get signed in user's liveChatId + YouTube.LiveBroadcasts.List broadcastList = youtube + .liveBroadcasts() + .list("snippet") + .setFields("items/snippet/liveChatId") + .setBroadcastType("all") + .setBroadcastStatus("active"); + LiveBroadcastListResponse broadcastListResponse = broadcastList.execute(); + for (LiveBroadcast b : broadcastListResponse.getItems()) { + String liveChatId = b.getSnippet().getLiveChatId(); + if (liveChatId != null && !liveChatId.isEmpty()) { + return liveChatId; } - } else { - // Get signed in user's liveChatId - YouTube.LiveBroadcasts.List broadcastList = youtube - .liveBroadcasts() - .list("snippet") - .setFields("items/snippet/liveChatId") - .setBroadcastType("all") - .setBroadcastStatus("active"); - LiveBroadcastListResponse broadcastListResponse = broadcastList.execute(); - for (LiveBroadcast b : broadcastListResponse.getItems()) { - String liveChatId = b.getSnippet().getLiveChatId(); - if (liveChatId != null && !liveChatId.isEmpty()) { - return liveChatId; - } + } + + return null; + } + + /** + * Retrieves the liveChatId from the broadcast associated with a videoId. + * + * @param youtube The object is used to make YouTube Data API requests. + * @param videoId The videoId associated with the live broadcast. + * @return A liveChatId, or null if not found. + */ + static String getLiveChatId(YouTube youtube, String videoId) throws IOException { + // Get liveChatId from the video + YouTube.Videos.List videoList = youtube.videos() + .list("liveStreamingDetails") + .setFields("items/liveStreamingDetails/activeLiveChatId") + .setId(videoId); + VideoListResponse response = videoList.execute(); + for (Video v : response.getItems()) { + String liveChatId = v.getLiveStreamingDetails().getActiveLiveChatId(); + if (liveChatId != null && !liveChatId.isEmpty()) { + return liveChatId; } } diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/InsertLiveChatMessage.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/InsertLiveChatMessage.java index e8e66f62..09fe059c 100644 --- a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/InsertLiveChatMessage.java +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/InsertLiveChatMessage.java @@ -22,8 +22,8 @@ import com.google.api.services.youtube.model.LiveChatMessage; import com.google.api.services.youtube.model.LiveChatMessageSnippet; import com.google.api.services.youtube.model.LiveChatTextMessageDetails; +import com.google.common.collect.Lists; import java.io.IOException; -import java.util.ArrayList; import java.util.List; /** @@ -61,11 +61,8 @@ public static void main(String[] args) { } String message = args[0]; - // This OAuth 2.0 access scope allows for read-only access to the - // authenticated user's account, but not other types of account access. - List scopes = new ArrayList(); - scopes.add(YouTubeScopes.YOUTUBE_FORCE_SSL); - scopes.add(YouTubeScopes.YOUTUBE); + // This OAuth 2.0 access scope allows for write access to the authenticated user's account. + List scopes = Lists.newArrayList(YouTubeScopes.YOUTUBE_FORCE_SSL); try { // Authorize the request. @@ -76,9 +73,9 @@ public static void main(String[] args) { .setApplicationName("youtube-cmdline-insertchatmessage-sample").build(); // Get the liveChatId - String liveChatId = GetLiveChatId.getLiveChatId( - youtube, - args.length == 2 ? args[1] : null); + String liveChatId = args.length == 2 + ? GetLiveChatId.getLiveChatId(youtube, args[1]) + : GetLiveChatId.getLiveChatId(youtube); if (liveChatId != null) { System.out.println("Live chat id: " + liveChatId); } else { @@ -91,7 +88,6 @@ public static void main(String[] args) { LiveChatMessageSnippet snippet = new LiveChatMessageSnippet(); snippet.setType("textMessageEvent"); snippet.setLiveChatId(liveChatId); - snippet.setDisplayMessage(message); LiveChatTextMessageDetails details = new LiveChatTextMessageDetails(); details.setMessageText(message); snippet.setTextMessageDetails(details); diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java index 8954ffaa..463326ed 100644 --- a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/ListLiveChatMessages.java @@ -26,6 +26,7 @@ import com.google.api.services.youtube.model.LiveChatSuperChatDetails; import com.google.common.collect.Lists; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; @@ -79,9 +80,9 @@ public static void main(String[] args) { .setApplicationName("youtube-cmdline-listchatmessages-sample").build(); // Get the liveChatId - String liveChatId = GetLiveChatId.getLiveChatId( - youtube, - args.length == 1 ? args[0] : null); + String liveChatId = args.length == 1 + ? GetLiveChatId.getLiveChatId(youtube, args[0]) + : GetLiveChatId.getLiveChatId(youtube); if (liveChatId != null) { System.out.println("Live chat id: " + liveChatId); } else { @@ -176,25 +177,22 @@ private static String buildOutput( output.append("SUPERCHAT RECEIVED FROM "); } output.append(author.getDisplayName()); - if (author.getIsChatOwner() || author.getIsChatModerator() || author.getIsChatSponsor()) { + List roles = new ArrayList(); + if (author.getIsChatOwner()) { + roles.add("OWNER"); + } + if (author.getIsChatModerator()) { + roles.add("MODERATOR"); + } + if (author.getIsChatSponsor()) { + roles.add("SPONSOR"); + } + if (roles.size() > 0) { output.append(" ("); - boolean appendComma = false; - if (author.getIsChatOwner()) { - output.append("OWNER"); - appendComma = true; - } - if (author.getIsChatModerator()) { - if (appendComma) { - output.append(", "); - } - output.append("MODERATOR"); - appendComma = true; - } - if (author.getIsChatSponsor()) { - if (appendComma) { - output.append(", "); - } - output.append("SPONSOR"); + String delim = ""; + for (String role : roles) { + output.append(delim).append(role); + delim = ", "; } output.append(")"); }