Telegram Web K with changes to work inside I2P https://web.telegram.i2p/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

384 lines
12 KiB

/*
* https://github.com/morethanwords/tweb
* Copyright (C) 2019-2021 Eduard Kuzmenko
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*
* Originally from:
* https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE
*/
import type { MyDocument } from "./appDocsManager";
import type { MyPhoto } from "./appPhotosManager";
import type { MyTopPeer } from "./appUsersManager";
import { BotInlineResult, GeoPoint, InputGeoPoint, InputMedia, MessageEntity, MessagesBotResults, ReplyMarkup } from "../../layer";
import insertInDescendSortedArray from "../../helpers/array/insertInDescendSortedArray";
import { AppManager } from "./manager";
import getPhotoMediaInput from "./utils/photos/getPhotoMediaInput";
import getServerMessageId from "./utils/messageId/getServerMessageId";
import generateQId from "./utils/inlineBots/generateQId";
import getDocumentMediaInput from "./utils/docs/getDocumentMediaInput";
export class AppInlineBotsManager extends AppManager {
private inlineResults: {[queryAndResultIds: string]: BotInlineResult} = {};
private setHash: {
[botId: UserId]: {
peerId: PeerId,
time: number
}
} = {};
public getGeoInput(geo: GeoPoint): InputGeoPoint {
return geo._ === 'geoPoint' ? {
_: 'inputGeoPoint',
lat: geo.lat,
long: geo.long,
accuracy_radius: geo.accuracy_radius
} : {
_: 'inputGeoPointEmpty'
};
}
public getInlineResults(peerId: PeerId, botId: BotId, query = '', offset = '', geo?: GeoPoint) {
return this.apiManager.invokeApi('messages.getInlineBotResults', {
bot: this.appUsersManager.getUserInput(botId),
peer: this.appPeersManager.getInputPeerById(peerId),
query,
geo_point: geo ? this.getGeoInput(geo) : undefined,
offset
}, {/* timeout: 1, */stopTime: -1, noErrorBox: true}).then((botResults) => {
const queryId = botResults.query_id;
/* if(botResults.switch_pm) {
botResults.switch_pm.rText = wrapRichText(botResults.switch_pm.text, {noLinebreaks: true, noLinks: true});
} */
botResults.results.forEach((result) => {
if(result._ === 'botInlineMediaResult') {
if(result.document) {
result.document = this.appDocsManager.saveDoc(result.document);
}
if(result.photo) {
result.photo = this.appPhotosManager.savePhoto(result.photo);
}
}
this.inlineResults[generateQId(queryId, result.id)] = result;
});
return botResults;
});
}
private pushPopularBot(botId: BotId) {
this.appUsersManager.getTopPeers('bots_inline').then((topPeers) => {
const botPeerId = botId.toPeerId();
const index = topPeers.findIndex((topPeer) => topPeer.id === botPeerId);
let topPeer: MyTopPeer;
if(index !== -1) {
topPeer = topPeers[index];
} else {
topPeer = {
id: botPeerId,
rating: 0
};
}
++topPeer.rating;
insertInDescendSortedArray(topPeers, topPeer, 'rating');
this.appStateManager.setKeyValueToStorage('topPeersCache');
// rootScope.$broadcast('inline_bots_popular')
});
}
public switchToPM(fromPeerId: PeerId, botId: BotId, startParam: string) {
this.setHash[botId] = {peerId: fromPeerId, time: Date.now()};
return this.appMessagesManager.startBot(botId, undefined, startParam);
}
/*
function resolveInlineMention (username) {
return AppPeersManager.resolveUsername(username).then(function (peerId) {
if (peerId.isUser()) {
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 &&
GeoLocationManager.isAvailable()) {
return checkGeoLocationAccess(peerId).then(function () {
return GeoLocationManager.getPosition().then(function (coords) {
resolvedBot.geo = coords
return qSync.when(resolvedBot)
})
})['catch'](function () {
return qSync.when(resolvedBot)
})
}
return qSync.when(resolvedBot)
}
}
return $q.reject()
}, function (error) {
error.handled = true
return $q.reject(error)
})
}
function regroupWrappedResults (results, rowW, rowH) {
if (!results ||
!results[0] ||
['photo', 'gif', 'sticker'].indexOf(results[0].type) === -1) {
return
}
var ratios = []
angular.forEach(results, function (result) {
var w
var h, doc
var photo
if (result._ === 'botInlineMediaResult') {
if (doc = result.document) {
w = result.document.w
h = result.document.h
}
else if (photo = result.photo) {
var photoSize = (photo.sizes || [])[0]
w = photoSize && photoSize.w
h = photoSize && photoSize.h
}
}else {
w = result.w
h = result.h
}
if (!w || !h) {
w = h = 1
}
ratios.push(w / h)
})
var rows = []
var curCnt = 0
var curW = 0
angular.forEach(ratios, function (ratio) {
var w = ratio * rowH
curW += w
if (!curCnt || curCnt < 4 && curW < (rowW * 1.1)) {
curCnt++
} else {
rows.push(curCnt)
curCnt = 1
curW = w
}
})
if (curCnt) {
rows.push(curCnt)
}
var i = 0
var thumbs = []
var lastRowI = rows.length - 1
angular.forEach(rows, function (rowCnt, rowI) {
var lastRow = rowI === lastRowI
var curRatios = ratios.slice(i, i + rowCnt)
var sumRatios = 0
angular.forEach(curRatios, function (ratio) {
sumRatios += ratio
})
angular.forEach(curRatios, function (ratio, j) {
var thumbH = rowH
var thumbW = rowW * ratio / sumRatios
var realW = thumbH * ratio
if (lastRow && thumbW > realW) {
thumbW = realW
}
var result = results[i + j]
result.thumbW = Math.floor(thumbW) - 2
result.thumbH = Math.floor(thumbH) - 2
})
i += rowCnt
})
} */
public async checkSwitchReturn(botId: BotId) {
const bot = this.appUsersManager.getUser(botId);
if(!bot || !bot.pFlags.bot || !bot.bot_inline_placeholder) {
return;
}
const peerData = this.setHash[botId];
if(peerData) {
delete this.setHash[botId];
if((Date.now() - peerData.time) < 3600e3) {
return peerData.peerId;
}
}
}
public switchInlineQuery(peerId: PeerId, threadId: number, botId: BotId, query: string) {
this.appDraftsManager.setDraft(peerId, threadId, '@' + this.appUsersManager.getUser(botId).username + ' ' + query);
}
public callbackButtonClick(peerId: PeerId, mid: number, button: any) {
return this.apiManager.invokeApi('messages.getBotCallbackAnswer', {
peer: this.appPeersManager.getInputPeerById(peerId),
msg_id: getServerMessageId(mid),
data: button.data
}, {/* timeout: 1, */stopTime: -1, noErrorBox: true});
}
/* function gameButtonClick (id) {
var message = AppMessagesManager.getMessage(id)
var peerId = AppMessagesManager.getMessagePeer(message)
return MtpApiManager.invokeApi('messages.getBotCallbackAnswer', {
peer: AppPeersManager.getInputPeerByID(peerId),
msg_id: AppMessagesIDsManager.getMessageLocalID(id)
}, {timeout: 1, stopTime: -1, noErrorBox: true}).then(function (callbackAnswer) {
if (typeof callbackAnswer.message === 'string' &&
callbackAnswer.message.length) {
showCallbackMessage(callbackAnswer.message, callbackAnswer.pFlags.alert)
}
else if (typeof callbackAnswer.url === 'string') {
AppGamesManager.openGame(message.media.game.id, id, callbackAnswer.url)
}
})
} */
public sendInlineResult(peerId: PeerId, botId: BotId, queryAndResultIds: string, options: Partial<{
viaBotId: BotId,
queryId: string,
resultId: string,
replyMarkup: ReplyMarkup,
entities: MessageEntity[],
replyToMsgId: number,
clearDraft: true,
scheduleDate: number,
silent: true,
sendAsPeerId: PeerId,
geoPoint: GeoPoint
}> = {}) {
const inlineResult = this.inlineResults[queryAndResultIds];
if(!inlineResult) {
return;
}
this.pushPopularBot(botId);
const splitted = queryAndResultIds.split('_');
const queryID = splitted.shift();
const resultID = splitted.join('_');
options.viaBotId = botId;
options.queryId = queryID;
options.resultId = resultID;
if(inlineResult.send_message.reply_markup) {
options.replyMarkup = inlineResult.send_message.reply_markup;
}
if(inlineResult.send_message._ === 'botInlineMessageText') {
options.entities = inlineResult.send_message.entities;
this.appMessagesManager.sendText(peerId, inlineResult.send_message.message, options);
} else {
let caption = '';
let inputMedia: InputMedia;
const sendMessage = inlineResult.send_message;
switch(sendMessage._) {
case 'botInlineMessageMediaAuto': {
caption = sendMessage.message;
if(inlineResult._ === 'botInlineMediaResult') {
const {document, photo} = inlineResult;
if(document) {
inputMedia = getDocumentMediaInput(document as MyDocument);
} else {
inputMedia = getPhotoMediaInput(photo as MyPhoto);
}
}
break;
}
case 'botInlineMessageMediaGeo': {
inputMedia = {
_: 'inputMediaGeoPoint',
geo_point: this.getGeoInput(sendMessage.geo)
};
options.geoPoint = sendMessage.geo;
break;
}
case 'botInlineMessageMediaVenue': {
inputMedia = {
_: 'inputMediaVenue',
geo_point: this.getGeoInput(sendMessage.geo),
title: sendMessage.title,
address: sendMessage.address,
provider: sendMessage.provider,
venue_id: sendMessage.venue_id,
venue_type: sendMessage.venue_type
};
options.geoPoint = sendMessage.geo;
break;
}
case 'botInlineMessageMediaContact': {
inputMedia = {
_: 'inputMediaContact',
phone_number: sendMessage.phone_number,
first_name: sendMessage.first_name,
last_name: sendMessage.last_name,
vcard: sendMessage.vcard
};
break;
}
}
if(!inputMedia) {
inputMedia = {
_: 'messageMediaPending',
type: inlineResult.type,
file_name: inlineResult.title ||
(inlineResult as BotInlineResult.botInlineResult).content?.url ||
(inlineResult as BotInlineResult.botInlineResult).url,
size: 0,
progress: {percent: 30, total: 0}
} as any;
}
this.appMessagesManager.sendOther(peerId, inputMedia, options);
}
}
/* 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_INLINE'
}).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()
})
})
} */
}