IMDb plaintext downloader: optionally download actors and actresses
[cinaest] / src / imdb / imdb-downloader-cli.vala
1 using GLib;
2
3 class IMDbDownloaderCLI : Object, IMDbDownloader {
4         MainLoop loop;
5         Cancellable cancellable;
6         bool running;
7         uint source_id;
8         unowned IMDbSqlite sqlite;
9 //      string mirrors[] = {
10 //              "ftp.fu-berlin.de/pub/misc/movies/database/"
11 //      };
12         string url;
13         int flags;
14         int percent_finished;
15
16         delegate void ParseLineFunction (string line);
17
18         construct {
19                 loop = new MainLoop (null, false);
20                 cancellable = new Cancellable ();
21         }
22
23         // IMDbDownloader implementation
24
25         public void download (string mirror, int _flags) throws DBus.Error {
26                 if (running) {
27                         stdout.printf ("Download in progress. Abort.\n");
28                         return;
29                 }
30                 running = true;
31                 if (source_id != 0) {
32                         Source.remove (source_id);
33                 }
34
35                 stdout.printf ("Download started (%x).", flags);
36                 progress (0);
37                 url = "ftp://anonymous@" + mirror;
38                 flags = _flags;
39                 try {
40                         Thread.create(download_thread, false);
41                 } catch (ThreadError e) {
42                         critical ("Failed to create download thread\n");
43                         return;
44                 }
45         }
46
47         public void cancel () throws DBus.Error {
48                 cancellable.cancel ();
49         }
50
51         public string[] get_mirrors () throws DBus.Error {
52                 return null;
53         }
54
55         // Private methods
56
57         private bool do_download () {
58                 try {
59                         download ("ftp.fu-berlin.de/pub/misc/movies/database/", MOVIES | GENRES | RATINGS | AKAS | PLOTS | ACTORS);
60                 } catch (Error e) {
61                         print ("Error: %s\n", e.message);
62                 }
63
64                 return false;
65         }
66
67         private void* download_thread () {
68                 description_changed ("Connecting to FTP ...");
69                 progress (0);
70                 percent_finished = 0;
71
72                 var cache_dir = Path.build_filename (Environment.get_user_cache_dir (), "cinaest");
73                 DirUtils.create_with_parents (cache_dir, 0770);
74
75                 var _sqlite = new IMDbSqlite (Path.build_filename (cache_dir, "imdb.db"));
76                 sqlite = _sqlite;
77                 _sqlite.clear ();
78
79                 try {
80                         var movie_parser = new MovieLineParser (sqlite);
81                         var genre_parser = new GenreLineParser (sqlite);
82                         var rating_parser = new RatingLineParser (sqlite);
83                         var aka_parser = new AkaLineParser (sqlite);
84                         var plot_parser = new PlotLineParser (sqlite);
85                         var person_parser = new PersonParser (sqlite);
86
87                         var downloader = new FtpDownloader (cancellable);
88
89                         var parser = new IMDbGzipParser (cancellable);
90
91                         downloader.progress.connect (on_progress);
92
93                         if (MOVIES in flags) {
94                                 description_changed ("Downloading movie list ...");
95                                 downloader.download (url + "movies.list.gz", Path.build_filename (cache_dir, "movies.list.gz"));
96                         }
97                         percent_finished = 20;
98                         if (GENRES in flags) {
99                                 description_changed ("Downloading genre data ...");
100                                 downloader.download (url + "genres.list.gz", Path.build_filename (cache_dir, "genres.list.gz"));
101                         }
102                         percent_finished = 40;
103                         if (RATINGS in flags) {
104                                 description_changed ("Downloading rating data ...");
105                                 downloader.download (url + "ratings.list.gz", Path.build_filename (cache_dir, "ratings.list.gz"));
106                         }
107                         percent_finished = 60;
108                         if (AKAS in flags) {
109                                 description_changed ("Downloading alternative titles ...");
110                                 downloader.download (url + "aka-titles.list.gz", Path.build_filename (cache_dir, "aka-titles.list.gz"));
111                         }
112                         percent_finished = 80;
113                         if (PLOTS in flags) {
114                                 description_changed ("Downloading plots ...");
115                                 downloader.download (url + "plot.list.gz", Path.build_filename (cache_dir, "plot.list.gz"));
116                         }
117                         if (ACTORS in flags) {
118                                 description_changed ("Downloading actors ...");
119                                 downloader.download (url + "actors.list.gz", Path.build_filename (cache_dir, "actors.list.gz"));
120                                 description_changed ("Downloading actresses ...");
121                                 downloader.download (url + "actresses.list.gz", Path.build_filename (cache_dir, "actresses.list.gz"));
122                         }
123                         // composers
124                         // costume-designers
125                         if (DIRECTORS in flags) {
126                                 description_changed ("Downloading directors ...");
127                                 downloader.download (url + "directors.list.gz", Path.build_filename (cache_dir, "directors.list.gz"));
128                         }
129                         // editors
130                         // producers
131                         // production-designers
132                         if (WRITERS in flags) {
133                                 description_changed ("Downloading writers ...");
134                                 downloader.download (url + "writers.list.gz", Path.build_filename (cache_dir, "writers.list.gz"));
135                         }
136
137                         if (MOVIES in flags) {
138                                 description_changed ("Parsing movie list ...");
139                                 parser.parse (Path.build_filename (cache_dir, "movies.list.gz"), movie_parser);
140                         }
141                         percent_finished = 20;
142                         if (GENRES in flags) {
143                                 description_changed ("Parsing genre data ...");
144                                 parser.parse (Path.build_filename (cache_dir, "genres.list.gz"), genre_parser);
145                         }
146                         percent_finished = 40;
147                         if (RATINGS in flags) {
148                                 description_changed ("Parsing rating data ...");
149                                 parser.parse (Path.build_filename (cache_dir, "ratings.list.gz"), rating_parser);
150                         }
151                         percent_finished = 60;
152                         if (AKAS in flags) {
153                                 description_changed ("Parsing alternative titles ...");
154                                 parser.parse (Path.build_filename (cache_dir, "aka-titles.list.gz"), aka_parser);
155                         }
156                         percent_finished = 80;
157                         if (PLOTS in flags) {
158                                 description_changed ("Parsing plots ...");
159                                 parser.parse (Path.build_filename (cache_dir, "plot.list.gz"), plot_parser);
160                         }
161                         if (ACTORS in flags) {
162                                 description_changed ("Parsing actors ...");
163                                 parser.parse (Path.build_filename (cache_dir, "actors.list.gz"), person_parser);
164                                 person_parser.reset ();
165                                 description_changed ("Parsing actresses ...");
166                                 parser.parse (Path.build_filename (cache_dir, "actresses.list.gz"), person_parser);
167                         }
168                 } catch (Error e2) {
169                         if (e2 is IOError.CANCELLED)
170                                 stdout.printf ("Download cancelled.\n");
171                         else
172                                 warning ("Failed to open/read stream: %s\n", e2.message);
173                 }
174
175                 description_changed ("Creating indices ...");
176                 if (AKAS in flags)
177                         sqlite.create_aka_index ();
178                 if (MOVIES in flags)
179                         sqlite.create_votes_index ();
180
181                 if (!cancellable.is_cancelled ()) {
182                         stdout.printf ("Download complete.\n");
183                         progress (100);
184                 }
185
186                 sqlite = null;
187                 running = false;
188
189                 timeout_quit ();
190
191                 return null;
192         }
193
194         private void on_progress (int dltotal, int dlnow) {
195         /*
196                 progress (percent_finished + percent / 5);
197                 stdout.printf ("%d %%\r", percent_finished + percent / 5);
198         */
199                 stdout.printf ("%d / %d\r", dlnow, dltotal);
200                 stdout.flush ();
201         }
202
203         private void timeout_quit () {
204                 source_id = Timeout.add (3000, quit);
205         }
206
207         private bool quit () {
208                 loop.quit ();
209
210                 // One-shot only
211                 return false;
212         }
213
214         public void run () {
215                 loop.run ();
216         }
217
218         public void show_desc (string desc) {
219                 print ("DESC: \"%s\"\n", desc);
220         }
221
222         public static void main () {
223                 Curl.global_init (Curl.GLOBAL_DEFAULT);
224
225                 // Start server
226                 var downloader = new IMDbDownloaderCLI ();
227                 downloader.description_changed.connect (downloader.show_desc);
228
229                 Idle.add (downloader.do_download);
230                 downloader.run ();
231
232                 Curl.global_cleanup ();
233         }
234 }