From 91b82a5cbd8a9c90798d1bd49bfa9a061e652a6a Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Thu, 11 Apr 2019 19:55:52 +0200 Subject: [PATCH] CLI search, step 1 --- src/be/nikiroo/fanfix/Main.java | 143 +++++++++++++++++- .../fanfix/bundles/resources_core.properties | 5 + .../bundles/resources_core_fr.properties | 5 + src/be/nikiroo/fanfix/reader/BasicReader.java | 6 + src/be/nikiroo/fanfix/reader/Reader.java | 53 +++++++ .../nikiroo/fanfix/reader/cli/CliReader.java | 100 ++++++++++++ .../nikiroo/fanfix/reader/tui/TuiReader.java | 13 ++ .../reader/tui/TuiReaderApplication.java | 11 ++ .../nikiroo/fanfix/reader/ui/GuiReader.java | 13 ++ .../fanfix/searchable/BasicSearchable.java | 2 +- .../nikiroo/fanfix/searchable/Fanfiction.java | 2 +- 11 files changed, 348 insertions(+), 5 deletions(-) diff --git a/src/be/nikiroo/fanfix/Main.java b/src/be/nikiroo/fanfix/Main.java index 953bc45..bbb335e 100644 --- a/src/be/nikiroo/fanfix/Main.java +++ b/src/be/nikiroo/fanfix/Main.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; import java.util.List; import be.nikiroo.fanfix.bundles.StringId; @@ -20,6 +21,7 @@ import be.nikiroo.fanfix.output.BasicOutput.OutputType; import be.nikiroo.fanfix.reader.BasicReader; import be.nikiroo.fanfix.reader.Reader; import be.nikiroo.fanfix.reader.Reader.ReaderType; +import be.nikiroo.fanfix.searchable.BasicSearchable; import be.nikiroo.fanfix.supported.BasicSupport; import be.nikiroo.fanfix.supported.SupportType; import be.nikiroo.utils.Progress; @@ -33,7 +35,7 @@ import be.nikiroo.utils.serial.server.ServerObject; */ public class Main { private enum MainAction { - IMPORT, EXPORT, CONVERT, READ, READ_URL, LIST, HELP, SET_READER, START, VERSION, SERVER, STOP_SERVER, REMOTE, SET_SOURCE, SET_TITLE, SET_AUTHOR + IMPORT, EXPORT, CONVERT, READ, READ_URL, LIST, HELP, SET_READER, START, VERSION, SERVER, STOP_SERVER, REMOTE, SET_SOURCE, SET_TITLE, SET_AUTHOR, SEARCH, SEARCH_TAG } /** @@ -59,6 +61,11 @@ public class Main { * *
  • --read-url [URL] ([chapter number]): convert on the fly and read the * story, without saving it
  • + *
  • --search WEBSITE [free text] ([page] ([item])): search for the given terms, + * show the given page (page 0 means "how many page do we have", starts at page 1)
  • + *
  • --search-tag WEBSITE ([tag 1] [tag2...] ([page] ([item]))): list the known + * tags or search the stories for the given tag(s), show the given page of results + * (page 0 means "how many page do we have", starts at page 1)
  • *
  • --list ([type]): list the stories present in the library
  • *
  • --set-source [id] [new source]: change the source of the given story
  • *
  • --set-title [id] [new title]: change the title of the given story
  • @@ -88,6 +95,11 @@ public class Main { Boolean plusInfo = null; String host = null; Integer port = null; + SupportType searchOn = null; + String search = null; + List tags = new ArrayList(); + Integer page = null; + Integer item = null; boolean noMoreActions = false; @@ -200,6 +212,64 @@ public class Main { exitCode = 255; } break; + case SEARCH: + if (searchOn == null) { + searchOn = SupportType.valueOfAllOkUC(args[i]); + + if (searchOn == null) { + Instance.getTraceHandler().error( + "Website not known: <" + args[i] + ">"); + exitCode = 255; + } + + if (BasicSearchable.getSearchable(searchOn) == null) { + Instance.getTraceHandler().error( + "Website not supported: " + searchOn); + exitCode = 255; + } + } else if (search == null) { + search = args[i]; + } else if (page == null) { + try { + page = Integer.parseInt(args[i]); + } catch (NumberFormatException e) { + Instance.getTraceHandler().error( + new Exception("Incorrect page number: <" + + args[i] + ">", e)); + exitCode = 255; + } + } else if (item == null) { + try { + item = Integer.parseInt(args[i]); + } catch (NumberFormatException e) { + Instance.getTraceHandler().error( + new Exception("Incorrect item number: <" + + args[i] + ">", e)); + exitCode = 255; + } + } else { + exitCode = 255; + } + break; + case SEARCH_TAG: + if (searchOn == null) { + searchOn = SupportType.valueOfAllOkUC(args[i]); + + if (searchOn == null) { + Instance.getTraceHandler().error( + "Website not known: <" + args[i] + ">"); + exitCode = 255; + } + + if (BasicSearchable.getSearchable(searchOn) == null) { + Instance.getTraceHandler().error( + "Website not supported: " + searchOn); + exitCode = 255; + } + } else { + tags.add(args[i]); + } + break; case HELP: exitCode = 255; break; @@ -282,8 +352,8 @@ public class Main { System.err.println("\tVersion " + v); System.err.println("\t-------------"); System.err.println(""); - for (String item : updates.getChanges().get(v)) { - System.err.println("\t- " + item); + for (String it : updates.getChanges().get(v)) { + System.err.println("\t- " + it); } System.err.println(""); } @@ -357,6 +427,73 @@ public class Main { break; } exitCode = read(urlString, chapString, false); + break; + case SEARCH: + if (searchOn == null || search == null) { + exitCode = 255; + break; + } + + if (page == null) { + page = 1; + } + if (item == null) { + item = 0; + } + + if (BasicReader.getReader() == null) { + Instance.getTraceHandler() + .error(new Exception( + "No reader type has been configured")); + exitCode = 10; + break; + } + + try { + BasicReader.getReader().search(searchOn, search, page, item); + } catch (IOException e1) { + Instance.getTraceHandler().error(e1); + } + + break; + case SEARCH_TAG: + if (searchOn == null) { + exitCode = 255; + break; + } + + item = 0; + page = 1; + + try { + item = Integer.parseInt(tags.get(tags.size()-1)); + tags.remove(tags.size() - 1); + + try { + int tmp = Integer.parseInt(tags.get(tags.size()-1)); + tags.remove(tags.size() - 1); + + page = item; + item = tmp; + } catch (Exception e) { + } + } catch (Exception e) { + } + + if (BasicReader.getReader() == null) { + Instance.getTraceHandler() + .error(new Exception( + "No reader type has been configured")); + exitCode = 10; + break; + } + + try { + BasicReader.getReader().searchTag(searchOn, page, item, tags.toArray(new String[]{})); + } catch (IOException e1) { + Instance.getTraceHandler().error(e1); + } + break; case HELP: syntax(true); diff --git a/src/be/nikiroo/fanfix/bundles/resources_core.properties b/src/be/nikiroo/fanfix/bundles/resources_core.properties index 62fd158..6a08973 100644 --- a/src/be/nikiroo/fanfix/bundles/resources_core.properties +++ b/src/be/nikiroo/fanfix/bundles/resources_core.properties @@ -16,6 +16,11 @@ HELP_SYNTAX = Valid options:\n\ \t--read [id] ([chapter number]): read the given story from the library\n\ \t--read-url [URL] ([chapter number]): convert on the fly and read the \n\ \t\tstory, without saving it\n\ +\t--search WEBSITE [free text] ([page] ([item])): search for the given terms, show the\n\ +\t\tgiven page (page 0 means "how many page do we have", starts at page 1)\n\ +\t--search-tag WEBSITE ([tag 1] [tag2...] ([page] ([item]))): list the known tags or \n\ +\t\tsearch the stories for the given tag(s), show the given page of results\n\ +\t\t(page 0 means "how many page do we have", starts at page 1)\n\ \t--list ([type]) : list the stories present in the library\n\ \t--set-source [id] [new source]: change the source of the given story\n\ \t--set-title [id] [new title]: change the title of the given story\n\ diff --git a/src/be/nikiroo/fanfix/bundles/resources_core_fr.properties b/src/be/nikiroo/fanfix/bundles/resources_core_fr.properties index 092bd33..149391e 100644 --- a/src/be/nikiroo/fanfix/bundles/resources_core_fr.properties +++ b/src/be/nikiroo/fanfix/bundles/resources_core_fr.properties @@ -15,6 +15,11 @@ HELP_SYNTAX = Options reconnues :\n\ \t--convert [URL] [output_type] [target] (+info): convertir l'histoire vers le fichier donné, et forcer l'ajout d'un fichier .info si +info est utilisé\n\ \t--read [id] ([chapter number]): afficher l'histoire "id"\n\ \t--read-url [URL] ([chapter number]): convertir l'histoire et la lire à la volée, sans la sauver\n\ +\t--search WEBSITE [texte libre] ([page] ([item])): cherche des histoires, affiche la\n\ +\t\tpage de résultats demandée (la page 0 affiche le nombre de pages, la première page est la page 1)\n\ +\t--search-tag WEBSITE ([tag 1] [tag2...] ([page] ([item]))): list the known tags or \n\ +\t\tcherche des histoires avec le/les tag(s) demandé(s), affiche la page de résultats demandée\n\ +\t\t(la page 0 affiche le nombre de pages, la première page est la page 1)\n\ \t--list ([type]): lister les histoires presentes dans la librairie et leurs IDs\n\ \t--set-source [id] [nouvelle source]: change la source de l'histoire\n\ \t--set-title [id] [nouveau titre]: change le titre de l'histoire\n\ diff --git a/src/be/nikiroo/fanfix/reader/BasicReader.java b/src/be/nikiroo/fanfix/reader/BasicReader.java index c2a650c..c749a59 100644 --- a/src/be/nikiroo/fanfix/reader/BasicReader.java +++ b/src/be/nikiroo/fanfix/reader/BasicReader.java @@ -351,7 +351,13 @@ public abstract class BasicReader implements Reader { } } + /** + * @deprecated use StringUtils when updated + */ + @Deprecated static private String format(long value) { + //TODO: use StringUtils + String display = ""; String suffix = ""; diff --git a/src/be/nikiroo/fanfix/reader/Reader.java b/src/be/nikiroo/fanfix/reader/Reader.java index b001e30..59ed024 100644 --- a/src/be/nikiroo/fanfix/reader/Reader.java +++ b/src/be/nikiroo/fanfix/reader/Reader.java @@ -6,6 +6,7 @@ import java.net.URL; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; import be.nikiroo.fanfix.library.BasicLibrary; +import be.nikiroo.fanfix.supported.SupportType; import be.nikiroo.utils.Progress; /** @@ -169,6 +170,58 @@ public interface Reader { */ public void browse(String source); + /** + * Search for the given terms and find stories that correspond if possible. + * + * @param searchOn + * the website to search on + * @param keywords + * the words to search for (cannot be NULL) + * @param page + * the page of results to show (0 = request the maximum number of + * pages, pages start at 1) + * @param item + * the item to select (0 = do not select a specific item but show + * all the page, items start at 1) + * + * @throws IOException + * in case of I/O error + */ + public void search(SupportType searchOn, String keywords, int page, int item) + throws IOException; + + /** + * Search based upon a hierarchy of tags, or search for (sub)tags. + *

    + * We use the tags DisplayName. + *

    + * If no tag is given, the main tags will be shown. + *

    + * If a non-leaf tag is given, the subtags will be shown. + *

    + * If a leaf tag is given (or a full hierarchy ending with a leaf tag), + * stories will be shown. + *

    + * You can select the story you want with the item number. + * + * @param searchOn + * the website to search on + * @param page + * the page of results to show (0 = request the maximum number of + * pages, pages start at 1) + * @param item + * the item to select (0 = do not select a specific item but show + * all the page, items start at 1) + * @param tags + * the tags display names to search for (this is a tag + * hierarchy, NOT a multiple tags choice) + * + * @throws IOException + * in case of I/O error + */ + public void searchTag(SupportType searchOn, int page, int item, + String... tags) throws IOException; + /** * Open the {@link Story} with an external reader (the program should be * passed the main file associated with this {@link Story}). diff --git a/src/be/nikiroo/fanfix/reader/cli/CliReader.java b/src/be/nikiroo/fanfix/reader/cli/CliReader.java index 9ec37a5..7a4abfb 100644 --- a/src/be/nikiroo/fanfix/reader/cli/CliReader.java +++ b/src/be/nikiroo/fanfix/reader/cli/CliReader.java @@ -1,6 +1,7 @@ package be.nikiroo.fanfix.reader.cli; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import be.nikiroo.fanfix.Instance; @@ -10,6 +11,9 @@ import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Paragraph; import be.nikiroo.fanfix.data.Story; import be.nikiroo.fanfix.reader.BasicReader; +import be.nikiroo.fanfix.searchable.BasicSearchable; +import be.nikiroo.fanfix.searchable.SearchableTag; +import be.nikiroo.fanfix.supported.SupportType; /** * Command line {@link Story} reader. @@ -95,4 +99,100 @@ class CliReader extends BasicReader { + author); } } + + @Override + public void search(SupportType searchOn, String keywords, int page, int item) throws IOException { + + } + + @Override + public void searchTag(SupportType searchOn, int page, int item, String... tags) throws IOException { + BasicSearchable search = BasicSearchable.getSearchable(searchOn); + List stags = search.getTags(); + + + SearchableTag stag = null; + for (String tag : tags) { + stag = null; + for (int i = 0 ; i < stags.size() ; i++) { + if (stags.get(i).getName().equalsIgnoreCase(tag)) { + stag = stags.get(i); + break; + } + } + + if (stag != null) { + search.fillTag(stag); + stags = stag.getChildren(); + } else { + stags = new ArrayList(); + break; + } + } + + if (stag != null) { + if (page <= 0) { + if (stag.isLeaf()) { + System.out.println(stag.getPages()); + } else { + System.out.println(stag.getCount()); + } + } else { + List metas = null; + List subtags = null; + int count; + + if (stag.isLeaf()) { + metas = search.search(stag, page); + count = metas.size(); + } else { + subtags = stag.getChildren(); + count = subtags.size(); + } + + if (item > 0) { + if (item <= count) { + if (metas != null) { + MetaData meta = metas.get(item - 1); + System.out.println(item + ": " + meta.getTitle()); + System.out.println(meta.getUrl()); + System.out.println(); + System.out.println("Tags: " + meta.getTags()); + System.out.println(); + for (Paragraph para : meta.getResume()) { + System.out.println(para.getContent()); + System.out.println(""); + } + } else { + SearchableTag subtag = subtags.get(item - 1); + // TODO: display fixed info, not debug + System.out.println(subtag); + } + } else { + System.out.println("Invalid item: only " + count + " items found"); + } + } else { + if (metas != null) { + int i = 0; + for (MetaData meta : metas) { + System.out.println((i + 1) + ": " + meta.getTitle()); + i++; + } + } else { + for (SearchableTag subtag : subtags) { + if (subtag.getCount() > 0) { + System.out.println(subtag.getName() + " (" + subtag.getCount() + ")"); + } else { + System.out.println(subtag.getName()); + } + } + } + } + } + } else { + for (SearchableTag s : stags) { + System.out.println(s.getName()); + } + } + } } diff --git a/src/be/nikiroo/fanfix/reader/tui/TuiReader.java b/src/be/nikiroo/fanfix/reader/tui/TuiReader.java index f94f783..cc39dcd 100644 --- a/src/be/nikiroo/fanfix/reader/tui/TuiReader.java +++ b/src/be/nikiroo/fanfix/reader/tui/TuiReader.java @@ -7,6 +7,7 @@ import jexer.TApplication.BackendType; import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.reader.BasicReader; import be.nikiroo.fanfix.reader.Reader; +import be.nikiroo.fanfix.supported.SupportType; /** * This {@link Reader}is based upon the TUI widget library 'jexer' @@ -70,4 +71,16 @@ class TuiReader extends BasicReader { Instance.getTraceHandler().error(e); } } + + @Override + public void search(SupportType searchOn, String keywords, int page, int item) { + // TODO: !!! + throw new java.lang.IllegalStateException("Not implemented yet."); + } + + @Override + public void searchTag(SupportType searchOn, int page, int item, String... tags) { + // TODO: !!! + throw new java.lang.IllegalStateException("Not implemented yet."); + } } diff --git a/src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java b/src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java index f08b84c..177c12a 100644 --- a/src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java +++ b/src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java @@ -25,6 +25,7 @@ import be.nikiroo.fanfix.library.BasicLibrary; import be.nikiroo.fanfix.reader.BasicReader; import be.nikiroo.fanfix.reader.Reader; import be.nikiroo.fanfix.reader.tui.TuiReaderMainWindow.Mode; +import be.nikiroo.fanfix.supported.SupportType; import be.nikiroo.utils.Progress; /** @@ -124,6 +125,16 @@ class TuiReaderApplication extends TApplication implements Reader { public void setChapter(int chapter) { reader.setChapter(chapter); } + + @Override + public void search(SupportType searchOn, String keywords, int page, int item) { + reader.search(searchOn, keywords, page,item); + } + + @Override + public void searchTag(SupportType searchOn, int page, int item, String... tags) { + reader.searchTag(searchOn, page, item, tags); + } /** * Open the given {@link Story} for reading. This may or may not start an diff --git a/src/be/nikiroo/fanfix/reader/ui/GuiReader.java b/src/be/nikiroo/fanfix/reader/ui/GuiReader.java index f4a932b..2ca6191 100644 --- a/src/be/nikiroo/fanfix/reader/ui/GuiReader.java +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReader.java @@ -25,6 +25,7 @@ import be.nikiroo.fanfix.library.BasicLibrary; import be.nikiroo.fanfix.library.CacheLibrary; import be.nikiroo.fanfix.reader.BasicReader; import be.nikiroo.fanfix.reader.Reader; +import be.nikiroo.fanfix.supported.SupportType; import be.nikiroo.utils.Progress; import be.nikiroo.utils.Version; import be.nikiroo.utils.ui.UIUtils; @@ -217,6 +218,18 @@ class GuiReader extends BasicReader { super.start(target, program, sync); } } + + @Override + public void search(SupportType searchOn, String keywords, int page, int item) { + // TODO: !!! + throw new java.lang.IllegalStateException("Not implemented yet."); + } + + @Override + public void searchTag(SupportType searchOn, int page, int item, String... tags) { + // TODO: !!! + throw new java.lang.IllegalStateException("Not implemented yet."); + } /** * Delete the {@link Story} from the cache if it is present, but NOT diff --git a/src/be/nikiroo/fanfix/searchable/BasicSearchable.java b/src/be/nikiroo/fanfix/searchable/BasicSearchable.java index c639443..ebc5096 100644 --- a/src/be/nikiroo/fanfix/searchable/BasicSearchable.java +++ b/src/be/nikiroo/fanfix/searchable/BasicSearchable.java @@ -83,7 +83,7 @@ public abstract class BasicSearchable { * @throws IOException * in case of I/O error */ - abstract protected void fillTag(SearchableTag tag) throws IOException; + abstract public void fillTag(SearchableTag tag) throws IOException; /** * Search for the given term and return a list of stories satisfying this diff --git a/src/be/nikiroo/fanfix/searchable/Fanfiction.java b/src/be/nikiroo/fanfix/searchable/Fanfiction.java index bcc4759..71732fc 100644 --- a/src/be/nikiroo/fanfix/searchable/Fanfiction.java +++ b/src/be/nikiroo/fanfix/searchable/Fanfiction.java @@ -94,7 +94,7 @@ class Fanfiction extends BasicSearchable { } @Override - protected void fillTag(SearchableTag tag) throws IOException { + public void fillTag(SearchableTag tag) throws IOException { if (tag.getId() == null || tag.isComplete()) { return; } -- 2.27.0