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