org.aankor.animenforadio.api.WebsiteGate.java Source code

Java tutorial

Introduction

Here is the source code for org.aankor.animenforadio.api.WebsiteGate.java

Source

/*
 * This file is part of AnimeNfoRadio.
 * Copyright (C) 2014  aankor
 *
 * AnimeNfoRadio 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.
    
 * AnimeNfoRadio 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 AnimeNfoRadio.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.aankor.animenforadio.api;

import org.json.JSONException;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Date;
import java.util.EnumSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ssl.HttpsURLConnection;

public class WebsiteGate {
    private final Pattern mainNowPlayingPattern = Pattern
            .compile("^Artist: (.*) Title: (.*) Album: (.*) Album Type: (.*) Series: (.*) Genre\\(s\\): (.*)$");
    private final Pattern raitingNowPlayingPattern = Pattern.compile("Rating: (.*)\n");
    private final Pattern nowPlayingBarPattern = Pattern.compile("^left: ([\\d\\.]*)%$");
    private String phpSessID = "";
    private SongInfo currentSong = null;
    private long currentSongEndTime = 0;
    private SongPos currentSongPos = null;

    public SongInfo getCurrentSong() {
        return currentSong;
    }

    public long getCurrentSongEndTime() {
        return currentSongEndTime;
    }

    public int getCurrentSongPosTime() {
        return currentSongPos.time;
    }

    public String getCurrentSongPosTimeStr() {
        return currentSongPos.timeStr;
    }

    public double getCurrentSongPosPercent() {
        return currentSongPos.percent;
    }

    private void fetchCookies() throws IOException {
        if (phpSessID.equals("")) {
            URL url = new URL("https://www.animenfo.com/radio/index.php");
            HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
            con.setRequestMethod("GET");
            con.connect();
            updateCookies(con);
        }
    }

    private void updateCookies(HttpsURLConnection con) {
        Pattern titlePattern = Pattern.compile("PHPSESSID=([^;]*);");
        Matcher matcher = titlePattern.matcher(con.getHeaderField("Set-Cookie"));
        if (matcher.find())
            phpSessID = matcher.group(1);
    }

    // return currentSongPos updated
    private boolean updateNowPlaying(String nowPlaying) {
        Document doc = Jsoup.parse(nowPlaying);

        Elements spans = doc.select("div .float-container .row .span6");

        Matcher matcher = mainNowPlayingPattern.matcher(spans.first().text());

        if (!matcher.find()) {
            unsetCurrentSong();
            return false;
        }
        SongInfo newSongInfo = new SongInfo(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4),
                matcher.group(5), matcher.group(6));

        Elements e = doc.select("div img");
        if (!e.isEmpty()) {
            String artUrl = e.attr("src");
            newSongInfo.setArtUrl(artUrl);
        } else
            newSongInfo.unsetArtUrl();

        newSongInfo.setSongId(Integer.valueOf(spans.get(1).select("a[data-songinfo]").attr("data-songinfo")));

        int songPosTime = Integer.valueOf(spans.get(1).select("#np_timer").attr("rel"));
        long currentTime = (new Date()).getTime();
        currentSongEndTime = currentTime + songPosTime * 1000l;
        String songPosTimeStr = spans.get(1).select("#np_timer").text();
        newSongInfo.setDuration(Integer.valueOf(spans.get(1).select("#np_time").attr("rel")));
        newSongInfo.setDurationStr(spans.get(1).select("#np_time").text());

        matcher = raitingNowPlayingPattern.matcher(spans.get(1).html());

        if (matcher.find())
            newSongInfo.setRating(matcher.group(1));
        else
            newSongInfo.unsetRating();

        newSongInfo.setFavourites(Integer.valueOf(spans.get(1)
                .select(".favourite-container span[data-favourite-count]").attr("data-favourite-count")));

        matcher = nowPlayingBarPattern.matcher(doc.select("#nowPlayingBar").attr("style"));
        double nowPlayingPos = 0.0;
        if (matcher.find())
            nowPlayingPos = Double.valueOf(matcher.group(1));

        if ((currentSong != null) && newSongInfo.getArtUrl().equals(currentSong.getArtUrl()))
            newSongInfo.setArtBmp(currentSong.getArtBmp(), currentSong.getMiniArtBmp());
        currentSong = newSongInfo;
        currentSongPos = new SongPos(songPosTime, songPosTimeStr, nowPlayingPos);
        return true;
    }

    private JSONObject request(EnumSet<Subscription> subscriptions) throws IOException, JSONException {
        // fetchCookies();

        // TODO: fetch peice by piece
        URL url = new URL("https://www.animenfo.com/radio/index.php?t=" + (new Date()).getTime());
        // URL url = new URL("http://192.168.0.2:12345/");
        String body = "{\"ajaxcombine\":true,\"pages\":[{\"uid\":\"nowplaying\",\"page\":\"nowplaying.php\",\"args\":{\"mod\":\"playing\"}}"
                + ",{\"uid\":\"queue\",\"page\":\"nowplaying.php\",\"args\":{\"mod\":\"queue\"}},{\"uid\":\"recent\",\"page\":\"nowplaying.php\",\"args\":{\"mod\":\"recent\"}}]}";
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("Accept", "application/json");
        con.setRequestProperty("Accept-Encoding", "gzip, deflate");
        con.setRequestProperty("Content-Type", "application/json");
        if (!phpSessID.equals(""))
            con.setRequestProperty("Cookie", "PHPSESSID=" + phpSessID);
        con.setRequestProperty("Host", "www.animenfo.com");
        con.setRequestProperty("Referer", "https://www.animenfo.com/radio/nowplaying.php");
        con.setRequestProperty("User-Agent",
                "Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.1.0");
        // con.setUseCaches (false);
        con.setDoInput(true);
        con.setDoOutput(true);

        //Send request

        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes(body);
        wr.flush();
        wr.close();
        InputStream is = con.getInputStream();
        BufferedReader rd = new BufferedReader(new InputStreamReader(is));
        String line;
        StringBuilder response = new StringBuilder();
        while ((line = rd.readLine()) != null) {
            response.append(line);
        }
        rd.close();

        // updateCookies(con);
        return new JSONObject(response.toString());

    }

    public void fetch(EnumSet<Subscription> subscriptions) {
        boolean currentSongPosUpdated = false;
        if (!subscriptions.isEmpty()) {
            try {
                JSONObject res = request(subscriptions);
                if (subscriptions.contains(Subscription.CURRENT_SONG))
                    currentSongPosUpdated = updateNowPlaying(res.getString("nowplaying"));
            } catch (Exception e) {
                unsetCurrentSong();
            }
        }

        if (!currentSongPosUpdated) {
            if (currentSong == null)
                currentSongPos = null;
            else
                currentSongPos = new SongPos(currentSongEndTime, currentSong.getDuration());
        }
    }

    public void unsetCurrentSong() {
        if (getCurrentSongEndTime() < (new Date()).getTime())
            currentSong = null;
    }

    public enum Subscription {
        CURRENT_SONG, QUEUE
    }

    private static class SongPos {
        public int time;
        public String timeStr;
        public double percent;

        private SongPos(int time, String timeStr, double percent) {
            this.time = time;
            this.timeStr = timeStr;
            this.percent = percent;
            fix();
        }

        private SongPos(long currentSongEndTime, int currentSongDuration) {
            long currentTime = new Date().getTime();
            time = (int) ((currentSongEndTime - currentTime) / 1000);
            final int secs = (time % 60);
            timeStr = (time / 60) + ":" + ((secs < 10) ? "0" : "") + secs;
            percent = (100.0 * (currentSongDuration - time)) / currentSongDuration;
            fix();
        }

        private void fix() {
            if (time < 0) {
                time = 0;
                timeStr = "0:00";
            }
            if (percent < 0)
                percent = 0;
            else if (percent > 100)
                percent = 100;
        }
    }

}