295 lines
		
	
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			295 lines
		
	
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
This file is part of Telegram Desktop,
 | 
						|
the official desktop application for the Telegram messaging service.
 | 
						|
 | 
						|
For license and copyright information please follow this link:
 | 
						|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
						|
*/
 | 
						|
#include "core/local_url_handlers.h"
 | 
						|
 | 
						|
#include "base/qthelp_regex.h"
 | 
						|
#include "base/qthelp_url.h"
 | 
						|
#include "lang/lang_cloud_manager.h"
 | 
						|
#include "lang/lang_keys.h"
 | 
						|
#include "core/update_checker.h"
 | 
						|
#include "boxes/confirm_phone_box.h"
 | 
						|
#include "boxes/confirm_box.h"
 | 
						|
#include "boxes/share_box.h"
 | 
						|
#include "boxes/connection_box.h"
 | 
						|
#include "boxes/sticker_set_box.h"
 | 
						|
#include "passport/passport_form_controller.h"
 | 
						|
#include "window/window_controller.h"
 | 
						|
#include "mainwindow.h"
 | 
						|
#include "mainwidget.h"
 | 
						|
#include "messenger.h"
 | 
						|
#include "auth_session.h"
 | 
						|
#include "apiwrap.h"
 | 
						|
 | 
						|
namespace Core {
 | 
						|
namespace {
 | 
						|
 | 
						|
using Match = qthelp::RegularExpressionMatch;
 | 
						|
 | 
						|
bool JoinGroupByHash(const Match &match, const QVariant &context) {
 | 
						|
	if (!AuthSession::Exists()) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	const auto hash = match->captured(1);
 | 
						|
	Auth().api().checkChatInvite(hash, [=](const MTPChatInvite &result) {
 | 
						|
		Messenger::Instance().hideMediaView();
 | 
						|
		result.match([=](const MTPDchatInvite &data) {
 | 
						|
			Ui::show(Box<ConfirmInviteBox>(data, [=] {
 | 
						|
				Auth().api().importChatInvite(hash);
 | 
						|
			}));
 | 
						|
		}, [=](const MTPDchatInviteAlready &data) {
 | 
						|
			if (const auto chat = App::feedChat(data.vchat)) {
 | 
						|
				App::wnd()->controller()->showPeerHistory(
 | 
						|
					chat,
 | 
						|
					Window::SectionShow::Way::Forward);
 | 
						|
			}
 | 
						|
		});
 | 
						|
	}, [=](const RPCError &error) {
 | 
						|
		if (error.code() != 400) {
 | 
						|
			return;
 | 
						|
		}
 | 
						|
		Messenger::Instance().hideMediaView();
 | 
						|
		Ui::show(Box<InformBox>(lang(lng_group_invite_bad_link)));
 | 
						|
	});
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool ShowStickerSet(const Match &match, const QVariant &context) {
 | 
						|
	if (!AuthSession::Exists()) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	Messenger::Instance().hideMediaView();
 | 
						|
	Ui::show(Box<StickerSetBox>(
 | 
						|
		MTP_inputStickerSetShortName(MTP_string(match->captured(1)))));
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool SetLanguage(const Match &match, const QVariant &context) {
 | 
						|
	const auto languageId = match->captured(1);
 | 
						|
	Lang::CurrentCloudManager().switchWithWarning(languageId);
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool ShareUrl(const Match &match, const QVariant &context) {
 | 
						|
	if (!AuthSession::Exists()) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	auto params = url_parse_params(
 | 
						|
		match->captured(1),
 | 
						|
		qthelp::UrlParamNameTransform::ToLower);
 | 
						|
	auto url = params.value(qsl("url"));
 | 
						|
	if (url.isEmpty()) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	App::main()->shareUrlLayer(url, params.value("text"));
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool ConfirmPhone(const Match &match, const QVariant &context) {
 | 
						|
	if (!AuthSession::Exists()) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	auto params = url_parse_params(
 | 
						|
		match->captured(1),
 | 
						|
		qthelp::UrlParamNameTransform::ToLower);
 | 
						|
	auto phone = params.value(qsl("phone"));
 | 
						|
	auto hash = params.value(qsl("hash"));
 | 
						|
	if (phone.isEmpty() || hash.isEmpty()) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	ConfirmPhoneBox::start(phone, hash);
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool ShareGameScore(const Match &match, const QVariant &context) {
 | 
						|
	if (!AuthSession::Exists()) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	const auto params = url_parse_params(
 | 
						|
		match->captured(1),
 | 
						|
		qthelp::UrlParamNameTransform::ToLower);
 | 
						|
	ShareGameScoreByHash(params.value(qsl("hash")));
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool ApplySocksProxy(const Match &match, const QVariant &context) {
 | 
						|
	auto params = url_parse_params(
 | 
						|
		match->captured(1),
 | 
						|
		qthelp::UrlParamNameTransform::ToLower);
 | 
						|
	ProxiesBoxController::ShowApplyConfirmation(ProxyData::Type::Socks5, params);
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool ApplyMtprotoProxy(const Match &match, const QVariant &context) {
 | 
						|
	auto params = url_parse_params(
 | 
						|
		match->captured(1),
 | 
						|
		qthelp::UrlParamNameTransform::ToLower);
 | 
						|
	ProxiesBoxController::ShowApplyConfirmation(ProxyData::Type::Mtproto, params);
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool ShowPassportForm(const QMap<QString, QString> ¶ms) {
 | 
						|
	const auto botId = params.value("bot_id", QString()).toInt();
 | 
						|
	const auto scope = params.value("scope", QString());
 | 
						|
	const auto callback = params.value("callback_url", QString());
 | 
						|
	const auto publicKey = params.value("public_key", QString());
 | 
						|
	const auto nonce = params.value(
 | 
						|
		Passport::NonceNameByScope(scope),
 | 
						|
		QString());
 | 
						|
	const auto errors = params.value("errors", QString());
 | 
						|
	if (const auto window = App::wnd()) {
 | 
						|
		if (const auto controller = window->controller()) {
 | 
						|
			controller->showPassportForm(Passport::FormRequest(
 | 
						|
				botId,
 | 
						|
				scope,
 | 
						|
				callback,
 | 
						|
				publicKey,
 | 
						|
				nonce,
 | 
						|
				errors));
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
bool ShowPassport(const Match &match, const QVariant &context) {
 | 
						|
	return ShowPassportForm(url_parse_params(
 | 
						|
		match->captured(1),
 | 
						|
		qthelp::UrlParamNameTransform::ToLower));
 | 
						|
}
 | 
						|
 | 
						|
bool ResolveUsername(const Match &match, const QVariant &context) {
 | 
						|
	if (!AuthSession::Exists()) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	auto params = url_parse_params(
 | 
						|
		match->captured(1),
 | 
						|
		qthelp::UrlParamNameTransform::ToLower);
 | 
						|
	const auto domain = params.value(qsl("domain"));
 | 
						|
	const auto valid = [](const QString &domain) {
 | 
						|
		return qthelp::regex_match(
 | 
						|
			qsl("^[a-zA-Z0-9\\.\\_]+$"),
 | 
						|
			domain,
 | 
						|
			{}
 | 
						|
		).valid();
 | 
						|
	};
 | 
						|
	if (domain == qsl("telegrampassport")) {
 | 
						|
		return ShowPassportForm(params);
 | 
						|
	} else if (!valid(domain)) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	auto start = qsl("start");
 | 
						|
	auto startToken = params.value(start);
 | 
						|
	if (startToken.isEmpty()) {
 | 
						|
		start = qsl("startgroup");
 | 
						|
		startToken = params.value(start);
 | 
						|
		if (startToken.isEmpty()) {
 | 
						|
			start = QString();
 | 
						|
		}
 | 
						|
	}
 | 
						|
	auto post = (start == qsl("startgroup")) ? ShowAtProfileMsgId : ShowAtUnreadMsgId;
 | 
						|
	auto postParam = params.value(qsl("post"));
 | 
						|
	if (auto postId = postParam.toInt()) {
 | 
						|
		post = postId;
 | 
						|
	}
 | 
						|
	auto gameParam = params.value(qsl("game"));
 | 
						|
	if (!gameParam.isEmpty() && valid(gameParam)) {
 | 
						|
		startToken = gameParam;
 | 
						|
		post = ShowAtGameShareMsgId;
 | 
						|
	}
 | 
						|
	const auto clickFromMessageId = context.value<FullMsgId>();
 | 
						|
	App::main()->openPeerByName(
 | 
						|
		domain,
 | 
						|
		post,
 | 
						|
		startToken,
 | 
						|
		clickFromMessageId);
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool HandleUnknown(const Match &match, const QVariant &context) {
 | 
						|
	if (!AuthSession::Exists()) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	const auto request = match->captured(1);
 | 
						|
	const auto callback = [=](const MTPDhelp_deepLinkInfo &result) {
 | 
						|
		const auto text = TextWithEntities{
 | 
						|
			qs(result.vmessage),
 | 
						|
			(result.has_entities()
 | 
						|
				? TextUtilities::EntitiesFromMTP(result.ventities.v)
 | 
						|
				: EntitiesInText())
 | 
						|
		};
 | 
						|
		if (result.is_update_app()) {
 | 
						|
			const auto box = std::make_shared<QPointer<BoxContent>>();
 | 
						|
			const auto callback = [=] {
 | 
						|
				Core::UpdateApplication();
 | 
						|
				if (*box) (*box)->closeBox();
 | 
						|
			};
 | 
						|
			*box = Ui::show(Box<ConfirmBox>(
 | 
						|
				text,
 | 
						|
				lang(lng_menu_update),
 | 
						|
				callback));
 | 
						|
		} else {
 | 
						|
			Ui::show(Box<InformBox>(text));
 | 
						|
		}
 | 
						|
	};
 | 
						|
	Auth().api().requestDeepLinkInfo(request, callback);
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
} // namespace
 | 
						|
 | 
						|
const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
 | 
						|
	static auto Result = std::vector<LocalUrlHandler>{
 | 
						|
		{
 | 
						|
			qsl("^join/?\\?invite=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"),
 | 
						|
			JoinGroupByHash
 | 
						|
		},
 | 
						|
		{
 | 
						|
			qsl("^addstickers/?\\?set=([a-zA-Z0-9\\.\\_]+)(&|$)"),
 | 
						|
			ShowStickerSet
 | 
						|
		},
 | 
						|
		{
 | 
						|
			qsl("^setlanguage/?\\?lang=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"),
 | 
						|
			SetLanguage
 | 
						|
		},
 | 
						|
		{
 | 
						|
			qsl("^msg_url/?\\?(.+)(#|$)"),
 | 
						|
			ShareUrl
 | 
						|
		},
 | 
						|
		{
 | 
						|
			qsl("^confirmphone/?\\?(.+)(#|$)"),
 | 
						|
			ConfirmPhone
 | 
						|
		},
 | 
						|
		{
 | 
						|
			qsl("^share_game_score/?\\?(.+)(#|$)"),
 | 
						|
			ShareGameScore
 | 
						|
		},
 | 
						|
		{
 | 
						|
			qsl("^socks/?\\?(.+)(#|$)"),
 | 
						|
			ApplySocksProxy
 | 
						|
		},
 | 
						|
		{
 | 
						|
			qsl("^proxy/?\\?(.+)(#|$)"),
 | 
						|
			ApplyMtprotoProxy
 | 
						|
		},
 | 
						|
		{
 | 
						|
			qsl("^passport/?\\?(.+)(#|$)"),
 | 
						|
			ShowPassport
 | 
						|
		},
 | 
						|
		{
 | 
						|
			qsl("^resolve/?\\?(.+)(#|$)"),
 | 
						|
			ResolveUsername
 | 
						|
		},
 | 
						|
		{
 | 
						|
			qsl("^([^\\?]+)(\\?|#|$)"),
 | 
						|
			HandleUnknown
 | 
						|
		}
 | 
						|
	};
 | 
						|
	return Result;
 | 
						|
}
 | 
						|
 | 
						|
} // namespace Core
 |