реструктуризация файлов, добавление вебчатов
This commit is contained in:
@@ -0,0 +1,660 @@
|
||||
unit uTTWEventSub;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.SysUtils, System.JSON, System.Types, System.UITypes, System.Classes,
|
||||
WinInet, ComObj, IdException,
|
||||
ipwcore, ipwtypes, ipwwsclient, ipwping, idhttp, IdSSLOpenSSL, uRecords,
|
||||
fmx.Types, System.Net.HttpClient, System.Net.HttpClientComponent;
|
||||
|
||||
type
|
||||
TNotifyEvent = procedure(s: string) of object;
|
||||
TGetCustomRewardEvent = procedure(s: TCustomRewardEvent) of object;
|
||||
TGetFollowEvent = procedure(s: TFollowEvent) of object;
|
||||
TGetGiftEvent = procedure(s: TGiftEvent) of object;
|
||||
TGetSubEvent = procedure(s: TSubEvent) of object;
|
||||
TGetRaidEvent = procedure(s: TRaidEvent) of object;
|
||||
TOnLog = procedure(aModul: string; aMethod: string; aMessage: string; aLevel: integer) of object;
|
||||
|
||||
TOnStatus = procedure(Sender: TObject; const ConnectionEvent: String;
|
||||
StatusCode: Integer; const Description: String) of Object;
|
||||
|
||||
type
|
||||
TTTW_ES = class(TObject)
|
||||
FTimer: ttimer;
|
||||
wss: TipwWSClient;
|
||||
|
||||
private
|
||||
|
||||
BroadcasterID: string;
|
||||
FAccessToken: string;
|
||||
FClientID: string;
|
||||
FOnError: TNotifyEvent;
|
||||
FOnMessage: TNotifyEvent;
|
||||
FOnSubOk: TNotifyEvent;
|
||||
FOnRAW: TNotifyEvent;
|
||||
FOnGetCustomReward: TGetCustomRewardEvent;
|
||||
FOnFollow: TGetFollowEvent;
|
||||
FOnGift: TGetGiftEvent;
|
||||
FOnSub: TGetSubEvent;
|
||||
FOnLog: TOnLog;
|
||||
FOnRaid: TGetRaidEvent;
|
||||
FOnStatus: TOnStatus;
|
||||
SW: TWelcomMessage;
|
||||
procedure HandleTimer(Sender: TObject);
|
||||
procedure ipwWSClient1DataIn(Sender: TObject; DataFormat: Integer;
|
||||
const Text: string; const TextB: TBytes; EOM, EOL: Boolean);
|
||||
procedure ipwWSPing(Sender: TObject; const Payload: String;
|
||||
const PayloadB: TBytes; Response: Boolean);
|
||||
procedure ipwWSClient1ConnectionStatus(Sender: TObject;
|
||||
const ConnectionEvent: String; StatusCode: Integer;
|
||||
const Description: String);
|
||||
procedure ipwWSClientError(Sender: TObject; ErrorCode: Integer;
|
||||
const Description: string);
|
||||
procedure ipwWSClientDisconnected(Sender: TObject; StatusCode: Integer;
|
||||
const Description: String);
|
||||
procedure ipwWSClientHeader(Sender: TObject; const Field: String;
|
||||
const Value: String);
|
||||
procedure ipwWSClientLog(Sender: TObject; LogLevel: Integer;
|
||||
const aMessage, aLog: string);
|
||||
function subscribeTo(const EventType, Version: string; const Condition: string): Boolean;
|
||||
procedure subscribe();
|
||||
// function ParseRewardRedeemed(const AJsonString: string): TRewardRedeemed;
|
||||
procedure EventMSG(const AText: string);
|
||||
function ParseWelcomMessage(const JSONString: string): TWelcomMessage;
|
||||
function ParseCustomRewardEvent(const JSONString: string)
|
||||
: TCustomRewardEvent;
|
||||
function ParseFollowEvent(const JSONString: string): TFollowEvent;
|
||||
function ParseSubEvent(const JSONString: string): TSubEvent;
|
||||
function ParseGiftEvent(const JSONString: string): TGiftEvent;
|
||||
function ParseRaidEvent(const JSONString: string): TRaidEvent;
|
||||
procedure toLog(aLevel: integer; aMethod: string; aMessage: string);
|
||||
function ParseMetadata(const JSONString: string): TMetadata;
|
||||
public
|
||||
|
||||
constructor Create(Sender: TObject;
|
||||
aTokenWS, aClientID, aBroadcasterID: string);
|
||||
destructor Destroy; override;
|
||||
procedure Connect();
|
||||
procedure Disconnect;
|
||||
|
||||
property OnMessage: TNotifyEvent read FOnMessage write FOnMessage;
|
||||
property OnError: TNotifyEvent read FOnError write FOnError;
|
||||
property OnSubOk: TNotifyEvent read FOnSubOk write FOnSubOk;
|
||||
property OnRAW: TNotifyEvent read FOnRAW write FOnRAW;
|
||||
property OnGetCustomReward: TGetCustomRewardEvent read FOnGetCustomReward
|
||||
write FOnGetCustomReward;
|
||||
property OnStatus: TOnStatus read FOnStatus write FOnStatus;
|
||||
property OnFollow: TGetFollowEvent read FOnFollow write FOnFollow;
|
||||
property OnSub: TGetSubEvent read FOnSub write FOnSub;
|
||||
property OnGift: TGetGiftEvent read FOnGift write FOnGift;
|
||||
property OnRaid: TGetRaidEvent read FOnRaid write FOnRaid;
|
||||
property OnLog: TOnLog read FOnLog write FOnLog;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses ugeneral;
|
||||
|
||||
function SafeGetObj(Parent: TJSONObject; const Name: string): TJSONObject;
|
||||
begin
|
||||
Result := Parent.GetValue<TJSONObject>(Name);
|
||||
if not Assigned(Result) then
|
||||
raise Exception.CreateFmt('JSON object "%s" not found', [Name]);
|
||||
end;
|
||||
|
||||
function SafeGetStr(Parent: TJSONObject; const Name: string): string;
|
||||
var
|
||||
V: TJSONValue;
|
||||
begin
|
||||
V := Parent.GetValue(Name);
|
||||
if Assigned(V) then
|
||||
Result := V.Value
|
||||
else
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
function SafeGetInt(Parent: TJSONObject; const Name: string): Integer;
|
||||
var
|
||||
V: TJSONValue;
|
||||
begin
|
||||
V := Parent.GetValue(Name);
|
||||
if Assigned(V) then
|
||||
Result := StrToIntDef(V.Value, 0)
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function SafeGetBool(Parent: TJSONObject; const Name: string): Boolean;
|
||||
var
|
||||
V: TJSONValue;
|
||||
begin
|
||||
V := Parent.GetValue(Name);
|
||||
if Assigned(V) then
|
||||
Result := SameText(V.Value, 'true')
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.toLog(aLevel: integer; aMethod: string; aMessage: string);
|
||||
begin
|
||||
if Assigned(FOnLog) then
|
||||
FOnLog('uTTWEvenSub', aMethod, aMessage, aLevel);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure TTTW_ES.Connect;
|
||||
begin
|
||||
|
||||
if wss.Connected then
|
||||
wss.Disconnect;
|
||||
|
||||
try
|
||||
wss.ConnectTo('wss://eventsub.wss.twitch.tv/ws?keepalive_timeout_seconds=60');
|
||||
toLog(0, 'Connect', 'Ïîäêëþ÷åíèå ê WebSocket âûïîëíåíî');
|
||||
FTimer.Enabled := True;
|
||||
except
|
||||
on E: Exception do
|
||||
toLog(2, 'Connect', E.Message);
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TTTW_ES.Create(Sender: TObject;
|
||||
aTokenWS, aClientID, aBroadcasterID: string);
|
||||
begin
|
||||
FAccessToken := aTokenWS;
|
||||
FClientID := aClientID;
|
||||
BroadcasterID := aBroadcasterID;
|
||||
|
||||
wss := TipwWSClient.Create(nil);
|
||||
wss.Timeout := 30;
|
||||
wss.OnPing := ipwWSPing;
|
||||
wss.OnDataIn := ipwWSClient1DataIn;
|
||||
wss.OnConnectionStatus := ipwWSClient1ConnectionStatus;
|
||||
wss.OnError := ipwWSClientError;
|
||||
wss.OnLog := ipwWSClientLog;
|
||||
wss.OnDisconnected := ipwWSClientDisconnected;
|
||||
wss.OnHeader := ipwWSClientHeader;
|
||||
|
||||
FTimer := TTimer.Create(nil);
|
||||
FTimer.Interval := 9000;
|
||||
FTimer.OnTimer := HandleTimer;
|
||||
FTimer.Enabled := False;
|
||||
|
||||
toLog(0, 'Create', 'Èíèöèàëèçàöèÿ EventSub');
|
||||
end;
|
||||
|
||||
destructor TTTW_ES.Destroy;
|
||||
begin
|
||||
toLog(0, 'Destroy', 'Çàâåðøåíèå ðàáîòû EventSub');
|
||||
try
|
||||
if Assigned(FTimer) then
|
||||
FreeAndNil(FTimer);
|
||||
|
||||
if Assigned(wss) then
|
||||
begin
|
||||
if wss.Connected then
|
||||
Disconnect;
|
||||
FreeAndNil(wss);
|
||||
end;
|
||||
finally
|
||||
inherited Destroy;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.Disconnect;
|
||||
begin
|
||||
toLog(1, 'Disconnect', 'Îòêëþ÷åíèå îò WebSocket');
|
||||
try
|
||||
if wss.Connected then
|
||||
wss.Disconnect;
|
||||
except
|
||||
on E: Exception do
|
||||
toLog(2, 'Disconnect', E.ClassName + ': ' + E.Message);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.EventMSG(const AText: string);
|
||||
var
|
||||
md: TMetadata;
|
||||
begin
|
||||
if Assigned(FOnRAW) then
|
||||
FOnRAW(AText);
|
||||
|
||||
md := ParseMetadata(AText);
|
||||
toLog(0, 'EventMSG', 'Òèï ñîîáùåíèÿ: ' + md.message_type + ', Òèï ïîäïèñêè: ' + md.subscription_type);
|
||||
|
||||
if md.message_type = 'session_welcome' then
|
||||
begin
|
||||
toLog(0, 'EventMSG', 'Ïîëó÷åí session_welcome');
|
||||
SW := ParseWelcomMessage(AText);
|
||||
if Assigned(FOnMessage) then
|
||||
FOnMessage('Welcome message');
|
||||
subscribe;
|
||||
end
|
||||
else if md.message_type = 'notification' then
|
||||
begin
|
||||
if md.subscription_type = 'channel.channel_points_custom_reward_redemption.add' then
|
||||
if Assigned(FOnGetCustomReward) then
|
||||
FOnGetCustomReward(ParseCustomRewardEvent(AText));
|
||||
|
||||
if md.subscription_type = 'channel.follow' then
|
||||
if Assigned(FOnFollow) then
|
||||
FOnFollow(ParseFollowEvent(AText));
|
||||
|
||||
// Òóò àíàëîãè÷íî ìîæíî âûçûâàòü ParseSubEvent, ParseGiftEvent, ParseRaidEvent
|
||||
end
|
||||
else if md.message_type = 'session_keepalive' then
|
||||
toLog(3, 'EventMSG', 'Ïîëó÷åí keepalive');
|
||||
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.HandleTimer(Sender: TObject);
|
||||
begin
|
||||
if wss.Connected then
|
||||
begin
|
||||
toLog(3, 'HandleTimer', 'Îòïðàâêà ping');
|
||||
wss.Ping;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.ipwWSClient1ConnectionStatus(Sender: TObject;
|
||||
const ConnectionEvent: String; StatusCode: Integer;
|
||||
const Description: String);
|
||||
begin
|
||||
toLog(0, 'ConnectionStatus',
|
||||
Format('%s | %d | %s', [ConnectionEvent, StatusCode, Description]));
|
||||
if Assigned(FOnStatus) then
|
||||
FOnStatus(Sender, ConnectionEvent, StatusCode, Description);
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.ipwWSClient1DataIn(Sender: TObject; DataFormat: Integer;
|
||||
const Text: string; const TextB: TBytes; EOM, EOL: Boolean);
|
||||
begin
|
||||
toLog(3, 'ipwWSClient1DataIn', Text);
|
||||
EventMSG(Text);
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.ipwWSClientDisconnected(Sender: TObject; StatusCode: Integer;
|
||||
const Description: String);
|
||||
begin
|
||||
toLog(1, 'ipwWSClientDisconnected', Description);
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.ipwWSClientError(Sender: TObject; ErrorCode: Integer;
|
||||
const Description: string);
|
||||
begin
|
||||
toLog(2, 'ipwWSClientError', Format('Êîä: %d | %s', [ErrorCode, Description]));
|
||||
if Assigned(FOnError) then
|
||||
FOnError(Description);
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.ipwWSClientHeader(Sender: TObject;
|
||||
const Field, Value: String);
|
||||
begin
|
||||
// toLog(3, 'ipwWSClientHeader',
|
||||
// 'Field: ' + Field + ' | Value: ' + Value);
|
||||
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.ipwWSClientLog(Sender: TObject; LogLevel: Integer;
|
||||
const aMessage, aLog: string);
|
||||
begin
|
||||
// toLog(3, 'ipwWSClientLog', 'Level: ' + IntToStr(LogLevel)
|
||||
// + ' | ' + aMessage + ' | ' + aLog);
|
||||
// form1.log(1, 'ipwWSClientLog', 'Level: ' + inttostr(LogLevel) + ' Message: ' +
|
||||
// aMessage + ' Log: ' + aLog);
|
||||
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.ipwWSPing(Sender: TObject; const Payload: String;
|
||||
const PayloadB: TBytes; Response: Boolean);
|
||||
begin
|
||||
toLog(3, 'ipwWSPing', 'PING ' + Payload);
|
||||
end;
|
||||
|
||||
function TTTW_ES.ParseMetadata(const JSONString: string): TMetadata;
|
||||
var
|
||||
Root, Metadata: TJSONObject;
|
||||
begin
|
||||
Root := TJSONObject.ParseJSONValue(JSONString) as TJSONObject;
|
||||
if not Assigned(Root) then
|
||||
raise Exception.Create('Invalid JSON');
|
||||
try
|
||||
Metadata := SafeGetObj(Root, 'metadata');
|
||||
Result.message_id := SafeGetStr(Metadata, 'message_id');
|
||||
Result.message_type := SafeGetStr(Metadata, 'message_type');
|
||||
Result.message_timestamp := SafeGetStr(Metadata, 'message_timestamp');
|
||||
Result.subscription_type := SafeGetStr(Metadata, 'subscription_type');
|
||||
finally
|
||||
Root.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTTW_ES.ParseWelcomMessage(const JSONString: string): TWelcomMessage;
|
||||
var
|
||||
Root, Payload, Session: TJSONObject;
|
||||
begin
|
||||
Root := TJSONObject.ParseJSONValue(JSONString) as TJSONObject;
|
||||
if not Assigned(Root) then
|
||||
raise Exception.Create('Invalid JSON');
|
||||
try
|
||||
Payload := SafeGetObj(Root, 'payload');
|
||||
Session := SafeGetObj(Payload, 'session');
|
||||
Result.Payload.session.id := SafeGetStr(Session, 'id');
|
||||
Result.Payload.session.status := SafeGetStr(Session, 'status');
|
||||
Result.Payload.session.connected_at := SafeGetStr(Session, 'connected_at');
|
||||
Result.Payload.session.keepalive_timeout_seconds := SafeGetInt(Session, 'keepalive_timeout_seconds');
|
||||
Result.Payload.session.reconnect_url := SafeGetStr(Session, 'reconnect_url');
|
||||
finally
|
||||
Root.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTTW_ES.ParseCustomRewardEvent(const JSONString: string)
|
||||
: TCustomRewardEvent;
|
||||
var
|
||||
Root, Payload, Subscription, mCondition, mTransport, Event, mReward: TJSONObject;
|
||||
begin
|
||||
toLog(3, 'ParseCustomRewardEvent', 'Íà÷àëî ïàðñèíãà íàãðàäû');
|
||||
Root := TJSONObject.ParseJSONValue(JSONString) as TJSONObject;
|
||||
if not Assigned(Root) then
|
||||
raise Exception.Create('Invalid JSON');
|
||||
try
|
||||
Payload := SafeGetObj(Root, 'payload');
|
||||
Subscription := SafeGetObj(Payload, 'subscription');
|
||||
with Result.Subscription do
|
||||
begin
|
||||
id := SafeGetStr(Subscription, 'id');
|
||||
subscription_type := SafeGetStr(Subscription, 'type');
|
||||
version := SafeGetStr(Subscription, 'version');
|
||||
status := SafeGetStr(Subscription, 'status');
|
||||
cost := SafeGetInt(Subscription, 'cost');
|
||||
created_at := SafeGetStr(Subscription, 'created_at');
|
||||
mCondition := SafeGetObj(Subscription, 'condition');
|
||||
condition.broadcaster_user_id := SafeGetStr(mCondition, 'broadcaster_user_id');
|
||||
condition.reward_id := SafeGetStr(mCondition, 'reward_id');
|
||||
mTransport := SafeGetObj(Subscription, 'transport');
|
||||
transport.method := SafeGetStr(mTransport, 'method');
|
||||
end;
|
||||
|
||||
Event := SafeGetObj(Payload, 'event');
|
||||
with Result.Event do
|
||||
begin
|
||||
id := SafeGetStr(Event, 'id');
|
||||
broadcaster_user_id := SafeGetStr(Event, 'broadcaster_user_id');
|
||||
broadcaster_user_login := SafeGetStr(Event, 'broadcaster_user_login');
|
||||
broadcaster_user_name := SafeGetStr(Event, 'broadcaster_user_name');
|
||||
user_id := SafeGetStr(Event, 'user_id');
|
||||
user_login := SafeGetStr(Event, 'user_login');
|
||||
user_name := SafeGetStr(Event, 'user_name');
|
||||
user_input := SafeGetStr(Event, 'user_input');
|
||||
mReward := SafeGetObj(Event, 'reward');
|
||||
revard.id := SafeGetStr(mReward, 'id');
|
||||
revard.title := SafeGetStr(mReward, 'title');
|
||||
revard.cost := SafeGetInt(mReward, 'cost');
|
||||
revard.prompt := SafeGetStr(mReward, 'prompt');
|
||||
end;
|
||||
finally
|
||||
Root.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTTW_ES.ParseFollowEvent(const JSONString: string): TFollowEvent;
|
||||
var
|
||||
Root, Payload, Subscription, mCondition, mTransport, Event: TJSONObject;
|
||||
begin
|
||||
toLog(3, 'ParseFollowEvent', 'Ïàðñèíã ïîäïèñêè');
|
||||
Root := TJSONObject.ParseJSONValue(JSONString) as TJSONObject;
|
||||
if not Assigned(Root) then
|
||||
raise Exception.Create('Invalid JSON');
|
||||
try
|
||||
Payload := SafeGetObj(Root, 'payload');
|
||||
Subscription := SafeGetObj(Payload, 'subscription');
|
||||
with Result.Subscription do
|
||||
begin
|
||||
id := SafeGetStr(Subscription, 'id');
|
||||
subscription_type := SafeGetStr(Subscription, 'type');
|
||||
version := SafeGetStr(Subscription, 'version');
|
||||
status := SafeGetStr(Subscription, 'status');
|
||||
cost := SafeGetInt(Subscription, 'cost');
|
||||
created_at := SafeGetStr(Subscription, 'created_at');
|
||||
mCondition := SafeGetObj(Subscription, 'condition');
|
||||
condition.broadcaster_user_id := SafeGetStr(mCondition, 'broadcaster_user_id');
|
||||
mTransport := SafeGetObj(Subscription, 'transport');
|
||||
transport.method := SafeGetStr(mTransport, 'method');
|
||||
end;
|
||||
|
||||
Event := SafeGetObj(Payload, 'event');
|
||||
with Result.Event do
|
||||
begin
|
||||
broadcaster_user_id := SafeGetStr(Event, 'broadcaster_user_id');
|
||||
broadcaster_user_login := SafeGetStr(Event, 'broadcaster_user_login');
|
||||
broadcaster_user_name := SafeGetStr(Event, 'broadcaster_user_name');
|
||||
user_id := SafeGetStr(Event, 'user_id');
|
||||
user_login := SafeGetStr(Event, 'user_login');
|
||||
user_name := SafeGetStr(Event, 'user_name');
|
||||
followed_at := SafeGetStr(Event, 'followed_at');
|
||||
end;
|
||||
finally
|
||||
Root.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTTW_ES.ParseGiftEvent(const JSONString: string): TGiftEvent;
|
||||
var
|
||||
Root, Payload, Subscription, mCondition, mTransport, Event: TJSONObject;
|
||||
begin
|
||||
toLog(3, 'ParseGiftEvent', 'Ïàðñèíã ïîäàðî÷íîé ïîäïèñêè');
|
||||
Root := TJSONObject.ParseJSONValue(JSONString) as TJSONObject;
|
||||
if not Assigned(Root) then
|
||||
raise Exception.Create('Invalid JSON');
|
||||
try
|
||||
Payload := SafeGetObj(Root, 'payload');
|
||||
Subscription := SafeGetObj(Payload, 'subscription');
|
||||
with Result.Subscription do
|
||||
begin
|
||||
id := SafeGetStr(Subscription, 'id');
|
||||
subscription_type := SafeGetStr(Subscription, 'type');
|
||||
version := SafeGetStr(Subscription, 'version');
|
||||
status := SafeGetStr(Subscription, 'status');
|
||||
cost := SafeGetInt(Subscription, 'cost');
|
||||
created_at := SafeGetStr(Subscription, 'created_at');
|
||||
mCondition := SafeGetObj(Subscription, 'condition');
|
||||
condition.broadcaster_user_id := SafeGetStr(mCondition, 'broadcaster_user_id');
|
||||
mTransport := SafeGetObj(Subscription, 'transport');
|
||||
transport.method := SafeGetStr(mTransport, 'method');
|
||||
end;
|
||||
|
||||
Event := SafeGetObj(Payload, 'event');
|
||||
with Result.Event do
|
||||
begin
|
||||
broadcaster_user_id := SafeGetStr(Event, 'broadcaster_user_id');
|
||||
broadcaster_user_login := SafeGetStr(Event, 'broadcaster_user_login');
|
||||
broadcaster_user_name := SafeGetStr(Event, 'broadcaster_user_name');
|
||||
user_id := SafeGetStr(Event, 'user_id');
|
||||
user_login := SafeGetStr(Event, 'user_login');
|
||||
user_name := SafeGetStr(Event, 'user_name');
|
||||
total := SafeGetInt(Event, 'total');
|
||||
tier := SafeGetStr(Event, 'tier');
|
||||
cumulative_total := SafeGetInt(Event, 'cumulative_total');
|
||||
is_anonymous := SafeGetBool(Event, 'anonymous');
|
||||
end;
|
||||
finally
|
||||
Root.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function TTTW_ES.ParseRaidEvent(const JSONString: string): TRaidEvent;
|
||||
var
|
||||
Root, Payload, Subscription, mCondition, mTransport, Event: TJSONObject;
|
||||
begin
|
||||
toLog(3, 'ParseRaidEvent', 'Ïàðñèíã ðåéäà');
|
||||
Root := TJSONObject.ParseJSONValue(JSONString) as TJSONObject;
|
||||
if not Assigned(Root) then
|
||||
raise Exception.Create('Invalid JSON');
|
||||
try
|
||||
Payload := SafeGetObj(Root, 'payload');
|
||||
Subscription := SafeGetObj(Payload, 'subscription');
|
||||
with Result.Subscription do
|
||||
begin
|
||||
id := SafeGetStr(Subscription, 'id');
|
||||
subscription_type := SafeGetStr(Subscription, 'type');
|
||||
version := SafeGetStr(Subscription, 'version');
|
||||
status := SafeGetStr(Subscription, 'status');
|
||||
cost := SafeGetInt(Subscription, 'cost');
|
||||
created_at := SafeGetStr(Subscription, 'created_at');
|
||||
mCondition := SafeGetObj(Subscription, 'condition');
|
||||
condition.broadcaster_user_id := SafeGetStr(mCondition, 'to_broadcaster_user_id');
|
||||
mTransport := SafeGetObj(Subscription, 'transport');
|
||||
transport.method := SafeGetStr(mTransport, 'method');
|
||||
end;
|
||||
|
||||
Event := SafeGetObj(Payload, 'event');
|
||||
with Result.Event do
|
||||
begin
|
||||
from_broadcaster_user_id := SafeGetStr(Event, 'from_broadcaster_user_id');
|
||||
from_broadcaster_user_login := SafeGetStr(Event, 'from_broadcaster_user_login');
|
||||
from_broadcaster_user_name := SafeGetStr(Event, 'from_broadcaster_user_name');
|
||||
to_broadcaster_user_id := SafeGetStr(Event, 'to_broadcaster_user_id');
|
||||
to_broadcaster_user_login := SafeGetStr(Event, 'to_broadcaster_user_login');
|
||||
to_broadcaster_user_name := SafeGetStr(Event, 'to_broadcaster_user_name');
|
||||
viewers := SafeGetInt(Event, 'viewers');
|
||||
end;
|
||||
finally
|
||||
Root.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTTW_ES.ParseSubEvent(const JSONString: string): TSubEvent;
|
||||
var
|
||||
Root, Payload, Subscription, mCondition, mTransport, Event: TJSONObject;
|
||||
begin
|
||||
toLog(3, 'ParseSubEvent', 'Ïàðñèíã ïîäïèñêè');
|
||||
Root := TJSONObject.ParseJSONValue(JSONString) as TJSONObject;
|
||||
if not Assigned(Root) then
|
||||
raise Exception.Create('Invalid JSON');
|
||||
try
|
||||
Payload := SafeGetObj(Root, 'payload');
|
||||
Subscription := SafeGetObj(Payload, 'subscription');
|
||||
with Result.Subscription do
|
||||
begin
|
||||
id := SafeGetStr(Subscription, 'id');
|
||||
subscription_type := SafeGetStr(Subscription, 'type');
|
||||
version := SafeGetStr(Subscription, 'version');
|
||||
status := SafeGetStr(Subscription, 'status');
|
||||
cost := SafeGetInt(Subscription, 'cost');
|
||||
created_at := SafeGetStr(Subscription, 'created_at');
|
||||
mCondition := SafeGetObj(Subscription, 'condition');
|
||||
condition.broadcaster_user_id := SafeGetStr(mCondition, 'broadcaster_user_id');
|
||||
mTransport := SafeGetObj(Subscription, 'transport');
|
||||
transport.method := SafeGetStr(mTransport, 'method');
|
||||
end;
|
||||
|
||||
Event := SafeGetObj(Payload, 'event');
|
||||
with Result.Event do
|
||||
begin
|
||||
broadcaster_user_id := SafeGetStr(Event, 'broadcaster_user_id');
|
||||
broadcaster_user_login := SafeGetStr(Event, 'broadcaster_user_login');
|
||||
broadcaster_user_name := SafeGetStr(Event, 'broadcaster_user_name');
|
||||
user_id := SafeGetStr(Event, 'user_id');
|
||||
user_login := SafeGetStr(Event, 'user_login');
|
||||
user_name := SafeGetStr(Event, 'user_name');
|
||||
tier := SafeGetStr(Event, 'tier');
|
||||
is_gift := SafeGetBool(Event, 'is_gift');
|
||||
end;
|
||||
finally
|
||||
Root.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTTW_ES.subscribeTo(const EventType, Version: string; const Condition: string): Boolean;
|
||||
var
|
||||
Json: TStringStream;
|
||||
Resp: string;
|
||||
HTTP: TNetHTTPClient;
|
||||
begin
|
||||
Result := False;
|
||||
toLog(0, 'subscribeTo', 'Ïîäïèñêà íà ' + EventType);
|
||||
|
||||
HTTP := TNetHTTPClient.Create(nil);
|
||||
try
|
||||
HTTP.ContentType := 'application/json';
|
||||
HTTP.CustomHeaders['Authorization'] := 'Bearer ' + FAccessToken;
|
||||
HTTP.CustomHeaders['Client-Id'] := FClientID;
|
||||
|
||||
Json := TStringStream.Create(
|
||||
TJSONObject.Create
|
||||
.AddPair('type', EventType)
|
||||
.AddPair('version', Version)
|
||||
.AddPair('condition', TJSONObject.ParseJSONValue(Condition) as TJSONObject)
|
||||
.AddPair('transport',
|
||||
TJSONObject.Create
|
||||
.AddPair('method', 'websocket')
|
||||
.AddPair('session_id', SW.Payload.session.id)
|
||||
).ToJSON, TEncoding.UTF8
|
||||
);
|
||||
try
|
||||
Resp := HTTP.Post('https://api.twitch.tv/helix/eventsub/subscriptions', Json).ContentAsString();
|
||||
toLog(3, 'subscribeTo', 'Îòâåò Twitch: ' + Resp);
|
||||
|
||||
if Pos('"status":"enabled"', Resp) > 0 then
|
||||
begin
|
||||
toLog(0, 'subscribeTo', 'Ïîäïèñêà óñïåøíà');
|
||||
Result := True;
|
||||
end
|
||||
else
|
||||
toLog(1, 'subscribeTo', 'Ïîäïèñêà íå ïîäòâåðæäåíà: ' + Resp);
|
||||
finally
|
||||
Json.Free;
|
||||
end;
|
||||
except
|
||||
on E: Exception do
|
||||
toLog(2, 'subscribeTo', 'Îøèáêà ïîäïèñêè: ' + E.Message);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTTW_ES.subscribe;
|
||||
begin
|
||||
// channel.channel_points_custom_reward.add (1)
|
||||
// channel.follow (2) moderator:read:followers
|
||||
// channel.subscribe (1) channel:read:subscriptions
|
||||
// channel.subscription.gift (1) channel:read:subscriptions
|
||||
// channel.raid (1)
|
||||
if subscribeTo('channel.channel_points_custom_reward_redemption.add', '1',
|
||||
'{"broadcaster_user_id":"' + BroadcasterID + '"}') then
|
||||
toLog(0, 'subscribe',
|
||||
'channel.channel_points_custom_reward_redemption.add OK')
|
||||
else
|
||||
toLog(2, 'subscribe',
|
||||
'channel.channel_points_custom_reward_redemption.add');
|
||||
|
||||
if subscribeTo('channel.raid', '1', '{"to_broadcaster_user_id":"' +
|
||||
BroadcasterID + '"}') then
|
||||
toLog(0, 'subscribe', 'channel.raid OK')
|
||||
else
|
||||
toLog(2, 'subscribe', 'channel.raid');
|
||||
|
||||
if subscribeTo('channel.follow', '2', '{"broadcaster_user_id":"' +
|
||||
BroadcasterID + '","moderator_user_id":"' + BroadcasterID + '"}') then
|
||||
toLog(0, 'subscribe', 'channel.follow OK')
|
||||
else
|
||||
toLog(2, 'subscribe', 'channel.follow');
|
||||
|
||||
if subscribeTo('channel.subscribe', '1', '{"broadcaster_user_id":"' +
|
||||
BroadcasterID + '"}') then
|
||||
toLog(0, 'subscribe', 'channel.subscribe OK')
|
||||
else
|
||||
toLog(2, 'subscribe', 'channel.subscribe');
|
||||
|
||||
if subscribeTo('channel.subscription.gift', '1', '{"broadcaster_user_id":"' +
|
||||
BroadcasterID + '"}') then
|
||||
toLog(0, 'subscribe', 'channel.subscription.gift OK')
|
||||
else
|
||||
toLog(2, 'subscribe', 'channel.subscription.gift');
|
||||
end;
|
||||
|
||||
end.
|
||||
Reference in New Issue
Block a user