int AskForConfirmation(anime::Episode& episode) { auto anime_item = AnimeDatabase.FindItem(episode.anime_id); // Set up dialog win32::TaskDialog dlg; wstring title = L"Anime title: " + anime_item->GetTitle(); dlg.SetWindowTitle(APP_TITLE); dlg.SetMainIcon(TD_ICON_INFORMATION); dlg.SetMainInstruction(L"Do you want to update your anime list?"); dlg.SetContent(title.c_str()); dlg.SetVerificationText(L"Don't ask again, update automatically"); dlg.UseCommandLinks(true); // Get episode number int number = GetEpisodeHigh(episode.number); if (number == 0) number = 1; if (anime_item->GetEpisodeCount() == 1) episode.number = L"1"; // Add buttons if (anime_item->GetMyStatus() != mal::MYSTATUS_NOTINLIST) { if (anime_item->GetEpisodeCount() == number) { // Completed dlg.AddButton(L"Update and move\n" L"Update and set as completed", IDCANCEL); } else if (anime_item->GetMyStatus() != mal::MYSTATUS_WATCHING) { // Watching dlg.AddButton(L"Update and move\n" L"Update and set as watching", IDCANCEL); } } wstring button = L"Update\n" L"Update episode number from " + ToWstr(anime_item->GetMyLastWatchedEpisode()) + L" to " + ToWstr(number); dlg.AddButton(button.c_str(), IDYES); dlg.AddButton(L"Cancel\n" L"Don't update anything", IDNO); // Show dialog dlg.Show(g_hMain); if (dlg.GetVerificationCheck()) Settings.Account.Update.ask_to_confirm = FALSE; return dlg.GetSelectedButtonID(); }
void SearchDialog::AddAnimeToList(int anime_id) { auto anime_item = AnimeDatabase.FindItem(anime_id); if (anime_item) { int i = list_.GetItemCount(); list_.InsertItem(i, anime_item->IsInList() ? 1 : 0, StatusToIcon(anime_item->GetAiringStatus()), 0, nullptr, anime_item->GetTitle().c_str(), static_cast<LPARAM>(anime_item->GetId())); list_.SetItem(i, 1, anime::TranslateType(anime_item->GetType()).c_str()); list_.SetItem(i, 2, anime::TranslateNumber(anime_item->GetEpisodeCount()).c_str()); list_.SetItem(i, 3, anime::TranslateScore(anime_item->GetScore()).c_str()); list_.SetItem(i, 4, anime::TranslateDateToSeasonString(anime_item->GetDateStart()).c_str()); } }
void ExecuteAction(std::wstring action, WPARAM wParam, LPARAM lParam) { LOG(LevelDebug, action); std::wstring body; size_t pos = action.find('('); if (pos != action.npos) { body = action.substr(pos + 1, action.find_last_of(')') - (pos + 1)); action.resize(pos); } Trim(body); Trim(action); if (action.empty()) return; ////////////////////////////////////////////////////////////////////////////// // Taiga // CheckUpdates() // Checks for a new version of the program. if (action == L"CheckUpdates") { ui::ShowDialog(ui::kDialogUpdate); // Exit(), Quit() // Exits from Taiga. } else if (action == L"Exit" || action == L"Quit") { ui::DlgMain.Destroy(); ////////////////////////////////////////////////////////////////////////////// // Services // Synchronize() // Synchronizes local and remote lists. } else if (action == L"Synchronize") { sync::Synchronize(); // SearchAnime() // wParam is a BOOL value that defines local search. } else if (action == L"SearchAnime") { if (body.empty()) return; bool local_search = wParam != FALSE; if (!local_search) { auto service = taiga::GetCurrentService(); if (service->RequestNeedsAuthentication(sync::kSearchTitle)) { if (taiga::GetCurrentUsername().empty() || taiga::GetCurrentPassword().empty()) { ui::OnSettingsAccountEmpty(); return; } } } ui::DlgMain.navigation.SetCurrentPage(ui::kSidebarItemSearch); ui::DlgMain.edit.SetText(body); ui::DlgSearch.Search(body, local_search); // ViewAnimePage // Opens up anime page on the active service. // lParam is an anime ID. } else if (action == L"ViewAnimePage") { int anime_id = static_cast<int>(lParam); switch (taiga::GetCurrentServiceId()) { case sync::kMyAnimeList: sync::myanimelist::ViewAnimePage(anime_id); break; case sync::kHummingbird: sync::hummingbird::ViewAnimePage(anime_id); break; } // ViewUpcomingAnime // Opens up upcoming anime page on MAL. } else if (action == L"ViewUpcomingAnime") { switch (taiga::GetCurrentServiceId()) { case sync::kMyAnimeList: sync::myanimelist::ViewUpcomingAnime(); break; case sync::kHummingbird: sync::hummingbird::ViewUpcomingAnime(); break; } // MalViewPanel() // MalViewProfile() // MalViewHistory() // Opens up MyAnimeList user pages. } else if (action == L"MalViewPanel") { sync::myanimelist::ViewPanel(); } else if (action == L"MalViewProfile") { sync::myanimelist::ViewProfile(); } else if (action == L"MalViewHistory") { sync::myanimelist::ViewHistory(); // HummingbirdViewProfile() // HummingbirdViewDashboard() // HummingbirdViewRecommendations() // Opens up Hummingbird user pages. } else if (action == L"HummingbirdViewProfile") { sync::hummingbird::ViewProfile(); } else if (action == L"HummingbirdViewDashboard") { sync::hummingbird::ViewDashboard(); } else if (action == L"HummingbirdViewRecommendations") { sync::hummingbird::ViewRecommendations(); ////////////////////////////////////////////////////////////////////////////// // Execute(path) // Executes a file or folder. } else if (action == L"Execute") { Execute(body); // URL(address) // Opens a web page. // lParam is an anime ID. } else if (action == L"URL") { int anime_id = static_cast<int>(lParam); auto anime_item = AnimeDatabase.FindItem(anime_id); if (anime_item) { std::wstring title = anime_item->GetTitle(); ReplaceString(body, L"%title%", EncodeUrl(title)); } ExecuteLink(body); ////////////////////////////////////////////////////////////////////////////// // UI // About() // Shows about window. } else if (action == L"About") { ui::ShowDialog(ui::kDialogAbout); // Info([anime_id]) // Shows anime information window. // lParam is an anime ID. } else if (action == L"Info") { int anime_id = body.empty() ? static_cast<int>(lParam) : ToInt(body); ui::ShowDlgAnimeInfo(anime_id); // MainDialog() } else if (action == L"MainDialog") { ui::ShowDialog(ui::kDialogMain); // Settings() // Shows settings window. // wParam is the initial section. // lParam is the initial page. } else if (action == L"Settings") { ui::ShowDlgSettings(wParam, lParam); // SearchTorrents(source) // Searches torrents from specified source URL. // lParam is an anime ID. } else if (action == L"SearchTorrents") { int anime_id = static_cast<int>(lParam); if (body.empty()) body = Settings[taiga::kTorrent_Discovery_SearchUrl]; ui::DlgTorrent.Search(body, anime_id); // ToggleSidebar() } else if (action == L"ToggleSidebar") { bool hide_sidebar = Settings.Toggle(taiga::kApp_Option_HideSidebar); ui::DlgMain.treeview.Show(!hide_sidebar); ui::DlgMain.UpdateControlPositions(); ui::Menus.UpdateView(); // TorrentAddFilter() // Shows add new filter window. // wParam is a BOOL value that represents modal status. // lParam is the handle of the parent window. } else if (action == L"TorrentAddFilter") { if (!ui::DlgFeedFilter.IsWindow()) { ui::DlgFeedFilter.Create(IDD_FEED_FILTER, reinterpret_cast<HWND>(lParam), wParam != FALSE); } else { ActivateWindow(ui::DlgFeedFilter.GetWindowHandle()); } // ViewContent(page) // Selects a page from sidebar. } else if (action == L"ViewContent") { int page = ToInt(body); ui::DlgMain.navigation.SetCurrentPage(page); ////////////////////////////////////////////////////////////////////////////// // Library // AddToList(status) // Adds an anime to list with given status. // wParam is a BOOL value that defines lParam. // lParam is an anime ID, or a pointer to a vector of anime IDs. } else if (action == L"AddToList") { int status = ToInt(body); if (!wParam) { int anime_id = static_cast<int>(lParam); AnimeDatabase.AddToList(anime_id, status); } else { const auto& anime_ids = *reinterpret_cast<std::vector<int>*>(lParam); for (const auto& anime_id : anime_ids) { AnimeDatabase.AddToList(anime_id, status); } } // ClearHistory() // Deletes all history items. } else if (action == L"ClearHistory") { if (ui::OnHistoryClear()) History.Clear(); ////////////////////////////////////////////////////////////////////////////// // Tracker // AddFolder() // Opens up a dialog to add new library folder. } else if (action == L"AddFolder") { std::wstring path; if (win::BrowseForFolder(ui::GetWindowHandle(ui::kDialogMain), L"Add a Library Folder", L"", path)) { Settings.library_folders.push_back(path); if (Settings.GetBool(taiga::kLibrary_WatchFolders)) FolderMonitor.Enable(); ui::ShowDlgSettings(ui::kSettingsSectionLibrary, ui::kSettingsPageLibraryFolders); } // ScanEpisodes(), ScanEpisodesAll() // Checks episode availability. } else if (action == L"ScanEpisodes") { int anime_id = static_cast<int>(lParam); ScanAvailableEpisodes(false, anime_id, 0); } else if (action == L"ScanEpisodesAll") { ScanAvailableEpisodes(false); ////////////////////////////////////////////////////////////////////////////// // Settings // ToggleRecognition() // Enables or disables anime recognition. } else if (action == L"ToggleRecognition") { bool enable_recognition = Settings.Toggle(taiga::kApp_Option_EnableRecognition); if (enable_recognition) { ui::ChangeStatusText(L"Automatic anime recognition is now enabled."); CurrentEpisode.Set(anime::ID_UNKNOWN); } else { ui::ChangeStatusText(L"Automatic anime recognition is now disabled."); auto anime_item = AnimeDatabase.FindItem(CurrentEpisode.anime_id); CurrentEpisode.Set(anime::ID_NOTINLIST); if (anime_item) EndWatching(*anime_item, CurrentEpisode); } // ToggleSharing() // Enables or disables automatic sharing. } else if (action == L"ToggleSharing") { bool enable_sharing = Settings.Toggle(taiga::kApp_Option_EnableSharing); ui::Menus.UpdateTools(); if (enable_sharing) { ui::ChangeStatusText(L"Automatic sharing is now enabled."); } else { ui::ChangeStatusText(L"Automatic sharing is now disabled."); } // ToggleSynchronization() // Enables or disables automatic list synchronization. } else if (action == L"ToggleSynchronization") { bool enable_sync = Settings.Toggle(taiga::kApp_Option_EnableSync); ui::Menus.UpdateTools(); if (enable_sync) { ui::ChangeStatusText(L"Automatic synchronization is now enabled."); } else { ui::ChangeStatusText(L"Automatic synchronization is now disabled."); } ////////////////////////////////////////////////////////////////////////////// // Sharing // AnnounceToHTTP(force) // Sends an HTTP request. } else if (action == L"AnnounceToHTTP") { Announcer.Do(taiga::kAnnounceToHttp, nullptr, body == L"true"); // AnnounceToMIRC(force) // Sends message to specified channels in mIRC. } else if (action == L"AnnounceToMIRC") { Announcer.Do(taiga::kAnnounceToMirc, nullptr, body == L"true"); // AnnounceToSkype(force) // Changes Skype mood text. // Requires authorization. } else if (action == L"AnnounceToSkype") { Announcer.Do(taiga::kAnnounceToSkype, nullptr, body == L"true"); // AnnounceToTwitter(force) // Changes Twitter status. } else if (action == L"AnnounceToTwitter") { Announcer.Do(taiga::kAnnounceToTwitter, nullptr, body == L"true"); ////////////////////////////////////////////////////////////////////////////// // EditAll([anime_id]) // Shows a dialog to edit details of an anime. // lParam is an anime ID. } else if (action == L"EditAll") { int anime_id = body.empty() ? static_cast<int>(lParam) : ToInt(body); ui::ShowDlgAnimeEdit(anime_id); // EditDelete() // Removes an anime from list. // lParam is a pointer to a vector of anime IDs. } else if (action == L"EditDelete") { const auto& anime_ids = *reinterpret_cast<std::vector<int>*>(lParam); if (ui::OnLibraryEntriesEditDelete(anime_ids)) { for (const auto& anime_id : anime_ids) { HistoryItem history_item; history_item.anime_id = anime_id; history_item.mode = taiga::kHttpServiceDeleteLibraryEntry; History.queue.Add(history_item); } } // EditEpisode() // Changes watched episode value of an anime. // lParam is a pointer to a vector of anime IDs. } else if (action == L"EditEpisode") { const auto& anime_ids = *reinterpret_cast<std::vector<int>*>(lParam); int value = ui::OnLibraryEntriesEditEpisode(anime_ids); if (value > -1) { for (const auto& anime_id : anime_ids) { anime::ChangeEpisode(anime_id, value); } } // DecrementEpisode() // lParam is an anime ID. } else if (action == L"DecrementEpisode") { int anime_id = static_cast<int>(lParam); anime::DecrementEpisode(anime_id); // IncrementEpisode() // lParam is an anime ID. } else if (action == L"IncrementEpisode") { int anime_id = static_cast<int>(lParam); anime::IncrementEpisode(anime_id); // EditScore(value) // Changes anime score. // Value must be between 0-10 and different from current score. // lParam is a pointer to a vector of anime IDs. } else if (action == L"EditScore") { const auto& anime_ids = *reinterpret_cast<std::vector<int>*>(lParam); for (const auto& anime_id : anime_ids) { HistoryItem history_item; history_item.anime_id = anime_id; history_item.score = ToInt(body); history_item.mode = taiga::kHttpServiceUpdateLibraryEntry; History.queue.Add(history_item); } // EditStatus(value) // Changes anime status of user. // Value must be 1, 2, 3, 4 or 5, and different from current status. // lParam is a pointer to a vector of anime IDs. } else if (action == L"EditStatus") { const auto& anime_ids = *reinterpret_cast<std::vector<int>*>(lParam); for (const auto& anime_id : anime_ids) { HistoryItem history_item; history_item.status = ToInt(body); auto anime_item = AnimeDatabase.FindItem(anime_id); if (!anime_item) continue; switch (*history_item.status) { case anime::kCompleted: history_item.episode = anime_item->GetEpisodeCount(); if (*history_item.episode == 0) history_item.episode.Reset(); if (!anime::IsValidDate(anime_item->GetMyDateStart()) && anime_item->GetEpisodeCount() == 1) history_item.date_start = GetDate(); if (!anime::IsValidDate(anime_item->GetMyDateEnd())) history_item.date_finish = GetDate(); break; } history_item.anime_id = anime_id; history_item.mode = taiga::kHttpServiceUpdateLibraryEntry; History.queue.Add(history_item); } // EditTags(tags) // Changes anime tags. // Tags must be separated by a comma. // lParam is a pointer to a vector of anime IDs. } else if (action == L"EditTags") { const auto& anime_ids = *reinterpret_cast<std::vector<int>*>(lParam); std::wstring tags; if (ui::OnLibraryEntriesEditTags(anime_ids, tags)) { for (const auto& anime_id : anime_ids) { HistoryItem history_item; history_item.anime_id = anime_id; history_item.tags = tags; history_item.mode = taiga::kHttpServiceUpdateLibraryEntry; History.queue.Add(history_item); } } ////////////////////////////////////////////////////////////////////////////// // OpenFolder() // Searches for anime folder and opens it. // lParam is an anime ID. } else if (action == L"OpenFolder") { int anime_id = static_cast<int>(lParam); auto anime_item = AnimeDatabase.FindItem(anime_id); if (!anime_item || !anime_item->IsInList()) return; if (!anime::ValidateFolder(*anime_item)) ScanAvailableEpisodes(false, anime_item->GetId(), 0); if (anime_item->GetFolder().empty()) { if (ui::OnAnimeFolderNotFound()) { std::wstring default_path, path; if (!Settings.library_folders.empty()) default_path = Settings.library_folders.front(); if (win::BrowseForFolder(ui::GetWindowHandle(ui::kDialogMain), L"Select Anime Folder", default_path, path)) { anime_item->SetFolder(path); Settings.Save(); } } } ui::ClearStatusText(); if (!anime_item->GetFolder().empty()) { Execute(anime_item->GetFolder()); } ////////////////////////////////////////////////////////////////////////////// // PlayEpisode(value) // Searches for an episode of an anime and plays it. // lParam is an anime ID. } else if (action == L"PlayEpisode") { int number = ToInt(body); int anime_id = static_cast<int>(lParam); anime::PlayEpisode(anime_id, number); // PlayLast() // Searches for the last watched episode of an anime and plays it. // lParam is an anime ID. } else if (action == L"PlayLast") { int anime_id = static_cast<int>(lParam); anime::PlayLastEpisode(anime_id); // PlayNext([anime_id]) // Searches for the next episode of an anime and plays it. // lParam is an anime ID. } else if (action == L"PlayNext") { int anime_id = body.empty() ? static_cast<int>(lParam) : ToInt(body); if (anime::IsValidId(anime_id)) { anime::PlayNextEpisode(anime_id); } else { anime::PlayNextEpisodeOfLastWatchedAnime(); } // PlayRandom() // Searches for a random episode of an anime and plays it. // lParam is an anime ID. } else if (action == L"PlayRandom") { int anime_id = body.empty() ? static_cast<int>(lParam) : ToInt(body); anime::PlayRandomEpisode(anime_id); // PlayRandomAnime() // Searches for a random episode of a random anime and plays it. } else if (action == L"PlayRandomAnime") { anime::PlayRandomAnime(); ////////////////////////////////////////////////////////////////////////////// // Season_Load(file) // Loads season data. } else if (action == L"Season_Load") { if (SeasonDatabase.Load(body)) { SeasonDatabase.Review(); ui::DlgSeason.RefreshList(); ui::DlgSeason.RefreshStatus(); ui::DlgSeason.RefreshToolbar(); if (SeasonDatabase.IsRefreshRequired()) if (ui::OnSeasonRefreshRequired()) ui::DlgSeason.RefreshData(); } // Season_GroupBy(group) // Groups season data. } else if (action == L"Season_GroupBy") { ui::DlgSeason.group_by = ToInt(body); ui::DlgSeason.RefreshList(); ui::DlgSeason.RefreshToolbar(); // Season_SortBy(sort) // Sorts season data. } else if (action == L"Season_SortBy") { ui::DlgSeason.sort_by = ToInt(body); ui::DlgSeason.RefreshList(); ui::DlgSeason.RefreshToolbar(); // Season_RefreshItemData() // Refreshes an individual season item data. // lParam is a pointer to a vector of anime IDs. } else if (action == L"Season_RefreshItemData") { const auto& anime_ids = *reinterpret_cast<std::vector<int>*>(lParam); for (const auto& anime_id : anime_ids) { ui::DlgSeason.RefreshData(anime_id); } // Season_ViewAs(mode) // Changes view mode. } else if (action == L"Season_ViewAs") { ui::DlgSeason.SetViewMode(ToInt(body)); ui::DlgSeason.RefreshList(); ui::DlgSeason.RefreshToolbar(); // Unknown } else { LOG(LevelWarning, L"Unknown action: " + action); } }
bool EvaluateCondition(const FeedFilterCondition& condition, const FeedItem& item) { bool is_numeric = false; std::wstring element; std::wstring value = ReplaceVariables(condition.value, item.episode_data); auto anime = AnimeDatabase.FindItem(item.episode_data.anime_id); switch (condition.element) { case kFeedFilterElement_File_Title: element = item.title; break; case kFeedFilterElement_File_Category: element = item.category; break; case kFeedFilterElement_File_Description: element = item.description; break; case kFeedFilterElement_File_Link: element = item.link; break; case kFeedFilterElement_Meta_Id: if (anime) element = ToWstr(anime->GetId()); is_numeric = true; break; case kFeedFilterElement_Episode_Title: element = item.episode_data.title; break; case kFeedFilterElement_Meta_DateStart: if (anime) element = anime->GetDateStart(); break; case kFeedFilterElement_Meta_DateEnd: if (anime) element = anime->GetDateEnd(); break; case kFeedFilterElement_Meta_Episodes: if (anime) element = ToWstr(anime->GetEpisodeCount()); is_numeric = true; break; case kFeedFilterElement_Meta_Status: if (anime) element = ToWstr(anime->GetAiringStatus()); is_numeric = true; break; case kFeedFilterElement_Meta_Type: if (anime) element = ToWstr(anime->GetType()); is_numeric = true; break; case kFeedFilterElement_User_Status: if (anime) element = ToWstr(anime->GetMyStatus()); is_numeric = true; break; case kFeedFilterElement_Episode_Number: element = ToWstr(anime::GetEpisodeHigh(item.episode_data.number)); is_numeric = true; break; case kFeedFilterElement_Episode_Version: element = item.episode_data.version; if (element.empty()) element = L"1"; is_numeric = true; break; case kFeedFilterElement_Local_EpisodeAvailable: if (anime) element = ToWstr(anime->IsEpisodeAvailable( anime::GetEpisodeHigh(item.episode_data.number))); is_numeric = true; break; case kFeedFilterElement_Episode_Group: element = item.episode_data.group; break; case kFeedFilterElement_Episode_VideoResolution: element = item.episode_data.resolution; break; case kFeedFilterElement_Episode_VideoType: element = item.episode_data.video_type; break; } switch (condition.op) { case kFeedFilterOperator_Equals: if (is_numeric) { if (IsEqual(value, L"True")) return ToInt(element) == TRUE; return ToInt(element) == ToInt(value); } else { if (condition.element == kFeedFilterElement_Episode_VideoResolution) { return anime::TranslateResolution(element) == anime::TranslateResolution(condition.value); } else { return IsEqual(element, value); } } case kFeedFilterOperator_NotEquals: if (is_numeric) { if (IsEqual(value, L"True")) return ToInt(element) == TRUE; return ToInt(element) != ToInt(value); } else { if (condition.element == kFeedFilterElement_Episode_VideoResolution) { return anime::TranslateResolution(element) != anime::TranslateResolution(condition.value); } else { return !IsEqual(element, value); } } case kFeedFilterOperator_IsGreaterThan: if (is_numeric) { return ToInt(element) > ToInt(value); } else { if (condition.element == kFeedFilterElement_Episode_VideoResolution) { return anime::TranslateResolution(element) > anime::TranslateResolution(condition.value); } else { return CompareStrings(element, condition.value) > 0; } } case kFeedFilterOperator_IsGreaterThanOrEqualTo: if (is_numeric) { return ToInt(element) >= ToInt(value); } else { if (condition.element == kFeedFilterElement_Episode_VideoResolution) { return anime::TranslateResolution(element) >= anime::TranslateResolution(condition.value); } else { return CompareStrings(element, condition.value) >= 0; } } case kFeedFilterOperator_IsLessThan: if (is_numeric) { return ToInt(element) < ToInt(value); } else { if (condition.element == kFeedFilterElement_Episode_VideoResolution) { return anime::TranslateResolution(element) < anime::TranslateResolution(condition.value); } else { return CompareStrings(element, condition.value) < 0; } } case kFeedFilterOperator_IsLessThanOrEqualTo: if (is_numeric) { return ToInt(element) <= ToInt(value); } else { if (condition.element == kFeedFilterElement_Episode_VideoResolution) { return anime::TranslateResolution(element) <= anime::TranslateResolution(condition.value); } else { return CompareStrings(element, condition.value) <= 0; } } case kFeedFilterOperator_BeginsWith: return StartsWith(element, value); case kFeedFilterOperator_EndsWith: return EndsWith(element, value); case kFeedFilterOperator_Contains: return InStr(element, value, 0, true) > -1; case kFeedFilterOperator_NotContains: return InStr(element, value, 0, true) == -1; } return false; }