diff --git a/Telegram/PrepareWin.bat b/Telegram/PrepareWin.bat
index 1b4532518..868329c42 100644
--- a/Telegram/PrepareWin.bat
+++ b/Telegram/PrepareWin.bat
@@ -1,11 +1,11 @@
 @echo OFF
 
 set "AppVersionStrMajor=0.8"
-set "AppVersion=8048"
-set "AppVersionStrSmall=0.8.48"
-set "AppVersionStr=0.8.48"
-set "AppVersionStrFull=0.8.48.0"
-set "DevChannel=0"
+set "AppVersion=8049"
+set "AppVersionStrSmall=0.8.49"
+set "AppVersionStr=0.8.49"
+set "AppVersionStrFull=0.8.49.0"
+set "DevChannel=1"
 
 if %DevChannel% neq 0 goto preparedev
 
diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings
index 19528d4ac..b51067d5c 100644
--- a/Telegram/Resources/lang.strings
+++ b/Telegram/Resources/lang.strings
@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
 "lng_reconnecting_try_now" = "Try now";
 
 "lng_status_service_notifications" = "service notifications";
+"lng_status_support" = "support";
 "lng_status_bot" = "bot";
 "lng_status_bot_reads_all" = "has access to messages";
 "lng_status_bot_not_reads_all" = "has no access to messages";
@@ -324,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
 "lng_settings_reset_one_sure" = "Do you want to terminate this session?";
 "lng_settings_reset_button" = "Terminate";
 "lng_settings_reset_done" = "Other sessions terminated";
+"lng_settings_ask_question" = "Ask a Question";
+"lng_settings_ask_sure" = "Please note that Telegram Support is done by volunteers. We try to respond as quickly as possible, but it may take a while.\n\nPlease take a look at the Telegram FAQ: it has important troubleshooting tips and answers to most questions.";
+"lng_settings_faq_button" = "Go to FAQ";
+"lng_settings_ask_ok" = "Ask";
+"lng_settings_faq" = "Telegram FAQ";
 "lng_settings_logout" = "Log Out";
 "lng_sure_logout" = "Are you sure you want to log out?";
 
@@ -356,6 +362,10 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
 "lng_profile_delete_conversation" = "Delete conversation";
 "lng_profile_clear_and_exit" = "Delete and exit";
 "lng_profile_search_messages" = "Search for messages";
+"lng_profile_block_user" = "Block user";
+"lng_profile_unblock_user" = "Unblock user";
+"lng_profile_block_bot" = "Stop and block bot";
+"lng_profile_unblock_bot" = "Unblock bot";
 "lng_profile_send_message" = "Send Message";
 "lng_profile_share_contact" = "Share Contact";
 "lng_profile_invite_to_group" = "Add to Group";
@@ -476,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
 "lng_message_with_from" = "[c]{from}:[/c] {message}";
 "lng_from_you" = "You";
 "lng_bot_description" = "What can this bot do?";
+"lng_unblock_button" = "Unblock";
 
 "lng_bot_start" = "Start";
 "lng_bot_choose_group" = "Choose Group";
diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt
index e2658c14c..bdc6e4276 100644
--- a/Telegram/Resources/style.txt
+++ b/Telegram/Resources/style.txt
@@ -972,6 +972,11 @@ btnSend: flatButton(btnDefFlat) {
 	font: font(16px);
 	overFont: font(16px);
 }
+btnUnblock: flatButton(btnSend) {
+	color: #d15948;
+	overColor: #d15948;
+	downColor: #db6352;
+}
 
 btnAttachDocument: iconedButton(btnDefIconed) {
 	icon: sprite(218px, 68px, 24px, 24px);
diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp
index 75d8187c7..a0fe57772 100644
--- a/Telegram/SourceFiles/apiwrap.cpp
+++ b/Telegram/SourceFiles/apiwrap.cpp
@@ -199,6 +199,7 @@ void ApiWrap::gotUserFull(PeerData *peer, const MTPUserFull &result) {
 	App::main()->gotNotifySetting(MTP_inputNotifyPeer(peer->input), d.vnotify_settings);
 
 	peer->asUser()->setBotInfo(d.vbot_info);
+	peer->asUser()->blocked = d.vblocked.v ? UserIsBlocked : UserIsNotBlocked;
 
 	_fullPeerRequests.remove(peer);
 	App::clearPeerUpdated(peer);
diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp
index ac3773b9e..1a31593ba 100644
--- a/Telegram/SourceFiles/app.cpp
+++ b/Telegram/SourceFiles/app.cpp
@@ -289,8 +289,10 @@ namespace App {
 	}
 
 	QString onlineText(UserData *user, int32 now, bool precise) {
-		if (isServiceUser(user->id)) {
+		if (isNotificationsUser(user->id)) {
 			return lang(lng_status_service_notifications);
+		} else if (isServiceUser(user->id)) {
+			return lang(lng_status_support);
 		} else if (user->botInfo) {
 			return lang(lng_status_bot);
 		}
@@ -370,8 +372,8 @@ namespace App {
 
 				PeerId peer(peerFromUser(d.vid.v));
 				data = App::user(peer);
-				data->input = MTP_inputPeerContact(d.vid);
-				data->inputUser = MTP_inputUserContact(d.vid);
+				data->input = MTP_inputPeerUser(d.vid, MTP_long(0));
+				data->inputUser = MTP_inputUser(d.vid, MTP_long(0));
 				data->setName(lang(lng_deleted), QString(), QString(), QString());
 				data->setPhoto(MTP_userProfilePhotoEmpty());
 				data->access = UserNoAccess;
@@ -389,12 +391,12 @@ namespace App {
 				if (flags & MTPDuser_flag_self) {
 					data->input = MTP_inputPeerSelf();
 					data->inputUser = MTP_inputUserSelf();
-				} else if ((flags & (MTPDuser_flag_contact | MTPDuser_flag_mutual_contact)) || !d.has_access_hash()) {
-					data->input = MTP_inputPeerContact(d.vid);
-					data->inputUser = MTP_inputUserContact(d.vid);
+				} else if (!d.has_access_hash()) {
+					data->input = MTP_inputPeerUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access));
+					data->inputUser = MTP_inputUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access));
 				} else {
-					data->input = MTP_inputPeerForeign(d.vid, d.vaccess_hash);
-					data->inputUser = MTP_inputUserForeign(d.vid, d.vaccess_hash);
+					data->input = MTP_inputPeerUser(d.vid, d.vaccess_hash);
+					data->inputUser = MTP_inputUser(d.vid, d.vaccess_hash);
 				}
 				if (flags & MTPDuser_flag_deleted) {
 					data->setPhone(QString());
@@ -868,14 +870,8 @@ namespace App {
 			if (user->contact > 0) {
 				if (!wasContact) {
 					App::main()->addNewContact(App::userFromPeer(user->id), false);
-					if (user->input.type() != mtpc_inputPeerSelf) user->input = MTP_inputPeerContact(userId);
-					if (user->inputUser.type() != mtpc_inputUserSelf) user->inputUser = MTP_inputUserContact(userId);
 				}
 			} else {
-				if (user->access && user->access != UserNoAccess) {
-					if (user->input.type() != mtpc_inputPeerSelf) user->input = MTP_inputPeerForeign(userId, MTP_long(user->access));
-					if (user->inputUser.type() != mtpc_inputUserSelf) user->inputUser = MTP_inputUserForeign(userId, MTP_long(user->access));
-				}
 				if (user->contact < 0 && !user->phone.isEmpty() && App::userFromPeer(user->id) != MTP::authedId()) {
 					user->contact = 0;
 				}
@@ -924,7 +920,7 @@ namespace App {
 			return feedPhoto(photo.c_photo(), convert);
 		} break;
 		case mtpc_photoEmpty: {
-			return App::photoSet(photo.c_photoEmpty().vid.v, convert, 0, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
+			return App::photoSet(photo.c_photoEmpty().vid.v, convert, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
 		} break;
 		}
 		return App::photo(0);
@@ -968,7 +964,7 @@ namespace App {
 		switch (photo.type()) {
 		case mtpc_photo: {
 			const MTPDphoto &ph(photo.c_photo());
-			return App::photoSet(ph.vid.v, 0, ph.vaccess_hash.v, ph.vuser_id.v, ph.vdate.v, ImagePtr(*thumb, "JPG"), ImagePtr(*medium, "JPG"), ImagePtr(*full, "JPG"));
+			return App::photoSet(ph.vid.v, 0, ph.vaccess_hash.v, ph.vdate.v, ImagePtr(*thumb, "JPG"), ImagePtr(*medium, "JPG"), ImagePtr(*full, "JPG"));
 		} break;
 		case mtpc_photoEmpty: return App::photo(photo.c_photoEmpty().vid.v);
 		}
@@ -1023,13 +1019,13 @@ namespace App {
 			}
 		}
 		if (thumb && medium && full) {
-			return App::photoSet(photo.vid.v, convert, photo.vaccess_hash.v, photo.vuser_id.v, photo.vdate.v, App::image(*thumb), App::image(*medium), App::image(*full));
+			return App::photoSet(photo.vid.v, convert, photo.vaccess_hash.v, photo.vdate.v, App::image(*thumb), App::image(*medium), App::image(*full));
 		}
-		return App::photoSet(photo.vid.v, convert, 0, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
+		return App::photoSet(photo.vid.v, convert, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
 	}
 	
 	VideoData *feedVideo(const MTPDvideo &video, VideoData *convert) {
-		return App::videoSet(video.vid.v, convert, video.vaccess_hash.v, video.vuser_id.v, video.vdate.v, video.vduration.v, video.vw.v, video.vh.v, App::image(video.vthumb), video.vdc_id.v, video.vsize.v);
+		return App::videoSet(video.vid.v, convert, video.vaccess_hash.v, video.vdate.v, video.vduration.v, video.vw.v, video.vh.v, App::image(video.vthumb), video.vdc_id.v, video.vsize.v);
 	}
 
 	AudioData *feedAudio(const MTPaudio &audio, AudioData *convert) {
@@ -1038,14 +1034,14 @@ namespace App {
 			return feedAudio(audio.c_audio(), convert);
 		} break;
 		case mtpc_audioEmpty: {
-			return App::audioSet(audio.c_audioEmpty().vid.v, convert, 0, 0, 0, QString(), 0, 0, 0);
+			return App::audioSet(audio.c_audioEmpty().vid.v, convert, 0, 0, QString(), 0, 0, 0);
 		} break;
 		}
 		return App::audio(0);
 	}
 
 	AudioData *feedAudio(const MTPDaudio &audio, AudioData *convert) {
-		return App::audioSet(audio.vid.v, convert, audio.vaccess_hash.v, audio.vuser_id.v, audio.vdate.v, qs(audio.vmime_type), audio.vduration.v, audio.vdc_id.v, audio.vsize.v);
+		return App::audioSet(audio.vid.v, convert, audio.vaccess_hash.v, audio.vdate.v, qs(audio.vmime_type), audio.vduration.v, audio.vdc_id.v, audio.vsize.v);
 	}
 
 	DocumentData *feedDocument(const MTPdocument &document, const QPixmap &thumb) {
@@ -1172,7 +1168,7 @@ namespace App {
 		return i.value();
 	}
 
-	PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 user, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) {
+	PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) {
 		if (convert) {
 			if (convert->id != photo) {
 				PhotosData::iterator i = photosData.find(convert->id);
@@ -1182,8 +1178,7 @@ namespace App {
 				convert->id = photo;
 			}
 			convert->access = access;
-			if (!convert->user && !convert->date && (user || date)) {
-				convert->user = user;
+			if (!convert->date && date) {
 				convert->date = date;
 				convert->thumb = thumb;
 				convert->medium = medium;
@@ -1197,14 +1192,13 @@ namespace App {
 			if (convert) {
 				result = convert;
 			} else {
-				result = new PhotoData(photo, access, user, date, thumb, medium, full);
+				result = new PhotoData(photo, access, date, thumb, medium, full);
 			}
 			photosData.insert(photo, result);
 		} else {
 			result = i.value();
-			if (result != convert && !result->user && !result->date && (user || date)) {
+			if (result != convert && !result->date && date) {
 				result->access = access;
-				result->user = user;
 				result->date = date;
 				result->thumb = thumb;
 				result->medium = medium;
@@ -1234,7 +1228,7 @@ namespace App {
 		return i.value();
 	}
 
-	VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) {
+	VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) {
 		if (convert) {
 			if (convert->id != video) {
 				VideosData::iterator i = videosData.find(convert->id);
@@ -1245,8 +1239,7 @@ namespace App {
 				convert->status = FileReady;
 			}
 			convert->access = access;
-			if (!convert->user && !convert->date && (user || date)) {
-				convert->user = user;
+			if (!convert->date && date) {
 				convert->date = date;
 				convert->duration = duration;
 				convert->w = w;
@@ -1262,14 +1255,13 @@ namespace App {
 			if (convert) {
 				result = convert;
 			} else {
-				result = new VideoData(video, access, user, date, duration, w, h, thumb, dc, size);
+				result = new VideoData(video, access, date, duration, w, h, thumb, dc, size);
 			}
 			videosData.insert(video, result);
 		} else {
 			result = i.value();
-			if (result != convert && !result->user && !result->date && (user || date)) {
+			if (result != convert && !result->date && date) {
 				result->access = access;
-				result->user = user;
 				result->date = date;
 				result->duration = duration;
 				result->w = w;
@@ -1290,7 +1282,7 @@ namespace App {
 		return i.value();
 	}
 
-	AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) {
+	AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) {
 		if (convert) {
 			if (convert->id != audio) {
 				AudiosData::iterator i = audiosData.find(convert->id);
@@ -1301,8 +1293,7 @@ namespace App {
 				convert->status = FileReady;
 			}
 			convert->access = access;
-			if (!convert->user && !convert->date && (user || date)) {
-				convert->user = user;
+			if (!convert->date && date) {
 				convert->date = date;
 				convert->mime = mime;
 				convert->duration = duration;
@@ -1316,14 +1307,13 @@ namespace App {
 			if (convert) {
 				result = convert;
 			} else {
-				result = new AudioData(audio, access, user, date, mime, duration, dc, size);
+				result = new AudioData(audio, access, date, mime, duration, dc, size);
 			}
 			audiosData.insert(audio, result);
 		} else {
 			result = i.value();
-			if (result != convert && !result->user && !result->date && (user || date)) {
+			if (result != convert && !result->date && date) {
 				result->access = access;
-				result->user = user;
 				result->date = date;
 				result->mime = mime;
 				result->duration = duration;
@@ -1547,7 +1537,7 @@ namespace App {
 			photoSizes.push_back(MTP_photoSize(MTP_string("a"), uphoto.vphoto_small, MTP_int(160), MTP_int(160), MTP_int(0)));
 			photoSizes.push_back(MTP_photoSize(MTP_string("c"), uphoto.vphoto_big, MTP_int(640), MTP_int(640), MTP_int(0)));
 
-			return MTP_photo(uphoto.vphoto_id, MTP_long(0), userId, date, MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes));
+			return MTP_photo(uphoto.vphoto_id, MTP_long(0), date, MTP_vector<MTPPhotoSize>(photoSizes));
 		}
 		return MTP_photoEmpty(MTP_long(0));
 	}
diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h
index 1033ef90d..a68c390c3 100644
--- a/Telegram/SourceFiles/app.h
+++ b/Telegram/SourceFiles/app.h
@@ -158,11 +158,11 @@ namespace App {
 	ChatData *chat(int32 chat);
 	QString peerName(const PeerData *peer, bool forDialogs = false);
 	PhotoData *photo(const PhotoId &photo);
-	PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 user, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
+	PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
 	VideoData *video(const VideoId &video);
-	VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size);
+	VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size);
 	AudioData *audio(const AudioId &audio);
-	AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size);
+	AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size);
 	DocumentData *document(const DocumentId &document);
 	DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation);
 	WebPageData *webPage(const WebPageId &webPage);
diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp
index 83e1334c3..867e035fa 100644
--- a/Telegram/SourceFiles/application.cpp
+++ b/Telegram/SourceFiles/application.cpp
@@ -474,7 +474,7 @@ void Application::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId)
 
 	PhotoId id = MTP::nonce<PhotoId>();
 
-	MTPPhoto photo(MTP_photo(MTP_long(id), MTP_long(0), MTP_int(MTP::authedId()), MTP_int(unixtime()), MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes)));
+	MTPPhoto photo(MTP_photo(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_vector<MTPPhotoSize>(photoSizes)));
 
 	QString file, filename;
 	int32 filesize = 0;
@@ -658,8 +658,8 @@ void Application::checkMapVersion() {
 		psRegisterCustomScheme();
 		if (Local::oldMapVersion()) {
 			QString versionFeatures;
-			if (cDevVersion() && Local::oldMapVersion() < 8047) {
-				versionFeatures = QString::fromUtf8("\xe2\x80\x94 Search for messages in conversation\n\xe2\x80\x94 Clear messages history in groups\n\xe2\x80\x94 Contacts without messages are hidden from the conversations list");// .replace('@', qsl("@") + QChar(0x200D));
+			if (cDevVersion() && Local::oldMapVersion() < 8049) {
+				versionFeatures = QString::fromUtf8("\xe2\x80\x94 Block users from user profile\n\xe2\x80\x94 Ask support team a question from Settings\n\xe2\x80\x94 Windows toast notifications support added");// .replace('@', qsl("@") + QChar(0x200D));
 			} else if (!cDevVersion() && Local::oldMapVersion() < 8048) {
 				versionFeatures = lang(lng_new_version_text).trimmed();
 			}
diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp
index 8231651ea..bd4ed0d01 100644
--- a/Telegram/SourceFiles/boxes/confirmbox.cpp
+++ b/Telegram/SourceFiles/boxes/confirmbox.cpp
@@ -56,19 +56,24 @@ void ConfirmBox::init(const QString &text) {
 		_confirm.hide();
 		_cancel.hide();
 
-		connect(&_close, SIGNAL(clicked()), this, SLOT(onClose()));
+		connect(&_close, SIGNAL(clicked()), this, SLOT(onCancel()));
 
 		setMouseTracking(_text.hasLinks());
 	} else {
 		_close.hide();
 
 		connect(&_confirm, SIGNAL(clicked()), this, SIGNAL(confirmed()));
-		connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
+		connect(&_cancel, SIGNAL(clicked()), this, SLOT(onCancel()));
 	}
 
 	prepare();
 }
 
+void ConfirmBox::onCancel() {
+	emit cancelPressed();
+	onClose();
+}
+
 void ConfirmBox::mouseMoveEvent(QMouseEvent *e) {
 	_lastMousePos = e->globalPos();
 	updateHover();
diff --git a/Telegram/SourceFiles/boxes/confirmbox.h b/Telegram/SourceFiles/boxes/confirmbox.h
index 2cbf4de9f..1a54c33ac 100644
--- a/Telegram/SourceFiles/boxes/confirmbox.h
+++ b/Telegram/SourceFiles/boxes/confirmbox.h
@@ -35,10 +35,15 @@ public:
 	void leaveEvent(QEvent *e);
 	void updateLink();
 
+public slots:
+
+	void onCancel();
+
 signals:
 
 	void confirmed();
 	void cancelled();
+	void cancelPressed();
 
 protected:
 
diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h
index b53fe420e..7caebfc95 100644
--- a/Telegram/SourceFiles/config.h
+++ b/Telegram/SourceFiles/config.h
@@ -17,9 +17,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
 */
 #pragma once
 
-static const int32 AppVersion = 8048;
-static const wchar_t *AppVersionStr = L"0.8.48";
-static const bool DevVersion = false;
+static const int32 AppVersion = 8049;
+static const wchar_t *AppVersionStr = L"0.8.49";
+static const bool DevVersion = true;
 
 static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
 static const wchar_t *AppName = L"Telegram Desktop";
@@ -144,10 +144,14 @@ enum {
 	ChoosePeerByDragTimeout = 1000, // 1 second mouse not moved to choose dialog when dragging a file
 };
 
-inline bool isServiceUser(uint64 id) {
+inline bool isNotificationsUser(uint64 id) {
 	return (id == 333000) || (id == ServiceUserId);
 }
 
+inline bool isServiceUser(uint64 id) {
+	return !(id % 1000);// (id == 333000) || (id == ServiceUserId);
+}
+
 #ifdef Q_OS_WIN
 inline const GUID &cGUID() {
 	static const GUID gGuid = { 0x87a94ab0, 0xe370, 0x4cde, { 0x98, 0xd3, 0xac, 0xc1, 0x10, 0xc5, 0x96, 0x7d } };
diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp
index 6e506cc1a..a26a190f0 100644
--- a/Telegram/SourceFiles/historywidget.cpp
+++ b/Telegram/SourceFiles/historywidget.cpp
@@ -75,7 +75,9 @@ HistoryList::HistoryList(HistoryWidget *historyWidget, ScrollArea *scroll, Histo
 
 	_trippleClickTimer.setSingleShot(true);
 
-	if (botInfo && !botInfo->inited) App::api()->requestFullPeer(hist->peer);
+	if (botInfo && !botInfo->inited) {
+		App::api()->requestFullPeer(hist->peer);
+	}
 
 	setMouseTracking(true);
 }
@@ -2200,7 +2202,9 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
 , _toHistoryEnd(this, st::historyToEnd)
 , _attachMention(this)
 , _send(this, lang(lng_send_button), st::btnSend)
+, _unblock(this, lang(lng_unblock_button), st::btnUnblock)
 , _botStart(this, lang(lng_bot_start), st::btnSend)
+, _unblockRequest(0)
 , _attachDocument(this, st::btnAttachDocument)
 , _attachPhoto(this, st::btnAttachPhoto)
 , _attachEmoji(this, st::btnAttachEmoji)
@@ -2243,6 +2247,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
 	connect(&_toHistoryEnd, SIGNAL(clicked()), this, SLOT(onHistoryToEnd()));
 	connect(&_replyForwardPreviewCancel, SIGNAL(clicked()), this, SLOT(onReplyForwardPreviewCancel()));
 	connect(&_send, SIGNAL(clicked()), this, SLOT(onSend()));
+	connect(&_unblock, SIGNAL(clicked()), this, SLOT(onUnblock()));
 	connect(&_botStart, SIGNAL(clicked()), this, SLOT(onBotStart()));
 	connect(&_attachDocument, SIGNAL(clicked()), this, SLOT(onDocumentSelect()));
 	connect(&_attachPhoto, SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
@@ -2305,6 +2310,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
 	_field.hide();
 	_field.resize(width() - _send.width() - _attachDocument.width() - _attachEmoji.width(), _send.height() - 2 * st::sendPadding);
 	_send.hide();
+	_unblock.hide();
 	_botStart.hide();
 
 	_attachDocument.hide();
@@ -2368,8 +2374,8 @@ void HistoryWidget::onTextChange() {
 	}
 	if (updateCmdStartShown()) {
 		updateControlsVisibility();
-resizeEvent(0);
-update();
+		resizeEvent(0);
+		update();
 	}
 
 	if (!_history || _synthedTextUpdate) return;
@@ -2482,7 +2488,7 @@ void HistoryWidget::sendActionDone(const MTPBool &result, mtpRequestId req) {
 void HistoryWidget::activate() {
 	if (_history) updateListSize(0, true);
 	if (_list) {
-		if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart()) {
+		if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart() || isBlocked()) {
 			_list->setFocus();
 		} else {
 			_field.setFocus();
@@ -2776,6 +2782,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) {
 	}
 
 	_peer = peerId ? App::peer(peerId) : 0;
+	_unblockRequest = 0;
 
 	_titlePeerText = QString();
 	_titlePeerTextWidth = 0;
@@ -2890,6 +2897,7 @@ void HistoryWidget::updateControlsVisibility() {
 		_scroll.hide();
 		_kbScroll.hide();
 		_send.hide();
+		_unblock.hide();
 		_botStart.hide();
 		_attachMention.hide();
 		_field.hide();
@@ -2914,7 +2922,25 @@ void HistoryWidget::updateControlsVisibility() {
 	}
 	if ((_peer->chat && !_peer->asChat()->forbidden && !_peer->asChat()->left) || (!_peer->chat && _peer->asUser()->access != UserNoAccess)) {
 		checkMentionDropdown();
-		if (isBotStart()) {
+		if (isBlocked()) {
+			_botStart.hide();
+			if (_unblock.isHidden()) {
+				_unblock.clearState();
+				_unblock.show();
+				_kbShown = false;
+			}
+			_send.hide();
+			_field.hide();
+			_attachEmoji.hide();
+			_kbShow.hide();
+			_kbHide.hide();
+			_cmdStart.hide();
+			_attachDocument.hide();
+			_attachPhoto.hide();
+			_kbScroll.hide();
+			_replyForwardPreviewCancel.hide();
+		} else if (isBotStart()) {
+			_unblock.hide();
 			if (_botStart.isHidden()) {
 				_botStart.clearState();
 				_botStart.show();
@@ -2931,6 +2957,7 @@ void HistoryWidget::updateControlsVisibility() {
 			_kbScroll.hide();
 			_replyForwardPreviewCancel.hide();
 		} else {
+			_unblock.hide();
 			_botStart.hide();
 			if (cHasAudioCapture() && _field.getLastText().isEmpty() && !App::main()->hasForwardingItems()) {
 				_send.hide();
@@ -3007,6 +3034,7 @@ void HistoryWidget::updateControlsVisibility() {
 	} else {
 		_attachMention.hide();
 		_send.hide();
+		_unblock.hide();
 		_botStart.hide();
 		_attachDocument.hide();
 		_attachPhoto.hide();
@@ -3321,6 +3349,29 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
 	if (!_keyboard.hasMarkup() && _keyboard.forceReply() && !_kbReplyTo) onKbToggle();
 }
 
+void HistoryWidget::onUnblock() {
+	if (_unblockRequest) return;
+	if (!_peer || _peer->chat || _peer->asUser()->blocked != UserIsBlocked) {
+		updateControlsVisibility();
+		return;
+	}
+
+	_unblockRequest = MTP::send(MTPcontacts_Unblock(_peer->asUser()->inputUser), rpcDone(&HistoryWidget::unblockDone, _peer), rpcFail(&HistoryWidget::unblockFail));
+}
+
+void HistoryWidget::unblockDone(PeerData *peer, const MTPBool &result) {
+	if (peer->chat) return;
+	_unblockRequest = 0;
+	peer->asUser()->blocked = UserIsNotBlocked;
+	emit App::main()->peerUpdated(peer);
+}
+
+bool HistoryWidget::unblockFail(const RPCError &error) {
+	if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
+//	_unblockRequest = 0;
+	return false;
+}
+
 void HistoryWidget::onBotStart() {
 	if (!_peer || _peer->chat || !_peer->asUser()->botInfo) {
 		updateControlsVisibility();
@@ -3418,6 +3469,7 @@ void HistoryWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTo
 	_field.hide();
 	_replyForwardPreviewCancel.hide();
 	_send.hide();
+	_unblock.hide();
 	_botStart.hide();
 	a_coord = back ? anim::ivalue(-st::introSlideShift, 0) : anim::ivalue(st::introSlideShift, 0);
 	a_alpha = anim::fvalue(0, 1);
@@ -3470,7 +3522,7 @@ void HistoryWidget::animStop() {
 bool HistoryWidget::recordStep(float64 ms) {
 	float64 dt = ms / st::btnSend.duration;
 	bool res = true;
-	if (dt >= 1 || !_send.isHidden() || isBotStart()) {
+	if (dt >= 1 || !_send.isHidden() || isBotStart() || isBlocked()) {
 		res = false;
 		a_recordOver.finish();
 		a_recordDown.finish();
@@ -3787,10 +3839,14 @@ bool HistoryWidget::isBotStart() const {
 	return !_peer->asUser()->botInfo->startToken.isEmpty() || (_history->isEmpty() && !_history->lastMsg);
 }
 
+bool HistoryWidget::isBlocked() const {
+	return _peer && !_peer->chat && _peer->asUser()->blocked == UserIsBlocked;
+}
+
 bool HistoryWidget::updateCmdStartShown() {
 	bool cmdStartShown = false;
 	if (_history && _peer && ((_peer->chat && _peer->asChat()->botStatus > 0) || (!_peer->chat && _peer->asUser()->botInfo))) {
-		if (!isBotStart() && !_keyboard.hasMarkup() && !_keyboard.forceReply()) {
+		if (!isBotStart() && !isBlocked() && !_keyboard.hasMarkup() && !_keyboard.forceReply()) {
 			if (_field.getLastText().isEmpty()) {
 				cmdStartShown = true;
 			}
@@ -4069,6 +4125,7 @@ void HistoryWidget::onFieldResize() {
 	_attachDocument.move(0, height() - kbh - _attachDocument.height());
 	_attachPhoto.move(_attachDocument.x(), _attachDocument.y());
 	_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height());
+	_unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height());
 	_send.move(width() - _send.width(), _attachDocument.y());
 	_attachEmoji.move(_send.x() - _attachEmoji.width(), height() - kbh - _attachEmoji.height());
 	_kbShow.move(_attachEmoji.x() - _kbShow.width(), height() - kbh - _kbShow.height());
@@ -4427,7 +4484,7 @@ void HistoryWidget::peerMessagesUpdated(PeerId peer) {
 	if (_peer && _list && peer == _peer->id) {
 		updateListSize();
 		updateBotKeyboard();
-		if (!_scroll.isHidden() && _botStart.isHidden() == isBotStart()) {
+		if (!_scroll.isHidden() && !isBlocked() && _botStart.isHidden() == isBotStart()) {
 			updateControlsVisibility();
 			resizeEvent(0);
 		}
@@ -4468,6 +4525,7 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
 
 	_send.move(width() - _send.width(), _attachDocument.y());
 	_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height());
+	_unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height());
 	_attachEmoji.move(_send.x() - _attachEmoji.width(), height() - kbh - _attachEmoji.height());
 	_kbShow.move(_attachEmoji.x() - _kbShow.width(), height() - kbh - _kbShow.height());
 	_kbHide.move(_attachEmoji.x(), _attachEmoji.y());
@@ -4537,7 +4595,9 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown,
 	}
 
 	int32 newScrollHeight = height();
-	if (isBotStart()) {
+	if (isBlocked()) {
+		newScrollHeight -= _unblock.height();
+	} else if (isBotStart()) {
 		newScrollHeight -= _botStart.height();
 	} else {
 		if ((_peer->chat && !_peer->asChat()->forbidden && !_peer->asChat()->left) || (!_peer->chat && _peer->asUser()->access != UserNoAccess)) {
@@ -4676,7 +4736,7 @@ void HistoryWidget::updateBotKeyboard() {
 	bool hasMarkup = _keyboard.hasMarkup(), forceReply = _keyboard.forceReply() && !_replyTo;
 	if (hasMarkup || forceReply) {
 		if (_keyboard.singleUse() && _keyboard.hasMarkup() && _keyboard.forMsgId() == _history->lastKeyboardId && _history->lastKeyboardUsed) _kbWasHidden = true;
-		if (!isBotStart() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) {
+		if (!isBotStart() && !isBlocked() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) {
 			if (!_showAnim.animating()) {
 				if (hasMarkup) {
 					_kbScroll.show();
@@ -5094,6 +5154,9 @@ void HistoryWidget::onFullPeerUpdated(PeerData *data) {
 		updateControlsVisibility();
 		resizeEvent(0);
 		update();
+	} else if (!_scroll.isHidden() && _unblock.isHidden() == isBlocked()) {
+		updateControlsVisibility();
+		resizeEvent(0);
 	}
 	if (newScrollTop != _scroll.scrollTop()) {
 		if (_scroll.isVisible()) {
@@ -5110,6 +5173,11 @@ void HistoryWidget::peerUpdated(PeerData *data) {
 		if (!_showAnim.animating()) updateControlsVisibility();
 		if (data->chat && data->asChat()->count > 0 && data->asChat()->participants.isEmpty()) {
 			App::api()->requestFullPeer(data);
+		} else if (!data->chat && data->asUser()->blocked == UserBlockUnknown) {
+			App::api()->requestFullPeer(data);
+		} else if (!_scroll.isHidden() && _unblock.isHidden() == isBlocked()) {
+			updateControlsVisibility();
+			resizeEvent(0);
 		}
 		App::main()->updateOnlineDisplay();
 	}
@@ -5225,7 +5293,7 @@ void HistoryWidget::updateTopBarSelection() {
 	updateControlsVisibility();
 	updateListSize();
 	if (!App::wnd()->layerShown() && !App::passcoded()) {
-		if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart()) {
+		if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart() || isBlocked()) {
 			_list->setFocus();
 		} else {
 			_field.setFocus();
diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h
index e6535ccfe..0ce5c0c81 100644
--- a/Telegram/SourceFiles/historywidget.h
+++ b/Telegram/SourceFiles/historywidget.h
@@ -518,6 +518,7 @@ public slots:
 	void onListScroll();
 	void onHistoryToEnd();
 	void onSend(bool ctrlShiftEnter = false, MsgId replyTo = -1);
+	void onUnblock();
 	void onBotStart();
 
 	void onPhotoSelect();
@@ -604,6 +605,9 @@ private:
 	void addMessagesToFront(const QVector<MTPMessage> &messages);
 	void addMessagesToBack(const QVector<MTPMessage> &messages);
 
+	void unblockDone(PeerData *peer, const MTPBool &result);
+	bool unblockFail(const RPCError &error);
+
 	void countHistoryShowFrom();
 
 	void updateToEndVisibility();
@@ -640,9 +644,11 @@ private:
 	MentionsDropdown _attachMention;
 
 	bool isBotStart() const;
+	bool isBlocked() const;
 	bool updateCmdStartShown();
 
-	FlatButton _send, _botStart;
+	FlatButton _send, _unblock, _botStart;
+	mtpRequestId _unblockRequest;
 	IconedButton _attachDocument, _attachPhoto, _attachEmoji, _kbShow, _kbHide, _cmdStart;
 	bool _cmdStartShown;
 	MessageField _field;
diff --git a/Telegram/SourceFiles/localimageloader.cpp b/Telegram/SourceFiles/localimageloader.cpp
index 2e212aec6..4d7edf177 100644
--- a/Telegram/SourceFiles/localimageloader.cpp
+++ b/Telegram/SourceFiles/localimageloader.cpp
@@ -221,7 +221,7 @@ void LocalImageLoaderPrivate::prepareImages() {
 			}
 			if (!filesize) filesize = jpeg.size();
 		
-			photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes));
+			photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_vector<MTPPhotoSize>(photoSizes));
 
 			thumbId = id;
 		} else if ((type == ToPrepareVideo || type == ToPrepareDocument) && !img.isNull() && !isSong) {
@@ -254,7 +254,7 @@ void LocalImageLoaderPrivate::prepareImages() {
 		if (type == ToPrepareDocument) {
 			document = MTP_document(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(filesize), thumb, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
 		} else if (type == ToPrepareAudio) {
-			audio = MTP_audio(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_int(duration), MTP_string(mime), MTP_int(filesize), MTP_int(MTP::maindc()));
+			audio = MTP_audio(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_int(duration), MTP_string(mime), MTP_int(filesize), MTP_int(MTP::maindc()));
 		}
 
 		{
diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp
index 0809f9205..0ca20aca2 100644
--- a/Telegram/SourceFiles/localstorage.cpp
+++ b/Telegram/SourceFiles/localstorage.cpp
@@ -2821,12 +2821,9 @@ namespace Local {
 			if (App::userFromPeer(user->id) == MTP::authedId()) {
 				user->input = MTP_inputPeerSelf();
 				user->inputUser = MTP_inputUserSelf();
-			} else if (user->contact > 0 || !user->access) {
-				user->input = MTP_inputPeerContact(MTP_int(App::userFromPeer(user->id)));
-				user->inputUser = MTP_inputUserContact(MTP_int(App::userFromPeer(user->id)));
 			} else {
-				user->input = MTP_inputPeerForeign(MTP_int(App::userFromPeer(user->id)), MTP_long(user->access));
-				user->inputUser = MTP_inputUserForeign(MTP_int(App::userFromPeer(user->id)), MTP_long(user->access));
+				user->input = MTP_inputPeerUser(MTP_int(App::userFromPeer(user->id)), MTP_long((user->access == UserNoAccess) ? 0 : user->access));
+				user->inputUser = MTP_inputUser(MTP_int(App::userFromPeer(user->id)), MTP_long((user->access == UserNoAccess) ? 0 : user->access));
 			}
 
 			user->photo = photoLoc.isNull() ? ImagePtr(userDefPhoto(user->colorIndex)) : ImagePtr(photoLoc);
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index 0013557e3..0b0760725 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -3040,8 +3040,7 @@ void MainWidget::gotNotifySetting(MTPInputNotifyPeer peer, const MTPPeerNotifySe
 		switch (peer.c_inputNotifyPeer().vpeer.type()) {
 		case mtpc_inputPeerEmpty: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(MTP_int(0))), settings); break;
 		case mtpc_inputPeerSelf: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(MTP_int(MTP::authedId()))), settings); break;
-		case mtpc_inputPeerContact: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerContact().vuser_id)), settings); break;
-		case mtpc_inputPeerForeign: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerForeign().vuser_id)), settings); break;
+		case mtpc_inputPeerUser: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerUser().vuser_id)), settings); break;
 		case mtpc_inputPeerChat: applyNotifySetting(MTP_notifyPeer(MTP_peerChat(peer.c_inputNotifyPeer().vpeer.c_inputPeerChat().vchat_id)), settings); break;
 		}
 	break;
@@ -3650,6 +3649,10 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
 
 	case mtpc_updateUserBlocked: {
 		const MTPDupdateUserBlocked &d(update.c_updateUserBlocked());
+		if (UserData *user = App::userLoaded(d.vuser_id.v)) {
+			user->blocked = d.vblocked.v ? UserIsBlocked : UserIsNotBlocked;
+			App::markPeerUpdated(user);
+		}
 	} break;
 
 	case mtpc_updateNewAuthorization: {
diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp
index f0739b97c..6baf5b562 100644
--- a/Telegram/SourceFiles/mediaview.cpp
+++ b/Telegram/SourceFiles/mediaview.cpp
@@ -775,18 +775,14 @@ void MediaView::displayPhoto(PhotoData *photo, HistoryItem *item) {
 	_x = (width() - _w) / 2;
 	_y = (height() - _h) / 2;
 	_width = _w;
-	if (_photo->user == WebPageUserId && _msgid) {
-		if (HistoryItem *item = App::histItemById(_msgid)) {
-			if (dynamic_cast<HistoryForwarded*>(item)) {
-				_from = static_cast<HistoryForwarded*>(item)->fromForwarded();
-			} else {
-				_from = item->from();
-			}
+	if (_msgid && item) {
+		if (HistoryForwarded *fwd = item->toHistoryForwarded()) {
+			_from = fwd->fromForwarded();
 		} else {
-			_from = App::user(_photo->user);
+			_from = item->from();
 		}
 	} else {
-		_from = App::user(_photo->user);
+		_from = _user;
 	}
 	updateControls();
 	_photo->full->load();
@@ -955,10 +951,10 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
 	}
 	_x = (width() - _w) / 2;
 	_y = (height() - _h) / 2;
-	if (HistoryForwarded *fwd = dynamic_cast<HistoryForwarded*>(item)) {
-		_from = fwd->fromForwarded()->asUser();
+	if (HistoryForwarded *fwd = item->toHistoryForwarded()) {
+		_from = fwd->fromForwarded();
 	} else {
-		_from = item->from()->asUser();
+		_from = item->from();
 	}
 	_full = 1;
 	updateControls();
@@ -1850,7 +1846,7 @@ void MediaView::loadBack() {
 		if (App::main()) App::main()->loadMediaBack(_history->peer, _overview);
 	} else if (_user && _user->photosCount != 0) {
 		int32 limit = (_index < MediaOverviewStartPerPage && _user->photos.size() > MediaOverviewStartPerPage) ? SearchPerPage : MediaOverviewStartPerPage;
-		_loadRequest = MTP::send(MTPphotos_GetUserPhotos(_user->inputUser, MTP_int(_user->photos.size()), MTP_int(0), MTP_int(limit)), rpcDone(&MediaView::userPhotosLoaded, _user));
+		_loadRequest = MTP::send(MTPphotos_GetUserPhotos(_user->inputUser, MTP_int(_user->photos.size()), MTP_long(0), MTP_int(limit)), rpcDone(&MediaView::userPhotosLoaded, _user));
 	}
 }
 
diff --git a/Telegram/SourceFiles/mtproto/mtpCoreTypes.h b/Telegram/SourceFiles/mtproto/mtpCoreTypes.h
index 950d5be3a..63b6c1fad 100644
--- a/Telegram/SourceFiles/mtproto/mtpCoreTypes.h
+++ b/Telegram/SourceFiles/mtproto/mtpCoreTypes.h
@@ -366,7 +366,7 @@ static const mtpTypeId mtpLayers[] = {
 	mtpc_invokeWithLayer17,
 	mtpc_invokeWithLayer18,
 }, mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]);
-static const mtpPrime mtpCurrentLayer = 32;
+static const mtpPrime mtpCurrentLayer = 33;
 
 template <typename bareT>
 class MTPBoxed : public bareT {
diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.cpp b/Telegram/SourceFiles/mtproto/mtpScheme.cpp
index a79731ee7..457cd9470 100644
--- a/Telegram/SourceFiles/mtproto/mtpScheme.cpp
+++ b/Telegram/SourceFiles/mtproto/mtpScheme.cpp
@@ -487,33 +487,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
 				to.add("{ inputPeerSelf }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
 			break;
 
-			case mtpc_inputPeerContact:
-				if (stage) {
-					to.add(",\n").addSpaces(lev);
-				} else {
-					to.add("{ inputPeerContact");
-					to.add("\n").addSpaces(lev);
-				}
-				switch (stage) {
-				case 0: to.add("  user_id: "); ++stages.back(); types.push_back(mtpc_int); 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;
-				}
-			break;
-
-			case mtpc_inputPeerForeign:
-				if (stage) {
-					to.add(",\n").addSpaces(lev);
-				} else {
-					to.add("{ inputPeerForeign");
-					to.add("\n").addSpaces(lev);
-				}
-				switch (stage) {
-				case 0: to.add("  user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 1: to.add("  access_hash: "); ++stages.back(); types.push_back(mtpc_long); 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;
-				}
-			break;
-
 			case mtpc_inputPeerChat:
 				if (stage) {
 					to.add(",\n").addSpaces(lev);
@@ -527,6 +500,20 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
 				}
 			break;
 
+			case mtpc_inputPeerUser:
+				if (stage) {
+					to.add(",\n").addSpaces(lev);
+				} else {
+					to.add("{ inputPeerUser");
+					to.add("\n").addSpaces(lev);
+				}
+				switch (stage) {
+				case 0: to.add("  user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 1: to.add("  access_hash: "); ++stages.back(); types.push_back(mtpc_long); 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;
+				}
+			break;
+
 			case mtpc_inputUserEmpty:
 				to.add("{ inputUserEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
 			break;
@@ -535,24 +522,11 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
 				to.add("{ inputUserSelf }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
 			break;
 
-			case mtpc_inputUserContact:
+			case mtpc_inputUser:
 				if (stage) {
 					to.add(",\n").addSpaces(lev);
 				} else {
-					to.add("{ inputUserContact");
-					to.add("\n").addSpaces(lev);
-				}
-				switch (stage) {
-				case 0: to.add("  user_id: "); ++stages.back(); types.push_back(mtpc_int); 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;
-				}
-			break;
-
-			case mtpc_inputUserForeign:
-				if (stage) {
-					to.add(",\n").addSpaces(lev);
-				} else {
-					to.add("{ inputUserForeign");
+					to.add("{ inputUser");
 					to.add("\n").addSpaces(lev);
 				}
 				switch (stage) {
@@ -1662,10 +1636,8 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
 				switch (stage) {
 				case 0: to.add("  id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 				case 1: to.add("  access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 2: to.add("  user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 3: to.add("  date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 4: to.add("  geo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 5: to.add("  sizes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 2: to.add("  date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 3: to.add("  sizes: "); ++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;
 				}
 			break;
@@ -1740,9 +1712,9 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
 				switch (stage) {
 				case 0: to.add("  id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 				case 1: to.add("  access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 2: to.add("  user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 3: to.add("  date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 4: to.add("  duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 2: to.add("  date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 3: to.add("  duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 4: to.add("  mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 				case 5: to.add("  size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 				case 6: to.add("  thumb: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 				case 7: to.add("  dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
@@ -2336,6 +2308,10 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
 				to.add("{ inputMessagesFilterAudioDocuments }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
 			break;
 
+			case mtpc_inputMessagesFilterUrl:
+				to.add("{ inputMessagesFilterUrl }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
+			break;
+
 			case mtpc_updateNewMessage:
 				if (stage) {
 					to.add(",\n").addSpaces(lev);
@@ -3513,12 +3489,11 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
 				switch (stage) {
 				case 0: to.add("  id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 				case 1: to.add("  access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 2: to.add("  user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 3: to.add("  date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 4: to.add("  duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 5: to.add("  mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 6: to.add("  size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 7: to.add("  dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 2: to.add("  date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 3: to.add("  duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 4: to.add("  mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 5: to.add("  size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 6: to.add("  dc_id: "); ++stages.back(); types.push_back(mtpc_int); 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;
 				}
 			break;
@@ -4389,6 +4364,23 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
 				}
 			break;
 
+			case mtpc_help_appChangelogEmpty:
+				to.add("{ help_appChangelogEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
+			break;
+
+			case mtpc_help_appChangelog:
+				if (stage) {
+					to.add(",\n").addSpaces(lev);
+				} else {
+					to.add("{ help_appChangelog");
+					to.add("\n").addSpaces(lev);
+				}
+				switch (stage) {
+				case 0: to.add("  text: "); ++stages.back(); types.push_back(mtpc_string); 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;
+				}
+			break;
+
 			case mtpc_req_pq:
 				if (stage) {
 					to.add(",\n").addSpaces(lev);
@@ -5786,7 +5778,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
 				switch (stage) {
 				case 0: to.add("  user_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 				case 1: to.add("  offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
-				case 2: to.add("  max_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 2: to.add("  max_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
 				case 3: to.add("  limit: "); ++stages.back(); types.push_back(mtpc_int); 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;
 				}
@@ -6201,6 +6193,22 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
 				}
 			break;
 
+			case mtpc_help_getAppChangelog:
+				if (stage) {
+					to.add(",\n").addSpaces(lev);
+				} else {
+					to.add("{ help_getAppChangelog");
+					to.add("\n").addSpaces(lev);
+				}
+				switch (stage) {
+				case 0: to.add("  device_model: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 1: to.add("  system_version: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 2: to.add("  app_version: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
+				case 3: to.add("  lang_code: "); ++stages.back(); types.push_back(mtpc_string); 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;
+				}
+			break;
+
 			case mtpc_rpc_result:
 				if (stage) {
 					to.add(",\n").addSpaces(lev);
diff --git a/Telegram/SourceFiles/mtproto/mtpScheme.h b/Telegram/SourceFiles/mtproto/mtpScheme.h
index 2cebf65f9..17d3f4a6f 100644
--- a/Telegram/SourceFiles/mtproto/mtpScheme.h
+++ b/Telegram/SourceFiles/mtproto/mtpScheme.h
@@ -67,13 +67,9 @@ enum {
 	mtpc_null = 0x56730bcc,
 	mtpc_inputPeerEmpty = 0x7f3b18ea,
 	mtpc_inputPeerSelf = 0x7da07ec9,
-	mtpc_inputPeerContact = 0x1023dbe8,
-	mtpc_inputPeerForeign = 0x9b447325,
 	mtpc_inputPeerChat = 0x179be863,
 	mtpc_inputUserEmpty = 0xb98886cf,
 	mtpc_inputUserSelf = 0xf7c1b13f,
-	mtpc_inputUserContact = 0x86e94f65,
-	mtpc_inputUserForeign = 0x655e74ff,
 	mtpc_inputPhoneContact = 0xf392b7f4,
 	mtpc_inputFile = 0xf52ff27f,
 	mtpc_inputMediaEmpty = 0x9664f57f,
@@ -145,12 +141,12 @@ enum {
 	mtpc_messageActionChatDeleteUser = 0xb2ae9b0c,
 	mtpc_dialog = 0xc1dd804a,
 	mtpc_photoEmpty = 0x2331b22d,
-	mtpc_photo = 0xc3838076,
+	mtpc_photo = 0xcded42fe,
 	mtpc_photoSizeEmpty = 0xe17e23c,
 	mtpc_photoSize = 0x77bfb61b,
 	mtpc_photoCachedSize = 0xe9a734fa,
 	mtpc_videoEmpty = 0xc10658a8,
-	mtpc_video = 0xee9f4a4d,
+	mtpc_video = 0xf72887d3,
 	mtpc_geoPointEmpty = 0x1117dd5f,
 	mtpc_geoPoint = 0x2049d70c,
 	mtpc_auth_checkedPhone = 0x811ea28e,
@@ -200,6 +196,7 @@ enum {
 	mtpc_inputMessagesFilterDocument = 0x9eddf188,
 	mtpc_inputMessagesFilterAudio = 0xcfc87522,
 	mtpc_inputMessagesFilterAudioDocuments = 0x5afbf764,
+	mtpc_inputMessagesFilterUrl = 0x7ef0dd87,
 	mtpc_updateNewMessage = 0x1f2b0afd,
 	mtpc_updateMessageID = 0x4e90bfd6,
 	mtpc_updateDeleteMessages = 0xa20db0e5,
@@ -288,7 +285,7 @@ enum {
 	mtpc_inputAudioFileLocation = 0x74dc404d,
 	mtpc_inputDocumentFileLocation = 0x4e45abe9,
 	mtpc_audioEmpty = 0x586988d8,
-	mtpc_audio = 0xc7ac6496,
+	mtpc_audio = 0xf9e35055,
 	mtpc_documentEmpty = 0x36f8c871,
 	mtpc_document = 0xf9a39f4f,
 	mtpc_help_support = 0x17c6b5f6,
@@ -388,6 +385,10 @@ enum {
 	mtpc_replyKeyboardHide = 0xa03e5b85,
 	mtpc_replyKeyboardForceReply = 0xf4108aa0,
 	mtpc_replyKeyboardMarkup = 0x3502758c,
+	mtpc_inputPeerUser = 0x7b8e7de6,
+	mtpc_inputUser = 0xd8292816,
+	mtpc_help_appChangelogEmpty = 0xaf7e0394,
+	mtpc_help_appChangelog = 0x4668e6bd,
 	mtpc_invokeAfterMsg = 0xcb9f372d,
 	mtpc_invokeAfterMsgs = 0x3dc4b4f0,
 	mtpc_auth_checkPhone = 0x6fe51dfb,
@@ -453,7 +454,7 @@ enum {
 	mtpc_help_getAppUpdate = 0xc812ac7e,
 	mtpc_help_saveAppLog = 0x6f02f748,
 	mtpc_help_getInviteText = 0xa4a95186,
-	mtpc_photos_getUserPhotos = 0xb7ee553c,
+	mtpc_photos_getUserPhotos = 0x91cd32a8,
 	mtpc_messages_forwardMessage = 0x33963bf9,
 	mtpc_messages_sendBroadcast = 0xbf73f4da,
 	mtpc_geochats_getLocated = 0x7f192d8f,
@@ -515,7 +516,8 @@ enum {
 	mtpc_messages_getStickerSet = 0x2619a90e,
 	mtpc_messages_installStickerSet = 0x7b30c3a6,
 	mtpc_messages_uninstallStickerSet = 0xf96e55de,
-	mtpc_messages_startBot = 0x1b3e0ffc
+	mtpc_messages_startBot = 0x1b3e0ffc,
+	mtpc_help_getAppChangelog = 0x5bab7fb2
 };
 
 // Type forward declarations
@@ -594,13 +596,11 @@ class MTPDerror;
 class MTPnull;
 
 class MTPinputPeer;
-class MTPDinputPeerContact;
-class MTPDinputPeerForeign;
 class MTPDinputPeerChat;
+class MTPDinputPeerUser;
 
 class MTPinputUser;
-class MTPDinputUserContact;
-class MTPDinputUserForeign;
+class MTPDinputUser;
 
 class MTPinputContact;
 class MTPDinputPhoneContact;
@@ -1083,6 +1083,9 @@ class MTPDreplyKeyboardHide;
 class MTPDreplyKeyboardForceReply;
 class MTPDreplyKeyboardMarkup;
 
+class MTPhelp_appChangelog;
+class MTPDhelp_appChangelog;
+
 
 // Boxed types definitions
 typedef MTPBoxed<MTPresPQ> MTPResPQ;
@@ -1234,6 +1237,7 @@ typedef MTPBoxed<MTPbotInfo> MTPBotInfo;
 typedef MTPBoxed<MTPkeyboardButton> MTPKeyboardButton;
 typedef MTPBoxed<MTPkeyboardButtonRow> MTPKeyboardButtonRow;
 typedef MTPBoxed<MTPreplyMarkup> MTPReplyMarkup;
+typedef MTPBoxed<MTPhelp_appChangelog> MTPhelp_AppChangelog;
 
 // Type classes definitions
 
@@ -2070,30 +2074,6 @@ public:
 		read(from, end, cons);
 	}
 
-	MTPDinputPeerContact &_inputPeerContact() {
-		if (!data) throw mtpErrorUninitialized();
-		if (_type != mtpc_inputPeerContact) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerContact);
-		split();
-		return *(MTPDinputPeerContact*)data;
-	}
-	const MTPDinputPeerContact &c_inputPeerContact() const {
-		if (!data) throw mtpErrorUninitialized();
-		if (_type != mtpc_inputPeerContact) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerContact);
-		return *(const MTPDinputPeerContact*)data;
-	}
-
-	MTPDinputPeerForeign &_inputPeerForeign() {
-		if (!data) throw mtpErrorUninitialized();
-		if (_type != mtpc_inputPeerForeign) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerForeign);
-		split();
-		return *(MTPDinputPeerForeign*)data;
-	}
-	const MTPDinputPeerForeign &c_inputPeerForeign() const {
-		if (!data) throw mtpErrorUninitialized();
-		if (_type != mtpc_inputPeerForeign) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerForeign);
-		return *(const MTPDinputPeerForeign*)data;
-	}
-
 	MTPDinputPeerChat &_inputPeerChat() {
 		if (!data) throw mtpErrorUninitialized();
 		if (_type != mtpc_inputPeerChat) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerChat);
@@ -2106,6 +2086,18 @@ public:
 		return *(const MTPDinputPeerChat*)data;
 	}
 
+	MTPDinputPeerUser &_inputPeerUser() {
+		if (!data) throw mtpErrorUninitialized();
+		if (_type != mtpc_inputPeerUser) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerUser);
+		split();
+		return *(MTPDinputPeerUser*)data;
+	}
+	const MTPDinputPeerUser &c_inputPeerUser() const {
+		if (!data) throw mtpErrorUninitialized();
+		if (_type != mtpc_inputPeerUser) throw mtpErrorWrongTypeId(_type, mtpc_inputPeerUser);
+		return *(const MTPDinputPeerUser*)data;
+	}
+
 	uint32 innerLength() const;
 	mtpTypeId type() const;
 	void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons);
@@ -2115,15 +2107,13 @@ public:
 
 private:
 	explicit MTPinputPeer(mtpTypeId type);
-	explicit MTPinputPeer(MTPDinputPeerContact *_data);
-	explicit MTPinputPeer(MTPDinputPeerForeign *_data);
 	explicit MTPinputPeer(MTPDinputPeerChat *_data);
+	explicit MTPinputPeer(MTPDinputPeerUser *_data);
 
 	friend MTPinputPeer MTP_inputPeerEmpty();
 	friend MTPinputPeer MTP_inputPeerSelf();
-	friend MTPinputPeer MTP_inputPeerContact(MTPint _user_id);
-	friend MTPinputPeer MTP_inputPeerForeign(MTPint _user_id, const MTPlong &_access_hash);
 	friend MTPinputPeer MTP_inputPeerChat(MTPint _chat_id);
+	friend MTPinputPeer MTP_inputPeerUser(MTPint _user_id, const MTPlong &_access_hash);
 
 	mtpTypeId _type;
 };
@@ -2137,28 +2127,16 @@ public:
 		read(from, end, cons);
 	}
 
-	MTPDinputUserContact &_inputUserContact() {
+	MTPDinputUser &_inputUser() {
 		if (!data) throw mtpErrorUninitialized();
-		if (_type != mtpc_inputUserContact) throw mtpErrorWrongTypeId(_type, mtpc_inputUserContact);
+		if (_type != mtpc_inputUser) throw mtpErrorWrongTypeId(_type, mtpc_inputUser);
 		split();
-		return *(MTPDinputUserContact*)data;
+		return *(MTPDinputUser*)data;
 	}
-	const MTPDinputUserContact &c_inputUserContact() const {
+	const MTPDinputUser &c_inputUser() const {
 		if (!data) throw mtpErrorUninitialized();
-		if (_type != mtpc_inputUserContact) throw mtpErrorWrongTypeId(_type, mtpc_inputUserContact);
-		return *(const MTPDinputUserContact*)data;
-	}
-
-	MTPDinputUserForeign &_inputUserForeign() {
-		if (!data) throw mtpErrorUninitialized();
-		if (_type != mtpc_inputUserForeign) throw mtpErrorWrongTypeId(_type, mtpc_inputUserForeign);
-		split();
-		return *(MTPDinputUserForeign*)data;
-	}
-	const MTPDinputUserForeign &c_inputUserForeign() const {
-		if (!data) throw mtpErrorUninitialized();
-		if (_type != mtpc_inputUserForeign) throw mtpErrorWrongTypeId(_type, mtpc_inputUserForeign);
-		return *(const MTPDinputUserForeign*)data;
+		if (_type != mtpc_inputUser) throw mtpErrorWrongTypeId(_type, mtpc_inputUser);
+		return *(const MTPDinputUser*)data;
 	}
 
 	uint32 innerLength() const;
@@ -2170,13 +2148,11 @@ public:
 
 private:
 	explicit MTPinputUser(mtpTypeId type);
-	explicit MTPinputUser(MTPDinputUserContact *_data);
-	explicit MTPinputUser(MTPDinputUserForeign *_data);
+	explicit MTPinputUser(MTPDinputUser *_data);
 
 	friend MTPinputUser MTP_inputUserEmpty();
 	friend MTPinputUser MTP_inputUserSelf();
-	friend MTPinputUser MTP_inputUserContact(MTPint _user_id);
-	friend MTPinputUser MTP_inputUserForeign(MTPint _user_id, const MTPlong &_access_hash);
+	friend MTPinputUser MTP_inputUser(MTPint _user_id, const MTPlong &_access_hash);
 
 	mtpTypeId _type;
 };
@@ -3709,7 +3685,7 @@ private:
 	explicit MTPphoto(MTPDphoto *_data);
 
 	friend MTPphoto MTP_photoEmpty(const MTPlong &_id);
-	friend MTPphoto MTP_photo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, const MTPGeoPoint &_geo, const MTPVector<MTPPhotoSize> &_sizes);
+	friend MTPphoto MTP_photo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPVector<MTPPhotoSize> &_sizes);
 
 	mtpTypeId _type;
 };
@@ -3825,7 +3801,7 @@ private:
 	explicit MTPvideo(MTPDvideo *_data);
 
 	friend MTPvideo MTP_videoEmpty(const MTPlong &_id);
-	friend MTPvideo MTP_video(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h);
+	friend MTPvideo MTP_video(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h);
 
 	mtpTypeId _type;
 };
@@ -4929,6 +4905,7 @@ private:
 	friend MTPmessagesFilter MTP_inputMessagesFilterDocument();
 	friend MTPmessagesFilter MTP_inputMessagesFilterAudio();
 	friend MTPmessagesFilter MTP_inputMessagesFilterAudioDocuments();
+	friend MTPmessagesFilter MTP_inputMessagesFilterUrl();
 
 	mtpTypeId _type;
 };
@@ -6539,7 +6516,7 @@ private:
 	explicit MTPaudio(MTPDaudio *_data);
 
 	friend MTPaudio MTP_audioEmpty(const MTPlong &_id);
-	friend MTPaudio MTP_audio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id);
+	friend MTPaudio MTP_audio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id);
 
 	mtpTypeId _type;
 };
@@ -8050,6 +8027,44 @@ private:
 };
 typedef MTPBoxed<MTPreplyMarkup> MTPReplyMarkup;
 
+class MTPhelp_appChangelog : private mtpDataOwner {
+public:
+	MTPhelp_appChangelog() : mtpDataOwner(0), _type(0) {
+	}
+	MTPhelp_appChangelog(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) : mtpDataOwner(0), _type(0) {
+		read(from, end, cons);
+	}
+
+	MTPDhelp_appChangelog &_help_appChangelog() {
+		if (!data) throw mtpErrorUninitialized();
+		if (_type != mtpc_help_appChangelog) throw mtpErrorWrongTypeId(_type, mtpc_help_appChangelog);
+		split();
+		return *(MTPDhelp_appChangelog*)data;
+	}
+	const MTPDhelp_appChangelog &c_help_appChangelog() const {
+		if (!data) throw mtpErrorUninitialized();
+		if (_type != mtpc_help_appChangelog) throw mtpErrorWrongTypeId(_type, mtpc_help_appChangelog);
+		return *(const MTPDhelp_appChangelog*)data;
+	}
+
+	uint32 innerLength() const;
+	mtpTypeId type() const;
+	void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons);
+	void write(mtpBuffer &to) const;
+
+	typedef void ResponseType;
+
+private:
+	explicit MTPhelp_appChangelog(mtpTypeId type);
+	explicit MTPhelp_appChangelog(MTPDhelp_appChangelog *_data);
+
+	friend MTPhelp_appChangelog MTP_help_appChangelogEmpty();
+	friend MTPhelp_appChangelog MTP_help_appChangelog(const MTPstring &_text);
+
+	mtpTypeId _type;
+};
+typedef MTPBoxed<MTPhelp_appChangelog> MTPhelp_AppChangelog;
+
 // Type constructors with data
 
 class MTPDresPQ : public mtpDataImpl<MTPDresPQ> {
@@ -8383,27 +8398,6 @@ public:
 	MTPstring vtext;
 };
 
-class MTPDinputPeerContact : public mtpDataImpl<MTPDinputPeerContact> {
-public:
-	MTPDinputPeerContact() {
-	}
-	MTPDinputPeerContact(MTPint _user_id) : vuser_id(_user_id) {
-	}
-
-	MTPint vuser_id;
-};
-
-class MTPDinputPeerForeign : public mtpDataImpl<MTPDinputPeerForeign> {
-public:
-	MTPDinputPeerForeign() {
-	}
-	MTPDinputPeerForeign(MTPint _user_id, const MTPlong &_access_hash) : vuser_id(_user_id), vaccess_hash(_access_hash) {
-	}
-
-	MTPint vuser_id;
-	MTPlong vaccess_hash;
-};
-
 class MTPDinputPeerChat : public mtpDataImpl<MTPDinputPeerChat> {
 public:
 	MTPDinputPeerChat() {
@@ -8414,21 +8408,22 @@ public:
 	MTPint vchat_id;
 };
 
-class MTPDinputUserContact : public mtpDataImpl<MTPDinputUserContact> {
+class MTPDinputPeerUser : public mtpDataImpl<MTPDinputPeerUser> {
 public:
-	MTPDinputUserContact() {
+	MTPDinputPeerUser() {
 	}
-	MTPDinputUserContact(MTPint _user_id) : vuser_id(_user_id) {
+	MTPDinputPeerUser(MTPint _user_id, const MTPlong &_access_hash) : vuser_id(_user_id), vaccess_hash(_access_hash) {
 	}
 
 	MTPint vuser_id;
+	MTPlong vaccess_hash;
 };
 
-class MTPDinputUserForeign : public mtpDataImpl<MTPDinputUserForeign> {
+class MTPDinputUser : public mtpDataImpl<MTPDinputUser> {
 public:
-	MTPDinputUserForeign() {
+	MTPDinputUser() {
 	}
-	MTPDinputUserForeign(MTPint _user_id, const MTPlong &_access_hash) : vuser_id(_user_id), vaccess_hash(_access_hash) {
+	MTPDinputUser(MTPint _user_id, const MTPlong &_access_hash) : vuser_id(_user_id), vaccess_hash(_access_hash) {
 	}
 
 	MTPint vuser_id;
@@ -9255,14 +9250,12 @@ class MTPDphoto : public mtpDataImpl<MTPDphoto> {
 public:
 	MTPDphoto() {
 	}
-	MTPDphoto(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, const MTPGeoPoint &_geo, const MTPVector<MTPPhotoSize> &_sizes) : vid(_id), vaccess_hash(_access_hash), vuser_id(_user_id), vdate(_date), vgeo(_geo), vsizes(_sizes) {
+	MTPDphoto(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPVector<MTPPhotoSize> &_sizes) : vid(_id), vaccess_hash(_access_hash), vdate(_date), vsizes(_sizes) {
 	}
 
 	MTPlong vid;
 	MTPlong vaccess_hash;
-	MTPint vuser_id;
 	MTPint vdate;
-	MTPGeoPoint vgeo;
 	MTPVector<MTPPhotoSize> vsizes;
 };
 
@@ -9318,14 +9311,14 @@ class MTPDvideo : public mtpDataImpl<MTPDvideo> {
 public:
 	MTPDvideo() {
 	}
-	MTPDvideo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h) : vid(_id), vaccess_hash(_access_hash), vuser_id(_user_id), vdate(_date), vduration(_duration), vsize(_size), vthumb(_thumb), vdc_id(_dc_id), vw(_w), vh(_h) {
+	MTPDvideo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h) : vid(_id), vaccess_hash(_access_hash), vdate(_date), vduration(_duration), vmime_type(_mime_type), vsize(_size), vthumb(_thumb), vdc_id(_dc_id), vw(_w), vh(_h) {
 	}
 
 	MTPlong vid;
 	MTPlong vaccess_hash;
-	MTPint vuser_id;
 	MTPint vdate;
 	MTPint vduration;
+	MTPstring vmime_type;
 	MTPint vsize;
 	MTPPhotoSize vthumb;
 	MTPint vdc_id;
@@ -10684,12 +10677,11 @@ class MTPDaudio : public mtpDataImpl<MTPDaudio> {
 public:
 	MTPDaudio() {
 	}
-	MTPDaudio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id) : vid(_id), vaccess_hash(_access_hash), vuser_id(_user_id), vdate(_date), vduration(_duration), vmime_type(_mime_type), vsize(_size), vdc_id(_dc_id) {
+	MTPDaudio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id) : vid(_id), vaccess_hash(_access_hash), vdate(_date), vduration(_duration), vmime_type(_mime_type), vsize(_size), vdc_id(_dc_id) {
 	}
 
 	MTPlong vid;
 	MTPlong vaccess_hash;
-	MTPint vuser_id;
 	MTPint vdate;
 	MTPint vduration;
 	MTPstring vmime_type;
@@ -11329,6 +11321,16 @@ public:
 	MTPVector<MTPKeyboardButtonRow> vrows;
 };
 
+class MTPDhelp_appChangelog : public mtpDataImpl<MTPDhelp_appChangelog> {
+public:
+	MTPDhelp_appChangelog() {
+	}
+	MTPDhelp_appChangelog(const MTPstring &_text) : vtext(_text) {
+	}
+
+	MTPstring vtext;
+};
+
 // RPC methods
 
 class MTPreq_pq { // RPC method 'req_pq'
@@ -14429,7 +14431,7 @@ class MTPphotos_getUserPhotos { // RPC method 'photos.getUserPhotos'
 public:
 	MTPInputUser vuser_id;
 	MTPint voffset;
-	MTPint vmax_id;
+	MTPlong vmax_id;
 	MTPint vlimit;
 
 	MTPphotos_getUserPhotos() {
@@ -14437,7 +14439,7 @@ public:
 	MTPphotos_getUserPhotos(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_photos_getUserPhotos) {
 		read(from, end, cons);
 	}
-	MTPphotos_getUserPhotos(const MTPInputUser &_user_id, MTPint _offset, MTPint _max_id, MTPint _limit) : vuser_id(_user_id), voffset(_offset), vmax_id(_max_id), vlimit(_limit) {
+	MTPphotos_getUserPhotos(const MTPInputUser &_user_id, MTPint _offset, const MTPlong &_max_id, MTPint _limit) : vuser_id(_user_id), voffset(_offset), vmax_id(_max_id), vlimit(_limit) {
 	}
 
 	uint32 innerLength() const {
@@ -14469,7 +14471,7 @@ public:
 	}
 	MTPphotos_GetUserPhotos(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPphotos_getUserPhotos>(from, end, cons) {
 	}
-	MTPphotos_GetUserPhotos(const MTPInputUser &_user_id, MTPint _offset, MTPint _max_id, MTPint _limit) : MTPBoxed<MTPphotos_getUserPhotos>(MTPphotos_getUserPhotos(_user_id, _offset, _max_id, _limit)) {
+	MTPphotos_GetUserPhotos(const MTPInputUser &_user_id, MTPint _offset, const MTPlong &_max_id, MTPint _limit) : MTPBoxed<MTPphotos_getUserPhotos>(MTPphotos_getUserPhotos(_user_id, _offset, _max_id, _limit)) {
 	}
 };
 
@@ -17049,6 +17051,54 @@ public:
 	}
 };
 
+class MTPhelp_getAppChangelog { // RPC method 'help.getAppChangelog'
+public:
+	MTPstring vdevice_model;
+	MTPstring vsystem_version;
+	MTPstring vapp_version;
+	MTPstring vlang_code;
+
+	MTPhelp_getAppChangelog() {
+	}
+	MTPhelp_getAppChangelog(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_getAppChangelog) {
+		read(from, end, cons);
+	}
+	MTPhelp_getAppChangelog(const MTPstring &_device_model, const MTPstring &_system_version, const MTPstring &_app_version, const MTPstring &_lang_code) : vdevice_model(_device_model), vsystem_version(_system_version), vapp_version(_app_version), vlang_code(_lang_code) {
+	}
+
+	uint32 innerLength() const {
+		return vdevice_model.innerLength() + vsystem_version.innerLength() + vapp_version.innerLength() + vlang_code.innerLength();
+	}
+	mtpTypeId type() const {
+		return mtpc_help_getAppChangelog;
+	}
+	void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_help_getAppChangelog) {
+		vdevice_model.read(from, end);
+		vsystem_version.read(from, end);
+		vapp_version.read(from, end);
+		vlang_code.read(from, end);
+	}
+	void write(mtpBuffer &to) const {
+		vdevice_model.write(to);
+		vsystem_version.write(to);
+		vapp_version.write(to);
+		vlang_code.write(to);
+	}
+
+	typedef MTPhelp_AppChangelog ResponseType;
+};
+class MTPhelp_GetAppChangelog : public MTPBoxed<MTPhelp_getAppChangelog> {
+public:
+	MTPhelp_GetAppChangelog() {
+	}
+	MTPhelp_GetAppChangelog(const MTPhelp_getAppChangelog &v) : MTPBoxed<MTPhelp_getAppChangelog>(v) {
+	}
+	MTPhelp_GetAppChangelog(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPhelp_getAppChangelog>(from, end, cons) {
+	}
+	MTPhelp_GetAppChangelog(const MTPstring &_device_model, const MTPstring &_system_version, const MTPstring &_app_version, const MTPstring &_lang_code) : MTPBoxed<MTPhelp_getAppChangelog>(MTPhelp_getAppChangelog(_device_model, _system_version, _app_version, _lang_code)) {
+	}
+};
+
 // Inline methods definition
 
 inline MTPresPQ::MTPresPQ() : mtpDataOwner(new MTPDresPQ()) {
@@ -17989,18 +18039,14 @@ inline MTPnull MTP_null() {
 
 inline uint32 MTPinputPeer::innerLength() const {
 	switch (_type) {
-		case mtpc_inputPeerContact: {
-			const MTPDinputPeerContact &v(c_inputPeerContact());
-			return v.vuser_id.innerLength();
-		}
-		case mtpc_inputPeerForeign: {
-			const MTPDinputPeerForeign &v(c_inputPeerForeign());
-			return v.vuser_id.innerLength() + v.vaccess_hash.innerLength();
-		}
 		case mtpc_inputPeerChat: {
 			const MTPDinputPeerChat &v(c_inputPeerChat());
 			return v.vchat_id.innerLength();
 		}
+		case mtpc_inputPeerUser: {
+			const MTPDinputPeerUser &v(c_inputPeerUser());
+			return v.vuser_id.innerLength() + v.vaccess_hash.innerLength();
+		}
 	}
 	return 0;
 }
@@ -18013,82 +18059,63 @@ inline void MTPinputPeer::read(const mtpPrime *&from, const mtpPrime *end, mtpTy
 	switch (cons) {
 		case mtpc_inputPeerEmpty: _type = cons; break;
 		case mtpc_inputPeerSelf: _type = cons; break;
-		case mtpc_inputPeerContact: _type = cons; {
-			if (!data) setData(new MTPDinputPeerContact());
-			MTPDinputPeerContact &v(_inputPeerContact());
-			v.vuser_id.read(from, end);
-		} break;
-		case mtpc_inputPeerForeign: _type = cons; {
-			if (!data) setData(new MTPDinputPeerForeign());
-			MTPDinputPeerForeign &v(_inputPeerForeign());
-			v.vuser_id.read(from, end);
-			v.vaccess_hash.read(from, end);
-		} break;
 		case mtpc_inputPeerChat: _type = cons; {
 			if (!data) setData(new MTPDinputPeerChat());
 			MTPDinputPeerChat &v(_inputPeerChat());
 			v.vchat_id.read(from, end);
 		} break;
+		case mtpc_inputPeerUser: _type = cons; {
+			if (!data) setData(new MTPDinputPeerUser());
+			MTPDinputPeerUser &v(_inputPeerUser());
+			v.vuser_id.read(from, end);
+			v.vaccess_hash.read(from, end);
+		} break;
 		default: throw mtpErrorUnexpected(cons, "MTPinputPeer");
 	}
 }
 inline void MTPinputPeer::write(mtpBuffer &to) const {
 	switch (_type) {
-		case mtpc_inputPeerContact: {
-			const MTPDinputPeerContact &v(c_inputPeerContact());
-			v.vuser_id.write(to);
-		} break;
-		case mtpc_inputPeerForeign: {
-			const MTPDinputPeerForeign &v(c_inputPeerForeign());
-			v.vuser_id.write(to);
-			v.vaccess_hash.write(to);
-		} break;
 		case mtpc_inputPeerChat: {
 			const MTPDinputPeerChat &v(c_inputPeerChat());
 			v.vchat_id.write(to);
 		} break;
+		case mtpc_inputPeerUser: {
+			const MTPDinputPeerUser &v(c_inputPeerUser());
+			v.vuser_id.write(to);
+			v.vaccess_hash.write(to);
+		} break;
 	}
 }
 inline MTPinputPeer::MTPinputPeer(mtpTypeId type) : mtpDataOwner(0), _type(type) {
 	switch (type) {
 		case mtpc_inputPeerEmpty: break;
 		case mtpc_inputPeerSelf: break;
-		case mtpc_inputPeerContact: setData(new MTPDinputPeerContact()); break;
-		case mtpc_inputPeerForeign: setData(new MTPDinputPeerForeign()); break;
 		case mtpc_inputPeerChat: setData(new MTPDinputPeerChat()); break;
+		case mtpc_inputPeerUser: setData(new MTPDinputPeerUser()); break;
 		default: throw mtpErrorBadTypeId(type, "MTPinputPeer");
 	}
 }
-inline MTPinputPeer::MTPinputPeer(MTPDinputPeerContact *_data) : mtpDataOwner(_data), _type(mtpc_inputPeerContact) {
-}
-inline MTPinputPeer::MTPinputPeer(MTPDinputPeerForeign *_data) : mtpDataOwner(_data), _type(mtpc_inputPeerForeign) {
-}
 inline MTPinputPeer::MTPinputPeer(MTPDinputPeerChat *_data) : mtpDataOwner(_data), _type(mtpc_inputPeerChat) {
 }
+inline MTPinputPeer::MTPinputPeer(MTPDinputPeerUser *_data) : mtpDataOwner(_data), _type(mtpc_inputPeerUser) {
+}
 inline MTPinputPeer MTP_inputPeerEmpty() {
 	return MTPinputPeer(mtpc_inputPeerEmpty);
 }
 inline MTPinputPeer MTP_inputPeerSelf() {
 	return MTPinputPeer(mtpc_inputPeerSelf);
 }
-inline MTPinputPeer MTP_inputPeerContact(MTPint _user_id) {
-	return MTPinputPeer(new MTPDinputPeerContact(_user_id));
-}
-inline MTPinputPeer MTP_inputPeerForeign(MTPint _user_id, const MTPlong &_access_hash) {
-	return MTPinputPeer(new MTPDinputPeerForeign(_user_id, _access_hash));
-}
 inline MTPinputPeer MTP_inputPeerChat(MTPint _chat_id) {
 	return MTPinputPeer(new MTPDinputPeerChat(_chat_id));
 }
+inline MTPinputPeer MTP_inputPeerUser(MTPint _user_id, const MTPlong &_access_hash) {
+	return MTPinputPeer(new MTPDinputPeerUser(_user_id, _access_hash));
+}
 
 inline uint32 MTPinputUser::innerLength() const {
 	switch (_type) {
-		case mtpc_inputUserContact: {
-			const MTPDinputUserContact &v(c_inputUserContact());
-			return v.vuser_id.innerLength();
-		}
-		case mtpc_inputUserForeign: {
-			const MTPDinputUserForeign &v(c_inputUserForeign());
+		case mtpc_inputUser: {
+			const MTPDinputUser &v(c_inputUser());
 			return v.vuser_id.innerLength() + v.vaccess_hash.innerLength();
 		}
 	}
@@ -18103,14 +18130,9 @@ inline void MTPinputUser::read(const mtpPrime *&from, const mtpPrime *end, mtpTy
 	switch (cons) {
 		case mtpc_inputUserEmpty: _type = cons; break;
 		case mtpc_inputUserSelf: _type = cons; break;
-		case mtpc_inputUserContact: _type = cons; {
-			if (!data) setData(new MTPDinputUserContact());
-			MTPDinputUserContact &v(_inputUserContact());
-			v.vuser_id.read(from, end);
-		} break;
-		case mtpc_inputUserForeign: _type = cons; {
-			if (!data) setData(new MTPDinputUserForeign());
-			MTPDinputUserForeign &v(_inputUserForeign());
+		case mtpc_inputUser: _type = cons; {
+			if (!data) setData(new MTPDinputUser());
+			MTPDinputUser &v(_inputUser());
 			v.vuser_id.read(from, end);
 			v.vaccess_hash.read(from, end);
 		} break;
@@ -18119,12 +18141,8 @@ inline void MTPinputUser::read(const mtpPrime *&from, const mtpPrime *end, mtpTy
 }
 inline void MTPinputUser::write(mtpBuffer &to) const {
 	switch (_type) {
-		case mtpc_inputUserContact: {
-			const MTPDinputUserContact &v(c_inputUserContact());
-			v.vuser_id.write(to);
-		} break;
-		case mtpc_inputUserForeign: {
-			const MTPDinputUserForeign &v(c_inputUserForeign());
+		case mtpc_inputUser: {
+			const MTPDinputUser &v(c_inputUser());
 			v.vuser_id.write(to);
 			v.vaccess_hash.write(to);
 		} break;
@@ -18134,14 +18152,11 @@ inline MTPinputUser::MTPinputUser(mtpTypeId type) : mtpDataOwner(0), _type(type)
 	switch (type) {
 		case mtpc_inputUserEmpty: break;
 		case mtpc_inputUserSelf: break;
-		case mtpc_inputUserContact: setData(new MTPDinputUserContact()); break;
-		case mtpc_inputUserForeign: setData(new MTPDinputUserForeign()); break;
+		case mtpc_inputUser: setData(new MTPDinputUser()); break;
 		default: throw mtpErrorBadTypeId(type, "MTPinputUser");
 	}
 }
-inline MTPinputUser::MTPinputUser(MTPDinputUserContact *_data) : mtpDataOwner(_data), _type(mtpc_inputUserContact) {
-}
-inline MTPinputUser::MTPinputUser(MTPDinputUserForeign *_data) : mtpDataOwner(_data), _type(mtpc_inputUserForeign) {
+inline MTPinputUser::MTPinputUser(MTPDinputUser *_data) : mtpDataOwner(_data), _type(mtpc_inputUser) {
 }
 inline MTPinputUser MTP_inputUserEmpty() {
 	return MTPinputUser(mtpc_inputUserEmpty);
@@ -18149,11 +18164,8 @@ inline MTPinputUser MTP_inputUserEmpty() {
 inline MTPinputUser MTP_inputUserSelf() {
 	return MTPinputUser(mtpc_inputUserSelf);
 }
-inline MTPinputUser MTP_inputUserContact(MTPint _user_id) {
-	return MTPinputUser(new MTPDinputUserContact(_user_id));
-}
-inline MTPinputUser MTP_inputUserForeign(MTPint _user_id, const MTPlong &_access_hash) {
-	return MTPinputUser(new MTPDinputUserForeign(_user_id, _access_hash));
+inline MTPinputUser MTP_inputUser(MTPint _user_id, const MTPlong &_access_hash) {
+	return MTPinputUser(new MTPDinputUser(_user_id, _access_hash));
 }
 
 inline MTPinputContact::MTPinputContact() : mtpDataOwner(new MTPDinputPhoneContact()) {
@@ -20319,7 +20331,7 @@ inline uint32 MTPphoto::innerLength() const {
 		}
 		case mtpc_photo: {
 			const MTPDphoto &v(c_photo());
-			return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vuser_id.innerLength() + v.vdate.innerLength() + v.vgeo.innerLength() + v.vsizes.innerLength();
+			return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vdate.innerLength() + v.vsizes.innerLength();
 		}
 	}
 	return 0;
@@ -20341,9 +20353,7 @@ inline void MTPphoto::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId
 			MTPDphoto &v(_photo());
 			v.vid.read(from, end);
 			v.vaccess_hash.read(from, end);
-			v.vuser_id.read(from, end);
 			v.vdate.read(from, end);
-			v.vgeo.read(from, end);
 			v.vsizes.read(from, end);
 		} break;
 		default: throw mtpErrorUnexpected(cons, "MTPphoto");
@@ -20359,9 +20369,7 @@ inline void MTPphoto::write(mtpBuffer &to) const {
 			const MTPDphoto &v(c_photo());
 			v.vid.write(to);
 			v.vaccess_hash.write(to);
-			v.vuser_id.write(to);
 			v.vdate.write(to);
-			v.vgeo.write(to);
 			v.vsizes.write(to);
 		} break;
 	}
@@ -20380,8 +20388,8 @@ inline MTPphoto::MTPphoto(MTPDphoto *_data) : mtpDataOwner(_data), _type(mtpc_ph
 inline MTPphoto MTP_photoEmpty(const MTPlong &_id) {
 	return MTPphoto(new MTPDphotoEmpty(_id));
 }
-inline MTPphoto MTP_photo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, const MTPGeoPoint &_geo, const MTPVector<MTPPhotoSize> &_sizes) {
-	return MTPphoto(new MTPDphoto(_id, _access_hash, _user_id, _date, _geo, _sizes));
+inline MTPphoto MTP_photo(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, const MTPVector<MTPPhotoSize> &_sizes) {
+	return MTPphoto(new MTPDphoto(_id, _access_hash, _date, _sizes));
 }
 
 inline uint32 MTPphotoSize::innerLength() const {
@@ -20490,7 +20498,7 @@ inline uint32 MTPvideo::innerLength() const {
 		}
 		case mtpc_video: {
 			const MTPDvideo &v(c_video());
-			return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vuser_id.innerLength() + v.vdate.innerLength() + v.vduration.innerLength() + v.vsize.innerLength() + v.vthumb.innerLength() + v.vdc_id.innerLength() + v.vw.innerLength() + v.vh.innerLength();
+			return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vdate.innerLength() + v.vduration.innerLength() + v.vmime_type.innerLength() + v.vsize.innerLength() + v.vthumb.innerLength() + v.vdc_id.innerLength() + v.vw.innerLength() + v.vh.innerLength();
 		}
 	}
 	return 0;
@@ -20512,9 +20520,9 @@ inline void MTPvideo::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId
 			MTPDvideo &v(_video());
 			v.vid.read(from, end);
 			v.vaccess_hash.read(from, end);
-			v.vuser_id.read(from, end);
 			v.vdate.read(from, end);
 			v.vduration.read(from, end);
+			v.vmime_type.read(from, end);
 			v.vsize.read(from, end);
 			v.vthumb.read(from, end);
 			v.vdc_id.read(from, end);
@@ -20534,9 +20542,9 @@ inline void MTPvideo::write(mtpBuffer &to) const {
 			const MTPDvideo &v(c_video());
 			v.vid.write(to);
 			v.vaccess_hash.write(to);
-			v.vuser_id.write(to);
 			v.vdate.write(to);
 			v.vduration.write(to);
+			v.vmime_type.write(to);
 			v.vsize.write(to);
 			v.vthumb.write(to);
 			v.vdc_id.write(to);
@@ -20559,8 +20567,8 @@ inline MTPvideo::MTPvideo(MTPDvideo *_data) : mtpDataOwner(_data), _type(mtpc_vi
 inline MTPvideo MTP_videoEmpty(const MTPlong &_id) {
 	return MTPvideo(new MTPDvideoEmpty(_id));
 }
-inline MTPvideo MTP_video(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h) {
-	return MTPvideo(new MTPDvideo(_id, _access_hash, _user_id, _date, _duration, _size, _thumb, _dc_id, _w, _h));
+inline MTPvideo MTP_video(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, const MTPPhotoSize &_thumb, MTPint _dc_id, MTPint _w, MTPint _h) {
+	return MTPvideo(new MTPDvideo(_id, _access_hash, _date, _duration, _mime_type, _size, _thumb, _dc_id, _w, _h));
 }
 
 inline uint32 MTPgeoPoint::innerLength() const {
@@ -21852,6 +21860,7 @@ inline void MTPmessagesFilter::read(const mtpPrime *&from, const mtpPrime *end,
 		case mtpc_inputMessagesFilterDocument: _type = cons; break;
 		case mtpc_inputMessagesFilterAudio: _type = cons; break;
 		case mtpc_inputMessagesFilterAudioDocuments: _type = cons; break;
+		case mtpc_inputMessagesFilterUrl: _type = cons; break;
 		default: throw mtpErrorUnexpected(cons, "MTPmessagesFilter");
 	}
 }
@@ -21869,6 +21878,7 @@ inline MTPmessagesFilter::MTPmessagesFilter(mtpTypeId type) : _type(type) {
 		case mtpc_inputMessagesFilterDocument: break;
 		case mtpc_inputMessagesFilterAudio: break;
 		case mtpc_inputMessagesFilterAudioDocuments: break;
+		case mtpc_inputMessagesFilterUrl: break;
 		default: throw mtpErrorBadTypeId(type, "MTPmessagesFilter");
 	}
 }
@@ -21896,6 +21906,9 @@ inline MTPmessagesFilter MTP_inputMessagesFilterAudio() {
 inline MTPmessagesFilter MTP_inputMessagesFilterAudioDocuments() {
 	return MTPmessagesFilter(mtpc_inputMessagesFilterAudioDocuments);
 }
+inline MTPmessagesFilter MTP_inputMessagesFilterUrl() {
+	return MTPmessagesFilter(mtpc_inputMessagesFilterUrl);
+}
 
 inline uint32 MTPupdate::innerLength() const {
 	switch (_type) {
@@ -24147,7 +24160,7 @@ inline uint32 MTPaudio::innerLength() const {
 		}
 		case mtpc_audio: {
 			const MTPDaudio &v(c_audio());
-			return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vuser_id.innerLength() + v.vdate.innerLength() + v.vduration.innerLength() + v.vmime_type.innerLength() + v.vsize.innerLength() + v.vdc_id.innerLength();
+			return v.vid.innerLength() + v.vaccess_hash.innerLength() + v.vdate.innerLength() + v.vduration.innerLength() + v.vmime_type.innerLength() + v.vsize.innerLength() + v.vdc_id.innerLength();
 		}
 	}
 	return 0;
@@ -24169,7 +24182,6 @@ inline void MTPaudio::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId
 			MTPDaudio &v(_audio());
 			v.vid.read(from, end);
 			v.vaccess_hash.read(from, end);
-			v.vuser_id.read(from, end);
 			v.vdate.read(from, end);
 			v.vduration.read(from, end);
 			v.vmime_type.read(from, end);
@@ -24189,7 +24201,6 @@ inline void MTPaudio::write(mtpBuffer &to) const {
 			const MTPDaudio &v(c_audio());
 			v.vid.write(to);
 			v.vaccess_hash.write(to);
-			v.vuser_id.write(to);
 			v.vdate.write(to);
 			v.vduration.write(to);
 			v.vmime_type.write(to);
@@ -24212,8 +24223,8 @@ inline MTPaudio::MTPaudio(MTPDaudio *_data) : mtpDataOwner(_data), _type(mtpc_au
 inline MTPaudio MTP_audioEmpty(const MTPlong &_id) {
 	return MTPaudio(new MTPDaudioEmpty(_id));
 }
-inline MTPaudio MTP_audio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _user_id, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id) {
-	return MTPaudio(new MTPDaudio(_id, _access_hash, _user_id, _date, _duration, _mime_type, _size, _dc_id));
+inline MTPaudio MTP_audio(const MTPlong &_id, const MTPlong &_access_hash, MTPint _date, MTPint _duration, const MTPstring &_mime_type, MTPint _size, MTPint _dc_id) {
+	return MTPaudio(new MTPDaudio(_id, _access_hash, _date, _duration, _mime_type, _size, _dc_id));
 }
 
 inline uint32 MTPdocument::innerLength() const {
@@ -26072,6 +26083,55 @@ inline MTPreplyMarkup MTP_replyKeyboardMarkup(MTPint _flags, const MTPVector<MTP
 	return MTPreplyMarkup(new MTPDreplyKeyboardMarkup(_flags, _rows));
 }
 
+inline uint32 MTPhelp_appChangelog::innerLength() const {
+	switch (_type) {
+		case mtpc_help_appChangelog: {
+			const MTPDhelp_appChangelog &v(c_help_appChangelog());
+			return v.vtext.innerLength();
+		}
+	}
+	return 0;
+}
+inline mtpTypeId MTPhelp_appChangelog::type() const {
+	if (!_type) throw mtpErrorUninitialized();
+	return _type;
+}
+inline void MTPhelp_appChangelog::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {
+	if (cons != _type) setData(0);
+	switch (cons) {
+		case mtpc_help_appChangelogEmpty: _type = cons; break;
+		case mtpc_help_appChangelog: _type = cons; {
+			if (!data) setData(new MTPDhelp_appChangelog());
+			MTPDhelp_appChangelog &v(_help_appChangelog());
+			v.vtext.read(from, end);
+		} break;
+		default: throw mtpErrorUnexpected(cons, "MTPhelp_appChangelog");
+	}
+}
+inline void MTPhelp_appChangelog::write(mtpBuffer &to) const {
+	switch (_type) {
+		case mtpc_help_appChangelog: {
+			const MTPDhelp_appChangelog &v(c_help_appChangelog());
+			v.vtext.write(to);
+		} break;
+	}
+}
+inline MTPhelp_appChangelog::MTPhelp_appChangelog(mtpTypeId type) : mtpDataOwner(0), _type(type) {
+	switch (type) {
+		case mtpc_help_appChangelogEmpty: break;
+		case mtpc_help_appChangelog: setData(new MTPDhelp_appChangelog()); break;
+		default: throw mtpErrorBadTypeId(type, "MTPhelp_appChangelog");
+	}
+}
+inline MTPhelp_appChangelog::MTPhelp_appChangelog(MTPDhelp_appChangelog *_data) : mtpDataOwner(_data), _type(mtpc_help_appChangelog) {
+}
+inline MTPhelp_appChangelog MTP_help_appChangelogEmpty() {
+	return MTPhelp_appChangelog(mtpc_help_appChangelogEmpty);
+}
+inline MTPhelp_appChangelog MTP_help_appChangelog(const MTPstring &_text) {
+	return MTPhelp_appChangelog(new MTPDhelp_appChangelog(_text));
+}
+
 // Human-readable text serialization
 #if (defined _DEBUG || defined _WITH_DEBUG)
 
diff --git a/Telegram/SourceFiles/mtproto/scheme.tl b/Telegram/SourceFiles/mtproto/scheme.tl
index 4e4d27e91..d4167a25b 100644
--- a/Telegram/SourceFiles/mtproto/scheme.tl
+++ b/Telegram/SourceFiles/mtproto/scheme.tl
@@ -132,14 +132,10 @@ null#56730bcc = Null;
 
 inputPeerEmpty#7f3b18ea = InputPeer;
 inputPeerSelf#7da07ec9 = InputPeer;
-inputPeerContact#1023dbe8 user_id:int = InputPeer;
-inputPeerForeign#9b447325 user_id:int access_hash:long = InputPeer;
 inputPeerChat#179be863 chat_id:int = InputPeer;
 
 inputUserEmpty#b98886cf = InputUser;
 inputUserSelf#f7c1b13f = InputUser;
-inputUserContact#86e94f65 user_id:int = InputUser;
-inputUserForeign#655e74ff user_id:int access_hash:long = InputUser;
 
 inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact;
 
@@ -237,14 +233,14 @@ messageActionChatDeleteUser#b2ae9b0c user_id:int = MessageAction;
 dialog#c1dd804a peer:Peer top_message:int read_inbox_max_id:int unread_count:int notify_settings:PeerNotifySettings = Dialog;
 
 photoEmpty#2331b22d id:long = Photo;
-photo#c3838076 id:long access_hash:long user_id:int date:int geo:GeoPoint sizes:Vector<PhotoSize> = Photo;
+photo#cded42fe id:long access_hash:long date:int sizes:Vector<PhotoSize> = Photo;
 
 photoSizeEmpty#e17e23c type:string = PhotoSize;
 photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
 photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
 
 videoEmpty#c10658a8 id:long = Video;
-video#ee9f4a4d id:long access_hash:long user_id:int date:int duration:int size:int thumb:PhotoSize dc_id:int w:int h:int = Video;
+video#f72887d3 id:long access_hash:long date:int duration:int mime_type:string size:int thumb:PhotoSize dc_id:int w:int h:int = Video;
 
 geoPointEmpty#1117dd5f = GeoPoint;
 geoPoint#2049d70c long:double lat:double = GeoPoint;
@@ -325,6 +321,7 @@ inputMessagesFilterPhotoVideoDocuments#d95e73bb = MessagesFilter;
 inputMessagesFilterDocument#9eddf188 = MessagesFilter;
 inputMessagesFilterAudio#cfc87522 = MessagesFilter;
 inputMessagesFilterAudioDocuments#5afbf764 = MessagesFilter;
+inputMessagesFilterUrl#7ef0dd87 = MessagesFilter;
 
 updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
 updateMessageID#4e90bfd6 id:int random_id:long = Update;
@@ -454,7 +451,7 @@ inputAudioFileLocation#74dc404d id:long access_hash:long = InputFileLocation;
 inputDocumentFileLocation#4e45abe9 id:long access_hash:long = InputFileLocation;
 
 audioEmpty#586988d8 id:long = Audio;
-audio#c7ac6496 id:long access_hash:long user_id:int date:int duration:int mime_type:string size:int dc_id:int = Audio;
+audio#f9e35055 id:long access_hash:long date:int duration:int mime_type:string size:int dc_id:int = Audio;
 
 documentEmpty#36f8c871 id:long = Document;
 document#f9a39f4f id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector<DocumentAttribute> = Document;
@@ -607,6 +604,13 @@ replyKeyboardHide#a03e5b85 flags:# = ReplyMarkup;
 replyKeyboardForceReply#f4108aa0 flags:# = ReplyMarkup;
 replyKeyboardMarkup#3502758c flags:# rows:Vector<KeyboardButtonRow> = ReplyMarkup;
 
+inputPeerUser#7b8e7de6 user_id:int access_hash:long = InputPeer;
+
+inputUser#d8292816 user_id:int access_hash:long = InputUser;
+
+help.appChangelogEmpty#af7e0394 = help.AppChangelog;
+help.appChangelog#4668e6bd text:string = help.AppChangelog;
+
 ---functions---
 
 invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@@ -685,7 +689,7 @@ help.getAppUpdate#c812ac7e device_model:string system_version:string app_version
 help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
 help.getInviteText#a4a95186 lang_code:string = help.InviteText;
 
-photos.getUserPhotos#b7ee553c user_id:InputUser offset:int max_id:int limit:int = photos.Photos;
+photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int = photos.Photos;
 
 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;
@@ -770,3 +774,5 @@ messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet
 messages.installStickerSet#7b30c3a6 stickerset:InputStickerSet disabled:Bool = Bool;
 messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
 messages.startBot#1b3e0ffc bot:InputUser chat_id:int random_id:long start_param:string = Updates;
+
+help.getAppChangelog#5bab7fb2 device_model:string system_version:string app_version:string lang_code:string = help.AppChangelog;
diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp
index 30743e737..e6cf819e2 100644
--- a/Telegram/SourceFiles/profilewidget.cpp
+++ b/Telegram/SourceFiles/profilewidget.cpp
@@ -56,11 +56,6 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
 	// settings
 	_enableNotifications(this, lang(lng_profile_enable_notifications)),
 
-	// actions
-	_searchInPeer(this, lang(lng_profile_search_messages)),
-	_clearHistory(this, lang(lng_profile_clear_history)),
-	_deleteConversation(this, lang(_peer->chat ? lng_profile_clear_and_exit : lng_profile_delete_conversation)),
-
 	// shared media
 	_allMediaTypes(false),
 	_mediaShowAll(this, lang(lng_profile_show_all_types)),
@@ -69,6 +64,14 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
 	_mediaDocuments(this, QString()),
 	_mediaAudios(this, QString()),
 
+	// actions
+	_searchInPeer(this, lang(lng_profile_search_messages)),
+	_clearHistory(this, lang(lng_profile_clear_history)),
+	_deleteConversation(this, lang(_peer->chat ? lng_profile_clear_and_exit : lng_profile_delete_conversation)),
+	_wasBlocked(_peerUser ? _peerUser->blocked : UserBlockUnknown),
+	_blockRequest(0),
+	_blockUser(this, lang((_peerUser && _peerUser->botInfo) ? lng_profile_block_bot : lng_profile_block_user), st::btnRedLink),
+
 	// participants
 	_pHeight(st::profileListPhotoSize + st::profileListPadding.height() * 2),
 	_kickWidth(st::linkFont->m.width(lang(lng_profile_kick))),
@@ -80,12 +83,15 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
 	connect(App::api(), SIGNAL(fullPeerUpdated(PeerData*)), this, SLOT(onFullPeerUpdated(PeerData*)));
 
 	if (_peerUser) {
+		if (_peerUser->blocked == UserIsBlocked) {
+			_blockUser.setText(lang(_peerUser->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user));
+		}
 		_phoneText = App::formatPhone(_peerUser->phone);
 		PhotoData *userPhoto = (_peerUser->photoId && _peerUser->photoId != UnknownPeerPhotoId) ? App::photo(_peerUser->photoId) : 0;
 		if (userPhoto && userPhoto->date) {
 			_photoLink = TextLinkPtr(new PhotoLink(userPhoto, _peer));
 		}
-		if ((_peerUser->botInfo && !_peerUser->botInfo->inited) || (_peerUser->photoId == UnknownPeerPhotoId) || (_peerUser->photoId && !userPhoto->date)) {
+		if ((_peerUser->botInfo && !_peerUser->botInfo->inited) || (_peerUser->photoId == UnknownPeerPhotoId) || (_peerUser->photoId && !userPhoto->date) || (_peerUser->blocked == UserBlockUnknown)) {
 			App::api()->requestFullPeer(_peer);
 		}
 	} else {
@@ -153,11 +159,6 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
 	// settings
 	connect(&_enableNotifications, SIGNAL(clicked()), this, SLOT(onEnableNotifications()));
 
-	// actions
-	connect(&_searchInPeer, SIGNAL(clicked()), this, SLOT(onSearchInPeer()));
-	connect(&_clearHistory, SIGNAL(clicked()), this, SLOT(onClearHistory()));
-	connect(&_deleteConversation, SIGNAL(clicked()), this, SLOT(onDeleteConversation()));
-
 	// shared media
 	connect(&_mediaShowAll, SIGNAL(clicked()), this, SLOT(onMediaShowAll()));
 	connect(&_mediaPhotos, SIGNAL(clicked()), this, SLOT(onMediaPhotos()));
@@ -170,6 +171,12 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
 	_mediaLinks[OverviewAudios] = &_mediaAudios;
 	App::main()->preloadOverviews(_peer);
 
+	// actions
+	connect(&_searchInPeer, SIGNAL(clicked()), this, SLOT(onSearchInPeer()));
+	connect(&_clearHistory, SIGNAL(clicked()), this, SLOT(onClearHistory()));
+	connect(&_deleteConversation, SIGNAL(clicked()), this, SLOT(onDeleteConversation()));
+	connect(&_blockUser, SIGNAL(clicked()), this, SLOT(onBlockUser()));
+
 	App::contextItem(0);
 
 	resizeEvent(0);
@@ -281,6 +288,28 @@ void ProfileInner::onDeleteConversationSure() {
 	}
 }
 
+void ProfileInner::onBlockUser() {
+	if (!_peerUser || _blockRequest) return;
+	if (_peerUser->blocked == UserIsBlocked) {
+		_blockRequest = MTP::send(MTPcontacts_Unblock(_peerUser->inputUser), rpcDone(&ProfileInner::blockDone, false), rpcFail(&ProfileInner::blockFail));
+	} else {
+		_blockRequest = MTP::send(MTPcontacts_Block(_peerUser->inputUser), rpcDone(&ProfileInner::blockDone, true), rpcFail(&ProfileInner::blockFail));
+	}
+}
+
+void ProfileInner::blockDone(bool blocked, const MTPBool &result) {
+	_blockRequest = 0;
+	if (!_peerUser) return;
+	_peerUser->blocked = blocked ? UserIsBlocked : UserIsNotBlocked;
+	emit App::main()->peerUpdated(_peerUser);
+}
+
+bool ProfileInner::blockFail(const RPCError &error) {
+	if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
+	//_blockRequest = 0;
+	return false;
+}
+
 void ProfileInner::onAddParticipant() {
 	App::wnd()->showLayer(new ContactsBox(_peerChat));
 }
@@ -410,6 +439,10 @@ void ProfileInner::peerUpdated(PeerData *data) {
 		if (_peerUser) {
 			_phoneText = App::formatPhone(_peerUser->phone);
 			if (_peerUser->photoId && _peerUser->photoId != UnknownPeerPhotoId) photo = App::photo(_peerUser->photoId);
+			if (_wasBlocked != _peerUser->blocked) {
+				_wasBlocked = _peerUser->blocked;
+				_blockUser.setText(lang((_peerUser->blocked == UserIsBlocked) ? (_peerUser->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user) : (_peerUser->botInfo ? lng_profile_block_bot : lng_profile_block_user)));
+			}
 		} else {
 			if (_peerChat->photoId && _peerChat->photoId != UnknownPeerPhotoId) photo = App::photo(_peerChat->photoId);
 		}
@@ -595,14 +628,6 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
 
 	top += _enableNotifications.height();
 
-	// actions
-	p.setFont(st::profileHeaderFont->f);
-	p.setPen(st::profileHeaderColor->p);
-	p.drawText(_left + st::profileHeaderLeft, top + st::profileHeaderTop + st::profileHeaderFont->ascent, lang(lng_profile_actions_section));
-	top += st::profileHeaderSkip;
-
-	top += _searchInPeer.height() + st::setLittleSkip + _clearHistory.height() + st::setLittleSkip + _deleteConversation.height();
-
 	// shared media
 	p.setFont(st::profileHeaderFont->f);
 	p.setPen(st::profileHeaderColor->p);
@@ -644,6 +669,15 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
 		top += _mediaLinks[OverviewPhotos]->height();
 	}
 
+	// actions
+	p.setFont(st::profileHeaderFont->f);
+	p.setPen(st::profileHeaderColor->p);
+	p.drawText(_left + st::profileHeaderLeft, top + st::profileHeaderTop + st::profileHeaderFont->ascent, lang(lng_profile_actions_section));
+	top += st::profileHeaderSkip;
+
+	top += _searchInPeer.height() + st::setLittleSkip + _clearHistory.height() + st::setLittleSkip + _deleteConversation.height();
+	if (_peerUser && _peerUser->id != MTP::authedId()) top += st::setSectionSkip + _blockUser.height();
+
 	// participants
 	if (_peerChat && (_peerChat->count > 0 || !_participants.isEmpty())) {
 		QString sectionHeader = lang(_participants.isEmpty() ? lng_profile_loading : lng_profile_participants_section);
@@ -741,7 +775,7 @@ void ProfileInner::updateSelected() {
 		update(QRect(_left, _aboutTop, _width, _aboutHeight));
 	}
 
-	int32 partfrom = _mediaAudios.y() + _mediaAudios.height() + st::profileHeaderSkip;
+	int32 partfrom = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
 	int32 newSelected = (lp.x() >= _left - st::profileListPadding.width() && lp.x() < _left + _width + st::profileListPadding.width() && lp.y() >= partfrom) ? (lp.y() - partfrom) / _pHeight : -1;
 
 	UserData *newKickOver = 0;
@@ -889,12 +923,6 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
 	top += st::profileHeaderSkip;
 	_enableNotifications.move(_left, top); top += _enableNotifications.height();
 
-	// actions
-	top += st::profileHeaderSkip;
-	_searchInPeer.move(_left, top);	top += _searchInPeer.height() + st::setLittleSkip;
-	_clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip;
-	_deleteConversation.move(_left, top); top += _deleteConversation.height();
-
 	// shared media
 	top += st::profileHeaderSkip;
 
@@ -914,6 +942,16 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
 	}
 	top += _mediaLinks[OverviewPhotos]->height();
 
+	// actions
+	top += st::profileHeaderSkip;
+	_searchInPeer.move(_left, top);	top += _searchInPeer.height() + st::setLittleSkip;
+	_clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip;
+	_deleteConversation.move(_left, top); top += _deleteConversation.height();
+	if (_peerUser && _peerUser->id != MTP::authedId()) {
+		top += st::setSectionSkip;
+		_blockUser.move(_left, top); top += _blockUser.height();
+	}
+
 	// participants
 	if (_peerChat && (_peerChat->count > 0 || !_participants.isEmpty())) {
 		top += st::profileHeaderSkip;
@@ -1047,7 +1085,7 @@ void ProfileInner::showAll() {
 				_addParticipant.hide();
 			}
 		}
-		_enableNotifications.show();
+		_blockUser.hide();
 	} else {
 		_uploadPhoto.hide();
 		_cancelPhoto.hide();
@@ -1066,9 +1104,14 @@ void ProfileInner::showAll() {
 			_shareContact.show();
 			_inviteToGroup.hide();
 		}
-		_enableNotifications.show();
 		_clearHistory.show();
+		if (_peerUser->id != MTP::authedId()) {
+			_blockUser.show();
+		} else {
+			_blockUser.hide();
+		}
 	}
+	_enableNotifications.show();
 	updateNotifySettings();
 
 	// shared media
@@ -1111,15 +1154,13 @@ void ProfileInner::showAll() {
 	reorderParticipants();
 	int32 h;
 	if (_peerUser) {
-		h = _mediaShowAll.y() + _mediaShowAll.height() + st::profileHeaderSkip;
-		if (_mediaShowAll.isHidden()) {
-			for (int i = 0; i < OverviewCount; ++i) {
-				if (i == OverviewAudioDocuments) continue;
-				if (!_mediaLinks[i]->isHidden()) h += _mediaLinks[i]->height() + st::setLittleSkip;
-			}
+		if (_peerUser->id == MTP::authedId()) {
+			h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
+		} else {
+			h = _blockUser.y() + _blockUser.height() + st::profileHeaderSkip;
 		}
 	} else {
-		h = _mediaAudios.y() + _mediaAudios.height() + st::profileHeaderSkip;
+		h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
 		if (!_participants.isEmpty()) {
 			h += st::profileHeaderSkip + _participants.size() * _pHeight;
 		} else if (_peerChat->count > 0) {
diff --git a/Telegram/SourceFiles/profilewidget.h b/Telegram/SourceFiles/profilewidget.h
index 94765769d..5c742d31f 100644
--- a/Telegram/SourceFiles/profilewidget.h
+++ b/Telegram/SourceFiles/profilewidget.h
@@ -75,6 +75,7 @@ public slots:
 	void onClearHistorySure();
 	void onDeleteConversation();
 	void onDeleteConversationSure();
+	void onBlockUser();
 	void onAddParticipant();
 
 	void onUpdatePhoto();
@@ -146,15 +147,18 @@ private:
 	// settings
 	FlatCheckbox _enableNotifications;
 
-	// actions
-	LinkButton _searchInPeer, _clearHistory, _deleteConversation;
-
 	// shared media
 	bool _allMediaTypes;
 	LinkButton _mediaShowAll, _mediaPhotos, _mediaVideos, _mediaDocuments, _mediaAudios;
 	LinkButton *_mediaLinks[OverviewCount];
 	QString overviewLinkText(int32 type, int32 count);
 
+	// actions
+	LinkButton _searchInPeer, _clearHistory, _deleteConversation;
+	UserBlockedStatus _wasBlocked;
+	mtpRequestId _blockRequest;
+	LinkButton _blockUser;
+
 	// participants
 	int32 _pHeight;
 	int32 _kickWidth, _selectedRow, _lastPreload;
@@ -176,6 +180,9 @@ private:
 	QString _onlineText;
 	ContextMenu *_menu;
 
+	void blockDone(bool blocked, const MTPBool &result);
+	bool blockFail(const RPCError &error);
+
 };
 
 class ProfileWidget : public QWidget, public RPCSender, public Animated {
diff --git a/Telegram/SourceFiles/settingswidget.cpp b/Telegram/SourceFiles/settingswidget.cpp
index acda58647..d272122ed 100644
--- a/Telegram/SourceFiles/settingswidget.cpp
+++ b/Telegram/SourceFiles/settingswidget.cpp
@@ -187,7 +187,10 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
 	_connectionTypeText(lang(lng_connection_type) + ' '),
 	_connectionTypeWidth(st::linkFont->m.width(_connectionTypeText)),
 	_showSessions(this, lang(lng_settings_show_sessions)),
-	_logOut(this, lang(lng_settings_logout), st::btnLogout)
+	_askQuestion(this, lang(lng_settings_ask_question)),
+	_telegramFAQ(this, lang(lng_settings_faq)),
+	_logOut(this, lang(lng_settings_logout), st::btnLogout),
+	_supportGetRequest(0)
 {
 	if (self()) {
 		_nameText.setText(st::setNameFont, _nameCache, _textNameOptions);
@@ -290,6 +293,8 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
 	connect(&_passwordTurnOff, SIGNAL(clicked()), this, SLOT(onPasswordOff()));
 	connect(&_connectionType, SIGNAL(clicked()), this, SLOT(onConnectionType()));
 	connect(&_showSessions, SIGNAL(clicked()), this, SLOT(onShowSessions()));
+	connect(&_askQuestion, SIGNAL(clicked()), this, SLOT(onAskQuestion()));
+	connect(&_telegramFAQ, SIGNAL(clicked()), this, SLOT(onTelegramFAQ()));
 	connect(&_logOut, SIGNAL(clicked()), App::wnd(), SLOT(onLogout()));
 
     if (App::main()) {
@@ -727,7 +732,12 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
 	_connectionType.move(_left + _connectionTypeWidth, top); top += _connectionType.height() + st::setLittleSkip;
 	if (self()) {
 		_showSessions.move(_left, top); top += _showSessions.height() + st::setSectionSkip;
+		_askQuestion.move(_left, top); top += _askQuestion.height() + st::setLittleSkip;
+		_telegramFAQ.move(_left, top); top += _telegramFAQ.height() + st::setSectionSkip;
 		_logOut.move(_left, top);
+	} else {
+		top += st::setSectionSkip - st::setLittleSkip;
+		_telegramFAQ.move(_left, top);
 	}
 }
 
@@ -818,7 +828,7 @@ bool SettingsInner::animStep(float64 ms) {
 
 void SettingsInner::updateSize(int32 newWidth) {
 	if (_logOut.isHidden()) {
-		resize(newWidth, _connectionType.geometry().bottom() + st::setBottom);
+		resize(newWidth, _telegramFAQ.geometry().bottom() + st::setBottom);
 	} else {
 		resize(newWidth, _logOut.geometry().bottom() + st::setBottom);
 	}
@@ -1063,6 +1073,7 @@ void SettingsInner::showAll() {
 			_passwordTurnOff.show();
 		}
 		_showSessions.show();
+		_askQuestion.show();
 		_logOut.show();
 	} else {
 		_passcodeEdit.hide();
@@ -1071,8 +1082,10 @@ void SettingsInner::showAll() {
 		_passwordEdit.hide();
 		_passwordTurnOff.hide();
 		_showSessions.hide();
+		_askQuestion.hide();
 		_logOut.hide();
 	}
+	_telegramFAQ.show();
 }
 
 void SettingsInner::saveError(const QString &str) {
@@ -1081,6 +1094,17 @@ void SettingsInner::saveError(const QString &str) {
 	update();
 }
 
+void SettingsInner::supportGot(const MTPhelp_Support &support) {
+	if (!App::main()) return;
+
+	if (support.type() == mtpc_help_support) {
+		const MTPDhelp_support &d(support.c_help_support());
+		UserData *u = App::feedUsers(MTP_vector<MTPUser>(1, d.vuser));
+		App::main()->showPeerHistory(u->id, ShowAtUnreadMsgId);
+		App::wnd()->hideSettings();
+	}
+}
+
 void SettingsInner::onUpdatePhotoCancel() {
 	if (self()) {
 		App::app()->cancelPhotoUpdate(self()->id);
@@ -1124,6 +1148,25 @@ void SettingsInner::onShowSessions() {
 	App::wnd()->showLayer(box);
 }
 
+void SettingsInner::onAskQuestion() {
+	if (!App::self()) return;
+
+	ConfirmBox *box = new ConfirmBox(lang(lng_settings_ask_sure), lang(lng_settings_ask_ok), lang(lng_settings_faq_button));
+	connect(box, SIGNAL(confirmed()), this, SLOT(onAskQuestionSure()));
+	connect(box, SIGNAL(cancelPressed()), this, SLOT(onTelegramFAQ()));
+	App::wnd()->showLayer(box);
+}
+
+void SettingsInner::onAskQuestionSure() {
+	if (_supportGetRequest) return;
+	_supportGetRequest = MTP::send(MTPhelp_GetSupport(), rpcDone(&SettingsInner::supportGot));
+}
+
+void SettingsInner::onTelegramFAQ() {
+	App::wnd()->hideLayer();
+	QDesktopServices::openUrl(qsl("https://telegram.org/faq#general"));
+}
+
 void SettingsInner::onChangeLanguage() {
 	if ((_changeLanguage.clickModifiers() & Qt::ShiftModifier) && (_changeLanguage.clickModifiers() & Qt::AltModifier)) {
 		QString file;
diff --git a/Telegram/SourceFiles/settingswidget.h b/Telegram/SourceFiles/settingswidget.h
index 0ce9dcfa9..540c6f6c3 100644
--- a/Telegram/SourceFiles/settingswidget.h
+++ b/Telegram/SourceFiles/settingswidget.h
@@ -164,10 +164,16 @@ public slots:
 
 	void onUpdateLocalStorage();
 
+	void onAskQuestion();
+	void onAskQuestionSure();
+	void onTelegramFAQ();
+
 private:
 
 	void saveError(const QString &str = QString());
 
+	void supportGot(const MTPhelp_Support &support);
+
 	void setScale(DBIScale newScale);
 
 	QString _testlang, _secretText;
@@ -263,9 +269,11 @@ private:
 	LinkButton _connectionType;
 	QString _connectionTypeText;
 	int32 _connectionTypeWidth;
-	LinkButton _showSessions;
+	LinkButton _showSessions, _askQuestion, _telegramFAQ;
 	FlatButton _logOut;
 
+	mtpRequestId _supportGetRequest;
+
 	void gotPassword(const MTPaccount_Password &result);
 	void offPasswordDone(const MTPBool &result);
 	bool offPasswordFail(const RPCError &error);
diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp
index 080b346af..86885d11e 100644
--- a/Telegram/SourceFiles/structs.cpp
+++ b/Telegram/SourceFiles/structs.cpp
@@ -404,7 +404,7 @@ QString saveFileName(const QString &title, const QString &filter, const QString
 
 void VideoOpenLink::onClick(Qt::MouseButton button) const {
 	VideoData *data = video();
-	if ((!data->user && !data->date) || button != Qt::LeftButton) return;
+	if (!data->date || button != Qt::LeftButton) return;
 
 	QString already = data->already(true);
 	if (!already.isEmpty()) {
@@ -424,7 +424,7 @@ void VideoOpenLink::onClick(Qt::MouseButton button) const {
 }
 
 void VideoSaveLink::doSave(VideoData *data, bool forceSavingAs) {
-	if (!data->user && !data->date) return;
+	if (!data->date) return;
 
 	QString already = data->already(true);
 	if (!already.isEmpty() && !forceSavingAs) {
@@ -456,13 +456,13 @@ void VideoSaveLink::onClick(Qt::MouseButton button) const {
 
 void VideoCancelLink::onClick(Qt::MouseButton button) const {
 	VideoData *data = video();
-	if ((!data->user && !data->date) || button != Qt::LeftButton) return;
+	if (!data->date || button != Qt::LeftButton) return;
 
 	data->cancel();
 }
 
-VideoData::VideoData(const VideoId &id, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) :
-id(id), access(access), user(user), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
+VideoData::VideoData(const VideoId &id, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) :
+id(id), access(access), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
 	location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id));
 }
 
@@ -482,7 +482,7 @@ QString VideoData::already(bool check) {
 
 void AudioOpenLink::onClick(Qt::MouseButton button) const {
 	AudioData *data = audio();
-	if ((!data->user && !data->date) || button != Qt::LeftButton) return;
+	if (!data->date || button != Qt::LeftButton) return;
 
 	QString already = data->already(true);
 	bool play = App::hoveredLinkItem() && audioPlayer();
@@ -516,7 +516,7 @@ void AudioOpenLink::onClick(Qt::MouseButton button) const {
 }
 
 void AudioSaveLink::doSave(AudioData *data, bool forceSavingAs) {
-	if (!data->user && !data->date) return;
+	if (!data->date) return;
 
 	QString already = data->already(true);
 	if (!already.isEmpty() && !forceSavingAs) {
@@ -549,7 +549,7 @@ void AudioSaveLink::onClick(Qt::MouseButton button) const {
 
 void AudioCancelLink::onClick(Qt::MouseButton button) const {
 	AudioData *data = audio();
-	if ((!data->user && !data->date) || button != Qt::LeftButton) return;
+	if (!data->date || button != Qt::LeftButton) return;
 
 	data->cancel();
 }
@@ -569,8 +569,8 @@ bool StickerData::setInstalled() const {
 	return false;
 }
 
-AudioData::AudioData(const AudioId &id, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) :
-id(id), access(access), user(user), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
+AudioData::AudioData(const AudioId &id, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) :
+id(id), access(access), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
 	location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
 }
 
diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h
index 6bcdd6c5c..bbc1b41b3 100644
--- a/Telegram/SourceFiles/structs.h
+++ b/Telegram/SourceFiles/structs.h
@@ -167,9 +167,15 @@ struct BotInfo {
 	QString startToken, startGroupToken;
 };
 
+enum UserBlockedStatus {
+	UserBlockUnknown = 0,
+	UserIsBlocked,
+	UserIsNotBlocked,
+};
+
 struct PhotoData;
 struct UserData : public PeerData {
-	UserData(const PeerId &id) : PeerData(id), access(0), lnk(new PeerLink(this)), onlineTill(0), contact(-1), photosCount(-1), botInfo(0) {
+	UserData(const PeerId &id) : PeerData(id), access(0), lnk(new PeerLink(this)), onlineTill(0), contact(-1), blocked(UserBlockUnknown), photosCount(-1), botInfo(0) {
 	}
 	void setPhoto(const MTPUserProfilePhoto &photo);
 	void setName(const QString &first, const QString &last, const QString &phoneName, const QString &username);
@@ -192,6 +198,7 @@ struct UserData : public PeerData {
 	TextLinkPtr lnk;
 	int32 onlineTill;
 	int32 contact; // -1 - not contact, cant add (self, empty, deleted, foreign), 0 - not contact, can add (request), 1 - contact
+	UserBlockedStatus blocked;
 
 	typedef QList<PhotoData*> Photos;
 	Photos photos;
@@ -230,8 +237,8 @@ inline int32 newMessageFlags(PeerData *p) {
 
 typedef QMap<char, QPixmap> PreparedPhotoThumbs;
 struct PhotoData {
-	PhotoData(const PhotoId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()) :
-		id(id), access(access), user(user), date(date), thumb(thumb), medium(medium), full(full), chat(0) {
+	PhotoData(const PhotoId &id, const uint64 &access = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()) :
+		id(id), access(access), date(date), thumb(thumb), medium(medium), full(full), chat(0) {
 	}
 	void forget() {
 		thumb->forget();
@@ -254,7 +261,6 @@ struct PhotoData {
 	}
 	PhotoId id;
 	uint64 access;
-	int32 user;
 	int32 date;
 	ImagePtr thumb, replyPreview;
 	ImagePtr medium;
@@ -294,7 +300,7 @@ enum FileStatus {
 };
 
 struct VideoData {
-	VideoData(const VideoId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
+	VideoData(const VideoId &id, const uint64 &access = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
 
 	void forget() {
 		thumb->forget();
@@ -330,7 +336,6 @@ struct VideoData {
 
 	VideoId id;
 	uint64 access;
-	int32 user;
 	int32 date;
 	int32 duration;
 	int32 w, h;
@@ -390,7 +395,7 @@ public:
 };
 
 struct AudioData {
-	AudioData(const AudioId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
+	AudioData(const AudioId &id, const uint64 &access = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
 
 	void forget() {
 	}
@@ -425,7 +430,6 @@ struct AudioData {
 
 	AudioId id;
 	uint64 access;
-	int32 user;
 	int32 date;
 	QString mime;
 	int32 duration;
diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist
index e397d0312..0e5abe0cb 100644
--- a/Telegram/Telegram.plist
+++ b/Telegram/Telegram.plist
@@ -11,7 +11,7 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.8.48</string>
+	<string>0.8.49</string>
         <key>LSMinimumSystemVersion</key>
         <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
 	<key>CFBundleSignature</key>
diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc
index 6be096038..251f2edd5 100644
Binary files a/Telegram/Telegram.rc and b/Telegram/Telegram.rc differ
diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj
index b749011c5..7f02c5851 100644
--- a/Telegram/Telegram.vcxproj
+++ b/Telegram/Telegram.vcxproj
@@ -59,12 +59,12 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
     <IntDir>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\</IntDir>
-    <IncludePath>$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
+    <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">
     <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
     <IntDir>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\</IntDir>
-    <IncludePath>$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
+    <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
@@ -111,7 +111,7 @@
       <SubSystem>Windows</SubSystem>
       <OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
       <AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <ImageHasSafeExceptionHandlers />
       <ImportLibrary>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib</ImportLibrary>
       <ProfileGuidedDatabase>$(IntDir)$(TargetName).pgd</ProfileGuidedDatabase>
@@ -139,7 +139,7 @@
       <SubSystem>Windows</SubSystem>
       <OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
       <AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <ImageHasSafeExceptionHandlers>
       </ImageHasSafeExceptionHandlers>
       <ImportLibrary>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib</ImportLibrary>
diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj
index acf18ab7f..681fafc96 100644
--- a/Telegram/Telegram.xcodeproj/project.pbxproj
+++ b/Telegram/Telegram.xcodeproj/project.pbxproj
@@ -1707,7 +1707,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.8.48;
+				CURRENT_PROJECT_VERSION = 0.8.49;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
 				GCC_OPTIMIZATION_LEVEL = 0;
@@ -1725,7 +1725,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				COPY_PHASE_STRIP = YES;
-				CURRENT_PROJECT_VERSION = 0.8.48;
+				CURRENT_PROJECT_VERSION = 0.8.49;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_OPTIMIZATION_LEVEL = fast;
 				GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
@@ -1751,10 +1751,10 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CODE_SIGN_IDENTITY = "";
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.8.48;
+				CURRENT_PROJECT_VERSION = 0.8.49;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DYLIB_COMPATIBILITY_VERSION = 0.8;
-				DYLIB_CURRENT_VERSION = 0.8.48;
+				DYLIB_CURRENT_VERSION = 0.8.49;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				FRAMEWORK_SEARCH_PATHS = "";
 				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
@@ -1885,10 +1885,10 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CODE_SIGN_IDENTITY = "";
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.8.48;
+				CURRENT_PROJECT_VERSION = 0.8.49;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DYLIB_COMPATIBILITY_VERSION = 0.8;
-				DYLIB_CURRENT_VERSION = 0.8.48;
+				DYLIB_CURRENT_VERSION = 0.8.49;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				FRAMEWORK_SEARCH_PATHS = "";
 				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
diff --git a/Telegram/Version.sh b/Telegram/Version.sh
index 89b3f7622..deafb9a75 100755
--- a/Telegram/Version.sh
+++ b/Telegram/Version.sh
@@ -1,2 +1,2 @@
-echo 0.8 8048 0.8.48 0
+echo 0.8 8049 0.8.49 1
 # AppVersionStrMajor AppVersion AppVersionStr DevChannel