You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RnQ/RnQ/ICQ/Stickers.pas

264 lines
7.1 KiB
Plaintext

unit Stickers;
{$I forRnQConfig.inc}
interface
uses
Windows, Classes, SysUtils, Generics.Collections, JSON;
{$I PubRTTI.inc}
type
PStickerPack = ^TStickerPack;
TStickerPack = record
Id: Integer;
StoreId: String;
Name: String;
Desc: String;
ListIconLink: String;
Content: TArray;
ContentType: String;
Purchased: Boolean;
UserSticker: Boolean;
IsEnabled: Boolean;
Priority: Integer;
Count: Integer;
class function FromJSON(const JSON: TJSONObject): TStickerPack; static;
end;
TStickerPacks = TArray;
{$I NoRTTI.inc}
function GetSticker(const FileID: String; pifs: TMemoryStream = nil; const ForceSize: String = ''): TBytes;
function GetAnimatedSticker(const FileID: String; pifs: TMemoryStream = nil; IsPicker: Boolean = False): TBytes;
function GetStickerPackContent(const Id: String): TArray;
// function CheckStickerCache(Ext, Sticker: Integer; const ForceSize: String = ''): Boolean;
// function GetCachedStickers: String;
function GetCachedPickers: String;
procedure RemoveStickerPackCache(const PackId: String);
var
DupStickerPacks: TList;
implementation
uses
Base64, RDGlobal, RnQGlobal, RDUtils, RnQNet, SQLiteDB, globalLib, utilLib, ICQConsts;
function GetSticker(const FileID: String; pifs: TMemoryStream = nil; const ForceSize: String = ''): TBytes;
var
URL, Size: String;
fn: String;
fs: TMemoryStream;
begin
if pifs = nil then
fs := TMemoryStream.Create
else
fs := pifs;
if not (ForceSize = '') then
Size := ForceSize
else
Size := 'sticker_small';
URL := BIN_PREVIEW_HOST + Size + '/' + FileID;
fn := StickerPath + FileID + '_' + Size + '.webp';
if not FileExists(fn) then
begin
if not DirectoryExists(StickerPath) then
ForceDirectories(StickerPath);
LoadFromURLAsFile(URL, fn);
end;
if FileExists(fn) then
fs.LoadFromFile(fn);
fs.Seek(0, 0);
SetLength(Result, fs.size);
fs.ReadBuffer(Result, fs.size);
if pifs = nil then
fs.Free
else
fs.Seek(0, 0);
end;
function GetAnimatedSticker(const FileID: String; pifs: TMemoryStream = nil; IsPicker: Boolean = False): TBytes;
var
URL, Size: String;
fn: String;
fs: TMemoryStream;
begin
if pifs = nil then
fs := TMemoryStream.Create
else
fs := pifs;
if IsPicker then
begin
URL := LOTTIE_PREVIEW_HOST + 'stickerpicker_small/' + FileID;
fn := StickerPath + FileID + '_stickerpicker_small.webp'; // It's actually PNG
end
else
begin
URL := LOTTIE_ORIGINAL_HOST + FileID;
fn := StickerPath + FileID + '_original.json';
end;
if not FileExists(fn) then
begin
if not DirectoryExists(StickerPath) then
ForceDirectories(StickerPath);
LoadFromURLAsFile(URL, fn);
end;
if FileExists(fn) then
fs.LoadFromFile(fn);
fs.Seek(0, 0);
SetLength(Result, fs.size);
fs.ReadBuffer(Result, fs.size);
if pifs = nil then
fs.Free
else
fs.Seek(0, 0);
end;
function GetStickerPackContent(const Id: String): TArray;
begin
Result := SQLDB.GetStickerPackContent(Id);
if Length(Result) = 0 then
begin
Result := Account.AccProto.GetStoreStickerPackContent(Id);
if Length(Result) > 0 then
SQLDB.SaveStickerPackContent(Id, Result);
end;
end;
procedure RemoveStickerPackCache(const PackId: String);
var
sr: TSearchRec;
begin
if FindFirst(StickerPath + PackId + '_*_*.webp', faAnyFile, sr) = 0 then
repeat
if not (sr.name = '.') and not (sr.name = '..') then
DeleteFile(StickerPath + sr.name);
until FindNext(sr) <> 0;
FindClose(sr);
end;
{
function CheckStickerCache(Ext, Sticker: Integer; const ForceSize: String = ''): Boolean;
var
Size: String;
fn: String;
begin
if not (ForceSize = '') then
Size := ForceSize
else
case StickerResolution of
0:
Size := 'small';
1:
Size := 'medium';
2:
Size := 'large';
end;
fn := StickerPath + IntToStr(Ext) + '_' + IntToStr(Sticker) + '_' + Size + '.png';
Result := FileExists(fn);
end;
function GetCachedStickers: String;
var
i, j: Integer;
begin
Result := '';
for i := 0 to Length(StickerCats) - 1 do
for j := 1 to StickerCatCounts[i] do
if CheckStickerCache(StickerCats[i], j, 'small') then
Result := Result + 'sticker:n' + IntToStr(StickerCats[i]) + '_' + IntToStr(j) + #10;
Result := Trim(Result);
end;
}
function CheckPickerCache(FileID: String): Boolean;
begin
Result := FileExists(StickerPath + FileID + '_stickerpicker_small.webp');
end;
function GetCachedPickers: String;
var
I: Integer;
Packs: TStickerPacks;
begin
Result := '';
Packs := SQLDB.GetStickerPacks(True);
for I := 0 to Length(Packs) - 1 do
if (Length(Packs[i].Content) > 0) and CheckPickerCache(Packs[i].Content[0]) then
Result := Result + IfThen(Packs[i].ContentType = 'animated', 'picker:a', 'picker:n') + Packs[i].Content[0] + #10;
Result := Trim(Result);
end;
class function TStickerPack.FromJSON(const JSON: TJSONObject): TStickerPack;
var
FileIDs, FileID: TJSONValue;
PickerIcon: String;
begin
Result := Default(TStickerPack);
with JSON do
begin
GetValueSafe('id', Result.Id);
GetValueSafe('store_id', Result.StoreId);
GetValueSafe('name', Result.Name);
GetValueSafe('description', Result.Desc);
GetValueSafe('count', Result.Count);
GetValueSafe('purchased', Result.Purchased);
if not GetValueSafe('usersticker', Result.UserSticker) then
GetValueSafe('user_sticker', Result.UserSticker);
GetValueSafe('priority', Result.Priority);
GetValueSafe('is_enabled', Result.IsEnabled);
try
if (GetValue('list_icons') is TJSONString) then
GetValueSafe('list_icons', Result.ListIconLink)
else if (GetValue('list_icons') is TJSONObject) then
GetValue('list_icons').GetValueSafe('small', Result.ListIconLink);
if (Result.ListIconLink = '') then
if GetValue('icons') is TJSONString then
GetValueSafe('icons', Result.ListIconLink)
else if GetValue('icons') is TJSONObject then
GetValue('icons').GetValueSafe('small', Result.ListIconLink);
except end;
if not GetValueSafe('type', Result.ContentType) then
begin
PickerIcon := '';
if not GetValueSafe('sticker_picker_icon', PickerIcon) then
GetValueSafe('contentlist_sticker_picker_icon', PickerIcon);
Result.ContentType := IfThen(PickerIcon.Contains('api/v1/files/sticker'), 'animated', 'image');
end;
SetLength(Result.Content, 0);
FileIDs := JSON.GetValue('content');
if (FileIDs is TJSONArray) then
for FileID in TJSONArray(FileIDs) do
if FileID is TJSONString then
begin
SetLength(Result.Content, Length(Result.Content) + 1);
Result.Content[High(Result.Content)] := FileID.Value;
end;
end;
end;
initialization
DupStickerPacks := TList.Create;
DupStickerPacks.AddRange([116288, 194855, 234247 {Cute Pigs - Incomplete set}]);
finalization
DupStickerPacks.Free;
end.