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 *      André Justo
016 */
017
018package org.nuxeo.ecm.media.publishing.wistia;
019
020import com.google.api.client.auth.oauth2.Credential;
021import com.sun.jersey.core.util.MultivaluedMapImpl;
022import org.apache.commons.logging.Log;
023import org.apache.commons.logging.LogFactory;
024import org.nuxeo.ecm.core.api.Blob;
025import org.nuxeo.ecm.core.api.NuxeoException;
026import org.nuxeo.ecm.media.publishing.wistia.model.Media;
027import org.nuxeo.ecm.media.publishing.OAuth2MediaPublishingProvider;
028import org.nuxeo.ecm.media.publishing.adapter.PublishableMedia;
029import org.nuxeo.ecm.media.publishing.upload.MediaPublishingProgressListener;
030import org.nuxeo.ecm.media.publishing.wistia.model.Project;
031import org.nuxeo.ecm.media.publishing.wistia.model.Stats;
032
033import javax.ws.rs.core.MultivaluedMap;
034import java.io.IOException;
035import java.util.Collections;
036import java.util.HashMap;
037import java.util.List;
038import java.util.Map;
039import java.util.Map.Entry;
040
041/**
042 * Wistia Media Publishing Provider Service
043 *
044 * @since 7.3
045 */
046public class WistiaService extends OAuth2MediaPublishingProvider {
047
048    private static final Log log = LogFactory.getLog(WistiaService.class);
049
050    public static final String PROVIDER = "Wistia";
051
052    public WistiaService() {
053        super(PROVIDER);
054    }
055
056    public WistiaClient getWistiaClient(String account) {
057        Credential credential = getCredential(account);
058        if (credential == null) {
059            return null;
060        }
061        try {
062            // Refresh access token if needed (based on com.google.api.client.auth.oauth.Credential.intercept())
063            // TODO: rely on Google Oauth aware client instead
064            Long expiresIn = credential.getExpiresInSeconds();
065            // check if token will expire in a minute
066            if (credential.getAccessToken() == null || expiresIn != null && expiresIn <= 60) {
067                credential.refreshToken();
068                if (credential.getAccessToken() == null) {
069                    // nothing we can do without an access token
070                    throw new NuxeoException("Failed to refresh access token");
071                }
072            }
073        } catch (IOException e) {
074            throw new NuxeoException(e.getMessage(), e);
075        }
076
077        return new WistiaClient(credential.getAccessToken());
078    }
079
080    @Override
081    public String upload(PublishableMedia media, MediaPublishingProgressListener progressListener, String account, Map<String, String> options) throws IOException {
082        MultivaluedMap<String, String> params = new MultivaluedMapImpl();
083
084        params.putSingle("name", media.getTitle());
085        params.putSingle("description", media.getDescription());
086
087        for (Entry<String, String> entry : options.entrySet()) {
088            if (entry.getValue() != null && entry.getValue().length() > 0) {
089                params.putSingle(entry.getKey(), entry.getValue());
090            }
091        }
092
093        // upload original video
094        Blob blob = media.getBlob();
095
096        Media video = getWistiaClient(account).upload(blob.getFilename(), blob.getStream(), params);
097
098        return video.getHashedId();
099    }
100
101    @Override
102    public boolean unpublish(PublishableMedia media) {
103        String account = media.getAccount(PROVIDER);
104        String mediaId = media.getId(PROVIDER);
105        return getWistiaClient(account).deleteMedia(mediaId) != null;
106    }
107
108    @Override
109    public String getPublishedUrl(String mediaId, String account) {
110        WistiaClient client = getWistiaClient(account);
111        return client == null ? null : client.getAccount().getUrl() + "/medias/" + mediaId;
112    }
113
114    @Override
115    public String getEmbedCode(String mediaId, String account) {
116        WistiaClient client = getWistiaClient(account);
117        return client == null ? null : client.getEmbedCode(getPublishedUrl(mediaId, account));
118    }
119
120    @Override
121    public Map<String, String> getStats(String mediaId, String account) {
122        WistiaClient client = getWistiaClient(account);
123        if (client == null) {
124            return null;
125        }
126
127        Stats stats = client.getMediaStats(mediaId);
128        if (stats == null) {
129            return null;
130        }
131
132        Map<String, String> map = new HashMap<>();
133        map.put("label.mediaPublishing.stats.visitors", Integer.toString(stats.getVisitors()));
134        map.put("label.mediaPublishing.stats.plays", Integer.toString(stats.getPlays()));
135        map.put("label.mediaPublishing.stats.averagePercentWatched", Integer.toString(stats.getAveragePercentWatched()));
136        map.put("label.mediaPublishing.stats.pageLoads", Integer.toString(stats.getPageLoads()));
137        map.put("label.mediaPublishing.stats.percentOfVisitorsClickingPlay", Integer.toString(stats.getPercentOfVisitorsClickingPlay()));
138        return map;
139    }
140
141    @Override
142    public boolean isMediaPublished(String mediaId, String account) {
143        WistiaClient client = getWistiaClient(account);
144        if (client == null) {
145            return false;
146        }
147
148        Media media = client.getMedia(mediaId);
149        return media != null;
150    }
151
152    public List<Project> getProjects(String account) {
153        WistiaClient client = getWistiaClient(account);
154        return client == null ? Collections.emptyList() : client.getProjects();
155    }
156}