diff --git a/td/telegram/BackgroundManager.cpp b/td/telegram/BackgroundManager.cpp index c76477de1..369add8d6 100644 --- a/td/telegram/BackgroundManager.cpp +++ b/td/telegram/BackgroundManager.cpp @@ -397,46 +397,55 @@ static bool is_background_name_local(Slice name) { return name.size() <= 13u || name.find('?') <= 13u || !is_base64url_characters(name.substr(0, name.find('?'))); } -BackgroundId BackgroundManager::search_background(const string &name, Promise &&promise) { - auto it = name_to_background_id_.find(name); +std::pair BackgroundManager::search_background(const string &name, + Promise &&promise) { + auto params_pos = name.find('?'); + string slug = params_pos >= name.size() ? name : name.substr(0, params_pos); + auto it = name_to_background_id_.find(slug); if (it != name_to_background_id_.end()) { + CHECK(!is_background_name_local(slug)); + + const auto *background = get_background(it->second); + CHECK(background != nullptr); promise.set_value(Unit()); - return it->second; + BackgroundType type = background->type; + type.apply_parameters_from_link(name); + return {it->second, std::move(type)}; } - if (name.empty()) { + if (slug.empty()) { promise.set_error(Status::Error(400, "Background name must be non-empty")); - return BackgroundId(); + return {}; } - if (is_background_name_local(name)) { + if (is_background_name_local(slug)) { auto r_fill = BackgroundFill::get_background_fill(name); if (r_fill.is_error()) { promise.set_error(r_fill.move_as_error()); - return BackgroundId(); + return {}; } auto background_id = add_fill_background(r_fill.ok()); promise.set_value(Unit()); - return background_id; + return {background_id, BackgroundType(r_fill.ok())}; } - if (G()->parameters().use_file_db && loaded_from_database_backgrounds_.count(name) == 0) { - auto &queries = being_loaded_from_database_backgrounds_[name]; + if (G()->parameters().use_file_db && loaded_from_database_backgrounds_.count(slug) == 0) { + auto &queries = being_loaded_from_database_backgrounds_[slug]; queries.push_back(std::move(promise)); if (queries.size() == 1) { - LOG(INFO) << "Trying to load background " << name << " from database"; + LOG(INFO) << "Trying to load background " << slug << " from database"; G()->td_db()->get_sqlite_pmc()->get( - get_background_name_database_key(name), PromiseCreator::lambda([name](string value) { + get_background_name_database_key(slug), PromiseCreator::lambda([slug](string value) { send_closure(G()->background_manager(), &BackgroundManager::on_load_background_from_database, - std::move(name), std::move(value)); + std::move(slug), std::move(value)); })); } - return BackgroundId(); + return {}; } - reload_background_from_server(BackgroundId(), name, telegram_api::make_object(name), + reload_background_from_server(BackgroundId(), slug, telegram_api::make_object(slug), std::move(promise)); - return BackgroundId(); + return {}; } void BackgroundManager::on_load_background_from_database(string name, string value) { @@ -581,7 +590,7 @@ BackgroundId BackgroundManager::set_background(const td_api::InputBackground *in BackgroundId BackgroundManager::set_background(BackgroundId background_id, const BackgroundType &type, bool for_dark_theme, Promise &&promise) { LOG(INFO) << "Set " << background_id << " with " << type; - auto *background = get_background(background_id); + const auto *background = get_background(background_id); if (background == nullptr) { promise.set_error(Status::Error(400, "Background to set not found")); return BackgroundId(); @@ -721,7 +730,7 @@ void BackgroundManager::on_uploaded_background_file(FileId file_id, const Backgr return promise.set_error(Status::Error(500, "Receive wrong uploaded background")); } - auto background = get_background(background_id); + const auto *background = get_background(background_id); CHECK(background != nullptr); if (!background->file_id.is_valid()) { td_->file_manager_->cancel_upload(file_id); @@ -733,7 +742,7 @@ void BackgroundManager::on_uploaded_background_file(FileId file_id, const Backgr } void BackgroundManager::remove_background(BackgroundId background_id, Promise &&promise) { - auto background = get_background(background_id); + const auto *background = get_background(background_id); if (background == nullptr) { return promise.set_error(Status::Error(400, "Background not found")); } @@ -1001,18 +1010,21 @@ void BackgroundManager::on_get_backgrounds(Result BackgroundManager::get_background_object(BackgroundId background_id, - bool for_dark_theme) const { - auto background = get_background(background_id); + bool for_dark_theme, + const BackgroundType *type) const { + const auto *background = get_background(background_id); if (background == nullptr) { return nullptr; } - auto type = &background->type; - // first check another set_background_id to get correct type if both backgrounds are the same - if (background_id == set_background_id_[1 - static_cast(for_dark_theme)]) { - type = &set_background_type_[1 - static_cast(for_dark_theme)]; - } - if (background_id == set_background_id_[for_dark_theme]) { - type = &set_background_type_[for_dark_theme]; + if (type == nullptr) { + type = &background->type; + // first check another set_background_id to get correct type if both backgrounds are the same + if (background_id == set_background_id_[1 - static_cast(for_dark_theme)]) { + type = &set_background_type_[1 - static_cast(for_dark_theme)]; + } + if (background_id == set_background_id_[for_dark_theme]) { + type = &set_background_type_[for_dark_theme]; + } } return td_api::make_object( background->id.get(), background->is_default, background->is_dark, background->name, diff --git a/td/telegram/BackgroundManager.h b/td/telegram/BackgroundManager.h index 145c3de0e..b7930f174 100644 --- a/td/telegram/BackgroundManager.h +++ b/td/telegram/BackgroundManager.h @@ -40,7 +40,7 @@ class BackgroundManager : public Actor { void reload_background(BackgroundId background_id, int64 access_hash, Promise &&promise); - BackgroundId search_background(const string &name, Promise &&promise); + std::pair search_background(const string &name, Promise &&promise); BackgroundId set_background(const td_api::InputBackground *input_background, const td_api::BackgroundType *background_type, bool for_dark_theme, @@ -50,7 +50,8 @@ class BackgroundManager : public Actor { void reset_backgrounds(Promise &&promise); - td_api::object_ptr get_background_object(BackgroundId background_id, bool for_dark_theme) const; + td_api::object_ptr get_background_object(BackgroundId background_id, bool for_dark_theme, + const BackgroundType *type = nullptr) const; td_api::object_ptr get_backgrounds_object(bool for_dark_theme) const; diff --git a/td/telegram/BackgroundType.cpp b/td/telegram/BackgroundType.cpp index 9c6039373..4afb60322 100644 --- a/td/telegram/BackgroundType.cpp +++ b/td/telegram/BackgroundType.cpp @@ -6,6 +6,7 @@ // #include "td/telegram/BackgroundType.h" +#include "td/utils/HttpUrl.h" #include "td/utils/logging.h" #include "td/utils/misc.h" #include "td/utils/Slice.h" @@ -138,23 +139,28 @@ Result BackgroundFill::get_background_fill(Slice name) { return static_cast(r_color.ok()); }; + size_t hyphen_pos = name.find('-'); if (name.find('~') < name.size()) { vector color_strings = full_split(name, '~'); - if (color_strings.size() != 4 && color_strings.size() != 3) { - return Status::Error(400, "WALLPAPER_INVALID"); - } + CHECK(color_strings.size() >= 2); + if (color_strings.size() == 2) { + hyphen_pos = color_strings[0].size(); + } else { + if (color_strings.size() > 4) { + return Status::Error(400, "WALLPAPER_INVALID"); + } - TRY_RESULT(first_color, get_color(color_strings[0])); - TRY_RESULT(second_color, get_color(color_strings[1])); - TRY_RESULT(third_color, get_color(color_strings[2])); - int32 fourth_color = -1; - if (color_strings.size() == 4) { - TRY_RESULT_ASSIGN(fourth_color, get_color(color_strings[3])); + TRY_RESULT(first_color, get_color(color_strings[0])); + TRY_RESULT(second_color, get_color(color_strings[1])); + TRY_RESULT(third_color, get_color(color_strings[2])); + int32 fourth_color = -1; + if (color_strings.size() == 4) { + TRY_RESULT_ASSIGN(fourth_color, get_color(color_strings[3])); + } + return BackgroundFill(first_color, second_color, third_color, fourth_color); } - return BackgroundFill(first_color, second_color, third_color, fourth_color); } - size_t hyphen_pos = name.find('-'); if (hyphen_pos < name.size()) { TRY_RESULT(top_color, get_color(name.substr(0, hyphen_pos))); TRY_RESULT(bottom_color, get_color(name.substr(hyphen_pos + 1))); @@ -179,14 +185,9 @@ static string get_background_fill_color_hex_string(const BackgroundFill &fill, b switch (fill.get_type()) { case BackgroundFill::Type::Solid: return get_color_hex_string(fill.top_color); - case BackgroundFill::Type::Gradient: { - string colors = PSTRING() << get_color_hex_string(fill.top_color) << '-' - << get_color_hex_string(fill.bottom_color); - if (fill.rotation_angle != 0) { - colors += (PSTRING() << (is_first ? '?' : '&') << "rotation=" << fill.rotation_angle); - } - return colors; - } + case BackgroundFill::Type::Gradient: + return PSTRING() << get_color_hex_string(fill.top_color) << '-' << get_color_hex_string(fill.bottom_color) + << (is_first ? '?' : '&') << "rotation=" << fill.rotation_angle; case BackgroundFill::Type::FreeformGradient: { SliceBuilder sb; sb << get_color_hex_string(fill.top_color) << '~' << get_color_hex_string(fill.bottom_color) << '~' @@ -257,6 +258,42 @@ bool operator==(const BackgroundFill &lhs, const BackgroundFill &rhs) { lhs.fourth_color == rhs.fourth_color; } +void BackgroundType::apply_parameters_from_link(Slice name) { + const auto query = parse_url_query(name); + + is_blurred = false; + is_moving = false; + auto modes = full_split(query.get_arg("mode"), ' '); + for (auto &mode : modes) { + if (type != Type::Pattern && to_lower(mode) == "blur") { + is_blurred = true; + } + if (to_lower(mode) == "motion") { + is_moving = true; + } + } + + if (type == Type::Pattern) { + intensity = -1; + auto intensity_arg = query.get_arg("intensity"); + if (!intensity_arg.empty()) { + intensity = to_integer(intensity_arg); + } + if (!is_valid_intensity(intensity)) { + intensity = 50; + } + + auto bg_color = query.get_arg("bg_color"); + if (!bg_color.empty()) { + auto r_fill = BackgroundFill::get_background_fill( + PSLICE() << url_encode(bg_color) << "?rotation=" << url_encode(query.get_arg("rotation"))); + if (r_fill.is_ok()) { + fill = r_fill.move_as_ok(); + } + } + } +} + string BackgroundType::get_link() const { string mode; if (is_blurred) { diff --git a/td/telegram/BackgroundType.h b/td/telegram/BackgroundType.h index fc7c4a1f8..c2ecf72cf 100644 --- a/td/telegram/BackgroundType.h +++ b/td/telegram/BackgroundType.h @@ -78,6 +78,8 @@ struct BackgroundType { return type == Type::Wallpaper || type == Type::Pattern; } + void apply_parameters_from_link(Slice name); + string get_link() const; }; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index fcac4ac70..794261bed 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -2957,14 +2957,14 @@ class GetBackgroundsRequest : public RequestOnceActor { class SearchBackgroundRequest : public RequestActor<> { string name_; - BackgroundId background_id_; + std::pair background_; void do_run(Promise &&promise) override { - background_id_ = td->background_manager_->search_background(name_, std::move(promise)); + background_ = td->background_manager_->search_background(name_, std::move(promise)); } void do_send_result() override { - send_result(td->background_manager_->get_background_object(background_id_, false)); + send_result(td->background_manager_->get_background_object(background_.first, false, &background_.second)); } public: