std::wstring GetAbsoluteTimeString(time_t unix_time) { std::tm tm; if (!unix_time || localtime_s(&tm, &unix_time)) return L"Unknown"; Duration duration(std::abs(time(nullptr) - unix_time)); Date today = GetDate(); auto strftime = [&tm](const char* format) { std::string result(100, '\0'); std::strftime(&result.at(0), result.size(), format, &tm); return StrToWstr(result); }; if (1900 + tm.tm_year < today.year) { return strftime("%d %B %Y"); // 01 January 2014 } else if (std::lround(duration.days()) <= 1 && tm.tm_mday == today.day) { return strftime("%H:%M"); // 13:37 } else if (std::lround(duration.days()) <= 7) { return strftime("%A, %d %B"); // Thursday, 01 January } else { return strftime("%d %B"); // 01 January } }
std::wstring ConvertRfc822ToLocal(const std::wstring& datetime) { auto time = ConvertRfc822(datetime); std::tm local_tm = {0}; if (localtime_s(&local_tm, &time) != 0) return datetime; std::string result(100, '\0'); std::strftime(&result.at(0), result.size(), "%a, %d %b %Y %H:%M:%S", &local_tm); TIME_ZONE_INFORMATION time_zone_info = {0}; const auto time_zone_id = GetTimeZoneInformation(&time_zone_info); const auto bias = time_zone_info.Bias + time_zone_info.DaylightBias; std::wstring sign = bias <= 0 ? L"+" : L"-"; int hh = std::abs(bias) / 60; int mm = std::abs(bias) % 60; std::wstring result_with_tz = StrToWstr(result) + L" " + sign + PadChar(ToWstr(hh), L'0', 2) + PadChar(ToWstr(mm), L'0', 2); return result_with_tz; }
std::wstring Base64Encode(const std::wstring& str, bool for_filename) { std::wstring output = StrToWstr(Base64Encode(WstrToStr(str))); if (for_filename) ReplaceChar(output, '/', '-'); return output; }
void Service::ParseLibraryObject(Json::Value& value) { auto& anime_value = value["anime"]; auto& rating_value = value["rating"]; ::anime::Item anime_item; anime_item.SetSource(this->id()); anime_item.SetId(ToWstr(anime_value["id"].asInt()), this->id()); anime_item.SetLastModified(time(nullptr)); // current time int mal_id = value["mal_id"].asInt(); if (mal_id > 0) anime_item.SetId(ToWstr(mal_id), sync::kMyAnimeList); ParseAnimeObject(anime_value, anime_item); anime_item.AddtoUserList(); anime_item.SetMyLastWatchedEpisode(value["episodes_watched"].asInt()); anime_item.SetMyStatus(TranslateMyStatusFrom(StrToWstr(value["status"].asString()))); anime_item.SetMyRewatching(value["rewatching"].asBool()); anime_item.SetMyScore(TranslateMyRatingFrom(StrToWstr(rating_value["value"].asString()), StrToWstr(rating_value["type"].asString()))); AnimeDatabase.UpdateItem(anime_item); }
void Service::ParseAnimeObject(Json::Value& value, anime::Item& anime_item) { anime_item.SetSlug(StrToWstr(value["slug"].asString())); anime_item.SetAiringStatus(TranslateSeriesStatusFrom(StrToWstr(value["status"].asString()))); anime_item.SetTitle(StrToWstr(value["title"].asString())); anime_item.SetSynonyms(StrToWstr(value["alternate_title"].asString())); anime_item.SetEpisodeCount(value["episode_count"].asInt()); anime_item.SetImageUrl(StrToWstr(value["cover_image"].asString())); anime_item.SetSynopsis(StrToWstr(value["synopsis"].asString())); anime_item.SetType(TranslateSeriesTypeFrom(StrToWstr(value["show_type"].asString()))); std::vector<std::wstring> genres; auto& genres_value = value["genres"]; for (size_t i = 0; i < genres_value.size(); i++) genres.push_back(StrToWstr(genres_value[i]["name"].asString())); if (!genres.empty()) anime_item.SetGenres(genres); }
std::wstring GetRelativeTimeString(time_t unix_time) { if (!unix_time) return L"Unknown"; std::tm tm; if (localtime_s(&tm, &unix_time)) { return L"Unknown"; } std::wstring str; auto date_now = GetDate(); auto str_time = [](std::tm& tm, const char* format) { std::string result(100, '\0'); std::strftime(&result.at(0), result.size(), format, &tm); return StrToWstr(result); }; if (1900 + tm.tm_year < date_now.year) { str = Date(1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday); // YYYY-MM-DD } else if (tm.tm_mon + 1 < date_now.month) { str = str_time(tm, "%B %d"); // January 1 } else { time_t seconds = time(nullptr) - unix_time; if (seconds >= 60 * 60 * 24) { auto value = std::lround(static_cast<float>(seconds) / (60 * 60 * 24)); str = ToWstr(value) + (value == 1 ? L" day" : L" days"); } else if (seconds >= 60 * 60) { auto value = std::lround(static_cast<float>(seconds) / (60 * 60)); str = ToWstr(value) + (value == 1 ? L" hour" : L" hours"); } else if (seconds >= 60) { auto value = std::lround(static_cast<float>(seconds) / 60); str = ToWstr(value) + (value == 1 ? L" minute" : L" minutes"); } else { str = L"a moment"; } str += L" ago"; } return str; }
bool Service::RequestSucceeded(Response& response, const HttpResponse& http_response) { switch (http_response.code) { // OK case 200: case 201: return true; // Error default: { Json::Value root; Json::Reader reader; bool parsed = reader.parse(WstrToStr(http_response.body), root); response.data[L"error"] = name() + L" returned an error: "; if (parsed) { response.data[L"error"] += StrToWstr(root["error"].asString()); } else { response.data[L"error"] += L"Unknown error (" + ToWstr(static_cast<int>(http_response.code)) + L")"; } return false; } } }
void Service::ParseAnimeObjectV2(Json::Value& value, anime::Item& anime_item) { anime_item.SetSlug(StrToWstr(value["slug"].asString())); anime_item.SetTitle(StrToWstr(value["canonical_title"].asString())); anime_item.SetEnglishTitle(StrToWstr(value["english_title"].asString())); anime_item.SetSynonyms(StrToWstr(value["romaji_title"].asString())); anime_item.SetSynopsis(StrToWstr(value["synopsis"].asString())); anime_item.SetImageUrl(StrToWstr(value["poster_image"].asString())); anime_item.SetType(TranslateSeriesTypeFrom(StrToWstr(value["type"].asString()))); anime_item.SetDateStart(StrToWstr(value["started_airing"].asString())); anime_item.SetDateEnd(StrToWstr(value["finished_airing"].asString())); anime_item.SetScore(TranslateSeriesRatingFrom(value["community_rating"].asFloat())); anime_item.SetAgeRating(TranslateAgeRatingFrom(StrToWstr(value["age_rating"].asString()))); anime_item.SetEpisodeCount(value["episode_count"].asInt()); anime_item.SetEpisodeLength(value["episode_length"].asInt()); std::vector<std::wstring> genres; auto& genres_value = value["genres"]; for (size_t i = 0; i < genres_value.size(); i++) genres.push_back(StrToWstr(genres_value[i].asString())); if (!genres.empty()) anime_item.SetGenres(genres); }