From fd1c6b6bb8beaf1f2c814008523adf2d6056cea7 Mon Sep 17 00:00:00 2001 From: "PC1\\PTyTb" Date: Sat, 16 Aug 2025 22:42:29 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BE=D0=BF=D0=BE=D0=B2=D0=B5=D1=89=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F,=20=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=B0=D1=8E=D1=82=20=D1=87=D0=B5=D1=82=D0=BA?= =?UTF-8?q?=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Services/uTTWAPI.pas | 7 +- TTW_Bot_app.dpr | 3 +- TTW_Bot_app.dproj | 38 ++- TTW_Bot_app_Icon2.ico | Bin 0 -> 93062 bytes Win32/Release/botapp.cfg | 5 + forms/uCreateNotify.fmx | 13 +- forms/uCreateNotify.pas | 118 ++++++-- forms/uGeneral.fmx | 146 ++++++--- forms/uGeneral.pas | 108 ++++--- frames/fEvents.pas | 393 ++++++++++-------------- frames/fOBS.fmx | 4 +- frames/fOBS.pas | 545 ++++++++++++---------------------- frames/fRevards.fmx | 109 +++++++ frames/fRevards.pas | 66 ++++ utils/uRecords.pas | 105 ++++--- utils/uWebServerEvents.pas | 230 ++++++-------- utils/uWebServerKandinsky.pas | 6 +- 17 files changed, 968 insertions(+), 928 deletions(-) create mode 100644 TTW_Bot_app_Icon2.ico create mode 100644 Win32/Release/botapp.cfg create mode 100644 frames/fRevards.fmx create mode 100644 frames/fRevards.pas diff --git a/Services/uTTWAPI.pas b/Services/uTTWAPI.pas index e53660e..bfe7d20 100644 --- a/Services/uTTWAPI.pas +++ b/Services/uTTWAPI.pas @@ -93,7 +93,6 @@ function TTTW_API.createCustomReward(title: string; cost: string; var RequestData: TStringStream; s, s1, json: string; - i: integer; cr: TCustomRevards; JSONData: TJSONObject; JSONArray: TJSONArray; @@ -1041,9 +1040,9 @@ var EmoteObj: TJSONObject; ImagesObj: TJSONObject; Emote: TEmotes; - I, J: Integer; + I: Integer; chosenFormat, chosenTheme, chosenScale: string; - foundAnimated, foundNonStatic, foundDark: Boolean; + foundAnimated, foundDark: Boolean; scaleVal, maxScale: Double; s: string; begin @@ -1076,7 +1075,6 @@ begin // Выбор формата (format) foundAnimated := False; - foundNonStatic := False; chosenFormat := 'static'; // значение по умолчанию // Проверка наличия "animated" @@ -1094,7 +1092,6 @@ begin if s <> 'static' then begin chosenFormat := s; - foundNonStatic := True; Break; end; diff --git a/TTW_Bot_app.dpr b/TTW_Bot_app.dpr index 3eda71b..8f125f7 100644 --- a/TTW_Bot_app.dpr +++ b/TTW_Bot_app.dpr @@ -47,7 +47,8 @@ uses uWebServerKandinsky in 'utils\uWebServerKandinsky.pas', uWebServerEvents in 'utils\uWebServerEvents.pas', fEvents in 'frames\fEvents.pas' {frEvents: TFrame}, - uKeyEvent in 'utils\uKeyEvent.pas'; + uKeyEvent in 'utils\uKeyEvent.pas', + fRevards in 'frames\fRevards.pas' {frRevards: TFrame}; {$R *.res} diff --git a/TTW_Bot_app.dproj b/TTW_Bot_app.dproj index 85d3d0c..53a8597 100644 --- a/TTW_Bot_app.dproj +++ b/TTW_Bot_app.dproj @@ -306,9 +306,12 @@ true 10 1 - 1 + 2 1049 - CompanyName=PTyTb;FileDescription=$(MSBuildProjectName);FileVersion=10.1.1.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=ru.ptytb.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + CompanyName=PTyTb;FileDescription=$(MSBuildProjectName);FileVersion=10.1.2.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=ru.ptytb.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + TTW_Bot_app_Icon2.ico + ..\ttw_fmx_v9\fawico_44_2.png + ..\ttw_fmx_v9\fawico_150_2.png PerMonitorV2 @@ -438,6 +441,11 @@ TFrame + +
frRevards
+ fmx + TFrame +
Base @@ -487,6 +495,13 @@ true + + + Assets\ + Logo150x150.png + true + + Assets\ @@ -494,18 +509,37 @@ true + + + Assets\ + Logo44x44.png + true + + .\ true + + + .\ + true + + TTW_Bot_app.exe true + + + TTW_Bot_app.exe + true + + 1 diff --git a/TTW_Bot_app_Icon2.ico b/TTW_Bot_app_Icon2.ico new file mode 100644 index 0000000000000000000000000000000000000000..dca514ba007ec36a8948162f570e8baeebb2706b GIT binary patch literal 93062 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 O`F}QD{;U1ukNpd>Yhqvk literal 0 HcmV?d00001 diff --git a/Win32/Release/botapp.cfg b/Win32/Release/botapp.cfg new file mode 100644 index 0000000..36df4ce --- /dev/null +++ b/Win32/Release/botapp.cfg @@ -0,0 +1,5 @@ + QKPG@VrKK3q|#/<6# #?2r?3t&)_< +6s  q ,*< m.~|0256{|I *55w" KK8WZFD +-!2->1-7)WDB2,/7p-t+$kmSN? w t (!8+uv5( +4*,(3,+V)20B= +*u8+", (3&2ucR*"'>3&s ( s +W*!(B=&x{LR-r{s`SXKJ| q;kup%1K_FS_s%t<%%$ugRR \ No newline at end of file diff --git a/forms/uCreateNotify.fmx b/forms/uCreateNotify.fmx index 81b5965..f3a2011 100644 --- a/forms/uCreateNotify.fmx +++ b/forms/uCreateNotify.fmx @@ -146,7 +146,7 @@ object fCreateNotify: TfCreateNotify Position.X = 8.000000000000000000 Position.Y = 135.000000000000000000 Text = #1057#1086#1073#1099#1090#1080#1077 - TabOrder = 37 + TabOrder = 38 end object cbEventsType: TComboBox Items.Strings = ( @@ -154,13 +154,14 @@ object fCreateNotify: TfCreateNotify #1055#1086#1076#1087#1080#1089#1082#1072 #1055#1086#1076#1072#1088#1086#1095#1085#1072#1103' '#1087#1086#1076#1087#1080#1089#1082#1072 #1056#1077#1081#1076 - #1044#1086#1085#1072#1090) + #1044#1086#1085#1072#1090 + #1057#1074#1086#1077) Position.X = 8.000000000000000000 Position.Y = 160.000000000000000000 Size.Width = 192.000000000000000000 Size.Height = 22.000000000000000000 Size.PlatformDefault = False - TabOrder = 38 + TabOrder = 39 OnChange = cbEventsTypeChange end object Label3: TLabel @@ -168,11 +169,11 @@ object fCreateNotify: TfCreateNotify Position.Y = 190.000000000000000000 Text = #1059#1089#1083#1086#1074#1080#1077' '#1089#1091#1084#1084#1099 Visible = False - TabOrder = 39 + TabOrder = 40 end object edtIF: TEdit Touch.InteractiveGestures = [LongTap, DoubleTap] - TabOrder = 40 + TabOrder = 41 Position.X = 8.000000000000000000 Position.Y = 215.000000000000000000 Size.Width = 192.000000000000000000 @@ -215,7 +216,7 @@ object fCreateNotify: TfCreateNotify object edtESTitle: TEdit Touch.InteractiveGestures = [LongTap, DoubleTap] Align = Top - TabOrder = 37 + TabOrder = 38 Text = '[NICK] '#1085#1072#1095#1072#1083' '#1086#1090#1089#1083#1077#1078#1080#1074#1072#1090#1100' '#1074#1072#1089 Position.X = 10.000000000000000000 Position.Y = 20.000000000000000000 diff --git a/forms/uCreateNotify.pas b/forms/uCreateNotify.pas index 43cf9b6..8cbd4e9 100644 --- a/forms/uCreateNotify.pas +++ b/forms/uCreateNotify.pas @@ -4,7 +4,7 @@ interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, - System.Variants, fOBS, + System.Variants, fOBS, System.RegularExpressions, Math, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, fFontSettings, fColorSettings, FMX.StdCtrls, FMX.Edit, FMX.Controls.Presentation, FMX.ListBox, FMX.EditBox, FMX.SpinBox, FMX.Colors, uRecords; @@ -44,6 +44,9 @@ type { Private declarations } function GetColorFromColorPanel(aColor: TAlphaColor): string; function GetColorFromCCB(aColor: TAlphaColor): string; + + function GetColorFromRGBA(const s: string): TAlphaColor; + function GetColorFromHex(const s: string): TAlphaColor; public { Public declarations } isEdit: boolean; @@ -60,6 +63,33 @@ uses uGeneral; {$R *.fmx} + function TfCreateNotify.GetColorFromRGBA(const s: string): TAlphaColor; +var + Match: TMatch; + r, g, b: Integer; + a: Double; + Rec: TAlphaColorRec; +begin + Match := TRegEx.Match(s, 'rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)'); + if Match.Success then + begin + r := StrToInt(Match.Groups[1].Value); + g := StrToInt(Match.Groups[2].Value); + b := StrToInt(Match.Groups[3].Value); + a := StrToFloat(Match.Groups[4].Value, TFormatSettings.Invariant); + + // Заполняем структуру вручную + Rec.R := Byte(r); + Rec.G := Byte(g); + Rec.B := Byte(b); + Rec.A := Round(a * 255); + + Result := Rec.Color; + end + else + raise Exception.CreateFmt('Неверный формат rgba: %s', [s]); +end; + function TfCreateNotify.GetColorFromColorPanel(aColor: TAlphaColor): string; var Color: TAlphaColor; @@ -80,6 +110,47 @@ begin result := Format('rgba(%d, %d, %d, %.2f)', [r, G, B, A], FS); end; +function TfCreateNotify.GetColorFromCCB(aColor: TAlphaColor): string; +var + Color: TAlphaColor; + r, G, B: Byte; +begin + Color := aColor; + r := TAlphaColorRec(Color).r; + G := TAlphaColorRec(Color).G; + B := TAlphaColorRec(Color).B; + result := Format('#%.2X%.2X%.2X', [r, G, B]); +end; + +function TfCreateNotify.GetColorFromHex(const s: string): TAlphaColor; +var + Hex: string; + r, g, b: Integer; + Rec: TAlphaColorRec; +begin + // Убираем возможный символ # + Hex := s.Trim; + if Hex.StartsWith('#') then + Hex := Hex.Substring(1); + + // Ожидаем ровно 6 символов (RRGGBB) + if Length(Hex) <> 6 then + raise Exception.CreateFmt('Неверный HEX цвет: %s', [s]); + + // Парсим компоненты + r := StrToInt('$' + Copy(Hex, 1, 2)); + g := StrToInt('$' + Copy(Hex, 3, 2)); + b := StrToInt('$' + Copy(Hex, 5, 2)); + + // Заполняем структуру + Rec.R := Byte(r); + Rec.G := Byte(g); + Rec.B := Byte(b); + Rec.A := 255; // полная непрозрачность + + Result := Rec.Color; +end; + procedure TfCreateNotify.setRecord(aRec: TOBSNotify); var SavedColor: TAlphaColor; @@ -97,19 +168,21 @@ begin fCreateNotify.frColorSettings1.sbStyleBlockBorderSize.Value := SolidBorder; fCreateNotify.frColorSettings1.sbStyleBlockPadding.Value := Paddings; - fCreateNotify.frColorSettings1.ccbStyleBorderColor.ItemIndex := ColorBorder; - fCreateNotify.frColorSettings1.ccbBColor.ItemIndex := ColorBackground; + fCreateNotify.frColorSettings1.ccbStyleBorderColor.Color := GetColorFromHex(ColorBorder); + fCreateNotify.frColorSettings1.ccbBColor.Color := GetColorFromHex(ColorBackground); + fCreateNotify.frColorSettings1.cpStyleBlockColor.Color:=GetColorFromRGBA(ColorBlock); fCreateNotify.edtESTitle.Text := HeaderText; - fCreateNotify.frFontSettings2.ccbFontColor.ItemIndex := HeaderColorFont; + fCreateNotify.frFontSettings2.ccbFontColor.Color := GetColorFromHex(HeaderColorFont); fCreateNotify.frFontSettings2.sbFontSize.Value := HeaderSizeFont; fCreateNotify.frFontSettings2.cbFontStyleDefault.ItemIndex := - HeaderStyleFont; + fCreateNotify.frFontSettings2.cbFontStyleDefault.Items.IndexOf(HeaderStyleFont); fCreateNotify.edtESMessage.Text := MessText; - fCreateNotify.frFontSettings3.ccbFontColor.ItemIndex := MessColorFont; + fCreateNotify.frFontSettings3.ccbFontColor.Color := GetColorFromHex(MessColorFont); fCreateNotify.frFontSettings3.sbFontSize.Value := MessSizeFont; - fCreateNotify.frFontSettings3.cbFontStyleDefault.ItemIndex := MessStyleFont; + fCreateNotify.frFontSettings3.cbFontStyleDefault.ItemIndex := + fCreateNotify.frFontSettings3.cbFontStyleDefault.Items.IndexOf(MessStyleFont); fCreateNotify.sbTimeMsg.Value := TimeMess; fCreateNotify.cbEventsType.ItemIndex := TypeEvent; @@ -132,18 +205,18 @@ begin (frColorSettings1.cpStyleBlockColor.Color); SolidBorder := round(frColorSettings1.sbStyleBlockBorderSize.Value); Paddings := round(frColorSettings1.sbStyleBlockPadding.Value); - ColorBorder := frColorSettings1.ccbStyleBorderColor.ItemIndex; - ColorBackground := frColorSettings1.ccbBColor.ItemIndex; + ColorBorder := GetColorFromCCB(frColorSettings1.ccbStyleBorderColor.Color); + ColorBackground := GetColorFromCCB(frColorSettings1.ccbBColor.Color); HeaderText := edtESTitle.Text; - HeaderColorFont := frFontSettings2.ccbFontColor.ItemIndex; + HeaderColorFont := GetColorFromCCB(frFontSettings2.ccbFontColor.Color); HeaderSizeFont := round(frFontSettings2.sbFontSize.Value); - HeaderStyleFont := frFontSettings2.cbFontStyleDefault.ItemIndex; + HeaderStyleFont := frFontSettings2.cbFontStyleDefault.Text; MessText := edtESMessage.Text; - MessColorFont := frFontSettings3.ccbFontColor.ItemIndex; + MessColorFont := GetColorFromCCB(frFontSettings3.ccbFontColor.color); MessSizeFont := round(frFontSettings3.sbFontSize.Value); - MessStyleFont := frFontSettings3.cbFontStyleDefault.ItemIndex; + MessStyleFont := frFontSettings3.cbFontStyleDefault.Text; TimeMess := round(sbTimeMsg.Value); TypeEvent := cbEventsType.ItemIndex; @@ -159,22 +232,13 @@ end; -function TfCreateNotify.GetColorFromCCB(aColor: TAlphaColor): string; -var - Color: TAlphaColor; - r, G, B: Byte; -begin - Color := aColor; - r := TAlphaColorRec(Color).r; - G := TAlphaColorRec(Color).G; - B := TAlphaColorRec(Color).B; - result := Format('#%.2X%.2X%.2X', [r, G, B]); -end; + procedure TfCreateNotify.btnESTestClick(Sender: TObject); var se: TStyleEvent; i: Integer; + ws:TEventWebServers; begin se.Title := edtESTitle.Text; @@ -195,8 +259,12 @@ begin se.RequireInteraction := True; for i := 0 to TTW_Bot.frOBS1.EventWebServers.Count - 1 do begin - TTW_Bot.frOBS1.EventWebServers[i].WebServerChat.AddMessage(se); + if TTW_Bot.frOBS1.EventWebServers[i].port = oldPort then + ws:=TTW_Bot.frOBS1.EventWebServers[i]; + + end; + ws.WebServerChat.addMessage(se); end; procedure TfCreateNotify.cbEventsTypeChange(Sender: TObject); diff --git a/forms/uGeneral.fmx b/forms/uGeneral.fmx index 8155f97..49e3274 100644 --- a/forms/uGeneral.fmx +++ b/forms/uGeneral.fmx @@ -3,7 +3,7 @@ object TTW_Bot: TTTW_Bot Top = 0 Caption = 'TTW_Bot' ClientHeight = 886 - ClientWidth = 970 + ClientWidth = 1003 Position = Designed FormFactor.Width = 320 FormFactor.Height = 480 @@ -15,30 +15,30 @@ object TTW_Bot: TTTW_Bot object V: TTabControl Align = Client Images = ImageList1 - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 Size.Height = 744.000000000000000000 Size.PlatformDefault = False - TabIndex = 5 + TabIndex = 3 TabOrder = 0 TabPosition = PlatformDefault Sizes = ( - 970s + 1003s 718s - 970s + 1003s 718s - 970s + 1003s 718s - 970s + 1003s 718s - 970s + 1003s 718s - 970s + 1003s 718s - 970s + 1003s 718s - 970s + 1003s 718s - 970s + 1003s 718s) object TabItem1: TTabItem CustomIcon = < @@ -57,7 +57,7 @@ object TTW_Bot: TTTW_Bot ExplicitSize.cy = 26.000000000000000000 inline frSettings1: TfrSettings Align = Client - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 Size.Height = 718.000000000000000000 Size.PlatformDefault = False inherited GroupBox3: TGroupBox @@ -92,35 +92,35 @@ object TTW_Bot: TTTW_Bot TabOrder = 34 end inherited Label63: TLabel - TabOrder = 30 + TabOrder = 29 end inherited edtDAClientID: TEdit - TabOrder = 32 - end - inherited Label64: TLabel TabOrder = 31 end - inherited edtDAClientSecret: TEdit - TabOrder = 33 + inherited Label64: TLabel + TabOrder = 30 + end + inherited Label65: TLabel + TabOrder = 32 end inherited edtDARedirectURL: TEdit - TabOrder = 40 + TabOrder = 37 end inherited edtDACode: TEdit - TabOrder = 36 + TabOrder = 35 end inherited Label66: TLabel - TabOrder = 37 + TabOrder = 36 end inherited btnDAStart: TButton Images = ImageList1 ImageIndex = 18 - TabOrder = 39 + TabOrder = 38 OnClick = frSettings1btnDAStartClick end inherited btnGetDADef: TButton Images = ImageList1 - TabOrder = 43 + TabOrder = 40 end end inherited btnOpenRomaning: TButton @@ -168,7 +168,7 @@ object TTW_Bot: TTTW_Bot ExplicitSize.cy = 26.000000000000000000 inline frAI1: TfrAI Align = Client - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 Size.Height = 718.000000000000000000 Size.PlatformDefault = False inherited btnGetAIDef: TButton @@ -201,7 +201,7 @@ object TTW_Bot: TTTW_Bot ExplicitSize.cy = 26.000000000000000000 inline frCommands1: TfrCommands Align = Client - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 Size.Height = 718.000000000000000000 Size.PlatformDefault = False inherited sgCommands: TStringGrid @@ -269,6 +269,15 @@ object TTW_Bot: TTTW_Bot Images = ImageList1 ImageIndex = 12 end + object cbHelloTTS: TCheckBox + Position.X = 240.000000000000000000 + Position.Y = 35.000000000000000000 + Size.Width = 152.000000000000000000 + Size.Height = 19.000000000000000000 + Size.PlatformDefault = False + TabOrder = 48 + Text = #1055#1088#1080#1074#1077#1090#1089#1090#1074#1086#1074#1072#1090#1100' '#1085#1086#1074#1099#1093 + end end end inherited GroupBox9: TGroupBox @@ -423,7 +432,7 @@ object TTW_Bot: TTTW_Bot item end> TextSettings.Trimming = None - IsSelected = False + IsSelected = True ImageIndex = 20 Size.Width = 79.000000000000000000 Size.Height = 26.000000000000000000 @@ -466,7 +475,8 @@ object TTW_Bot: TTTW_Bot Padding.Top = 20.000000000000000000 Padding.Right = 10.000000000000000000 Padding.Bottom = 10.000000000000000000 - Position.Y = 249.000000000000000000 + Position.X = 1.000000000000000000 + Position.Y = 342.000000000000000000 Size.Width = 841.000000000000000000 Size.Height = 368.000000000000000000 Size.PlatformDefault = False @@ -509,6 +519,52 @@ object TTW_Bot: TTTW_Bot end end end + object GroupBox3: TGroupBox + Padding.Left = 10.000000000000000000 + Padding.Top = 20.000000000000000000 + Padding.Right = 10.000000000000000000 + Padding.Bottom = 10.000000000000000000 + Position.X = 337.000000000000000000 + Position.Y = 8.000000000000000000 + Size.Width = 625.000000000000000000 + Size.Height = 326.000000000000000000 + Size.PlatformDefault = False + Text = #1053#1072#1075#1088#1072#1076#1099 + TabOrder = 2 + inline frRevards1: TfrRevards + Align = Client + Size.Width = 605.000000000000000000 + Size.Height = 296.000000000000000000 + Size.PlatformDefault = False + inherited StringGrid1: TStringGrid + Size.Width = 605.000000000000000000 + Size.Height = 153.000000000000000000 + Viewport.Width = 605.000000000000000000 + Viewport.Height = 153.000000000000000000 + inherited StringColumn1: TStringColumn + Size.Width = 241.000000000000000000 + end + inherited StringColumn2: TStringColumn + Size.Width = 140.000000000000000000 + end + end + inherited Label34: TLabel + TabOrder = 2 + end + inherited nbCustomRevardCost: TNumberBox + TabOrder = 5 + end + inherited Label35: TLabel + TabOrder = 3 + end + inherited Label2: TLabel + TabOrder = 9 + end + inherited btnDelCustomRewards: TButton + TabOrder = 16 + end + end + end end object TabItem4: TTabItem CustomIcon = < @@ -527,13 +583,13 @@ object TTW_Bot: TTTW_Bot ExplicitSize.cy = 26.000000000000000000 inline frOBS1: TfrOBS Align = Top - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 Size.Height = 345.000000000000000000 Size.PlatformDefault = False inherited sgWebChats: TStringGrid - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 Size.Height = 282.000000000000000000 - Viewport.Width = 970.000000000000000000 + Viewport.Width = 1003.000000000000000000 Viewport.Height = 282.000000000000000000 inherited StringColumn2: TStringColumn Size.Width = 200.000000000000000000 @@ -550,7 +606,7 @@ object TTW_Bot: TTTW_Bot Anchors = [akTop, akRight] Images = ImageList1 ImageIndex = 4 - Position.X = 882.000000000000000000 + Position.X = 915.000000000000000000 TabOrder = 3 OnClick = frOBS1btnDeleteeChatClick end @@ -566,7 +622,7 @@ object TTW_Bot: TTTW_Bot Images = ImageList1 ImageIndex = 5 Position.X = 264.000000000000000000 - TabOrder = 8 + TabOrder = 11 end object btnCreateChat: TButton Images = ImageList1 @@ -603,7 +659,7 @@ object TTW_Bot: TTTW_Bot item end> TextSettings.Trimming = None - IsSelected = True + IsSelected = False ImageIndex = 24 Size.Width = 110.000000000000000000 Size.Height = 26.000000000000000000 @@ -615,7 +671,7 @@ object TTW_Bot: TTTW_Bot ExplicitSize.cy = 26.000000000000000000 inline frNotify1: TfrNotify Align = Client - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 Size.Height = 718.000000000000000000 Size.PlatformDefault = False inherited btnNotifyOpen: TButton @@ -697,7 +753,7 @@ object TTW_Bot: TTTW_Bot ExplicitSize.cy = 26.000000000000000000 inline frAutoActions1: TfrAutoActions Align = Client - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 Size.Height = 718.000000000000000000 Size.PlatformDefault = False inherited GroupBox20: TGroupBox @@ -850,20 +906,20 @@ object TTW_Bot: TTTW_Bot ExplicitSize.cy = 26.000000000000000000 inline frLog1: TfrLog Align = Client - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 Size.Height = 718.000000000000000000 Size.PlatformDefault = False inherited Panel1: TPanel - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 inherited btnClear: TButton Images = ImageList1 ImageIndex = 4 end end inherited sgLog: TStringGrid - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 Size.Height = 685.000000000000000000 - Viewport.Width = 970.000000000000000000 + Viewport.Width = 1003.000000000000000000 Viewport.Height = 685.000000000000000000 inherited StringColumn2: TStringColumn Size.Width = 170.000000000000000000 @@ -881,7 +937,7 @@ object TTW_Bot: TTTW_Bot object Panel1: TPanel Align = Bottom Position.Y = 744.000000000000000000 - Size.Width = 970.000000000000000000 + Size.Width = 1003.000000000000000000 Size.Height = 142.000000000000000000 Size.PlatformDefault = False TabOrder = 10 @@ -1004,7 +1060,7 @@ object TTW_Bot: TTTW_Bot end object Label1: TLabel Anchors = [akTop, akRight] - Position.X = 821.000000000000000000 + Position.X = 854.000000000000000000 Position.Y = 8.000000000000000000 Text = #1054#1090#1076#1077#1083#1100#1085#1086#1077' '#1089#1087#1072#1089#1080#1073#1086':' TabOrder = 12 @@ -1041,7 +1097,7 @@ object TTW_Bot: TTTW_Bot Anchors = [akTop, akRight] Images = ImageList1 ImageIndex = 11 - Position.X = 821.000000000000000000 + Position.X = 854.000000000000000000 Position.Y = 33.000000000000000000 Size.Width = 141.000000000000000000 Size.Height = 22.000000000000000000 @@ -1054,7 +1110,7 @@ object TTW_Bot: TTTW_Bot Anchors = [akTop, akRight] Images = ImageList1 ImageIndex = 11 - Position.X = 821.000000000000000000 + Position.X = 854.000000000000000000 Position.Y = 63.000000000000000000 Size.Width = 141.000000000000000000 Size.Height = 22.000000000000000000 @@ -1067,7 +1123,7 @@ object TTW_Bot: TTTW_Bot Anchors = [akTop, akRight] Images = ImageList1 ImageIndex = 11 - Position.X = 821.000000000000000000 + Position.X = 854.000000000000000000 Position.Y = 93.000000000000000000 Size.Width = 141.000000000000000000 Size.Height = 22.000000000000000000 diff --git a/forms/uGeneral.pas b/forms/uGeneral.pas index 6d91565..578a320 100644 --- a/forms/uGeneral.pas +++ b/forms/uGeneral.pas @@ -1,15 +1,15 @@ п»ї{ -получение доната -procedure TfrSettings.HandleWSDonate(aNick, aMessage, aSum: string); + получение доната + procedure TfrSettings.HandleWSDonate(aNick, aMessage, aSum: string); -получение сообщения -procedure TTTW_Bot.ttwIRCOnMessageRecord(aRecord: TTwitchChatMessage); + получение сообщения + procedure TTTW_Bot.ttwIRCOnMessageRecord(aRecord: TTwitchChatMessage); -получение событий -ttw_ES.OnFollow := frOBS1.toEventWebServer; -ttw_ES.OnSub := frOBS1.toEventWebServer; -ttw_ES.OnGift := frOBS1.toEventWebServer; -ttw_ES.OnRaid := frOBS1.toEventWebServer; + получение событий + ttw_ES.OnFollow := frOBS1.toEventWebServer; + ttw_ES.OnSub := frOBS1.toEventWebServer; + ttw_ES.OnGift := frOBS1.toEventWebServer; + ttw_ES.OnRaid := frOBS1.toEventWebServer; } unit uGeneral; @@ -26,7 +26,8 @@ uses System.Generics.Collections, utts, uGigaChat, uChatAPI, uMyTimer, uRecords, System.IOUtils, fCommands, uDataBase, FMX.Edit, FMX.Colors, FMX.SpinBox, windows, System.Skia, FMX.Skia, uCreateChat, uCreateNotify, fOBS, fTTS, - fPlayerWeb, uWebServerKandinsky, FMX.Memo.Types, FMX.ScrollBox, FMX.Memo; + fPlayerWeb, uWebServerKandinsky, FMX.Memo.Types, FMX.ScrollBox, FMX.Memo, + fRevards; type TTTW_Bot = class(TForm) @@ -73,6 +74,9 @@ type frPlayerWeb1: TfrPlayerWeb; frEvents1: TfrEvents; GroupBox2: TGroupBox; + cbHelloTTS: TCheckBox; + GroupBox3: TGroupBox; + frRevards1: TfrRevards; procedure cbThemeChange(Sender: TObject); procedure FormCreate(Sender: TObject); procedure SpeedButton1Click(Sender: TObject); @@ -117,6 +121,7 @@ type procedure ESError(aMsg: string); procedure ESStatus(Sender: TObject; const ConnectionEvent: String; StatusCode: Integer; const Description: String); + procedure ESOnSubOk(s: string); public { Public declarations } procedure toLog(aModule, aMethod, aMessage: string; aCode: Integer); @@ -134,7 +139,7 @@ var ttw_API: TTTW_API; userlist: TList; Kandinsky: TKandinsky_Web; - kePoints:TKE; + kePoints: TKE; implementation @@ -217,7 +222,7 @@ begin on E: Exception do begin toLog('uGeneral', 'ConnectProcedure.ttw_API.Init', E.Message, 2); - raise; + end; end; @@ -226,7 +231,14 @@ begin rid := ttw_API.getRoomAndBot; if rid = '' then raise Exception.Create('РќРµ удалось получить Room ID'); - + try + frRevards1.LoadCustomRevards; + except + on E: Exception do + begin + toLog('uGeneral', 'ConnectProcedure.LoadCustomRevards', E.Message, 2); + end; + end; // Загрузка СЌРјРѕРґР·Рё Рё бейджей try frOBS1.ChatBadges.Clear; @@ -246,7 +258,7 @@ begin on E: Exception do begin toLog('uGeneral', 'ConnectProcedure.Emotes', E.Message, 2); - raise; + end; end; @@ -262,10 +274,10 @@ begin // Назначение обработчиков событий // ttw_ES.OnMessage := fRewards.ESOnMessage; ttw_ES.OnError := ESError; - ttw_ES.OnGetCustomReward := frEvents1.ESOnGetCustomReward; + ttw_ES.OnGetCustomReward := frEvents1.ESOnGetCustomReward; ttw_ES.OnStatus := ESStatus; // ttw_ES.OnRAW := fRewards.ESOnRAW; - // ttw_ES.OnSubOk := fRewards.ESOnSubOk; + ttw_ES.OnSubOk := ESOnSubOk; ttw_ES.OnFollow := frOBS1.toEventWebServer; ttw_ES.OnSub := frOBS1.toEventWebServer; ttw_ES.OnGift := frOBS1.toEventWebServer; @@ -276,7 +288,7 @@ begin on E: Exception do begin toLog('uGeneral', 'ConnectProcedure.ttw_ES', E.Message, 2); - raise; + end; end; @@ -290,8 +302,7 @@ begin end; procedure TTTW_Bot.DisconnectProcedure; -var - I: Integer; + begin try toLog('DisconnectProcedure', 'Start', 'Начало процедуры отключения', 3); @@ -340,6 +351,11 @@ begin toLog('uGeneral', 'ESError', aMsg, 2); end; +procedure TTTW_Bot.ESOnSubOk(s: string); +begin + toLog('uGeneral', 'ESOnSubOk', s, 0); +end; + procedure TTTW_Bot.ESStatus(Sender: TObject; const ConnectionEvent: String; StatusCode: Integer; const Description: String); begin @@ -373,9 +389,7 @@ begin end; procedure TTTW_Bot.btnConnectingClick(Sender: TObject); -var - rid, tb, ts: string; - I: Integer; + begin if not ValidateInput then exit; @@ -489,17 +503,6 @@ begin ttw_API := TTTW_API.Create(Self); - if (frAI1.edtKandiKey.text <> '') and (frAI1.edtKandiSecret.text <> '') then - begin - try - Kandinsky := TKandinsky_Web.Create(frAI1.edtKandiKey.text, - frAI1.edtKandiSecret.text); - Kandinsky.ActiveServer(true); - toLog('uAI', 'FormCreate', 'Kandinsky Создан', 0); - finally - - end; - end; end; procedure TTTW_Bot.OnTTWStatus(ASender: TObject; const AStatus: TIdStatus; @@ -514,8 +517,9 @@ begin frOBS1.ChatEmotes.Free; frOBS1.ChatWebServers.Free; frOBS1.EventWebServers.Free; - frEvents1.CustomRewards.Free; -kePoints.Free; + frOBS1.KandinskyWebServers.Free; + frRevards1.CustomRewards.Free; + kePoints.Free; DisconnectProcedure; if Assigned(ttw_IRS) then ttw_IRS.Free; @@ -726,6 +730,10 @@ begin exit; end; + if (TTW_Bot.cbHelloTTS.IsChecked) and (aRecord.FirstMsg = 1) then + toSpeech('приветствую, ' + IfThen(aRecord.DisplayName <> '', + aRecord.DisplayName, aRecord.Username)); + firstWord := ExtractFirstWord(processedText); if IsCommand(firstWord) then begin @@ -1050,6 +1058,7 @@ procedure TTTW_Bot.ReadDB; end; frSettings1.Init; + end; // Загрузка РіСЂРёРґРѕРІ автоматических действий @@ -1084,9 +1093,20 @@ procedure TTTW_Bot.ReadDB; frOBS1.EventWebServers := TList.Create; for I := 0 to High(frOBS1.listNotify) do begin + frOBS1.CreateWebEvents(frOBS1.listNotify[I]); end; db.LoadRecordArray('listKandinsky', frOBS1.listKandinsky); + frOBS1.KandinskyWebServers := TList.Create; + if (frAI1.edtKandiKey.text <> '') and (frAI1.edtKandiSecret.text <> '') then + begin + for I := 0 to High(frOBS1.listKandinsky) do + begin + frOBS1.CreateWebKandinsky(frOBS1.listKandinsky[I]); + end; + + end; + frOBS1.UpdateGridFromArray; end; @@ -1095,11 +1115,11 @@ procedure TTTW_Bot.ReadDB; begin db.LoadRecordArray('ListEvents', frEvents1.ListEvents); frEvents1.UpdateGrid; + frRevards1.CustomRewards := TList.Create; - frEvents1.CustomRewards := Tlist.Create; - // frEvents1.LoadCustomRevards(); - frEvents1.CustomRewardEvents := Tlist.Create; - kePoints:=TKE.Create(frEvents1.edtParams, frEvents1.cbKey1,frEvents1.cbKey2,frEvents1.cbKey3); + frEvents1.CustomRewardEvents := TList.Create; + kePoints := TKE.Create(frEvents1.edtParams, frEvents1.cbKey1, + frEvents1.cbKey2, frEvents1.cbKey3); frTTS1.btnUpdateVoicesClick(Self); frTTS1.cbVoices.ItemIndex := strtoint(db.ReadSetting('cbVoices', '0')); frTTS1.cbOutput.ItemIndex := strtoint(db.ReadSetting('cbOutput', '0')); @@ -1107,14 +1127,15 @@ procedure TTTW_Bot.ReadDB; end; begin -LoadSkills; + LoadAISettings; + LoadSkills; LoadSettingsComponents; LoadGridsData; LoadGroupNames; LoadEncryptedConfig; LoadNotifySettings; - LoadAISettings; + LoadOBSGrids; LoadAutoActionsGrids; end; @@ -1558,11 +1579,14 @@ function TTTW_Bot.ResponsParserAIPic(inMess, aCommandText, aNick: string): string; var res: string; + I: Integer; begin res := inMess; if ContainsText(res, '[Kandinsky]') then begin - Kandinsky.generate(aCommandText, aNick); + for I := 0 to frOBS1.KandinskyWebServers.Count - 1 do + frOBS1.KandinskyWebServers[I].WebServerKandinsky.generate + (aCommandText, aNick); res := StringReplace(res, '[Kandinsky]', '', [rfReplaceAll]); end; Result := res; diff --git a/frames/fEvents.pas b/frames/fEvents.pas index 2717867..ce46e1e 100644 --- a/frames/fEvents.pas +++ b/frames/fEvents.pas @@ -7,7 +7,8 @@ uses System.Variants, System.Generics.Collections, ShellAPI, uSoundManager, FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, FMX.Edit, FMX.ListBox, FMX.Controls.Presentation, System.Rtti, FMX.Grid.Style, - FMX.ScrollBox, FMX.Grid, uRecords, uDataBase, FMX.Menus, uKeyEvent; + FMX.ScrollBox, FMX.Grid, uRecords, uDataBase, FMX.Menus, uKeyEvent, + fColorSettings, fFontSettings; type TfrEvents = class(TFrame) @@ -42,16 +43,13 @@ type procedure MenuItem1Click(Sender: TObject); procedure cbActionsChange(Sender: TObject); private - { Private declarations } - procedure toLog(aCode: integer; aMethod: string; aMess: string); + procedure toLog(aCode: integer; aMethod, aMess: string); + procedure ExecuteAction(const aAction: integer; const aParam, aUserInput, aUserName, aUserLogin: string); public - { Public declarations } ListEvents: TArray; - CustomRewards: Tlist; - CustomRewardEvents: Tlist; + CustomRewardEvents: TList; procedure UpdateGrid; - procedure LoadCustomRevards(); procedure ESOnGetCustomReward(CustomReward: TCustomRewardEvent); procedure OnDonate(aNick, aMessage, aSum: string); end; @@ -62,36 +60,40 @@ implementation uses uGeneral; +{ --- UI --- } + procedure TfrEvents.btnAddClick(Sender: TObject); var NewRec: TEventGlobal; begin - if (cbEventList.Text = '') or (cbActions.Text = '') then - exit; + if (cbEventList.ItemIndex < 0) or (cbActions.ItemIndex < 0) then + Exit; + NewRec.Event := cbEventList.ItemIndex; NewRec.Action := cbActions.ItemIndex; NewRec.Param := edtParams.Text; + if edtIF.Visible then - NewRec.Condition := edtIF.Text; - if cbRevards.Visible then + NewRec.Condition := edtIF.Text + else if cbRevards.Visible then NewRec.Condition := cbRevards.Text; - SetLength(ListEvents, Length(ListEvents) + 1); - ListEvents[High(ListEvents)] := NewRec; + ListEvents := ListEvents + [NewRec]; + DB.SaveRecordArray('ListEvents', ListEvents); UpdateGrid; end; procedure TfrEvents.btnDeleteClick(Sender: TObject); var - i, RowIndex: integer; + RowIndex: integer; begin RowIndex := sgEvents.Row; if (RowIndex < 0) or (RowIndex > High(ListEvents)) then - exit; - for i := RowIndex to High(ListEvents) - 1 do - ListEvents[i] := ListEvents[i + 1]; - SetLength(ListEvents, Length(ListEvents) - 1); + Exit; + + Delete(ListEvents, RowIndex, 1); + DB.SaveRecordArray('ListEvents', ListEvents); UpdateGrid; end; @@ -106,265 +108,172 @@ begin edtIF.Visible := cbEventList.ItemIndex = 0; cbRevards.Visible := cbEventList.ItemIndex = 1; Label2.Visible := cbEventList.ItemIndex <= 1; - end; -procedure TfrEvents.ESOnGetCustomReward(CustomReward: TCustomRewardEvent); +procedure TfrEvents.MenuItem1Click(Sender: TObject); +begin + if OpenDialog1.Execute and (PopupMenu1.PopupComponent is TEdit) then + TEdit(PopupMenu1.PopupComponent).Text := OpenDialog1.FileName; +end; + +{ --- Общая логика --- } + +procedure TfrEvents.ExecuteAction(const aAction: integer; const aParam, aUserInput, aUserName, aUserLogin: string); var - i, i2: integer; - req, s: string; - hr: TCustomRewardEvent; sm: TSongMachine; - myAction: integer; + f: TfrColorSettings; + t: TfrFontSettings; + i, j: Integer; + notify: TOBSNotify; + se: TStyleEvent; begin sm := TSongMachine.Create; try - toLog(3, 'ESOnGetCustomReward', 'Начало обработки награды: ' + - CustomReward.Event.revard.Title); - s := '[' + CustomReward.Event.user_name + - '] купил за баллы канала награду "' + - CustomReward.Event.revard.Title + '" '; - if CustomReward.Event.user_input <> '' then - begin - toLog(0, 'ESOnGetCustomReward', 'Пользовательский ввод: ' + - CustomReward.Event.user_input); - s := s + ' и передал строку ' + CustomReward.Event.user_input - end; + case aAction of + 0: begin // Нажать кнопку + toLog(0, 'ExecuteAction', 'Симуляция нажатия: ' + aParam); + kePoints.SimulateKeyPress(aParam, 500); + end; + 1: begin // Воспроизведение звука + toLog(0, 'ExecuteAction', 'Воспроизведение звука: ' + aParam); + sm.PlayPublic(aParam, '100'); + end; + 2: begin // Kandinsky + toLog(0, 'ExecuteAction', 'Генерация Kandinsky для: ' + aUserInput); + Kandinsky.generate(aUserInput, aUserLogin); + end; + 3: begin // OBS Notify + f := TfrColorSettings.Create(Self); + t := TfrFontSettings.Create(Self); + try + for i := 0 to High(TTW_Bot.frOBS1.listNotify) do + if TTW_Bot.frOBS1.listNotify[i].TypeEvent = 5 then + begin + notify := TTW_Bot.frOBS1.listNotify[i]; + se.Title := StringReplace(notify.HeaderText, '[NICK]', aUserName, [rfReplaceAll]); + se.Context := notify.MessText; + se.Url := notify.Picture; + se.SoundURL := notify.Sound; + se.Timestamp := Now; + se.TimeMsg := notify.TimeMess; + se.BorderColor := notify.ColorBorder; + se.BorderSize := notify.SolidBorder; + se.BlockColor := notify.ColorBlock; + se.FontTitle.Font := notify.HeaderStyleFont; + se.FontTitle.Size := notify.HeaderSizeFont; + se.FontTitle.Color := notify.HeaderColorFont; + se.FontContext.Font := notify.MessStyleFont; + se.FontContext.Size := notify.MessSizeFont; + se.FontContext.Color := notify.MessColorFont; + se.RequireInteraction := True; - for i := 0 to high(ListEvents) do - begin - if ListEvents[i].Event <> 1 then - continue; - if ListEvents[i].Condition = CustomReward.Event.revard.Title then - begin - myAction := ListEvents[i].Action; - - { - 0 Нажать нкопку на клавиатуре - 1 Проиграть звук - 2 Kandinsky - 3 Запустить Web Event - 4 Написать в чат - 5 Запустить программу - - } - case myAction of - 0: - begin // нажать кнопку - toLog(0, 'ESOnGetCustomReward', 'Симуляция нажатия: ' + - ListEvents[i].Param); - kePoints.SimulateKeyPress(ListEvents[i].Param, 500); - end; - 1: - begin // воспроизведение звука - toLog(0, 'ESOnGetCustomReward', 'Воспроизведение звука: ' + - ListEvents[i].Param); - sm.PlayPublic(ListEvents[i].Param, '100'); - end; - 2: - begin // Kandinsky - toLog(0, 'ESOnGetCustomReward', 'Генерация Kandinsky для: ' + - CustomReward.Event.user_input); - Kandinsky.generate(CustomReward.Event.user_input, - CustomReward.Event.user_login); - end; - 4: - begin // Написать в чат - - toLog(0, 'ESOnGetCustomReward', 'Написать в чат: ' + - CustomReward.Event.user_input); - end; - 5: - begin // запуск файла - toLog(0, 'ESOnGetCustomReward', 'Запуск файла: ' + ListEvents - [i].Param); - ShellExecute(0, 'open', pwidechar(ListEvents[i].Param), - nil, nil, 0); - end; - end; - end; + for j := 0 to TTW_Bot.frOBS1.EventWebServers.Count - 1 do + TTW_Bot.frOBS1.EventWebServers[j].WebServerChat.AddMessage(se); + end; + finally + f.Free; + t.Free; + end; + end; + 4: toLog(0, 'ExecuteAction', 'Написать в чат: ' + aUserInput); + 5: begin // Запуск файла + toLog(0, 'ExecuteAction', 'Запуск файла: ' + aParam); + ShellExecute(0, 'open', PWideChar(aParam), nil, nil, 0); + end; end; finally sm.Free; end; end; -procedure TfrEvents.LoadCustomRevards(); +procedure TfrEvents.ESOnGetCustomReward(CustomReward: TCustomRewardEvent); var - cr: TCustomRevards; + ev: TEventGlobal; begin - CustomRewards.Clear; - cbRevards.Items.Clear; - TTW_Bot.toLog('fEvents', 'LoadCustomRevards', 'Запрос наград с сервера', 3); - ttw_API.getCustomReward(CustomRewards); - for cr in CustomRewards do - begin - cbRevards.Items.Add(cr.Title); - end; -end; + toLog(3, 'ESOnGetCustomReward', 'Начало обработки награды: ' + CustomReward.Event.revard.Title); -procedure TfrEvents.MenuItem1Click(Sender: TObject); -begin - if OpenDialog1.Execute then - TEdit(PopupMenu1.PopupComponent).Text := OpenDialog1.FileName; + for ev in ListEvents do + if (ev.Event = 1) and (ev.Condition = CustomReward.Event.revard.Title) then + ExecuteAction(ev.Action, ev.Param, CustomReward.Event.user_input, CustomReward.Event.user_name, CustomReward.Event.user_login); end; procedure TfrEvents.OnDonate(aNick, aMessage, aSum: string); var - i, i2: integer; - req, s: string; - hr: TCustomRewardEvent; - sm: TSongMachine; - myAction: integer; - - j: integer; - aSumInt: integer; - BestRow: integer; - BestPriority: integer; - BestValue: integer; + i, aSumInt, BestRow, BestPriority, BestValue, + CurrentPriority, CurrentValue, MinVal, MaxVal: integer; Condition: string; - CurrentPriority: integer; - CurrentValue: integer; - MinVal, MaxVal: integer; - Parts: tstringlist; - se: TStyleEvent; - notify: TEventGlobal; - + Parts: TStringList; begin - aSumInt := StrToIntDef(aSum, 0); BestRow := -1; BestPriority := -1; BestValue := 0; - for i := 0 to high(ListEvents) do + for i := 0 to High(ListEvents) do begin - if ListEvents[i].Event = 0 then + if ListEvents[i].Event <> 0 then + Continue; + + Condition := ListEvents[i].Condition; + CurrentPriority := -1; + CurrentValue := 0; + + if TryStrToInt(Condition, CurrentValue) then begin - Condition := ListEvents[i].Condition; - CurrentPriority := -1; - CurrentValue := 0; - - // Проверка на точное значение - if Pos('-', Condition) = 0 then - begin - if Pos('>', Condition) = 0 then + if aSumInt = CurrentValue then + CurrentPriority := 4; + end + else if Pos('-', Condition) > 0 then + begin + Parts := TStringList.Create; + try + Parts.Delimiter := '-'; + Parts.StrictDelimiter := True; + Parts.DelimitedText := Condition; + if Parts.Count = 2 then begin - if Pos('<', Condition) = 0 then + MinVal := StrToIntDef(Trim(Parts[0]), 0); + MaxVal := StrToIntDef(Trim(Parts[1]), 0); + if (aSumInt >= MinVal) and (aSumInt <= MaxVal) then begin - // Точное значение - CurrentValue := StrToIntDef(Condition, -1); - if aSumInt = CurrentValue then - CurrentPriority := 4; + CurrentPriority := 3; + CurrentValue := MinVal; end; end; + finally + Parts.Free; end; - - if CurrentPriority = -1 then - begin - if Pos('-', Condition) > 0 then - begin - // Диапазон - Parts := tstringlist.Create; - try - Parts.Delimiter := '-'; - Parts.StrictDelimiter := True; - Parts.DelimitedText := Condition; - if Parts.Count = 2 then - begin - MinVal := StrToIntDef(Trim(Parts[0]), 0); - MaxVal := StrToIntDef(Trim(Parts[1]), 0); - if (aSumInt >= MinVal) and (aSumInt <= MaxVal) then - begin - CurrentPriority := 3; - CurrentValue := MinVal; // Приоритет по MinVal - end; - end; - finally - Parts.Free; - end; - end - else if Pos('>', Condition) > 0 then - begin - // Условие ">X" - CurrentValue := - StrToIntDef(Trim(StringReplace(Condition, '>', '', - [rfReplaceAll])), 0); - if aSumInt >= CurrentValue then - CurrentPriority := 2; - end - else if Pos('<', Condition) > 0 then - begin - // Условие " -1 then - begin - // Определение наилучшего условия - if (CurrentPriority > BestPriority) or (CurrentPriority = BestPriority) - and ((CurrentPriority = 3) and (CurrentValue > BestValue) or - (CurrentPriority = 2) and (CurrentValue > BestValue) or - (CurrentPriority = 1) and (CurrentValue < BestValue)) then - begin - BestPriority := CurrentPriority; - BestValue := CurrentValue; - BestRow := i; - notify := ListEvents[i]; - end; - end; - if BestRow = -1 then - Break; - - end; - end; - if BestRow = -1 then - exit; - sm := TSongMachine.Create; - try - myAction := ListEvents[i].Action; - case myAction of - 0: - begin // нажать кнопку - toLog(0, 'OnDonate', 'Симуляция нажатия: ' + ListEvents[i].Param); - kePoints.SimulateKeyPress(ListEvents[i].Param, 500); - end; - 1: - begin // воспроизведение звука - toLog(0, 'OnDonate', 'Воспроизведение звука: ' + ListEvents[i].Param); - sm.PlayPublic(ListEvents[i].Param, '100'); - end; - 2: - begin // Kandinsky - toLog(0, 'OnDonate', 'Генерация Kandinsky для: ' + aNick); - Kandinsky.generate(aMessage, aNick); - end; - 4: - begin // Написать в чат - - toLog(0, 'OnDonate', 'Написать в чат: ' + aNick); - end; - 5: - begin // запуск файла - toLog(0, 'OnDonate', 'Запуск файла: ' + ListEvents[i].Param); - ShellExecute(0, 'open', pwidechar(ListEvents[i].Param), nil, nil, 0); - end; + end + else if (Condition.StartsWith('>')) then + begin + CurrentValue := StrToIntDef(Copy(Condition, 2), 0); + if aSumInt >= CurrentValue then + CurrentPriority := 2; + end + else if (Condition.StartsWith('<')) then + begin + CurrentValue := StrToIntDef(Copy(Condition, 2), 0); + if aSumInt <= CurrentValue then + CurrentPriority := 1; end; - finally - sm.Free; + if (CurrentPriority <> -1) and + ((CurrentPriority > BestPriority) or + ((CurrentPriority = BestPriority) and + (((CurrentPriority in [2,3]) and (CurrentValue > BestValue)) or + ((CurrentPriority = 1) and (CurrentValue < BestValue))))) then + begin + BestPriority := CurrentPriority; + BestValue := CurrentValue; + BestRow := i; + end; end; + + if BestRow <> -1 then + ExecuteAction(ListEvents[BestRow].Action, ListEvents[BestRow].Param, aMessage, aNick, aNick); end; -procedure TfrEvents.toLog(aCode: integer; aMethod, aMess: string); -begin - TTW_Bot.toLog('fEvents', aMethod, aMess, aCode); -end; + procedure TfrEvents.UpdateGrid; var @@ -372,11 +281,9 @@ var begin sgEvents.BeginUpdate; try - sgEvents.RowCount := 0; // Сбрасываем строки (оставляем только заголовки) - + sgEvents.RowCount := Length(ListEvents); for i := 0 to High(ListEvents) do begin - sgEvents.RowCount := i + 1; sgEvents.Cells[0, i] := cbEventList.Items[ListEvents[i].Event]; sgEvents.Cells[1, i] := ListEvents[i].Condition; sgEvents.Cells[2, i] := cbActions.Items[ListEvents[i].Action]; @@ -387,4 +294,10 @@ begin end; end; +procedure TfrEvents.toLog(aCode: integer; aMethod, aMess: string); +begin + TTW_Bot.toLog('fEvents', aMethod, aMess, aCode); +end; + end. + diff --git a/frames/fOBS.fmx b/frames/fOBS.fmx index 56c193e..f934fdc 100644 --- a/frames/fOBS.fmx +++ b/frames/fOBS.fmx @@ -14,8 +14,8 @@ object frOBS: TfrOBS RowCount = 0 Options = [ColumnResize, ColumnMove, ColLines, RowLines, Tabs, Header, HeaderClick, AutoDisplacement] OnCellDblClick = sgWebChatsCellDblClick - Viewport.Width = 685.000000000000000000 - Viewport.Height = 164.000000000000000000 + Viewport.Width = 689.000000000000000000 + Viewport.Height = 189.000000000000000000 object IntegerColumn1: TIntegerColumn Header = #1055#1086#1088#1090 HeaderSettings.TextSettings.WordWrap = False diff --git a/frames/fOBS.pas b/frames/fOBS.pas index 89c4d87..3939901 100644 --- a/frames/fOBS.pas +++ b/frames/fOBS.pas @@ -5,11 +5,12 @@ interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, uCustomEmoties, System.Variants, uWebServerChat, uWebServerEvents, fColorSettings, - System.Generics.Collections, + fFontSettings, + System.Generics.Collections, uWebServerKandinsky, FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, System.Rtti, FMX.Grid.Style, FMX.Grid, FMX.ScrollBox, FMX.Edit, FMX.Colors, FMX.ListBox, FMX.EditBox, FMX.SpinBox, FMX.Controls.Presentation, uRecords, - System.Generics.Defaults, fFontSettings, System.Character; + System.Generics.Defaults, System.Character; type TChatWebServers = record @@ -31,10 +32,17 @@ type type TEventWebServers = record port: integer; + typeEvent: integer; se: TStyleEvent; WebServerChat: TTTW_Events; end; +type + TKandinskyWebServers = record + port: integer; + WebServerKandinsky: TKandinsky_Web; + end; + type TfrOBS = class(TFrame) sgWebChats: TStringGrid; @@ -71,11 +79,12 @@ type ChatEmotes: Tlist; ChatWebServers: Tlist; EventWebServers: Tlist; + KandinskyWebServers: Tlist; procedure MsgToWebServer(const aRecord: TTwitchChatMessage); - procedure toEventWebServer(CustomReward: TFollowEvent); overload; // follow - procedure toEventWebServer(CustomReward: TSubEvent); overload; // sub - procedure toEventWebServer(CustomReward: TRaidEvent); overload; // raid - procedure toEventWebServer(CustomReward: TGiftEvent); overload; // gift + procedure toEventWebServer(aEvent: TFollowEvent); overload; // follow + procedure toEventWebServer(aEvent: TSubEvent); overload; // sub + procedure toEventWebServer(aEvent: TRaidEvent); overload; // raid + procedure toEventWebServer(aEvent: TGiftEvent); overload; // gift procedure toEventWebServer(aNick, aSum, aText: string); overload; // donate procedure CreateWebEvents(eventsSettings: TOBSNotify); @@ -91,7 +100,7 @@ type procedure AddKandinsky(newRecord: TOBSKandinsky); procedure DelKandinsky(aPort: integer); - + procedure CreateWebKandinsky(aRecord: TOBSKandinsky); end; implementation @@ -290,6 +299,7 @@ begin SetLength(listChats, Length(listChats) + 1); listChats[High(listChats)] := newRecord; UpdateGridFromArray; + db.SaveRecordArray('listChats', listChats); CreateWebChat(newRecord); end; @@ -300,6 +310,7 @@ begin listKandinsky[High(listKandinsky)] := newRecord; UpdateGridFromArray; db.SaveRecordArray('listKandinsky', listKandinsky); + CreateWebKandinsky(newRecord); end; procedure TfrOBS.AddNotify(newRecord: TOBSNotify); @@ -308,7 +319,7 @@ begin listNotify[High(listNotify)] := newRecord; UpdateGridFromArray; db.SaveRecordArray('listNotify', listNotify); - CreateWebEvents(newRecord); + CreateWebEvents(newRecord); end; procedure TfrOBS.btnCreateOBSChatClick(Sender: TObject); @@ -383,12 +394,10 @@ var procedure LoadFontList(const mySL: tstringlist); var SearchRec: TSearchRec; - n: integer; begin if not DirectoryExists(myConst.fontsPath) then CreateDir(myConst.fontsPath); - n := 1; if FindFirst(IncludeTrailingPathDelimiter(myConst.fontsPath) + '*.*', faArchive, SearchRec) = 0 then try @@ -396,7 +405,6 @@ var if (SearchRec.Attr and faAnyFile) = SearchRec.Attr then begin mySL.Add(SearchRec.name); - Inc(n); end; until FindNext(SearchRec) <> 0; finally @@ -448,12 +456,9 @@ var procedure LoadFontList(const mySL: tstringlist); var SearchRec: TSearchRec; - n: integer; begin if not DirectoryExists(myConst.fontsPath) then CreateDir(myConst.fontsPath); - - n := 1; if FindFirst(IncludeTrailingPathDelimiter(myConst.fontsPath) + '*.*', faArchive, SearchRec) = 0 then try @@ -461,7 +466,6 @@ var if (SearchRec.Attr and faAnyFile) = SearchRec.Attr then begin mySL.Add(SearchRec.name); - Inc(n); end; until FindNext(SearchRec) <> 0; finally @@ -470,24 +474,37 @@ var end; function GetColorFromColorPanel(aColor: TAlphaColor): string; -var - Color: TAlphaColor; - r, G, B: Byte; - A: Real; - FS: TFormatSettings; -begin - Color := aColor; - r := TAlphaColorRec(Color).r; - G := TAlphaColorRec(Color).G; - B := TAlphaColorRec(Color).B; - A := TAlphaColorRec(Color).A / 255; // Преобразуем альфа-канал в диапазон 0..1 + var + Color: TAlphaColor; + r, G, B: Byte; + A: Real; + FS: TFormatSettings; + begin + Color := aColor; + r := TAlphaColorRec(Color).r; + G := TAlphaColorRec(Color).G; + B := TAlphaColorRec(Color).B; + A := TAlphaColorRec(Color).A / 255; + // Преобразуем альфа-канал в диапазон 0..1 - // Устанавливаем точку в качестве десятичного разделителя - FS := TFormatSettings.Create; - FS.DecimalSeparator := '.'; + // Устанавливаем точку в качестве десятичного разделителя + FS := TFormatSettings.Create; + FS.DecimalSeparator := '.'; - result := Format('rgba(%d, %d, %d, %.2f)', [r, G, B, A], FS); -end; + result := Format('rgba(%d, %d, %d, %.2f)', [r, G, B, A], FS); + end; + + function GetColorFromCCB(aColor: TAlphaColor): string; + var + Color: TAlphaColor; + r, G, B: Byte; + begin + Color := aColor; + r := TAlphaColorRec(Color).r; + G := TAlphaColorRec(Color).G; + B := TAlphaColorRec(Color).B; + result := Format('#%.2X%.2X%.2X', [r, G, B]); + end; begin fonts := tstringlist.Create; @@ -495,25 +512,25 @@ begin t := TfrFontSettings.Create(self); try LoadFontList(fonts); - EventWebServer.WebServerChat := TTTW_Events.Create(fonts,eventsSettings.port); + EventWebServer.WebServerChat := TTTW_Events.Create(fonts, + eventsSettings.port); EventWebServer.port := eventsSettings.port; - - EventWebServer.se.title := eventsSettings.HeaderText; - EventWebServer.se.Context:=eventsSettings.MessText; - EventWebServer.se.Url:=eventsSettings.Picture; - EventWebServer.se.SoundURL:=eventsSettings.Sound; - EventWebServer.se.Timestamp:=now; - EventWebServer.se.TimeMsg:=eventsSettings.TimeMess; - EventWebServer.se.FontTitle.Font:= t.cbFontStyleDefault.Items[eventsSettings.HeaderStyleFont]; - EventWebServer.se.FontTitle.Size:=eventsSettings.HeaderSizeFont; - EventWebServer.se.FontTitle.Color:=t.ccbFontColor.Items[eventsSettings.HeaderColorFont]; - EventWebServer.se.FontContext.Font:= t.cbFontStyleDefault.Items[eventsSettings.MessStyleFont]; - EventWebServer.se.FontContext.Size:=eventsSettings.MessSizeFont; - EventWebServer.se.FontContext.Color:=t.ccbFontColor.Items[eventsSettings.MessColorFont]; - EventWebServer.se.BorderColor:=f.ccbStyleBorderColor.Items[eventsSettings.ColorBorder]; - EventWebServer.se.BorderSize:=eventsSettings.SolidBorder; - EventWebServer.se.BlockColor:=GetColorFromColorPanel(f.cpStyleBlockColor.Color); - + EventWebServer.typeEvent := eventsSettings.typeEvent; + EventWebServer.se.Title := eventsSettings.HeaderText; + EventWebServer.se.Context := eventsSettings.MessText; + EventWebServer.se.Url := eventsSettings.Picture; + EventWebServer.se.SoundURL := eventsSettings.Sound; + EventWebServer.se.Timestamp := now; + EventWebServer.se.TimeMsg := eventsSettings.TimeMess; + EventWebServer.se.FontTitle.Font := eventsSettings.HeaderStyleFont; + EventWebServer.se.FontTitle.Size := eventsSettings.HeaderSizeFont; + EventWebServer.se.FontTitle.Color := eventsSettings.HeaderColorFont; + EventWebServer.se.FontContext.Font := eventsSettings.MessStyleFont; + EventWebServer.se.FontContext.Size := eventsSettings.MessSizeFont; + EventWebServer.se.FontContext.Color :=eventsSettings.MessColorFont; + EventWebServer.se.BorderColor := eventsSettings.ColorBorder; + EventWebServer.se.BorderSize := eventsSettings.SolidBorder; + EventWebServer.se.BlockColor := eventsSettings.ColorBlock; EventWebServers.Add(EventWebServer); EventWebServers[EventWebServers.Count - 1].WebServerChat.ActiveServer(True); finally @@ -523,6 +540,20 @@ begin end; end; +procedure TfrOBS.CreateWebKandinsky(aRecord: TOBSKandinsky); +var + KandinskyWebServer: TKandinskyWebServers; +begin + KandinskyWebServer.port := aRecord.port; + KandinskyWebServer.WebServerKandinsky := + TKandinsky_Web.Create(TTW_Bot.frAI1.edtKandiKey.text, + TTW_Bot.frAI1.edtKandiSecret.text, aRecord.port); + KandinskyWebServers.Add(KandinskyWebServer); + KandinskyWebServers[KandinskyWebServers.Count - 1] + .WebServerKandinsky.ActiveServer(True); + +end; + procedure TfrOBS.DelChat(aPort: integer); var i, j: integer; @@ -566,6 +597,9 @@ begin Break; end; end; + KandinskyWebServers[i].WebServerKandinsky.ActiveServer(false); + KandinskyWebServers[i].WebServerKandinsky.Destroy; + KandinskyWebServers.Delete(i); UpdateGridFromArray; db.SaveRecordArray('listKandinsky', listKandinsky); end; @@ -588,7 +622,9 @@ begin Break; end; end; - + EventWebServers[i].WebServerChat.ActiveServer(false); + EventWebServers[i].WebServerChat.Destroy; + EventWebServers.Delete(i); UpdateGridFromArray; db.SaveRecordArray('listNotify', listNotify); end; @@ -654,12 +690,36 @@ end; procedure TfrOBS.EdtNotify(newRecord: TOBSNotify; oldPort: integer); var - i: integer; + i,mi: integer; ws:TEventWebServers; begin +for I := 0 to EventWebServers.Count - 1 do + if EventWebServers[i].port = oldPort then + begin + ws:=EventWebServers[i]; + mi:=i; + end; + for i := 0 to High(listNotify) do if listNotify[i].port = oldPort then begin listNotify[i] := newRecord; + ws.port:=listNotify[i].port; + ws.typeEvent:=listNotify[i].TypeEvent; + ws.se.title:=listNotify[i].HeaderText; + ws.se.Context:=listNotify[i].MessText; + ws.se.Url:=listNotify[i].Picture; + ws.se.SoundURL:=listNotify[i].Sound; + ws.se.TimeMsg:=listNotify[i].TimeMess; + ws.se.FontTitle.Font:=listNotify[i].HeaderStyleFont; + ws.se.FontTitle.Font := listNotify[i].HeaderStyleFont; + ws.se.FontTitle.Size := listNotify[i].HeaderSizeFont; + ws.se.FontTitle.Color := listNotify[i].HeaderColorFont; + ws.se.FontContext.Font := listNotify[i].MessStyleFont; + ws.se.FontContext.Size := listNotify[i].MessSizeFont; + ws.se.FontContext.Color := listNotify[i].MessColorFont; + ws.se.BorderColor :=listNotify[i].ColorBorder; + ws.se.BorderSize := listNotify[i].SolidBorder; + ws.se.BlockColor := listNotify[i].ColorBlock; UpdateGridFromArray; db.SaveRecordArray('listNotify', listNotify); Break; @@ -716,342 +776,105 @@ begin end; end; -procedure TfrOBS.toEventWebServer(CustomReward: TFollowEvent); +{ + 0 Отслеживание + 1 Подписка + 2 Подарочная подписка + 3 Рейд + 4 Донат + 5 Свое + +} + +procedure TfrOBS.toEventWebServer(aEvent: TFollowEvent); var - se: TStyleEvent; - i, j: integer; - f: TfrColorSettings; - t: TfrFontSettings; - notify: TOBSNotify; + i: integer; + ws: TEventWebServers; begin - f := TfrColorSettings.Create(self); - t := TfrFontSettings.Create(self); - try - for i := 0 to high(listNotify) do + TTW_Bot.toLog('fOBS', 'toEventWebServer', 'Получено событие Follow', 0); + for i := 0 to EventWebServers.Count - 1 do + begin + if EventWebServers[i].typeEvent = 0 then begin - if listNotify[i].TypeEvent = 0 then - begin - notify := listNotify[i]; - se.Title := notify.HeaderText; - se.Title := StringReplace(se.Title, '[NICK]', - CustomReward.event.user_name, [rfReplaceAll]); - se.Context := notify.MessText; - se.Url := notify.Picture; - se.SoundURL := notify.Sound; - se.Timestamp := Now; - se.TimeMsg := notify.TimeMess; - se.BorderColor := f.ccbStyleBorderColor.Items[notify.ColorBorder]; - se.BorderSize := notify.SolidBorder; - se.BlockColor := notify.ColorBlock; - se.FontTitle.Font := t.cbFontStyleDefault.Items[notify.HeaderStyleFont]; - se.FontTitle.Size := notify.HeaderSizeFont; - se.FontTitle.Color := t.ccbFontColor.Items[notify.HeaderColorFont]; - se.FontContext.Font := t.cbFontStyleDefault.Items[notify.MessSizeFont]; - se.FontContext.Size := notify.MessSizeFont; - se.FontContext.Color := t.ccbFontColor.Items[notify.MessColorFont]; - se.RequireInteraction := True; - for j := 0 to EventWebServers.Count - 1 do - begin - EventWebServers[j].WebServerChat.AddMessage(se); - end; - end; - + ws := EventWebServers[i]; + ws.se.Title := StringReplace(ws.se.Title, '[NICK]', + aEvent.event.user_name, [rfReplaceAll]); + ws.se.Timestamp:=now; + ws.se.RequireInteraction := True; + TTW_Bot.toLog('fOBS', 'toEventWebServer.BlockColor', ws.se.BlockColor, 3); + EventWebServers[i].WebServerChat.AddMessage(ws.se); end; - - finally - f.Free; - t.Free; end; end; -procedure TfrOBS.toEventWebServer(CustomReward: TSubEvent); +procedure TfrOBS.toEventWebServer(aEvent: TSubEvent); var - se: TStyleEvent; - i, j: integer; - f: TfrColorSettings; - t: TfrFontSettings; - notify: TOBSNotify; + i: integer; + ws: TEventWebServers; begin - f := TfrColorSettings.Create(self); - t := TfrFontSettings.Create(self); - try - for i := 0 to high(listNotify) do - begin - if listNotify[i].TypeEvent = 1 then - begin - notify := listNotify[i]; - se.Title := notify.HeaderText; - se.Title := StringReplace(se.Title, '[NICK]', - CustomReward.event.user_name, [rfReplaceAll]); - se.Context := notify.MessText; - - se.Url := notify.Picture; - se.SoundURL := notify.Sound; - se.Timestamp := Now; - se.TimeMsg := notify.TimeMess; - se.BorderColor := f.ccbStyleBorderColor.Items[notify.ColorBorder]; - se.BorderSize := notify.SolidBorder; - se.BlockColor := notify.ColorBlock; - se.FontTitle.Font := t.cbFontStyleDefault.Items[notify.HeaderStyleFont]; - se.FontTitle.Size := notify.HeaderSizeFont; - se.FontTitle.Color := t.ccbFontColor.Items[notify.HeaderColorFont]; - se.FontContext.Font := t.cbFontStyleDefault.Items[notify.MessSizeFont]; - se.FontContext.Size := notify.MessSizeFont; - se.FontContext.Color := t.ccbFontColor.Items[notify.MessColorFont]; - se.RequireInteraction := True; - for j := 0 to EventWebServers.Count - 1 do - begin - EventWebServers[j].WebServerChat.AddMessage(se); - end; - end; - - end; - - finally - f.Free; - t.Free; + for i := 0 to EventWebServers.Count - 1 do + begin + if EventWebServers[i].typeEvent <> 1 then + Continue; + ws := EventWebServers[i]; + ws.se.Title := StringReplace(ws.se.Title, '[NICK]', aEvent.event.user_name, + [rfReplaceAll]); + EventWebServers[i] := ws; + EventWebServers[i].WebServerChat.AddMessage(EventWebServers[i].se); end; end; -procedure TfrOBS.toEventWebServer(CustomReward: TRaidEvent); +procedure TfrOBS.toEventWebServer(aEvent: TRaidEvent); var - se: TStyleEvent; - i, j: integer; - f: TfrColorSettings; - t: TfrFontSettings; - notify: TOBSNotify; + i: integer; + ws: TEventWebServers; begin - f := TfrColorSettings.Create(self); - t := TfrFontSettings.Create(self); - try - for i := 0 to high(listNotify) do - begin - if listNotify[i].TypeEvent = 3 then - begin - notify := listNotify[i]; - se.Title := notify.HeaderText; - se.Title := StringReplace(se.Title, '[NICK]', - CustomReward.event.from_broadcaster_user_name, [rfReplaceAll]); - se.Context := notify.MessText; - se.Context := StringReplace(se.Context, '[SUM]', - inttostr(CustomReward.event.viewers), [rfReplaceAll]); - se.Url := notify.Picture; - se.SoundURL := notify.Sound; - se.Timestamp := Now; - se.TimeMsg := notify.TimeMess; - se.BorderColor := f.ccbStyleBorderColor.Items[notify.ColorBorder]; - se.BorderSize := notify.SolidBorder; - se.BlockColor := notify.ColorBlock; - se.FontTitle.Font := t.cbFontStyleDefault.Items[notify.HeaderStyleFont]; - se.FontTitle.Size := notify.HeaderSizeFont; - se.FontTitle.Color := t.ccbFontColor.Items[notify.HeaderColorFont]; - se.FontContext.Font := t.cbFontStyleDefault.Items[notify.MessSizeFont]; - se.FontContext.Size := notify.MessSizeFont; - se.FontContext.Color := t.ccbFontColor.Items[notify.MessColorFont]; - se.RequireInteraction := True; - for j := 0 to EventWebServers.Count - 1 do - begin - EventWebServers[j].WebServerChat.AddMessage(se); - end; - end; - - end; - - finally - f.Free; - t.Free; + for i := 0 to EventWebServers.Count - 1 do + begin + if EventWebServers[i].typeEvent <> 3 then + Continue; + ws := EventWebServers[i]; + ws.se.Title := StringReplace(ws.se.Title, '[NICK]', + aEvent.event.from_broadcaster_user_name, [rfReplaceAll]); + ws.se.Context := StringReplace(ws.se.Context, '[SUM]', + inttostr(aEvent.event.viewers), [rfReplaceAll]); + EventWebServers[i] := ws; + EventWebServers[i].WebServerChat.AddMessage(EventWebServers[i].se); end; end; -procedure TfrOBS.toEventWebServer(CustomReward: TGiftEvent); +procedure TfrOBS.toEventWebServer(aEvent: TGiftEvent); var - se: TStyleEvent; - i, j: integer; - f: TfrColorSettings; - t: TfrFontSettings; - notify: TOBSNotify; + i: integer; + ws: TEventWebServers; begin - f := TfrColorSettings.Create(self); - t := TfrFontSettings.Create(self); - try - for i := 0 to high(listNotify) do - begin - if listNotify[i].TypeEvent = 2 then - begin - notify := listNotify[i]; - se.Title := notify.HeaderText; - se.Title := StringReplace(se.Title, '[NICK]', - CustomReward.event.user_name, [rfReplaceAll]); - se.Context := notify.MessText; - se.Url := notify.Picture; - se.SoundURL := notify.Sound; - se.Timestamp := Now; - se.TimeMsg := notify.TimeMess; - se.BorderColor := f.ccbStyleBorderColor.Items[notify.ColorBorder]; - se.BorderSize := notify.SolidBorder; - se.BlockColor := notify.ColorBlock; - se.FontTitle.Font := t.cbFontStyleDefault.Items[notify.HeaderStyleFont]; - se.FontTitle.Size := notify.HeaderSizeFont; - se.FontTitle.Color := t.ccbFontColor.Items[notify.HeaderColorFont]; - se.FontContext.Font := t.cbFontStyleDefault.Items[notify.MessSizeFont]; - se.FontContext.Size := notify.MessSizeFont; - se.FontContext.Color := t.ccbFontColor.Items[notify.MessColorFont]; - se.RequireInteraction := True; - for j := 0 to EventWebServers.Count - 1 do - begin - EventWebServers[j].WebServerChat.AddMessage(se); - end; - end; - - end; - - finally - f.Free; - t.Free; + for i := 0 to EventWebServers.Count - 1 do + begin + if EventWebServers[i].typeEvent <> 2 then + Continue; + ws := EventWebServers[i]; + ws.se.Title := StringReplace(ws.se.Title, '[NICK]', aEvent.event.user_name, + [rfReplaceAll]); + EventWebServers[i] := ws; + EventWebServers[i].WebServerChat.AddMessage(EventWebServers[i].se); end; - end; procedure TfrOBS.toEventWebServer(aNick, aSum, aText: string); var - i, j: integer; - aSumInt: integer; - BestRow: integer; - BestPriority: integer; - BestValue: integer; - Condition: string; - CurrentPriority: integer; - CurrentValue: integer; - MinVal, MaxVal: integer; - Parts: tstringlist; - se: TStyleEvent; - notify: TOBSNotify; - f: TfrColorSettings; - t: TfrFontSettings; + i: integer; + ws: TEventWebServers; begin - aSumInt := StrToIntDef(aSum, 0); - BestRow := -1; - BestPriority := -1; - BestValue := 0; - - for i := 0 to high(listNotify) do + for i := 0 to EventWebServers.Count - 1 do begin - if listNotify[i].TypeEvent = 4 then - begin - Condition := Trim(listNotify[i].TypeEdit); - - if Condition = '' then - Continue; - - CurrentPriority := -1; - CurrentValue := 0; - - // Проверка на точное значение - if Pos('-', Condition) = 0 then - begin - if Pos('>', Condition) = 0 then - begin - if Pos('<', Condition) = 0 then - begin - // Точное значение - CurrentValue := StrToIntDef(Condition, -1); - if aSumInt = CurrentValue then - CurrentPriority := 4; - end; - end; - end; - - if CurrentPriority = -1 then - begin - if Pos('-', Condition) > 0 then - begin - // Диапазон - Parts := tstringlist.Create; - try - Parts.Delimiter := '-'; - Parts.StrictDelimiter := True; - Parts.DelimitedText := Condition; - if Parts.Count = 2 then - begin - MinVal := StrToIntDef(Trim(Parts[0]), 0); - MaxVal := StrToIntDef(Trim(Parts[1]), 0); - if (aSumInt >= MinVal) and (aSumInt <= MaxVal) then - begin - CurrentPriority := 3; - CurrentValue := MinVal; // Приоритет по MinVal - end; - end; - finally - Parts.Free; - end; - end - else if Pos('>', Condition) > 0 then - begin - // Условие ">X" - CurrentValue := - StrToIntDef(Trim(StringReplace(Condition, '>', '', - [rfReplaceAll])), 0); - if aSumInt >= CurrentValue then - CurrentPriority := 2; - end - else if Pos('<', Condition) > 0 then - begin - // Условие " -1 then - begin - // Определение наилучшего условия - if (CurrentPriority > BestPriority) or (CurrentPriority = BestPriority) - and ((CurrentPriority = 3) and (CurrentValue > BestValue) or - (CurrentPriority = 2) and (CurrentValue > BestValue) or - (CurrentPriority = 1) and (CurrentValue < BestValue)) then - begin - BestPriority := CurrentPriority; - BestValue := CurrentValue; - BestRow := i; - notify := listNotify[i]; - end; - end; - if BestRow = -1 then - Break; - - f := TfrColorSettings.Create(self); - t := TfrFontSettings.Create(self); - try - se.Title := notify.HeaderText; - se.Title := StringReplace(se.Title, '[NICK]', aNick, [rfReplaceAll]); - se.Title := StringReplace(se.Title, '[SUM]', aSum, [rfReplaceAll]); - se.Context := aText; - se.Url := notify.Picture; - se.SoundURL := notify.Sound; - se.Timestamp := Now; - se.TimeMsg := notify.TimeMess; - se.BorderColor := f.ccbStyleBorderColor.Items[notify.ColorBorder]; - se.BorderSize := notify.SolidBorder; - se.BlockColor := notify.ColorBlock; - se.FontTitle.Font := t.cbFontStyleDefault.Items[notify.HeaderStyleFont]; - se.FontTitle.Size := notify.HeaderSizeFont; - se.FontTitle.Color := t.ccbFontColor.Items[notify.HeaderColorFont]; - se.FontContext.Font := t.cbFontStyleDefault.Items[notify.MessSizeFont]; - se.FontContext.Size := notify.MessSizeFont; - se.FontContext.Color := t.ccbFontColor.Items[notify.MessColorFont]; - se.RequireInteraction := True; - finally - f.Free; - t.Free; - end; - for j := 0 to EventWebServers.Count - 1 do - begin - EventWebServers[j].WebServerChat.AddMessage(se); - end; - end; + if EventWebServers[i].typeEvent <> 4 then + Continue; + ws := EventWebServers[i]; + ws.se.Title := StringReplace(ws.se.Title, '[NICK]', aNick, [rfReplaceAll]); + ws.se.Context := StringReplace(ws.se.Context, '[SUM]', aSum, + [rfReplaceAll]); + EventWebServers[i] := ws; + EventWebServers[i].WebServerChat.AddMessage(EventWebServers[i].se); end; end; diff --git a/frames/fRevards.fmx b/frames/fRevards.fmx new file mode 100644 index 0000000..9a16d0e --- /dev/null +++ b/frames/fRevards.fmx @@ -0,0 +1,109 @@ +object frRevards: TfrRevards + Size.Width = 613.000000000000000000 + Size.Height = 339.000000000000000000 + Size.PlatformDefault = False + object Label1: TLabel + Position.X = 8.000000000000000000 + Position.Y = 118.000000000000000000 + Text = #1053#1072#1075#1088#1072#1076#1099' '#1073#1086#1090#1072 + TabOrder = 0 + end + object StringGrid1: TStringGrid + Align = Bottom + CanFocus = True + ClipChildren = True + Position.Y = 143.000000000000000000 + Size.Width = 613.000000000000000000 + Size.Height = 196.000000000000000000 + Size.PlatformDefault = False + TabOrder = 1 + Viewport.Width = 613.000000000000000000 + Viewport.Height = 196.000000000000000000 + object StringColumn1: TStringColumn + Header = #1053#1072#1079#1074#1072#1085#1080#1077 + HeaderSettings.TextSettings.WordWrap = False + Size.Width = 241.000000000000000000 + end + object StringColumn2: TStringColumn + Header = #1055#1086#1083#1100#1079#1086#1074#1072#1090#1077#1083#1100#1089#1082#1080#1081' '#1074#1074#1086#1076 + HeaderSettings.TextSettings.WordWrap = False + Size.Width = 140.000000000000000000 + end + object StringColumn3: TStringColumn + Header = #1054#1087#1080#1089#1072#1085#1080#1077 + HeaderSettings.TextSettings.WordWrap = False + end + object StringColumn4: TStringColumn + Header = #1062#1077#1085#1072 + HeaderSettings.TextSettings.WordWrap = False + end + end + object Label34: TLabel + Position.X = 8.000000000000000000 + Position.Y = 8.000000000000000000 + TextSettings.Trimming = None + Text = #1053#1072#1079#1074#1072#1085#1080#1077 + TabOrder = 4 + end + object ceCustomRevardTitle: TComboEdit + Touch.InteractiveGestures = [LongTap, DoubleTap] + TabOrder = 5 + ItemHeight = 19.000000000000000000 + ItemIndex = -1 + Position.X = 8.000000000000000000 + Position.Y = 33.000000000000000000 + Size.Width = 182.000000000000000000 + Size.Height = 22.000000000000000000 + Size.PlatformDefault = False + end + object edtCustomRevardPrompt: TEdit + Touch.InteractiveGestures = [LongTap, DoubleTap] + TabOrder = 9 + Position.X = 198.000000000000000000 + Position.Y = 33.000000000000000000 + Size.Width = 348.000000000000000000 + Size.Height = 22.000000000000000000 + Size.PlatformDefault = False + end + object nbCustomRevardCost: TNumberBox + Touch.InteractiveGestures = [LongTap, DoubleTap] + TabOrder = 7 + Cursor = crIBeam + Max = 1000000.000000000000000000 + Position.X = 8.000000000000000000 + Position.Y = 88.000000000000000000 + Size.Width = 79.000000000000000000 + Size.Height = 22.000000000000000000 + Size.PlatformDefault = False + end + object Label35: TLabel + Position.X = 8.000000000000000000 + Position.Y = 63.000000000000000000 + Size.Width = 57.000000000000000000 + Size.Height = 17.000000000000000000 + Size.PlatformDefault = False + TextSettings.Trimming = None + Text = #1062#1077#1085#1072 + TabOrder = 6 + end + object Label2: TLabel + Position.X = 198.000000000000000000 + Position.Y = 8.000000000000000000 + Text = #1054#1087#1080#1089#1072#1085#1080#1077 + TabOrder = 10 + end + object btnAddCustomRewards: TButton + Position.X = 95.000000000000000000 + Position.Y = 88.000000000000000000 + TabOrder = 16 + Text = #1044#1086#1073#1072#1074#1080#1090#1100 + TextSettings.Trimming = None + end + object btnDelCustomRewards: TButton + Position.X = 183.000000000000000000 + Position.Y = 88.000000000000000000 + TabOrder = 17 + Text = #1059#1076#1072#1083#1080#1090#1100 + TextSettings.Trimming = None + end +end diff --git a/frames/fRevards.pas b/frames/fRevards.pas new file mode 100644 index 0000000..72a88bf --- /dev/null +++ b/frames/fRevards.pas @@ -0,0 +1,66 @@ +unit fRevards; + +interface + +uses + System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, + FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, + System.Rtti, FMX.Grid.Style, FMX.Grid, FMX.ScrollBox, uRecords, System.Generics.Collections, + FMX.Controls.Presentation, FMX.EditBox, FMX.NumberBox, FMX.Edit, FMX.ComboEdit; + +type + TfrRevards = class(TFrame) + Label1: TLabel; + StringGrid1: TStringGrid; + StringColumn1: TStringColumn; + StringColumn2: TStringColumn; + StringColumn3: TStringColumn; + StringColumn4: TStringColumn; + Label34: TLabel; + ceCustomRevardTitle: TComboEdit; + edtCustomRevardPrompt: TEdit; + nbCustomRevardCost: TNumberBox; + Label35: TLabel; + Label2: TLabel; + btnDelCustomRewards: TButton; + btnAddCustomRewards: TButton; + private + { Private declarations } + public + { Public declarations } + + CustomRewards: TList; + listRevards:tarray; + procedure LoadCustomRevards; + procedure UpdateGrid; + end; + +implementation + +{$R *.fmx} + +uses ugeneral; + +procedure TfrRevards.LoadCustomRevards; +var + cr: TCustomRevards; +begin + CustomRewards.Clear; + TTW_Bot.frEvents1.cbRevards.Items.Clear; + ceCustomRevardTitle.items.Clear; + TTW_Bot.toLog('fRevards', 'LoadCustomRevards', 'Запрос наград с сервера', 3); + ttw_API.getCustomReward(CustomRewards); + + for cr in CustomRewards do + begin + TTW_Bot.frEvents1.cbRevards.Items.Add(cr.Title); + ceCustomRevardTitle.Items.Add(cr.Title); + end; +end; + +procedure TfrRevards.UpdateGrid; +begin + +end; + +end. diff --git a/utils/uRecords.pas b/utils/uRecords.pas index 6e6b53a..80d79d5 100644 --- a/utils/uRecords.pas +++ b/utils/uRecords.pas @@ -3,29 +3,11 @@ unit uRecords; interface type -TEventGlobal = record - Event:integer; - Condition:string; - Action:integer; - Param:string; -end; - - -type - TRLog = record - rTime: ttime; - rType: string; - rModule: string; - rMethod: string; - rMessage: string; - end; - -type - TCounter = record - counterName: string; - trigger: string; - count: integer; - auto: integer; + TEventGlobal = record + Event: integer; + Condition: string; + Action: integer; + Param: string; end; type @@ -33,19 +15,6 @@ type regexp: string; end; -type - TListTimer = record - Enable: integer; - interval: integer; - o: integer; - mess: string; - end; - -type - TOBSKandinsky = record - port: integer; - end; - type TOBSNotify = record Picture: string; @@ -54,18 +23,18 @@ type ColorBlock: string; SolidBorder: integer; Paddings: integer; - ColorBorder: integer; - ColorBackground: integer; + ColorBorder: string; + ColorBackground: string; HeaderText: string; - HeaderColorFont: integer; + HeaderColorFont: string; HeaderSizeFont: integer; - HeaderStyleFont: integer; + HeaderStyleFont: string; MessText: string; - MessColorFont: integer; + MessColorFont: string; MessSizeFont: integer; - MessStyleFont: integer; + MessStyleFont: string; TimeMess: integer; TypeEvent: integer; @@ -86,10 +55,37 @@ type MaxCountMess: integer; TimeMess: integer; port: integer; - freez:integer; + freez: integer; StyleFont: integer; end; +type + TListCommands = record + R1: string; + R2: string; + end; + +type + TCounter = record + counterName: string; + trigger: string; + count: integer; + auto: integer; + end; + +type + TListTimer = record + Enable: integer; + interval: integer; + o: integer; + mess: string; + end; + +type + TOBSKandinsky = record + port: integer; + end; + type TRandomCounters = record rndName: string; @@ -98,9 +94,12 @@ type end; type - TListCommands = record - R1: string; - R2: string; + TRLog = record + rTime: ttime; + rType: string; + rModule: string; + rMethod: string; + rMessage: string; end; type @@ -270,7 +269,7 @@ type format: TArray; scale: TArray; theme_mode: TArray; - topImage:string; + topImage: string; end; TStyleChat = record @@ -342,7 +341,7 @@ type version: string; status: string; cost: integer; - condition: TCondition; + Condition: TCondition; transport: TTransport; created_at: string; end; @@ -383,7 +382,7 @@ type TCustomRewardEvent = record subscription: TSubscriptionPoints; - event: TEventReward; + Event: TEventReward; end; TMetadata = record @@ -455,22 +454,22 @@ type TFollowEvent = record subscription: TSubscriptionPoints; - event: TEventFollow; + Event: TEventFollow; end; TSubEvent = record subscription: TSubscriptionPoints; - event: TEventSub; + Event: TEventSub; end; TGiftEvent = record subscription: TSubscriptionPoints; - event: TEventGift; + Event: TEventGift; end; TRaidEvent = record subscription: TSubscriptionPoints; - event: TEventRaid; + Event: TEventRaid; end; TBotAppCfg = record diff --git a/utils/uWebServerEvents.pas b/utils/uWebServerEvents.pas index 3cbdbee..604dc90 100644 --- a/utils/uWebServerEvents.pas +++ b/utils/uWebServerEvents.pas @@ -17,13 +17,14 @@ type FCriticalSection: TCriticalSection; procedure IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); - procedure ProcessFileRequest(ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo; const Folder: string); + procedure ProcessFileRequest(ARequestInfo: TIdHTTPRequestInfo; + AResponseInfo: TIdHTTPResponseInfo; const Folder: string); function GenerateHTML: string; function GenerateJSON: string; procedure CleanupOldMessages; public IdHTTPServer1: TIdHTTPServer; - constructor Create(FontList: TStrings; aPort:integer); + constructor Create(FontList: TStrings; aPort: integer); destructor Destroy; override; procedure addMessage(newMsg: TStyleEvent); procedure ActiveServer(aEn: boolean); @@ -35,9 +36,9 @@ uses ugeneral; { TTTW_Events } -constructor TTTW_Events.Create(FontList: TStrings; aPort:integer); +constructor TTTW_Events.Create(FontList: TStrings; aPort: integer); var - I: Integer; + I: integer; begin FCriticalSection := TCriticalSection.Create; FMessages := TList.Create; @@ -71,27 +72,19 @@ end; procedure TTTW_Events.CleanupOldMessages; var - I: Integer; + I: integer; TimeNow: TDateTime; begin TimeNow := Now; - FCriticalSection.Enter; - try - for I := FMessages.Count - 1 downto 0 do - begin - if SecondsBetween(TimeNow, FMessages[I].Timestamp) >= FMessages[I].TimeMsg then - FMessages.Delete(I); - end; - finally - FCriticalSection.Leave; - end; + for I := FMessages.Count - 1 downto 0 do + if SecondsBetween(TimeNow, FMessages[I].Timestamp) >= FMessages[I].TimeMsg + then + FMessages.Delete(I); end; - - function TTTW_Events.GenerateHTML: string; var - I: Integer; + I: integer; s, s1: string; begin // Генерация CSS для шрифтов @@ -99,126 +92,82 @@ begin for I := 41 to fFontsList.Count - 1 do begin s1 := StringReplace(fFontsList[I], '.ttf', '', [rfReplaceAll]); - s := s + Format('@font-face { font-family: ''%s''; src: url(fonts/%s); }', [s1, fFontsList[I]]) + #13#10; + s := s + Format('@font-face { font-family: ''%s''; src: url(fonts/%s); }', + [s1, fFontsList[I]]) + #13#10; end; Result := '' + - '' + - '' + - '' + - 'Twitch Messages' + - '' + - '' + + 'setInterval(fetchMessages, 1000);' + 'fetchMessages();' + '' + - '' + - '' + - '
' + + '' + '' + '
' + ''; end; @@ -226,55 +175,49 @@ end; function TTTW_Events.GenerateJSON: string; var JSONArray: TJSONArray; - I: Integer; S,S1:STRING; + I: Integer; Msg: TStyleEvent; begin JSONArray := TJSONArray.Create; try - FCriticalSection.Enter; - try - CleanupOldMessages; - for I := 0 to FMessages.Count - 1 do - begin - Msg := FMessages[I]; - s:=StringReplace(Msg.FontTitle.Font,'.ttf','',[rfReplaceAll]); - s1:=StringReplace(Msg.FontContext.Font,'.ttf','',[rfReplaceAll]); + FCriticalSection.Enter; + try + for I := 0 to FMessages.Count - 1 do + begin + Msg := FMessages[I]; - JSONArray.AddElement(TJSONObject.Create - .AddPair('nickname', Msg.Title) - .AddPair('url', Msg.Url) - .AddPair('content', Msg.Context) - .AddPair('timestamp', TJSONNumber.Create(DateTimeToUnix(Msg.Timestamp))) - .AddPair('sound', Msg.SoundURL) - .AddPair('duration', Msg.TimeMsg) - - .AddPair('color', Msg.BlockColor) - .AddPair('colorBorder', Msg.BorderColor) - .AddPair('sizeBorder', TJSONNumber.Create(Msg.BorderSize)) - .AddPair('fontSize', TJSONNumber.Create(Msg.FontTitle.size)) - - .AddPair('titlecolor', Msg.FontTitle.Color) - .AddPair('titlefamily', s) - .AddPair('titleSize', TJSONNumber.Create(Msg.FontTitle.Size)) - .AddPair('contentcolor', Msg.FontContext.Color) - .AddPair('contentfamily', s1) - .AddPair('contentSize', TJSONNumber.Create(Msg.FontContext.Size)) - - - ); // Фиксированный размер текста + JSONArray.AddElement( + TJSONObject.Create + .AddPair('nickname', Msg.Title) + .AddPair('url', Msg.Url) + .AddPair('content', Msg.Context) + .AddPair('timestamp', TJSONNumber.Create(DateTimeToUnix(Msg.Timestamp))) + .AddPair('sound', Msg.SoundURL) + .AddPair('duration', Msg.TimeMsg) + .AddPair('color', Msg.BlockColor) + .AddPair('colorBorder', Msg.BorderColor) + .AddPair('sizeBorder', TJSONNumber.Create(Msg.BorderSize)) + .AddPair('fontSize', TJSONNumber.Create(Msg.FontTitle.Size)) + .AddPair('titlecolor', Msg.FontTitle.Color) + .AddPair('titlefamily', TPath.GetFileNameWithoutExtension(Msg.FontTitle.Font)) + .AddPair('titleSize', TJSONNumber.Create(Msg.FontTitle.Size)) + .AddPair('contentcolor', Msg.FontContext.Color) + .AddPair('contentfamily', TPath.GetFileNameWithoutExtension(Msg.FontContext.Font)) + .AddPair('contentSize', TJSONNumber.Create(Msg.FontContext.Size)) + ); + end; + finally + FCriticalSection.Leave; end; - finally - FCriticalSection.Leave; - end; - Result := JSONArray.ToString; + Result := JSONArray.ToString; finally - JSONArray.Free; + JSONArray.Free; end; - end; -procedure TTTW_Events.ProcessFileRequest(ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo; const Folder: string); +procedure TTTW_Events.ProcessFileRequest(ARequestInfo: TIdHTTPRequestInfo; + AResponseInfo: TIdHTTPResponseInfo; const Folder: string); var FileName: string; FilePath: string; @@ -290,6 +233,7 @@ begin AResponseInfo.ContentStream := FS; AResponseInfo.ContentType := GetMIMETypeFromFile(FilePath);; AResponseInfo.ResponseNo := 200; + AResponseInfo.FreeContentStream := True; except FS.Free; AResponseInfo.ResponseNo := 500; diff --git a/utils/uWebServerKandinsky.pas b/utils/uWebServerKandinsky.pas index 0a53778..5807f1f 100644 --- a/utils/uWebServerKandinsky.pas +++ b/utils/uWebServerKandinsky.pas @@ -28,7 +28,7 @@ uses procedure GenerationError(Sender: TObject; const ErrorMessage: string); procedure GenerationUpdate(Sender: TObject; const Message: string); public - constructor Create(aKey:string; aSecret:string); + constructor Create(aKey:string; aSecret:string; aPort:integer); destructor Destroy; procedure generate(prompt:string; aNick:string); procedure ActiveServer(aEn: boolean); @@ -51,10 +51,10 @@ begin end; end; -constructor TKandinsky_Web.Create(aKey:string; aSecret:string); +constructor TKandinsky_Web.Create(aKey:string; aSecret:string; aPort:integer); begin IdHTTPServer1 := TIdHTTPServer.Create; - IdHTTPServer1.DefaultPort := 8087; + IdHTTPServer1.DefaultPort := aPort; IdHTTPServer1.OnCommandGet := IdHTTPServer1CommandGet; ka:=TFusionBrainAPI.Create(nil,aKey, aSecret); ka.OnGenerationDone := GenerationDone;