aboutsummaryrefslogtreecommitdiff
path: root/pl/episode_data.pl
diff options
context:
space:
mode:
Diffstat (limited to 'pl/episode_data.pl')
-rw-r--r--pl/episode_data.pl68
1 files changed, 68 insertions, 0 deletions
diff --git a/pl/episode_data.pl b/pl/episode_data.pl
new file mode 100644
index 0000000..49dddd0
--- /dev/null
+++ b/pl/episode_data.pl
@@ -0,0 +1,68 @@
+:- module(episode_data, [retract_episode/1,
+ lookup_episode/3,
+ lookup_episode_local/3,
+ lookup_episode_remote/3]).
+
+:- 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_name_data(episode:integer, name:atom, data:list).
+
+attach :-
+ absolute_file_name('episode_data.db', F, [access(write)]),
+ db_attach(F, []).
+
+detach :-
+ db_detach.
+
+retract_episode(Ep) :-
+ ( episode_name_data(Ep, _, _)
+ -> retractall_episode_name_data(Ep, _, _)
+ ; true
+ ).
+
+padding(Ep) --> { Ep < 10 }, "00".
+padding(Ep) --> { Ep >= 10, Ep < 100 }, "0".
+padding(Ep) --> { Ep >= 100 }.
+
+episode_number(Ep) --> padding(Ep), integer(Ep).
+
+lookup_episode(Ep, Name, Data) :- lookup_episode_local(Ep, Name, Data), !.
+lookup_episode(Ep, Name, Data) :- lookup_episode_remote(Ep, Name, Data).
+
+lookup_episode_local(Ep, Name, Data) :-
+ episode_name_data(Ep, Name, Data).
+
+lookup_episode_remote(Ep, Name, Data) :-
+ catch(http_load_html(
+ 'https://www.detectiveconanworld.com/wiki/Next_Conan%27s_Hint',
+ D),
+ _,
+ fail),
+ xpath(D, //tr, D1),
+ xpath(D1, td(index(1),text), T),
+ atom_phrase(episode_number(Ep), T),
+ xpath(D1, td(index(2),text), Name),
+ xpath(D1, td(index(3),text), Hint),
+ Data = [hint(Hint)],
+ assert_episode_name_data(Ep, Name, Data).
+
+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)).