Saturday, August 24, 2013

Next, the frontend, using primefaces mobile

Ok, now that we have the backend, it's time to start playing with some frontend. My first idea was to create something I could access from the blue-ray player or from the smart tv, but neither have a decent browser. Then I've considered learning a little android app development, but the UI is not incredibly complex.

Then I remembered Primeface Mobile UI. It's just JSF, so it's fast and easy. And I've tried a little and it looks good in my xperia :-) It's powered by jQuery mobile, so it's good stuff IMO.

Things that weren't obvious for those who does not like to wait, about primefaces mobile configuration:

[1] you have to install both primefaces and primefaces mobile jars, since the renderer is in the "core" primefaces jar.

<f:view xmlns="http://www.w3.org/1999/xhtml"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:p="http://primefaces.org/ui"
        xmlns:pm="http://primefaces.org/mobile"       
        contentType="text/html"
        renderKitId="PRIMEFACES_MOBILE">

    <pm:page title="Components">
        <pm:view id="main">
            <pm:header title="Header" />
            <pm:content>Content</pm:content>
        </pm:view>
    </pm:page>
</f:view>


[2] the minimal web.xml you need (I like xhtml)

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Movies</display-name>
    <context-param>
        <param-name>com.sun.faces.allowTextChildren</param-name>
        <param-value>true</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>/index.xhtml</welcome-file>
    </welcome-file-list>
</web-app>



Friday, August 23, 2013

How to add the torrent to your local uTorrent via Web API

after getting the torrent (see http://leonotepad.blogspot.com.br/2013/08/how-to-find-torrent-for-legend-youve.html), now it's time to download it.

uTorrent has some nice web API. This means that if you're running uTorrent at your machine, you can also control it using some http requests.

so, first, enable the web UI.

then, you'll need the (new) apache http client (or just anything that can deal with http BASIC auth)

please notice that you have to get the token. (don't worry, see the example below).

so now, just put the pieces together and make your own movie downloader at home :-)

package movies.backend;

import java.io.InputStream;
import java.io.StringWriter;
import java.net.URLEncoder;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;

public class TorrentDownload {

    public static void main(String[] args) throws Exception {

        HttpHost targetHost = new HttpHost("127.0.0.1", 8888, "http");

        DefaultHttpClient httpclient = new DefaultHttpClient();
        try {
            httpclient.getCredentialsProvider().setCredentials(
                    new AuthScope(targetHost.getHostName(), targetHost.getPort()),
                    new UsernamePasswordCredentials("xxx", "xxx"));

            // Create AuthCache instance
            AuthCache authCache = new BasicAuthCache();
            // Generate BASIC scheme object and add it to the local
            // auth cache
            BasicScheme basicAuth = new BasicScheme();
            authCache.put(targetHost, basicAuth);

            // Add AuthCache to the execution context
            BasicHttpContext localcontext = new BasicHttpContext();
            localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);

            HttpGet httpget = new HttpGet("http://127.0.0.1:8888/gui/");
            HttpResponse response = httpclient.execute(targetHost, httpget, localcontext);
            EntityUtils.consumeQuietly(response.getEntity());
           
            httpget = new HttpGet("http://127.0.0.1:8888/gui/token.html");
            response = httpclient.execute(targetHost, httpget, localcontext);
           
            HttpEntity e = response.getEntity();
            InputStream is = e.getContent();
            StringWriter sw = new StringWriter();
            IOUtils.copy(is, sw);
            sw.flush();
            sw.close();
            is.close();
            //<html><div id='token' style='display:none;'>gzB9zbMru3JJlBf2TbmwwklESgXW2hD_caJfFLvNBjmaRbLZ3kNGnSHrFlIAAAAA</div></html>
            String t = sw.toString();
            int start = "<html><div id='token' style='display:none;'>".length();
            int end = t.indexOf("</div></html>");
            String token = t.substring(start,end);
            System.out.println(token);
            EntityUtils.consumeQuietly(response.getEntity());
           
            String add = URLEncoder.encode("http://www.torrentportal.com/download/6066218/True.Blood.S06E01.Who.Are.You.Really.XviD-MGD%5Bettv%5D.torrent","UTF-8");
            httpget = new HttpGet("http://127.0.0.1:8888/gui/?action=add-url&s="+add+"&token="+token);
            response = httpclient.execute(targetHost, httpget, localcontext);
           
            e = response.getEntity();
            is = e.getContent();
            sw = new StringWriter();
            IOUtils.copy(is, sw);
            sw.flush();
            sw.close();
            is.close();
            System.out.println(sw.toString());

        } finally {
            // When HttpClient instance is no longer needed,
            // shut down the connection manager to ensure
            // immediate deallocation of all system resources
            httpclient.getConnectionManager().shutdown();
        }
    }
}


How to find the torrent for the legend you've got at opensubtitles.org using Isohunt web API

after getting the subtitle (see http://leonotepad.blogspot.com.br/2013/08/how-to-search-and-retrieve-subtitle.html), now it's time to find the torrent.

Isohunt has some nice web API.

package movies.backend;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

import flexjson.JSONDeserializer;

public class IsohuntTorrentSearch {

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        URL url = new URL("http://ca.isohunt.com/js/json.php?ihq="+URLEncoder.encode("True.Blood.S06E01.Who.Are.You.Really.720p","UTF-8")+"&start=21&rows=20&sort=seeds");
        Map json = (Map)new JSONDeserializer().deserialize(new InputStreamReader(url.openStream()));
        Map items = (Map)json.get("items");
        List list = (List)items.get("list");
        System.out.println(list.get(0));
        Map item = (Map)list.get(0);
        System.out.println(item.get("tracker_url"));
    }
}

How to search and retrieve a subtitle from opensubtitles.org using Java

First, you'll have to ask them for a valid user agent, but for test purposes, you can use "OS Test User Agent".

All the API details are described at http://trac.opensubtitles.org/projects/opensubtitles/wiki/XMLRPC.

You'll need

commons-io-2.4.jar
commons-logging-1.1.jar
ws-commons-util-1.0.2.jar
xmlrpc-client-3.1.3.jar
xmlrpc-common-3.1.3.jar


and Oracle java 7.

package movies.backend;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import org.apache.commons.io.IOUtils;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;

import sun.misc.BASE64Decoder;

public class SubtitleSearchService {

    /**
     * @param args
     * @throws XmlRpcException
     * @throws IOException
     */
    public static void main(String[] args) throws XmlRpcException, IOException {
        XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
        config.setServerURL(new URL("http://api.opensubtitles.org/xml-rpc"));
        XmlRpcClient client = new XmlRpcClient();
        client.setConfig(config);
        Object username = "xxx";
        Object password = "xxx";
        Object language = "pob";
        Object useragent = "OS Test User Agent";
        Object[] params = new Object[] { username, password, language, useragent };
        Map result = (Map) client.execute("LogIn", params);
        String status = (String) result.get("status");
        String token = (String) result.get("token");

        Object imdbQuery = "true blood";
        params = new Object[] { token, imdbQuery  };
        result = (Map) client.execute("SearchMoviesOnIMDB", params);
       
        System.out.println(result);
       
        Object[] data = (Object[])result.get("data");
        Map dataMap = (Map)data[0];
        Object id = dataMap.get("id");
        Object title = dataMap.get("title");
       
        Map movieQuery = new HashMap();
        movieQuery.put("sublanguageid", "pob");
        movieQuery.put("imdbid", id);
       
        Object[] listQuery = {movieQuery};
       
        params = new Object[] { token, listQuery   };
        result = (Map) client.execute("SearchSubtitles", params);
       
        System.out.println(result);
       
        data = (Object[])result.get("data");
        dataMap = (Map)data[0];
       
        System.out.println(dataMap.get("SubFileName"));
        //SubDownloadLink=http://dl.opensubtitles.org/en/download/filead/1953590867.gz/sid-ojl76mmpi89o8tvpb3ebl45d83
        System.out.println(dataMap.get("SubDownloadLink"));
       
        String downloadLink = (String)dataMap.get("SubDownloadLink");
        downloadLink = downloadLink.replaceFirst("http://dl.opensubtitles.org/en/download/filead/", "");
        Object subFileId = downloadLink.substring(0, downloadLink.indexOf(".gz"));

        Map listOfSubtitles = new HashMap();
        listOfSubtitles.put("data", subFileId);
        params = new Object[] { token, listOfSubtitles    };
        result = (Map) client.execute("DownloadSubtitles", params);
       
        System.out.println(result);
       
        data = (Object[])result.get("data");
        dataMap = (Map)data[0];
       
        System.out.print(dataMap.get("data"));
       
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] gzip = decoder.decodeBuffer((String)dataMap.get("data"));

        GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(gzip));
        StringWriter sw = new StringWriter();
       
        IOUtils.copy(gis, sw);
        sw.flush();
        sw.close();
        gis.close();
       
        System.out.println(sw.toString());
       
        params = new Object[] { token };
        client.execute("LogOut", params);
       
    }

}


enjoy