@FilterWith({XSRFFilter.class, AdminFilter.class})
  public Result renameTarget(
      Context context, @Param("name") String name, @Param("id") Integer targetId) {

    FlashScope flash = context.getFlashScope();
    Group group = context.getAttribute("group", Group.class);

    GoogleTarget target = getTarget(context, targetId);
    if (target == null) {
      flash.error("error.invalidWebsite");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    if (name != null) {
      name = name.replaceAll("(^\\s+)|(\\s+$)", "");
    }

    if (Validator.isEmpty(name)) {
      flash.error("error.invalidName");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    target.setName(name);
    googleDB.target.rename(target);

    flash.success("google.group.websiteRenamed");
    return Results.redirect(
        router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
  }
  @FilterWith({XSRFFilter.class, AdminFilter.class})
  public Result delete(Context context) {
    FlashScope flash = context.getFlashScope();
    Group group = context.getAttribute("group", Group.class);

    // TODO FIX ME locking until database modification done
    if (taskManager.isGoogleRunning()) {
      flash.error("admin.google.errorTaskRunning");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    List<GoogleTarget> targets = googleDB.target.list(Arrays.asList(group.getId()));
    for (GoogleTarget target : targets) {
      googleDB.targetSummary.deleteByTarget(target.getId());
      googleDB.rank.deleteByTarget(group.getId(), target.getId());
      googleDB.target.delete(target.getId());
    }

    List<GoogleSearch> searches = googleDB.search.listByGroup(Arrays.asList(group.getId()));
    for (GoogleSearch search : searches) {
      deleteSearch(group, search);
    }

    baseDB.event.delete(group);
    baseDB.user.delPerm(group);
    if (!baseDB.group.delete(group)) {
      flash.error("admin.google.failedDeleteGroup");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    } else {
      flash.success("admin.google.groupDeleted");
      return Results.redirect(router.getReverseRoute(GroupController.class, "groups"));
    }
  }
Ejemplo n.º 3
0
  @FilterWith(SecureFilter.class)
  public Result postArticleXml(@LoggedInUser String username, ArticleDto articleDto) {

    boolean succeeded = articleDao.postArticle(username, articleDto);

    if (!succeeded) {
      return Results.notFound();
    } else {
      return Results.xml();
    }
  }
  @FilterWith({XSRFFilter.class, AdminFilter.class})
  public Result exportSearches(Context context, @Params("id[]") String[] ids) {
    FlashScope flash = context.getFlashScope();
    Group group = context.getAttribute("group", Group.class);

    if (ids == null || ids.length == 0) {
      flash.error("error.noSearchSelected");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    List<GoogleSearch> searches = new ArrayList<>();
    for (String id : ids) {
      GoogleSearch search = null;
      try {
        search = getSearch(context, Integer.parseInt(id));
      } catch (Exception ex) {
        search = null;
      }

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

      searches.add(search);
    }

    StringBuilder builder = new StringBuilder();
    for (GoogleSearch search : searches) {
      builder.append(StringEscapeUtils.escapeCsv(search.getKeyword())).append(",");
      builder.append(search.getTld() != null ? search.getTld() : "com").append(",");
      builder.append(search.getDatacenter() != null ? search.getDatacenter() : "").append(",");
      builder
          .append(
              search.getDevice() != null
                  ? (search.getDevice() == GoogleDevice.DESKTOP ? "desktop" : "mobile")
                  : "")
          .append(",");
      builder
          .append(StringEscapeUtils.escapeCsv(search.getLocal() != null ? search.getLocal() : ""))
          .append(",");
      builder
          .append(
              StringEscapeUtils.escapeCsv(
                  search.getCustomParameters() != null ? search.getCustomParameters() : ""))
          .append("\n");
    }

    return Results.ok().text().render(builder.toString());
  }
  @Override
  public Result filter(final FilterChain filterChain, final Context context) {
    boolean blocked = false;

    UserDetail userDetail = SecurityUtil.getCurrentUser(context);

    if (userDetail == null) {
      blocked = true;
    }

    if (!blocked
        && null != context.getRoute().getControllerClass().getAnnotation(PermissionPolicy.class)) {
      blocked = filterWithClassAnnotation(context, userDetail);
    }

    if (!blocked
        && null != context.getRoute().getControllerMethod().getAnnotation(PermissionPolicy.class)) {
      blocked = filterWithMethodAnnotation(context, userDetail);
    }

    if (blocked) {
      return Results.forbidden();
    }
    return filterChain.next(context);
  }
 @FilterWith(XSRFFilter.class)
 public Result reset(Context context) {
   GoogleSettings options = new GoogleSettings();
   googleDB.options.update(options);
   context.getFlashScope().success("label.settingsUpdated");
   return Results.redirect(router.getReverseRoute(GoogleSettingsController.class, "settings"));
 }
Ejemplo n.º 7
0
  public Result debug(Context context) {

    return Results.ok()
    //            .render("f_warning",msg.get("test.translate", context,
    // Optional.absent(),12l).or(""))
    ;
  }
Ejemplo n.º 8
0
  public Result test(@Param("query") String query) throws SQLException {
    long _start = System.currentTimeMillis();

    HikariDataSource hds = null;
    if (ds instanceof HikariDataSource) {
      hds = (HikariDataSource) ds;
    } else {
      hds = ((P6DataSource) ds).unwrap(HikariDataSource.class);
    }

    if (query != null) {
      //            try(Connection con = DriverManager.getConnection(hds.getJdbcUrl()); Statement
      // stmt = con.createStatement() ){
      try (Connection con = ds.getConnection();
          Statement stmt = con.createStatement()) {
        stmt.execute(query);
      }
    }

    String duration = DurationFormatUtils.formatDurationHMS(System.currentTimeMillis() - _start);

    LOG.info(duration);

    return Results.ok().text().render(duration);
  }
Ejemplo n.º 9
0
 @Get
 @Route("/project/{id}/docs")
 public Result index(@PathParam("id") Integer projectId) {
   Project project = this.checkEntity(projectRepository.findById(projectId));
   List<Doc> docs = docRepository.findByProject(projectId);
   return Results.html().render("docs", docs).render("project", project);
 }
  public Result view(Context context) {

    Group group = context.getAttribute("group", Group.class);

    Map<Integer, GoogleTargetSummary> summaryByTagetId = new HashMap<>();
    Map<Integer, List<Integer>> scoreHistoryByTagetId = new HashMap<>();

    Run lastRun = baseDB.run.findLast(group.getModule(), RunDB.STATUSES_DONE, null);
    if (lastRun != null) {
      List<GoogleTargetSummary> summaries = googleDB.targetSummary.list(lastRun.getId());
      for (GoogleTargetSummary summary : summaries) {
        if (summary != null) {
          summaryByTagetId.put(summary.getTargetId(), summary);
          List<Integer> scoreHistory =
              googleDB.targetSummary.listScoreHistory(group.getId(), summary.getTargetId(), 30);
          int missingScore = 30 - scoreHistory.size();
          for (int i = 0; i < missingScore; i++) {
            scoreHistory.add(0, 0);
          }
          scoreHistoryByTagetId.put(summary.getTargetId(), scoreHistory);
        }
      }
    }

    return Results.ok()
        .render("events", baseDB.event.list(group, null, null))
        .render("default", googleDB.options.get())
        .render("searchesSize", context.getAttribute("searches", List.class).size())
        .render("targets", context.getAttribute("targets"))
        .render("summaries", summaryByTagetId)
        .render("histories", scoreHistoryByTagetId);
  }
  public Result jsonSearchSuggest(Context context, @Param("query") String query) {

    StringBuilder builder = new StringBuilder("[");
    getSearches(context)
        .stream()
        .filter((g) -> query == null ? true : g.getKeyword().contains(query))
        .sorted((o1, o2) -> o1.getId() - o2.getId())
        .limit(10)
        .forEach(
            (g) -> {
              builder
                  .append("{")
                  .append("\"id\":")
                  .append(g.getId())
                  .append(",")
                  .append("\"name\":\"")
                  .append(StringEscapeUtils.escapeJson(g.getKeyword()))
                  .append("\"")
                  .append("},");
            });
    if (builder.length() > 1) {
      builder.deleteCharAt(builder.length() - 1);
    }
    builder.append("]");

    return Results.json().renderRaw(builder.toString());
  }
Ejemplo n.º 12
0
 @Get
 @Route("/project/{id}/docs/{docId}/edit")
 public Result edit(@PathParam("id") Integer projectId, @PathParam("docId") Integer docId) {
   Project project = this.checkEntity(projectRepository.findById(projectId));
   Doc doc = this.checkEntity(docRepository.findById(docId));
   return Results.html().render("project", project).render("doc", doc);
 }
Ejemplo n.º 13
0
  @FilterWith(XSRFFilter.class)
  public Result generate(
      Context context,
      @Param("groups") Integer groups,
      @Param("searchPerGroup") Integer searchPerGroup,
      @Param("targetPerGroup") Integer targetPerGroup) {
    FlashScope flash = context.getFlashScope();

    if (groups == null
        || groups < 1
        || searchPerGroup == null
        || searchPerGroup < 1
        || targetPerGroup == null
        || targetPerGroup < 1) {
      flash.put("error", "error.invalidParameters");
      return Results.redirect(router.getReverseRoute(DebugController.class, "debug"));
    }

    for (int i = 0; i < groups; i++) {
      Group group = new Group(Group.Module.GOOGLE, "group#" + i);
      baseDB.group.insert(group);

      List<GoogleSearch> searches = new ArrayList<>();
      for (int j = 0; j < searchPerGroup; j++) {
        GoogleSearch search = new GoogleSearch("search#" + j + "#" + group.getName());
        search.setTld("com");
        searches.add(search);
      }
      googleDB.search.insert(searches, group.getId());

      List<GoogleTarget> targets = new ArrayList<>();
      for (int j = 0; j < targetPerGroup; j++) {
        int targetFakeId = j + 1;
        GoogleTarget target =
            new GoogleTarget(
                group.getId(),
                "target#" + targetFakeId + "#" + group.getName(),
                PatternType.REGEX,
                "^https?://www.site" + targetFakeId + ".com.+");
        targets.add(target);
      }
      googleDB.target.insert(targets);
    }

    flash.put("warning", "admin.debug.generated");
    return Results.redirect(router.getReverseRoute(DebugController.class, "debug"));
  }
  @FilterWith({XSRFFilter.class, AdminFilter.class})
  public Result delSearch(Context context, @Params("id[]") String[] ids) {

    FlashScope flash = context.getFlashScope();
    Group group = context.getAttribute("group", Group.class);

    if (ids == null || ids.length == 0) {
      flash.error("error.noSearchSelected");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    List<GoogleSearch> searches = new ArrayList<>();
    for (String id : ids) {
      GoogleSearch search = null;
      try {
        search = getSearch(context, Integer.parseInt(id));
      } catch (Exception ex) {
        search = null;
      }

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

      searches.add(search);
    }

    // TODO FIX ME locking until database modification done
    if (taskManager.isGoogleRunning()) {
      flash.error("admin.google.errorTaskRunning");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    for (GoogleSearch search : searches) {
      deleteSearch(group, search);
    }

    return Results.redirect(
        router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId())
            + "#tab-searches");
  }
  @FilterWith({XSRFFilter.class, AdminFilter.class})
  public Result rename(Context context, @Param("name") String name) {
    FlashScope flash = context.getFlashScope();
    Group group = context.getAttribute("group", Group.class);

    if (Validator.isEmpty(name)) {
      flash.error("error.invalidName");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    group.setName(name);
    baseDB.group.update(group);

    flash.success("google.group.groupRenamed");
    return Results.redirect(
        router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
  }
  public Result ranSuccessfully() {

    RanSuccessfullyList rsf = new RanSuccessfullyList();
    // This is a sample. You can copy and modify it for your needs.
    rsf.addPerson(new Person("Michael Hilton", "MichaelHilton", "Mac"));
    rsf.addPerson(new Person("Taylor Kirkpatrick", "kirkpatt", "Windows"));
    rsf.addPerson(new Person("Nathan Healea", "NathaHealea", "Mac"));

    return Results.json().render(rsf);
  }
Ejemplo n.º 17
0
    @Override
    public Result filter(FilterChain filterChain, Context context) {

      if (props.isProd()) {
        context.getFlashScope().error("error.unauthorizedAccess");
        return Results.redirect(router.getReverseRoute(AuthController.class, "login"));
      }

      return filterChain.next(context);
    }
Ejemplo n.º 18
0
  @FilterWith(XSRFFilter.class)
  public Result wipeRankings(Context context) {
    FlashScope flash = context.getFlashScope();

    googleDB.targetSummary.wipe();
    googleDB.rank.wipe();
    googleDB.serp.wipe();
    baseDB.run.wipe();

    flash.put("warning", "admin.debug.rankingsWiped");
    return Results.redirect(router.getReverseRoute(DebugController.class, "debug"));
  }
  @FilterWith({XSRFFilter.class, AdminFilter.class})
  public Result delTarget(Context context, @Params("id[]") String[] ids) {
    FlashScope flash = context.getFlashScope();
    Group group = context.getAttribute("group", Group.class);

    // TODO FIX ME locking until database modification done
    if (taskManager.isGoogleRunning()) {
      flash.error("admin.google.errorTaskRunning");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    if (ids == null || ids.length == 0) {
      flash.error("error.noWebsiteSelected");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    for (String id : ids) {
      GoogleTarget target = null;
      try {
        target = getTarget(context, Integer.parseInt(id));
      } catch (Exception ex) {
        target = null;
      }

      if (target == null) {
        flash.error("error.invalidWebsite");
        return Results.redirect(
            router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
      }

      googleDB.targetSummary.deleteByTarget(target.getId());
      googleDB.rank.deleteByTarget(group.getId(), target.getId());
      googleDB.target.delete(target.getId());
    }

    return Results.redirect(
        router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
  }
  @FilterWith({XSRFFilter.class, AdminFilter.class})
  public Result delEvent(Context context, @Param("day") String day) {
    FlashScope flash = context.getFlashScope();
    Group group = context.getAttribute("group", Group.class);

    Event event = new Event();
    event.setGroupId(group.getId());
    try {
      event.setDay(LocalDate.parse(day));
    } catch (Exception ex) {
    }
    if (event.getDay() == null) {
      flash.error("error.invalidDate");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    baseDB.event.delete(event);
    flash.success("google.group.eventDeleted");
    return Results.redirect(
        router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
  }
  /**
   * Processes submit of the restore password form.
   *
   * @param context Context.
   * @param restoreToken Restore token.
   * @param password Password.
   * @param confirmPassword Password confirmation.
   * @return Result.
   */
  @Transactional
  public Result restorePassword(
      Context context,
      @Param(value = "restoreToken") String restoreToken,
      @Param(value = "password") String password,
      @Param(value = "confirmPassword") String confirmPassword) {
    password = Strings.nullToEmpty(password);
    confirmPassword = Strings.nullToEmpty(confirmPassword);

    Result result = createResult(context, restoreToken);
    try {
      ExpirableToken token = expirableTokenEncryptor.decrypt(restoreToken);
      Long userId = token.getAttributeAsLong("userId");
      User user = userService.get(userId);
      if (user == null) {
        throw new ExpiredTokenException();
      }
      if (isValidPassword(password, confirmPassword)) {
        String ip = (String) context.getAttribute(IpAddressFilter.REMOTE_IP);
        byte[] oldSalt = user.getPasswordSalt();
        byte[] oldHash = user.getPasswordHash();
        userService.updatePasswordAndConfirm(user, password);
        userEventService.onUserPasswordUpdate(user, oldSalt, oldHash, ip, context.getHeaders());
        return Results.redirect(
            urlBuilderProvider.get().getSignInUrl(SignInState.PASSWORD_CHANGED));
      } else {
        result.render("restorePasswordError", "password");
      }
      result.render("user", user);
    } catch (ExpiredTokenException ex) {
      result.render("restorePasswordError", "expired");
    } catch (IllegalTokenException | IllegalFormatException ex) {
      result.render("restorePasswordError", "unknown");
    }
    return result;
  }
 public Result settings() {
   return Results.ok().render("options", googleDB.options.get());
 }
  @FilterWith({XSRFFilter.class, AdminFilter.class})
  public Result addTarget(
      Context context,
      @Param("target-radio") String targetType,
      @Params("name[]") String[] names,
      @Params("pattern[]") String[] patterns) {
    FlashScope flash = context.getFlashScope();
    Group group = context.getAttribute("group", Group.class);

    if (targetType == null
        || names == null
        || names.length == 0
        || patterns == null
        || patterns.length == 0
        || names.length != patterns.length) {
      flash.error("error.invalidParameters");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    Set<GoogleTarget> targets = new HashSet<>();
    for (int i = 0; i < names.length; i++) {
      String name = names[i];
      String pattern = patterns[i];

      if (name != null) {
        name = name.replaceAll("(^\\s+)|(\\s+$)", "");
      }

      if (pattern != null) {
        pattern = pattern.replaceAll("(^\\s+)|(\\s+$)", "");
      }

      if (Validator.isEmpty(name)) {
        flash.error("error.invalidName");
        return Results.redirect(
            router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
      }

      PatternType type = null;
      try {
        type = PatternType.valueOf(targetType);
      } catch (Exception ex) {
        flash.error("error.invalidTargetType");
        return Results.redirect(
            router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
      }

      if (PatternType.DOMAIN.equals(type) || PatternType.SUBDOMAIN.equals(type)) {
        try {
          pattern = IDN.toASCII(pattern);
        } catch (Exception ex) {
          pattern = null;
        }
      }

      if (!GoogleTarget.isValidPattern(type, pattern)) {
        flash.error("error.invalidPattern");
        return Results.redirect(
            router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
      }

      targets.add(new GoogleTarget(group.getId(), name, type, pattern));
    }

    if (googleDB.target.insert(targets) < 1) {
      flash.error("error.internalError");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }
    googleDB.serpRescan.rescan(null, targets, getSearches(context), true);

    Run runningGoogleTask = taskManager.getRunningGoogleTask();
    if (runningGoogleTask != null) {
      flash.put(
          "warning",
          msg.get(
                  "google.group.websiteInsertedWhileRun",
                  context,
                  Optional.absent(),
                  runningGoogleTask.getId())
              .or(""));
    } else {
      flash.success("google.group.websiteInserted");
    }

    return Results.redirect(
        router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
  }
  @FilterWith(XSRFFilter.class)
  public Result update(
      Context context,
      @Param("targetDisplayMode") String targetDisplayMode,
      @Param("searchDisplayMode") String searchDispayMode,
      @Param("pages") Integer pages,
      @Param("result-per-page") Integer resultPerPage,
      @Param("min-pause") Integer minPause,
      @Param("max-pause") Integer maxPause,
      @Param("maxThreads") Integer maxThreads,
      @Param("fetchRetry") Integer fetchRetry,
      @Param("tld") String tld,
      @Param("datacenter") String datacenter,
      @Param("device") Integer device,
      @Param("local") String local,
      @Param("custom") String custom) {
    FlashScope flash = context.getFlashScope();

    GoogleSettings defaultOptions = new GoogleSettings();
    GoogleSettings options = googleDB.options.get();

    if (pages != null && resultPerPage != null) {
      if (pages * resultPerPage > 1000 || pages * resultPerPage < 1) {
        flash.error("admin.google.invalidPages");
        return Results.redirect(router.getReverseRoute(GoogleSettingsController.class, "settings"));
      }
      options.setPages(pages);
      options.setResultPerPage(resultPerPage);
    }

    if (minPause != null && maxPause != null) {
      if (minPause > maxPause) {
        flash.error("admin.google.invalidPauseRange");
        return Results.redirect(router.getReverseRoute(GoogleSettingsController.class, "settings"));
      }
      options.setMinPauseBetweenPageSec(minPause);
      options.setMaxPauseBetweenPageSec(maxPause);
    }

    if (fetchRetry != null) {
      options.setFetchRetry(fetchRetry);
    }

    if (maxThreads != null) {
      options.setMaxThreads(maxThreads);
    }

    if (!Validator.isEmpty(tld)) {
      if (!Validator.isGoogleTLD(tld)) {
        flash.error("admin.google.invalidTLD");
        return Results.redirect(router.getReverseRoute(GoogleSettingsController.class, "settings"));
      }
      options.setDefaultTld(tld);
    } else {
      options.setDefaultTld(defaultOptions.getDefaultTld());
    }

    if (!Validator.isEmpty(datacenter)) {
      if (!Validator.isIPv4(datacenter)) {
        flash.error("error.invalidIP");
        return Results.redirect(router.getReverseRoute(GoogleSettingsController.class, "settings"));
      }
      options.setDefaultDatacenter(datacenter);
    } else {
      options.setDefaultDatacenter(defaultOptions.getDefaultDatacenter());
    }

    if (device != null && device == 1) {
      options.setDefaultDevice(GoogleDevice.SMARTPHONE);
    } else {
      options.setDefaultDevice(GoogleDevice.DESKTOP);
    }

    if (Validator.isNotEmpty(local)) {
      options.setDefaultLocal(local);
    } else {
      options.setDefaultLocal(defaultOptions.getDefaultLocal());
    }

    if (Validator.isNotEmpty(custom)) {
      options.setDefaultCustomParameters(custom);
    } else {
      options.setDefaultCustomParameters(defaultOptions.getDefaultCustomParameters());
    }

    googleDB.options.update(options);

    flash.success("label.settingsUpdated");
    return Results.redirect(router.getReverseRoute(GoogleSettingsController.class, "settings"));
  }
Ejemplo n.º 25
0
  public Result getArticlesXml() {

    ArticlesDto articlesDto = articleDao.getAllArticles();

    return Results.xml().render(articlesDto);
  }
Ejemplo n.º 26
0
 @Get
 @Route("/project/{id}/docs/new")
 public Result add(@PathParam("id") Integer projectId) {
   Project project = this.checkEntity(projectRepository.findById(projectId));
   return Results.html().render("project", project);
 }
Ejemplo n.º 27
0
  @Override
  public Result filter(FilterChain chain, Context context) {

    return Results.html().status(418).template("/views/TeaPotFilter/TeaPot.ftl.html");
  }
  public Result jsonSearches(Context context) {
    List<GoogleSearch> searches = context.getAttribute("searches", List.class);
    if (searches.isEmpty()) {
      return Results.json().renderRaw("[]");
    }

    return Results.ok()
        .json()
        .render(
            (Context context0, Result result) -> {
              PrintWriter writer = null;
              OutputStream os = null;
              try {

                String acceptEncoding = context0.getHeader("Accept-Encoding");
                if (acceptEncoding != null && acceptEncoding.contains("gzip")) {
                  result.addHeader("Content-Encoding", "gzip");
                }

                ResponseStreams response = context0.finalizeHeaders(result);
                os = response.getOutputStream();
                if (acceptEncoding != null && acceptEncoding.contains("gzip")) {
                  os = new GZIPOutputStream(os);
                }

                writer = new PrintWriter(os);
                writer.append("[");
                for (int i = 0; i < searches.size(); i++) {
                  GoogleSearch search = searches.get(i);
                  writer.append("{");
                  writer.append("\"id\":").append(Integer.toString(search.getId())).append(",");
                  writer
                      .append("\"keyword\":\"")
                      .append(StringEscapeUtils.escapeJson(search.getKeyword()))
                      .append("\",");
                  writer
                      .append("\"tld\":\"")
                      .append(
                          search.getTld() == null
                              ? ""
                              : StringEscapeUtils.escapeJson(search.getTld()))
                      .append("\",");
                  writer
                      .append("\"device\":\"")
                      .append(SMARTPHONE.equals(search.getDevice()) ? 'M' : 'D')
                      .append("\",");
                  writer
                      .append("\"local\":\"")
                      .append(
                          search.getLocal() == null
                              ? ""
                              : StringEscapeUtils.escapeJson(search.getLocal()))
                      .append("\",");
                  writer
                      .append("\"datacenter\":\"")
                      .append(
                          search.getDatacenter() == null
                              ? ""
                              : StringEscapeUtils.escapeJson(search.getDatacenter()))
                      .append("\",");
                  writer
                      .append("\"custom\":\"")
                      .append(
                          search.getCustomParameters() == null
                              ? ""
                              : StringEscapeUtils.escapeJson(search.getCustomParameters()))
                      .append("\"");
                  writer.append("}");
                  if (i != searches.size() - 1) {
                    writer.append(",");
                  }
                }
                writer.append("]");

              } catch (Exception ex) {
                LOG.warn("HTTP error", ex);
              } finally {
                if (os != null) {
                  try {
                    writer.close();
                    os.close();
                  } catch (Exception ex) {
                  }
                }
              }
            });
  }
  @FilterWith({XSRFFilter.class, AdminFilter.class})
  public Result addSearch(
      Context context,
      @Params("keyword[]") String[] keywords,
      @Params("tld[]") String tlds[],
      @Params("datacenter[]") String[] datacenters,
      @Params("device[]") Integer[] devices,
      @Params("local[]") String[] locals,
      @Params("custom[]") String[] customs) {
    FlashScope flash = context.getFlashScope();
    Group group = context.getAttribute("group", Group.class);

    if (keywords == null
        || tlds == null
        || datacenters == null
        || devices == null
        || locals == null
        || customs == null
        || keywords.length != tlds.length
        || keywords.length != datacenters.length
        || keywords.length != devices.length
        || keywords.length != locals.length
        || keywords.length != customs.length) {
      flash.error("error.invalidParameters");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    Set<GoogleSearch> searches = new HashSet<>();

    for (int i = 0; i < keywords.length; i++) {
      GoogleSearch search = new GoogleSearch();

      if (keywords[i].isEmpty()) {
        flash.error("admin.google.keywordEmpty");
        return Results.redirect(
            router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
      }
      search.setKeyword(keywords[i]);

      if (!Validator.isGoogleTLD(tlds[i])) {
        flash.error("admin.google.invalidTLD");
        return Results.redirect(
            router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
      }
      search.setTld(tlds[i]);

      if (!datacenters[i].isEmpty()) {
        if (!Validator.isIPv4(datacenters[i])) {
          flash.error("error.invalidIP");
          return Results.redirect(
              router.getReverseRoute(
                  GoogleGroupController.class, "view", "groupId", group.getId()));
        }
        search.setDatacenter(datacenters[i]);
      }

      if (devices[i] != null && devices[i] >= 0 && devices[i] < GoogleDevice.values().length) {
        search.setDevice(GoogleDevice.values()[devices[i]]);
      } else {
        search.setDevice(GoogleDevice.DESKTOP);
      }

      if (!Validator.isEmpty(locals[i])) {
        search.setLocal(locals[i]);
      }

      if (!Validator.isEmpty(customs[i])) {
        search.setCustomParameters(customs[i]);
      }

      searches.add(search);
    }

    List<GoogleSearch> knownSearches = new ArrayList<>();
    synchronized (searchLock) {
      for (GoogleSearch search : searches) {
        int id = googleDB.search.getId(search);
        if (id > 0) {
          search.setId(id);
          knownSearches.add(search);
        }
      }
      googleDB.search.insert(searches, group.getId());
    }

    googleDB.serpRescan.rescan(null, getTargets(context), knownSearches, false);

    flash.success("google.group.searchInserted");
    return Results.redirect(
        router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId())
            + "#tab-searches");
  }
  @FilterWith({XSRFFilter.class, AdminFilter.class})
  public Result addEvent(
      Context context,
      @Param("day") String day,
      @Param("title") String title,
      @Param("description") String description,
      @Param("redir-search") Integer redirSearchId,
      @Param("redir-target") Integer redirTargetId) {
    FlashScope flash = context.getFlashScope();
    Group group = context.getAttribute("group", Group.class);

    Event event = new Event();
    event.setGroupId(group.getId());
    try {
      event.setDay(LocalDate.parse(day));
    } catch (Exception ex) {
    }

    if (event.getDay() == null) {
      flash.error("error.invalidDate");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    if (Validator.isEmpty(title)) {
      flash.error("error.invalidTitle");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    if (baseDB.event.find(group, event.getDay()) != null) {
      flash.error("google.group.alreadyEventForThisDate");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    event.setTitle(title);
    event.setDescription(Jsoup.clean(description == null ? "" : description, Whitelist.basic()));

    if (!baseDB.event.insert(event)) {
      flash.error("error.internalError");
      return Results.redirect(
          router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
    }

    flash.success("google.group.eventInserted");
    if (redirSearchId != null) {
      return Results.redirect(
          router.getReverseRoute(
              GoogleSearchController.class,
              "search",
              "groupId",
              group.getId(),
              "searchId",
              redirSearchId));
    }
    if (redirTargetId != null) {
      return Results.redirect(
          router.getReverseRoute(
              GoogleTargetController.class,
              "target",
              "groupId",
              group.getId(),
              "targetId",
              redirTargetId));
    }

    return Results.redirect(
        router.getReverseRoute(GoogleGroupController.class, "view", "groupId", group.getId()));
  }