view src/nabble/view/web/tools/SpamSearch.java @ 47:72765b66e2c3

remove mailing list code
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 18 Jun 2021 17:44:24 -0600
parents 7ecd1a4ef557
children
line wrap: on
line source


package nabble.view.web.tools;

import com.google.gson.Gson;
import nabble.model.ModelHome;
import nabble.model.Node;
import nabble.model.Site;
import nabble.view.lib.Jtp;
import nabble.view.lib.Shared;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public final class SpamSearch extends HttpServlet {

	private static final String GOOGLE_URL = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&key=AIzaSyCjUKhbJVpU83CiRPJ1WV1x7WyszYSntC0&q=";
    private static final String CHARSET = "UTF-8";

	private static final Pattern POST_PTN = Pattern.compile("/.*-t(d\\d+)|((p\\d+)(p\\d+)?)\\.html$");

	/**
	 * Defines five blocks per page because google usually returns a block with four results.
	 * So it shows 20 results per page.
	*/
	private static final int BLOCKS_PER_PAGE = 6;

	static String extractDomain(String url) {
		int posDoubleSlash = url.indexOf("://");
		if (posDoubleSlash == -1)
			return null;
		int posNextSlash = url.indexOf('/', posDoubleSlash+3);
		return url.substring(posDoubleSlash+3, posNextSlash);
	}

	private static Long getPostId(String url) {
		Matcher m = POST_PTN.matcher(url);
		if (m.find()) {
			if (m.group(4) != null)
				return Long.valueOf(m.group(4).substring(1));
			else if (m.group(3) != null)
				return Long.valueOf(m.group(3).substring(1));
			else if (m.group(1) != null)
				return Long.valueOf(m.group(1).substring(1));
		}
		return null;
	}

	private static Long getSiteId(String domain) {
		if (domain.endsWith(Jtp.getDefaultHost())) {
			domain = domain.replace('.'+Jtp.getDefaultHost(), "");
			int dot = domain.lastIndexOf('.');
			return Long.valueOf(domain.substring(dot+1));
		}
		return null;
	}

	public void printResult(GoogleResults results, int j, PrintWriter out) {
		if (results.getResponseData() != null) {
			GoogleResults.Result result = results.getResponseData().getResults().get(j);
			String url = result.getUrl();
			String title = result.getTitle();
			String content = result.getContent();

			Long siteId = null;
			Long postId = getPostId(url);
			if (postId != null) {
				String domain = extractDomain(url);
				if (domain != null) {
					siteId = getSiteId(domain);
					siteId = siteId == null? ModelHome.getSiteIdFromDomain(domain) : siteId;
				}
			}
			Site site = siteId == null? null : ModelHome.getSite(siteId);
			Node node = site == null? null : site.getNode(postId);
			
		out.print( "\r\n" );
 if (node != null && !node.getMessage().isDeleted()) { 
		out.print( "\r\n	<tr>\r\n		<td><input type=\"checkbox\" class=\"checkBox\" value=\"" );
		out.print( (siteId) );
		out.print( "|" );
		out.print( (postId) );
		out.print( "\" name=\"results\"/></td>\r\n		<td>\r\n			<a href=\"" );
		out.print( (url) );
		out.print( "\">" );
		out.print( (title) );
		out.print( "</a><br/>\r\n			<div class=\"clickable\">\r\n				<span class='url'>" );
		out.print( (url) );
		out.print( "</span><br/>\r\n				" );
		out.print( (content) );
		out.print( "<br/>\r\n				" );
 if (node.getDescendantCount() > 1) { 
		out.print( "\r\n					<span class=\"badge\" style=\"font-weight:bold;background:red;color:white\">Has Replies</span>\r\n				" );
 } 
		out.print( "\r\n			</div>\r\n		</td>\r\n	</tr>\r\n" );
 } else { 
		out.print( "\r\n	<tr>\r\n		<td></td>\r\n		<td class=\"grayP\">\r\n			<a href='" );
		out.print( (url) );
		out.print( "'>" );
		out.print( (title) );
		out.print( "</a><br/>\r\n			<span class='url'>" );
		out.print( (url) );
		out.print( "</span><br/>\r\n			" );
		out.print( (content) );
		out.print( "\r\n		</td>\r\n	</tr>\r\n" );
 } 
		out.print( "\r\n" );

		}
	}

	public void getResults(String query, String site,HttpServletRequest request,PrintWriter out)
		throws IOException
	{
		int start = 0;
		int page = 0;

		if(request.getParameter("start") != null)
			start = Integer.parseInt(request.getParameter("start"));

		if(request.getParameter("page") != null)
			page = Integer.parseInt(request.getParameter("page"));

		if(!"".equals(query)) {
			
		out.print( "\r\n<div>Page " );
		out.print( (page) );
		out.print( "</div>\r\n<table>\r\n" );

			for (int k = 0; k < BLOCKS_PER_PAGE; k++) {
				URL url = new URL(GOOGLE_URL+ URLEncoder.encode("site:"+site+" "+query, CHARSET)+"&start="+start );
				Reader reader = new InputStreamReader(url.openStream(), CHARSET);
				GoogleResults results = new Gson().fromJson(reader, GoogleResults.class);
				if (results.getResponseData() != null) {
					int block_size = results.getResponseData().getResults().size();
					start += block_size;
					for (int j = 0; j < block_size; j++) {
							printResult(results,j,out);
					}
				}
			}
			
		out.print( "\r\n</table>\r\n<br />\r\nPage " );
		out.print( (page) );
		out.print( " &ndash;\r\n<a href='?start=" );
		out.print( (start) );
		out.print( "&site=" );
		out.print( (site) );
		out.print( "&query=" );
		out.print( (query) );
		out.print( "&page=" );
		out.print( ((page+1)) );
		out.print( "'>Next</a>\r\n<br />\r\n<br />\r\n<input type=\"submit\" value=\"Delete Selected Posts\" />\r\n" );

		}
	}


	protected void service(HttpServletRequest request,HttpServletResponse response)
		throws IOException
	{
		String query = request.getParameter("query");
		query = query == null? "" : query;

		String site = request.getParameter("site");
		site = site == null? Jtp.getDefaultHost() : site;

		boolean isDelete = "POST".equals(request.getMethod()) && "delete".equals(request.getParameter("action"));
		int deleteCounter = 0;
		if (isDelete) {
			String[] results = request.getParameterValues("results");
			for (String r : results) {
				String[] parts = r.split("\\|");
				long siteId = Long.valueOf(parts[0]);
				long nodeId = Long.valueOf(parts[1]);
				Node n = ModelHome.getSite(siteId).getNode(nodeId);
				if (n != null) {
					n.deleteMessageOrNode();
					deleteCounter++;
				}
			}
		}

		PrintWriter out = response.getWriter();
		
		out.print( "\r\n<html>\r\n	<head>\r\n		<title>Nabble Search</title>\r\n		" );
 Shared.loadJavascript(request, out); 
		out.print( "\r\n		" );
 javascript(out); 
		out.print( "\r\n		" );
 css(out); 
		out.print( "\r\n	</head>\r\n	<body>\r\n		<h1>Nabble Search</h1>\r\n		<form action=\"SpamSearch.jtp\" method=\"get\">\r\n			Search for <input type=\"text\" name=\"query\" value=\"" );
		out.print( (query) );
		out.print( "\" /> in <input type=\"text\" name=\"site\" value=\"" );
		out.print( (site) );
		out.print( "\" />\r\n			<input type=\"submit\" value=\"Search\" />\r\n			<input type=\"hidden\" value=\"0\" name=\"start\" />\r\n			<input type=\"hidden\" value=\"1\" name=\"page\" />\r\n		</form>\r\n		" );
 if (isDelete) { 
		out.print( "\r\n		<div style=\"color:red;padding:.5em 0\">Deleted " );
		out.print( (deleteCounter) );
		out.print( " nodes.</div>\r\n		" );
 } 
		out.print( "\r\n		<div id='results'>\r\n			<form action=\"SpamSearch.jtp\" method=\"post\">\r\n				<input type=\"hidden\" value=\"delete\" name=\"action\" />\r\n				<input type=\"hidden\" name=\"query\" value=\"" );
		out.print( (query) );
		out.print( "\"/>\r\n				<input type=\"hidden\" name=\"site\" value=\"" );
		out.print( (site) );
		out.print( "\" />\r\n				" );
 getResults(query,site,request,out); 
		out.print( "\r\n			</form>\r\n		</div>\r\n	</body>\r\n</html>\r\n" );

	}

	private void javascript(PrintWriter out) {
		
		out.print( "\r\n	<script type=\"text/javascript\">\r\n		$(document).ready(function() {\r\n			$('div.clickable').each(function() {\r\n				var $this = $(this);\r\n				var $checkbox = $this.parent().prev().children().eq(0);\r\n				$this.click(function() {\r\n					var checked = $checkbox.attr('checked');\r\n					if (checked) {\r\n						$this.removeClass('selected-row');\r\n						$checkbox.removeAttr('checked');\r\n					} else {\r\n						$this.addClass('selected-row');\r\n						$checkbox.attr('checked', true);\r\n					}\r\n				});\r\n			});\r\n		});\r\n	</script>\r\n" );

	}
	private void css(PrintWriter out) {
		
		out.print( "\r\n<style type=\"text/css\">\r\n	body {\r\n		padding: 1em;\r\n		font-family: Verdana, Sans-serif;\r\n		font-size:.84em;\r\n	}\r\n	span.url{\r\n		color: green;\r\n	}\r\n	#results table {\r\n		width: 100%;\r\n	}\r\n	#results table td {\r\n		vertical-align:top;\r\n		padding-bottom: 1em;\r\n	}\r\n	#results td.grayP , td.grayP a , td.grayP span {\r\n		color: #C8C8C8 !important;\r\n	}\r\n	form input {\r\n		margin-bottom: 15px;\r\n	}\r\n	span.badge {\r\n		font-size:90%;\r\n		-moz-border-radius: 5px;\r\n		-webkit-border-radius: 5px;\r\n		border-radius: 5px;\r\n		padding: .2em .4em;\r\n	}\r\n	div.clickable { cursor:pointer; }\r\n	.selected-row { background:#ffffcc; }\r\n</style>\r\n" );

	}
}


class GoogleResults {

    private ResponseData responseData;
    public ResponseData getResponseData() { return responseData; }
    public void setResponseData(ResponseData responseData) { this.responseData = responseData; }
    public String toString() { return "ResponseData[" + responseData + "]"; }

    static class ResponseData {
        private List<Result> results;
        public List<Result> getResults() { return results; }
        public void setResults(List<Result> results) { this.results = results; }
        public String toString() { return "Results[" + results + "]"; }
    }

    static class Result {
        private String url;
        private String title;
        private String content;
        public String getUrl() { return url; }
        public String getTitle() { return title; }
        public String getContent() { return content; }
        public void setUrl(String url) { this.url = url; }
        public void setTitle(String title) { this.title = title; }
        public String toString() { return "Result[url:" + url +",title:" + title + "]"; }
    }
}