serposcope.controllers.google.GoogleSearchController.java Source code

Java tutorial

Introduction

Here is the source code for serposcope.controllers.google.GoogleSearchController.java

Source

/* 
 * Serposcope - SEO rank checker https://serposcope.serphacker.com/
 * 
 * Copyright (c) 2016 SERP Hacker
 * @author Pierre Nogues <support@serphacker.com>
 * @license https://opensource.org/licenses/MIT MIT License
 */
package serposcope.controllers.google;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.google.inject.Inject;
import ninja.Result;
import ninja.Results;

import com.google.inject.Singleton;
import com.serphacker.serposcope.db.base.BaseDB;
import static com.serphacker.serposcope.db.base.RunDB.STATUSES_DONE;
import com.serphacker.serposcope.db.google.GoogleDB;
import com.serphacker.serposcope.models.base.Config;
import com.serphacker.serposcope.models.base.Group;
import com.serphacker.serposcope.models.base.Group.Module;
import com.serphacker.serposcope.models.base.Run;
import com.serphacker.serposcope.models.google.GoogleBest;
import com.serphacker.serposcope.models.google.GoogleRank;
import static com.serphacker.serposcope.models.google.GoogleRank.UNRANKED;
import com.serphacker.serposcope.models.google.GoogleSettings;
import com.serphacker.serposcope.models.google.GoogleSearch;
import com.serphacker.serposcope.models.google.GoogleSerp;
import com.serphacker.serposcope.models.google.GoogleSerpEntry;
import com.serphacker.serposcope.models.google.GoogleTarget;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ninja.Context;
import ninja.Router;
import ninja.i18n.Messages;
import ninja.params.Param;
import ninja.params.PathParam;
import org.apache.commons.lang3.StringEscapeUtils;

@Singleton
public class GoogleSearchController extends GoogleController {

    @Inject
    GoogleDB googleDB;

    @Inject
    BaseDB baseDB;

    @Inject
    Router router;

    @Inject
    Messages msg;

    @Inject
    ObjectMapper objectMapper;

    public Result search(Context context, @PathParam("searchId") Integer searchId,
            @Param("startDate") String startDateStr, @Param("endDate") String endDateStr) {
        GoogleSearch search = getSearch(context, searchId);
        Group group = context.getAttribute("group", Group.class);

        if (search == null) {
            context.getFlashScope().error("error.invalidSearch");
            return Results.redirect(
                    router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
        }

        Run minRun = baseDB.run.findFirst(Module.GOOGLE, STATUSES_DONE, null);
        Run maxRun = baseDB.run.findLast(Module.GOOGLE, STATUSES_DONE, null);
        if (maxRun == null || minRun == null) {
            return Results.ok().render("search", search);
        }

        LocalDate minDay = minRun.getDay();
        LocalDate maxDay = maxRun.getDay();

        LocalDate startDate = null;
        if (startDateStr != null) {
            try {
                startDate = LocalDate.parse(startDateStr);
            } catch (Exception ex) {
            }
        }
        LocalDate endDate = null;
        if (endDateStr != null) {
            try {
                endDate = LocalDate.parse(endDateStr);
            } catch (Exception ex) {
            }
        }

        if (startDate == null || endDate == null || endDate.isBefore(startDate)) {
            startDate = maxDay.minusDays(30);
            endDate = maxDay;
        }

        Run firstRun = baseDB.run.findFirst(Module.GOOGLE, STATUSES_DONE, startDate);
        Run lastRun = baseDB.run.findLast(Module.GOOGLE, STATUSES_DONE, endDate);

        if (firstRun == null || lastRun == null || firstRun.getDay().isAfter(lastRun.getDay())) {
            return Results.ok()
                    .render("f_warning", msg.get("error.noDataForThisPeriod", context, Optional.absent()).or(""))
                    .render("startDate", startDate).render("endDate", endDate).render("minDate", minDay)
                    .render("maxDate", maxDay).render("search", search);
        }

        startDate = firstRun.getDay();
        endDate = lastRun.getDay();

        String jsonEvents = null;
        try {
            jsonEvents = objectMapper.writeValueAsString(baseDB.event.list(group, startDate, endDate));
        } catch (JsonProcessingException ex) {
            jsonEvents = "[]";
        }

        GoogleSerp lastSerp = googleDB.serp.get(lastRun.getId(), search.getId());

        List<GoogleTarget> targets = getTargets(context);

        Map<Integer, GoogleBest> bestRankings = new HashMap<>();
        for (GoogleTarget target : targets) {
            GoogleBest best = googleDB.rank.getBest(target.getGroupId(), target.getId(), search.getId());
            if (best != null) {
                bestRankings.put(best.getGoogleTargetId(), best);
            }
        }

        String jsonRanks = getJsonRanks(group, targets, firstRun, lastRun, searchId);
        Config config = baseDB.config.getConfig();

        return Results.ok().render("displayMode", config.getDisplayGoogleSearch()).render("events", jsonEvents)
                .render("targets", targets).render("chart", jsonRanks).render("search", search)
                .render("serp", lastSerp).render("startDate", startDate).render("endDate", endDate)
                .render("minDate", minDay).render("maxDate", maxDay).render("bestRankings", bestRankings);
    }

    protected String getJsonRanks(Group group, List<GoogleTarget> targets, Run firstRun, Run lastRun,
            int searchId) {

        StringBuilder builder = new StringBuilder("{\"targets\":[");
        for (GoogleTarget target : targets) {
            builder.append("{\"id\":").append(target.getId()).append(",\"name\":\"")
                    .append(StringEscapeUtils.escapeJson(target.getName())).append("\"},");
        }
        if (builder.charAt(builder.length() - 1) == ',') {
            builder.setCharAt(builder.length() - 1, ']');
        } else {
            builder.append(']');
        }
        builder.append(",\"ranks\":[");

        final int[] maxRank = new int[1];

        googleDB.serp.stream(firstRun.getId(), lastRun.getId(), searchId, (GoogleSerp serp) -> {

            builder.append('[').append(serp.getRunDay().toEpochSecond(ZoneOffset.UTC) * 1000l).append(',');

            // calendar
            builder.append("null").append(",");

            for (GoogleTarget target : targets) {
                int position = UNRANKED;
                for (int i = 0; i < serp.getEntries().size(); i++) {
                    if (target.match(serp.getEntries().get(i).getUrl())) {
                        position = i + 1;
                        break;
                    }
                }

                builder.append(position == UNRANKED ? "null" : position).append(',');
                if (position != UNRANKED && position > maxRank[0]) {
                    maxRank[0] = position;
                }
            }

            if (builder.charAt(builder.length() - 1) == ',') {
                builder.setCharAt(builder.length() - 1, ']');
            }
            builder.append(',');
        });
        if (builder.charAt(builder.length() - 1) == ',') {
            builder.setCharAt(builder.length() - 1, ']');
        } else {
            builder.append(']');
        }

        builder.append(",\"maxRank\":").append(maxRank[0]);
        builder.append("}");

        return builder.toString();
    }

    public Result urlRanks(Context context, @PathParam("searchId") Integer searchId, @Param("url") String url,
            @Param("startDate") String startDateStr, @Param("endDate") String endDateStr) {
        Group group = (Group) context.getAttribute("group");

        GoogleSearch search = getSearch(context, searchId);
        if (search == null) {
            context.getFlashScope().error("error.invalidSearch");
            return Results.redirect(
                    router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
        }

        LocalDate startDate = null;
        if (startDateStr != null) {
            try {
                startDate = LocalDate.parse(startDateStr);
            } catch (Exception ex) {
            }
        }
        LocalDate endDate = null;
        if (endDateStr != null) {
            try {
                endDate = LocalDate.parse(endDateStr);
            } catch (Exception ex) {
            }
        }

        Run firstRun = baseDB.run.findFirst(Module.GOOGLE, STATUSES_DONE, startDate);
        Run lastRun = baseDB.run.findLast(Module.GOOGLE, STATUSES_DONE, endDate);

        if (url == null || firstRun == null || lastRun == null) {
            return Results.badRequest().text();
        }

        StringBuilder builder = new StringBuilder("{");
        googleDB.serp.stream(firstRun.getId(), lastRun.getId(), search.getId(), (GoogleSerp t) -> {
            int position = 0;
            for (int i = 0; i < t.getEntries().size(); i++) {
                if (t.getEntries().get(i).getUrl().equals(url)) {
                    position = i + 1;
                    break;
                }
            }

            builder.append("\"").append(t.getRunDay().toEpochSecond(ZoneOffset.UTC) * 1000l).append("\":")
                    .append(position).append(",");
        });

        if (builder.charAt(builder.length() - 1) == ',') {
            builder.setCharAt(builder.length() - 1, '}');
        } else {
            builder.append('}');
        }

        return Results.ok().text().render(builder.toString());
    }

    public Result exportSerp(Context context, @PathParam("searchId") Integer searchId,
            @Param("date") String pdate) {
        GoogleSerp serp = null;
        LocalDate date = null;
        try {
            date = LocalDate.parse(pdate);
        } catch (Exception ex) {
        }
        if (date != null) {
            List<Run> runs = baseDB.run.findByDay(Module.GOOGLE, date);
            if (!runs.isEmpty()) {
                GoogleSearch search = getSearch(context, searchId);
                if (search != null) {
                    serp = googleDB.serp.get(runs.get(0).getId(), search.getId());
                }
            }
        }

        if (serp == null) {
            return Results.ok().text().renderRaw("SERP not found");
        }

        boolean exportRank = context.getParameter("rank") != null;
        boolean exportD1 = context.getParameter("d1") != null;
        boolean exportD7 = context.getParameter("d7") != null;
        boolean exportD30 = context.getParameter("d30") != null;
        boolean exportD90 = context.getParameter("d90") != null;

        int position = 0;
        StringBuilder builder = new StringBuilder();
        for (GoogleSerpEntry entry : serp.getEntries()) {
            ++position;
            if (exportRank) {
                builder.append(position).append(",");
            }
            builder.append(StringEscapeUtils.escapeCsv(entry.getUrl())).append(",");
            if (exportD1) {
                Short rank = entry.getMap().getOrDefault((short) 1, (short) GoogleRank.UNRANKED);
                builder.append(rank != GoogleRank.UNRANKED ? rank.intValue() : "").append(",");
            }
            if (exportD7) {
                Short rank = entry.getMap().getOrDefault((short) 7, (short) GoogleRank.UNRANKED);
                builder.append(rank != GoogleRank.UNRANKED ? rank.intValue() : "").append(",");
            }
            if (exportD30) {
                Short rank = entry.getMap().getOrDefault((short) 30, (short) GoogleRank.UNRANKED);
                builder.append(rank != GoogleRank.UNRANKED ? rank.intValue() : "").append(",");
            }
            if (exportD90) {
                Short rank = entry.getMap().getOrDefault((short) 90, (short) GoogleRank.UNRANKED);
                builder.append(rank != GoogleRank.UNRANKED ? rank.intValue() : "").append(",");
            }
            if (builder.length() > 0) {
                builder.setCharAt(builder.length() - 1, '\n');
            }
        }

        return Results.text()
                .addHeader("Content-Disposition",
                        "attachment; filename=\"" + serp.getRunDay().toLocalDate() + ".csv\"")
                .renderRaw(builder.toString());
    }

}