Etterna 0.75.1
Loading...
Searching...
No Matches
DownloadManager.h
1#pragma once
2#ifndef SM_DOWNMANAGER
3#define SM_DOWNMANAGER
4
5#include "Etterna/Globals/global.h"
6#include "RageUtil/File/RageFile.h"
7#include "Etterna/Models/HighScore/HighScore.h"
8#include "ScreenManager.h"
9#include "RageUtil/File/RageFileManager.h"
10#include "Etterna/Models/Misc/Difficulty.h"
11
12#include "curl/curl.h"
13#include "rapidjson/document.h"
14
15#include <deque>
16#include <unordered_set>
17#include <unordered_map>
18#include <math.h>
19
20class ScoreGoal;
22class RageTexture;
23
25{
26 public:
28 std::atomic<curl_off_t> total{ 0 };
30 std::atomic<curl_off_t> downloaded{ 0 };
32 float time{ 0 };
33};
34
36{
37 public:
38 RageFile file;
39 std::atomic<size_t> bytes{ 0 };
40 std::atomic<bool> stop{ false };
41};
42
44{
45 public:
47 std::string url,
48 std::string filename = "");
49 ~Download();
50 void Install();
51 void Update(float fDeltaSeconds);
52 void Failed();
53 std::string StartMessage()
54 {
55 auto str = "Downloading: " + m_TempFileName;
56 if (str.length() > 64) {
57 str = str.substr(0, 60) + "...";
58 }
59 return str;
60 };
61 std::string Status()
62 {
63 return m_TempFileName + "\n" + speed + " KB/s\n" + "Downloaded " +
64 std::to_string((progress.downloaded.load() > 0
65 ? progress.downloaded.load()
66 : p_RFWrapper.bytes.load()) /
67 1024) +
68 (progress.total.load() > 0
69 ? "/" + std::to_string(progress.total.load() / 1024) + " (KB)"
70 : "");
71 }
72 CURL* handle{ nullptr };
73 int running{ 1 };
74 ProgressData progress;
75 std::string speed{ "" };
76 curl_off_t downloadedAtLastUpdate{ 0 };
77 curl_off_t lastUpdateDone{ 0 };
78 std::string m_Url{ "" };
79 RageFileWrapper p_RFWrapper;
80 DownloadablePack* p_Pack{ nullptr };
81 std::string m_TempFileName{ "" };
82 // Lua
83 void PushSelf(lua_State* L);
84
85 protected:
86 std::string MakeTempFileName(std::string s);
87};
88
90{
91 public:
92 DownloadableImage(std::string url);
94 std::string m_Url{ "" };
95 std::string filename{ "" };
96 bool finished = false;
97 bool inProgress = false;
98 bool successful = false;
99
100 CURL* handle{ nullptr };
101 ProgressData progress;
102 RageFileWrapper p_RFWrapper;
103 std::vector<LuaReference> queuedLuaRefs{};
104};
105
107{
108 public:
109 std::string name{ "" };
110 int64_t size{ 0 };
111 int id{ 0 };
112 float avgDifficulty{ 0 };
113 int plays{ 0 };
114 int songs{ 0 };
115 bool nsfw{ false };
116 std::string url{ "" };
117 std::string mirror{ "" };
118 std::string bannerUrl{ "" };
119 std::string thumbnail{ "" };
120 bool downloading{ false };
121 bool isQueued();
122 RageTexture* GetThumbnailTexture();
123 // Lua
124 void PushSelf(lua_State* L);
125};
126
128{
129 public:
130 DownloadablePackPaginationKey(const std::string& searchString,
131 std::set<std::string>& tagFilters,
132 bool tagsMatchAny,
133 int perPage,
134 const std::string& sortField,
135 bool ascendingSort)
136 : searchString(searchString)
137 , tagFilters(tagFilters)
138 , tagsMatchAny(tagsMatchAny)
139 , perPage(perPage)
140 , sortByField(sortField)
141 , sortIsAsc(ascendingSort)
142 {
143 }
145 : searchString("")
146 , tagFilters({})
147 , tagsMatchAny(true)
148 , perPage(0)
149 , sortByField("")
150 , sortIsAsc(true)
151 {
152 }
153
154 bool operator==(const DownloadablePackPaginationKey& other) const
155 {
156 return (perPage == other.perPage) &&
157 (searchString == other.searchString) &&
158 (tagFilters == other.tagFilters) &&
159 (tagsMatchAny == other.tagsMatchAny) &&
160 (sortByField == other.sortByField) &&
161 (sortIsAsc == other.sortIsAsc);
162 }
163
164 std::string searchString{};
165 std::set<std::string> tagFilters{};
166 int perPage = 0;
167 std::string sortByField{};
168 bool sortIsAsc = true;
169 bool tagsMatchAny = true;
170};
171
173{
174 public:
175 DownloadablePackPagination(const std::string& searchString,
176 std::set<std::string>& tagFilters,
177 bool tagsMatchAny,
178 int perPage,
179 const std::string& sortByField,
180 bool sortIsAsc)
181 : key(searchString,
182 tagFilters,
183 tagsMatchAny,
184 perPage,
185 sortByField,
186 sortIsAsc)
187 {
188 }
190 : key(key)
191 {
192 }
194 : key({}) // ??
195 {
196 }
197
198 bool operator==(const DownloadablePackPagination& other)
199 {
200 // under normal circumstances no two paginations
201 // with the same key and different data
202 // should exist
203 return key == other.key;
204 }
205
207
208 int currentPage = 0;
209 int totalEntries = 0;
210 std::vector<DownloadablePack*> results{};
211
212 // if true, page can't move
213 bool pendingRequest = false;
214
215 // if true, a request was made and got no results
216 bool noResults = false;
217
218 bool initialized = false;
219
220 void initialize(LuaReference& whenDone = EMPTY_REFERENCE) {
221 setPage(0, whenDone);
222 }
223
224 // get the cached packs on the current page
225 std::vector<DownloadablePack*> get() {
226 auto it = results.begin();
227 if (results.size() > currentPageStartIndex()) {
228 // make sure the start iterator is valid
229 it += currentPageStartIndex();
230 }
231
232 std::vector<DownloadablePack*> o{};
233
234 while (it != results.end()) {
235 o.push_back(*it);
236 it++;
237 }
238 return o;
239 }
240
241 // get all the packs that are cached
242 std::vector<DownloadablePack*> getCache() { return results; }
243
244 // move to n page and send packs to lua function
245 // possibly invoking a search request
246 void setPage(int page, LuaReference& whenDone = EMPTY_REFERENCE);
247
248 // move to next page and send packs to lua function
249 // possibly invoking a search request
250 void nextPage(LuaReference& whenDone = EMPTY_REFERENCE)
251 {
252 setPage(getNextPageNbr(), whenDone);
253 }
254 // move to prev page and send packs to lua function
255 // possibly invoking a search request
256 void prevPage(LuaReference& whenDone = EMPTY_REFERENCE)
257 {
258 setPage(getPrevPageNbr(), whenDone);
259 }
260
261 // number of pages, so "1" has only a page "0"
262 int getTotalPages() {
263 return static_cast<int>(ceilf(static_cast<float>(totalEntries) /
264 static_cast<float>(key.perPage)));
265 }
266
267 // Lua
268 void PushSelf(lua_State* L);
269
270 private:
272 static LuaReference EMPTY_REFERENCE;
273
274 std::set<int> finishedPageRequests{};
275
276 // return inclusive starting index of page
277 int currentPageStartIndex() {
278 return key.perPage * currentPage;
279 }
280
281 int getNextPageNbr() {
282 if (key.perPage >= totalEntries) {
283 return 0;
284 }
285 if (currentPage == getTotalPages() - 1) {
286 return 0;
287 } else {
288 return currentPage + 1;
289 }
290 }
291 int getPrevPageNbr() {
292 if (key.perPage >= totalEntries) {
293 return 0;
294 }
295 if (currentPage == 0) {
296 return getTotalPages() - 1;
297 } else {
298 return currentPage - 1;
299 }
300 }
301
302 bool mustRequestPage(int page) {
303 const auto ind = key.perPage * page;
304 if (results.size() <= ind) {
305 // dont make requests out of range
306 return false;
307 }
308 // if null, need to request it
309 return results.at(ind) == nullptr;
310 }
311};
312
313// required to actually use the key as a key
314// in unordered containers
315template<>
317{
318 std::size_t operator()(const DownloadablePackPaginationKey& k) const {
319 size_t r = 17;
320 r = r * 31 + std::hash<int>()(k.perPage);
321 r = r * 31 + std::hash<std::string>()(k.searchString);
322 size_t s = 0;
323 for (const auto& tag : k.tagFilters) {
324 std::hash<std::string> h;
325 s ^= h(tag) + 0x9e3779b9 + (s << 6) + (s >> 2);
326 }
327 r = r * 31 + s;
328 r = r * 31 + std::hash<std::string>()(k.sortByField);
329 r = r * 31 + std::hash<bool>()(k.sortIsAsc);
330 r = r * 31 + std::hash<bool>()(k.tagsMatchAny);
331 return r;
332 }
333};
334
336{
337 // request body
338 std::string packName{};
339 std::string songName{};
340 std::string chartAuthor{};
341 std::string songArtist{};
342 std::vector<std::string> packTags{};
343 bool packTagsMatchAny = true;
344
345 std::string sortBy{};
346 bool sortIsAscending = true;
347
348 // request params (actual names)
349 int page = 0;
350 int per_page = 0;
351
352 auto DebugString() const -> std::string
353 {
354 std::string o = "(ApiSearchCriteria ";
355 o += fmt::format("page: {}, per_page: {}", page, per_page);
356 if (!packName.empty()) {
357 o += fmt::format(", packName: {}", packName);
358 }
359 if (!songName.empty()) {
360 o += fmt::format(", songName: {}", songName);
361 }
362 if (!chartAuthor.empty()) {
363 o += fmt::format(", chartAuthor: {}", chartAuthor);
364 }
365 if (!songArtist.empty()) {
366 o += fmt::format(", songArtist: {}", songArtist);
367 }
368 if (!packTags.empty()) {
369 o += fmt::format(", tags (matchAny={}): [", packTagsMatchAny);
370 for (auto& s : packTags) {
371 o += fmt::format("'{}'", s);
372 }
373 o += "]";
374 }
375 if (!sortBy.empty()) {
376 o += fmt::format(
377 ", sortBy: {}:{}", sortBy, sortIsAscending ? "asc" : "desc");
378 }
379 return o + ")";
380 }
381};
382
383
385{
386 public:
388 CURL* h,
389 std::function<void(HTTPRequest&)> done = [](HTTPRequest& req) {},
390 curl_httppost* postform = nullptr,
391 std::function<void(HTTPRequest&)> fail = [](HTTPRequest& req) {},
392 bool requiresLogin = false)
393 : handle(h)
394 , form(postform)
395 , Done(done)
396 , Failed(fail)
397 , requiresLogin(requiresLogin){};
398 long response_code{ 0 };
399 CURL* handle{ nullptr };
400 curl_httppost* form{ nullptr };
401 std::string result;
402 std::string headers;
403 std::function<void(HTTPRequest&)> Done;
404 std::function<void(HTTPRequest&)> Failed;
405 bool requiresLogin = false;
406};
407enum class RequestMethod
408{
409 GET = 0,
410 POST = 1,
411 PATCH = 2,
412 DEL = 3,
413};
415{
416 public:
417 float wifeScore{ 0.0f };
418 std::string songName;
419 float rate{ 0.0f };
420 float ssr{ 0.0f };
421 float overall{ 0.0f };
422 std::string chartkey;
423 std::string scorekey;
424 Difficulty difficulty;
425 std::string steps;
426 std::string modifiers;
427};
429{
430 public:
431 bool hasReplay;
432 bool HasReplayData() override { return hasReplay; }
433};
435{
436 public:
437 std::map<Skillset, float> SSRs;
438 float rate{ 0.0f };
439 float wife{ 0.0f };
440 int wifeversion{ 0 };
441 int maxcombo{ 0 };
442 int miss{ 0 };
443 int bad{ 0 };
444 int good{ 0 };
445 int great{ 0 };
446 int perfect{ 0 };
447 int marvelous{ 0 };
448 int minehits{ 0 };
449 int held{ 0 };
450 int holdmiss{ 0 };
451 std::string songId;
452 int letgo{ 0 };
453 bool valid{ false };
454 bool nocc{ false };
455 std::string username;
456 float playerRating{ 0.0f };
457 std::string modifiers;
458 std::string scoreid;
459 std::string avatar;
460 int userid;
461 DateTime datetime;
462 bool hasReplay{ false };
463 std::vector<std::pair<float, float>> replayData;
464 std::string countryCode;
466 void Push(lua_State* L) { hs.PushSelf(L); }
467 bool HasReplayData() { return hasReplay; }
468};
469
471{
472 // new
473 public:
476
478 // Upkeep
479 void Init();
480 void Update(float fDeltaSeconds);
481 void UpdatePacks(float fDeltaSeconds);
482 void UpdateHTTP(float fDeltaSeconds);
483 void UpdateGameplayState(bool gameplay);
484
486 // Lua external access
487 void PushSelf(lua_State* L);
488
490 // State getters
491 bool LoggedIn();
492 bool ShouldUploadScores();
493 bool InGameplay() { return gameplay; }
494
496 // External Facing API Request Generators
497 void Login(
498 const std::string& username,
499 const std::string& password,
500 std::function<void(bool)> done = [](bool loggedIn) {})
501 {
502 LoginRequest(username, password, done);
503 }
504 void LoginWithToken(
505 const std::string& sessionToken,
506 std::function<void(bool)> done = [](bool loggedIn) {});
507 void Logout();
508 void LogoutIfLoggedIn()
509 {
510 if (LoggedIn())
511 Logout();
512 }
513
514 void GetRankedChartkeys(
515 std::function<void(void)> callback = []() {},
516 const DateTime start = DateTime::GetFromString("1990-01-01 12:00:00"),
517 const DateTime end = DateTime::GetFromString("2100-01-01 12:00:00"))
518 {
519 GetRankedChartkeysRequest(callback, start, end);
520 }
521 void AddFavorite(const std::string& chartKey)
522 {
523 AddFavoriteRequest(chartKey);
524 }
525 void BulkAddFavorites(
526 std::vector<std::string> chartKeys,
527 std::function<void()> = []() {});
528 void RemoveFavorite(const std::string& chartKey)
529 {
530 RemoveFavoriteRequest(chartKey);
531 }
532 void RefreshFavorites(
533 const DateTime start = DateTime::GetFromString("1990-01-01 12:00:00"),
534 const DateTime end = DateTime::GetFromString("2100-01-01 12:00:00"));
535 void AddGoal(ScoreGoal* goal) {
536 AddGoalRequest(goal);
537 }
538 void BulkAddGoals(
539 std::vector<ScoreGoal*> goals,
540 std::function<void()> callback = []() {});
541 void UpdateGoal(ScoreGoal* goal) {
542 UpdateGoalRequest(goal);
543 }
544 void RemoveGoal(ScoreGoal* goal, bool oldGoal = false) {
545 RemoveGoalRequest(goal, oldGoal);
546 }
547 void RefreshGoals(
548 const DateTime start = DateTime::GetFromString("1990-01-01 12:00:00"),
549 const DateTime end = DateTime::GetFromString("2100-01-01 12:00:00"));
550 void AddPlaylist(const std::string& name) {
551 AddPlaylistRequest(name);
552 }
553 void UpdatePlaylist(const std::string& name)
554 {
555 UpdatePlaylistRequest(name);
556 }
557 void RemovePlaylist(const std::string& name)
558 {
559 RemovePlaylistRequest(name);
560 }
561 // the point of this is to maintain the online id of playlists
562 void LoadPlaylists(
563 const DateTime start = DateTime::GetFromString("1990-01-01 12:00:00"),
564 const DateTime end = DateTime::GetFromString("2100-01-01 12:00:00"));
565 void DownloadMissingPlaylists(
566 const DateTime start = DateTime::GetFromString("1990-01-01 12:00:00"),
567 const DateTime end = DateTime::GetFromString("2100-01-01 12:00:00"));
568 void DownloadPlaylist(const std::string& name);
569
570 // Score upload functions
571 void UploadScore(HighScore* hs,
572 std::function<void()> callback,
573 bool load_from_disk);
574 void UploadScoreWithReplayData(HighScore* hs);
575 void UploadScoreWithReplayDataFromDisk(
576 HighScore* hs,
577 std::function<void()> callback = []() {});
578 void UploadBulkScores(
579 std::vector<HighScore*> hsList,
580 std::function<void()> callback = []() {});
581
582 void RefreshPackTags();
583 void SearchForPacks(ApiSearchCriteria searchCriteria,
584 std::function<void(rapidjson::Document&)> packSearchParser)
585 {
586 MultiSearchRequest(searchCriteria, packSearchParser);
587 }
588
589 // Mass score upload functions
590 bool ForceUploadPBsForChart(const std::string& ck, bool startNow = false);
591 bool ForceUploadPBsForPack(const std::string& pack, bool startNow = false);
592 bool ForceUploadAllPBs();
593 bool InitialScoreSync();
594
595 void GetChartLeaderboard(const std::string& chartkey,
596 LuaReference& ref = EMPTY_REFERENCE)
597 {
598 GetChartLeaderboardRequest(chartkey, ref);
599 }
600 void GetReplayData(const std::string& scorekey,
601 int userid,
602 const std::string& username,
603 const std::string& chartkey,
604 LuaReference& callback = EMPTY_REFERENCE)
605 {
606 GetReplayDataRequest(scorekey, userid, username, chartkey, callback);
607 }
608
609 OnlineTopScore GetTopSkillsetScore(unsigned int rank,
610 Skillset ss,
611 bool& result);
612 float GetSkillsetRating(Skillset ss);
613 int GetSkillsetRank(Skillset ss);
614
615 DownloadablePackPagination& GetPackPagination(
616 const std::string& searchString,
617 std::set<std::string> tagFilters,
618 bool tagsMatchAny,
619 int perPage,
620 const std::string& sortBy,
621 bool sortIsAsc);
622 std::shared_ptr<Download> DownloadAndInstallPack(const std::string& url,
623 std::string filename = "");
624 std::shared_ptr<Download> DownloadAndInstallPack(DownloadablePack* pack,
625 bool mirror = false);
626
627 void DownloadCoreBundle(const std::string& bundlename, bool mirror = false);
628 std::vector<DownloadablePack*> GetCoreBundle(const std::string& bundlename);
629
630 void DownloadImage(const std::string& url,
631 LuaReference& callback = EMPTY_REFERENCE);
632
633 bool OpenSitePage(const std::string& path);
634 bool OpenProjectPage(const std::string& path);
635
636 bool ShowPackPage(int packid) {
637 return OpenSitePage(fmt::format("/packs/{}", packid));
638 }
639 bool ShowUserPage(const std::string& username){
640 return OpenSitePage(fmt::format("/users/{}", username));
641 }
642 bool ShowScorePage(const std::string& username, int scoreid)
643 {
644 return OpenSitePage(
645 fmt::format("/users/{}/scores/{}", username, scoreid));
646 }
647 bool ShowBugReportSite();
648 bool ShowEditorSite();
649 bool ShowProjectReleases() {
650 return OpenProjectPage("/releases");
651 }
652 bool ShowProjectSite() {
653 return OpenProjectPage("");
654 }
655
657 // User session
658 // Session cookie content
659 std::string authToken{ "" };
660 // Currently logged in username
661 std::string sessionUser{ "" };
662 // Leaderboard ranks for logged in user by skillset
663 std::map<Skillset, int> sessionRanks{};
664 // Online profile skillset ratings
665 std::map<Skillset, double> sessionRatings{};
666
668 // Score uploads
669 std::deque<HighScore*> ScoreUploadSequentialQueue;
670 unsigned int sequentialScoreUploadTotalWorkload{ 0 };
671
673 // Goal uploads
674 std::deque<ScoreGoal*> GoalUploadSequentialQueue;
675 unsigned int sequentialGoalUploadTotalWorkload{ 0 };
676
678 // Favorite uploads
679 std::deque<std::string> FavoriteUploadSequentialQueue;
680 unsigned int sequentialFavoriteUploadTotalWorkload{ 0 };
681
683 // Pack downloads
684 // Active downloads
685 std::map<std::string, std::shared_ptr<Download>> downloads;
686 // (pack,isMirror)
687 std::deque<std::pair<DownloadablePack*, bool>> DownloadQueue;
688 std::map<std::string, std::shared_ptr<Download>> finishedDownloads;
689 std::map<std::string, std::shared_ptr<Download>> pendingInstallDownloads;
690 std::map<int, DownloadablePack> downloadablePacks;
691 std::unordered_map<std::string, std::vector<std::string>> packTags;
692 std::unordered_map<DownloadablePackPaginationKey,
694 downloadablePackPaginations{};
695 // (tag_name, list of pack ids) -- we use this for bundles
696 std::unordered_map<std::string, std::set<int>> tagPacks;
697
699 // Chart leaderboards
700 std::map<std::string, std::vector<OnlineScore>> chartLeaderboards{};
701 std::map<Skillset, std::vector<OnlineTopScore>> topScores{};
702 std::set<std::string> unrankedCharts{};
703 bool currentrateonly = false;
704 bool topscoresonly = true;
705 bool validonly = true;
706
708 // Misc information
709 // Last version according to server (Or current if non was obtained)
710 std::string lastVersion{ "" };
711 std::string countryCode{ "" };
712
713 private:
714 // Events
715 void OnLogin();
716
717 // Checks for generic response codes where we have consistent behavior
718 // status 401 - log out the user, cancel uploads
719 bool HandleAuthErrorResponse(const std::string& endpoint, HTTPRequest& req);
720 // status 429 - requeue the request, wait a while
721 bool HandleRatelimitResponse(const std::string& endpoint, HTTPRequest& req);
722 bool QueueRequestIfRatelimited(const std::string& endpiont,
723 HTTPRequest& req);
724 void QueueRatelimitedRequest(const std::string& endpoint, HTTPRequest& req);
725 // basically returns HandleAuthErrorResponse || HandleRatelimitResponse
726 // and runs the given lambda for the 401 or the 429. Won't run the 429
727 // if a 401 is given first.
728 bool Handle401And429Response(
729 const std::string& endpoint,
730 HTTPRequest& req,
731 std::function<void()> if401 = []() {},
732 std::function<void()> if429 = []() {});
733
734
735 // Specialized API Requests
736 void LoginRequest(const std::string& username,
737 const std::string& password,
738 std::function<void(bool)> done);
739 void GetRankedChartkeysRequest(std::function<void(void)> callback,
740 const DateTime start,
741 const DateTime end);
742 void AddFavoriteRequest(const std::string& chartKey);
743 void RemoveFavoriteRequest(const std::string& chartKey);
744 void GetFavoritesRequest(
745 std::function<void(std::set<std::string>)> onSuccess,
746 const DateTime start,
747 const DateTime end);
748 void AddGoalRequest(ScoreGoal* goal);
749 void UpdateGoalRequest(ScoreGoal* goal);
750 void RemoveGoalRequest(ScoreGoal* goal, bool oldGoal);
751 void GetGoalsRequest(std::function<void(std::vector<ScoreGoal>)> onSuccess,
752 const DateTime start,
753 const DateTime end);
754 void AddPlaylistRequest(const std::string& name);
755 void UpdatePlaylistRequest(const std::string& name);
756 void RemovePlaylistRequest(const std::string& name);
757 void GetPlaylistsRequest(
758 std::function<void(std::unordered_map<std::string, Playlist>)> onSuccess,
759 const DateTime start,
760 const DateTime end);
761 void GetPlaylistRequest(std::function<void(Playlist)> onSuccess, int id);
762 void GetChartLeaderboardRequest(const std::string& chartkey,
763 LuaReference& ref);
764 void GetReplayDataRequest(const std::string& scorekey,
765 int userid,
766 const std::string& username,
767 const std::string& chartkey,
768 LuaReference& callback);
769
770 void RefreshUserData();
771 void RequestTop25(Skillset ss);
772 void RefreshLastVersion();
773
774 void GetPackTagsRequest();
775 void CachePacksForTag(const std::string& tag);
776
777 void MultiSearchRequest(ApiSearchCriteria searchCriteria,
778 std::function<void(rapidjson::Document&)> whenDoneParser);
779
780 // To send a request to API base URL and ratelimit at that URL
781 HTTPRequest* SendRequest(
782 std::string requestName,
783 std::vector<std::pair<std::string, std::string>> params,
784 std::function<void(HTTPRequest&)> done,
785 bool requireLogin = true,
786 RequestMethod httpMethod = RequestMethod::GET,
787 bool compressed = false,
788 bool async = true,
789 bool withBearer = true);
790 // To send a request to API based URL, ratelimit at different path
791 HTTPRequest* SendRequest(
792 std::string requestName,
793 std::string apiPath,
794 std::vector<std::pair<std::string, std::string>> params,
795 std::function<void(HTTPRequest&)> done,
796 bool requireLogin = true,
797 RequestMethod httpMethod = RequestMethod::GET,
798 bool compressed = false,
799 bool async = true,
800 bool withBearer = true);
801 // Send a request directly to a given URL, ratelimit at other path
802 HTTPRequest* SendRequestToURL(
803 std::string url,
804 std::string apiPath,
805 std::vector<std::pair<std::string, std::string>> params,
806 std::function<void(HTTPRequest&)> done,
807 bool requireLogin,
808 RequestMethod httpMethod,
809 bool compressed,
810 bool async,
811 bool withBearer);
812
813 // Active HTTP requests (async, curlMulti)
814 std::vector<HTTPRequest*> HTTPRequests;
815
816 CURLM* pack_multi_handle = nullptr;
817 CURLM* http_req_handle = nullptr;
818
819 // Currently logging in (Since it's async, to not try twice)
820 bool loggingIn{ false };
821 // Currently in gameplay y/n
822 bool gameplay{ false };
823 bool initialized{ false };
824
825 float timeSinceLastDownload = 0.F;
826
827 std::unordered_map<std::string, std::chrono::steady_clock::time_point>
828 endpointRatelimitTimestamps{};
829 std::unordered_map<std::string, std::vector<HTTPRequest*>>
830 ratelimitedRequestQueue{};
831 std::unordered_set<std::string> newlyRankedChartkeys{};
832
833 std::unordered_map<std::string, DownloadableImage*> downloadableImages{};
834
835
836 // old
837 public:
838
839 void RefreshPackList(const std::string& url);
840};
841
842extern std::shared_ptr<DownloadManager> DLMAN;
843
844#endif
Definition DownloadManager.h:471
void RefreshPackList(const std::string &url)
Definition DownloadManager.cpp:5564
Definition DownloadManager.h:44
Definition DownloadManager.h:90
Definition DownloadManager.h:128
Definition DownloadManager.h:173
Definition DownloadManager.h:107
Definition DownloadManager.h:385
A self-cleaning Lua reference.
Definition LuaReference.h:10
Definition DownloadManager.h:435
Definition DownloadManager.h:415
Definition DownloadManager.h:25
float time
seconds passed
Definition DownloadManager.h:32
std::atomic< curl_off_t > total
total bytes
Definition DownloadManager.h:28
std::atomic< curl_off_t > downloaded
bytes downloaded
Definition DownloadManager.h:30
Definition DownloadManager.h:36
High-level file access.
Definition RageFile.h:16
Definition RageTexture.h:14
Definition Profile.h:67
Definition DownloadManager.h:336
A standard way of determining the date and the time.
Definition DateTime.h:81
The high score that is earned by a player.
Definition HighScore.h:18
Definition DownloadManager.h:429
Definition Difficulty.h:63