Exemple #1
0
        /// <summary>
        /// Identifies the name of the show.
        /// </summary>
        /// <param name="name">The name of the show.</param>
        /// <param name="ep">The episode.</param>
        /// <param name="askRemote">if set to <c>true</c> lab.rolisoft.net's API will be asked to identify a show after the local database failed.</param>
        /// <returns>
        /// A tuple containing the show's and episode's title and airdate.
        /// </returns>
        private static Tuple<string, string, DateTime, TVShow, Episode> IdentifyShow(string name, ShowEpisode ep, bool askRemote = false)
        {
            var title = string.Empty;
            var date  = DateTime.MinValue;
            var match = false;
            var ltvsh = default(TVShow);
            var lepis = default(Episode);

            // try to find show in local database

            foreach (var show in Database.TVShows.Values.ToList())
            {
                var titleMatch   = ShowNames.Parser.GenerateTitleRegex(show.Name).Match(name);
                var releaseMatch = !string.IsNullOrWhiteSpace(show.Release) ? Regex.Match(name, show.Release) : null;

                if ((titleMatch.Success && titleMatch.Value == name) || (releaseMatch != null && releaseMatch.Success && releaseMatch.Value == name))
                {
                    if (ep == null)
                    {
                        match = true;
                        ltvsh = show;
                        name  = show.Name;

                        break;
                    }
                    else if (ep.AirDate != null)
                    {
                        var episode = show.Episodes.Where(x => x.Airdate.ToOriginalTimeZone(x.Show.TimeZone).Date == ep.AirDate.Value.Date).ToList();
                        if (episode.Count != 0)
                        {
                            match = true;
                            ltvsh = show;
                            name  = show.Name;
                            lepis = episode[0];
                            title = episode[0].Name;
                            date  = episode[0].Airdate;

                            ep.Season  = episode[0].Season;
                            ep.Episode = episode[0].Number;

                            break;
                        }
                    }
                    else
                    {
                        Episode episode;
                        if (show.EpisodeByID.TryGetValue(ep.Season * 1000 + ep.Episode, out episode))
                        {
                            match = true;
                            ltvsh = show;
                            name  = show.Name;
                            lepis = episode;
                            title = episode.Name;
                            date  = episode.Airdate;

                            break;
                        }
                    }
                }
            }

            // try to find show in the local cache of the list over at lab.rolisoft.net

            if (!match)
            {
                if (AllKnownTVShows.Count == 0)
                {
                    var path = Path.Combine(Signature.InstallPath, @"misc\tvshows");

                    if (File.Exists(path) && new FileInfo(path).Length != 0)
                    {
                        using (var fs = File.OpenRead(path))
                        using (var br = new BinaryReader(fs))
                        {
                            var ver = br.ReadByte();
                            var upd = br.ReadUInt32();
                            var cnt = br.ReadUInt32();

                            AllKnownTVShows = new List<KnownTVShow>();

                            for (var i = 0; i < cnt; i++)
                            {
                                var show = new KnownTVShow();

                                show.Title      = br.ReadString();
                                show.Slug       = br.ReadString();
                                show.Database   = br.ReadString();
                                show.DatabaseID = br.ReadString();

                                AllKnownTVShows.Add(show);
                            }
                        }
                    }
                    else
                    {
                        try { GetAllKnownTVShows(); } catch { }
                    }
                }

                var slug    = Utils.CreateSlug(name);
                var matches = new List<KnownTVShow>();

                foreach (var show in AllKnownTVShows)
                {
                    if (show.Slug == slug)
                    {
                        matches.Add(show);
                    }
                }

                if (matches.Count != 0 && ep == null)
                {
                    match = true;
                    name  = matches[0].Title;
                }
                else if (matches.Count != 0 && ep != null)
                {
                    TVShow local = null;

                    foreach (var mtch in matches)
                    {
                        foreach (var show in Database.TVShows.Values)
                        {
                            if (show.Source == mtch.Database && show.SourceID == mtch.DatabaseID)
                            {
                                local = show;
                                break;
                            }
                        }
                    }

                    if (local != null)
                    {
                        match = true;
                        name  = local.Name;

                        if (ep.AirDate != null)
                        {
                            var eps = local.Episodes.Where(ch => ch.Airdate.Date == ep.AirDate.Value.Date).ToList();
                            if (eps.Count() != 0)
                            {
                                ltvsh = eps[0].Show;
                                title = eps[0].Name;
                                lepis = eps[0];
                                date  = eps[0].Airdate;

                                ep.Season  = eps[0].Season;
                                ep.Episode = eps[0].Number;
                            }
                        }
                        else
                        {
                            var eps = local.Episodes.Where(ch => ch.Season == ep.Season && ch.Number == ep.Episode).ToList();
                            if (eps.Count() != 0)
                            {
                                ltvsh = eps[0].Show;
                                title = eps[0].Name;
                                lepis = eps[0];
                                date  = eps[0].Airdate;
                            }
                        }
                    }
                    else if (ShowIDCache.ContainsKey(name) && TVShowCache.ContainsKey(name))
                    {
                        match = true;
                        name  = ShowIDCache[name].Title;

                        if (ep.AirDate != null)
                        {
                            var eps = TVShowCache[name].Episodes.Where(ch => ch.Airdate.Date == ep.AirDate.Value.Date).ToList();
                            if (eps.Count() != 0)
                            {
                                title = eps[0].Title;
                                date  = eps[0].Airdate;

                                ep.Season  = eps[0].Season;
                                ep.Episode = eps[0].Number;
                            }
                        }
                        else
                        {
                            var eps = TVShowCache[name].Episodes.Where(ch => ch.Season == ep.Season && ch.Number == ep.Episode).ToList();
                            if (eps.Count() != 0)
                            {
                                title = eps[0].Title;
                                date  = eps[0].Airdate;
                            }
                        }
                    }
                    else if (askRemote)
                    {
                        var guide = Updater.CreateGuide(matches[0].Database);
                        var data  = guide.GetData(matches[0].DatabaseID);

                        ShowIDCache[name] = new ShowID { Title = data.Title };

                        match = true;
                        name  = data.Title;

                        TVShowCache[name] = data;

                        if (ep.AirDate != null)
                        {
                            var eps = data.Episodes.Where(ch => ch.Airdate.Date == ep.AirDate.Value.Date).ToList();
                            if (eps.Count() != 0)
                            {
                                title = eps[0].Title;
                                date  = eps[0].Airdate;

                                ep.Season  = eps[0].Season;
                                ep.Episode = eps[0].Number;
                            }
                        }
                        else
                        {
                            var eps = data.Episodes.Where(ch => ch.Season == ep.Season && ch.Number == ep.Episode).ToList();
                            if (eps.Count() != 0)
                            {
                                title = eps[0].Title;
                                date  = eps[0].Airdate;
                            }
                        }
                    }
                }
            }

            // try to find show in cache

            if (!match && ShowIDCache.ContainsKey(name))
            {
                match = true;
                name  = ShowIDCache[name].Title;

                if (ep != null)
                {
                    if (TVShowCache.ContainsKey(name))
                    {
                        if (ep.AirDate != null)
                        {
                            var eps = TVShowCache[name].Episodes.Where(ch => ch.Airdate.Date == ep.AirDate.Value.Date).ToList();
                            if (eps.Count() != 0)
                            {
                                title = eps[0].Title;
                                date  = eps[0].Airdate;

                                ep.Season  = eps[0].Season;
                                ep.Episode = eps[0].Number;
                            }
                        }
                        else
                        {
                            var eps = TVShowCache[name].Episodes.Where(ch => ch.Season == ep.Season && ch.Number == ep.Episode).ToList();
                            if (eps.Count() != 0)
                            {
                                title = eps[0].Title;
                                date  = eps[0].Airdate;
                            }
                        }
                    }
                    else
                    {
                        match = false;
                    }
                }
            }

            // try to identify show using lab.rolisoft.net's API

            if (!match && askRemote)
            {
                var req = Remote.API.GetShowInfo(name, new[] { "Title", "Source", "SourceID" });

                if (req.Success)
                {
                    if (ep == null)
                    {
                        ShowIDCache[name] = new ShowID { Title = req.Title };

                        match = true;
                        name  = req.Title;
                    }
                    else
                    {
                        var guide = Updater.CreateGuide(req.Source);
                        var data  = guide.GetData(req.SourceID);

                        ShowIDCache[name] = new ShowID { Title = data.Title };

                        match = true;
                        name  = data.Title;

                        TVShowCache[name] = data;

                        if (ep.AirDate != null)
                        {
                            var eps = data.Episodes.Where(ch => ch.Airdate.Date == ep.AirDate.Value.Date).ToList();
                            if (eps.Count() != 0)
                            {
                                title = eps[0].Title;
                                date  = eps[0].Airdate;

                                ep.Season  = eps[0].Season;
                                ep.Episode = eps[0].Number;
                            }
                        }
                        else
                        {
                            var eps = data.Episodes.Where(ch => ch.Season == ep.Season && ch.Number == ep.Episode).ToList();
                            if (eps.Count() != 0)
                            {
                                title = eps[0].Title;
                                date  = eps[0].Airdate;
                            }
                        }
                    }
                }
            }

            // return

            return match
                   ? new Tuple<string, string, DateTime, TVShow, Episode>(name, title, date, ltvsh, lepis)
                   : null;
        }
        /// <summary>
        /// Adds the specified TV show to the database.
        /// </summary>
        /// <param name="sid">The show ID to add to the database.</param>
        /// <param name="callback">The status callback.</param>
        /// <returns>Added TV show or <c>null</c>.</returns>
        public static TVShow Add(ShowID sid, Action<int, string> callback = null)
        {
            Log.Info("Adding " + sid.Guide.Name + "/" + sid.ID + "...");

            var st = DateTime.Now;

            if (callback != null)
            {
                callback(0, "Downloading guide from " + sid.Guide.Name + "...");
            }

            TVShow tv;
            try
            {
                tv = sid.Guide.GetData(sid.ID, sid.Language);

                if (tv.Episodes.Count == 0)
                {
                    Log.Error("Downloaded guide for " + tv.Title + " (" + sid.Guide.Name + "/" + sid.ID + ") has no episodes.");

                    if (callback != null)
                    {
                        callback(-1, "No episodes listed for this show on " + sid.Guide.Name + ".");
                    }

                    return null;
                }
            }
            catch (Exception ex)
            {
                if (ex is ThreadAbortException)
                {
                    Log.Warn("Thread aborted while downloading data from guide for " + sid.Guide.Name + "/" + sid.ID + ".", ex);
                    return null;
                }

                Log.Error("Error while downloading data from guide for " + sid.Guide.Name + "/" + sid.ID + ".", ex);

                if (callback != null)
                {
                    callback(-1, "Error while downloading data: " + ex.Message);
                }

                return null;
            }

            if (TVShows.Values.FirstOrDefault(x => x.Title == tv.Title) != null)
            {
                Log.Error("Duplicate entry detected for " + tv.Title + " (" + sid.Guide.Name + "/" + sid.ID + ").");

                if (callback != null)
                {
                    callback(-1, tv.Title + " is already in your database.");
                }

                return null;
            }

            foreach (var tvs in TVShows.Values)
            {
                tvs.RowID++;
                tvs.SaveData();
            }

            tv.RowID       = 0;
            tv.ID          = TVShows.Values.Count > 0 ? TVShows.Values.Max(x => x.ID) + 1 : 1;
            tv.Data        = new Dictionary<string, string>();
            tv.Directory   = Path.Combine(DataPath, Utils.CreateSlug(tv.Title, false));
            tv.EpisodeByID = new Dictionary<int, Episode>();

            if (Directory.Exists(tv.Directory))
            {
                tv.Directory += "-" + tv.Source.ToLower();
            }

            if (Directory.Exists(tv.Directory))
            {
                tv.Directory += "-" + Utils.Rand.Next();
            }

            try
            {
                Directory.CreateDirectory(tv.Directory);
            }
            catch (Exception ex)
            {
                Log.Error("Error while creating directory db\\" + Path.GetFileName(tv.Directory) + " for " + tv.Title + " (" + sid.Guide.Name + "/" + sid.ID + ").", ex);

                if (callback != null)
                {
                    callback(-1, "Error while creating database.");
                }

                return null;
            }

            foreach (var ep in tv.Episodes)
            {
                ep.Show = tv;
                ep.ID   = ep.Number + (ep.Season * 1000) + (tv.ID * 1000 * 1000);

                tv.EpisodeByID[ep.Number + (ep.Season * 1000)] = ep;

                if (!string.IsNullOrWhiteSpace(tv.AirTime) && ep.Airdate != Utils.UnixEpoch)
                {
                    ep.Airdate = DateTime.Parse(ep.Airdate.ToString("yyyy-MM-dd ") + tv.AirTime).ToLocalTimeZone(tv.TimeZone);
                }
            }

            try
            {
                tv.Save();
                tv.SaveTracking();
            }
            catch (Exception ex)
            {
                Log.Error("Error while saving database to db\\" + Path.GetFileName(tv.Directory) + " for " + tv.Title + " (" + sid.Guide.Name + "/" + sid.ID + ").", ex);

                if (callback != null)
                {
                    callback(-1, "Error while saving to database.");
                }

                return null;
            }

            TVShows[tv.ID] = tv;
            DataChange = DateTime.Now;

            if (tv.Language == "en")
            {
                Updater.UpdateRemoteCache(tv);
            }

            if (callback != null)
            {
                callback(1, "Show added successfully.");
            }

            Log.Debug("Successfully added " + tv.Title + " (" + sid.Guide.Name + "/" + sid.ID + ") in " + (DateTime.Now - st).TotalSeconds + "s.");

            return tv;
        }
        /// <summary>
        /// Downloads and inserts the specified show into the database.
        /// </summary>
        /// <param name="show">The show.</param>
        private void AddShow(ShowID show)
        {
            working.Content           = "Downloading guide...";
            subworking.Content        = show.Title;
            selectTabItem.Visibility  = Visibility.Collapsed;
            workingTabItem.Visibility = Visibility.Visible;
            tabControl.SelectedIndex  = 1;

            Utils.Win7Taskbar(state: TaskbarProgressBarState.Indeterminate);

            _worker = new Thread(() =>
                {
                    var tv = Database.Add(_guide.GetType().Name, show.ID, show.Language, (i, s) =>
                        {
                            if (i == -1)
                            {
                                Dispatcher.Invoke((Action)(() =>
                                    {
                                        workingTabItem.Visibility = Visibility.Collapsed;
                                        addTabItem.Visibility     = Visibility.Visible;
                                        tabControl.SelectedIndex  = 0;

                                        Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);
                                    }));

                                TaskDialog.Show(new TaskDialogOptions
                                    {
                                        MainIcon        = VistaTaskDialogIcon.Error,
                                        Title           = "Error",
                                        MainInstruction = show.Title,
                                        Content         = s,
                                        CustomButtons   = new[] { "OK" }
                                    });
                            }
                        });

                    if (tv == null)
                    {
                        return;
                    }

                    if (tv.Language == "en")
                    {
                        Updater.UpdateRemoteCache(tv);
                    }

                    _dbid = tv.ID;

                    MainWindow.Active.DataChanged();

                    // show finish page
                    Dispatcher.Invoke((Action)(() =>
                        {
                            finishTitle.Content       = tv.Title;
                            workingTabItem.Visibility = Visibility.Collapsed;
                            finishTabItem.Visibility  = Visibility.Visible;
                            tabControl.SelectedIndex  = 3;

                            Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);

                            var shows = Database.TVShows[_dbid].Episodes.OrderByDescending(ep => ep.ID);

                            markUntil.Items.Clear();

                            var gotLast = false;

                            foreach (var item in shows)
                            {
                                markUntil.Items.Add("S{0:00}E{1:00} - {2}".FormatWith(item.Season, item.Number, item.Title));

                                if (!gotLast && item.Airdate < DateTime.Now && item.Airdate != Utils.UnixEpoch)
                                {
                                    gotLast = true;
                                    markUntil.Items[markUntil.Items.Count - 1] += " [last aired episode]";
                                }
                            }
                        }));
                });
            _worker.Start();
        }
        /// <summary>
        /// Downloads and inserts the specified show into the database.
        /// </summary>
        /// <param name="show">The show.</param>
        private void AddShow(ShowID show)
        {
            working.Content           = "Downloading guide...";
            subworking.Content        = show.Title;
            selectTabItem.Visibility  = Visibility.Collapsed;
            workingTabItem.Visibility = Visibility.Visible;
            tabControl.SelectedIndex  = 1;

            Utils.Win7Taskbar(state: TaskbarProgressBarState.Indeterminate);

            var lang = (language.SelectedValue as StackPanel).Tag.ToString();

            _worker = new Thread(() =>
                {
                    // get data from guide
                    TVShow tv;
                    try
                    {
                        tv = _guide.GetData(show.ID, lang);

                        if (tv.Episodes.Count == 0)
                        {
                            throw new Exception("There aren't any episodes associated to this TV show on this database.");
                        }
                    }
                    catch (Exception ex)
                    {
                        if (ex is ThreadAbortException)
                        {
                            return;
                        }

                        Dispatcher.Invoke((Action)(() =>
                            {
                                workingTabItem.Visibility = Visibility.Collapsed;
                                addTabItem.Visibility     = Visibility.Visible;
                                tabControl.SelectedIndex  = 0;

                                Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);
                            }));

                        new TaskDialog
                            {
                                Icon                = TaskDialogStandardIcon.Error,
                                Caption             = "Couldn't grab TV show",
                                InstructionText     = show.Title,
                                Text                = "Couldn't download the episode listing and associated informations due to an unexpected error.",
                                DetailsExpandedText = ex.Message,
                                Cancelable          = true
                            }.Show();

                        return;
                    }

                    // try to see if duplicate
                    if (Database.TVShows.Values.FirstOrDefault(x => x.Title == tv.Title) != null)
                    {
                        Dispatcher.Invoke((Action)(() =>
                            {
                                workingTabItem.Visibility = Visibility.Collapsed;
                                addTabItem.Visibility     = Visibility.Visible;
                                tabControl.SelectedIndex  = 0;

                                Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);
                            }));

                        new TaskDialog
                            {
                                Icon            = TaskDialogStandardIcon.Error,
                                Caption         = "Duplicate entry",
                                InstructionText = tv.Title,
                                Text            = "This TV show is already on your list.",
                                Cancelable      = true
                            }.Show();

                        return;
                    }

                    // increment each rowid
                    foreach (var tvs in Database.TVShows.Values)
                    {
                        tvs.RowID++;
                        tvs.SaveData();
                    }

                    // generate showid
                    tv.RowID = 0;
                    _dbid = tv.ID = Database.TVShows.Values.Max(x => x.ID) + 1;
                    tv.Data = new Dictionary<string, string>();
                    tv.Directory = Path.Combine(Database.DataPath, Utils.CreateSlug(tv.Title, false));

                    if (Directory.Exists(tv.Directory))
                    {
                        tv.Directory += "-" + tv.Source.ToLower();
                    }

                    if (Directory.Exists(tv.Directory))
                    {
                        tv.Directory += "-" + Utils.Rand.Next();
                    }

                    Directory.CreateDirectory(tv.Directory);

                    // apply timezone corrections
                    foreach (var ep in tv.Episodes)
                    {
                        if (!string.IsNullOrWhiteSpace(tv.AirTime) && ep.Airdate != Utils.UnixEpoch)
                        {
                            ep.Airdate = DateTime.Parse(ep.Airdate.ToString("yyyy-MM-dd ") + tv.AirTime).ToLocalTimeZone(tv.TimeZone);
                        }
                    }

                    // save
                    tv.Save();
                    tv.SaveTracking();

                    // fire data change event
                    Database.LoadDatabase();
                    MainWindow.Active.DataChanged();

                    // asynchronously update lab.rolisoft.net's cache
                    if (tv.Language == "en")
                    {
                        Updater.UpdateRemoteCache(tv);
                    }

                    // show finish page
                    Dispatcher.Invoke((Action)(() =>
                        {
                            finishTitle.Content       = tv.Title;
                            workingTabItem.Visibility = Visibility.Collapsed;
                            finishTabItem.Visibility  = Visibility.Visible;
                            tabControl.SelectedIndex  = 3;

                            Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);

                            var shows = Database.TVShows[_dbid].Episodes.OrderByDescending(ep => ep.ID);

                            markUntil.Items.Clear();

                            var gotLast = false;

                            foreach (var item in shows)
                            {
                                markUntil.Items.Add("S{0:00}E{1:00} - {2}".FormatWith(item.Season, item.Number, item.Title));

                                if (!gotLast && item.Airdate < DateTime.Now && item.Airdate != Utils.UnixEpoch)
                                {
                                    gotLast = true;
                                    markUntil.Items[markUntil.Items.Count - 1] += " [last aired episode]";
                                }
                            }
                        }));
                });
            _worker.Start();
        }
        /// <summary>
        /// Downloads and inserts the specified show into the database.
        /// </summary>
        /// <param name="show">The show.</param>
        private void AddShow(ShowID show)
        {
            working.Content           = "Downloading guide...";
            subworking.Content        = show.Title;
            selectTabItem.Visibility  = Visibility.Collapsed;
            workingTabItem.Visibility = Visibility.Visible;
            tabControl.SelectedIndex  = 1;

            Utils.Win7Taskbar(state: TaskbarProgressBarState.Indeterminate);

            var lang = (language.SelectedValue as StackPanel).Tag.ToString();

            _worker = new Thread(() =>
                {
                    // get data from guide
                    TVShow tv;
                    try
                    {
                        tv = _guide.GetData(show.ID, lang);

                        if (tv.Episodes.Count == 0)
                        {
                            throw new Exception("There aren't any episodes associated to this TV show on this database.");
                        }
                    }
                    catch (Exception ex)
                    {
                        if (ex is ThreadAbortException)
                        {
                            return;
                        }

                        Dispatcher.Invoke((Action)(() =>
                            {
                                workingTabItem.Visibility = Visibility.Collapsed;
                                addTabItem.Visibility     = Visibility.Visible;
                                tabControl.SelectedIndex  = 0;

                                Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);
                            }));

                        new TaskDialog
                            {
                                Icon                = TaskDialogStandardIcon.Error,
                                Caption             = "Couldn't grab TV show",
                                InstructionText     = show.Title,
                                Text                = "Couldn't download the episode listing and associated informations due to an unexpected error.",
                                DetailsExpandedText = ex.Message,
                                Cancelable          = true
                            }.Show();

                        return;
                    }

                    // try to see if duplicate
                    if (Database.GetShowID(tv.Title) != int.MinValue)
                    {
                        Dispatcher.Invoke((Action)(() =>
                            {
                                workingTabItem.Visibility = Visibility.Collapsed;
                                addTabItem.Visibility     = Visibility.Visible;
                                tabControl.SelectedIndex  = 0;

                                Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);
                            }));

                        new TaskDialog
                            {
                                Icon            = TaskDialogStandardIcon.Error,
                                Caption         = "Duplicate entry",
                                InstructionText = tv.Title,
                                Text            = "This TV show is already on your list.",
                                Cancelable      = true
                            }.Show();

                        return;
                    }

                    // create transaction
                    SQLiteTransaction tr;
                    try
                    {
                        tr = Database.Connection.BeginTransaction();
                    }
                    catch (Exception ex)
                    {
                        if (ex is ThreadAbortException)
                        {
                            return;
                        }

                        Dispatcher.Invoke((Action)(() =>
                        {
                            workingTabItem.Visibility = Visibility.Collapsed;
                            addTabItem.Visibility     = Visibility.Visible;
                            tabControl.SelectedIndex  = 0;

                            Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);
                        }));

                        new TaskDialog
                            {
                                Icon                = TaskDialogStandardIcon.Error,
                                Caption             = "Couldn't create transaction",
                                InstructionText     = tv.Title,
                                Text                = "Couldn't create transaction on the database to insert the episodes. The TV show is added to the list, however, there aren't any episodes associated to it. Run an update to add the episodes.",
                                DetailsExpandedText = ex.Message,
                                Cancelable          = true
                            }.Show();

                        return;
                    }

                    // insert into tvshows and let the autoincrementing field assign a showid
                    Database.Execute("update tvshows set rowid = rowid + 1");
                    Database.Execute("insert into tvshows values (1, null, ?, ?)", tv.Title, show.Title != tv.Title ? ShowNames.Parser.GenerateTitleRegex(show.Title).ToString() : string.Empty);

                    // then get that showid
                    _dbid = Database.Query("select showid from tvshows where name = ? limit 1", tv.Title)[0]["showid"].ToInteger();

                    // insert guide fields
                    var gname = _guide.GetType().Name;

                    Database.ShowData(_dbid, "grabber",       gname);
                    Database.ShowData(_dbid, gname + ".id",   show.ID);
                    Database.ShowData(_dbid, gname + ".lang", lang);

                    // insert showdata fields
                    Database.ShowData(_dbid, "genre",    tv.Genre);
                    Database.ShowData(_dbid, "descr",    tv.Description);
                    Database.ShowData(_dbid, "cover",    tv.Cover);
                    Database.ShowData(_dbid, "airing",   tv.Airing.ToString());
                    Database.ShowData(_dbid, "airtime",  tv.AirTime);
                    Database.ShowData(_dbid, "airday",   tv.AirDay);
                    Database.ShowData(_dbid, "network",  tv.Network);
                    Database.ShowData(_dbid, "timezone", tv.TimeZone);
                    Database.ShowData(_dbid, "runtime",  tv.Runtime.ToString());
                    Database.ShowData(_dbid, "url",      tv.URL);

                    // insert episodes
                    foreach (var ep in tv.Episodes)
                    {
                        try
                        {
                            Database.ExecuteOnTransaction(tr, "insert into episodes values (?, ?, ?, ?, ?, ?, ?, ?, ?)",
                                                          ep.Number + (ep.Season * 1000) + (_dbid * 100 * 1000),
                                                          _dbid,
                                                          ep.Season,
                                                          ep.Number,
                                                          tv.AirTime == String.Empty || ep.Airdate == Utils.UnixEpoch
                                                            ? ep.Airdate.ToUnixTimestamp()
                                                            : DateTime.Parse(ep.Airdate.ToString("yyyy-MM-dd ") + tv.AirTime).ToLocalTimeZone(tv.TimeZone).ToUnixTimestamp(),
                                                          ep.Title,
                                                          ep.Summary,
                                                          ep.Picture,
                                                          ep.URL);
                        }
                        catch
                        {
                            continue;
                        }
                    }

                    // commit the changes
                    tr.Commit();

                    // fire data change event
                    Database.CopyToMemory();
                    MainWindow.Active.DataChanged();

                    // asynchronously update lab.rolisoft.net's cache
                    Updater.UpdateRemoteCache(new Tuple<string, string>(_guide.GetType().Name, show.ID), tv);

                    // show finish page
                    Dispatcher.Invoke((Action)(() =>
                        {
                            finishTitle.Content       = tv.Title;
                            workingTabItem.Visibility = Visibility.Collapsed;
                            finishTabItem.Visibility  = Visibility.Visible;
                            tabControl.SelectedIndex  = 3;

                            Utils.Win7Taskbar(state: TaskbarProgressBarState.NoProgress);

                            var shows = Database.Query("select season, episode, name, airdate from episodes where showid = ? order by (season * 1000 + episode) desc", _dbid);

                            markUntil.Items.Clear();

                            var gotLast = false;

                            foreach (var item in shows)
                            {
                                markUntil.Items.Add("S{0:00}E{1:00} - {2}".FormatWith(item["season"].ToInteger(), item["episode"].ToInteger(), item["name"]));

                                if (!gotLast && item["airdate"].ToInteger() < DateTime.Now.ToUnixTimestamp() && item["airdate"] != "0")
                                {
                                    gotLast = true;
                                    markUntil.Items[markUntil.Items.Count - 1] += " [last aired episode]";
                                }
                            }
                        }));
                });
            _worker.Start();
        }