const utils = require('../Utils') const types = require('../tl').constructors const Session = require('./Abstract') class MemorySession extends Session { constructor() { super() this._serverAddress = null this._dcId = 0 this._port = null this._takeoutId = null this._entities = new Set() this._updateStates = {} } setDC(dcId, serverAddress, port) { this._dcId = dcId | 0 this._serverAddress = serverAddress this._port = port } get dcId() { return this._dcId } get serverAddress() { return this._serverAddress } get port() { return this._port } get authKey() { return this._authKey } set authKey(value) { this._authKey = value } /* CONTEST get takeoutId() { return this._takeoutId } set takeoutId(value) { this._takeoutId = value } getUpdateState(entityId) { return this._updateStates[entityId] } setUpdateState(entityId, state) { return this._updateStates[entityId] = state } close() { } save() { } async load() { } delete() { } _entityValuesToRow(id, hash, username, phone, name) { // While this is a simple implementation it might be overrode by, // other classes so they don't need to implement the plural form // of the method. Don't remove. return [id, hash, username, phone, name] } _entityToRow(e) { if (!(e.classType === "constructor")) { return } let p let markedId try { p = utils.getInputPeer(e, false) markedId = utils.getPeerId(p) } catch (e) { // Note: `get_input_peer` already checks for non-zero `accessHash`. // See issues #354 and #392. It also checks that the entity // is not `min`, because its `accessHash` cannot be used // anywhere (since layer 102, there are two access hashes). return } let pHash if (p instanceof types.InputPeerUser || p instanceof types.InputPeerChannel) { pHash = p.accessHash } else if (p instanceof types.InputPeerChat) { pHash = 0 } else { return } let username = e.username if (username) { username = username.toLowerCase() } const phone = e.phone const name = utils.getDisplayName(e) return this._entityValuesToRow(markedId, pHash, username, phone, name) } _entitiesToRows(tlo) { let entities = [] if (tlo.classType === "constructor" && utils.isListLike(tlo)) { // This may be a list of users already for instance entities = tlo } else { if (tlo instanceof Object) { if ('user' in tlo) { entities.push(tlo.user) } if ('chats' in tlo && utils.isListLike(tlo.chats)) { entities.concat(tlo.chats) } if ('users' in tlo && utils.isListLike(tlo.users)) { entities.concat(tlo.users) } } } const rows = [] // Rows to add (id, hash, username, phone, name) for (const e of entities) { const row = this._entityToRow(e) if (row) { rows.push(row) } } return rows } processEntities(tlo) { const entitiesSet = this._entitiesToRows(tlo) for (const e of entitiesSet) { this._entities.add(e) } } getEntityRowsByPhone(phone) { for (const e of this._entities) { // id, hash, username, phone, name if (e[3] === phone) { return [e[0], e[1]] } } } getEntityRowsByUsername(username) { for (const e of this._entities) { // id, hash, username, phone, name if (e[2] === username) { return [e[0], e[1]] } } } getEntityRowsByName(name) { for (const e of this._entities) { // id, hash, username, phone, name if (e[4] === name) { return [e[0], e[1]] } } } getEntityRowsById(id, exact = true) { if (exact) { for (const e of this._entities) { // id, hash, username, phone, name if (e[0] === id) { return [e[0], e[1]] } } } else { const ids = [utils.getPeerId(new types.PeerUser({ userId: id })), utils.getPeerId(new types.PeerChat({ chatId: id })), utils.getPeerId(new types.PeerChannel({ channelId: id })), ] for (const e of this._entities) { // id, hash, username, phone, name if (ids.includes(e[0])) { return [e[0], e[1]] } } } } getInputEntity(key) { let exact if (key.SUBCLASS_OF_ID !== undefined) { if ([0xc91c90b6, 0xe669bf46, 0x40f202fd].includes(key.SUBCLASS_OF_ID)) { // hex(crc32(b'InputPeer', b'InputUser' and b'InputChannel')) // We already have an Input version, so nothing else required return key } // Try to early return if this key can be casted as input peer return utils.getInputPeer(key) } else { // Not a TLObject or can't be cast into InputPeer if (key.classType === 'constructor') { key = utils.getPeerId(key) exact = true } else { exact = !(typeof key == 'number') || key < 0 } } let result = null if (typeof key === 'string') { const phone = utils.parsePhone(key) if (phone) { result = this.getEntityRowsByPhone(phone) } else { const { username, isInvite } = utils.parseUsername(key) if (username && !isInvite) { result = this.getEntityRowsByUsername(username) } else { const tup = utils.resolveInviteLink(key)[1] if (tup) { result = this.getEntityRowsById(tup, false) } } } } else if (typeof key === 'number') { result = this.getEntityRowsById(key, exact) } if (!result && typeof key === 'string') { result = this.getEntityRowsByName(key) } if (result) { let entityId = result[0] // unpack resulting tuple const entityHash = result[1] const resolved = utils.resolveId(entityId) entityId = resolved[0] const kind = resolved[1] // removes the mark and returns type of entity if (kind === types.PeerUser) { return new types.InputPeerUser({ userId: entityId, accessHash: entityHash }) } else if (kind === types.PeerChat) { return new types.InputPeerChat({ chatId: entityId }) } else if (kind === types.PeerChannel) { return new types.InputPeerChannel({ channelId: entityId, accessHash: entityHash }) } } else { throw new Error('Could not find input entity with key ' + key) } }*/ } module.exports = MemorySession