Parse background parameters in searchBackground.

This commit is contained in:
levlam 2021-05-26 20:17:05 +03:00
parent afb58801ec
commit 3e0e9f5291
5 changed files with 104 additions and 52 deletions

View File

@ -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<Unit> &&promise) {
auto it = name_to_background_id_.find(name);
std::pair<BackgroundId, BackgroundType> BackgroundManager::search_background(const string &name,
Promise<Unit> &&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<telegram_api::inputWallPaperSlug>(name),
reload_background_from_server(BackgroundId(), slug, telegram_api::make_object<telegram_api::inputWallPaperSlug>(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<Unit> &&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<Unit> &&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<telegram_api::object_ptr<teleg
}
td_api::object_ptr<td_api::background> 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<int>(for_dark_theme)]) {
type = &set_background_type_[1 - static_cast<int>(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<int>(for_dark_theme)]) {
type = &set_background_type_[1 - static_cast<int>(for_dark_theme)];
}
if (background_id == set_background_id_[for_dark_theme]) {
type = &set_background_type_[for_dark_theme];
}
}
return td_api::make_object<td_api::background>(
background->id.get(), background->is_default, background->is_dark, background->name,

View File

@ -40,7 +40,7 @@ class BackgroundManager : public Actor {
void reload_background(BackgroundId background_id, int64 access_hash, Promise<Unit> &&promise);
BackgroundId search_background(const string &name, Promise<Unit> &&promise);
std::pair<BackgroundId, BackgroundType> search_background(const string &name, Promise<Unit> &&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<Unit> &&promise);
td_api::object_ptr<td_api::background> get_background_object(BackgroundId background_id, bool for_dark_theme) const;
td_api::object_ptr<td_api::background> get_background_object(BackgroundId background_id, bool for_dark_theme,
const BackgroundType *type = nullptr) const;
td_api::object_ptr<td_api::backgrounds> get_backgrounds_object(bool for_dark_theme) const;

View File

@ -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> BackgroundFill::get_background_fill(Slice name) {
return static_cast<int32>(r_color.ok());
};
size_t hyphen_pos = name.find('-');
if (name.find('~') < name.size()) {
vector<Slice> 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<int32>(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) {

View File

@ -78,6 +78,8 @@ struct BackgroundType {
return type == Type::Wallpaper || type == Type::Pattern;
}
void apply_parameters_from_link(Slice name);
string get_link() const;
};

View File

@ -2957,14 +2957,14 @@ class GetBackgroundsRequest : public RequestOnceActor {
class SearchBackgroundRequest : public RequestActor<> {
string name_;
BackgroundId background_id_;
std::pair<BackgroundId, BackgroundType> background_;
void do_run(Promise<Unit> &&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: