001/*
002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *      Nelson Silva
018 */
019
020package org.nuxeo.ecm.media.publishing.youtube;
021
022import com.google.api.client.auth.oauth2.Credential;
023import com.google.api.client.googleapis.media.MediaHttpUploader;
024import com.google.api.client.googleapis.media.MediaHttpUploaderProgressListener;
025import com.google.api.client.http.HttpStatusCodes;
026import com.google.api.client.http.HttpTransport;
027import com.google.api.client.http.InputStreamContent;
028import com.google.api.client.http.javanet.NetHttpTransport;
029import com.google.api.client.json.JsonFactory;
030import com.google.api.client.json.jackson.JacksonFactory;
031import com.google.api.services.youtube.YouTube;
032import com.google.api.services.youtube.YouTube.Videos.Delete;
033import com.google.api.services.youtube.YouTube.Videos.Insert;
034import com.google.api.services.youtube.model.*;
035import org.apache.commons.logging.Log;
036import org.apache.commons.logging.LogFactory;
037import org.nuxeo.ecm.platform.oauth2.providers.OAuth2ServiceProviderRegistry;
038import org.nuxeo.runtime.api.Framework;
039
040import java.io.IOException;
041import java.io.InputStream;
042import java.util.List;
043
044/**
045 * Client for the YouTube API
046 *
047 * @since 7.3
048 */
049public class YouTubeClient {
050    private static final Log log = LogFactory.getLog(YouTubeClient.class);
051
052    /** Global instance of the HTTP transport. */
053    private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
054
055    /** Global instance of the JSON factory. */
056    private static final JsonFactory JSON_FACTORY = new JacksonFactory();
057
058    YouTube youtube;
059
060    Credential credential;
061
062    public YouTubeClient(Credential credential) {
063        this.credential = credential;
064    }
065
066    protected OAuth2ServiceProviderRegistry getOAuth2ServiceProviderRegistry() {
067        return Framework.getLocalService(OAuth2ServiceProviderRegistry.class);
068    }
069
070    public boolean isAuthorized() {
071        return (credential != null && credential.getAccessToken() != null);
072    }
073
074    public YouTube getYouTube() throws IOException {
075
076        // if credential found with an access token, invoke the user code
077        if (youtube == null) {
078            youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY,
079                credential).setApplicationName("nuxeo-media-publishing").build();
080        }
081        return youtube;
082    }
083
084    public List<Video> getVideos() throws IOException {
085        return getYouTube().videos().list("snippet").execute().getItems();
086    }
087
088    public List<Channel> getChannels() throws IOException {
089        return getYouTube().channels().list("snippet").setMine(true).execute().getItems();
090    }
091
092    public List<PlaylistItem> getVideos(Channel channel) throws IOException {
093        String id = channel.getId();
094        return getYouTube().playlistItems().list("snippet").setPlaylistId(id).execute().getItems();
095    }
096
097    public Video upload(Video video, InputStream stream, String type, long length,
098        final MediaHttpUploaderProgressListener uploadListener) throws IOException {
099
100        InputStreamContent mediaContent = new InputStreamContent(type, stream);
101        mediaContent.setLength(length);
102
103        Insert insert = getYouTube().videos().insert("snippet,status", video, mediaContent);
104
105        // Set the upload type and add event listener.
106        MediaHttpUploader uploader = insert.getMediaHttpUploader();
107
108        /*
109         * Sets whether direct media upload is enabled or disabled. True = whole
110         * media content is uploaded in a single request. False (default) =
111         * resumable media upload protocol to upload in data chunks.
112         */
113        uploader.setDirectUploadEnabled(false);
114
115        uploader.setProgressListener(uploadListener);
116
117        // Execute upload.
118        Video returnedVideo = insert.execute();
119
120        // Print out returned results.
121        if (returnedVideo != null) {
122            log.info("\n================== Returned Video ==================\n");
123            log.info("  - Id: " + returnedVideo.getId());
124            log.info("  - Title: " + returnedVideo.getSnippet().getTitle());
125            log.info("  - Tags: " + returnedVideo.getSnippet().getTags());
126            log.info("  - Privacy Status: " + returnedVideo.getStatus().getPrivacyStatus());
127        }
128
129        return returnedVideo;
130
131    }
132
133    public void setPrivacyStatus(String videoId, String privacyStatus) throws IOException {
134        Video youtubeVideo = new Video();
135        youtubeVideo.setId(videoId);
136
137        VideoStatus status = new VideoStatus();
138        status.setPrivacyStatus(privacyStatus);
139        youtubeVideo.setStatus(status);
140
141        getYouTube().videos().update("status", youtubeVideo).execute();
142    }
143
144    public boolean delete(String videoId) throws IOException {
145        Delete deleteRequest = getYouTube().videos().delete(videoId);
146        return deleteRequest.executeUnparsed().getStatusCode() == HttpStatusCodes.STATUS_CODE_NO_CONTENT;
147    }
148
149    public VideoStatistics getStatistics(String videoId) throws IOException {
150        VideoListResponse list = getYouTube().videos().list("statistics").setId(videoId).execute();
151
152        if (list.isEmpty() || list.getItems().size() == 0) {
153            return null;
154        }
155
156        Video video = list.getItems().get(0);
157        return video.getStatistics();
158    }
159}