ttw_fmx_v10/Services/uCustomEmoties.pas

413 lines
10 KiB
Plaintext
Raw Permalink Blame History

unit uCustomEmoties;
interface
uses
System.Classes, System.Generics.Collections, System.JSON, uRecords, IdHTTP, IdSSLOpenSSL,
System.Net.HttpClient, System.SysUtils;
type
TOnLog = procedure(aModul: string; aMethod: string; aMessage: string; aLevel: integer) of object;
type
TBTTV = class(TObject)
private
list: TList<TBTTVr>;
FOnLog: TOnLog;
procedure AddEmotesGlobalJson(const JsonStr: string);
procedure AddEmotesUserJson(const JsonStr: string);
function GetHTTP(aMethod: string): string;
procedure toLog(alevel: integer; amethod: string; amessage: string);
public
constructor Create;
destructor Destroy; override;
procedure GetGlobal;
procedure GetCustom(uid: string);
function GenerateURL(emoteName: string): string;
property OnLog: TOnLog read FOnLog write FOnLog;
end;
type
T7TV = class(TObject)
private
list7: TList<T7TVr>;
FOnLog: TOnLog;
procedure AddEmotesGlobalJson(const JsonStr: string);
procedure AddEmotesUserJson(const JsonStr: string);
function GetHTTP(aMethod: string): string;
public
constructor Create;
destructor Destroy; override;
procedure GetGlobal;
procedure GetCustom(uid: string);
function GenerateURL(emoteName: string): string;
procedure toLog(alevel: integer; amethod: string; amessage: string);
property OnLog: TOnLog read FOnLog write FOnLog;
end;
implementation
{ TBTTV }
constructor TBTTV.Create;
begin
inherited;
list := TList<TBTTVr>.Create;
end;
destructor TBTTV.Destroy;
begin
FreeAndNil(list);
inherited;
end;
procedure TBTTV.AddEmotesGlobalJson(const JsonStr: string);
var
JSONValue: TJSONValue;
JSONArray: TJSONArray;
EmoteObj: TJSONObject;
NewEmote: TBTTVr;
i: Integer;
begin
JSONValue := TJSONObject.ParseJSONValue(JsonStr);
if not Assigned(JSONValue) then Exit;
try
if not (JSONValue is TJSONArray) then Exit;
JSONArray := TJSONArray(JSONValue);
for i := 0 to JSONArray.Count - 1 do
begin
if not (JSONArray.Items[i] is TJSONObject) then Continue;
EmoteObj := TJSONObject(JSONArray.Items[i]);
NewEmote := Default(TBTTVr);
if Assigned(EmoteObj.GetValue('id')) then
NewEmote.id := EmoteObj.GetValue('id').Value;
if Assigned(EmoteObj.GetValue('code')) then
NewEmote.code := EmoteObj.GetValue('code').Value;
if not NewEmote.id.IsEmpty and not NewEmote.code.IsEmpty then
list.Add(NewEmote);
end;
finally
JSONValue.Free;
end;
end;
procedure TBTTV.AddEmotesUserJson(const JsonStr: string);
var
JSONValue, ChannelEmotes: TJSONValue;
JSONArray: TJSONArray;
EmoteObj: TJSONObject;
NewEmote: TBTTVr;
i: Integer;
begin
JSONValue := TJSONObject.ParseJSONValue(JsonStr);
if not Assigned(JSONValue) then Exit;
try
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> channelEmotes
ChannelEmotes := TJSONObject(JSONValue).GetValue('channelEmotes');
if (ChannelEmotes is TJSONArray) then
begin
JSONArray := TJSONArray(ChannelEmotes);
for i := 0 to JSONArray.Count - 1 do
begin
if not (JSONArray.Items[i] is TJSONObject) then Continue;
EmoteObj := TJSONObject(JSONArray.Items[i]);
NewEmote := Default(TBTTVr);
if Assigned(EmoteObj.GetValue('id')) then
NewEmote.id := EmoteObj.GetValue('id').Value;
if Assigned(EmoteObj.GetValue('code')) then
NewEmote.code := EmoteObj.GetValue('code').Value;
if not NewEmote.id.IsEmpty and not NewEmote.code.IsEmpty then
list.Add(NewEmote);
end;
end;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> sharedEmotes
ChannelEmotes := TJSONObject(JSONValue).GetValue('sharedEmotes');
if (ChannelEmotes is TJSONArray) then
begin
JSONArray := TJSONArray(ChannelEmotes);
for i := 0 to JSONArray.Count - 1 do
begin
if not (JSONArray.Items[i] is TJSONObject) then Continue;
EmoteObj := TJSONObject(JSONArray.Items[i]);
NewEmote := Default(TBTTVr);
if Assigned(EmoteObj.GetValue('id')) then
NewEmote.id := EmoteObj.GetValue('id').Value;
if Assigned(EmoteObj.GetValue('code')) then
NewEmote.code := EmoteObj.GetValue('code').Value;
if not NewEmote.id.IsEmpty and not NewEmote.code.IsEmpty then
list.Add(NewEmote);
end;
end;
finally
JSONValue.Free;
end;
end;
function TBTTV.GenerateURL(emoteName: string): string;
var
emote: TBTTVr;
begin
Result := '';
for emote in list do
begin
if emote.code = emoteName then
begin
Result := 'https://cdn.betterttv.net/emote/' + emote.id + '/1x';
Exit;
end;
end;
end;
procedure TBTTV.GetCustom(uid: string);
begin
if not uid.IsEmpty then
AddEmotesUserJson(GetHTTP('users/twitch/' + uid));
end;
procedure TBTTV.GetGlobal;
begin
AddEmotesGlobalJson(GetHTTP('emotes/global'));
end;
function TBTTV.GetHTTP(aMethod: string): string;
var
http: TIdHTTP;
ssl: TIdSSLIOHandlerSocketOpenSSL;
begin
Result := '';
try
http := TIdHTTP.Create(nil);
ssl := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
http.IOHandler := ssl;
ssl.SSLOptions.SSLVersions := [sslvTLSv1_2];
http.Request.UserAgent :=
'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
Result := http.Get('https://api.betterttv.net/3/cached/' + aMethod);
finally
ssl.Free;
http.Free;
end;
except
on E: Exception do
begin
toLog(2,'GetCustom',e.Message);
Result := '';
end;
end;
end;
procedure TBTTV.toLog(alevel: integer; amethod, amessage: string);
begin
if Assigned(FOnLog) then
FOnLog('uCustomEmoties.TBTTV', amethod, amessage, alevel);
end;
{ T7TV }
constructor T7TV.Create;
begin
inherited;
list7 := TList<T7TVr>.Create;
end;
destructor T7TV.Destroy;
begin
FreeAndNil(list7);
inherited;
end;
procedure T7TV.AddEmotesGlobalJson(const JsonStr: string);
var
Root: TJSONObject;
EmotesArray: TJSONArray;
EmoteObj, DataObj, HostObj: TJSONObject;
FilesArray: TJSONArray;
i: Integer;
Emote: T7TVr;
BaseUrl: string;
begin
Root := TJSONObject.ParseJSONValue(JsonStr) as TJSONObject;
if not Assigned(Root) then Exit;
try
EmotesArray := Root.GetValue('emotes') as TJSONArray;
if not Assigned(EmotesArray) then Exit;
for i := 0 to EmotesArray.Count - 1 do
begin
if not (EmotesArray.Items[i] is TJSONObject) then Continue;
EmoteObj := EmotesArray.Items[i] as TJSONObject;
Emote := Default(T7TVr);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if Assigned(EmoteObj.GetValue('id')) then
Emote.id := EmoteObj.GetValue('id').Value;
if Assigned(EmoteObj.GetValue('name')) then
Emote.code := EmoteObj.GetValue('name').Value;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> URL
DataObj := EmoteObj.GetValue('data') as TJSONObject;
if Assigned(DataObj) then
begin
HostObj := DataObj.GetValue('host') as TJSONObject;
if Assigned(HostObj) then
begin
if Assigned(HostObj.GetValue('url')) then
begin
BaseUrl := 'https:' + HostObj.GetValue('url').Value;
FilesArray := HostObj.GetValue('files') as TJSONArray;
if Assigned(FilesArray) and (FilesArray.Count > 0) and
(FilesArray.Items[0] is TJSONObject) then
begin
Emote.url := BaseUrl + '/' +
(FilesArray.Items[0] as TJSONObject).GetValue('name').Value;
end;
end;
end;
end;
if not Emote.id.IsEmpty and not Emote.code.IsEmpty and not Emote.url.IsEmpty then
list7.Add(Emote);
end;
finally
Root.Free;
end;
end;
procedure T7TV.AddEmotesUserJson(const JsonStr: string);
var
Root, EmoteSet, EmoteObj, DataObj, HostObj: TJSONObject;
EmotesArr, FilesArr: TJSONArray;
i: Integer;
Emote: T7TVr;
BaseUrl: string;
begin
Root := TJSONObject.ParseJSONValue(JsonStr) as TJSONObject;
if not Assigned(Root) then Exit;
try
if not Root.TryGetValue<TJSONObject>('emote_set', EmoteSet) then Exit;
EmotesArr := EmoteSet.GetValue('emotes') as TJSONArray;
if not Assigned(EmotesArr) then Exit;
for i := 0 to EmotesArr.Count - 1 do
begin
if not (EmotesArr.Items[i] is TJSONObject) then Continue;
EmoteObj := EmotesArr.Items[i] as TJSONObject;
Emote := Default(T7TVr);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if Assigned(EmoteObj.GetValue('id')) then
Emote.id := EmoteObj.GetValue('id').Value;
if Assigned(EmoteObj.GetValue('name')) then
Emote.code := EmoteObj.GetValue('name').Value;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> URL
DataObj := EmoteObj.GetValue('data') as TJSONObject;
if Assigned(DataObj) then
begin
HostObj := DataObj.GetValue('host') as TJSONObject;
if Assigned(HostObj) then
begin
if Assigned(HostObj.GetValue('url')) then
begin
BaseUrl := 'https:' + HostObj.GetValue('url').Value;
FilesArr := HostObj.GetValue('files') as TJSONArray;
if Assigned(FilesArr) and (FilesArr.Count > 0) and
(FilesArr.Items[0] is TJSONObject) then
begin
Emote.url := BaseUrl + '/' +
(FilesArr.Items[0] as TJSONObject).GetValue('name').Value;
end;
end;
end;
end;
if not Emote.id.IsEmpty and not Emote.code.IsEmpty and not Emote.url.IsEmpty then
list7.Add(Emote);
end;
finally
Root.Free;
end;
end;
function T7TV.GenerateURL(emoteName: string): string;
var
emote: T7TVr;
begin
Result := '';
for emote in list7 do
begin
if emote.code = emoteName then
begin
Result := emote.url;
Exit;
end;
end;
end;
procedure T7TV.GetCustom(uid: string);
begin
if not uid.IsEmpty then
AddEmotesUserJson(GetHTTP('users/twitch/' + uid));
end;
procedure T7TV.GetGlobal;
begin
AddEmotesGlobalJson(GetHTTP('emote-sets/global'));
end;
function T7TV.GetHTTP(aMethod: string): string;
var
HttpClient: THTTPClient;
Response: IHTTPResponse;
begin
Result := '';
HttpClient := THTTPClient.Create;
try
try
HttpClient.UserAgent := 'Mozilla/5.0';
Response := HttpClient.Get('https://api.7tv.app/v3/' + aMethod);
Result := Response.ContentAsString;
except
on E: Exception do
begin
toLog(2,'GetHTTP',e.Message);
Result := '';
end;
end;
finally
HttpClient.Free;
end;
end;
procedure T7TV.toLog(alevel: integer; amethod, amessage: string);
begin
if Assigned(FOnLog) then
FOnLog('uCustomEmoties.T7TV', amethod, amessage, alevel);
end;
end.