diff --git a/src/main/java/net/thauvin/erik/mobibot/modules/GoogleSearch.java b/src/main/java/net/thauvin/erik/mobibot/modules/GoogleSearch.java index e12bc1d..1fd4e6c 100644 --- a/src/main/java/net/thauvin/erik/mobibot/modules/GoogleSearch.java +++ b/src/main/java/net/thauvin/erik/mobibot/modules/GoogleSearch.java @@ -83,43 +83,52 @@ public final class GoogleSearch extends ThreadedModule { * @param cseKey The Google search results. */ @SuppressFBWarnings(value = {"URLCONNECTION_SSRF_FD", "REC_CATCH_EXCEPTION"}) - static ArrayList searchGoogle(String query, String apiKey, String cseKey) throws ModuleException { - final ArrayList results = new ArrayList<>(); - try { - final String q = URLEncoder.encode(query, StandardCharsets.UTF_8.toString()); - - final URL url = - new URL("https://www.googleapis.com/customsearch/v1?key=" - + apiKey - + "&cx=" - + cseKey - + "&q=" - + q - + "&filter=1&num=5&alt=json"); - final URLConnection conn = url.openConnection(); - - final StringBuilder sb = new StringBuilder(); - try (final BufferedReader reader = - new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) { - String line; - while ((line = reader.readLine()) != null) { - sb.append(line); - } - - final JSONObject json = new JSONObject(sb.toString()); - final JSONArray ja = json.getJSONArray("items"); - - for (int i = 0; i < ja.length(); i++) { - final JSONObject j = ja.getJSONObject(i); - results.add(new NoticeMessage(Utils.unescapeXml(j.getString("title")))); - results.add(new NoticeMessage(j.getString("link"))); - } - } - } catch (IOException e) { - throw new ModuleException("searchGoogle(" + query + ')', "An error has occurred searching Google.", e); + static ArrayList searchGoogle(final String query, final String apiKey, final String cseKey) + throws ModuleException { + if (!Utils.isValidString(apiKey) || !Utils.isValidString(cseKey)) { + throw new ModuleException(Utils.capitalize(GOOGLE_CMD) + " is disabled. The API keys are missing."); } - return results; + if (Utils.isValidString(query)) { + final ArrayList results = new ArrayList<>(); + try { + final String q = URLEncoder.encode(query, StandardCharsets.UTF_8.toString()); + + final URL url = + new URL("https://www.googleapis.com/customsearch/v1?key=" + + apiKey + + "&cx=" + + cseKey + + "&q=" + + q + + "&filter=1&num=5&alt=json"); + final URLConnection conn = url.openConnection(); + + final StringBuilder sb = new StringBuilder(); + try (final BufferedReader reader = + new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) { + String line; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + + final JSONObject json = new JSONObject(sb.toString()); + final JSONArray ja = json.getJSONArray("items"); + + for (int i = 0; i < ja.length(); i++) { + final JSONObject j = ja.getJSONObject(i); + results.add(new NoticeMessage(Utils.unescapeXml(j.getString("title")))); + results.add(new NoticeMessage(j.getString("link"))); + } + } + } catch (IOException e) { + throw new ModuleException("searchGoogle(" + query + ')', "An error has occurred searching Google.", e); + } + + return results; + } else { + throw new ModuleException("Invalid query."); + } } /** @@ -131,7 +140,7 @@ public final class GoogleSearch extends ThreadedModule { bot.send(sender, "To search Google:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + GOOGLE_CMD + " ")); } else { - bot.send(sender, "The Google searching facility is disabled."); + bot.send(sender, "The Google search module is disabled."); } } @@ -139,22 +148,26 @@ public final class GoogleSearch extends ThreadedModule { * Searches Google. */ void run(final Mobibot bot, final String sender, final String query) { - try { - final ArrayList results = searchGoogle(query, properties.get(GOOGLE_API_KEY_PROP), - properties.get(GOOGLE_CSE_KEY_PROP)); + if (Utils.isValidString(query)) { + try { + final ArrayList results = searchGoogle(query, properties.get(GOOGLE_API_KEY_PROP), + properties.get(GOOGLE_CSE_KEY_PROP)); - int i = 0; - for (Message msg : results) { - if (i % 2 == 0) { - bot.send(sender, Utils.green(TAB_INDENT + msg.getMessage())); - } else { - bot.send(sender, msg.getMessage()); + int i = 0; + for (final Message msg : results) { + if (i % 2 == 0) { + bot.send(sender, Utils.green(TAB_INDENT + msg.getMessage())); + } else { + bot.send(sender, msg.getMessage()); + } + i++; } - i++; + } catch (ModuleException e) { + bot.getLogger().warn(e.getDebugMessage(), e); + bot.send(sender, e.getMessage()); } - } catch (ModuleException e) { - bot.getLogger().warn(e.getDebugMessage(), e); - bot.send(sender, e.getMessage()); + } else { + helpResponse(bot, sender, query, true); } } } diff --git a/src/test/java/net/thauvin/erik/mobibot/modules/GoogleSearchTest.java b/src/test/java/net/thauvin/erik/mobibot/modules/GoogleSearchTest.java index 6cac311..d222eec 100644 --- a/src/test/java/net/thauvin/erik/mobibot/modules/GoogleSearchTest.java +++ b/src/test/java/net/thauvin/erik/mobibot/modules/GoogleSearchTest.java @@ -45,7 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @created 2019-04-08 * @since 1.0 */ -public class GoogleSearchTest { +public class GoogleSearchTest extends LocalProperties { @Test public void testGoogleSearchImpl() { AbstractModuleTest.testAbstractModule(new GoogleSearch()); @@ -63,6 +63,27 @@ public class GoogleSearchTest { messages = GoogleSearch.searchGoogle("aapl", apiKey, cseKey); assertThat(messages).as("aapl results not empty").isNotEmpty(); assertThat(messages.get(0).getMessage()).as("found apple").containsIgnoringCase("apple"); + + try { + GoogleSearch.searchGoogle("test", "", "apiKey"); + } catch (Exception e) { + assertThat(e).as("no API key").isInstanceOf(ModuleException.class); + assertThat(e).as("no API key exception has no cause").hasNoCause(); + } + + try { + GoogleSearch.searchGoogle("test", "apiKey", ""); + } catch (Exception e) { + assertThat(e).as("no CSE API key").isInstanceOf(ModuleException.class); + assertThat(e).as("no CSE API key exception has no cause").hasNoCause(); + } + + try { + GoogleSearch.searchGoogle("", "apikey", "apiKey"); + } catch (Exception e) { + assertThat(e).as("no query").isInstanceOf(ModuleException.class); + assertThat(e).as("no query exception has no cause").hasNoCause(); + } } catch (ModuleException e) { // Avoid displaying api keys in CI logs. if ("true".equals(System.getenv("CI"))) {