From 172d977dcdf962385c4b9720647248aba5d781c0 Mon Sep 17 00:00:00 2001 From: Igor Zhukov Date: Mon, 18 Apr 2016 14:17:51 +0300 Subject: [PATCH] Bot access for geo & contact --- app/js/controllers.js | 63 ++++++++++++-- app/js/lib/ng_utils.js | 38 ++++++++- app/js/lib/tl_utils.js | 2 +- app/js/messages_manager.js | 42 +++++++++- app/js/services.js | 167 +++++++++++++++++++++++++++---------- 5 files changed, 253 insertions(+), 59 deletions(-) diff --git a/app/js/controllers.js b/app/js/controllers.js index 12d27efa..40e3f227 100644 --- a/app/js/controllers.js +++ b/app/js/controllers.js @@ -1804,9 +1804,48 @@ angular.module('myApp.controllers', ['myApp.i18n']) if (!replyKeyboard) { return; } - AppMessagesManager.sendText(peerID, button.text, { - replyToMsgID: peerID < 0 && replyKeyboard.mid - }); + switch (button._) { + case 'keyboardButtonRequestPhone': + ErrorService.confirm({type: 'BOT_ACCESS_PHONE'}).then(function () { + var user = AppUsersManager.getSelf(); + AppMessagesManager.sendOther(peerID, { + _: 'inputMediaContact', + phone_number: user.phone, + first_name: user.first_name, + last_name: user.last_name + }, { + replyToMsgID: peerID < 0 && replyKeyboard.mid + }); + }); + break; + + case 'keyboardButtonRequestGeoLocation': + ErrorService.confirm({type: 'BOT_ACCESS_GEO'}).then(function () { + return GeoLocationManager.getPosition().then(function (coords) { + AppMessagesManager.sendOther(peerID, { + _: 'inputMediaGeoPoint', + geo_point: { + _: 'inputGeoPoint', + 'lat': coords['lat'], + 'long': coords['long'] + } + }, { + replyToMsgID: peerID < 0 && replyKeyboard.mid + }); + }, function (error) { + ErrorService.alert( + _('error_modal_password_success_title_raw'), + _('error_modal_password_success_descripion_raw') + ); + }); + }); + break; + + default: + AppMessagesManager.sendText(peerID, button.text, { + replyToMsgID: peerID < 0 && replyKeyboard.mid + }); + } }); $scope.$on('history_reload', function (e, updPeerID) { @@ -2479,7 +2518,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) var inlineUsernameRegex = /^@([a-zA-Z\d_]{1,32})( | )([\s\S]*)$/; var getInlineResultsTO = false; - var lastInlineBotID = false; + var lastInlineBot = false; var jump = 0; function checkInlinePattern (message) { @@ -2499,12 +2538,18 @@ angular.module('myApp.controllers', ['myApp.i18n']) return; } var username = matches[1]; + var inlineBotPromise; $scope.draftMessage.inlineProgress = true; - AppPeersManager.resolveInlineMention(username).then(function (inlineBot) { + if (lastInlineBot && lastInlineBot.username == username) { + inlineBotPromise = $q.when(lastInlineBot); + } else { + inlineBotPromise = AppInlineBotsManager.resolveInlineMention(username); + } + inlineBotPromise.then(function (inlineBot) { if (curJump != jump) { return; } - lastInlineBotID = inlineBot.id; + lastInlineBot = inlineBot; $scope.$broadcast('inline_placeholder', { prefix: '@' + username + matches[2], placeholder: inlineBot.placeholder @@ -2514,7 +2559,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) } getInlineResultsTO = $timeout(function () { var query = RichTextProcessor.parseEmojis(matches[3]); - AppInlineBotsManager.getInlineResults($scope.curDialog.peerID, inlineBot.id, query, '').then(function (botResults) { + AppInlineBotsManager.getInlineResults($scope.curDialog.peerID, inlineBot.id, query, inlineBot.geo, '').then(function (botResults) { getInlineResultsTO = false; if (curJump != jump) { return; @@ -2527,7 +2572,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) delete $scope.draftMessage.inlineProgress; }); }, 500); - }, function () { + }, function (error) { $scope.$broadcast('inline_results', false); delete $scope.draftMessage.inlineProgress; }); @@ -2614,7 +2659,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) } if (qID.substr(0, 11) == '_switch_pm_') { - var botID = lastInlineBotID; + var botID = lastInlineBot.id; var startParam = qID.substr(11); return AppInlineBotsManager.switchToPM($scope.curDialog.peerID, botID, startParam); } diff --git a/app/js/lib/ng_utils.js b/app/js/lib/ng_utils.js index 228683be..165a757f 100644 --- a/app/js/lib/ng_utils.js +++ b/app/js/lib/ng_utils.js @@ -1084,6 +1084,42 @@ angular.module('izhukov.utils', []) } }) +.service('GeoLocationManager', function ($q) { + + var lastCoords = false; + + function isAvailable() { + return navigator.geolocation !== undefined; + } + + function getPosition(force) { + if (!force && lastCoords) { + return $q.when(lastCoords); + } + if (!isAvailable()) { + return $q.reject(); + } + var deferred = $q.defer(); + navigator.geolocation.getCurrentPosition(function (position) { + lastCoords = { + lat: position.coords.latitude, + long: position.coords.longitude + }; + deferred.resolve(lastCoords); + }, function (error) { + deferred.reject(error); + }); + + return deferred.promise; + } + + return { + getPosition: getPosition, + isAvailable: isAvailable + } + +}) + .service('AppRuntimeManager', function ($window) { return { @@ -1771,7 +1807,7 @@ angular.module('izhukov.utils', []) return url; } -}) +}); diff --git a/app/js/lib/tl_utils.js b/app/js/lib/tl_utils.js index 94baa52c..03ea952c 100644 --- a/app/js/lib/tl_utils.js +++ b/app/js/lib/tl_utils.js @@ -111,7 +111,7 @@ TLSerialization.prototype.storeLong = function (sLong, field) { this.writeInt(intToUint(divRem[0].intValue()), (field || '') + ':long[high]'); }; -TLSerialization.prototype.storeDouble = function (f) { +TLSerialization.prototype.storeDouble = function (f, field) { var buffer = new ArrayBuffer(8); var intView = new Int32Array(buffer); var doubleView = new Float64Array(buffer); diff --git a/app/js/messages_manager.js b/app/js/messages_manager.js index 5e190251..68f72c3a 100644 --- a/app/js/messages_manager.js +++ b/app/js/messages_manager.js @@ -1351,6 +1351,7 @@ angular.module('myApp.services') random_id: randomIDS, reply_to_msg_id: replyToMsgID, via_bot_id: options.viaBotID, + reply_markup: options.reply_markup, entities: entities, views: asChannel && 1, pending: true @@ -1658,10 +1659,6 @@ angular.module('myApp.services') var fromID = AppUsersManager.getSelf().id; var media; switch (inputMedia._) { - case 'inputMediaContact': - media = angular.extend({}, inputMedia, {_: 'messageMediaContact'}); - break; - case 'inputMediaPhoto': media = { _: 'messageMediaPhoto', @@ -1682,6 +1679,42 @@ angular.module('myApp.services') }; break; + case 'inputMediaContact': + media = { + _: 'messageMediaContact', + phone_number: phone_number, + first_name: first_name, + last_name: last_name, + user_id: 0 + }; + break; + + case 'inputMediaGeoPoint': + media = { + _: 'messageMediaGeo', + geo: { + _: 'geoPoint', + 'lat': inputMedia.geo_point['lat'], + 'long': inputMedia.geo_point['long'] + } + }; + break; + + case 'inputMediaVenue': + media = { + _: 'messageMediaVenue', + geo: { + _: 'geoPoint', + 'lat': inputMedia.geo_point['lat'], + 'long': inputMedia.geo_point['long'] + }, + title: inputMedia.title, + address: inputMedia.address, + provider: inputMedia.provider, + venue_id: inputMedia.venue_id + }; + break; + case 'messageMediaPending': media = inputMedia; break; @@ -1719,6 +1752,7 @@ angular.module('myApp.services') random_id: randomIDS, reply_to_msg_id: replyToMsgID, via_bot_id: options.viaBotID, + reply_markup: options.reply_markup, views: asChannel && 1, pending: true }; diff --git a/app/js/services.js b/app/js/services.js index 7ef90c7e..c2dade42 100755 --- a/app/js/services.js +++ b/app/js/services.js @@ -11,7 +11,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) -.service('AppUsersManager', function ($rootScope, $modal, $modalStack, $filter, $q, qSync, MtpApiManager, RichTextProcessor, ErrorService, Storage, _) { +.service('AppUsersManager', function ($rootScope, $modal, $modalStack, $filter, $q, qSync, MtpApiManager, RichTextProcessor, Storage, _) { var users = {}, usernames = {}, userAccess = {}, @@ -960,24 +960,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) }); } - function resolveInlineMention (username) { - return resolveUsername(username).then(function (peerID) { - if (peerID > 0) { - var bot = AppUsersManager.getUser(peerID); - if (bot.pFlags.bot && bot.bot_inline_placeholder !== undefined) { - return qSync.when({ - id: peerID, - placeholder: bot.bot_inline_placeholder - }); - } - } - return $q.reject(); - }, function (error) { - error.handled = true; - return $q.reject(error); - }); - } - function getPeerID (peerString) { if (angular.isObject(peerString)) { return peerString.user_id @@ -1024,7 +1006,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) getPeer: getPeer, getPeerPhoto: getPeerPhoto, resolveUsername: resolveUsername, - resolveInlineMention: resolveInlineMention, isChannel: isChannel, isMegagroup: isMegagroup, isBot: isBot @@ -2402,19 +2383,20 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) } }) -.service('AppInlineBotsManager', function ($rootScope, Storage, MtpApiManager, AppMessagesManager, AppDocsManager, AppPhotosManager, RichTextProcessor, AppUsersManager, AppPeersManager, PeersSelectService) { +.service('AppInlineBotsManager', function (qSync, $q, $rootScope, Storage, ErrorService, MtpApiManager, AppMessagesManager, AppDocsManager, AppPhotosManager, RichTextProcessor, AppUsersManager, AppPeersManager, PeersSelectService, GeoLocationManager) { var inlineResults = {}; return { + resolveInlineMention: resolveInlineMention, + getPopularBots: getPopularBots, sendInlineResult: sendInlineResult, + getInlineResults: getInlineResults, regroupWrappedResults: regroupWrappedResults, switchToPM: switchToPM, checkSwitchReturn: checkSwitchReturn, switchInlineButtonClick: switchInlineButtonClick, - callbackButtonClick: callbackButtonClick, - getInlineResults: getInlineResults, - getPopularBots: getPopularBots + callbackButtonClick: callbackButtonClick }; function getPopularBots () { @@ -2468,12 +2450,46 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) }); } - function getInlineResults (peerID, botID, query, offset) { + function resolveInlineMention (username) { + return AppPeersManager.resolveUsername(username).then(function (peerID) { + if (peerID > 0) { + var bot = AppUsersManager.getUser(peerID); + if (bot.pFlags.bot && bot.bot_inline_placeholder !== undefined) { + var resolvedBot = { + username: username, + id: peerID, + placeholder: bot.bot_inline_placeholder + }; + if (bot.pFlags.bot_inline_geo) { + return checkGeoLocationAccess(peerID).then(function () { + // console.log('bot has access'); + return GeoLocationManager.getPosition().then(function (coords) { + resolvedBot.geo = coords; + console.log('got position', resolvedBot); + return qSync.when(resolvedBot); + }); + })['catch'](function () { + console.log('resolve', resolvedBot); + return qSync.when(resolvedBot); + }) + } + return qSync.when(resolvedBot); + } + } + return $q.reject(); + }, function (error) { + error.handled = true; + return $q.reject(error); + }); + } + + function getInlineResults (peerID, botID, query, geo, offset) { return MtpApiManager.invokeApi('messages.getInlineBotResults', { - flags: 0, + flags: 0 | (geo ? 1 : 0), bot: AppUsersManager.getUserInput(botID), peer: AppPeersManager.getInputPeerByID(peerID), query: query, + geo_point: geo && {_: 'inputGeoPoint', lat: geo['lat'], long: geo['long']}, offset: offset }, {timeout: 1, stopTime: -1, noErrorBox: true}).then(function(botResults) { var queryID = botResults.query_id; @@ -2661,31 +2677,72 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) options.viaBotID = inlineResult.botID; options.queryID = queryID; options.resultID = resultID; + if (inlineResult.send_message.reply_markup) { + options.reply_markup = inlineResult.send_message.reply_markup; + } if (inlineResult.send_message._ == 'botInlineMessageText') { options.entities = inlineResult.send_message.entities; AppMessagesManager.sendText(peerID, inlineResult.send_message.message, options); } else { var caption = ''; - if (inlineResult.send_message._ == 'botInlineMessageMediaAuto') { - caption = inlineResult.send_message.caption; - } var inputMedia = false; - if (inlineResult._ == 'botInlineMediaResultDocument') { - var doc = inlineResult.document; - inputMedia = { - _: 'inputMediaDocument', - id: {_: 'inputDocument', id: doc.id, access_hash: doc.access_hash}, - caption: caption - }; - } - else if (inlineResult._ == 'botInlineMediaResultPhoto') { - var photo = inlineResult.photo; - inputMedia = { - _: 'inputMediaPhoto', - id: {_: 'inputPhoto', id: photo.id, access_hash: photo.access_hash}, - caption: caption - }; + switch (inlineResult.send_message._) { + case 'botInlineMessageMediaAuto': + caption = inlineResult.send_message.caption; + if (inlineResult._ == 'botInlineMediaResult') { + var doc = inlineResult.document; + var photo = inlineResult.photo; + if (doc) { + inputMedia = { + _: 'inputMediaDocument', + id: {_: 'inputDocument', id: doc.id, access_hash: doc.access_hash}, + caption: caption + }; + } else { + inputMedia = { + _: 'inputMediaPhoto', + id: {_: 'inputPhoto', id: photo.id, access_hash: photo.access_hash}, + caption: caption + }; + } + } + break; + + case 'botInlineMessageMediaGeo': + inputMedia = { + _: 'inputMediaGeoPoint', + geo_point: { + _: 'inputGeoPoint', + 'lat': inlineResult.send_message.geo['lat'], + 'long': inlineResult.send_message.geo['long'] + } + }; + break; + + case 'botInlineMessageMediaVenue': + inputMedia = { + _: 'inputMediaVenue', + geo_point: { + _: 'inputGeoPoint', + 'lat': inlineResult.send_message.geo['lat'], + 'long': inlineResult.send_message.geo['long'] + }, + title: title, + address: address, + provider: provider, + venue_id: venue_id + }; + break; + + case 'botInlineMessageMediaContact': + inputMedia = { + _: 'inputMediaContact', + phone_number: inlineResult.send_message.phone_number, + first_name: inlineResult.send_message.first_name, + last_name: inlineResult.send_message.last_name + }; + break; } if (!inputMedia) { inputMedia = { @@ -2700,6 +2757,28 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) } } + function checkGeoLocationAccess(botID) { + var key = 'bot_access_geo' + botID; + return Storage.get(key).then(function (geoAccess) { + if (geoAccess && geoAccess.granted) { + return true; + } + return ErrorService.confirm({ + type: 'BOT_ACCESS_GEO' + }).then(function () { + var setHash = {}; + setHash[key] = {granted: true, time: tsNow()}; + Storage.set(setHash); + return true; + }, function () { + var setHash = {}; + setHash[key] = {denied: true, time: tsNow()}; + Storage.set(setHash); + return $q.reject(); + }); + }); + } + }) .service('ApiUpdatesManager', function ($rootScope, MtpNetworkerFactory, AppUsersManager, AppChatsManager, AppPeersManager, MtpApiManager) {