|
|
|
import AppStorage from '../storage';
|
|
|
|
//import apiManager from '../mtproto/apiManager';
|
|
|
|
import apiManager from '../mtproto/mtprotoworker';
|
|
|
|
import apiFileManager from '../mtproto/apiFileManager';
|
|
|
|
import appDocsManager from './appDocsManager';
|
|
|
|
import { MTDocument } from '../../types';
|
|
|
|
|
|
|
|
export type MTStickerSet = {
|
|
|
|
_: 'stickerSet',
|
|
|
|
flags: number,
|
|
|
|
archived?: true,
|
|
|
|
official?: true,
|
|
|
|
masks?: true,
|
|
|
|
animated?: true,
|
|
|
|
installed_date?: number,
|
|
|
|
id: string, // long
|
|
|
|
access_hash: string, // long,
|
|
|
|
title: string,
|
|
|
|
short_name: string, // Short name of stickerset to use in tg://addstickers?set=short_name
|
|
|
|
thumb?: {
|
|
|
|
_: 'photoSize',
|
|
|
|
type: 'm',
|
|
|
|
location: {
|
|
|
|
_: string,
|
|
|
|
volume_id: string,
|
|
|
|
local_id: number
|
|
|
|
},
|
|
|
|
w: number,
|
|
|
|
h: number,
|
|
|
|
size: number
|
|
|
|
},
|
|
|
|
pFlags: {
|
|
|
|
animated?: boolean
|
|
|
|
}
|
|
|
|
thumb_dc_id?: number,
|
|
|
|
count: number,
|
|
|
|
hash: number
|
|
|
|
};
|
|
|
|
|
|
|
|
export type MTStickerSetFull = {
|
|
|
|
set: MTStickerSet,
|
|
|
|
packs: any[],
|
|
|
|
documents: MTDocument[]
|
|
|
|
};
|
|
|
|
|
|
|
|
export type MTStickerSetCovered = {
|
|
|
|
_: 'stickerSetCovered',
|
|
|
|
set: MTStickerSet,
|
|
|
|
cover: MTDocument
|
|
|
|
};
|
|
|
|
|
|
|
|
export type MTStickerSetMultiCovered = {
|
|
|
|
_: 'stickerSetMultiCovered',
|
|
|
|
set: MTStickerSet,
|
|
|
|
covers: MTDocument[]
|
|
|
|
};
|
|
|
|
|
|
|
|
class AppStickersManager {
|
|
|
|
private documents: {
|
|
|
|
[fileID: string]: MTDocument
|
|
|
|
} = {};
|
|
|
|
|
|
|
|
private stickerSets: {
|
|
|
|
[stickerSetID: string]: MTStickerSetFull
|
|
|
|
} = {};
|
|
|
|
|
|
|
|
private saveSetsTimeout: number;
|
|
|
|
|
|
|
|
private hashes: Partial<{
|
|
|
|
featured: Partial<{hash: number, result: (MTStickerSetCovered | MTStickerSetMultiCovered)[]}>,
|
|
|
|
search: {
|
|
|
|
[query: string]: Partial<{
|
|
|
|
hash: number,
|
|
|
|
result: (MTStickerSetCovered | MTStickerSetMultiCovered)[]
|
|
|
|
}>
|
|
|
|
}
|
|
|
|
}> = {
|
|
|
|
featured: {},
|
|
|
|
search: {}
|
|
|
|
};
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
AppStorage.get<{
|
|
|
|
[stickerSetID: string]: MTStickerSetFull
|
|
|
|
}>('stickerSets').then((sets) => {
|
|
|
|
if(sets) {
|
|
|
|
for(let id in sets) {
|
|
|
|
let set = sets[id];
|
|
|
|
this.saveStickers(set.documents);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.stickerSets = sets;
|
|
|
|
}
|
|
|
|
|
|
|
|
//if(!this.stickerSets['emoji']) {
|
|
|
|
this.getStickerSet({id: 'emoji', access_hash: ''}, {overwrite: true});
|
|
|
|
//}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public saveSticker(doc: MTDocument) {
|
|
|
|
if(this.documents[doc.id]) return this.documents[doc.id];
|
|
|
|
|
|
|
|
doc = appDocsManager.saveDoc(doc);
|
|
|
|
this.documents[doc.id] = doc;
|
|
|
|
|
|
|
|
return doc;
|
|
|
|
}
|
|
|
|
|
|
|
|
public saveStickers(docs: MTDocument[]) {
|
|
|
|
docs.forEach((doc, idx) => {
|
|
|
|
docs[idx] = this.saveSticker(doc);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public getSticker(fileID: string) {
|
|
|
|
return this.documents[fileID];
|
|
|
|
}
|
|
|
|
|
|
|
|
public async getStickerSet(set: {
|
|
|
|
id: string,
|
|
|
|
access_hash: string
|
|
|
|
}, params: Partial<{
|
|
|
|
overwrite: boolean
|
|
|
|
}> = {}) {
|
|
|
|
if(this.stickerSets[set.id] && !params.overwrite && this.stickerSets[set.id].documents?.length) return this.stickerSets[set.id];
|
|
|
|
|
|
|
|
let promise = apiManager.invokeApi('messages.getStickerSet', {
|
|
|
|
stickerset: this.getStickerSetInput(set)
|
|
|
|
});
|
|
|
|
|
|
|
|
let res = await promise;
|
|
|
|
let stickerSet: {
|
|
|
|
_: "messages.stickerSet",
|
|
|
|
set: MTStickerSet,
|
|
|
|
packs: any[],
|
|
|
|
documents: MTDocument[]
|
|
|
|
} = res as any;
|
|
|
|
|
|
|
|
this.saveStickerSet(stickerSet, set.id);
|
|
|
|
|
|
|
|
return stickerSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
public async getRecentStickers() {
|
|
|
|
let res: {
|
|
|
|
_: string,
|
|
|
|
hash: number,
|
|
|
|
packs: any[],
|
|
|
|
stickers: MTDocument[],
|
|
|
|
dates: number[]
|
|
|
|
} = await apiManager.invokeApi('messages.getRecentStickers', {flags: 0, hash: 0});
|
|
|
|
|
|
|
|
this.saveStickers(res.stickers);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
public getAnimatedEmojiSticker(emoji: string) {
|
|
|
|
let stickerSet = this.stickerSets.emoji;
|
|
|
|
if(!stickerSet || !stickerSet.documents) return undefined;
|
|
|
|
|
|
|
|
emoji = emoji.replace(/\ufe0f/g, '').replace(/🏻|🏼|🏽|🏾|🏿/g, '');
|
|
|
|
return stickerSet.documents.find(doc => doc.stickerEmojiRaw == emoji);
|
|
|
|
}
|
|
|
|
|
|
|
|
public saveStickerSet(res: {
|
|
|
|
//_: "messages.stickerSet",
|
|
|
|
set: MTStickerSet,
|
|
|
|
packs: any[],
|
|
|
|
documents: MTDocument[]
|
|
|
|
}, id: string) {
|
|
|
|
//console.log('stickers save set', res);w
|
|
|
|
|
|
|
|
const newSet = {
|
|
|
|
set: res.set,
|
|
|
|
packs: res.packs,
|
|
|
|
documents: res.documents
|
|
|
|
};
|
|
|
|
|
|
|
|
if(this.stickerSets[id]) {
|
|
|
|
Object.assign(this.stickerSets[id], newSet);
|
|
|
|
} else {
|
|
|
|
this.stickerSets[id] = newSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.saveStickers(res.documents);
|
|
|
|
|
|
|
|
//console.log('stickers wrote', this.stickerSets);
|
|
|
|
if(this.saveSetsTimeout) return;
|
|
|
|
this.saveSetsTimeout = setTimeout(() => {
|
|
|
|
const savedSets: {[id: string]: MTStickerSetFull} = {};
|
|
|
|
for(const id in this.stickerSets) {
|
|
|
|
const set = this.stickerSets[id];
|
|
|
|
if(set.set.installed_date || id == 'emoji') {
|
|
|
|
savedSets[id] = set;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AppStorage.set({
|
|
|
|
stickerSets: savedSets
|
|
|
|
});
|
|
|
|
|
|
|
|
this.saveSetsTimeout = 0;
|
|
|
|
}, 100);
|
|
|
|
}
|
|
|
|
|
|
|
|
public getStickerSetThumb(stickerSet: MTStickerSet) {
|
|
|
|
const thumb = stickerSet.thumb;
|
|
|
|
const dcID = stickerSet.thumb_dc_id;
|
|
|
|
|
|
|
|
const isAnimated = stickerSet.pFlags?.animated;
|
|
|
|
|
|
|
|
const promise = apiFileManager.downloadFile(dcID, {
|
|
|
|
_: 'inputStickerSetThumb',
|
|
|
|
stickerset: this.getStickerSetInput(stickerSet),
|
|
|
|
volume_id: thumb.location.volume_id,
|
|
|
|
local_id: thumb.location.local_id
|
|
|
|
}, thumb.size, {
|
|
|
|
stickerType: isAnimated ? 2 : 1,
|
|
|
|
mimeType: isAnimated ? "application/x-tgsticker" : 'image/webp'
|
|
|
|
});
|
|
|
|
|
|
|
|
return promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
public getStickerSetInput(set: {id: string, access_hash: string}) {
|
|
|
|
return set.id == 'emoji' ? {
|
|
|
|
_: 'inputStickerSetAnimatedEmoji'
|
|
|
|
} : {
|
|
|
|
_: 'inputStickerSetID',
|
|
|
|
id: set.id,
|
|
|
|
access_hash: set.access_hash
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
public async getFeaturedStickers() {
|
|
|
|
const res = (await apiManager.invokeApi('messages.getFeaturedStickers', {
|
|
|
|
hash: this.hashes.featured?.hash || 0
|
|
|
|
})) as {
|
|
|
|
_: 'messages.featuredStickers',
|
|
|
|
unread: string[],
|
|
|
|
count: number,
|
|
|
|
hash: number,
|
|
|
|
sets: (MTStickerSetMultiCovered | MTStickerSetCovered)[]
|
|
|
|
} | {
|
|
|
|
_: 'messages.featuredStickersNotModified',
|
|
|
|
count: number
|
|
|
|
};
|
|
|
|
|
|
|
|
const hashed = this.hashes.featured ?? (this.hashes.featured = {});
|
|
|
|
if(res._ != 'messages.featuredStickersNotModified') {
|
|
|
|
hashed.hash = res.hash;
|
|
|
|
hashed.result = res.sets;
|
|
|
|
}
|
|
|
|
|
|
|
|
hashed.result.forEach(covered => {
|
|
|
|
this.saveStickerSet({set: covered.set, documents: [], packs: []}, covered.set.id);
|
|
|
|
});
|
|
|
|
|
|
|
|
return hashed.result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public async toggleStickerSet(set: MTStickerSet) {
|
|
|
|
if(set.installed_date) {
|
|
|
|
const res = await apiManager.invokeApi('messages.uninstallStickerSet', {
|
|
|
|
stickerset: this.getStickerSetInput(set)
|
|
|
|
});
|
|
|
|
|
|
|
|
if(res) {
|
|
|
|
delete set.installed_date;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const res = await apiManager.invokeApi('messages.installStickerSet', {
|
|
|
|
stickerset: this.getStickerSetInput(set),
|
|
|
|
archived: false
|
|
|
|
});
|
|
|
|
|
|
|
|
if(res) {
|
|
|
|
set.installed_date = Date.now() / 1000 | 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public async searchStickerSets(query: string, excludeFeatured = true) {
|
|
|
|
const flags = excludeFeatured ? 1 : 0;
|
|
|
|
const res = await apiManager.invokeApi('messages.searchStickerSets', {
|
|
|
|
flags,
|
|
|
|
exclude_featured: excludeFeatured,
|
|
|
|
q: query,
|
|
|
|
hash: this.hashes.search[query]?.hash || 0
|
|
|
|
}) as {
|
|
|
|
_: 'messages.foundStickerSets',
|
|
|
|
hash: number,
|
|
|
|
sets: Array<MTStickerSetCovered | MTStickerSetMultiCovered>
|
|
|
|
} | {
|
|
|
|
_: 'messages.foundStickerSetsNotModified'
|
|
|
|
};
|
|
|
|
|
|
|
|
const hashed = this.hashes.search[query] ?? (this.hashes.search[query] = {});
|
|
|
|
if(res._ != 'messages.foundStickerSetsNotModified') {
|
|
|
|
hashed.hash = res.hash;
|
|
|
|
hashed.result = res.sets;
|
|
|
|
}
|
|
|
|
|
|
|
|
hashed.result.forEach(covered => {
|
|
|
|
this.saveStickerSet({set: covered.set, documents: [], packs: []}, covered.set.id);
|
|
|
|
});
|
|
|
|
|
|
|
|
const foundSaved: MTStickerSetCovered[] = [];
|
|
|
|
for(let id in this.stickerSets) {
|
|
|
|
const {set} = this.stickerSets[id];
|
|
|
|
|
|
|
|
if(set.title.toLowerCase().includes(query.toLowerCase()) && !hashed.result.find(c => c.set.id == set.id)) {
|
|
|
|
foundSaved.push({_: 'stickerSetCovered', set, cover: null});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashed.result.concat(foundSaved);
|
|
|
|
}
|
|
|
|
|
|
|
|
public async cleanup() { // if logout
|
|
|
|
await AppStorage.remove('stickerSets');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const appStickersManager = new AppStickersManager();
|
|
|
|
// @ts-ignore
|
|
|
|
if(process.env.NODE_ENV != 'production') {
|
|
|
|
(window as any).appStickersManager = appStickersManager;
|
|
|
|
}
|
|
|
|
export default appStickersManager;
|