From 343cbf0e035a9c2a3735cd1c972fabc89851be65 Mon Sep 17 00:00:00 2001 From: "Oleg Koval (revenkroz)" Date: Thu, 18 Jul 2024 15:34:10 +0300 Subject: [PATCH] Update code to support Bot API 7.7 --- .gitignore | 2 + README.md | 4 +- index.html | 503 ++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 445 insertions(+), 64 deletions(-) diff --git a/.gitignore b/.gitignore index 485dee64..a2f94306 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .idea +.vscode +frp diff --git a/README.md b/README.md index 2d64b010..5f5dfe42 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # Telegram Web Apps for Bots Example -Example HTML-file that contains a basic interaction with Telegram Web Apps API. Based on [Attach Bot](https://t.me/asmico_attach_bot). +Example HTML-file that contains a plain-JS interaction with Telegram Web Apps API. +Live demo: [Attach Bot](https://t.me/asmico_attach_bot). ## Links * Official docs: https://core.telegram.org/bots/webapps * Live Demo Bot: [Attach Bot](https://t.me/asmico_attach_bot) * Telegram Promo Bot: [Durger King](https://t.me/durgerkingbot) -* My Telegram WebApp to track movies and TV shows: [EPSCAPE Bot](https://t.me/EpscapeBot) ## Quick setup diff --git a/index.html b/index.html index 09731306..757c3dd8 100644 --- a/index.html +++ b/index.html @@ -2,15 +2,13 @@ - - - - - - - - + + + + + + + + @@ -340,34 +368,43 @@ + + - + +
-
Header:
-
Background:
+
Header: + +
+
Background: + +
+
- + +

Test links:

-

Test permissions:

+ +

Test permissions:

+ +

Test alerts:

+

Haptics:

+ +

Cloud storage:

+
+ + + + + + + + + + + + + + + + +
KeyValue
+ + +
+
+ +

Biometrics:

+
+ +
+
Data passed to webview. @@ -421,6 +515,7 @@ platform:
+
@@ -435,15 +530,23 @@ const DemoApp = { initData : Telegram.WebApp.initData || '', initDataUnsafe: Telegram.WebApp.initDataUnsafe || {}, - MainButton : Telegram.WebApp.MainButton, + MainButton: Telegram.WebApp.MainButton, + BackButton: Telegram.WebApp.BackButton, + SettingsButton: Telegram.WebApp.SettingsButton, init(options) { - document.body.style.visibility = ''; - Telegram.WebApp.ready(); + document.body.style.visibility = '' + Telegram.WebApp.ready() Telegram.WebApp.MainButton.setParams({ text : 'CLOSE WEBVIEW', is_visible: true - }).onClick(DemoApp.close); + }).onClick(DemoApp.close) + Telegram.WebApp.BackButton.onClick(function() { + DemoApp.showAlert('Back button pressed') + }) + Telegram.WebApp.SettingsButton.onClick(function() { + DemoApp.showAlert('Settings opened!') + }) }, expand() { Telegram.WebApp.expand(); @@ -461,6 +564,46 @@ el.innerHTML = 'Hide Main Button'; } }, + toggleBackButton(el) { + if (DemoApp.BackButton.isVisible) { + DemoApp.BackButton.hide(); + el.innerHTML = 'Show Back Button'; + } else { + DemoApp.BackButton.show(); + el.innerHTML = 'Hide Back Button'; + } + }, + toggleSettingsButton(el) { + if (DemoApp.SettingsButton.isVisible) { + DemoApp.SettingsButton.hide(); + el.innerHTML = 'Show Settings Button'; + } else { + DemoApp.SettingsButton.show(); + el.innerHTML = 'Hide Settings Button'; + } + }, + toggleSwipeBehavior(el) { + if (Telegram.WebApp.isVerticalSwipesEnabled) { + Telegram.WebApp.disableVerticalSwipes(); + el.innerHTML = 'Enable Vertical Swypes'; + } else { + Telegram.WebApp.enableVerticalSwipes(); + el.innerHTML = 'Disable Vertical Swypes'; + } + }, + + // version to string Example: '6.9' + doesntSupport(version) { + // console.log("version: " + version); + // console.log("realVersion: " + this.version()); + // console.log("doesntSupport: " + this.isVersionAtLeast(version)); + if (!this.isVersionAtLeast(version)) { + Telegram.WebApp.showAlert('This feature is not supported in this version of Telegram', function () { + Telegram.WebApp.close(); + }); + throw new Error('This feature is not supported in this version of Telegram'); + } + }, // actions sendMessage(msg_id, with_webview) { @@ -581,6 +724,26 @@ Telegram.WebApp.sendData(new Date().toString()); } }, + switchInlineQuery(query, chooseChat) { + if (chooseChat) { + const chatTypes = [] + const types = ['users', 'bots', 'groups', 'channels']; + for (let i = 0; i < types.length; i++) { + const el = document.getElementById('select-' + types[i]); + if (el.checked) { + chatTypes.push(types[i]); + } + } + + if (!chooseChatTypes.length) { + return DemoApp.showAlert('Select chat types!'); + } + + Telegram.WebApp.switchInlineQuery(query, chatTypes) + } + + Telegram.WebApp.switchInlineQuery(query, false) + }, // Alerts showAlert(message) { @@ -589,15 +752,6 @@ showConfirm(message) { Telegram.WebApp.showConfirm(message); }, - requestWriteAccess() { - Telegram.WebApp.requestWriteAccess(function (result) { - if (result) { - DemoApp.showAlert('Write access granted'); - } else { - DemoApp.showAlert('Write access denied'); - } - }); - }, requestContact() { Telegram.WebApp.requestContact(function (result) { if (result) { @@ -610,18 +764,6 @@ isVersionAtLeast(version) { return Telegram.WebApp.isVersionAtLeast(version); }, - //version to string Example: '6.9' - doesntSupport(version) { - // console.log("version: " + version); - // console.log("realVersion: " + this.version()); - // console.log("doesntSupport: " + this.isVersionAtLeast(version)); - if (!this.isVersionAtLeast(version)) { - Telegram.WebApp.showAlert('This feature is not supported in this version of Telegram', function () { - Telegram.WebApp.close(); - }); - throw new Error('This feature is not supported in this version of Telegram'); - } - }, showPopup() { Telegram.WebApp.showPopup({ title : 'Popup title', @@ -722,6 +864,227 @@ }); return false; }, + requestWriteAccess(el) { + Telegram.WebApp.requestWriteAccess(function(allowed) { + if (allowed) { + el.nextElementSibling.innerHTML = '(Access granted)' + el.nextElementSibling.className = 'ok' + } else { + el.nextElementSibling.innerHTML = '(User declined this request)' + el.nextElementSibling.className = 'err' + } + }) + }, + requestPhoneNumber(el) { + Telegram.WebApp.requestContact(function(sent, event) { + if (sent) { + el.nextElementSibling.innerHTML = '(Phone number sent to the bot' + (event && event.responseUnsafe && event.responseUnsafe.contact && event.responseUnsafe.contact.phone_number ? ': +' + event.responseUnsafe.contact.phone_number : '') + ')' + el.nextElementSibling.className = 'ok' + } else { + el.nextElementSibling.innerHTML = '(User declined this request)' + el.nextElementSibling.className = 'err' + } + }) + }, + requestServerTime(el) { + Telegram.WebApp.invokeCustomMethod('getCurrentTime', {}, function(err, time) { + if (err) { + el.nextElementSibling.innerHTML = '(' + err + ')' + el.nextElementSibling.className = 'err' + } else { + el.nextElementSibling.innerHTML = '(' + (new Date(time * 1000)).toString() + ')' + el.nextElementSibling.className = 'ok' + } + }); + }, + + // cloud storage + cloudStorageKeys: {}, + cloudStorageItems: {}, + editCloudRow(el, event) { + event.preventDefault(); + const values = DemoApp.cloudStorageItems + const key = el.closest('tr').getAttribute('data-key') + el.form.reset(); + el.form.key.value = key; + el.form.value.value = values[key]; + }, + deleteCloudRow(el, event) { + event.preventDefault(); + const key = el.closest('tr').getAttribute('data-key') + Telegram.WebApp.CloudStorage.removeItem(key, function(err, deleted) { + if (err) { + DemoApp.showAlert('Error: ' + err); + } else { + if (deleted) { + const index = DemoApp.cloudStorageKeys.indexOf(key); + if (index >= 0) { + DemoApp.cloudStorageKeys.splice(index, 1); + } + delete DemoApp.cloudStorageItems[key]; + } + el.form.reset(); + DemoApp.updateCloudRows(); + } + }); + }, + saveCloudForm(form, event) { + event.preventDefault(); + const key = form.key.value + const value = form.value.value + Telegram.WebApp.CloudStorage.setItem(key, value, function(err, saved) { + if (err) { + DemoApp.showAlert('Error: ' + err); + } else { + if (saved) { + if (typeof DemoApp.cloudStorageItems[key] === 'undefined') { + DemoApp.cloudStorageKeys.push(key); + } + DemoApp.cloudStorageItems[key] = value; + } + form.reset(); + DemoApp.updateCloudRows(); + } + }); + }, + updateCloudRows() { + let html = ''; + const keys = DemoApp.cloudStorageKeys; + const values = DemoApp.cloudStorageItems; + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + html += ''+cleanHTML(key)+''+cleanHTML(values[key])+''; + } + + document.getElementById('cloud_rows').innerHTML = html + }, + loadCloudKeys(el) { + Telegram.WebApp.CloudStorage.getKeys(function(err, keys) { + if (err) { + DemoApp.showAlert('Error: ' + err); + } else { + if (keys.length > 0) { + Telegram.WebApp.CloudStorage.getItems(keys, function(err, values) { + if (err) { + DemoApp.showAlert('Error: ' + err); + } else { + DemoApp.cloudStorageKeys = keys; + DemoApp.cloudStorageItems = {}; + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + DemoApp.cloudStorageItems[key] = values[key]; + } + DemoApp.updateCloudRows(); + } + }); + } + } + }); + }, + + // biometrics + biometricInit(el) { + const biometricManager = Telegram.WebApp.BiometricManager; + if (!DemoApp.biometricInited) { + DemoApp.biometricInited = true; + Telegram.WebApp.onEvent('biometricManagerUpdated', function() { + document.getElementById('bm_inited').textContent = biometricManager.isInited ? 'true' : 'false' + document.getElementById('bm_available').textContent = biometricManager.isBiometricAvailable ? 'true' : 'false' + document.getElementById('bm_type').textContent = biometricManager.biometricType || '' + document.getElementById('bm_access_requested').textContent = biometricManager.isAccessRequested ? 'true' : 'false' + document.getElementById('bm_access_granted').textContent = biometricManager.isAccessGranted ? 'true' : 'false' + document.getElementById('bm_token_saved').textContent = biometricManager.isBiometricTokenSaved ? 'true' : 'false' + document.getElementById('bm_device_id').textContent = biometricManager.deviceId || '' + document.getElementById('bm_settings').style.display = biometricManager.isBiometricAvailable && biometricManager.isAccessRequested && !biometricManager.isAccessGranted ? 'block' : 'none' + }); + } + + biometricManager.init(); + }, + biometricRequestAccess(el) { + const biometricManager = Telegram.WebApp.BiometricManager; + if (!biometricManager.isInited) { + return DemoApp.showAlert('Biometric not inited yet!'); + } + + biometricManager.requestAccess({reason: 'The bot uses biometrics for testing purposes.'}, function(access_granted) { + if (access_granted) { + el.nextElementSibling.innerHTML = '(Access granted)'; + el.nextElementSibling.className = 'ok'; + } else { + el.nextElementSibling.innerHTML = '(Request declined)'; + el.nextElementSibling.className = 'err'; + } + }); + }, + biometricRequestAuth(el) { + const biometricManager = Telegram.WebApp.BiometricManager; + if (!biometricManager.isInited) { + return DemoApp.showAlert('Biometric not inited yet!'); + } + + el.nextElementSibling.innerHTML = ''; + el.nextElementSibling.classList.remove('ok', 'err') + + biometricManager.authenticate({reason: 'The bot requests biometrics for testing purposes.'}, function(success, token) { + if (success) { + el.nextElementSibling.innerHTML = '(Success, token: ' + token + ')'; + el.nextElementSibling.className = 'ok'; + } else { + el.nextElementSibling.innerHTML = '(Failed)'; + el.nextElementSibling.className = 'err'; + } + }); + }, + biometricOpenSettings(el) { + const biometricManager = Telegram.WebApp.BiometricManager; + if (!biometricManager.isInited) { + return DemoApp.showAlert('Biometric not inited yet!'); + } + + if (!biometricManager.isBiometricAvailable || + !biometricManager.isAccessRequested || + biometricManager.isAccessGranted) { + return false; + } + + biometricManager.openSettings(); + }, + biometricSetToken(el) { + const biometricManager = Telegram.WebApp.BiometricManager; + if (!biometricManager.isInited) { + return DemoApp.showAlert('Biometric not inited yet!'); + } + + const token = parseInt(Math.random().toString().substring(2)).toString(16); + biometricManager.updateBiometricToken(token, function(updated) { + if (updated) { + document.getElementById('bm_token_saved').textContent = biometricManager.isBiometricTokenSaved ? 'true' : 'false' + el.nextElementSibling.innerHTML = '(Updated: ' + token + ')' + el.nextElementSibling.className = 'ok' + } else { + el.nextElementSibling.innerHTML = '(Failed)' + el.nextElementSibling.className = 'err' + } + }); + }, + biometricRemoveToken(el) { + const biometricManager = Telegram.WebApp.BiometricManager; + if (!biometricManager.isInited) { + return DemoApp.showAlert('Biometric not inited yet!'); + } + + biometricManager.updateBiometricToken('', function(updated) { + if (updated) { + document.getElementById('bm_token_saved').textContent = biometricManager.isBiometricTokenSaved ? 'true' : 'false' + el.nextElementSibling.innerHTML = '(Removed)' + el.nextElementSibling.className = 'ok' + } else { + el.nextElementSibling.innerHTML = '(Failed)' + el.nextElementSibling.className = 'err' + } + }); + }, // Other apiRequest(method, data, onCallback) { @@ -782,7 +1145,16 @@ document.querySelector('.viewport-stable_border').setAttribute('text', window.innerWidth + ' x ' + round(Telegram.WebApp.viewportStableHeight, 2) + ' | is_expanded: ' + (Telegram.WebApp.isExpanded ? 'true' : 'false')); } - }; + } + + function cleanHTML(value) { + return value + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/\n/g, '
') + } function byteLength(str) { if (window.Blob) { @@ -874,9 +1246,6 @@ Telegram.WebApp.setHeaderColor('secondary_bg_color'); Telegram.WebApp.onEvent('viewportChanged', setViewportData); setViewportData(); - Telegram.WebApp.onEvent('settingsButtonClicked', function () { - alert('Settings opened!'); - }); let prevBgColorVal = document.getElementById('bg_color_sel').value; const bgColorInput = document.getElementById('bg_color_input'); @@ -918,7 +1287,17 @@ document.body.setAttribute('style', '--bg-color:' + Telegram.WebApp.backgroundColor); }); - DemoApp.testClipboard(document.getElementById('clipboard_test')); + try { + DemoApp.testClipboard(document.getElementById('clipboard_test')); + } catch(e) {} + + try { + DemoApp.loadCloudKeys(); + } catch(e) {} + + try { + DemoApp.biometricInit(); + } catch(e) {}