From 6fd66a9264731bd7ee6d7602675965021d929a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Wed, 24 Aug 2022 15:17:08 +0200 Subject: Remove Prolog dependency. The only thing left to reimplement is the tracking of watched episodes in MPC-HC. --- pl/atom_dcg.pl | 82 --------------------- pl/cfg.pl | 76 -------------------- pl/episode_data.pl | 196 --------------------------------------------------- pl/local_episodes.pl | 50 ------------- pl/track_episodes.pl | 112 ----------------------------- 5 files changed, 516 deletions(-) delete mode 100644 pl/atom_dcg.pl delete mode 100644 pl/cfg.pl delete mode 100644 pl/episode_data.pl delete mode 100644 pl/local_episodes.pl delete mode 100644 pl/track_episodes.pl (limited to 'pl') diff --git a/pl/atom_dcg.pl b/pl/atom_dcg.pl deleted file mode 100644 index c5b9bfc..0000000 --- a/pl/atom_dcg.pl +++ /dev/null @@ -1,82 +0,0 @@ -:- module(atom_dcg, [compound_atom_codes/2]). - -% with_atoms/1-9 automatically convert atoms for the caller to codes -% for the callee, primarily to make atoms easier to use with -% definite-clause grammars. atom_phrase/2 is defined as a shortcut. - -% with_codes/1-9, conversely, convert codes for the caller to atoms -% for the callee. - -:- meta_predicate user:with_atoms(0). -:- meta_predicate user:with_atoms(0,0). -:- meta_predicate user:with_atoms(0,0,0). -:- meta_predicate user:with_atoms(0,0,0,0). -:- meta_predicate user:with_atoms(0,0,0,0,0). -:- meta_predicate user:with_atoms(0,0,0,0,0,0). -:- meta_predicate user:with_atoms(0,0,0,0,0,0,0). -:- meta_predicate user:with_atoms(0,0,0,0,0,0,0,0). -:- meta_predicate user:with_atoms(0,0,0,0,0,0,0,0,0). -user:with_atoms(A) :- atom_dcg:compound_atom_codes(A, A1), call(A1). -user:with_atoms(A, B) :- maplist(user:with_atoms, [A,B]). -user:with_atoms(A, B, C) :- maplist(user:with_atoms, [A,B,C]). -user:with_atoms(A, B, C, D) :- maplist(user:with_atoms, [A,B,C,D]). -user:with_atoms(A, B, C, D, E) :- maplist(user:with_atoms, [A,B,C,D,E]). -user:with_atoms(A, B, C, D, E, F) :- maplist(user:with_atoms, [A,B,C,D,E,F]). -user:with_atoms(A, B, C, D, E, F, G) :- maplist(user:with_atoms, [A,B,C,D,E,F,G]). -user:with_atoms(A, B, C, D, E, F, G, H) :- maplist(user:with_atoms, [A,B,C,D,E,F,G,H]). -user:with_atoms(A, B, C, D, E, F, G, H, I) :- maplist(user:with_atoms, [A,B,C,D,E,F,G,H,I]). - -:- meta_predicate user:with_codes(0). -:- meta_predicate user:with_codes(0,0). -:- meta_predicate user:with_codes(0,0,0). -:- meta_predicate user:with_codes(0,0,0,0). -:- meta_predicate user:with_codes(0,0,0,0,0). -:- meta_predicate user:with_codes(0,0,0,0,0,0). -:- meta_predicate user:with_codes(0,0,0,0,0,0,0). -:- meta_predicate user:with_codes(0,0,0,0,0,0,0,0). -:- meta_predicate user:with_codes(0,0,0,0,0,0,0,0,0). -user:with_codes(A) :- atom_dcg:compound_atom_codes(A1, A), call(A1). -user:with_codes(A, B) :- maplist(user:with_codes, [A,B]). -user:with_codes(A, B, C) :- maplist(user:with_codes, [A,B,C]). -user:with_codes(A, B, C, D) :- maplist(user:with_codes, [A,B,C,D]). -user:with_codes(A, B, C, D, E) :- maplist(user:with_codes, [A,B,C,D,E]). -user:with_codes(A, B, C, D, E, F) :- maplist(user:with_codes, [A,B,C,D,E,F]). -user:with_codes(A, B, C, D, E, F, G) :- maplist(user:with_codes, [A,B,C,D,E,F,G]). -user:with_codes(A, B, C, D, E, F, G, H) :- maplist(user:with_codes, [A,B,C,D,E,F,G,H]). -user:with_codes(A, B, C, D, E, F, G, H, I) :- maplist(user:with_codes, [A,B,C,D,E,F,G,H,I]). - -:- meta_predicate user:atom_phrase(2, ?). -user:atom_phrase(G, A) :- - atom_dcg:compound_atom_codes(G, G1), - ( var(A) - -> phrase(G1, C), - atom_codes(A, C) - ; atom_codes(A, C), - phrase(G1, C) - ). - -compound_atom_codes(Module:G, Module:G1) :- !, compound_atom_codes(G, G1). -compound_atom_codes(G, G1) :- - ( nonvar(G) - -> G =.. [F|Args0], - maplist(maybe_atom_codes, Args0, Args), - G1 =.. [F|Args] - ; G1 =.. [F|Args], - maplist(maybe_atom_codes, Args0, Args), - G =.. [F|Args0] - ). - -maybe_atom_codes(A, C) :- - (compound(A) ; compound(C)), !, - compound_atom_codes(A, C). - -maybe_atom_codes(A, C) :- - nonvar(A), !, - ( atom(A) - -> atom_codes(A, C) - ; C = A - ). - -maybe_atom_codes(A, C) :- - var(A), !, - when((ground(A) ; ground(C)), catch(atom_codes(A, C), _, A = C)). diff --git a/pl/cfg.pl b/pl/cfg.pl deleted file mode 100644 index 297d426..0000000 --- a/pl/cfg.pl +++ /dev/null @@ -1,76 +0,0 @@ -:- module(cfg, [set_glob/1, - get_glob/1, - set_root/1, - get_root/1, - set_url/1, - get_url/1]). - -:- use_module(library(registry)). - -set_key(Key, Value) :- - registry_set_key(current_user/software/'JohnAJ'/'EpisodeBrowser'/'Settings', Key, Value). -get_key(Key, Value) :- - catch(registry_get_key(current_user/software/'JohnAJ'/'EpisodeBrowser'/'Settings', Key, Value), - _, - fail). - -set_root(V) :- set_key('EpisodeRoot', V). -get_root(V) :- - get_key('EpisodeRoot', V0), - re_replace('\\\\', '/', V0, V1), - atom_string(V, V1). - -set_glob(V) :- set_key('EpisodeGlob', V). -get_glob(V) :- - ( get_key('EpisodeGlob', V), ! - ; V = '*/*.*' - ). - -set_url(V) :- set_key('UrlPrefix', V). -get_url(V) :- - ( get_key('UrlPrefix', V), ! - ; V = 'https://animixplay.to/v1/detective-conan/ep' - ). - -set_view_watched(V) :- set_key('ViewWatched', V). -get_view_watched(V) :- - ( get_key('ViewWatched', V), - integer(V), ! - ; V = 1 - ). - -set_view_tv_original(V) :- set_key('ViewTVOriginal', V). -get_view_tv_original(V) :- - ( get_key('ViewTVOriginal', V), - integer(V), ! - ; V = 1 - ). - -set_limit_screenwriter(V) :- set_key('LimitScreenwriter', V). -get_limit_screenwriter(V) :- - ( get_key('LimitScreenwriter', V), - atom(V), ! - ; V = "" - ). - -set_sort(V) :- W is V + 2147483647, set_key('Sort', W). -get_sort(V) :- - ( get_key('Sort', W), - integer(W), !, - V is W - 2147483647 - ; V = 1 - ). - -set_focus(V) :- set_key('Focus', V). -get_focus(V) :- - ( get_key('Focus', V), - integer(V), ! - ; V = 1 - ). - -set_dlv_height(V) :- set_key('DlvHeight', V). -get_dlv_height(V) :- - ( get_key('DlvHeight', V), - integer(V), ! - ; V = 0 - ). diff --git a/pl/episode_data.pl b/pl/episode_data.pl deleted file mode 100644 index 5b83546..0000000 --- a/pl/episode_data.pl +++ /dev/null @@ -1,196 +0,0 @@ -:- module(episode_data, [ensure_episode_data/0, - update_episode_data/0, - update_screenwriters/0, - retract_episode/1, - episode_count/1, - rate_episode/2, - episode_rating/2, - tv_original/1, - thread_running/1, - thread_exception/2]). - -:- use_module(library(clpfd)). -:- use_module(library(dcg/basics)). -:- use_module(library(http/http_open)). -:- use_module(library(sgml)). -:- use_module(library(xpath)). -:- use_module(library(persistency)). -:- use_module(atom_dcg). - -:- persistent episode_title(episode:integer, title:atom). -:- persistent episode_wiki(episode:integer, wiki:atom). -:- persistent episode_datum(episode:integer, key:atom, value:atom). -:- persistent episode_rating(episode:integer, rating:integer). - -attach :- - absolute_file_name('episode_data.db', F, [access(write)]), - db_attach(F, []). - -detach :- - db_detach. - -ensure_episode_data :- episode_title(_, _), !. -ensure_episode_data :- update_episode_data. - -retract_episode(Ep) :- - ( episode_title(Ep, _) - -> retractall_episode_title(Ep, _) - ; true - ), - ( episode_datum(Ep, 'Hint', _) - -> retractall_episode_datum(Ep, 'Hint', _) - ; true - ). - -episode_count(N) :- - setof(E, T^episode_title(E,T), Es), - last(Es, N). - -rate_episode(Ep, 0) :- - ( episode_rating(Ep, _) - -> retractall_episode_rating(Ep, _) - ; true - ), - !. - -rate_episode(Ep, R) :- - dif(R, 0), - ( episode_rating(Ep, R) - -> true - ; ( episode_rating(Ep, _) - -> retractall_episode_rating(Ep, _) - ; true - ), - assert_episode_rating(Ep, R) - ). - -open_episode_wiki(Ep) :- - episode_wiki(Ep, W), - win_shell(open, W). - -tv_original(Ep) :- episode_datum(Ep, 'Source', 'TV Original'). - -% Remote data retrieval. - -absolute_url(R) --> "https://www.detectiveconanworld.com", R. - -thread_running(T) :- thread_property(T, status(running)). -thread_exception(T, E) :- thread_property(T, status(exception(E))). - -update_episode_data :- - findall(Ep-Info, - (fetch_episode_info(Ep, Info)), - Set), - maplist(set_episode_info, Set). - -set_episode_info(Ep-Info) :- - maplist(set_episode_datum(Ep), Info). - -set_episode_datum(Ep, 'Title'-Title) :- !, - maybe_assert_episode_title(Ep, Title). -set_episode_datum(Ep, 'Wiki'-W) :- !, - maybe_assert_episode_wiki(Ep, W). -set_episode_datum(Ep, Key-Value) :- - maybe_assert_episode_datum(Ep, Key, Value). - -maybe_assert_episode_title(Ep, Title) :- - ( episode_title(Ep, Title), ! - ; assert_episode_title(Ep, Title) - ). - -maybe_assert_episode_wiki(Ep, W) :- - ( episode_wiki(Ep, W), ! - ; assert_episode_wiki(Ep, W) - ). - -maybe_assert_episode_datum(Ep, Key, Value) :- - ( episode_datum(Ep, Key, Value), ! - ; ( episode_datum(Ep, Key, _) - -> retract_episode_datum(Ep, Key, _) - ; true - ), - assert_episode_datum(Ep, Key, Value) - ). - -episode_number(Ep) --> integer(Ep). -episode_number(Ep) --> integer(Ep), "WPS", integer(_). - -% Temporary helper. -fetch_episode_data(Ep, Title, W, Date, Source, Hint) :- - fetch_episode_info(Ep, ['Title'-Title, 'Wiki'-W, 'Date'-Date, 'Source'-Source, 'Hint'-Hint]). - -fetch_episode_info(Ep, ['Title'-Title, 'Wiki'-W, 'Date'-Date, 'Source'-Source, 'Hint'-Hint]) :- - cached_html('https://www.detectiveconanworld.com/wiki/Anime', H), - xpath(H, //tr(td(index(3),@style='background:#f2fde9;')), R), - xpath(R, td(index(1),normalize_space), Ep0), - atom_phrase(episode_number(Ep), Ep0), - xpath(R, td(index(3),normalize_space), Title), - xpath(R, td(index(3))/a(@href), W0), - atom_phrase(absolute_url(W0), W), - xpath(R, td(index(4),normalize_space), Date), - xpath(R, td(index(7),normalize_space), Source0), - re_replace('\\(([0-9])', ' (\\1', Source0, Source1), - atom_string(Source, Source1), - xpath(R, td(index(8),normalize_space), Hint). - -update_screenwriters :- - findall(Ep-Name, - (maybe_fetch_screenwriter_episode(Name, Ep)), - Set), - maplist(set_episode_screenwriter, Set). - -set_episode_screenwriter(Ep-Name) :- - maybe_assert_episode_datum(Ep, 'Screenwriter', Name). - -maybe_fetch_screenwriter_episode(Name, Ep) :- - \+ episode_datum(Ep, 'Screenwriter', Ep), - fetch_screenwriter_episode(Name, Ep). - -fetch_screenwriter(Name) :- - cached_html('https://www.detectiveconanworld.com/wiki/Category:Screenplay_writers', H), - xpath(H, //'div'(@id='mw-pages')//a, A), - xpath(A, /self(normalize_space), Name). - -fetch_screenwriter_url(Name, U) :- - cached_html('https://www.detectiveconanworld.com/wiki/Category:Screenplay_writers', H), - xpath(H, //'div'(@id='mw-pages')//a, A), - xpath(A, /self(normalize_space), Name), - xpath(A, /self(@href), U). - -screenwriter_episode(Ep) --> string(_), "(Episode ", integer(Ep), ")". -screenwriter_episode(Ep) --> string(_), "(Episodes ", integer(Ep1), "-", integer(Ep2), ")", - { between(Ep1, Ep2, Ep) }. -screenwriter_episode(Ep) --> string(_), "(Episodes ", integer(Ep1), "-", integer(Ep2), " only)", - { between(Ep1, Ep2, Ep) }. - -fetch_screenwriter_episode(Name, Ep) :- - fetch_screenwriter_url(Name, U0), - atom_phrase(absolute_url(U0), U), - cached_html(U, H), - xpath(H, //div(@id='mw-content-text')//li, L), - xpath(L, /self(normalize_space), T), - atom_phrase(screenwriter_episode(Ep), T). - -fetch_html(U, H) :- - catch(http_load_html(U, H), _, fail), - !, - nb_setval(U, H). - -cached_html(U, H) :- nb_current(U, H), !. -cached_html(U, H) :- fetch_html(U, H). - -http_load_html(URL, DOM) :- - setup_call_cleanup(http_open(URL, In, - [ timeout(60) - ]), - ( dtd(html, DTD), - load_structure(stream(In), - DOM, - [ dtd(DTD), - dialect(sgml), - shorttag(false), - max_errors(-1), - syntax_errors(quiet) - ]) - ), - close(In)). diff --git a/pl/local_episodes.pl b/pl/local_episodes.pl deleted file mode 100644 index 68809a7..0000000 --- a/pl/local_episodes.pl +++ /dev/null @@ -1,50 +0,0 @@ -:- module(local_episodes, [local_episode//1, - episode_file/2, - open_episode_locally/1, - open_episode_online/1]). - -:- use_module(library(dcg/basics)). -:- use_module(atom_dcg). -:- use_module(cfg). - -local_episode_prefix --> string(_), "Detective_Conan_-_". -local_episode_prefix --> string(_), "Detective Conan - ". -local_episode_prefix --> string(_), "Detective-Conan-". -local_episode_prefix --> string(_), "detective_conan_". - -nondigit --> [C], !, { \+ code_type(C, digit) }. -nondigit --> []. - -zeroes --> "0". -zeroes --> "0", zeroes. - -paddedint(N) --> integer(N). -paddedint(N) --> zeroes, integer(N). - -local_episode --> - local_episode(_). -local_episode(N) --> - local_episode_prefix, paddedint(N), nondigit, string(_). -local_episode(N) --> - local_episode_prefix, paddedint(First), "-", paddedint(Last), nondigit, string(_), - { Second is First + 1, between(Second, Last, N) }. - -% Find episode on disk. - -episode_file(N, F) :- - get_root(R), - get_glob(G), - atomic_list_concat([R, '/', G], G1), - expand_file_name(G1, F1), - ( nonvar(N) - -> include(atom_phrase(local_episode(N)), F1, [F|_]) - ; include(atom_phrase(local_episode), F1, F2), - member(F, F2), - atom_phrase(local_episode(N), F) - ). - -% Open episode. - -episode_url(N) --> { with_codes(get_url(U)) }, string(U), integer(N). -open_episode_locally(N) :- episode_file(N, F), !, win_shell(open, F). -open_episode_online(N) :- atom_phrase(episode_url(N), U), win_shell(open, U). diff --git a/pl/track_episodes.pl b/pl/track_episodes.pl deleted file mode 100644 index 1973a75..0000000 --- a/pl/track_episodes.pl +++ /dev/null @@ -1,112 +0,0 @@ -:- module(track_episodes, [update_tracked_episodes/0, - toggle_episode/1, - forget_episode/1, - most_recently_watched/1, - watched/1, - next_unwatched/2, - previous_unwatched/2]). - -:- use_module(library(dcg/basics)). -:- use_module(library(registry)). -:- use_module(library(persistency)). -:- use_module(local_episodes). - -attach :- - absolute_file_name('track_episodes.db', F, [access(write)]), - db_attach(F, []). - -detach :- - db_detach. - -:- persistent episode_watched(episode:integer, watched:atom). - -% Helpers. - -swapbc(P, A, B, C, D) :- call(P, A, C, B, D). -compound(F, A, B, T) :- T =.. [F, A, B]. - -% Get data from registry. - -file(N) --> "File Name ", integer(N). - -pos(N) --> "File Position ", integer(N). - -mpc_reg(Phrase, Value) :- - phrase(Phrase, Name), - atom_codes(Name1, Name), - registry_get_key(current_user/software/'mpc-hc'/'mpc-hc'/settings, - Name1, Value). - -% Create episode-position list. - -epipos(L) :- epipos_x(0, L). - -epipos_x(N, L) :- - ( catch((mpc_reg(file(N), File), - mpc_reg(pos(N), Pos)), - _, - fail) - -> M is N + 1, - ( atom_codes(File, File1), - findall(Ep, phrase(local_episode(Ep), File1), Eps) - -> atom_codes(Pos, Pos1), - phrase(integer(Pos2), Pos1), - maplist(swapbc(compound, '-', Pos2), Eps, Eps1), - append(Eps1, T, L), - epipos_x(M, T) - ; epipos_x(M, L)) - ; L = [] - ). - -considered_watched(_-Pos) :- - Pos > 11000000000. - -% Update database. - -update_tracked_episodes :- - epipos(All), - include(considered_watched, All, Watched), - maplist(add, Watched). - -add(Ep-_) :- episode_watched(Ep, _), !. -add(Ep-_) :- assert_episode_watched(Ep, true). - -forget_episode(Ep) :- - retractall_episode_watched(Ep, true), - retractall_episode_watched(Ep, false). - -toggle_episode(Ep) :- - episode_watched(Ep, true), !, - retractall_episode_watched(Ep, true), - assert_episode_watched(Ep, false). - -toggle_episode(Ep) :- - episode_watched(Ep, false), !, - retractall_episode_watched(Ep, false), - assert_episode_watched(Ep, true). - -toggle_episode(Ep) :- - assert_episode_watched(Ep, true). - -% Utility. - -most_recently_watched(Ep) :- - findall(N, episode_watched(N, true), All), - last(All, Ep). - -watched(Ep) :- - episode_watched(Ep, true). - -next_unwatched(Ep0, Ep) :- - Ep1 is Ep0 + 1, - ( \+ watched(Ep1) - -> Ep = Ep1 - ; next_unwatched(Ep1, Ep) - ). - -previous_unwatched(Ep0, Ep) :- - Ep1 is Ep0 - 1, - ( \+ watched(Ep1) - -> Ep = Ep1 - ; previous_unwatched(Ep1, Ep) - ). -- cgit v1.2.3