org.messic.server.api.musicinfo.youtube.MusicInfoYoutubePlugin.java Source code

Java tutorial

Introduction

Here is the source code for org.messic.server.api.musicinfo.youtube.MusicInfoYoutubePlugin.java

Source

/*
 * Copyright (C) 2013
 *
 *  This file is part of Messic.
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.messic.server.api.musicinfo.youtube;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Locale;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.messic.server.api.musicinfo.service.MusicInfoPlugin;
import org.messic.server.api.plugin.MessicPlugin;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

public class MusicInfoYoutubePlugin implements MusicInfoPlugin {

    private Logger log = Logger.getLogger(MusicInfoYoutubePlugin.class);

    public static final String NAME = "YOUTUBE";

    public static final String PROVIDER_NAME = "Youtube";

    public static final String EN_DESCRIPTION = "Plugin to obtain videos from youtube.";

    public static final float VERSION = 1.0f;

    public static final float MINIMUM_MESSIC_VERSION = 1.0f;

    /** configuration for the plugin */
    private Properties configuration;

    private Proxy getProxy() {
        if (this.configuration != null) {
            String url = (String) this.configuration.get(MessicPlugin.CONFIG_PROXY_URL);
            String port = (String) this.configuration.get(MessicPlugin.CONFIG_PROXY_PORT);
            if (url != null && port != null && url.length() > 0 && port.length() > 0) {
                SocketAddress addr = new InetSocketAddress(url, Integer.valueOf(port));
                Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
                return proxy;
            }
        }
        return null;
    }

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public Properties getConfiguration() {
        return null;
    }

    @Override
    public void setConfiguration(Properties properties) {
        this.configuration = properties;
    }

    @Override
    public String getDescription(Locale locale) {
        // TODO any other language
        return EN_DESCRIPTION;
    }

    private String search(Locale locale, String search) throws IOException {

        // http://ctrlq.org/code/19608-youtube-search-api
        // Based con code writted by Amit Agarwal

        // YouTube Data API base URL (JSON response)
        String surl = "v=2&alt=jsonc";
        // set paid-content as false to hide movie rentals
        surl = surl + "&paid-content=false";
        // set duration as long to filter partial uploads
        // url = url + "&duration=long";
        // order search results by view count
        surl = surl + "&orderby=viewCount";
        // we can request a maximum of 50 search results in a batch
        surl = surl + "&max-results=50";
        surl = surl + "&q=" + search;

        URI uri = null;
        try {
            uri = new URI("http", "gdata.youtube.com", "/feeds/api/videos", surl, null);
        } catch (URISyntaxException e) {
            log.error("failed!", e);
        }

        URL url = new URL(uri.toASCIIString());
        log.info(surl);
        Proxy proxy = getProxy();
        URLConnection connection = (proxy != null ? url.openConnection(proxy) : url.openConnection());
        InputStream is = connection.getInputStream();

        JsonFactory jsonFactory = new JsonFactory(); // or, for data binding,
                                                     // org.codehaus.jackson.mapper.MappingJsonFactory
        JsonParser jParser = jsonFactory.createParser(is);

        String htmlCode = "<script type=\"text/javascript\">";
        htmlCode = htmlCode + "  function musicInfoYoutubeDestroy(){";
        htmlCode = htmlCode + "       $('.messic-musicinfo-youtube-overlay').remove();";
        htmlCode = htmlCode + "       $('.messic-musicinfo-youtube-iframe').remove();";
        htmlCode = htmlCode + "  }";
        htmlCode = htmlCode + "  function musicInfoYoutubePlay(id){";
        htmlCode = htmlCode
                + "      var code='<div class=\"messic-musicinfo-youtube-overlay\" onclick=\"musicInfoYoutubeDestroy()\"></div>';";
        htmlCode = htmlCode
                + "      code=code+'<iframe class=\"messic-musicinfo-youtube-iframe\" src=\"http://www.youtube.com/embed/'+id+'\" frameborder=\"0\" allowfullscreen></iframe>';";
        htmlCode = htmlCode + "      $(code).hide().appendTo('body').fadeIn();";
        htmlCode = htmlCode + "  }";
        htmlCode = htmlCode + "</script>";

        // loop until token equal to "}"
        while (jParser.nextToken() != null) {
            String fieldname = jParser.getCurrentName();
            if ("items".equals(fieldname)) {
                jParser.nextToken();
                while (jParser.nextToken() != JsonToken.END_OBJECT) {
                    YoutubeItem yi = new YoutubeItem();
                    while (jParser.nextToken() != JsonToken.END_OBJECT) {
                        if (jParser.getCurrentToken() == JsonToken.START_OBJECT) {
                            jParser.skipChildren();
                        }
                        fieldname = jParser.getCurrentName();

                        if ("id".equals(fieldname)) {
                            jParser.nextToken();
                            yi.id = jParser.getText();
                        }
                        if ("category".equals(fieldname)) {
                            jParser.nextToken();
                            yi.category = jParser.getText();
                        }
                        if ("title".equals(fieldname)) {
                            jParser.nextToken();
                            yi.title = jParser.getText();
                        }
                        if ("description".equals(fieldname)) {
                            jParser.nextToken();
                            yi.description = jParser.getText();
                        }
                        if ("thumbnail".equals(fieldname)) {
                            jParser.nextToken();
                            jParser.nextToken();
                            jParser.nextToken();
                            jParser.nextToken();
                            fieldname = jParser.getCurrentName();
                            if ("hqDefault".equals(fieldname)) {
                                jParser.nextToken();
                                yi.thumbnail = jParser.getText();
                            }
                            jParser.nextToken();
                        }
                    }

                    if (yi.category != null && "MUSIC".equals(yi.category.toUpperCase()) || (yi.category == null)) {
                        if (yi.title != null) {
                            htmlCode = htmlCode + "<div class=\"messic-musicinfo-youtube-item\"><img src=\""
                                    + yi.thumbnail
                                    + "\"/><div class=\"messic-musicinfo-youtube-item-play\" onclick=\"musicInfoYoutubePlay('"
                                    + yi.id + "')\"></div>" + "<div class=\"messic-musicinfo-youtube-description\">"
                                    + "  <div class=\"messic-musicinfo-youtube-item-title\">" + yi.title + "</div>"
                                    + "  <div class=\"messic-musicinfo-youtube-item-description\">" + yi.description
                                    + "</div>" + "</div>" + "</div>";
                        }
                    }
                }
            }

        }
        return htmlCode;
    }

    @Override
    public String getAuthorInfo(Locale locale, String authorName) {
        try {
            return search(locale, "\"" + authorName + "\"");
        } catch (IOException e) {
            log.error("failed!", e);
            return "ERROR: " + e.getMessage();
        }
    }

    @Override
    public String getAlbumInfo(Locale locale, String authorName, String albumName) {
        try {
            return search(locale, "\"" + albumName + "\" " + "\"" + authorName + "\"");
        } catch (IOException e) {
            log.error("failed!", e);
            return "ERROR: " + e.getMessage();
        }
    }

    @Override
    public String getSongInfo(Locale locale, String authorName, String albumName, String songName) {
        try {
            return search(locale, "\"" + songName + "\"" + " \"" + albumName + "\" " + "\"" + authorName);
        } catch (IOException e) {
            log.error("failed!", e);
            return "ERROR: " + e.getMessage();
        }
    }

    @Override
    public float getVersion() {
        return VERSION;
    }

    @Override
    public float getMinimumMessicVersion() {
        return MINIMUM_MESSIC_VERSION;
    }

    @Override
    public byte[] getProviderIcon() {
        InputStream is = MusicInfoYoutubePlugin.class
                .getResourceAsStream("/org/messic/server/api/musicinfo/youtube/YouTube-logo-full_color.png");
        try {
            return readInputStream(is);
        } catch (IOException e) {
            // TODO
            return null;
        }
    }

    /**
     * Read an inputstream and return a byte[] with the whole content of the readed at the inputstream
     * 
     * @param is {@link InputStream}
     * @return byte[] content
     * @throws IOException
     */
    public static byte[] readInputStream(InputStream is) throws IOException {
        byte[] buffer = new byte[1024];
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int cant = is.read(buffer);
        while (cant > 0) {
            baos.write(buffer, 0, cant);
            cant = is.read(buffer);
        }

        return baos.toByteArray();
    }

    @Override
    public String getProviderName() {
        return PROVIDER_NAME;
    }

}