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