diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index f356cc219..be6f42516 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -599,8 +599,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 "lng_channel_not_accessible" = "Sorry, this channel is not accessible.";
 "lng_group_not_accessible" = "Sorry, this group is not accessible.";
 
-"lng_channels_too_much_public_existing" = "Sorry, you have created too many public channels already. Please delete one first.";
-"lng_channels_too_much_public" = "Sorry, you have created too many public channels.\n\nYou can either create a private channel\nor delete one of your public channels first.";
+"lng_channels_too_much_public_about" = "Sorry, you have reserved too many public usernames. You can revoke the link from one of your older groups or channels.";
+"lng_channels_too_much_public_revoke_confirm_group" = "Are you sure you want to revoke the link {link}?\n\nThe group «{group}» will become private.";
+"lng_channels_too_much_public_revoke_confirm_channel" = "Are you sure you want to revoke the link {link}?\n\nThe channel «{group}» will become private.";
+"lng_channels_too_much_public_revoke" = "Revoke";
 
 "lng_group_invite_bad_link" = "This invite link is broken or has expired.";
 "lng_group_invite_want_join" = "Do you want to join the group «{title}»?";
diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp
index 5f5086f4f..0f7acc35a 100644
--- a/Telegram/SourceFiles/apiwrap.cpp
+++ b/Telegram/SourceFiles/apiwrap.cpp
@@ -453,7 +453,10 @@ void ApiWrap::gotUser(PeerData *peer, const MTPVector<MTPUser> &result) {
 }
 
 void ApiWrap::gotChats(const MTPmessages_Chats &result) {
-	App::feedChats(result.c_messages_chats().vchats);
+	if (result.type() == mtpc_messages_chats) {
+		auto &d = result.c_messages_chats();
+		App::feedChats(d.vchats);
+	}
 }
 
 void ApiWrap::gotUsers(const MTPVector<MTPUser> &result) {
diff --git a/Telegram/SourceFiles/boxes/addcontactbox.cpp b/Telegram/SourceFiles/boxes/addcontactbox.cpp
index e5274942d..1ece3dedc 100644
--- a/Telegram/SourceFiles/boxes/addcontactbox.cpp
+++ b/Telegram/SourceFiles/boxes/addcontactbox.cpp
@@ -31,6 +31,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 #include "mainwindow.h"
 #include "apiwrap.h"
 #include "observer_peer.h"
+#include "styles/style_boxes.h"
 
 AddContactBox::AddContactBox(QString fname, QString lname, QString phone) : AbstractBox(st::boxWidth)
 , _save(this, lang(lng_add_contact), st::defaultBoxButton)
@@ -611,9 +612,6 @@ SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : Abstract
 , _linkOver(false)
 , _save(this, lang(lng_settings_save), st::defaultBoxButton)
 , _skip(this, lang(existing ? lng_cancel : lng_create_group_skip), st::cancelBoxButton)
-, _tooMuchUsernames(false)
-, _saveRequestId(0)
-, _checkRequestId(0)
 , a_goodOpacity(0, 0)
 , _a_goodFade(animation(this, &SetupChannelBox::step_goodFade)) {
 	setMouseTracking(true);
@@ -747,7 +745,6 @@ void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) {
 }
 
 void SetupChannelBox::mousePressEvent(QMouseEvent *e) {
-	mouseMoveEvent(e);
 	if (_linkOver) {
 		Application::clipboard()->setText(_channel->inviteLink());
 		_goodTextLink = lang(lng_create_channel_link_copied);
@@ -863,7 +860,12 @@ void SetupChannelBox::onPrivacyChange() {
 	if (_public.checked()) {
 		if (_tooMuchUsernames) {
 			_private.setChecked(true);
-			Ui::showLayer(new InformBox(lang(lng_channels_too_much_public)), KeepOtherLayers);
+			Ui::showLayer(new RevokePublicLinkBox([this, weak_this = weakThis()]() {
+				if (!weak_this) return;
+				_tooMuchUsernames = false;
+				_public.setChecked(true);
+				onCheck();
+			}), KeepOtherLayers);
 			return;
 		}
 		_link.show();
@@ -930,7 +932,7 @@ bool SetupChannelBox::onCheckFail(const RPCError &error) {
 		return true;
 	} else if (err == qstr("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) {
 		if (_existing) {
-			Ui::showLayer(new InformBox(lang(lng_channels_too_much_public_existing)));
+			showRevokePublicLinkBoxForEdit();
 		} else {
 			_tooMuchUsernames = true;
 			_private.setChecked(true);
@@ -951,6 +953,13 @@ bool SetupChannelBox::onCheckFail(const RPCError &error) {
 	return true;
 }
 
+void SetupChannelBox::showRevokePublicLinkBoxForEdit() {
+	onClose();
+	Ui::showLayer(new RevokePublicLinkBox([channel = _channel, existing = _existing]() {
+		Ui::showLayer(new SetupChannelBox(channel, existing), KeepOtherLayers);
+	}), KeepOtherLayers);
+}
+
 bool SetupChannelBox::onFirstCheckFail(const RPCError &error) {
 	if (MTP::isDefaultHandledError(error)) return false;
 
@@ -961,7 +970,7 @@ bool SetupChannelBox::onFirstCheckFail(const RPCError &error) {
 		return true;
 	} else if (err == qstr("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) {
 		if (_existing) {
-			Ui::showLayer(new InformBox(lang(lng_channels_too_much_public_existing)));
+			showRevokePublicLinkBoxForEdit();
 		} else {
 			_tooMuchUsernames = true;
 			_private.setChecked(true);
@@ -1382,3 +1391,157 @@ void EditChannelBox::onSaveSignDone(const MTPUpdates &updates) {
 	onClose();
 }
 
+RevokePublicLinkBox::RevokePublicLinkBox(base::lambda_unique<void()> &&revokeCallback) : AbstractBox()
+, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
+, _revokeWidth(st::normalFont->width(lang(lng_channels_too_much_public_revoke)))
+, _aboutRevoke(this, lang(lng_channels_too_much_public_about), FlatLabel::InitType::Simple, st::aboutRevokePublicLabel)
+, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
+, _revokeCallback(std::move(revokeCallback)) {
+	setMouseTracking(true);
+
+	MTP::send(MTPchannels_GetAdminedPublicChannels(), rpcDone(&RevokePublicLinkBox::getPublicDone), rpcFail(&RevokePublicLinkBox::getPublicFail));
+
+	updateMaxHeight();
+
+	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
+	connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
+
+	prepare();
+}
+
+void RevokePublicLinkBox::updateMaxHeight() {
+	_rowsTop = st::boxPadding.top() + _aboutRevoke->height() + st::boxPadding.top();
+	setMaxHeight(_rowsTop + (5 * _rowHeight) + st::boxButtonPadding.top() + _cancel->height() + st::boxButtonPadding.bottom());
+}
+
+void RevokePublicLinkBox::mouseMoveEvent(QMouseEvent *e) {
+	updateSelected();
+}
+
+void RevokePublicLinkBox::updateSelected() {
+	auto point = mapFromGlobal(QCursor::pos());
+	PeerData *selected = nullptr;
+	auto top = _rowsTop;
+	for_const (auto &row, _rows) {
+		auto revokeLink = rtlrect(width() - st::contactsPadding.right() - st::contactsCheckPosition.x() - _revokeWidth, top + st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, _revokeWidth, st::normalFont->height, width());
+		if (revokeLink.contains(point)) {
+			selected = row.peer;
+			break;
+		}
+		top += _rowHeight;
+	}
+	if (selected != _selected) {
+		_selected = selected;
+		setCursor((_selected || _pressed) ? style::cur_pointer : style::cur_default);
+		update();
+	}
+}
+
+void RevokePublicLinkBox::mousePressEvent(QMouseEvent *e) {
+	if (_pressed != _selected) {
+		_pressed = _selected;
+		update();
+	}
+}
+
+void RevokePublicLinkBox::mouseReleaseEvent(QMouseEvent *e) {
+	auto pressed = createAndSwap(_pressed);
+	setCursor((_selected || _pressed) ? style::cur_pointer : style::cur_default);
+	if (pressed == _selected) {
+		auto text_method = pressed->isMegagroup() ? lng_channels_too_much_public_revoke_confirm_group : lng_channels_too_much_public_revoke_confirm_channel;
+		auto text = text_method(lt_link, qsl("telegram.me/") + pressed->userName(), lt_group, pressed->name);
+		weakRevokeConfirmBox = new ConfirmBox(text, lang(lng_channels_too_much_public_revoke));
+		weakRevokeConfirmBox->setConfirmedCallback([this, weak_this = weakThis(), pressed]() {
+			if (!weak_this) return;
+			if (_revokeRequestId) return;
+			_revokeRequestId = MTP::send(MTPchannels_UpdateUsername(pressed->asChannel()->inputChannel, MTP_string("")), rpcDone(&RevokePublicLinkBox::revokeLinkDone), rpcFail(&RevokePublicLinkBox::revokeLinkFail));
+		});
+		Ui::showLayer(weakRevokeConfirmBox, KeepOtherLayers);
+	}
+}
+
+void RevokePublicLinkBox::paintEvent(QPaintEvent *e) {
+	Painter p(this);
+	if (paint(p)) return;
+
+	p.translate(0, _rowsTop);
+	for_const (auto &row, _rows) {
+		paintChat(p, row, (row.peer == _selected), (row.peer == _pressed));
+		p.translate(0, _rowHeight);
+	}
+}
+
+void RevokePublicLinkBox::resizeEvent(QResizeEvent *e) {
+	_aboutRevoke->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
+	_cancel->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _cancel->height());
+}
+
+void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selected, bool pressed) const {
+	auto peer = row.peer;
+	peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width());
+
+	p.setPen(st::black);
+
+	int32 namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
+	int32 namew = width() - namex - st::contactsPadding.right() - (_revokeWidth + st::contactsCheckPosition.x() * 2);
+	if (peer->isVerified()) {
+		namew -= st::verifiedCheck.pxWidth() + st::verifiedCheckPos.x();
+		p.drawSpriteLeft(namex + qMin(row.name.maxWidth(), namew) + st::verifiedCheckPos.x(), st::contactsPadding.top() + st::contactsNameTop + st::verifiedCheckPos.y(), width(), st::verifiedCheck);
+	}
+	row.name.drawLeftElided(p, namex, st::contactsPadding.top() + st::contactsNameTop, namew, width());
+
+	p.setFont(selected ? st::linkOverFont : st::linkFont);
+	p.setPen(pressed ? st::btnDefLink.downColor : st::btnDefLink.color->p);
+	p.drawTextRight(st::contactsPadding.right() + st::contactsCheckPosition.x(), st::contactsPadding.top() + (st::contactsPhotoSize - st::normalFont->height) / 2, width(), lang(lng_channels_too_much_public_revoke), _revokeWidth);
+
+	p.setPen(st::contactsStatusFg);
+	textstyleSet(&st::revokePublicLinkStatusStyle);
+	row.status.drawLeftElided(p, namex, st::contactsPadding.top() + st::contactsStatusTop, namew, width());
+	textstyleRestore();
+}
+
+void RevokePublicLinkBox::getPublicDone(const MTPmessages_Chats &result) {
+	if (result.type() == mtpc_messages_chats) {
+		auto &chats = result.c_messages_chats().vchats;
+		for_const (auto &chat, chats.c_vector().v) {
+			if (auto peer = App::feedChat(chat)) {
+				if (!peer->isChannel() || peer->userName().isEmpty()) continue;
+
+				ChatRow row;
+				row.peer = peer;
+				row.name.setText(st::contactsNameFont, peer->name, _textNameOptions);
+				textstyleSet(&st::revokePublicLinkStatusStyle);
+				row.status.setText(st::normalFont, qsl("telegram.me/") + textcmdLink(1, peer->userName()), _textDlgOptions);
+				textstyleRestore();
+				_rows.push_back(std_::move(row));
+			}
+		}
+	}
+	update();
+}
+
+bool RevokePublicLinkBox::getPublicFail(const RPCError &error) {
+	if (MTP::isDefaultHandledError(error)) {
+		return false;
+	}
+
+	return true;
+}
+
+void RevokePublicLinkBox::revokeLinkDone(const MTPBool &result) {
+	if (weakRevokeConfirmBox) {
+		weakRevokeConfirmBox->onClose();
+	}
+	onClose();
+	if (_revokeCallback) {
+		_revokeCallback();
+	}
+}
+
+bool RevokePublicLinkBox::revokeLinkFail(const RPCError &error) {
+	if (MTP::isDefaultHandledError(error)) {
+		return false;
+	}
+
+	return true;
+}
diff --git a/Telegram/SourceFiles/boxes/addcontactbox.h b/Telegram/SourceFiles/boxes/addcontactbox.h
index e12ccc3aa..f15130b44 100644
--- a/Telegram/SourceFiles/boxes/addcontactbox.h
+++ b/Telegram/SourceFiles/boxes/addcontactbox.h
@@ -21,6 +21,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 #pragma once
 
 #include "abstractbox.h"
+#include "core/lambda_wrap.h"
+
+class FlatLabel;
+class ConfirmBox;
 
 class AddContactBox : public AbstractBox, public RPCSender {
 	Q_OBJECT
@@ -213,6 +217,8 @@ private:
 
 	void updateMaxHeight();
 
+	void showRevokePublicLinkBoxForEdit();
+
 	ChannelData *_channel;
 	bool _existing;
 
@@ -224,9 +230,10 @@ private:
 	bool _linkOver;
 	BoxButton _save, _skip;
 
-	bool _tooMuchUsernames;
+	bool _tooMuchUsernames = false;
 
-	mtpRequestId _saveRequestId, _checkRequestId;
+	mtpRequestId _saveRequestId = 0;
+	mtpRequestId _checkRequestId = 0;
 	QString _sentUsername, _checkUsername, _errorText, _goodText;
 
 	QString _goodTextLink;
@@ -333,4 +340,52 @@ private:
 
 	mtpRequestId _saveTitleRequestId, _saveDescriptionRequestId, _saveSignRequestId;
 	QString _sentTitle, _sentDescription;
+
+};
+
+class RevokePublicLinkBox : public AbstractBox, public RPCSender {
+	Q_OBJECT
+
+public:
+	RevokePublicLinkBox(base::lambda_unique<void()> &&revokeCallback);
+
+protected:
+	void mouseMoveEvent(QMouseEvent *e) override;
+	void mousePressEvent(QMouseEvent *e) override;
+	void mouseReleaseEvent(QMouseEvent *e) override;
+	void paintEvent(QPaintEvent *e) override;
+	void resizeEvent(QResizeEvent *e) override;
+
+private:
+	void updateMaxHeight();
+	void updateSelected();
+
+	struct ChatRow {
+		PeerData *peer;
+		Text name, status;
+	};
+	void paintChat(Painter &p, const ChatRow &row, bool selected, bool pressed) const;
+
+	void getPublicDone(const MTPmessages_Chats &result);
+	bool getPublicFail(const RPCError &error);
+
+	void revokeLinkDone(const MTPBool &result);
+	bool revokeLinkFail(const RPCError &error);
+
+	PeerData *_selected = nullptr;
+	PeerData *_pressed = nullptr;
+
+	QVector<ChatRow> _rows;
+
+	int _rowsTop = 0;
+	int _rowHeight = 0;
+	int _revokeWidth = 0;
+
+	ChildWidget<FlatLabel> _aboutRevoke;
+	ChildWidget<BoxButton> _cancel;
+
+	base::lambda_unique<void()> _revokeCallback;
+	mtpRequestId _revokeRequestId = 0;
+	QPointer<ConfirmBox> weakRevokeConfirmBox;
+
 };
diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style
index ba77c0abe..69dfca7de 100644
--- a/Telegram/SourceFiles/boxes/boxes.style
+++ b/Telegram/SourceFiles/boxes/boxes.style
@@ -73,3 +73,15 @@ confirmPhoneAboutLabel: flatLabel(labelDefFlat) {
 }
 confirmPhoneCodeField: InputField(defaultInputField) {
 }
+
+revokePublicLinkStatusStyle: textStyle(defaultTextStyle) {
+	linkFg: contactsStatusFgOnline;
+	linkFgDown: contactsStatusFgOnline;
+	linkFlagsOver: font(fsize);
+}
+aboutRevokePublicLabel: flatLabel(labelDefFlat) {
+	font: normalFont;
+	align: align(topleft);
+	width: 320px;
+	textFg: windowTextFg;
+}
diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp
index 39c978ed3..cb394b926 100644
--- a/Telegram/SourceFiles/boxes/confirmbox.cpp
+++ b/Telegram/SourceFiles/boxes/confirmbox.cpp
@@ -55,21 +55,32 @@ ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style
 void ConfirmBox::init(const QString &text) {
 	_text.setText(st::boxTextFont, text, _informative ? _confirmBoxTextOptions : _textPlainOptions);
 
+	connect(&_confirm, SIGNAL(clicked()), this, SLOT(onConfirmPressed()));
+	connect(&_cancel, SIGNAL(clicked()), this, SLOT(onCancel()));
+	if (_informative) {
+		_cancel.hide();
+		connect(this, SIGNAL(confirmed()), this, SLOT(onCancel()));
+	}
+	onTextUpdated();
+
+	prepare();
+}
+
+void ConfirmBox::onConfirmPressed() {
+	if (_confirmedCallback) {
+		_confirmedCallback();
+	}
+	emit confirmed();
+}
+
+void ConfirmBox::onTextUpdated() {
 	textstyleSet(&st::boxTextStyle);
 	_textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right();
 	_textHeight = qMin(_text.countHeight(_textWidth), 16 * int(st::boxTextStyle.lineHeight));
 	setMaxHeight(st::boxPadding.top() + _textHeight + st::boxPadding.bottom() + st::boxButtonPadding.top() + _confirm.height() + st::boxButtonPadding.bottom());
 	textstyleRestore();
 
-	connect(&_confirm, SIGNAL(clicked()), this, SIGNAL(confirmed()));
-	connect(&_cancel, SIGNAL(clicked()), this, SLOT(onCancel()));
-	if (_informative) {
-		_cancel.hide();
-		connect(this, SIGNAL(confirmed()), this, SLOT(onCancel()));
-	}
 	setMouseTracking(_text.hasLinks());
-
-	prepare();
 }
 
 void ConfirmBox::onCancel() {
@@ -146,7 +157,7 @@ void ConfirmBox::showAll() {
 
 void ConfirmBox::keyPressEvent(QKeyEvent *e) {
 	if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
-		emit confirmed();
+		onConfirmPressed();
 	} else {
 		AbstractBox::keyPressEvent(e);
 	}
diff --git a/Telegram/SourceFiles/boxes/confirmbox.h b/Telegram/SourceFiles/boxes/confirmbox.h
index 11dabfaef..15cfc74ed 100644
--- a/Telegram/SourceFiles/boxes/confirmbox.h
+++ b/Telegram/SourceFiles/boxes/confirmbox.h
@@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 
 #include "abstractbox.h"
 #include "ui/flatlabel.h"
+#include "core/lambda_wrap.h"
 
 class InformBox;
 class ConfirmBox : public AbstractBox, public ClickHandlerHost {
@@ -39,32 +40,38 @@ public:
 	void leaveEvent(QEvent *e);
 	void updateLink();
 
+	// You can use this instead of connecting to "confirmed()" signal.
+	void setConfirmedCallback(base::lambda_wrap<void()> &&callback) {
+		_confirmedCallback = std_::move(callback);
+	}
+
 	// ClickHandlerHost interface
 	void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active);
 	void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed);
 
 public slots:
-
 	void onCancel();
 
 signals:
-
 	void confirmed();
 	void cancelled();
 	void cancelPressed();
 
 protected:
-
 	void closePressed();
 	void hideAll();
 	void showAll();
 
+private slots:
+	void onConfirmPressed();
+
 private:
 
 	ConfirmBox(const QString &text, const QString &doneText, const style::RoundButton &doneStyle, bool informative);
 	friend class InformBox;
 
 	void init(const QString &text);
+	void onTextUpdated();
 
 	bool _informative;
 
@@ -76,6 +83,9 @@ private:
 	QPoint _lastMousePos;
 
 	BoxButton _confirm, _cancel;
+
+	base::lambda_unique<void()> _confirmedCallback;
+
 };
 
 class InformBox : public ConfirmBox {
diff --git a/Telegram/SourceFiles/core/basic_types.h b/Telegram/SourceFiles/core/basic_types.h
index 18958f2f6..678170c16 100644
--- a/Telegram/SourceFiles/core/basic_types.h
+++ b/Telegram/SourceFiles/core/basic_types.h
@@ -323,6 +323,49 @@ inline constexpr typename remove_reference<T>::type &&move(T &&value) noexcept {
 	return static_cast<typename remove_reference<T>::type&&>(value);
 }
 
+template <typename T>
+struct remove_const {
+	using type = T;
+};
+
+template <typename T>
+struct remove_const<const T> {
+	using type = T;
+};
+
+template <typename T>
+struct remove_volatile {
+	using type = T;
+};
+
+template <typename T>
+struct remove_volatile<volatile T> {
+	using type = T;
+};
+
+template <typename T>
+using decay_simple_t = typename remove_const<typename remove_volatile<typename remove_reference<T>::type>::type>::type;
+
+template <typename T1, typename T2>
+struct is_same : false_type {
+};
+
+template <typename T>
+struct is_same<T, T> : true_type {
+};
+
+template <bool,	typename T = void>
+struct enable_if {
+};
+
+template <typename T>
+struct enable_if<true, T> {
+	using type = T;
+};
+
+template <bool Test, typename T = void>
+using enable_if_t = typename enable_if<Test, T>::type;
+
 template <typename T>
 struct add_const {
 	using type = const T;
diff --git a/Telegram/SourceFiles/core/lambda_wrap.h b/Telegram/SourceFiles/core/lambda_wrap.h
new file mode 100644
index 000000000..5a93152c0
--- /dev/null
+++ b/Telegram/SourceFiles/core/lambda_wrap.h
@@ -0,0 +1,374 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop version of Telegram messaging app, see https://telegram.org
+
+Telegram Desktop is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+In addition, as a special exception, the copyright holders give permission
+to link the code of portions of this program with the OpenSSL library.
+
+Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
+Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
+*/
+#pragma once
+
+namespace base {
+namespace internal {
+
+template <typename Return, typename ...Args>
+struct lambda_wrap_helper_base {
+	using construct_copy_other_type = void(*)(void *, const void *); // dst, src
+	using construct_move_other_type = void(*)(void *, void *); // dst, src
+	using call_type = Return(*)(const void *, Args...);
+	using destruct_type = void(*)(const void *);
+
+	lambda_wrap_helper_base() = delete;
+	lambda_wrap_helper_base(const lambda_wrap_helper_base &other) = delete;
+	lambda_wrap_helper_base &operator=(const lambda_wrap_helper_base &other) = delete;
+
+	lambda_wrap_helper_base(
+		construct_copy_other_type construct_copy_other,
+		construct_move_other_type construct_move_other,
+		call_type call,
+		destruct_type destruct)
+		: construct_copy_other(construct_copy_other)
+		, construct_move_other(construct_move_other)
+		, call(call)
+		, destruct(destruct) {
+	}
+
+	const construct_copy_other_type construct_copy_other;
+	const construct_move_other_type construct_move_other;
+	const call_type call;
+	const destruct_type destruct;
+
+	static constexpr size_t kFullStorageSize = 40U;
+	static constexpr size_t kStorageSize = kFullStorageSize - sizeof(void*);
+
+	template <typename Lambda>
+	using IsLarge = std_::integral_constant<bool, !(sizeof(std_::decay_simple_t<Lambda>) <= kStorageSize)>;
+
+protected:
+	static void bad_construct_copy(void *lambda, const void *source) {
+		throw std::exception();
+	}
+
+};
+
+template <typename Return, typename ...Args>
+struct lambda_wrap_empty : public lambda_wrap_helper_base<Return, Args...> {
+	static void construct_copy_other_method(void *lambda, const void *source) {
+	}
+	static void construct_move_other_method(void *lambda, void *source) {
+	}
+	static Return call_method(const void *lambda, Args... args) {
+		throw std::exception();
+	}
+	static void destruct_method(const void *lambda) {
+	}
+	lambda_wrap_empty() : lambda_wrap_helper_base<Return, Args...>(
+		&lambda_wrap_empty::construct_copy_other_method,
+		&lambda_wrap_empty::construct_move_other_method,
+		&lambda_wrap_empty::call_method,
+		&lambda_wrap_empty::destruct_method) {
+	}
+
+	static const lambda_wrap_empty<Return, Args...> instance;
+
+};
+
+template <typename Return, typename ...Args>
+const lambda_wrap_empty<Return, Args...> lambda_wrap_empty<Return, Args...>::instance;
+
+template <typename Lambda, typename IsLarge, typename Return, typename ...Args> struct lambda_wrap_helper_move_impl;
+
+template <typename Lambda, typename Return, typename ...Args>
+struct lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...> : public lambda_wrap_helper_base<Return, Args...> {
+	using JustLambda = std_::decay_simple_t<Lambda>;
+	using LambdaPtr = std_::unique_ptr<JustLambda>;
+	using Parent = lambda_wrap_helper_base<Return, Args...>;
+	static void construct_move_other_method(void *lambda, void *source) {
+		auto source_lambda = static_cast<LambdaPtr*>(source);
+		new (lambda) LambdaPtr(std_::move(*source_lambda));
+	}
+	static void construct_move_lambda_method(void *lambda, void *source) {
+		auto source_lambda = static_cast<JustLambda*>(source);
+		new (lambda) LambdaPtr(std_::make_unique<JustLambda>(static_cast<JustLambda&&>(*source_lambda)));
+	}
+	static Return call_method(const void *lambda, Args... args) {
+		return (**static_cast<const LambdaPtr*>(lambda))(std_::forward<Args>(args)...);
+	}
+	static void destruct_method(const void *lambda) {
+		static_cast<const LambdaPtr*>(lambda)->~LambdaPtr();
+	}
+	lambda_wrap_helper_move_impl() : Parent(
+		&Parent::bad_construct_copy,
+		&lambda_wrap_helper_move_impl::construct_move_other_method,
+		&lambda_wrap_helper_move_impl::call_method,
+		&lambda_wrap_helper_move_impl::destruct_method) {
+	}
+
+protected:
+	lambda_wrap_helper_move_impl(
+		Parent::construct_copy_other_type construct_copy_other
+	) : Parent(
+		construct_copy_other,
+		&lambda_wrap_helper_move_impl::construct_move_other_method,
+		&lambda_wrap_helper_move_impl::call_method,
+		&lambda_wrap_helper_move_impl::destruct_method) {
+	}
+
+};
+
+template <typename Lambda, typename Return, typename ...Args>
+struct lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...> : public lambda_wrap_helper_base<Return, Args...> {
+	using JustLambda = std_::decay_simple_t<Lambda>;
+	using Parent = lambda_wrap_helper_base<Return, Args...>;
+	static void construct_move_other_method(void *lambda, void *source) {
+		auto source_lambda = static_cast<JustLambda*>(source);
+		new (lambda) JustLambda(static_cast<JustLambda&&>(*source_lambda));
+	}
+	static void construct_move_lambda_method(void *lambda, void *source) {
+		auto source_lambda = static_cast<JustLambda*>(source);
+		new (lambda) JustLambda(static_cast<JustLambda&&>(*source_lambda));
+	}
+	static Return call_method(const void *lambda, Args... args) {
+		return (*static_cast<const JustLambda*>(lambda))(std_::forward<Args>(args)...);
+	}
+	static void destruct_method(const void *lambda) {
+		static_cast<const JustLambda*>(lambda)->~JustLambda();
+	}
+	lambda_wrap_helper_move_impl() : Parent(
+		&Parent::bad_construct_copy,
+		&lambda_wrap_helper_move_impl::construct_move_other_method,
+		&lambda_wrap_helper_move_impl::call_method,
+		&lambda_wrap_helper_move_impl::destruct_method) {
+	}
+
+protected:
+	lambda_wrap_helper_move_impl(
+		Parent::construct_copy_other_type construct_copy_other
+	) : Parent(
+		construct_copy_other,
+		&lambda_wrap_helper_move_impl::construct_move_other_method,
+		&lambda_wrap_helper_move_impl::call_method,
+		&lambda_wrap_helper_move_impl::destruct_method) {
+	}
+
+};
+
+template <typename Lambda, typename Return, typename ...Args>
+struct lambda_wrap_helper_move : public lambda_wrap_helper_move_impl<Lambda
+	, lambda_wrap_helper_base<Return, Args...>::IsLarge<Lambda>
+	, Return, Args...> {
+	static const lambda_wrap_helper_move instance;
+};
+
+template <typename Lambda, typename Return, typename ...Args>
+const lambda_wrap_helper_move<Lambda, Return, Args...> lambda_wrap_helper_move<Lambda, Return, Args...>::instance;
+
+template <typename Lambda, typename IsLarge, typename Return, typename ...Args> struct lambda_wrap_helper_copy_impl;
+
+template <typename Lambda, typename Return, typename ...Args>
+struct lambda_wrap_helper_copy_impl<Lambda, std_::true_type, Return, Args...> : public lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...> {
+	using JustLambda = std_::decay_simple_t<Lambda>;
+	using LambdaPtr = std_::unique_ptr<JustLambda>;
+	using Parent = lambda_wrap_helper_move_impl<Lambda, std_::true_type, Return, Args...>;
+	static void construct_copy_other_method(void *lambda, const void *source) {
+		auto source_lambda = static_cast<const LambdaPtr*>(source);
+		new (lambda) LambdaPtr(std_::make_unique<JustLambda>(*source_lambda->get()));
+	}
+	static void construct_copy_lambda_method(void *lambda, const void *source) {
+		auto source_lambda = static_cast<const JustLambda*>(source);
+		new (lambda) LambdaPtr(std_::make_unique<JustLambda>(static_cast<const JustLambda &>(*source_lambda)));
+	}
+	lambda_wrap_helper_copy_impl() : Parent(&lambda_wrap_helper_copy_impl::construct_copy_other_method) {
+	}
+
+};
+
+template <typename Lambda, typename Return, typename ...Args>
+struct lambda_wrap_helper_copy_impl<Lambda, std_::false_type, Return, Args...> : public lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...> {
+	using JustLambda = std_::decay_simple_t<Lambda>;
+	using Parent = lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...>;
+	static void construct_copy_other_method(void *lambda, const void *source) {
+		auto source_lambda = static_cast<const JustLambda*>(source);
+		new (lambda) JustLambda(static_cast<const JustLambda &>(*source_lambda));
+	}
+	static void construct_copy_lambda_method(void *lambda, const void *source) {
+		auto source_lambda = static_cast<const JustLambda*>(source);
+		new (lambda) JustLambda(static_cast<const JustLambda &>(*source_lambda));
+	}
+	lambda_wrap_helper_copy_impl() : Parent(&lambda_wrap_helper_copy_impl::construct_copy_other_method) {
+	}
+
+};
+
+template <typename Lambda, typename Return, typename ...Args>
+struct lambda_wrap_helper_copy : public lambda_wrap_helper_copy_impl<Lambda
+	, lambda_wrap_helper_base<Return, Args...>::IsLarge<Lambda>
+	, Return, Args...> {
+	static const lambda_wrap_helper_copy instance;
+};
+
+template <typename Lambda, typename Return, typename ...Args>
+const lambda_wrap_helper_copy<Lambda, Return, Args...> lambda_wrap_helper_copy<Lambda, Return, Args...>::instance;
+
+} // namespace internal
+
+template <typename Function> class lambda_unique;
+template <typename Function> class lambda_wrap;
+
+template <typename Return, typename ...Args>
+class lambda_unique<Return(Args...)> {
+	using BaseHelper = internal::lambda_wrap_helper_base<Return, Args...>;
+	using EmptyHelper = internal::lambda_wrap_empty<Return, Args...>;
+
+	template <typename Lambda>
+	using IsUnique = std_::is_same<lambda_unique, std_::decay_simple_t<Lambda>>;
+	template <typename Lambda>
+	using IsWrap = std_::is_same<lambda_wrap<Return(Args...)>, std_::decay_simple_t<Lambda>>;
+	template <typename Lambda>
+	using IsOther = std_::enable_if_t<!IsUnique<Lambda>::value && !IsWrap<Lambda>::value>;
+	template <typename Lambda>
+	using IsRvalue = std_::enable_if_t<std_::is_rvalue_reference<Lambda&&>::value>;
+
+public:
+	lambda_unique() : helper_(&EmptyHelper::instance) {
+	}
+
+	lambda_unique(const lambda_unique &other) = delete;
+	lambda_unique &operator=(const lambda_unique &other) = delete;
+
+	lambda_unique(lambda_unique &&other) : helper_(other.helper_) {
+		helper_->construct_move_other(storage_, other.storage_);
+	}
+	lambda_unique &operator=(lambda_unique &&other) {
+		auto temp = std_::move(other);
+		helper_->destruct(storage_);
+		helper_ = temp.helper_;
+		helper_->construct_move_other(storage_, temp.storage_);
+		return *this;
+	}
+
+	void swap(lambda_unique &other) {
+		if (this != &other) {
+			lambda_unique temp = std_::move(other);
+			other = std_::move(*this);
+			*this = std_::move(other);
+		}
+	}
+
+	template <typename Lambda, typename = IsOther<Lambda>, typename = IsRvalue<Lambda>>
+	lambda_unique(Lambda &&other) : helper_(&internal::lambda_wrap_helper_move<Lambda, Return, Args...>::instance) {
+		internal::lambda_wrap_helper_move<Lambda, Return, Args...>::construct_move_lambda_method(storage_, &other);
+	}
+
+	template <typename Lambda, typename = IsOther<Lambda>, typename = IsRvalue<Lambda>>
+	lambda_unique &operator=(Lambda &&other) {
+		auto temp = std_::move(other);
+		helper_->destruct(storage_);
+		helper_ = &internal::lambda_wrap_helper_move<Lambda, Return, Args...>::instance;
+		internal::lambda_wrap_helper_move<Lambda, Return, Args...>::construct_move_lambda_method(storage_, &temp);
+		return *this;
+	}
+
+	inline Return operator()(Args... args) const {
+		return helper_->call(storage_, std_::forward<Args>(args)...);
+	}
+
+	explicit operator bool() const {
+		return (helper_ != &EmptyHelper::instance);
+	}
+
+	~lambda_unique() {
+		helper_->destruct(storage_);
+	}
+
+protected:
+	struct Private {
+	};
+	lambda_unique(const BaseHelper *helper, const Private &) : helper_(helper) {
+	}
+
+	const BaseHelper *helper_;
+
+	static_assert(BaseHelper::kStorageSize % sizeof(void*) == 0, "Bad pointer size.");
+	void *(storage_[BaseHelper::kStorageSize / sizeof(void*)]);
+
+};
+
+template <typename Return, typename ...Args>
+class lambda_wrap<Return(Args...)> : public lambda_unique<Return(Args...)> {
+	using BaseHelper = internal::lambda_wrap_helper_base<Return, Args...>;
+	using Parent = lambda_unique<Return(Args...)>;
+
+	template <typename Lambda>
+	using IsOther = std_::enable_if_t<!std_::is_same<lambda_wrap, std_::decay_simple_t<Lambda>>::value>;
+	template <typename Lambda>
+	using IsRvalue = std_::enable_if_t<std_::is_rvalue_reference<Lambda&&>::value>;
+	template <typename Lambda>
+	using IsNotRvalue = std_::enable_if_t<!std_::is_rvalue_reference<Lambda&&>::value>;
+
+public:
+	lambda_wrap() = default;
+
+	lambda_wrap(const lambda_wrap &other) : Parent(other.helper_, Parent::Private()) {
+		helper_->construct_copy_other(storage_, other.storage_);
+	}
+	lambda_wrap &operator=(const lambda_wrap &other) {
+		auto temp = other;
+		other.swap(*this);
+		return *this;
+	}
+
+	lambda_wrap(lambda_wrap &&other) = default;
+	lambda_wrap &operator=(lambda_wrap &&other) = default;
+
+	void swap(lambda_wrap &other) {
+		if (this != &other) {
+			lambda_wrap temp = std_::move(other);
+			other = std_::move(*this);
+			*this = std_::move(other);
+		}
+	}
+
+	template <typename Lambda, typename = IsOther<Lambda>>
+	lambda_wrap(const Lambda &other) : Parent(&internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::instance, Parent::Private()) {
+		internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::construct_copy_lambda_method(storage_, &other);
+	}
+
+	template <typename Lambda, typename = IsOther<Lambda>, typename = IsRvalue<Lambda>>
+	lambda_wrap(Lambda &&other) : Parent(&internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::instance, Parent::Private()) {
+		internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::construct_move_lambda_method(storage_, &other);
+	}
+
+	template <typename Lambda, typename = IsOther<Lambda>>
+	lambda_wrap &operator=(const Lambda &other) {
+		auto temp = other;
+		helper_->destruct(storage_);
+		helper_ = &internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::instance;
+		internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::construct_move_lambda_method(storage_, &copy);
+		return *this;
+	}
+
+	template <typename Lambda, typename = IsOther<Lambda>, typename = IsRvalue<Lambda>>
+	lambda_wrap &operator=(Lambda &&other) {
+		auto temp = std_::move(other);
+		helper_->destruct(storage_);
+		helper_ = &internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::instance;
+		internal::lambda_wrap_helper_copy<Lambda, Return, Args...>::construct_move_lambda_method(storage_, &copy);
+		return *this;
+	}
+
+};
+
+} // namespace base
diff --git a/Telegram/SourceFiles/mtproto/scheme.tl b/Telegram/SourceFiles/mtproto/scheme.tl
index c418d0fdf..64cb8d5ff 100644
--- a/Telegram/SourceFiles/mtproto/scheme.tl
+++ b/Telegram/SourceFiles/mtproto/scheme.tl
@@ -155,6 +155,8 @@ inputMediaUploadedThumbDocument#ad613491 file:InputFile thumb:InputFile mime_typ
 inputMediaDocument#1a77f29c id:InputDocument caption:string = InputMedia;
 inputMediaVenue#2827a81a geo_point:InputGeoPoint title:string address:string provider:string venue_id:string = InputMedia;
 inputMediaGifExternal#4843b0fd url:string q:string = InputMedia;
+inputMediaPhotoExternal#b55f4f18 url:string caption:string = InputMedia;
+inputMediaDocumentExternal#e5e9607c url:string caption:string = InputMedia;
 
 inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
 inputChatUploadedPhoto#94254732 file:InputFile crop:InputPhotoCrop = InputChatPhoto;
@@ -268,7 +270,7 @@ auth.checkedPhone#811ea28e phone_registered:Bool = auth.CheckedPhone;
 
 auth.sentCode#5e002502 flags:# phone_registered:flags.0?true type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode;
 
-auth.authorization#ff036af1 user:User = auth.Authorization;
+auth.authorization#cd050916 flags:# tmp_sessions:flags.0?int user:User = auth.Authorization;
 
 auth.exportedAuthorization#df969c2d id:int bytes:bytes = auth.ExportedAuthorization;
 
@@ -394,6 +396,8 @@ updateReadChannelOutbox#25d6c9c7 channel_id:int max_id:int = Update;
 updateDraftMessage#ee2bb969 peer:Peer draft:DraftMessage = Update;
 updateReadFeaturedStickers#571d2742 = Update;
 updateRecentStickers#9a422c20 = Update;
+updateConfig#a229dd06 = Update;
+updatePtsChanged#3354678f = Update;
 
 updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
 
@@ -418,7 +422,7 @@ upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
 
 dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true id:int ip_address:string port:int = DcOption;
 
-config#f401a4bf date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int disabled_features:Vector<DisabledFeature> = Config;
+config#9a6b2e2a flags:# date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int tmp_sessions:flags.0?int disabled_features:Vector<DisabledFeature> = Config;
 
 nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
 
@@ -568,7 +572,7 @@ keyboardButtonUrl#258aff05 text:string url:string = KeyboardButton;
 keyboardButtonCallback#683a5e46 text:string data:bytes = KeyboardButton;
 keyboardButtonRequestPhone#b16a6c29 text:string = KeyboardButton;
 keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton;
-keyboardButtonSwitchInline#ea1b7a14 text:string query:string = KeyboardButton;
+keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton;
 
 keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
 
@@ -672,7 +676,7 @@ auth.sentCodeTypeSms#c000bba2 length:int = auth.SentCodeType;
 auth.sentCodeTypeCall#5353e5a7 length:int = auth.SentCodeType;
 auth.sentCodeTypeFlashCall#ab03c6d9 pattern:string = auth.SentCodeType;
 
-messages.botCallbackAnswer#b10df1fb flags:# alert:flags.1?true message:flags.0?string url:flags.2?string = messages.BotCallbackAnswer;
+messages.botCallbackAnswer#b10df1fb flags:# alert:flags.1?true has_url:flags.3?true message:flags.0?string url:flags.2?string = messages.BotCallbackAnswer;
 
 messages.messageEditData#26b5dde6 flags:# caption:flags.0?true = messages.MessageEditData;
 
@@ -804,7 +808,6 @@ messages.addChatUser#f9a0aa09 chat_id:int user_id:InputUser fwd_limit:int = Upda
 messages.deleteChatUser#e0611f16 chat_id:int user_id:InputUser = Updates;
 messages.createChat#9cb126e users:Vector<InputUser> title:string = Updates;
 messages.forwardMessage#33963bf9 peer:InputPeer id:int random_id:long = Updates;
-messages.sendBroadcast#bf73f4da contacts:Vector<InputUser> random_id:Vector<long> message:string media:InputMedia = Updates;
 messages.getDhConfig#26cf8950 version:int random_length:int = messages.DhConfig;
 messages.requestEncryption#f64daf43 user_id:InputUser random_id:int g_a:bytes = EncryptedChat;
 messages.acceptEncryption#3dbc0415 peer:InputEncryptedChat g_b:bytes key_fingerprint:long = EncryptedChat;
@@ -903,5 +906,6 @@ channels.toggleInvites#49609307 channel:InputChannel enabled:Bool = Updates;
 channels.exportMessageLink#c846d22d channel:InputChannel id:int = ExportedMessageLink;
 channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
 channels.updatePinnedMessage#a72ded52 flags:# silent:flags.0?true channel:InputChannel id:int = Updates;
+channels.getAdminedPublicChannels#8d8d82d7 = messages.Chats;
 
-// LAYER 54
+// LAYER 55
diff --git a/Telegram/SourceFiles/mtproto/scheme_auto.cpp b/Telegram/SourceFiles/mtproto/scheme_auto.cpp
index 34298d2bd..19ad70dc3 100644
--- a/Telegram/SourceFiles/mtproto/scheme_auto.cpp
+++ b/Telegram/SourceFiles/mtproto/scheme_auto.cpp
@@ -721,6 +721,34 @@ void _serialize_inputMediaGifExternal(MTPStringLogger &to, int32 stage, int32 le
 	}
 }
 
+void _serialize_inputMediaPhotoExternal(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	if (stage) {
+		to.add(",\n").addSpaces(lev);
+	} else {
+		to.add("{ inputMediaPhotoExternal");
+		to.add("\n").addSpaces(lev);
+	}
+	switch (stage) {
+	case 0: to.add("  url: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 1: to.add("  caption: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
+	}
+}
+
+void _serialize_inputMediaDocumentExternal(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	if (stage) {
+		to.add(",\n").addSpaces(lev);
+	} else {
+		to.add("{ inputMediaDocumentExternal");
+		to.add("\n").addSpaces(lev);
+	}
+	switch (stage) {
+	case 0: to.add("  url: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 1: to.add("  caption: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
+	}
+}
+
 void _serialize_inputChatPhotoEmpty(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
 	to.add("{ inputChatPhotoEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
 }
@@ -1795,6 +1823,8 @@ void _serialize_auth_sentCode(MTPStringLogger &to, int32 stage, int32 lev, Types
 }
 
 void _serialize_auth_authorization(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	MTPDauth_authorization::Flags flag(iflag);
+
 	if (stage) {
 		to.add(",\n").addSpaces(lev);
 	} else {
@@ -1802,7 +1832,9 @@ void _serialize_auth_authorization(MTPStringLogger &to, int32 stage, int32 lev,
 		to.add("\n").addSpaces(lev);
 	}
 	switch (stage) {
-	case 0: to.add("  user: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 0: to.add("  flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 1: to.add("  tmp_sessions: "); ++stages.back(); if (flag & MTPDauth_authorization::Flag::f_tmp_sessions) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
+	case 2: to.add("  user: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
 	}
 }
@@ -3021,6 +3053,14 @@ void _serialize_updateRecentStickers(MTPStringLogger &to, int32 stage, int32 lev
 	to.add("{ updateRecentStickers }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
 }
 
+void _serialize_updateConfig(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	to.add("{ updateConfig }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
+}
+
+void _serialize_updatePtsChanged(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	to.add("{ updatePtsChanged }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
+}
+
 void _serialize_updates_state(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
 	if (stage) {
 		to.add(",\n").addSpaces(lev);
@@ -3302,6 +3342,8 @@ void _serialize_dcOption(MTPStringLogger &to, int32 stage, int32 lev, Types &typ
 }
 
 void _serialize_config(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	MTPDconfig::Flags flag(iflag);
+
 	if (stage) {
 		to.add(",\n").addSpaces(lev);
 	} else {
@@ -3309,28 +3351,30 @@ void _serialize_config(MTPStringLogger &to, int32 stage, int32 lev, Types &types
 		to.add("\n").addSpaces(lev);
 	}
 	switch (stage) {
-	case 0: to.add("  date: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 1: to.add("  expires: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 2: to.add("  test_mode: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 3: to.add("  this_dc: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 4: to.add("  dc_options: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 5: to.add("  chat_size_max: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 6: to.add("  megagroup_size_max: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 7: to.add("  forwarded_count_max: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 8: to.add("  online_update_period_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 9: to.add("  offline_blur_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 10: to.add("  offline_idle_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 11: to.add("  online_cloud_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 12: to.add("  notify_cloud_delay_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 13: to.add("  notify_default_delay_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 14: to.add("  chat_big_size: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 15: to.add("  push_chat_period_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 16: to.add("  push_chat_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 17: to.add("  saved_gifs_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 18: to.add("  edit_time_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 19: to.add("  rating_e_decay: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 20: to.add("  stickers_recent_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 21: to.add("  disabled_features: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 0: to.add("  flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 1: to.add("  date: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 2: to.add("  expires: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 3: to.add("  test_mode: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 4: to.add("  this_dc: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 5: to.add("  dc_options: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 6: to.add("  chat_size_max: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 7: to.add("  megagroup_size_max: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 8: to.add("  forwarded_count_max: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 9: to.add("  online_update_period_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 10: to.add("  offline_blur_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 11: to.add("  offline_idle_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 12: to.add("  online_cloud_timeout_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 13: to.add("  notify_cloud_delay_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 14: to.add("  notify_default_delay_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 15: to.add("  chat_big_size: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 16: to.add("  push_chat_period_ms: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 17: to.add("  push_chat_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 18: to.add("  saved_gifs_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 19: to.add("  edit_time_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 20: to.add("  rating_e_decay: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 21: to.add("  stickers_recent_limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 22: to.add("  tmp_sessions: "); ++stages.back(); if (flag & MTPDconfig::Flag::f_tmp_sessions) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
+	case 23: to.add("  disabled_features: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
 	}
 }
@@ -4524,6 +4568,8 @@ void _serialize_keyboardButtonRequestGeoLocation(MTPStringLogger &to, int32 stag
 }
 
 void _serialize_keyboardButtonSwitchInline(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	MTPDkeyboardButtonSwitchInline::Flags flag(iflag);
+
 	if (stage) {
 		to.add(",\n").addSpaces(lev);
 	} else {
@@ -4531,8 +4577,10 @@ void _serialize_keyboardButtonSwitchInline(MTPStringLogger &to, int32 stage, int
 		to.add("\n").addSpaces(lev);
 	}
 	switch (stage) {
-	case 0: to.add("  text: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 1: to.add("  query: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 0: to.add("  flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 1: to.add("  same_peer: "); ++stages.back(); if (flag & MTPDkeyboardButtonSwitchInline::Flag::f_same_peer) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
+	case 2: to.add("  text: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+	case 3: to.add("  query: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
 	}
 }
@@ -5600,8 +5648,9 @@ void _serialize_messages_botCallbackAnswer(MTPStringLogger &to, int32 stage, int
 	switch (stage) {
 	case 0: to.add("  flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 	case 1: to.add("  alert: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_alert) { to.add("YES [ BY BIT 1 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
-	case 2: to.add("  message: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_message) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
-	case 3: to.add("  url: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_url) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
+	case 2: to.add("  has_url: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_has_url) { to.add("YES [ BY BIT 3 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
+	case 3: to.add("  message: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_message) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
+	case 4: to.add("  url: "); ++stages.back(); if (flag & MTPDmessages_botCallbackAnswer::Flag::f_url) { types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
 	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
 	}
 }
@@ -7492,22 +7541,6 @@ void _serialize_messages_forwardMessage(MTPStringLogger &to, int32 stage, int32
 	}
 }
 
-void _serialize_messages_sendBroadcast(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
-	if (stage) {
-		to.add(",\n").addSpaces(lev);
-	} else {
-		to.add("{ messages_sendBroadcast");
-		to.add("\n").addSpaces(lev);
-	}
-	switch (stage) {
-	case 0: to.add("  contacts: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 1: to.add("  random_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(mtpc_long+0); stages.push_back(0); flags.push_back(0); break;
-	case 2: to.add("  message: "); ++stages.back(); types.push_back(mtpc_string+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	case 3: to.add("  media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-	default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
-	}
-}
-
 void _serialize_messages_importChatInvite(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
 	if (stage) {
 		to.add(",\n").addSpaces(lev);
@@ -7827,6 +7860,10 @@ void _serialize_channels_getChannels(MTPStringLogger &to, int32 stage, int32 lev
 	}
 }
 
+void _serialize_channels_getAdminedPublicChannels(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
+	to.add("{ channels_getAdminedPublicChannels }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
+}
+
 void _serialize_messages_getFullChat(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
 	if (stage) {
 		to.add(",\n").addSpaces(lev);
@@ -8504,6 +8541,8 @@ namespace {
 		_serializers.insert(mtpc_inputMediaDocument, _serialize_inputMediaDocument);
 		_serializers.insert(mtpc_inputMediaVenue, _serialize_inputMediaVenue);
 		_serializers.insert(mtpc_inputMediaGifExternal, _serialize_inputMediaGifExternal);
+		_serializers.insert(mtpc_inputMediaPhotoExternal, _serialize_inputMediaPhotoExternal);
+		_serializers.insert(mtpc_inputMediaDocumentExternal, _serialize_inputMediaDocumentExternal);
 		_serializers.insert(mtpc_inputChatPhotoEmpty, _serialize_inputChatPhotoEmpty);
 		_serializers.insert(mtpc_inputChatUploadedPhoto, _serialize_inputChatUploadedPhoto);
 		_serializers.insert(mtpc_inputChatPhoto, _serialize_inputChatPhoto);
@@ -8691,6 +8730,8 @@ namespace {
 		_serializers.insert(mtpc_updateDraftMessage, _serialize_updateDraftMessage);
 		_serializers.insert(mtpc_updateReadFeaturedStickers, _serialize_updateReadFeaturedStickers);
 		_serializers.insert(mtpc_updateRecentStickers, _serialize_updateRecentStickers);
+		_serializers.insert(mtpc_updateConfig, _serialize_updateConfig);
+		_serializers.insert(mtpc_updatePtsChanged, _serialize_updatePtsChanged);
 		_serializers.insert(mtpc_updates_state, _serialize_updates_state);
 		_serializers.insert(mtpc_updates_differenceEmpty, _serialize_updates_differenceEmpty);
 		_serializers.insert(mtpc_updates_difference, _serialize_updates_difference);
@@ -9033,7 +9074,6 @@ namespace {
 		_serializers.insert(mtpc_messages_deleteChatUser, _serialize_messages_deleteChatUser);
 		_serializers.insert(mtpc_messages_createChat, _serialize_messages_createChat);
 		_serializers.insert(mtpc_messages_forwardMessage, _serialize_messages_forwardMessage);
-		_serializers.insert(mtpc_messages_sendBroadcast, _serialize_messages_sendBroadcast);
 		_serializers.insert(mtpc_messages_importChatInvite, _serialize_messages_importChatInvite);
 		_serializers.insert(mtpc_messages_startBot, _serialize_messages_startBot);
 		_serializers.insert(mtpc_messages_toggleChatAdmins, _serialize_messages_toggleChatAdmins);
@@ -9056,6 +9096,7 @@ namespace {
 		_serializers.insert(mtpc_messages_getPeerSettings, _serialize_messages_getPeerSettings);
 		_serializers.insert(mtpc_messages_getChats, _serialize_messages_getChats);
 		_serializers.insert(mtpc_channels_getChannels, _serialize_channels_getChannels);
+		_serializers.insert(mtpc_channels_getAdminedPublicChannels, _serialize_channels_getAdminedPublicChannels);
 		_serializers.insert(mtpc_messages_getFullChat, _serialize_messages_getFullChat);
 		_serializers.insert(mtpc_channels_getFullChannel, _serialize_channels_getFullChannel);
 		_serializers.insert(mtpc_messages_getDhConfig, _serialize_messages_getDhConfig);
diff --git a/Telegram/SourceFiles/mtproto/scheme_auto.h b/Telegram/SourceFiles/mtproto/scheme_auto.h
index ff8bb5e72..b4e9ede56 100644
--- a/Telegram/SourceFiles/mtproto/scheme_auto.h
+++ b/Telegram/SourceFiles/mtproto/scheme_auto.h
@@ -30,7 +30,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
 namespace MTP {
 namespace internal {
 
-static constexpr mtpPrime CurrentLayer = 54;
+static constexpr mtpPrime CurrentLayer = 55;
 
 class TypeCreator;
 
@@ -103,6 +103,8 @@ enum {
 	mtpc_inputMediaDocument = 0x1a77f29c,
 	mtpc_inputMediaVenue = 0x2827a81a,
 	mtpc_inputMediaGifExternal = 0x4843b0fd,
+	mtpc_inputMediaPhotoExternal = 0xb55f4f18,
+	mtpc_inputMediaDocumentExternal = 0xe5e9607c,
 	mtpc_inputChatPhotoEmpty = 0x1ca48f57,
 	mtpc_inputChatUploadedPhoto = 0x94254732,
 	mtpc_inputChatPhoto = 0xb2e1bf08,
@@ -189,7 +191,7 @@ enum {
 	mtpc_geoPoint = 0x2049d70c,
 	mtpc_auth_checkedPhone = 0x811ea28e,
 	mtpc_auth_sentCode = 0x5e002502,
-	mtpc_auth_authorization = 0xff036af1,
+	mtpc_auth_authorization = 0xcd050916,
 	mtpc_auth_exportedAuthorization = 0xdf969c2d,
 	mtpc_inputNotifyPeer = 0xb8bc5b0c,
 	mtpc_inputNotifyUsers = 0x193b4417,
@@ -290,6 +292,8 @@ enum {
 	mtpc_updateDraftMessage = 0xee2bb969,
 	mtpc_updateReadFeaturedStickers = 0x571d2742,
 	mtpc_updateRecentStickers = 0x9a422c20,
+	mtpc_updateConfig = 0xa229dd06,
+	mtpc_updatePtsChanged = 0x3354678f,
 	mtpc_updates_state = 0xa56c2a3e,
 	mtpc_updates_differenceEmpty = 0x5d75a138,
 	mtpc_updates_difference = 0xf49ca0,
@@ -306,7 +310,7 @@ enum {
 	mtpc_photos_photo = 0x20212ca8,
 	mtpc_upload_file = 0x96a18d5,
 	mtpc_dcOption = 0x5d8c6cc,
-	mtpc_config = 0xf401a4bf,
+	mtpc_config = 0x9a6b2e2a,
 	mtpc_nearestDc = 0x8e1a1775,
 	mtpc_help_appUpdate = 0x8987f311,
 	mtpc_help_noAppUpdate = 0xc45a6536,
@@ -411,7 +415,7 @@ enum {
 	mtpc_keyboardButtonCallback = 0x683a5e46,
 	mtpc_keyboardButtonRequestPhone = 0xb16a6c29,
 	mtpc_keyboardButtonRequestGeoLocation = 0xfc796b3f,
-	mtpc_keyboardButtonSwitchInline = 0xea1b7a14,
+	mtpc_keyboardButtonSwitchInline = 0x568a748,
 	mtpc_keyboardButtonRow = 0x77608b83,
 	mtpc_replyKeyboardHide = 0xa03e5b85,
 	mtpc_replyKeyboardForceReply = 0xf4108aa0,
@@ -597,7 +601,6 @@ enum {
 	mtpc_messages_deleteChatUser = 0xe0611f16,
 	mtpc_messages_createChat = 0x9cb126e,
 	mtpc_messages_forwardMessage = 0x33963bf9,
-	mtpc_messages_sendBroadcast = 0xbf73f4da,
 	mtpc_messages_getDhConfig = 0x26cf8950,
 	mtpc_messages_requestEncryption = 0xf64daf43,
 	mtpc_messages_acceptEncryption = 0x3dbc0415,
@@ -690,7 +693,8 @@ enum {
 	mtpc_channels_toggleInvites = 0x49609307,
 	mtpc_channels_exportMessageLink = 0xc846d22d,
 	mtpc_channels_toggleSignatures = 0x1f69b606,
-	mtpc_channels_updatePinnedMessage = 0xa72ded52
+	mtpc_channels_updatePinnedMessage = 0xa72ded52,
+	mtpc_channels_getAdminedPublicChannels = 0x8d8d82d7
 };
 
 // Type forward declarations
@@ -797,6 +801,8 @@ class MTPDinputMediaUploadedThumbDocument;
 class MTPDinputMediaDocument;
 class MTPDinputMediaVenue;
 class MTPDinputMediaGifExternal;
+class MTPDinputMediaPhotoExternal;
+class MTPDinputMediaDocumentExternal;
 
 class MTPinputChatPhoto;
 class MTPDinputChatUploadedPhoto;
@@ -2728,6 +2734,30 @@ public:
 		return *(const MTPDinputMediaGifExternal*)data;
 	}
 
+	MTPDinputMediaPhotoExternal &_inputMediaPhotoExternal() {
+		if (!data) throw mtpErrorUninitialized();
+		if (_type != mtpc_inputMediaPhotoExternal) throw mtpErrorWrongTypeId(_type, mtpc_inputMediaPhotoExternal);
+		split();
+		return *(MTPDinputMediaPhotoExternal*)data;
+	}
+	const MTPDinputMediaPhotoExternal &c_inputMediaPhotoExternal() const {
+		if (!data) throw mtpErrorUninitialized();
+		if (_type != mtpc_inputMediaPhotoExternal) throw mtpErrorWrongTypeId(_type, mtpc_inputMediaPhotoExternal);
+		return *(const MTPDinputMediaPhotoExternal*)data;
+	}
+
+	MTPDinputMediaDocumentExternal &_inputMediaDocumentExternal() {
+		if (!data) throw mtpErrorUninitialized();
+		if (_type != mtpc_inputMediaDocumentExternal) throw mtpErrorWrongTypeId(_type, mtpc_inputMediaDocumentExternal);
+		split();
+		return *(MTPDinputMediaDocumentExternal*)data;
+	}
+	const MTPDinputMediaDocumentExternal &c_inputMediaDocumentExternal() const {
+		if (!data) throw mtpErrorUninitialized();
+		if (_type != mtpc_inputMediaDocumentExternal) throw mtpErrorWrongTypeId(_type, mtpc_inputMediaDocumentExternal);
+		return *(const MTPDinputMediaDocumentExternal*)data;
+	}
+
 	uint32 innerLength() const;
 	mtpTypeId type() const;
 	void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons);
@@ -2746,6 +2776,8 @@ private:
 	explicit MTPinputMedia(MTPDinputMediaDocument *_data);
 	explicit MTPinputMedia(MTPDinputMediaVenue *_data);
 	explicit MTPinputMedia(MTPDinputMediaGifExternal *_data);
+	explicit MTPinputMedia(MTPDinputMediaPhotoExternal *_data);
+	explicit MTPinputMedia(MTPDinputMediaDocumentExternal *_data);
 
 	friend class MTP::internal::TypeCreator;
 
@@ -10265,6 +10297,28 @@ public:
 	MTPstring vq;
 };
 
+class MTPDinputMediaPhotoExternal : public mtpDataImpl<MTPDinputMediaPhotoExternal> {
+public:
+	MTPDinputMediaPhotoExternal() {
+	}
+	MTPDinputMediaPhotoExternal(const MTPstring &_url, const MTPstring &_caption) : vurl(_url), vcaption(_caption) {
+	}
+
+	MTPstring vurl;
+	MTPstring vcaption;
+};
+
+class MTPDinputMediaDocumentExternal : public mtpDataImpl<MTPDinputMediaDocumentExternal> {
+public:
+	MTPDinputMediaDocumentExternal() {
+	}
+	MTPDinputMediaDocumentExternal(const MTPstring &_url, const MTPstring &_caption) : vurl(_url), vcaption(_caption) {
+	}
+
+	MTPstring vurl;
+	MTPstring vcaption;
+};
+
 class MTPDinputChatUploadedPhoto : public mtpDataImpl<MTPDinputChatUploadedPhoto> {
 public:
 	MTPDinputChatUploadedPhoto() {
@@ -11230,11 +11284,22 @@ public:
 
 class MTPDauth_authorization : public mtpDataImpl<MTPDauth_authorization> {
 public:
+	enum class Flag : int32 {
+		f_tmp_sessions = (1 << 0),
+		MAX_FIELD = (1 << 0),
+	};
+	Q_DECLARE_FLAGS(Flags, Flag);
+	friend inline Flags operator~(Flag v) { return QFlag(~static_cast<int32>(v)); }
+
+	bool has_tmp_sessions() const { return vflags.v & Flag::f_tmp_sessions; }
+
 	MTPDauth_authorization() {
 	}
-	MTPDauth_authorization(const MTPUser &_user) : vuser(_user) {
+	MTPDauth_authorization(const MTPflags<MTPDauth_authorization::Flags> &_flags, MTPint _tmp_sessions, const MTPUser &_user) : vflags(_flags), vtmp_sessions(_tmp_sessions), vuser(_user) {
 	}
 
+	MTPflags<MTPDauth_authorization::Flags> vflags;
+	MTPint vtmp_sessions;
 	MTPUser vuser;
 };
 
@@ -12479,11 +12544,21 @@ public:
 
 class MTPDconfig : public mtpDataImpl<MTPDconfig> {
 public:
+	enum class Flag : int32 {
+		f_tmp_sessions = (1 << 0),
+		MAX_FIELD = (1 << 0),
+	};
+	Q_DECLARE_FLAGS(Flags, Flag);
+	friend inline Flags operator~(Flag v) { return QFlag(~static_cast<int32>(v)); }
+
+	bool has_tmp_sessions() const { return vflags.v & Flag::f_tmp_sessions; }
+
 	MTPDconfig() {
 	}
-	MTPDconfig(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, MTPint _stickers_recent_limit, const MTPVector<MTPDisabledFeature> &_disabled_features) : vdate(_date), vexpires(_expires), vtest_mode(_test_mode), vthis_dc(_this_dc), vdc_options(_dc_options), vchat_size_max(_chat_size_max), vmegagroup_size_max(_megagroup_size_max), vforwarded_count_max(_forwarded_count_max), vonline_update_period_ms(_online_update_period_ms), voffline_blur_timeout_ms(_offline_blur_timeout_ms), voffline_idle_timeout_ms(_offline_idle_timeout_ms), vonline_cloud_timeout_ms(_online_cloud_timeout_ms), vnotify_cloud_delay_ms(_notify_cloud_delay_ms), vnotify_default_delay_ms(_notify_default_delay_ms), vchat_big_size(_chat_big_size), vpush_chat_period_ms(_push_chat_period_ms), vpush_chat_limit(_push_chat_limit), vsaved_gifs_limit(_saved_gifs_limit), vedit_time_limit(_edit_time_limit), vrating_e_decay(_rating_e_decay), vstickers_recent_limit(_stickers_recent_limit), vdisabled_features(_disabled_features) {
+	MTPDconfig(const MTPflags<MTPDconfig::Flags> &_flags, MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, MTPint _stickers_recent_limit, MTPint _tmp_sessions, const MTPVector<MTPDisabledFeature> &_disabled_features) : vflags(_flags), vdate(_date), vexpires(_expires), vtest_mode(_test_mode), vthis_dc(_this_dc), vdc_options(_dc_options), vchat_size_max(_chat_size_max), vmegagroup_size_max(_megagroup_size_max), vforwarded_count_max(_forwarded_count_max), vonline_update_period_ms(_online_update_period_ms), voffline_blur_timeout_ms(_offline_blur_timeout_ms), voffline_idle_timeout_ms(_offline_idle_timeout_ms), vonline_cloud_timeout_ms(_online_cloud_timeout_ms), vnotify_cloud_delay_ms(_notify_cloud_delay_ms), vnotify_default_delay_ms(_notify_default_delay_ms), vchat_big_size(_chat_big_size), vpush_chat_period_ms(_push_chat_period_ms), vpush_chat_limit(_push_chat_limit), vsaved_gifs_limit(_saved_gifs_limit), vedit_time_limit(_edit_time_limit), vrating_e_decay(_rating_e_decay), vstickers_recent_limit(_stickers_recent_limit), vtmp_sessions(_tmp_sessions), vdisabled_features(_disabled_features) {
 	}
 
+	MTPflags<MTPDconfig::Flags> vflags;
 	MTPint vdate;
 	MTPint vexpires;
 	MTPBool vtest_mode;
@@ -12505,6 +12580,7 @@ public:
 	MTPint vedit_time_limit;
 	MTPint vrating_e_decay;
 	MTPint vstickers_recent_limit;
+	MTPint vtmp_sessions;
 	MTPVector<MTPDisabledFeature> vdisabled_features;
 };
 
@@ -13430,11 +13506,21 @@ public:
 
 class MTPDkeyboardButtonSwitchInline : public mtpDataImpl<MTPDkeyboardButtonSwitchInline> {
 public:
+	enum class Flag : int32 {
+		f_same_peer = (1 << 0),
+		MAX_FIELD = (1 << 0),
+	};
+	Q_DECLARE_FLAGS(Flags, Flag);
+	friend inline Flags operator~(Flag v) { return QFlag(~static_cast<int32>(v)); }
+
+	bool is_same_peer() const { return vflags.v & Flag::f_same_peer; }
+
 	MTPDkeyboardButtonSwitchInline() {
 	}
-	MTPDkeyboardButtonSwitchInline(const MTPstring &_text, const MTPstring &_query) : vtext(_text), vquery(_query) {
+	MTPDkeyboardButtonSwitchInline(const MTPflags<MTPDkeyboardButtonSwitchInline::Flags> &_flags, const MTPstring &_text, const MTPstring &_query) : vflags(_flags), vtext(_text), vquery(_query) {
 	}
 
+	MTPflags<MTPDkeyboardButtonSwitchInline::Flags> vflags;
 	MTPstring vtext;
 	MTPstring vquery;
 };
@@ -14494,15 +14580,17 @@ class MTPDmessages_botCallbackAnswer : public mtpDataImpl<MTPDmessages_botCallba
 public:
 	enum class Flag : int32 {
 		f_alert = (1 << 1),
+		f_has_url = (1 << 3),
 		f_message = (1 << 0),
 		f_url = (1 << 2),
 
-		MAX_FIELD = (1 << 2),
+		MAX_FIELD = (1 << 3),
 	};
 	Q_DECLARE_FLAGS(Flags, Flag);
 	friend inline Flags operator~(Flag v) { return QFlag(~static_cast<int32>(v)); }
 
 	bool is_alert() const { return vflags.v & Flag::f_alert; }
+	bool is_has_url() const { return vflags.v & Flag::f_has_url; }
 	bool has_message() const { return vflags.v & Flag::f_message; }
 	bool has_url() const { return vflags.v & Flag::f_url; }
 
@@ -18788,54 +18876,6 @@ public:
 	}
 };
 
-class MTPmessages_sendBroadcast { // RPC method 'messages.sendBroadcast'
-public:
-	MTPVector<MTPInputUser> vcontacts;
-	MTPVector<MTPlong> vrandom_id;
-	MTPstring vmessage;
-	MTPInputMedia vmedia;
-
-	MTPmessages_sendBroadcast() {
-	}
-	MTPmessages_sendBroadcast(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_sendBroadcast) {
-		read(from, end, cons);
-	}
-	MTPmessages_sendBroadcast(const MTPVector<MTPInputUser> &_contacts, const MTPVector<MTPlong> &_random_id, const MTPstring &_message, const MTPInputMedia &_media) : vcontacts(_contacts), vrandom_id(_random_id), vmessage(_message), vmedia(_media) {
-	}
-
-	uint32 innerLength() const {
-		return vcontacts.innerLength() + vrandom_id.innerLength() + vmessage.innerLength() + vmedia.innerLength();
-	}
-	mtpTypeId type() const {
-		return mtpc_messages_sendBroadcast;
-	}
-	void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_sendBroadcast) {
-		vcontacts.read(from, end);
-		vrandom_id.read(from, end);
-		vmessage.read(from, end);
-		vmedia.read(from, end);
-	}
-	void write(mtpBuffer &to) const {
-		vcontacts.write(to);
-		vrandom_id.write(to);
-		vmessage.write(to);
-		vmedia.write(to);
-	}
-
-	typedef MTPUpdates ResponseType;
-};
-class MTPmessages_SendBroadcast : public MTPBoxed<MTPmessages_sendBroadcast> {
-public:
-	MTPmessages_SendBroadcast() {
-	}
-	MTPmessages_SendBroadcast(const MTPmessages_sendBroadcast &v) : MTPBoxed<MTPmessages_sendBroadcast>(v) {
-	}
-	MTPmessages_SendBroadcast(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_sendBroadcast>(from, end, cons) {
-	}
-	MTPmessages_SendBroadcast(const MTPVector<MTPInputUser> &_contacts, const MTPVector<MTPlong> &_random_id, const MTPstring &_message, const MTPInputMedia &_media) : MTPBoxed<MTPmessages_sendBroadcast>(MTPmessages_sendBroadcast(_contacts, _random_id, _message, _media)) {
-	}
-};
-
 class MTPmessages_getDhConfig { // RPC method 'messages.getDhConfig'
 public:
 	MTPint vversion;
@@ -22857,6 +22897,37 @@ public:
 	}
 };
 
+class MTPchannels_getAdminedPublicChannels { // RPC method 'channels.getAdminedPublicChannels'
+public:
+	MTPchannels_getAdminedPublicChannels() {
+	}
+	MTPchannels_getAdminedPublicChannels(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_channels_getAdminedPublicChannels) {
+		read(from, end, cons);
+	}
+
+	uint32 innerLength() const {
+		return 0;
+	}
+	mtpTypeId type() const {
+		return mtpc_channels_getAdminedPublicChannels;
+	}
+	void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_channels_getAdminedPublicChannels) {
+	}
+	void write(mtpBuffer &to) const {
+	}
+
+	typedef MTPmessages_Chats ResponseType;
+};
+class MTPchannels_GetAdminedPublicChannels : public MTPBoxed<MTPchannels_getAdminedPublicChannels> {
+public:
+	MTPchannels_GetAdminedPublicChannels() {
+	}
+	MTPchannels_GetAdminedPublicChannels(const MTPchannels_getAdminedPublicChannels &v) : MTPBoxed<MTPchannels_getAdminedPublicChannels>(v) {
+	}
+	MTPchannels_GetAdminedPublicChannels(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPchannels_getAdminedPublicChannels>(from, end, cons) {
+	}
+};
+
 // Creator proxy class definition
 namespace MTP {
 namespace internal {
@@ -23028,6 +23099,12 @@ public:
 	inline static MTPinputMedia new_inputMediaGifExternal(const MTPstring &_url, const MTPstring &_q) {
 		return MTPinputMedia(new MTPDinputMediaGifExternal(_url, _q));
 	}
+	inline static MTPinputMedia new_inputMediaPhotoExternal(const MTPstring &_url, const MTPstring &_caption) {
+		return MTPinputMedia(new MTPDinputMediaPhotoExternal(_url, _caption));
+	}
+	inline static MTPinputMedia new_inputMediaDocumentExternal(const MTPstring &_url, const MTPstring &_caption) {
+		return MTPinputMedia(new MTPDinputMediaDocumentExternal(_url, _caption));
+	}
 	inline static MTPinputChatPhoto new_inputChatPhotoEmpty() {
 		return MTPinputChatPhoto(mtpc_inputChatPhotoEmpty);
 	}
@@ -23286,8 +23363,8 @@ public:
 	inline static MTPauth_sentCode new_auth_sentCode(const MTPflags<MTPDauth_sentCode::Flags> &_flags, const MTPauth_SentCodeType &_type, const MTPstring &_phone_code_hash, const MTPauth_CodeType &_next_type, MTPint _timeout) {
 		return MTPauth_sentCode(new MTPDauth_sentCode(_flags, _type, _phone_code_hash, _next_type, _timeout));
 	}
-	inline static MTPauth_authorization new_auth_authorization(const MTPUser &_user) {
-		return MTPauth_authorization(new MTPDauth_authorization(_user));
+	inline static MTPauth_authorization new_auth_authorization(const MTPflags<MTPDauth_authorization::Flags> &_flags, MTPint _tmp_sessions, const MTPUser &_user) {
+		return MTPauth_authorization(new MTPDauth_authorization(_flags, _tmp_sessions, _user));
 	}
 	inline static MTPauth_exportedAuthorization new_auth_exportedAuthorization(MTPint _id, const MTPbytes &_bytes) {
 		return MTPauth_exportedAuthorization(new MTPDauth_exportedAuthorization(_id, _bytes));
@@ -23589,6 +23666,12 @@ public:
 	inline static MTPupdate new_updateRecentStickers() {
 		return MTPupdate(mtpc_updateRecentStickers);
 	}
+	inline static MTPupdate new_updateConfig() {
+		return MTPupdate(mtpc_updateConfig);
+	}
+	inline static MTPupdate new_updatePtsChanged() {
+		return MTPupdate(mtpc_updatePtsChanged);
+	}
 	inline static MTPupdates_state new_updates_state(MTPint _pts, MTPint _qts, MTPint _date, MTPint _seq, MTPint _unread_count) {
 		return MTPupdates_state(new MTPDupdates_state(_pts, _qts, _date, _seq, _unread_count));
 	}
@@ -23637,8 +23720,8 @@ public:
 	inline static MTPdcOption new_dcOption(const MTPflags<MTPDdcOption::Flags> &_flags, MTPint _id, const MTPstring &_ip_address, MTPint _port) {
 		return MTPdcOption(new MTPDdcOption(_flags, _id, _ip_address, _port));
 	}
-	inline static MTPconfig new_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, MTPint _stickers_recent_limit, const MTPVector<MTPDisabledFeature> &_disabled_features) {
-		return MTPconfig(new MTPDconfig(_date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _megagroup_size_max, _forwarded_count_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _push_chat_period_ms, _push_chat_limit, _saved_gifs_limit, _edit_time_limit, _rating_e_decay, _stickers_recent_limit, _disabled_features));
+	inline static MTPconfig new_config(const MTPflags<MTPDconfig::Flags> &_flags, MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, MTPint _stickers_recent_limit, MTPint _tmp_sessions, const MTPVector<MTPDisabledFeature> &_disabled_features) {
+		return MTPconfig(new MTPDconfig(_flags, _date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _megagroup_size_max, _forwarded_count_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _push_chat_period_ms, _push_chat_limit, _saved_gifs_limit, _edit_time_limit, _rating_e_decay, _stickers_recent_limit, _tmp_sessions, _disabled_features));
 	}
 	inline static MTPnearestDc new_nearestDc(const MTPstring &_country, MTPint _this_dc, MTPint _nearest_dc) {
 		return MTPnearestDc(new MTPDnearestDc(_country, _this_dc, _nearest_dc));
@@ -23952,8 +24035,8 @@ public:
 	inline static MTPkeyboardButton new_keyboardButtonRequestGeoLocation(const MTPstring &_text) {
 		return MTPkeyboardButton(new MTPDkeyboardButtonRequestGeoLocation(_text));
 	}
-	inline static MTPkeyboardButton new_keyboardButtonSwitchInline(const MTPstring &_text, const MTPstring &_query) {
-		return MTPkeyboardButton(new MTPDkeyboardButtonSwitchInline(_text, _query));
+	inline static MTPkeyboardButton new_keyboardButtonSwitchInline(const MTPflags<MTPDkeyboardButtonSwitchInline::Flags> &_flags, const MTPstring &_text, const MTPstring &_query) {
+		return MTPkeyboardButton(new MTPDkeyboardButtonSwitchInline(_flags, _text, _query));
 	}
 	inline static MTPkeyboardButtonRow new_keyboardButtonRow(const MTPVector<MTPKeyboardButton> &_buttons) {
 		return MTPkeyboardButtonRow(new MTPDkeyboardButtonRow(_buttons));
@@ -25535,6 +25618,14 @@ inline uint32 MTPinputMedia::innerLength() const {
 			const MTPDinputMediaGifExternal &v(c_inputMediaGifExternal());
 			return v.vurl.innerLength() + v.vq.innerLength();
 		}
+		case mtpc_inputMediaPhotoExternal: {
+			const MTPDinputMediaPhotoExternal &v(c_inputMediaPhotoExternal());
+			return v.vurl.innerLength() + v.vcaption.innerLength();
+		}
+		case mtpc_inputMediaDocumentExternal: {
+			const MTPDinputMediaDocumentExternal &v(c_inputMediaDocumentExternal());
+			return v.vurl.innerLength() + v.vcaption.innerLength();
+		}
 	}
 	return 0;
 }
@@ -25608,6 +25699,18 @@ inline void MTPinputMedia::read(const mtpPrime *&from, const mtpPrime *end, mtpT
 			v.vurl.read(from, end);
 			v.vq.read(from, end);
 		} break;
+		case mtpc_inputMediaPhotoExternal: _type = cons; {
+			if (!data) setData(new MTPDinputMediaPhotoExternal());
+			MTPDinputMediaPhotoExternal &v(_inputMediaPhotoExternal());
+			v.vurl.read(from, end);
+			v.vcaption.read(from, end);
+		} break;
+		case mtpc_inputMediaDocumentExternal: _type = cons; {
+			if (!data) setData(new MTPDinputMediaDocumentExternal());
+			MTPDinputMediaDocumentExternal &v(_inputMediaDocumentExternal());
+			v.vurl.read(from, end);
+			v.vcaption.read(from, end);
+		} break;
 		default: throw mtpErrorUnexpected(cons, "MTPinputMedia");
 	}
 }
@@ -25666,6 +25769,16 @@ inline void MTPinputMedia::write(mtpBuffer &to) const {
 			v.vurl.write(to);
 			v.vq.write(to);
 		} break;
+		case mtpc_inputMediaPhotoExternal: {
+			const MTPDinputMediaPhotoExternal &v(c_inputMediaPhotoExternal());
+			v.vurl.write(to);
+			v.vcaption.write(to);
+		} break;
+		case mtpc_inputMediaDocumentExternal: {
+			const MTPDinputMediaDocumentExternal &v(c_inputMediaDocumentExternal());
+			v.vurl.write(to);
+			v.vcaption.write(to);
+		} break;
 	}
 }
 inline MTPinputMedia::MTPinputMedia(mtpTypeId type) : mtpDataOwner(0), _type(type) {
@@ -25680,6 +25793,8 @@ inline MTPinputMedia::MTPinputMedia(mtpTypeId type) : mtpDataOwner(0), _type(typ
 		case mtpc_inputMediaDocument: setData(new MTPDinputMediaDocument()); break;
 		case mtpc_inputMediaVenue: setData(new MTPDinputMediaVenue()); break;
 		case mtpc_inputMediaGifExternal: setData(new MTPDinputMediaGifExternal()); break;
+		case mtpc_inputMediaPhotoExternal: setData(new MTPDinputMediaPhotoExternal()); break;
+		case mtpc_inputMediaDocumentExternal: setData(new MTPDinputMediaDocumentExternal()); break;
 		default: throw mtpErrorBadTypeId(type, "MTPinputMedia");
 	}
 }
@@ -25701,6 +25816,10 @@ inline MTPinputMedia::MTPinputMedia(MTPDinputMediaVenue *_data) : mtpDataOwner(_
 }
 inline MTPinputMedia::MTPinputMedia(MTPDinputMediaGifExternal *_data) : mtpDataOwner(_data), _type(mtpc_inputMediaGifExternal) {
 }
+inline MTPinputMedia::MTPinputMedia(MTPDinputMediaPhotoExternal *_data) : mtpDataOwner(_data), _type(mtpc_inputMediaPhotoExternal) {
+}
+inline MTPinputMedia::MTPinputMedia(MTPDinputMediaDocumentExternal *_data) : mtpDataOwner(_data), _type(mtpc_inputMediaDocumentExternal) {
+}
 inline MTPinputMedia MTP_inputMediaEmpty() {
 	return MTP::internal::TypeCreator::new_inputMediaEmpty();
 }
@@ -25731,6 +25850,12 @@ inline MTPinputMedia MTP_inputMediaVenue(const MTPInputGeoPoint &_geo_point, con
 inline MTPinputMedia MTP_inputMediaGifExternal(const MTPstring &_url, const MTPstring &_q) {
 	return MTP::internal::TypeCreator::new_inputMediaGifExternal(_url, _q);
 }
+inline MTPinputMedia MTP_inputMediaPhotoExternal(const MTPstring &_url, const MTPstring &_caption) {
+	return MTP::internal::TypeCreator::new_inputMediaPhotoExternal(_url, _caption);
+}
+inline MTPinputMedia MTP_inputMediaDocumentExternal(const MTPstring &_url, const MTPstring &_caption) {
+	return MTP::internal::TypeCreator::new_inputMediaDocumentExternal(_url, _caption);
+}
 
 inline uint32 MTPinputChatPhoto::innerLength() const {
 	switch (_type) {
@@ -27848,7 +27973,7 @@ inline MTPauth_authorization::MTPauth_authorization() : mtpDataOwner(new MTPDaut
 
 inline uint32 MTPauth_authorization::innerLength() const {
 	const MTPDauth_authorization &v(c_auth_authorization());
-	return v.vuser.innerLength();
+	return v.vflags.innerLength() + (v.has_tmp_sessions() ? v.vtmp_sessions.innerLength() : 0) + v.vuser.innerLength();
 }
 inline mtpTypeId MTPauth_authorization::type() const {
 	return mtpc_auth_authorization;
@@ -27858,16 +27983,21 @@ inline void MTPauth_authorization::read(const mtpPrime *&from, const mtpPrime *e
 
 	if (!data) setData(new MTPDauth_authorization());
 	MTPDauth_authorization &v(_auth_authorization());
+	v.vflags.read(from, end);
+	if (v.has_tmp_sessions()) { v.vtmp_sessions.read(from, end); } else { v.vtmp_sessions = MTPint(); }
 	v.vuser.read(from, end);
 }
 inline void MTPauth_authorization::write(mtpBuffer &to) const {
 	const MTPDauth_authorization &v(c_auth_authorization());
+	v.vflags.write(to);
+	if (v.has_tmp_sessions()) v.vtmp_sessions.write(to);
 	v.vuser.write(to);
 }
 inline MTPauth_authorization::MTPauth_authorization(MTPDauth_authorization *_data) : mtpDataOwner(_data) {
 }
-inline MTPauth_authorization MTP_auth_authorization(const MTPUser &_user) {
-	return MTP::internal::TypeCreator::new_auth_authorization(_user);
+Q_DECLARE_OPERATORS_FOR_FLAGS(MTPDauth_authorization::Flags)
+inline MTPauth_authorization MTP_auth_authorization(const MTPflags<MTPDauth_authorization::Flags> &_flags, MTPint _tmp_sessions, const MTPUser &_user) {
+	return MTP::internal::TypeCreator::new_auth_authorization(_flags, _tmp_sessions, _user);
 }
 
 inline MTPauth_exportedAuthorization::MTPauth_exportedAuthorization() : mtpDataOwner(new MTPDauth_exportedAuthorization()) {
@@ -29473,6 +29603,8 @@ inline void MTPupdate::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI
 		} break;
 		case mtpc_updateReadFeaturedStickers: _type = cons; break;
 		case mtpc_updateRecentStickers: _type = cons; break;
+		case mtpc_updateConfig: _type = cons; break;
+		case mtpc_updatePtsChanged: _type = cons; break;
 		default: throw mtpErrorUnexpected(cons, "MTPupdate");
 	}
 }
@@ -29808,6 +29940,8 @@ inline MTPupdate::MTPupdate(mtpTypeId type) : mtpDataOwner(0), _type(type) {
 		case mtpc_updateDraftMessage: setData(new MTPDupdateDraftMessage()); break;
 		case mtpc_updateReadFeaturedStickers: break;
 		case mtpc_updateRecentStickers: break;
+		case mtpc_updateConfig: break;
+		case mtpc_updatePtsChanged: break;
 		default: throw mtpErrorBadTypeId(type, "MTPupdate");
 	}
 }
@@ -30061,6 +30195,12 @@ inline MTPupdate MTP_updateReadFeaturedStickers() {
 inline MTPupdate MTP_updateRecentStickers() {
 	return MTP::internal::TypeCreator::new_updateRecentStickers();
 }
+inline MTPupdate MTP_updateConfig() {
+	return MTP::internal::TypeCreator::new_updateConfig();
+}
+inline MTPupdate MTP_updatePtsChanged() {
+	return MTP::internal::TypeCreator::new_updatePtsChanged();
+}
 
 inline MTPupdates_state::MTPupdates_state() : mtpDataOwner(new MTPDupdates_state()) {
 }
@@ -30590,7 +30730,7 @@ inline MTPconfig::MTPconfig() : mtpDataOwner(new MTPDconfig()) {
 
 inline uint32 MTPconfig::innerLength() const {
 	const MTPDconfig &v(c_config());
-	return v.vdate.innerLength() + v.vexpires.innerLength() + v.vtest_mode.innerLength() + v.vthis_dc.innerLength() + v.vdc_options.innerLength() + v.vchat_size_max.innerLength() + v.vmegagroup_size_max.innerLength() + v.vforwarded_count_max.innerLength() + v.vonline_update_period_ms.innerLength() + v.voffline_blur_timeout_ms.innerLength() + v.voffline_idle_timeout_ms.innerLength() + v.vonline_cloud_timeout_ms.innerLength() + v.vnotify_cloud_delay_ms.innerLength() + v.vnotify_default_delay_ms.innerLength() + v.vchat_big_size.innerLength() + v.vpush_chat_period_ms.innerLength() + v.vpush_chat_limit.innerLength() + v.vsaved_gifs_limit.innerLength() + v.vedit_time_limit.innerLength() + v.vrating_e_decay.innerLength() + v.vstickers_recent_limit.innerLength() + v.vdisabled_features.innerLength();
+	return v.vflags.innerLength() + v.vdate.innerLength() + v.vexpires.innerLength() + v.vtest_mode.innerLength() + v.vthis_dc.innerLength() + v.vdc_options.innerLength() + v.vchat_size_max.innerLength() + v.vmegagroup_size_max.innerLength() + v.vforwarded_count_max.innerLength() + v.vonline_update_period_ms.innerLength() + v.voffline_blur_timeout_ms.innerLength() + v.voffline_idle_timeout_ms.innerLength() + v.vonline_cloud_timeout_ms.innerLength() + v.vnotify_cloud_delay_ms.innerLength() + v.vnotify_default_delay_ms.innerLength() + v.vchat_big_size.innerLength() + v.vpush_chat_period_ms.innerLength() + v.vpush_chat_limit.innerLength() + v.vsaved_gifs_limit.innerLength() + v.vedit_time_limit.innerLength() + v.vrating_e_decay.innerLength() + v.vstickers_recent_limit.innerLength() + (v.has_tmp_sessions() ? v.vtmp_sessions.innerLength() : 0) + v.vdisabled_features.innerLength();
 }
 inline mtpTypeId MTPconfig::type() const {
 	return mtpc_config;
@@ -30600,6 +30740,7 @@ inline void MTPconfig::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI
 
 	if (!data) setData(new MTPDconfig());
 	MTPDconfig &v(_config());
+	v.vflags.read(from, end);
 	v.vdate.read(from, end);
 	v.vexpires.read(from, end);
 	v.vtest_mode.read(from, end);
@@ -30621,10 +30762,12 @@ inline void MTPconfig::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI
 	v.vedit_time_limit.read(from, end);
 	v.vrating_e_decay.read(from, end);
 	v.vstickers_recent_limit.read(from, end);
+	if (v.has_tmp_sessions()) { v.vtmp_sessions.read(from, end); } else { v.vtmp_sessions = MTPint(); }
 	v.vdisabled_features.read(from, end);
 }
 inline void MTPconfig::write(mtpBuffer &to) const {
 	const MTPDconfig &v(c_config());
+	v.vflags.write(to);
 	v.vdate.write(to);
 	v.vexpires.write(to);
 	v.vtest_mode.write(to);
@@ -30646,12 +30789,14 @@ inline void MTPconfig::write(mtpBuffer &to) const {
 	v.vedit_time_limit.write(to);
 	v.vrating_e_decay.write(to);
 	v.vstickers_recent_limit.write(to);
+	if (v.has_tmp_sessions()) v.vtmp_sessions.write(to);
 	v.vdisabled_features.write(to);
 }
 inline MTPconfig::MTPconfig(MTPDconfig *_data) : mtpDataOwner(_data) {
 }
-inline MTPconfig MTP_config(MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, MTPint _stickers_recent_limit, const MTPVector<MTPDisabledFeature> &_disabled_features) {
-	return MTP::internal::TypeCreator::new_config(_date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _megagroup_size_max, _forwarded_count_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _push_chat_period_ms, _push_chat_limit, _saved_gifs_limit, _edit_time_limit, _rating_e_decay, _stickers_recent_limit, _disabled_features);
+Q_DECLARE_OPERATORS_FOR_FLAGS(MTPDconfig::Flags)
+inline MTPconfig MTP_config(const MTPflags<MTPDconfig::Flags> &_flags, MTPint _date, MTPint _expires, MTPBool _test_mode, MTPint _this_dc, const MTPVector<MTPDcOption> &_dc_options, MTPint _chat_size_max, MTPint _megagroup_size_max, MTPint _forwarded_count_max, MTPint _online_update_period_ms, MTPint _offline_blur_timeout_ms, MTPint _offline_idle_timeout_ms, MTPint _online_cloud_timeout_ms, MTPint _notify_cloud_delay_ms, MTPint _notify_default_delay_ms, MTPint _chat_big_size, MTPint _push_chat_period_ms, MTPint _push_chat_limit, MTPint _saved_gifs_limit, MTPint _edit_time_limit, MTPint _rating_e_decay, MTPint _stickers_recent_limit, MTPint _tmp_sessions, const MTPVector<MTPDisabledFeature> &_disabled_features) {
+	return MTP::internal::TypeCreator::new_config(_flags, _date, _expires, _test_mode, _this_dc, _dc_options, _chat_size_max, _megagroup_size_max, _forwarded_count_max, _online_update_period_ms, _offline_blur_timeout_ms, _offline_idle_timeout_ms, _online_cloud_timeout_ms, _notify_cloud_delay_ms, _notify_default_delay_ms, _chat_big_size, _push_chat_period_ms, _push_chat_limit, _saved_gifs_limit, _edit_time_limit, _rating_e_decay, _stickers_recent_limit, _tmp_sessions, _disabled_features);
 }
 
 inline MTPnearestDc::MTPnearestDc() : mtpDataOwner(new MTPDnearestDc()) {
@@ -33077,7 +33222,7 @@ inline uint32 MTPkeyboardButton::innerLength() const {
 		}
 		case mtpc_keyboardButtonSwitchInline: {
 			const MTPDkeyboardButtonSwitchInline &v(c_keyboardButtonSwitchInline());
-			return v.vtext.innerLength() + v.vquery.innerLength();
+			return v.vflags.innerLength() + v.vtext.innerLength() + v.vquery.innerLength();
 		}
 	}
 	return 0;
@@ -33119,6 +33264,7 @@ inline void MTPkeyboardButton::read(const mtpPrime *&from, const mtpPrime *end,
 		case mtpc_keyboardButtonSwitchInline: _type = cons; {
 			if (!data) setData(new MTPDkeyboardButtonSwitchInline());
 			MTPDkeyboardButtonSwitchInline &v(_keyboardButtonSwitchInline());
+			v.vflags.read(from, end);
 			v.vtext.read(from, end);
 			v.vquery.read(from, end);
 		} break;
@@ -33151,6 +33297,7 @@ inline void MTPkeyboardButton::write(mtpBuffer &to) const {
 		} break;
 		case mtpc_keyboardButtonSwitchInline: {
 			const MTPDkeyboardButtonSwitchInline &v(c_keyboardButtonSwitchInline());
+			v.vflags.write(to);
 			v.vtext.write(to);
 			v.vquery.write(to);
 		} break;
@@ -33194,8 +33341,9 @@ inline MTPkeyboardButton MTP_keyboardButtonRequestPhone(const MTPstring &_text)
 inline MTPkeyboardButton MTP_keyboardButtonRequestGeoLocation(const MTPstring &_text) {
 	return MTP::internal::TypeCreator::new_keyboardButtonRequestGeoLocation(_text);
 }
-inline MTPkeyboardButton MTP_keyboardButtonSwitchInline(const MTPstring &_text, const MTPstring &_query) {
-	return MTP::internal::TypeCreator::new_keyboardButtonSwitchInline(_text, _query);
+Q_DECLARE_OPERATORS_FOR_FLAGS(MTPDkeyboardButtonSwitchInline::Flags)
+inline MTPkeyboardButton MTP_keyboardButtonSwitchInline(const MTPflags<MTPDkeyboardButtonSwitchInline::Flags> &_flags, const MTPstring &_text, const MTPstring &_query) {
+	return MTP::internal::TypeCreator::new_keyboardButtonSwitchInline(_flags, _text, _query);
 }
 
 inline MTPkeyboardButtonRow::MTPkeyboardButtonRow() : mtpDataOwner(new MTPDkeyboardButtonRow()) {
diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj
index fe6751439..e9aac31ac 100644
--- a/Telegram/Telegram.vcxproj
+++ b/Telegram/Telegram.vcxproj
@@ -1581,6 +1581,7 @@
     </CustomBuild>
     <ClInclude Include="SourceFiles\core\click_handler.h" />
     <ClInclude Include="SourceFiles\core\click_handler_types.h" />
+    <ClInclude Include="SourceFiles\core\lambda_wrap.h" />
     <ClInclude Include="SourceFiles\core\observer.h" />
     <ClInclude Include="SourceFiles\core\qthelp_regex.h" />
     <ClInclude Include="SourceFiles\core\qthelp_url.h" />
diff --git a/Telegram/Telegram.vcxproj.filters b/Telegram/Telegram.vcxproj.filters
index ef9cabae0..3280ee544 100644
--- a/Telegram/Telegram.vcxproj.filters
+++ b/Telegram/Telegram.vcxproj.filters
@@ -1754,6 +1754,9 @@
     <ClInclude Include="SourceFiles\core\qthelp_url.h">
       <Filter>SourceFiles\core</Filter>
     </ClInclude>
+    <ClInclude Include="SourceFiles\core\lambda_wrap.h">
+      <Filter>SourceFiles\core</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="SourceFiles\application.h">