diff --git a/README.md b/README.md
index 21e1c2c2..c8843d76 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,14 @@
+
### TwitchDownloader
A Twitch VOD/Clip/Chat downloader I wrote, as well as a chat render feature
-![](https://i.imgur.com/XXnLKyT.gif)
+![](https://i.imgur.com/8XyVD00.gifv)
## Chat render example
-![](https://i.imgur.com/OhS6XAU.gif)
+![](https://i.imgur.com/rRw4bHq.gifv)
+
+## Video Demonstration (older version, same concept)
+https://www.youtube.com/watch?v=0W3MhfhnYjk
## What can this do?
- Can download Twitch VODs
@@ -12,14 +16,6 @@ A Twitch VOD/Clip/Chat downloader I wrote, as well as a chat render feature
- Can download chat for VODS and Clips, in either a [JSON with all the information](https://pastebin.com/raw/YDgRe6X4) or a [simple text file](https://pastebin.com/raw/016azeQX)
- Can use a previously generated JSON chat file, to render the chat with FFZ and BTTV support (including GIFS)
-## Why does it look so ugly?
-Because I made this in 2 days and I wanted to put it up before school starts :( (tomorrow as of publishing this)
-
## Things still needed to be done
-- Proper error handling (Just crashes most of the time currently)
-- Proper input validation
-- Have the text log actually log stuff
-- Better emoji support for chat rendering
-- ~~Fix some GIFs that play at the wrong speed~~
-- More options for chat rendering
-- Make it look less ugly
+- Fix bugs that slipped by
+- More options for chat rendering
\ No newline at end of file
diff --git a/TwitchDownloader.sln b/TwitchDownloader.sln
deleted file mode 100644
index 0d8c58cd..00000000
--- a/TwitchDownloader.sln
+++ /dev/null
@@ -1,37 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.28803.352
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwitchDownloader", "TwitchDownloader\TwitchDownloader.csproj", "{11768826-A184-4E62-B77C-2CF818242384}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Debug|x64 = Debug|x64
- Debug|x86 = Debug|x86
- Release|Any CPU = Release|Any CPU
- Release|x64 = Release|x64
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {11768826-A184-4E62-B77C-2CF818242384}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {11768826-A184-4E62-B77C-2CF818242384}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {11768826-A184-4E62-B77C-2CF818242384}.Debug|x64.ActiveCfg = Debug|x64
- {11768826-A184-4E62-B77C-2CF818242384}.Debug|x64.Build.0 = Debug|x64
- {11768826-A184-4E62-B77C-2CF818242384}.Debug|x86.ActiveCfg = Debug|x86
- {11768826-A184-4E62-B77C-2CF818242384}.Debug|x86.Build.0 = Debug|x86
- {11768826-A184-4E62-B77C-2CF818242384}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {11768826-A184-4E62-B77C-2CF818242384}.Release|Any CPU.Build.0 = Release|Any CPU
- {11768826-A184-4E62-B77C-2CF818242384}.Release|x64.ActiveCfg = Release|x64
- {11768826-A184-4E62-B77C-2CF818242384}.Release|x64.Build.0 = Release|x64
- {11768826-A184-4E62-B77C-2CF818242384}.Release|x86.ActiveCfg = Release|x86
- {11768826-A184-4E62-B77C-2CF818242384}.Release|x86.Build.0 = Release|x86
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {11217EF1-6708-48D6-BF64-2C2851D4F1F3}
- EndGlobalSection
-EndGlobal
diff --git a/TwitchDownloader/App.config b/TwitchDownloader/App.config
deleted file mode 100644
index e801ab20..00000000
--- a/TwitchDownloader/App.config
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #111111
-
-
- 500
-
-
- 300
-
-
- True
-
-
- True
-
-
- False
-
-
- 9
-
-
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/TwitchDownloader/Program.cs b/TwitchDownloader/Program.cs
deleted file mode 100644
index de5bfd8e..00000000
--- a/TwitchDownloader/Program.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace TwitchDownloader
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new frmMain());
- }
- }
-}
diff --git a/TwitchDownloader/Properties/Settings.settings b/TwitchDownloader/Properties/Settings.settings
deleted file mode 100644
index 78321ba5..00000000
--- a/TwitchDownloader/Properties/Settings.settings
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
- #111111
-
-
- 500
-
-
- 300
-
-
- True
-
-
- True
-
-
- False
-
-
- 9
-
-
- 1
-
-
-
-
-
-
\ No newline at end of file
diff --git a/TwitchDownloader/Resources/hypers.png b/TwitchDownloader/Resources/hypers.png
deleted file mode 100644
index a90bc34a..00000000
Binary files a/TwitchDownloader/Resources/hypers.png and /dev/null differ
diff --git a/TwitchDownloader/TwitchDownloader.csproj b/TwitchDownloader/TwitchDownloader.csproj
deleted file mode 100644
index cc9f3197..00000000
--- a/TwitchDownloader/TwitchDownloader.csproj
+++ /dev/null
@@ -1,220 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {11768826-A184-4E62-B77C-2CF818242384}
- WinExe
- TwitchDownloader
- TwitchDownloader
- v4.7.2
- 512
- true
- true
-
-
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- true
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- true
-
-
- true
- bin\x86\Debug\
- DEBUG;TRACE
- full
- x86
- prompt
- MinimumRecommendedRules.ruleset
- true
- true
-
-
- bin\x86\Release\
- TRACE
- true
- pdbonly
- x86
- prompt
- MinimumRecommendedRules.ruleset
- true
- true
-
-
- true
- bin\x64\Debug\
- DEBUG;TRACE
- full
- x64
- prompt
- MinimumRecommendedRules.ruleset
- true
- true
-
-
- bin\x64\Release\
- TRACE
- true
- pdbonly
- x64
- prompt
- MinimumRecommendedRules.ruleset
- true
- true
-
-
- icon_rT9_icon.ico
-
-
-
- ..\packages\Accord.3.8.0\lib\net462\Accord.dll
-
-
- ..\packages\Accord.Video.3.8.0\lib\net462\Accord.Video.dll
-
-
- ..\packages\Accord.Video.FFMPEG.x64.3.8.0\lib\net462\Accord.Video.FFMPEG.x64.dll
-
-
- ..\packages\Microsoft.WindowsAPICodePack-Core.1.1.0.2\lib\Microsoft.WindowsAPICodePack.dll
-
-
- ..\packages\Microsoft.WindowsAPICodePack-Shell.1.1.0.0\lib\Microsoft.WindowsAPICodePack.Shell.dll
-
-
- ..\packages\Microsoft.WindowsAPICodePack-Shell.1.1.0.0\lib\Microsoft.WindowsAPICodePack.ShellExtensions.dll
-
-
- ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
- ..\packages\Xabe.FFmpeg.3.4.0\lib\netstandard2.0\Xabe.FFmpeg.dll
-
-
-
-
- Form
-
-
- frmAbout.cs
-
-
- Form
-
-
- frmChatDownload.cs
-
-
- Form
-
-
- frmChatRender.cs
-
-
- Form
-
-
- frmClipDownload.cs
-
-
- Form
-
-
- frmMain.cs
-
-
- Form
-
-
- frmVodDownload.cs
-
-
-
-
- frmAbout.cs
-
-
- frmChatDownload.cs
-
-
- frmChatRender.cs
-
-
- frmClipDownload.cs
-
-
- frmMain.cs
-
-
- frmVodDownload.cs
-
-
- ResXFileCodeGenerator
- Resources.Designer.cs
- Designer
-
-
- True
- Resources.resx
- True
-
-
-
- SettingsSingleFileGenerator
- Settings.Designer.cs
-
-
- True
- Settings.settings
- True
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
-
-
\ No newline at end of file
diff --git a/TwitchDownloader/frmAbout.Designer.cs b/TwitchDownloader/frmAbout.Designer.cs
deleted file mode 100644
index cf07004e..00000000
--- a/TwitchDownloader/frmAbout.Designer.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-namespace TwitchDownloader
-{
- partial class frmAbout
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmAbout));
- this.label1 = new System.Windows.Forms.Label();
- this.pictureBox1 = new System.Windows.Forms.PictureBox();
- ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
- this.SuspendLayout();
- //
- // label1
- //
- this.label1.Location = new System.Drawing.Point(12, 9);
- this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(466, 343);
- this.label1.TabIndex = 0;
- this.label1.Text = "Made by Lewis Pardo (@lay295)\r\n\r\nDownload Icon made by Freepik from www.flaticon." +
- "com\r\n\r\nTwitter Emojis\r\nhttps://twemoji.twitter.com/";
- //
- // pictureBox1
- //
- this.pictureBox1.Image = global::TwitchDownloader.Properties.Resources.hypers;
- this.pictureBox1.Location = new System.Drawing.Point(414, 9);
- this.pictureBox1.Name = "pictureBox1";
- this.pictureBox1.Size = new System.Drawing.Size(64, 64);
- this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
- this.pictureBox1.TabIndex = 1;
- this.pictureBox1.TabStop = false;
- //
- // frmAbout
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(490, 361);
- this.Controls.Add(this.pictureBox1);
- this.Controls.Add(this.label1);
- this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
- this.Name = "frmAbout";
- this.Text = "About";
- ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
- this.ResumeLayout(false);
-
- }
-
- #endregion
-
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.PictureBox pictureBox1;
- }
-}
\ No newline at end of file
diff --git a/TwitchDownloader/frmAbout.cs b/TwitchDownloader/frmAbout.cs
deleted file mode 100644
index e8d67975..00000000
--- a/TwitchDownloader/frmAbout.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace TwitchDownloader
-{
- public partial class frmAbout : Form
- {
- public frmAbout()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/TwitchDownloader/frmAbout.resx b/TwitchDownloader/frmAbout.resx
deleted file mode 100644
index 66003700..00000000
--- a/TwitchDownloader/frmAbout.resx
+++ /dev/null
@@ -1,700 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
-
- AAABAAUAEBAAAAEAIABoBAAAVgAAABgYAAABACAAiAkAAL4EAAAgIAAAAQAgAKgQAABGDgAAMDAAAAEA
- IACoJQAA7h4AAEBAAAABACAAKEIAAJZEAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAADXDQAA1w0AAAAA
- AAAAAAAAAAAAmQAAAPsAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD7AAAAmQAAAMoAAAD/AAAA9gAAAO8AAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAA
- AO8AAAD2AAAA/wAAAMoAAADMAAAA/wAAAIwAAAA1AAAAOAAAADgAAAA4AAAAOAAAADgAAAA4AAAAOAAA
- ADgAAAA1AAAAjAAAAP8AAADMAAAAzAAAAP8AAABrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAGsAAAD/AAAAzAAAAMwAAAD/AAAAbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAABsAAAA/wAAAMwAAACWAAAAvgAAAE8AAAAAAAAAAAAAAAAAAAAAAAAABwAA
- AAkAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAL4AAACWAAAACgAAAAwAAAAFAAAAAAAAAAAAAAAAAAAABQAA
- AHcAAACLAAAADAAAAAAAAAAAAAAAAAAAAAUAAAAMAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AFsAAADuAAAA9wAAAG4AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AEEAAADfAAAA/wAAAP8AAADmAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- ACUAAADHAAAA/wAAAP8AAAD/AAAA/wAAAMsAAAAmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAjAAAAWgAAAK0AAAD/AAAA/wAAAL4AAABwAAAAKwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAB/AAAA/wAAAP8AAACJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAAAP8AAAD/AAAAigAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH8AAAD/AAAA/wAAAIoAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA/wAAAP8AAACKAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfQAAAP8AAAD/AAAAiAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/4AAAf+AAAHngAABw4AAD8HwAA+B8AAPAPAADwDwAA/D8AAPw/
- AAD8PwAA/D8AAPw/AAAoAAAAGAAAADAAAAABACAAAAAAAAAJAADXDQAA1w0AAAAAAAAAAAAAAAAATgAA
- ANwAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAANwAAABOAAAAoAAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAACgAAAArAAAAP8AAAD/AAAA+gAAAPMAAADzAAAA8wAAAPMAAADzAAAA8wAAAPMAAADzAAAA8wAA
- APMAAADzAAAA8wAAAPMAAADzAAAA8wAAAPMAAAD6AAAA/wAAAP8AAACsAAAArAAAAP8AAAD/AAAAtQAA
- AEkAAABIAAAASAAAAEgAAABIAAAASAAAAEgAAABIAAAASAAAAEgAAABIAAAASAAAAEgAAABIAAAASAAA
- AEkAAAC1AAAA/wAAAP8AAACsAAAArAAAAP8AAAD/AAAAlwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAACXAAAA/wAAAP8AAACsAAAArAAA
- AP8AAAD/AAAAmAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAIAAACYAAAA/wAAAP8AAACsAAAArAAAAP8AAAD/AAAAmAAAAAIAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACYAAAA/wAA
- AP8AAACsAAAArAAAAP8AAAD/AAAAmAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACZAAAA/wAAAP8AAACsAAAAcAAAAKgAAACpAAAAYwAA
- AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAEAAABjAAAAqQAAAKgAAABwAAAABgAAAAgAAAAIAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAgAAAB6AAAAlgAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAACAAAAAgAAAAGAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAGEAAADuAAAA+gAAAIQAAAAIAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAARQAAAN4AAAD/AAAA/wAAAO0AAABdAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxAAAAzAAAAP8AAAD/AAAA/wAA
- AP8AAADZAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAB4AAAC0AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAuQAAAB8AAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAJYAAAD7AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/AAAAJYAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAHIAAAB/AAAApgAAAPkAAAD/AAAA/wAAAPwAAADCAAAAnwAA
- AI0AAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAATgAAAPIAAAD/AAAA/wAAAPgAAABfAAAAAgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATwAAAPIAAAD/AAAA/wAA
- APgAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAATwAAAPIAAAD/AAAA/wAAAPgAAABcAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATwAA
- APIAAAD/AAAA/wAAAPgAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATwAAAPIAAAD/AAAA/wAAAPgAAABcAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAATwAAAPIAAAD/AAAA/wAAAPgAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATwAAAPIAAAD/AAAA/wAA
- APgAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAASgAAAO8AAAD/AAAA/wAAAPYAAABXAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/4AAH/+AAB//gAAf/4AAH5+AAD8PwAP+B
- /wD/gP8A/wD/AP4AfwD8AD8A/AA/AP+APwD/gf8A/4H/AP+B/wD/gf8A/4H/AP+B/wD/gf8AKAAAACAA
- AABAAAAAAQAgAAAAAAAAEAAA1w0AANcNAAAAAAAAAAAAAAAAABwAAACfAAAA9QAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA9AAAAJ4AAAAcAAAAaQAAAPMAAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8wAAAGgAAACJAAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAiQAA
- AIoAAAD/AAAA/wAAAP8AAAD9AAAA9gAAAPUAAAD2AAAA9gAAAPYAAAD2AAAA9gAAAPYAAAD2AAAA9gAA
- APYAAAD2AAAA9gAAAPYAAAD2AAAA9gAAAPYAAAD2AAAA9gAAAPYAAAD1AAAA9gAAAP0AAAD/AAAA/wAA
- AP8AAACKAAAAigAAAP8AAAD/AAAA/wAAANQAAABjAAAAVwAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAA
- AFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFcAAABkAAAA1AAA
- AP8AAAD/AAAA/wAAAIoAAACKAAAA/wAAAP8AAAD/AAAAvQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- ABEAAAC9AAAA/wAAAP8AAAD/AAAAigAAAIoAAAD/AAAA/wAAAP8AAAC+AAAAEgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAEgAAAL4AAAD/AAAA/wAAAP8AAACKAAAAigAAAP8AAAD/AAAA/wAAAL4AAAASAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAASAAAAvgAAAP8AAAD/AAAA/wAAAIoAAACKAAAA/wAAAP8AAAD/AAAAvgAA
- ABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAC+AAAA/wAAAP8AAAD/AAAAigAAAIoAAAD/AAAA/wAA
- AP8AAAC+AAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAL4AAAD/AAAA/wAAAP8AAACKAAAAiQAA
- AP4AAAD+AAAA/wAAAL0AAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAvQAAAP8AAAD+AAAA/gAA
- AIkAAABPAAAAkgAAAJIAAACTAAAAbAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAALAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAABsAAAAkwAA
- AJIAAACSAAAATwAAAAQAAAAHAAAABwAAAAcAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAADAAAAHsAAACcAAAAIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAUAAAAHAAAABwAAAAcAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAYAAABmAAAA7AAAAPsAAACUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAACAAAATAAAAN0AAAD/AAAA/wAAAPEAAAByAAAACAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADUAAADJAAAA/wAAAP8AAAD/AAAA/wAAAOAAAABQAAAAAQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlAAAAtQAAAP4AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AMkAAAAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAJwAAAD6AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/QAAAKgAAAAbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAACBAAAA8gAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA9AAAAIIAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAYwAAAOgAAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA6AAAAF0AAAACAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAABxAAAAoAAA
- AJ4AAACwAAAA7gAAAP8AAAD/AAAA/wAAAP8AAAD4AAAA0QAAAMMAAADFAAAAiQAAAAsAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- AAgAAAAKAAAACAAAADUAAADUAAAA/wAAAP8AAAD/AAAA/wAAAOQAAABLAAAAFwAAABoAAAATAAAAAgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAANIAAAD/AAAA/wAAAP8AAAD/AAAA4QAAADcAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtAAAA0gAAAP8AAAD/AAAA/wAAAP8AAADhAAAAOAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0AAADSAAAA/wAAAP8AAAD/AAAA/wAA
- AOEAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALQAAANIAAAD/AAAA/wAA
- AP8AAAD/AAAA4QAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtAAAA0gAA
- AP8AAAD/AAAA/wAAAP8AAADhAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AC0AAADSAAAA/wAAAP8AAAD/AAAA/wAAAOEAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAALQAAANIAAAD/AAAA/wAAAP8AAAD/AAAA4QAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAtAAAA0gAAAP8AAAD/AAAA/wAAAP8AAADhAAAAOAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0AAADSAAAA/wAAAP8AAAD/AAAA/wAAAOEAAAA4AAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJwAAAMoAAAD/AAAA/wAAAP8AAAD/AAAA2QAA
- ADIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAP//8AD///AA///wAP//8AD///AA///wAP+f8AH/D/g//gf///wD///8Af//+AH///A
- A///gAH//wAA//8AAP//AAD///AP///wD///8A////AP///wD///8A////AP///wD///8A////AP/ygA
- AAAwAAAAYAAAAAEAIAAAAAAAACQAANcNAADXDQAAAAAAAAAAAAAAAAAAAAAALAAAAJwAAADqAAAA/QAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/QAAAOkAAACaAAAAKwAAAAAAAAAXAAAAmwAA
- APUAAAD+AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP4AAAD1AAAAmQAA
- ABYAAAA6AAAA4QAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA4QAAADoAAABIAAAA9QAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA9QAAAEgAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAA
- AP8AAAD+AAAA+gAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAA
- APgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAA
- APgAAAD4AAAA+AAAAPgAAAD4AAAA+gAAAP4AAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAA
- AP8AAAD/AAAA/wAAAP8AAADzAAAAoQAAAHQAAAB2AAAAdgAAAHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAA
- AHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAA
- AHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAAAHYAAAB0AAAAogAAAPMAAAD/AAAA/wAAAP8AAAD/AAAA9gAA
- AEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAVQAAAAIAAAAFAAAABQAAAAUAAAAFAAAABQAA
- AAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAA
- AAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAADAAAAVQAAAOkAAAD/AAAA/wAA
- AP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAUQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAA
- AOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAUgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAA
- AP8AAADpAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAA
- AP8AAAD/AAAA/wAAAP8AAADpAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAA
- AEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAA
- AP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAUgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAA
- AOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAUgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAA
- AP8AAADpAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABDAAAA4gAA
- AOsAAADrAAAA6wAAAOwAAADWAAAASwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASwAAANYAAADsAAAA6wAAAOsAAADrAAAA4gAA
- AEMAAAAgAAAAbQAAAHEAAABxAAAAcQAAAHEAAABnAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAdAAAABAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAGcAAABxAAAAcQAA
- AHEAAABxAAAAbQAAACAAAAABAAAABQAAAAUAAAAFAAAABQAAAAUAAAAEAAAAAgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAHwAAACeAAAAPgAA
- AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
- AAQAAAAFAAAABQAAAAUAAAAFAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAbwAA
- AOgAAAD7AAAAqwAAAC8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAkAAABYAAAA2AAAAP8AAAD/AAAA9AAAAJEAAAAeAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAABgAAAEMAAADHAAAA/gAAAP8AAAD/AAAA/wAAAOwAAAB1AAAAEgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAACAAAAMAAAAK8AAAD9AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADXAAAAVwAA
- AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAmQAAAPYAAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD9AAAAvwAAAD0AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAACLAAAA8AAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA+gAAAKkAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAHIAAADjAAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPAAAACJAAAAGAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAXAAA
- ANQAAAD+AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADdAAAAZwAA
- AAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAABIAAAAxQAAAPwAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD8AAAAyQAAAEoAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAQAAADMAAACzAAAA9gAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA9wAAALAAAAAuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAAJoAAADyAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPEAAACQAAAAGAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPQAAAK4AAADHAAAAxwAAAMcAAADKAAAA4wAA
- APwAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA9wAAAO0AAADrAAAA6wAAAOsAAADKAAAARAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFQAAADUAAAA4AAAAOAAA
- ADcAAABDAAAAmwAAAPQAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD8AAAAvgAAAGoAAABeAAAAXwAA
- AF8AAABWAAAAIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAANAAAAfgAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmQAA
- ABQAAAABAAAAAgAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAA
- APEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAA
- ABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAA
- APEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAA
- ABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAgAAA
- APEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAOAAAAfgAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD5AAAAlwAAABIAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAKAAAAbAAAAOgAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADzAAAAhQAA
- AA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAACAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAA/////wAAAAD/////AAAAAP////8AAAAA/////wAAAAD/
- ////AAAAAP////8AAAAA/////wAAAAD/////AAAAAP/+P/8AAAAA//wf/wAAAP//+A///wAA///wB///
- AAD//+AH//8AAP//wAP//wAA///AAf//AAD//4AB//8AAP//AAD//wAA//4AAH//AAD//AAAP/8AAP/4
- AAA//wAA//gAAB//AAD/+AAAH/8AAP/4AAAf/wAA///AAD//AAD//8AD//8AAP//wAP//wAA///AA///
- AAD//8AD//8AAP//wAP//wAA///AA///AAD//8AD//8AAP//wAP//wAA///AA///AAD//8AD//8AAP//
- wAP//wAA///AA///AAD//8AD//8AAP//wAP//wAA///AA///AAAoAAAAQAAAAIAAAAABACAAAAAAAABA
- AADXDQAA1w0AAAAAAAAAAAAAAAAAAAAAAAAAAAAhAAAAkgAAAN8AAAD6AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAPoAAADeAAAAkAAAACAAAAAAAAAAAAAAAAAAAAAjAAAAyAAAAPUAAAD9AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/QAAAPQAAADHAAAAIQAAAAAAAAAAAAAAlAAA
- APAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8AAA
- AJEAAAAAAAAAAAAAANgAAAD8AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAPwAAADXAAAAAAAAAAQAAADsAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7AAAAAQAAAAFAAAA7gAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAO4AAAAFAAAABQAA
- AO4AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAADuAAAABQAAAAUAAADuAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA7gAAAAUAAAAFAAAA7gAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAADUAAAAkgAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAA
- AJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAA
- AJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAA
- AJMAAADUAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAO4AAAAFAAAABQAAAO4AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAAoAAAABAAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
- AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
- AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
- AAoAAAAKAAAACgAAAAoAAAAQAAAAoQAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADuAAAABQAA
- AAUAAADuAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAJ0AAAAGAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAJ0AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA7gAAAAUAAAAFAAAA7gAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACdAAAABgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAACdAAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAO4AAAAFAAAABQAAAO4AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAAnQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAHAAAAnQAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADuAAAABQAAAAUAAADuAAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAJ0AAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAJ0AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7gAA
- AAUAAAAFAAAA7gAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACdAAAABgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAACdAAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAO4AAAAFAAAABQAAAO4AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAnQAA
- AAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAnQAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADuAAAABQAAAAUAAADuAAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAJ0AAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAABwAAAJ0AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7gAAAAUAAAAFAAAA7gAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACdAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAACdAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AO4AAAAFAAAABQAAAO4AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAnQAAAAYAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAnQAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAADuAAAABQAAAAUAAADuAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AJ0AAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAA
- AJ0AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7gAAAAUAAAAFAAAA7gAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAACdAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAcAAACdAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAO4AAAAFAAAABQAA
- AO4AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAnQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAnQAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAADuAAAABQAAAAQAAADIAAAA1gAAANYAAADWAAAA1gAAANYAAADWAAAA1gAAAIQAAAAFAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAIQAAADWAAAA1gAA
- ANYAAADWAAAA1gAAANYAAADWAAAAyAAAAAQAAAACAAAAUgAAAFcAAABXAAAAVwAAAFcAAABXAAAAVwAA
- AFcAAAA2AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAADwAAACkAAAAEAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAA2AAAAVwAAAFcAAABXAAAAVwAAAFcAAABXAAAAVwAAAFIAAAACAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAFwAAAH0AAACgAAAATgAA
- AAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAEgAA
- AHEAAADyAAAA/wAAAMUAAAA/AAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAADgAAAFgAAADjAAAA/wAAAP8AAAD/AAAAqAAAADAAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAEYAAADOAAAA/wAAAP8AAAD/AAAA/wAAAPwAAACLAAAAJAAA
- AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAADgAAACzAAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA8wAAAG8AAAAWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAACoAAACXAAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADcAAAAVgAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- ABoAAAB8AAAA+QAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAALsAAABBAAAAAwAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAwAAABrAAAA7QAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAAngAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAABlAAAA4QAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPgAAACJAAAAFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABUAAAAyQAAAP0AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA5AAAAHQAAAAIAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDAAAAtgAA
- APkAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- APwAAADKAAAAWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAsAAAApAAAAPMAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA9wAAALAAAAA3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAaAAAAkgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADtAAAAmAAAABsAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAfgAAAN8AAAD+AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/gAA
- AOAAAAB9AAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAZwAAANUAAAD7AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD7AAAA0AAAAFwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASwAA
- AMgAAAD4AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPYAAAC8AAAANgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAIoAAADSAAAA3wAAAN8AAADfAAAA3wAAAN8AAADnAAAA9wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7gAA
- AJIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVAAAAbQAAAHAAAABwAAAAcAAAAHAAAABwAAAAlAAA
- ANsAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA9AAAAMMAAACnAAAApwAA
- AKcAAACnAAAApwAAAKIAAAB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AOEAAABhAAAAFwAAABcAAAAXAAAAFwAAABcAAAAUAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAvwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAADeAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAL8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA3gAAAFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAN4AAABSAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAABAAAAAvwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAADeAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAL8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA3gAAAFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAC/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAN4AAABSAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAABAAAAAvwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADeAAAAUgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAL8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA3gAAAFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAN4AAABSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAvwAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADeAAAAUgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAQAAAAL8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA3gAA
- AFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAN4AAABSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAvwAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADeAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA
- AL8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA3gAAAFIAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AN4AAABSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAvwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAADeAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAL8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA3gAAAFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAN4AAABSAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAABAAAAAvwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAADeAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAL0AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA2wAAAFEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0AAACeAAAA+QAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/gAAAL0AAAA+AAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAADgAAAAAAAAAGAAAAAAAAAAYAAAAAAAAABAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//////+AAAH//////4AAAf
- //////gAAB//////+AAAH//////4AAAf//////gAAB//////+AAAH//////4AAAf//////gAAB//////
- +AAAH//////4AAAf//////gAAB//////+AAAH//8P//4AP////gf////////8A/////////wB///////
- /+AD////////wAP///////+AAf///////wAA////////AAD///////4AAH///////AAAP//////8AAA/
- //////gAAB//////8AAAD//////gAAAH/////8AAAAP/////wAAAA//////AAAAD/////8AAAAP/////
- /4AAA///////gAH///////+AAf///////4AB////////gAH///////+AAf///////4AB////////gAH/
- //////+AAf///////4AB////////gAH///////+AAf///////4AB////////gAH///////+AAf//////
- /4AB////////gAH///////+AAf///////4AB////////gAH///////+AAf///////4AB////
-
-
-
\ No newline at end of file
diff --git a/TwitchDownloader/frmChatDownload.Designer.cs b/TwitchDownloader/frmChatDownload.Designer.cs
deleted file mode 100644
index 751feae4..00000000
--- a/TwitchDownloader/frmChatDownload.Designer.cs
+++ /dev/null
@@ -1,484 +0,0 @@
-namespace TwitchDownloader
-{
- partial class frmChatDownload
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.statusStrip = new System.Windows.Forms.StatusStrip();
- this.toolStatus = new System.Windows.Forms.ToolStripStatusLabel();
- this.toolProgressBar = new System.Windows.Forms.ToolStripProgressBar();
- this.btnDownload = new System.Windows.Forms.Button();
- this.label6 = new System.Windows.Forms.Label();
- this.textLog = new System.Windows.Forms.TextBox();
- this.labelCreated = new System.Windows.Forms.Label();
- this.labelStreamer = new System.Windows.Forms.Label();
- this.label16 = new System.Windows.Forms.Label();
- this.textTitle = new System.Windows.Forms.TextBox();
- this.label15 = new System.Windows.Forms.Label();
- this.label14 = new System.Windows.Forms.Label();
- this.pictureThumb = new System.Windows.Forms.PictureBox();
- this.label7 = new System.Windows.Forms.Label();
- this.btnGetInfo = new System.Windows.Forms.Button();
- this.textUrl = new System.Windows.Forms.TextBox();
- this.label1 = new System.Windows.Forms.Label();
- this.radioJSON = new System.Windows.Forms.RadioButton();
- this.radioTXT = new System.Windows.Forms.RadioButton();
- this.label12 = new System.Windows.Forms.Label();
- this.label13 = new System.Windows.Forms.Label();
- this.numEndSecond = new System.Windows.Forms.NumericUpDown();
- this.numEndMinute = new System.Windows.Forms.NumericUpDown();
- this.numEndHour = new System.Windows.Forms.NumericUpDown();
- this.label11 = new System.Windows.Forms.Label();
- this.label10 = new System.Windows.Forms.Label();
- this.numStartSecond = new System.Windows.Forms.NumericUpDown();
- this.numStartMinute = new System.Windows.Forms.NumericUpDown();
- this.numStartHour = new System.Windows.Forms.NumericUpDown();
- this.checkCropEnd = new System.Windows.Forms.CheckBox();
- this.checkCropStart = new System.Windows.Forms.CheckBox();
- this.label5 = new System.Windows.Forms.Label();
- this.panel2 = new System.Windows.Forms.Panel();
- this.backgroundDownloadManager = new System.ComponentModel.BackgroundWorker();
- this.statusStrip.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.pictureThumb)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndSecond)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndMinute)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndHour)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.numStartSecond)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.numStartMinute)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.numStartHour)).BeginInit();
- this.panel2.SuspendLayout();
- this.SuspendLayout();
- //
- // statusStrip
- //
- this.statusStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
- this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.toolStatus,
- this.toolProgressBar});
- this.statusStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow;
- this.statusStrip.Location = new System.Drawing.Point(0, 368);
- this.statusStrip.Name = "statusStrip";
- this.statusStrip.Size = new System.Drawing.Size(812, 22);
- this.statusStrip.SizingGrip = false;
- this.statusStrip.TabIndex = 66;
- this.statusStrip.Text = "statusStrip1";
- //
- // toolStatus
- //
- this.toolStatus.Name = "toolStatus";
- this.toolStatus.Size = new System.Drawing.Size(26, 17);
- this.toolStatus.Text = "Idle";
- //
- // toolProgressBar
- //
- this.toolProgressBar.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
- this.toolProgressBar.Name = "toolProgressBar";
- this.toolProgressBar.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
- this.toolProgressBar.Size = new System.Drawing.Size(200, 16);
- //
- // btnDownload
- //
- this.btnDownload.Enabled = false;
- this.btnDownload.Location = new System.Drawing.Point(369, 236);
- this.btnDownload.Name = "btnDownload";
- this.btnDownload.Size = new System.Drawing.Size(111, 41);
- this.btnDownload.TabIndex = 65;
- this.btnDownload.Text = "Download";
- this.btnDownload.UseVisualStyleBackColor = true;
- this.btnDownload.Click += new System.EventHandler(this.BtnDownload_Click);
- //
- // label6
- //
- this.label6.AutoSize = true;
- this.label6.Location = new System.Drawing.Point(606, 62);
- this.label6.Name = "label6";
- this.label6.Size = new System.Drawing.Size(31, 13);
- this.label6.TabIndex = 64;
- this.label6.Text = "Log :";
- //
- // textLog
- //
- this.textLog.Location = new System.Drawing.Point(609, 78);
- this.textLog.Multiline = true;
- this.textLog.Name = "textLog";
- this.textLog.Size = new System.Drawing.Size(175, 264);
- this.textLog.TabIndex = 63;
- //
- // labelCreated
- //
- this.labelCreated.AutoSize = true;
- this.labelCreated.Location = new System.Drawing.Point(91, 236);
- this.labelCreated.Name = "labelCreated";
- this.labelCreated.Size = new System.Drawing.Size(0, 13);
- this.labelCreated.TabIndex = 61;
- //
- // labelStreamer
- //
- this.labelStreamer.AutoSize = true;
- this.labelStreamer.Location = new System.Drawing.Point(91, 214);
- this.labelStreamer.Name = "labelStreamer";
- this.labelStreamer.Size = new System.Drawing.Size(0, 13);
- this.labelStreamer.TabIndex = 62;
- //
- // label16
- //
- this.label16.AutoSize = true;
- this.label16.Location = new System.Drawing.Point(19, 62);
- this.label16.Name = "label16";
- this.label16.Size = new System.Drawing.Size(62, 13);
- this.label16.TabIndex = 60;
- this.label16.Text = "Thumbnail :";
- //
- // textTitle
- //
- this.textTitle.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.textTitle.Location = new System.Drawing.Point(22, 279);
- this.textTitle.Multiline = true;
- this.textTitle.Name = "textTitle";
- this.textTitle.ReadOnly = true;
- this.textTitle.Size = new System.Drawing.Size(200, 63);
- this.textTitle.TabIndex = 59;
- //
- // label15
- //
- this.label15.AutoSize = true;
- this.label15.Location = new System.Drawing.Point(22, 236);
- this.label15.Name = "label15";
- this.label15.Size = new System.Drawing.Size(63, 13);
- this.label15.TabIndex = 58;
- this.label15.Text = "Created At :";
- //
- // label14
- //
- this.label14.AutoSize = true;
- this.label14.Location = new System.Drawing.Point(30, 214);
- this.label14.Name = "label14";
- this.label14.Size = new System.Drawing.Size(55, 13);
- this.label14.TabIndex = 57;
- this.label14.Text = "Streamer :";
- //
- // pictureThumb
- //
- this.pictureThumb.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.pictureThumb.Location = new System.Drawing.Point(22, 78);
- this.pictureThumb.Name = "pictureThumb";
- this.pictureThumb.Size = new System.Drawing.Size(200, 125);
- this.pictureThumb.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
- this.pictureThumb.TabIndex = 56;
- this.pictureThumb.TabStop = false;
- //
- // label7
- //
- this.label7.AutoSize = true;
- this.label7.Location = new System.Drawing.Point(52, 258);
- this.label7.Name = "label7";
- this.label7.Size = new System.Drawing.Size(33, 13);
- this.label7.TabIndex = 55;
- this.label7.Text = "Title :";
- //
- // btnGetInfo
- //
- this.btnGetInfo.Location = new System.Drawing.Point(510, 33);
- this.btnGetInfo.Name = "btnGetInfo";
- this.btnGetInfo.Size = new System.Drawing.Size(75, 23);
- this.btnGetInfo.TabIndex = 52;
- this.btnGetInfo.Text = "Get Info";
- this.btnGetInfo.UseVisualStyleBackColor = true;
- this.btnGetInfo.Click += new System.EventHandler(this.BtnGetInfo_Click);
- //
- // textUrl
- //
- this.textUrl.Location = new System.Drawing.Point(301, 35);
- this.textUrl.Name = "textUrl";
- this.textUrl.Size = new System.Drawing.Size(203, 20);
- this.textUrl.TabIndex = 0;
- //
- // label1
- //
- this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(223, 38);
- this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(72, 13);
- this.label1.TabIndex = 50;
- this.label1.Text = "Clip/VOD ID :";
- //
- // radioJSON
- //
- this.radioJSON.AutoSize = true;
- this.radioJSON.Checked = true;
- this.radioJSON.Enabled = false;
- this.radioJSON.Location = new System.Drawing.Point(4, 3);
- this.radioJSON.Name = "radioJSON";
- this.radioJSON.Size = new System.Drawing.Size(105, 17);
- this.radioJSON.TabIndex = 69;
- this.radioJSON.TabStop = true;
- this.radioJSON.Text = "Advanced JSON";
- this.radioJSON.UseVisualStyleBackColor = true;
- //
- // radioTXT
- //
- this.radioTXT.AutoSize = true;
- this.radioTXT.Enabled = false;
- this.radioTXT.Location = new System.Drawing.Point(115, 3);
- this.radioTXT.Name = "radioTXT";
- this.radioTXT.Size = new System.Drawing.Size(80, 17);
- this.radioTXT.TabIndex = 70;
- this.radioTXT.Text = "Simple TXT";
- this.radioTXT.UseVisualStyleBackColor = true;
- //
- // label12
- //
- this.label12.AutoSize = true;
- this.label12.Enabled = false;
- this.label12.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label12.Location = new System.Drawing.Point(443, 184);
- this.label12.Name = "label12";
- this.label12.Size = new System.Drawing.Size(11, 13);
- this.label12.TabIndex = 83;
- this.label12.Text = ":";
- //
- // label13
- //
- this.label13.AutoSize = true;
- this.label13.Enabled = false;
- this.label13.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label13.Location = new System.Drawing.Point(495, 184);
- this.label13.Name = "label13";
- this.label13.Size = new System.Drawing.Size(11, 13);
- this.label13.TabIndex = 82;
- this.label13.Text = ":";
- //
- // numEndSecond
- //
- this.numEndSecond.Enabled = false;
- this.numEndSecond.Location = new System.Drawing.Point(508, 180);
- this.numEndSecond.Name = "numEndSecond";
- this.numEndSecond.Size = new System.Drawing.Size(35, 20);
- this.numEndSecond.TabIndex = 81;
- //
- // numEndMinute
- //
- this.numEndMinute.Enabled = false;
- this.numEndMinute.Location = new System.Drawing.Point(456, 180);
- this.numEndMinute.Name = "numEndMinute";
- this.numEndMinute.Size = new System.Drawing.Size(35, 20);
- this.numEndMinute.TabIndex = 80;
- //
- // numEndHour
- //
- this.numEndHour.Enabled = false;
- this.numEndHour.Location = new System.Drawing.Point(405, 180);
- this.numEndHour.Name = "numEndHour";
- this.numEndHour.Size = new System.Drawing.Size(35, 20);
- this.numEndHour.TabIndex = 79;
- //
- // label11
- //
- this.label11.AutoSize = true;
- this.label11.Enabled = false;
- this.label11.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label11.Location = new System.Drawing.Point(443, 158);
- this.label11.Name = "label11";
- this.label11.Size = new System.Drawing.Size(11, 13);
- this.label11.TabIndex = 78;
- this.label11.Text = ":";
- //
- // label10
- //
- this.label10.AutoSize = true;
- this.label10.Enabled = false;
- this.label10.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label10.Location = new System.Drawing.Point(495, 158);
- this.label10.Name = "label10";
- this.label10.Size = new System.Drawing.Size(11, 13);
- this.label10.TabIndex = 77;
- this.label10.Text = ":";
- //
- // numStartSecond
- //
- this.numStartSecond.Enabled = false;
- this.numStartSecond.Location = new System.Drawing.Point(508, 154);
- this.numStartSecond.Name = "numStartSecond";
- this.numStartSecond.Size = new System.Drawing.Size(35, 20);
- this.numStartSecond.TabIndex = 76;
- //
- // numStartMinute
- //
- this.numStartMinute.Enabled = false;
- this.numStartMinute.Location = new System.Drawing.Point(456, 154);
- this.numStartMinute.Name = "numStartMinute";
- this.numStartMinute.Size = new System.Drawing.Size(35, 20);
- this.numStartMinute.TabIndex = 75;
- //
- // numStartHour
- //
- this.numStartHour.Enabled = false;
- this.numStartHour.Location = new System.Drawing.Point(405, 154);
- this.numStartHour.Name = "numStartHour";
- this.numStartHour.Size = new System.Drawing.Size(35, 20);
- this.numStartHour.TabIndex = 74;
- //
- // checkCropEnd
- //
- this.checkCropEnd.AutoSize = true;
- this.checkCropEnd.Enabled = false;
- this.checkCropEnd.Location = new System.Drawing.Point(340, 183);
- this.checkCropEnd.Name = "checkCropEnd";
- this.checkCropEnd.Size = new System.Drawing.Size(45, 17);
- this.checkCropEnd.TabIndex = 73;
- this.checkCropEnd.Text = "End";
- this.checkCropEnd.UseVisualStyleBackColor = true;
- //
- // checkCropStart
- //
- this.checkCropStart.AutoSize = true;
- this.checkCropStart.Enabled = false;
- this.checkCropStart.Location = new System.Drawing.Point(340, 157);
- this.checkCropStart.Name = "checkCropStart";
- this.checkCropStart.Size = new System.Drawing.Size(48, 17);
- this.checkCropStart.TabIndex = 72;
- this.checkCropStart.Text = "Start";
- this.checkCropStart.UseVisualStyleBackColor = true;
- //
- // label5
- //
- this.label5.AutoSize = true;
- this.label5.Location = new System.Drawing.Point(270, 158);
- this.label5.Name = "label5";
- this.label5.Size = new System.Drawing.Size(61, 13);
- this.label5.TabIndex = 71;
- this.label5.Text = "Crop Time :";
- //
- // panel2
- //
- this.panel2.Controls.Add(this.radioTXT);
- this.panel2.Controls.Add(this.radioJSON);
- this.panel2.Location = new System.Drawing.Point(330, 107);
- this.panel2.Name = "panel2";
- this.panel2.Size = new System.Drawing.Size(200, 26);
- this.panel2.TabIndex = 87;
- //
- // backgroundDownloadManager
- //
- this.backgroundDownloadManager.WorkerReportsProgress = true;
- this.backgroundDownloadManager.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BackgroundDownloadManager_DoWork);
- this.backgroundDownloadManager.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.BackgroundDownloadManager_ProgressChanged);
- this.backgroundDownloadManager.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.BackgroundDownloadManager_RunWorkerCompleted);
- //
- // frmChatDownload
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(812, 390);
- this.ControlBox = false;
- this.Controls.Add(this.panel2);
- this.Controls.Add(this.label12);
- this.Controls.Add(this.label13);
- this.Controls.Add(this.numEndSecond);
- this.Controls.Add(this.numEndMinute);
- this.Controls.Add(this.numEndHour);
- this.Controls.Add(this.label11);
- this.Controls.Add(this.label10);
- this.Controls.Add(this.numStartSecond);
- this.Controls.Add(this.numStartMinute);
- this.Controls.Add(this.numStartHour);
- this.Controls.Add(this.checkCropEnd);
- this.Controls.Add(this.checkCropStart);
- this.Controls.Add(this.label5);
- this.Controls.Add(this.statusStrip);
- this.Controls.Add(this.btnDownload);
- this.Controls.Add(this.label6);
- this.Controls.Add(this.textLog);
- this.Controls.Add(this.labelCreated);
- this.Controls.Add(this.labelStreamer);
- this.Controls.Add(this.label16);
- this.Controls.Add(this.textTitle);
- this.Controls.Add(this.label15);
- this.Controls.Add(this.label14);
- this.Controls.Add(this.pictureThumb);
- this.Controls.Add(this.label7);
- this.Controls.Add(this.btnGetInfo);
- this.Controls.Add(this.textUrl);
- this.Controls.Add(this.label1);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
- this.Name = "frmChatDownload";
- this.Text = "frmChatDownload";
- this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
- this.statusStrip.ResumeLayout(false);
- this.statusStrip.PerformLayout();
- ((System.ComponentModel.ISupportInitialize)(this.pictureThumb)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndSecond)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndMinute)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndHour)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.numStartSecond)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.numStartMinute)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.numStartHour)).EndInit();
- this.panel2.ResumeLayout(false);
- this.panel2.PerformLayout();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.StatusStrip statusStrip;
- private System.Windows.Forms.ToolStripStatusLabel toolStatus;
- private System.Windows.Forms.Button btnDownload;
- private System.Windows.Forms.Label label6;
- private System.Windows.Forms.TextBox textLog;
- private System.Windows.Forms.Label labelCreated;
- private System.Windows.Forms.Label labelStreamer;
- private System.Windows.Forms.Label label16;
- private System.Windows.Forms.TextBox textTitle;
- private System.Windows.Forms.Label label15;
- private System.Windows.Forms.Label label14;
- private System.Windows.Forms.PictureBox pictureThumb;
- private System.Windows.Forms.Label label7;
- private System.Windows.Forms.Button btnGetInfo;
- private System.Windows.Forms.TextBox textUrl;
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.RadioButton radioJSON;
- private System.Windows.Forms.RadioButton radioTXT;
- private System.Windows.Forms.Label label12;
- private System.Windows.Forms.Label label13;
- private System.Windows.Forms.NumericUpDown numEndSecond;
- private System.Windows.Forms.NumericUpDown numEndMinute;
- private System.Windows.Forms.NumericUpDown numEndHour;
- private System.Windows.Forms.Label label11;
- private System.Windows.Forms.Label label10;
- private System.Windows.Forms.NumericUpDown numStartSecond;
- private System.Windows.Forms.NumericUpDown numStartMinute;
- private System.Windows.Forms.NumericUpDown numStartHour;
- private System.Windows.Forms.CheckBox checkCropEnd;
- private System.Windows.Forms.CheckBox checkCropStart;
- private System.Windows.Forms.Label label5;
- private System.Windows.Forms.Panel panel2;
- private System.ComponentModel.BackgroundWorker backgroundDownloadManager;
- private System.Windows.Forms.ToolStripProgressBar toolProgressBar;
- }
-}
\ No newline at end of file
diff --git a/TwitchDownloader/frmChatDownload.cs b/TwitchDownloader/frmChatDownload.cs
deleted file mode 100644
index 382c7fba..00000000
--- a/TwitchDownloader/frmChatDownload.cs
+++ /dev/null
@@ -1,304 +0,0 @@
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace TwitchDownloader
-{
- public partial class frmChatDownload : Form
- {
- bool isVod = true;
- int streamerId = 0;
- JObject videoData = new JObject();
- public frmChatDownload()
- {
- InitializeComponent();
- }
-
- private async void BtnGetInfo_Click(object sender, EventArgs e)
- {
- try
- {
- isVod = textUrl.Text.Any(char.IsDigit);
-
- btnGetInfo.Enabled = false;
- if (isVod)
- {
- string VodId = textUrl.Text;
- Task taskInfo = GetVodInfo(VodId);
- await Task.WhenAll(taskInfo);
-
- JToken clipData = taskInfo.Result;
- videoData = taskInfo.Result;
- string thumbUrl = videoData["data"][0]["thumbnail_url"].ToString().Replace("%{width}", pictureThumb.Width.ToString()).Replace("%{height}", pictureThumb.Height.ToString());
- Task taskThumb = GetClipThumb(thumbUrl);
- await Task.WhenAll(taskThumb);
-
- pictureThumb.Image = taskThumb.Result;
- textTitle.Text = taskInfo.Result["data"][0]["title"].ToString();
- labelStreamer.Text = taskInfo.Result["data"][0]["user_name"].ToString();
- labelCreated.Text = taskInfo.Result["data"][0]["created_at"].ToString();
- streamerId = taskInfo.Result["data"][0]["user_id"].ToObject();
- SetEnabled(true, false);
- }
- else
- {
- string clipId = textUrl.Text;
- Task taskInfo = GetClipInfo(clipId);
- await Task.WhenAll(taskInfo);
-
- JToken clipData = taskInfo.Result;
- videoData = taskInfo.Result;
- string thumbUrl = clipData["thumbnails"]["medium"].ToString();
- Task taskThumb = GetClipThumb(thumbUrl);
- await Task.WhenAll(taskThumb);
-
- pictureThumb.Image = taskThumb.Result;
- labelStreamer.Text = clipData["broadcaster"]["display_name"].ToString();
- labelCreated.Text = clipData["created_at"].ToString();
- textTitle.Text = clipData["title"].ToString();
- streamerId = clipData["broadcaster"]["id"].ToObject();
- SetEnabled(true, false);
- SetEnabled(false, true);
- }
-
- btnGetInfo.Enabled = true;
- }
- catch (WebException)
- {
- MessageBox.Show("Unable to get information. Please double check VOD ID or Clip Slug and try again", "Unable to get info", MessageBoxButtons.OK, MessageBoxIcon.Error);
- btnGetInfo.Enabled = true;
- SetEnabled(false, false);
- }
- }
-
- private void SetEnabled(bool isEnabled, bool onlyCrop)
- {
- checkCropStart.Enabled = isEnabled;
- numStartHour.Enabled = isEnabled;
- numStartMinute.Enabled = isEnabled;
- numStartSecond.Enabled = isEnabled;
- checkCropEnd.Enabled = isEnabled;
- numEndHour.Enabled = isEnabled;
- numEndMinute.Enabled = isEnabled;
- numEndSecond.Enabled = isEnabled;
-
- if (!onlyCrop)
- {
- radioJSON.Enabled = isEnabled;
- radioTXT.Enabled = isEnabled;
- btnDownload.Enabled = isEnabled;
- }
- }
-
- private async Task GetClipInfo(object clipId)
- {
- using (WebClient client = new WebClient())
- {
- client.Headers.Add("Accept", "application/vnd.twitchtv.v5+json");
- client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
- string response = await client.DownloadStringTaskAsync(String.Format("https://api.twitch.tv/kraken/clips/{0}", clipId));
- JObject result = JObject.Parse(response);
- return result;
- }
- }
-
- private async Task GetVodInfo(string id)
- {
- using (WebClient client = new WebClient())
- {
- client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
- string response = await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/videos?id=" + id);
- JObject result = JObject.Parse(response);
- return result;
- }
- }
-
- private async Task GetClipThumb(string thumbUrl)
- {
- Bitmap result = new Bitmap(100, 100);
- using (WebClient client = new WebClient())
- {
- client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
- using (Stream s = await client.OpenReadTaskAsync(thumbUrl))
- {
- result = new Bitmap(s);
- }
- }
- return result;
- }
-
- private void BtnDownload_Click(object sender, EventArgs e)
- {
- SaveFileDialog saveFileDialog = new SaveFileDialog();
-
- if (radioJSON.Checked)
- saveFileDialog.Filter = "JSON Files | *.json";
- else
- saveFileDialog.Filter = "TXT Files | *.txt";
-
- saveFileDialog.RestoreDirectory = true;
-
- if (saveFileDialog.ShowDialog() == DialogResult.OK)
- {
- ChatDownloadInfo info;
- if (isVod)
- {
- int startTime = 0;
- int duration = 0;
-
- if (checkCropStart.Checked)
- {
- TimeSpan start = new TimeSpan((int)numStartHour.Value, (int)numStartMinute.Value, (int)numStartSecond.Value);
- startTime = (int)Math.Round(start.TotalSeconds);
- }
-
- if (checkCropEnd.Checked)
- {
- TimeSpan end = new TimeSpan((int)numEndHour.Value, (int)numEndMinute.Value, (int)numEndSecond.Value);
- duration = (int)Math.Ceiling(end.TotalSeconds - startTime);
- }
- else
- {
- TimeSpan vodLength = TimeSpan.Parse(Regex.Replace(videoData["data"][0]["duration"].ToString(), @"[^\d]", ":").TrimEnd(':'));
- duration = (int)Math.Ceiling(vodLength.TotalSeconds);
- }
- info = new ChatDownloadInfo(isVod, textUrl.Text, saveFileDialog.FileName, videoData["data"][0]["id"].ToString(), startTime, duration, radioJSON.Checked, labelStreamer.Text, streamerId);
- }
- else
- info = new ChatDownloadInfo(isVod, textUrl.Text, saveFileDialog.FileName, videoData["vod"]["id"].ToString(), videoData["vod"]["offset"].ToObject(), videoData["duration"].ToObject(), radioJSON.Checked, labelStreamer.Text, streamerId);
- toolStatus.Text = "Downloading";
- btnGetInfo.Enabled = false;
- SetEnabled(false, false);
-
- backgroundDownloadManager.RunWorkerAsync(info);
- }
- }
-
- private void BackgroundDownloadManager_DoWork(object sender, DoWorkEventArgs e)
- {
- ChatDownloadInfo clipInfo = (ChatDownloadInfo)e.Argument;
-
- using (WebClient client = new WebClient())
- {
- client.Encoding = Encoding.UTF8;
- client.Headers.Add("Accept", "application/vnd.twitchtv.v5+json; charset=UTF-8");
- client.Headers.Add("Client-Id", "kimne78kx3ncx6brgo4mv6wki5h1ko");
-
- bool isFirst = true;
- string cursor = "";
- double latestMessage = clipInfo.offset - 1;
- double videoStart = clipInfo.offset;
- double videoDuration = clipInfo.duration;
- JObject result = new JObject();
- JArray comments = new JArray();
- JObject streamer = new JObject();
-
- streamer["name"] = clipInfo.streamer_name;
- streamer["id"] = clipInfo.streamer_id;
-
- while (latestMessage < (videoStart + videoDuration))
- {
- string response;
- if (isFirst)
- response = client.DownloadString(String.Format("https://api.twitch.tv/v5/videos/{0}/comments?content_offset_seconds={1}", clipInfo.vod_id, clipInfo.offset));
- else
- response = client.DownloadString(String.Format("https://api.twitch.tv/v5/videos/{0}/comments?cursor={1}", clipInfo.vod_id, cursor));
-
- JObject res = JObject.Parse(response);
-
- foreach (var comment in res["comments"])
- {
- if (latestMessage < (videoStart + videoDuration))
- comments.Add(comment);
-
- latestMessage = comment["content_offset_seconds"].ToObject();
- }
- if (res["_next"] == null)
- break;
- else
- cursor = res["_next"].ToString();
-
- int percent = (int)Math.Floor((latestMessage - videoStart)/videoDuration * 100);
- backgroundDownloadManager.ReportProgress(percent, String.Format("Downloading {0}%", percent));
-
- if (isFirst)
- isFirst = false;
-
- }
-
- result["streamer"] = streamer;
- result["comments"] = comments;
-
- using (StreamWriter sw = new StreamWriter(clipInfo.path))
- {
- if (clipInfo.is_json)
- {
- sw.Write(result.ToString(Newtonsoft.Json.Formatting.Indented));
- }
- else
- {
- foreach (var comment in result["comments"])
- {
- string username = comment["commenter"]["display_name"].ToString();
- string message = comment["message"]["body"].ToString();
- sw.WriteLine(String.Format("{0}: {1}", username, message));
- }
- }
-
- sw.Flush();
- sw.Close();
- }
- }
- }
-
- private void BackgroundDownloadManager_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
- {
- toolStatus.Text = "Done";
- btnGetInfo.Enabled = true;
- }
-
- private void BackgroundDownloadManager_ProgressChanged(object sender, ProgressChangedEventArgs e)
- {
- string message = (string)e.UserState;
- toolStatus.Text = message;
- toolProgressBar.Value = e.ProgressPercentage >= 100 ? 100 : e.ProgressPercentage;
- }
- }
-}
-
-public class ChatDownloadInfo
-{
- public bool is_vod { get; set; }
- public string id { get; set; }
- public string path { get; set; }
- public string vod_id { get; set; }
- public int offset { get; set; }
- public double duration { get; set; }
- public bool is_json { get; set; }
- public string streamer_name { get; set; }
- public int streamer_id { get; set; }
-
- public ChatDownloadInfo(bool Is_vod, string Id, string Path, string Vod_id, int Offset , double Duration, bool Is_json, string Streamer_name, int Streamer_id)
- {
- is_vod = Is_vod;
- id = Id;
- path = Path;
- vod_id = Vod_id;
- offset = Offset;
- duration = Duration;
- is_json = Is_json;
- streamer_name = Streamer_name;
- streamer_id = Streamer_id;
- }
-}
\ No newline at end of file
diff --git a/TwitchDownloader/frmChatDownload.resx b/TwitchDownloader/frmChatDownload.resx
deleted file mode 100644
index 4721b491..00000000
--- a/TwitchDownloader/frmChatDownload.resx
+++ /dev/null
@@ -1,126 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- 17, 17
-
-
- 238, 17
-
-
\ No newline at end of file
diff --git a/TwitchDownloader/frmChatRender.Designer.cs b/TwitchDownloader/frmChatRender.Designer.cs
deleted file mode 100644
index b7b1ebd3..00000000
--- a/TwitchDownloader/frmChatRender.Designer.cs
+++ /dev/null
@@ -1,429 +0,0 @@
-namespace TwitchDownloader
-{
- partial class frmChatRender
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.colorDialog = new System.Windows.Forms.ColorDialog();
- this.label2 = new System.Windows.Forms.Label();
- this.label4 = new System.Windows.Forms.Label();
- this.label5 = new System.Windows.Forms.Label();
- this.label7 = new System.Windows.Forms.Label();
- this.label8 = new System.Windows.Forms.Label();
- this.btnColor = new System.Windows.Forms.Button();
- this.textColor = new System.Windows.Forms.TextBox();
- this.textHeight = new System.Windows.Forms.TextBox();
- this.textWidth = new System.Windows.Forms.TextBox();
- this.checkBTTV = new System.Windows.Forms.CheckBox();
- this.checkFFZ = new System.Windows.Forms.CheckBox();
- this.textJSON = new System.Windows.Forms.TextBox();
- this.btnBrowse = new System.Windows.Forms.Button();
- this.label9 = new System.Windows.Forms.Label();
- this.btnRender = new System.Windows.Forms.Button();
- this.backgroundRenderManager = new System.ComponentModel.BackgroundWorker();
- this.statusStrip = new System.Windows.Forms.StatusStrip();
- this.toolStatus = new System.Windows.Forms.ToolStripStatusLabel();
- this.toolProgressBar = new System.Windows.Forms.ToolStripProgressBar();
- this.label6 = new System.Windows.Forms.Label();
- this.textLog = new System.Windows.Forms.TextBox();
- this.label1 = new System.Windows.Forms.Label();
- this.checkOutline = new System.Windows.Forms.CheckBox();
- this.comboFonts = new System.Windows.Forms.ComboBox();
- this.label3 = new System.Windows.Forms.Label();
- this.label10 = new System.Windows.Forms.Label();
- this.textFontSize = new System.Windows.Forms.TextBox();
- this.label11 = new System.Windows.Forms.Label();
- this.textUpdateTime = new System.Windows.Forms.TextBox();
- this.statusStrip.SuspendLayout();
- this.SuspendLayout();
- //
- // colorDialog
- //
- this.colorDialog.Color = System.Drawing.Color.FromArgb(((int)(((byte)(17)))), ((int)(((byte)(17)))), ((int)(((byte)(17)))));
- //
- // label2
- //
- this.label2.AutoSize = true;
- this.label2.Location = new System.Drawing.Point(147, 151);
- this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(129, 17);
- this.label2.TabIndex = 2;
- this.label2.Text = "Background Color :";
- //
- // label4
- //
- this.label4.AutoSize = true;
- this.label4.Location = new System.Drawing.Point(475, 151);
- this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label4.Name = "label4";
- this.label4.Size = new System.Drawing.Size(57, 17);
- this.label4.TabIndex = 2;
- this.label4.Text = "Height :";
- //
- // label5
- //
- this.label5.AutoSize = true;
- this.label5.Location = new System.Drawing.Point(479, 185);
- this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label5.Name = "label5";
- this.label5.Size = new System.Drawing.Size(52, 17);
- this.label5.TabIndex = 2;
- this.label5.Text = "Width :";
- //
- // label7
- //
- this.label7.AutoSize = true;
- this.label7.Location = new System.Drawing.Point(172, 185);
- this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label7.Name = "label7";
- this.label7.Size = new System.Drawing.Size(103, 17);
- this.label7.TabIndex = 3;
- this.label7.Text = "BTTV Emotes :";
- //
- // label8
- //
- this.label8.AutoSize = true;
- this.label8.Location = new System.Drawing.Point(332, 185);
- this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label8.Name = "label8";
- this.label8.Size = new System.Drawing.Size(92, 17);
- this.label8.TabIndex = 3;
- this.label8.Text = "FFZ Emotes :";
- //
- // btnColor
- //
- this.btnColor.BackColor = System.Drawing.Color.Black;
- this.btnColor.Location = new System.Drawing.Point(283, 146);
- this.btnColor.Margin = new System.Windows.Forms.Padding(4);
- this.btnColor.Name = "btnColor";
- this.btnColor.Size = new System.Drawing.Size(41, 25);
- this.btnColor.TabIndex = 4;
- this.btnColor.UseVisualStyleBackColor = false;
- this.btnColor.Click += new System.EventHandler(this.BntColor_Click);
- //
- // textColor
- //
- this.textColor.Location = new System.Drawing.Point(332, 148);
- this.textColor.Margin = new System.Windows.Forms.Padding(4);
- this.textColor.Name = "textColor";
- this.textColor.Size = new System.Drawing.Size(132, 22);
- this.textColor.TabIndex = 5;
- this.textColor.Text = "#111111";
- this.textColor.TextChanged += new System.EventHandler(this.TextColor_TextChanged);
- //
- // textHeight
- //
- this.textHeight.Location = new System.Drawing.Point(541, 148);
- this.textHeight.Margin = new System.Windows.Forms.Padding(4);
- this.textHeight.Name = "textHeight";
- this.textHeight.Size = new System.Drawing.Size(92, 22);
- this.textHeight.TabIndex = 7;
- this.textHeight.Text = "500";
- //
- // textWidth
- //
- this.textWidth.Location = new System.Drawing.Point(541, 181);
- this.textWidth.Margin = new System.Windows.Forms.Padding(4);
- this.textWidth.Name = "textWidth";
- this.textWidth.Size = new System.Drawing.Size(92, 22);
- this.textWidth.TabIndex = 7;
- this.textWidth.Text = "300";
- //
- // checkBTTV
- //
- this.checkBTTV.AutoSize = true;
- this.checkBTTV.Checked = true;
- this.checkBTTV.CheckState = System.Windows.Forms.CheckState.Checked;
- this.checkBTTV.Location = new System.Drawing.Point(285, 185);
- this.checkBTTV.Margin = new System.Windows.Forms.Padding(4);
- this.checkBTTV.Name = "checkBTTV";
- this.checkBTTV.Size = new System.Drawing.Size(18, 17);
- this.checkBTTV.TabIndex = 8;
- this.checkBTTV.UseVisualStyleBackColor = true;
- //
- // checkFFZ
- //
- this.checkFFZ.AutoSize = true;
- this.checkFFZ.Checked = true;
- this.checkFFZ.CheckState = System.Windows.Forms.CheckState.Checked;
- this.checkFFZ.Location = new System.Drawing.Point(433, 185);
- this.checkFFZ.Margin = new System.Windows.Forms.Padding(4);
- this.checkFFZ.Name = "checkFFZ";
- this.checkFFZ.Size = new System.Drawing.Size(18, 17);
- this.checkFFZ.TabIndex = 8;
- this.checkFFZ.UseVisualStyleBackColor = true;
- //
- // textJSON
- //
- this.textJSON.Location = new System.Drawing.Point(253, 55);
- this.textJSON.Margin = new System.Windows.Forms.Padding(4);
- this.textJSON.Name = "textJSON";
- this.textJSON.Size = new System.Drawing.Size(293, 22);
- this.textJSON.TabIndex = 0;
- //
- // btnBrowse
- //
- this.btnBrowse.Location = new System.Drawing.Point(556, 53);
- this.btnBrowse.Margin = new System.Windows.Forms.Padding(4);
- this.btnBrowse.Name = "btnBrowse";
- this.btnBrowse.Size = new System.Drawing.Size(100, 28);
- this.btnBrowse.TabIndex = 10;
- this.btnBrowse.Text = "Browse";
- this.btnBrowse.UseVisualStyleBackColor = true;
- this.btnBrowse.Click += new System.EventHandler(this.BtnBrowse_Click);
- //
- // label9
- //
- this.label9.AutoSize = true;
- this.label9.Location = new System.Drawing.Point(165, 59);
- this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label9.Name = "label9";
- this.label9.Size = new System.Drawing.Size(79, 17);
- this.label9.TabIndex = 11;
- this.label9.Text = "JSON File :";
- //
- // btnRender
- //
- this.btnRender.Location = new System.Drawing.Point(365, 337);
- this.btnRender.Margin = new System.Windows.Forms.Padding(4);
- this.btnRender.Name = "btnRender";
- this.btnRender.Size = new System.Drawing.Size(148, 50);
- this.btnRender.TabIndex = 49;
- this.btnRender.Text = "Render Chat";
- this.btnRender.UseVisualStyleBackColor = true;
- this.btnRender.Click += new System.EventHandler(this.BtnRender_Click);
- //
- // backgroundRenderManager
- //
- this.backgroundRenderManager.WorkerReportsProgress = true;
- this.backgroundRenderManager.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BackgroundRenderManager_DoWork);
- this.backgroundRenderManager.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.BackgroundRenderManager_ProgressChanged);
- this.backgroundRenderManager.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.BackgroundRenderManager_RunWorkerCompleted);
- //
- // statusStrip
- //
- this.statusStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
- this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.toolStatus,
- this.toolProgressBar});
- this.statusStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow;
- this.statusStrip.Location = new System.Drawing.Point(0, 454);
- this.statusStrip.Name = "statusStrip";
- this.statusStrip.Padding = new System.Windows.Forms.Padding(1, 0, 19, 0);
- this.statusStrip.Size = new System.Drawing.Size(1083, 26);
- this.statusStrip.SizingGrip = false;
- this.statusStrip.TabIndex = 67;
- this.statusStrip.Text = "statusStrip1";
- //
- // toolStatus
- //
- this.toolStatus.Name = "toolStatus";
- this.toolStatus.Size = new System.Drawing.Size(34, 20);
- this.toolStatus.Text = "Idle";
- //
- // toolProgressBar
- //
- this.toolProgressBar.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
- this.toolProgressBar.Name = "toolProgressBar";
- this.toolProgressBar.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
- this.toolProgressBar.Size = new System.Drawing.Size(267, 18);
- //
- // label6
- //
- this.label6.AutoSize = true;
- this.label6.Location = new System.Drawing.Point(745, 33);
- this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label6.Name = "label6";
- this.label6.Size = new System.Drawing.Size(40, 17);
- this.label6.TabIndex = 69;
- this.label6.Text = "Log :";
- //
- // textLog
- //
- this.textLog.Location = new System.Drawing.Point(748, 59);
- this.textLog.Margin = new System.Windows.Forms.Padding(4);
- this.textLog.Multiline = true;
- this.textLog.Name = "textLog";
- this.textLog.Size = new System.Drawing.Size(296, 361);
- this.textLog.TabIndex = 68;
- //
- // label1
- //
- this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(84, 218);
- this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(191, 17);
- this.label1.TabIndex = 70;
- this.label1.Text = "Username/Message Outline :";
- //
- // checkOutline
- //
- this.checkOutline.AutoSize = true;
- this.checkOutline.Location = new System.Drawing.Point(285, 218);
- this.checkOutline.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
- this.checkOutline.Name = "checkOutline";
- this.checkOutline.Size = new System.Drawing.Size(18, 17);
- this.checkOutline.TabIndex = 71;
- this.checkOutline.UseVisualStyleBackColor = true;
- //
- // comboFonts
- //
- this.comboFonts.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this.comboFonts.FormattingEnabled = true;
- this.comboFonts.Location = new System.Drawing.Point(385, 213);
- this.comboFonts.Margin = new System.Windows.Forms.Padding(4);
- this.comboFonts.Name = "comboFonts";
- this.comboFonts.Size = new System.Drawing.Size(248, 24);
- this.comboFonts.TabIndex = 73;
- //
- // label3
- //
- this.label3.AutoSize = true;
- this.label3.Location = new System.Drawing.Point(332, 217);
- this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label3.Name = "label3";
- this.label3.Size = new System.Drawing.Size(44, 17);
- this.label3.TabIndex = 72;
- this.label3.Text = "Font :";
- //
- // label10
- //
- this.label10.AutoSize = true;
- this.label10.Location = new System.Drawing.Point(332, 255);
- this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label10.Name = "label10";
- this.label10.Size = new System.Drawing.Size(75, 17);
- this.label10.TabIndex = 74;
- this.label10.Text = "Font Size :";
- //
- // textFontSize
- //
- this.textFontSize.Location = new System.Drawing.Point(415, 251);
- this.textFontSize.Margin = new System.Windows.Forms.Padding(4);
- this.textFontSize.Name = "textFontSize";
- this.textFontSize.Size = new System.Drawing.Size(49, 22);
- this.textFontSize.TabIndex = 75;
- this.textFontSize.Text = "9";
- //
- // label11
- //
- this.label11.AutoSize = true;
- this.label11.Location = new System.Drawing.Point(481, 255);
- this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.label11.Name = "label11";
- this.label11.Size = new System.Drawing.Size(93, 17);
- this.label11.TabIndex = 76;
- this.label11.Text = "Update Time:";
- //
- // textUpdateTime
- //
- this.textUpdateTime.Location = new System.Drawing.Point(584, 251);
- this.textUpdateTime.Margin = new System.Windows.Forms.Padding(4);
- this.textUpdateTime.Name = "textUpdateTime";
- this.textUpdateTime.Size = new System.Drawing.Size(49, 22);
- this.textUpdateTime.TabIndex = 77;
- this.textUpdateTime.Text = "1.0";
- //
- // frmChatRender
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(1083, 480);
- this.ControlBox = false;
- this.Controls.Add(this.textUpdateTime);
- this.Controls.Add(this.label11);
- this.Controls.Add(this.textFontSize);
- this.Controls.Add(this.label10);
- this.Controls.Add(this.comboFonts);
- this.Controls.Add(this.label3);
- this.Controls.Add(this.checkOutline);
- this.Controls.Add(this.label1);
- this.Controls.Add(this.label6);
- this.Controls.Add(this.textLog);
- this.Controls.Add(this.statusStrip);
- this.Controls.Add(this.btnRender);
- this.Controls.Add(this.label9);
- this.Controls.Add(this.btnBrowse);
- this.Controls.Add(this.textJSON);
- this.Controls.Add(this.checkFFZ);
- this.Controls.Add(this.checkBTTV);
- this.Controls.Add(this.textWidth);
- this.Controls.Add(this.textHeight);
- this.Controls.Add(this.textColor);
- this.Controls.Add(this.btnColor);
- this.Controls.Add(this.label8);
- this.Controls.Add(this.label7);
- this.Controls.Add(this.label5);
- this.Controls.Add(this.label4);
- this.Controls.Add(this.label2);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
- this.Margin = new System.Windows.Forms.Padding(4);
- this.Name = "frmChatRender";
- this.Text = "frmChatRender";
- this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
- this.Load += new System.EventHandler(this.FrmChatRender_Load);
- this.statusStrip.ResumeLayout(false);
- this.statusStrip.PerformLayout();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
- private System.Windows.Forms.ColorDialog colorDialog;
- private System.Windows.Forms.Label label2;
- private System.Windows.Forms.Label label4;
- private System.Windows.Forms.Label label5;
- private System.Windows.Forms.Label label7;
- private System.Windows.Forms.Label label8;
- private System.Windows.Forms.Button btnColor;
- private System.Windows.Forms.TextBox textColor;
- private System.Windows.Forms.TextBox textHeight;
- private System.Windows.Forms.TextBox textWidth;
- private System.Windows.Forms.CheckBox checkBTTV;
- private System.Windows.Forms.CheckBox checkFFZ;
- private System.Windows.Forms.TextBox textJSON;
- private System.Windows.Forms.Button btnBrowse;
- private System.Windows.Forms.Label label9;
- private System.Windows.Forms.Button btnRender;
- private System.ComponentModel.BackgroundWorker backgroundRenderManager;
- private System.Windows.Forms.StatusStrip statusStrip;
- private System.Windows.Forms.ToolStripStatusLabel toolStatus;
- private System.Windows.Forms.ToolStripProgressBar toolProgressBar;
- private System.Windows.Forms.Label label6;
- private System.Windows.Forms.TextBox textLog;
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.CheckBox checkOutline;
- private System.Windows.Forms.ComboBox comboFonts;
- private System.Windows.Forms.Label label3;
- private System.Windows.Forms.Label label10;
- private System.Windows.Forms.TextBox textFontSize;
- private System.Windows.Forms.Label label11;
- private System.Windows.Forms.TextBox textUpdateTime;
- }
-}
\ No newline at end of file
diff --git a/TwitchDownloader/frmChatRender.cs b/TwitchDownloader/frmChatRender.cs
deleted file mode 100644
index 28c3126f..00000000
--- a/TwitchDownloader/frmChatRender.cs
+++ /dev/null
@@ -1,967 +0,0 @@
-using Accord.Video.FFMPEG;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Diagnostics;
-using System.Drawing;
-using System.Drawing.Drawing2D;
-using System.Drawing.Imaging;
-using System.Drawing.Text;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace TwitchDownloader
-{
- public partial class frmChatRender : Form
- {
- public frmChatRender()
- {
- InitializeComponent();
- }
-
- private void BntColor_Click(object sender, EventArgs e)
- {
- if (colorDialog.ShowDialog() == DialogResult.OK)
- {
- textColor.Text = ToHexValue(colorDialog.Color);
- }
- }
-
- public string ToHexValue(Color color)
- {
- return "#" + color.R.ToString("X2") +
- color.G.ToString("X2") +
- color.B.ToString("X2");
- }
-
- private void BtnRender_Click(object sender, EventArgs e)
- {
- SaveFileDialog saveFileDialog = new SaveFileDialog();
-
- saveFileDialog.Filter = "MP4 Files | *.mp4";
- saveFileDialog.RestoreDirectory = true;
-
- if (saveFileDialog.ShowDialog() == DialogResult.OK)
- {
- RenderOptions info = new RenderOptions(textJSON.Text, saveFileDialog.FileName, colorDialog.Color, Int32.Parse(textHeight.Text), Int32.Parse(textWidth.Text), checkBTTV.Checked, checkFFZ.Checked, checkOutline.Checked, (string)comboFonts.SelectedItem, Double.Parse(textFontSize.Text), Double.Parse(textUpdateTime.Text));
-
- backgroundRenderManager.RunWorkerAsync(info);
- btnRender.Enabled = false;
-
- Properties.Settings.Default.RENDER_FONT = (string)comboFonts.SelectedItem;
- Properties.Settings.Default.RENDER_COLOR = textColor.Text;
- Properties.Settings.Default.RENDER_HEIGHT = Int32.Parse(textHeight.Text);
- Properties.Settings.Default.RENDER_WIDTH = Int32.Parse(textWidth.Text);
- Properties.Settings.Default.RENDER_BTTV = checkBTTV.Checked;
- Properties.Settings.Default.RENDER_FFZ = checkFFZ.Checked;
- Properties.Settings.Default.RENDER_OUTLINE = checkOutline.Checked;
- Properties.Settings.Default.RENDER_FONT_SIZE = Double.Parse(textFontSize.Text);
- Properties.Settings.Default.RENDER_UPDATE_TIME = Double.Parse(textUpdateTime.Text);
- Properties.Settings.Default.Save();
- }
- }
-
- private void BackgroundRenderManager_DoWork(object sender, DoWorkEventArgs e)
- {
- RenderOptions renderOptions = (RenderOptions)e.Argument;
- JObject chatJson = JObject.Parse(File.ReadAllText(renderOptions.json_path));
- List finalComments = new List();
- List thirdPartyEmotes = new List();
- List chatBadges = new List();
- List> chatEmotes = new List>();
- Dictionary emojiCache = new Dictionary();
- Random rand = new Random();
- string[] defaultColors = { "#FF0000", "#0000FF", "#00FF00", "#B22222", "#FF7F50", "#9ACD32", "#FF4500", "#2E8B57", "#DAA520", "#D2691E", "#5F9EA0", "#1E90FF", "#FF69B4", "#8A2BE2", "#00FF7F" };
- string emojiRegex = "(?:0\x20E3|1\x20E3|2\x20E3|3\x20E3|4\x20E3|5\x20E3|6\x20E3|7\x20E3|8\x20E3|9\x20E3|#\x20E3|\\*\x20E3|\xD83C(?:\xDDE6\xD83C(?:\xDDE8|\xDDE9|\xDDEA|\xDDEB|\xDDEC|\xDDEE|\xDDF1|\xDDF2|\xDDF4|\xDDF6|\xDDF7|\xDDF8|\xDDF9|\xDDFA|\xDDFC|\xDDFD|\xDDFF)|\xDDE7\xD83C(?:\xDDE6|\xDDE7|\xDDE9|\xDDEA|\xDDEB|\xDDEC|\xDDED|\xDDEE|\xDDEF|\xDDF1|\xDDF2|\xDDF3|\xDDF4|\xDDF6|\xDDF7|\xDDF8|\xDDF9|\xDDFB|\xDDFC|\xDDFE|\xDDFF)|\xDDE8\xD83C(?:\xDDE6|\xDDE8|\xDDE9|\xDDEB|\xDDEC|\xDDED|\xDDEE|\xDDF0|\xDDF1|\xDDF2|\xDDF3|\xDDF4|\xDDF5|\xDDF7|\xDDFA|\xDDFB|\xDDFC|\xDDFD|\xDDFE|\xDDFF)|\xDDE9\xD83C(?:\xDDEA|\xDDEC|\xDDEF|\xDDF0|\xDDF2|\xDDF4|\xDDFF)|\xDDEA\xD83C(?:\xDDE6|\xDDE8|\xDDEA|\xDDEC|\xDDED|\xDDF7|\xDDF8|\xDDF9|\xDDFA)|\xDDEB\xD83C(?:\xDDEE|\xDDEF|\xDDF0|\xDDF2|\xDDF4|\xDDF7)|\xDDEC\xD83C(?:\xDDE6|\xDDE7|\xDDE9|\xDDEA|\xDDEB|\xDDEC|\xDDED|\xDDEE|\xDDF1|\xDDF2|\xDDF3|\xDDF5|\xDDF6|\xDDF7|\xDDF8|\xDDF9|\xDDFA|\xDDFC|\xDDFE)|\xDDED\xD83C(?:\xDDF0|\xDDF2|\xDDF3|\xDDF7|\xDDF9|\xDDFA)|\xDDEE\xD83C(?:\xDDE8|\xDDE9|\xDDEA|\xDDF1|\xDDF2|\xDDF3|\xDDF4|\xDDF6|\xDDF7|\xDDF8|\xDDF9)|\xDDEF\xD83C(?:\xDDEA|\xDDF2|\xDDF4|\xDDF5)|\xDDF0\xD83C(?:\xDDEA|\xDDEC|\xDDED|\xDDEE|\xDDF2|\xDDF3|\xDDF5|\xDDF7|\xDDFC|\xDDFE|\xDDFF)|\xDDF1\xD83C(?:\xDDE6|\xDDE7|\xDDE8|\xDDEE|\xDDF0|\xDDF7|\xDDF8|\xDDF9|\xDDFA|\xDDFB|\xDDFE)|\xDDF2\xD83C(?:\xDDE6|\xDDE8|\xDDE9|\xDDEA|\xDDEB|\xDDEC|\xDDED|\xDDF0|\xDDF1|\xDDF2|\xDDF3|\xDDF4|\xDDF5|\xDDF6|\xDDF7|\xDDF8|\xDDF9|\xDDFA|\xDDFB|\xDDFC|\xDDFD|\xDDFE|\xDDFF)|\xDDF3\xD83C(?:\xDDE6|\xDDE8|\xDDEA|\xDDEB|\xDDEC|\xDDEE|\xDDF1|\xDDF4|\xDDF5|\xDDF7|\xDDFA|\xDDFF)|\xDDF4\xD83C\xDDF2|\xDDF5\xD83C(?:\xDDE6|\xDDEA|\xDDEB|\xDDEC|\xDDED|\xDDF0|\xDDF1|\xDDF2|\xDDF3|\xDDF7|\xDDF8|\xDDF9|\xDDFC|\xDDFE)|\xDDF6\xD83C\xDDE6|\xDDF7\xD83C(?:\xDDEA|\xDDF4|\xDDF8|\xDDFA|\xDDFC)|\xDDF8\xD83C(?:\xDDE6|\xDDE7|\xDDE8|\xDDE9|\xDDEA|\xDDEC|\xDDED|\xDDEE|\xDDEF|\xDDF0|\xDDF1|\xDDF2|\xDDF3|\xDDF4|\xDDF7|\xDDF8|\xDDF9|\xDDFB|\xDDFD|\xDDFE|\xDDFF)|\xDDF9\xD83C(?:\xDDE6|\xDDE8|\xDDE9|\xDDEB|\xDDEC|\xDDED|\xDDEF|\xDDF0|\xDDF1|\xDDF2|\xDDF3|\xDDF4|\xDDF7|\xDDF9|\xDDFB|\xDDFC|\xDDFF)|\xDDFA\xD83C(?:\xDDE6|\xDDEC|\xDDF2|\xDDF8|\xDDFE|\xDDFF)|\xDDFB\xD83C(?:\xDDE6|\xDDE8|\xDDEA|\xDDEC|\xDDEE|\xDDF3|\xDDFA)|\xDDFC\xD83C(?:\xDDEB|\xDDF8)|\xDDFD\xD83C\xDDF0|\xDDFE\xD83C(?:\xDDEA|\xDDF9)|\xDDFF\xD83C(?:\xDDE6|\xDDF2|\xDDFC)))|[\xA9\xAE\x203C\x2049\x2122\x2139\x2194-\x2199\x21A9\x21AA\x231A\x231B\x2328\x23CF\x23E9-\x23F3\x23F8-\x23FA\x24C2\x25AA\x25AB\x25B6\x25C0\x25FB-\x25FE\x2600-\x2604\x260E\x2611\x2614\x2615\x2618\x261D\x2620\x2622\x2623\x2626\x262A\x262E\x262F\x2638-\x263A\x2648-\x2653\x2660\x2663\x2665\x2666\x2668\x267B\x267F\x2692-\x2694\x2696\x2697\x2699\x269B\x269C\x26A0\x26A1\x26AA\x26AB\x26B0\x26B1\x26BD\x26BE\x26C4\x26C5\x26C8\x26CE\x26CF\x26D1\x26D3\x26D4\x26E9\x26EA\x26F0-\x26F5\x26F7-\x26FA\x26FD\x2702\x2705\x2708-\x270D\x270F\x2712\x2714\x2716\x271D\x2721\x2728\x2733\x2734\x2744\x2747\x274C\x274E\x2753-\x2755\x2757\x2763\x2764\x2795-\x2797\x27A1\x27B0\x27BF\x2934\x2935\x2B05-\x2B07\x2B1B\x2B1C\x2B50\x2B55\x3030\x303D\x3297\x3299]|\xD83C[\xDC04\xDCCF\xDD70\xDD71\xDD7E\xDD7F\xDD8E\xDD91-\xDD9A\xDE01\xDE02\xDE1A\xDE2F\xDE32-\xDE3A\xDE50\xDE51\xDF00-\xDF21\xDF24-\xDF93\xDF96\xDF97\xDF99-\xDF9B\xDF9E-\xDFF0\xDFF3-\xDFF5\xDFF7-\xDFFF]|\xD83D[\xDC00-\xDCFD\xDCFF-\xDD3D\xDD49-\xDD4E\xDD50-\xDD67\xDD6F\xDD70\xDD73-\xDD79\xDD87\xDD8A-\xDD8D\xDD90\xDD95\xDD96\xDDA5\xDDA8\xDDB1\xDDB2\xDDBC\xDDC2-\xDDC4\xDDD1-\xDDD3\xDDDC-\xDDDE\xDDE1\xDDE3\xDDEF\xDDF3\xDDFA-\xDE4F\xDE80-\xDEC5\xDECB-\xDED0\xDEE0-\xDEE5\xDEE9\xDEEB\xDEEC\xDEF0\xDEF3]|\xD83E[\xDD10-\xDD18\xDD80-\xDD84\xDDC0]";
- string tempFolder = Path.Combine(Path.GetTempPath(), "TwitchDownloader");
- string downloadFolder = Path.Combine(tempFolder, "Chat Render");
-
- if (!Directory.Exists(downloadFolder))
- Directory.CreateDirectory(downloadFolder);
-
- backgroundRenderManager.ReportProgress(0, new Progress("Fetching Chat Badges"));
- GetChatBadges(chatBadges, chatJson["streamer"], renderOptions);
- backgroundRenderManager.ReportProgress(0, new Progress("Fetching Emotes"));
- GetEmotes(chatEmotes, chatJson["comments"], renderOptions);
- backgroundRenderManager.ReportProgress(0, new Progress("Fetching Third Party Emotes"));
- GetThirdPartyEmotes(thirdPartyEmotes, chatJson["streamer"], renderOptions);
- backgroundRenderManager.ReportProgress(0, new Progress("Fetching Twitter Emojis"));
- GetTwitterEmojis(emojiCache, chatJson["comments"], renderOptions, emojiRegex);
-
- Size canvasSize = new Size(renderOptions.chat_width, (int)Math.Floor(32 * renderOptions.image_scale));
- Font messageFont = new Font(renderOptions.font, (float)renderOptions.font_size, FontStyle.Regular);
- Font nameFont = new Font(renderOptions.font, (float)renderOptions.font_size, FontStyle.Bold);
-
- backgroundRenderManager.ReportProgress(0, new Progress("Rendering Comments"));
- foreach (var comment in chatJson["comments"])
- {
- string userName = comment["commenter"]["display_name"].ToString();
- Point drawPos = new Point(2, canvasSize.Height / 4);
- Color userColor = ColorTranslator.FromHtml(comment["message"]["user_color"] != null ? comment["message"]["user_color"].ToString() : defaultColors[rand.Next(0, defaultColors.Length)]);
- Bitmap sectionImage = new Bitmap(canvasSize.Width, canvasSize.Height);
- Graphics g = Graphics.FromImage(sectionImage);
- List messageSections = new List();
- List currentGifEmotes = new List();
- Section currentSection = new Section(sectionImage, false, currentGifEmotes);
- g.FillRectangle(new SolidBrush(renderOptions.background_color), -10, -10, canvasSize.Width + 20, canvasSize.Height + 20);
-
- SetAntiAlias(g);
- DrawBadges(g, renderOptions, chatBadges, comment, ref canvasSize, ref drawPos);
- DrawUsername(g, renderOptions, nameFont, userName, userColor, ref canvasSize, ref drawPos);
- DrawMessage(g, renderOptions, downloadFolder, sectionImage, messageSections, currentGifEmotes, currentSection, finalComments, messageFont, emojiCache, chatEmotes, thirdPartyEmotes, comment, userName, userColor, ref canvasSize, ref drawPos, emojiRegex);
- int percent = (int)Math.Floor(((double)finalComments.Count / (double)chatJson["comments"].Count()) * 100);
- backgroundRenderManager.ReportProgress(percent, new Progress("Rendering Comments"));
- }
-
- backgroundRenderManager.ReportProgress(0, new Progress("Rendering Video 0%"));
- RenderVideo(renderOptions, finalComments, chatJson["comments"]);
-
- string[] files = Directory.GetFiles(downloadFolder);
-
- for (int i = 0; i < files.Length; i++)
- {
- try
- {
- File.Delete(files[i]);
- }
- catch { }
- }
- }
-
- private void GetTwitterEmojis(Dictionary emojiCache, JToken comments, RenderOptions renderOptions, string emojiRegex)
- {
- using (WebClient client = new WebClient())
- {
- foreach (var comment in comments)
- {
- foreach (var fragment in comment["message"]["fragments"])
- {
- if (fragment["emoticon"] == null)
- {
- string[] fragmentParts = fragment["text"].ToString().Split(' ');
- for (int i = 0; i < fragmentParts.Length; i++)
- {
- string output = fragmentParts[i].Trim();
-
- if (output == "")
- continue;
-
- Match m = Regex.Match(output, emojiRegex);
- if (m.Success)
- {
- for (var k = 0; k < m.Value.Length; k += char.IsSurrogatePair(m.Value, k) ? 2 : 1)
- {
- string codepoint = String.Format("{0:X4}", char.ConvertToUtf32(m.Value, k)).ToLower();
- codepoint = codepoint.Replace("fe0f", "");
- Console.WriteLine("U+{0:X4}", codepoint);
- if (codepoint != "" && !emojiCache.ContainsKey(codepoint))
- {
- byte[] bytes = client.DownloadData(String.Format("https://abs.twimg.com/emoji/v2/72x72/{0}.png", codepoint));
- MemoryStream ms = new MemoryStream(bytes);
- Image emojiImage = System.Drawing.Image.FromStream(ms);
- emojiCache.Add(codepoint, (Bitmap)emojiImage);
- }
-
- }
- }
- }
- }
- }
- }
- }
- }
-
- private void RenderVideo(RenderOptions renderOptions, List finalComments, JToken comments)
- {
- Bitmap canvas = new Bitmap(renderOptions.chat_width, renderOptions.chat_height);
- Graphics gcan = Graphics.FromImage(canvas);
- int videoStart = (int)Math.Floor(comments.First["content_offset_seconds"].ToObject());
- int duration = (int)Math.Ceiling(comments.Last["content_offset_seconds"].ToObject()) - videoStart;
- List displayedGifs = new List();
- Stopwatch stopwatch = new Stopwatch();
- using (var vFWriter = new VideoFileWriter())
- {
- // create new video file
- stopwatch.Start();
- vFWriter.Open(renderOptions.save_path, renderOptions.chat_width, renderOptions.chat_height, 60, VideoCodec.H264, 6000000);
- gcan.FillRectangle(new SolidBrush(renderOptions.background_color), 0, 0, renderOptions.chat_width, renderOptions.chat_height);
- int startTick = (int)Math.Floor(videoStart / (1.0 / 60.0));
- int endTick = (int)Math.Floor((videoStart + duration) / (1.0 / 60.0));
- int lastUpdateTick = startTick;
- int globalTick = startTick;
- for (int i = startTick; i < endTick; i++)
- {
- int height = 0;
- if (globalTick % renderOptions.update_frame == 0)
- {
- int y = 0;
- List newly_added = new List();
- List old = new List(displayedGifs);
- for (int j = 0; j < finalComments.Count; j++)
- {
- int commentTick = (int)Math.Floor(finalComments[j].secondsOffset / (1.0 / 60.0));
- if (commentTick >= lastUpdateTick && commentTick < globalTick)
- {
- Bitmap sectionImage = (Bitmap)Bitmap.FromFile(finalComments[j].section);
- foreach (var emote in finalComments[j].gifEmotes)
- {
- GifEmote newGif = new GifEmote(new Point(emote.offset.X, emote.offset.Y + height), emote.name, emote.image);
- displayedGifs.Add(newGif);
- newly_added.Add(newGif);
- }
- height += sectionImage.Height;
- }
- }
- foreach (var emote in old)
- emote.offset = new Point(emote.offset.X, emote.offset.Y - height);
- foreach (var emote in newly_added)
- emote.offset = new Point(emote.offset.X, (renderOptions.chat_height - height) + emote.offset.Y);
-
- if (height > 0)
- {
- Bitmap buffer = new Bitmap(renderOptions.chat_width, height);
- Graphics bg = Graphics.FromImage(buffer);
-
- for (int j = 0; j < finalComments.Count; j++)
- {
- int commentTick = (int)Math.Floor(finalComments[j].secondsOffset / (1.0 / 60.0));
- if (commentTick >= lastUpdateTick && commentTick < globalTick)
- {
- Bitmap sectionImage = (Bitmap)Bitmap.FromFile(finalComments[j].section);
- bg.DrawImage(sectionImage, 0, y);
- y += sectionImage.Height;
- }
- }
- gcan = Graphics.FromImage(canvas);
- gcan.DrawImage(canvas, 0, -height);
- gcan.DrawImage(buffer, 0, renderOptions.chat_height - height);
- }
- lastUpdateTick = globalTick;
- }
- List to_remove = new List();
- foreach (var emote in displayedGifs)
- {
- if (emote.offset.Y < -emote.image.Width - renderOptions.chat_height)
- {
- to_remove.Add(emote);
- }
- else
- {
- int gifTime = (int)Math.Floor(1.5 * globalTick) % emote.total_duration;
- int frame = emote.frames - 1;
- int timeCount = 0;
- for (int k = 0; k < emote.durations.Count; k++)
- {
- if (timeCount + emote.durations[k] > gifTime)
- {
- frame = k;
- break;
- }
- timeCount += emote.durations[k];
- }
- FrameDimension dim = new FrameDimension(emote.image.FrameDimensionsList[0]);
- emote.image.SelectActiveFrame(dim, frame);
- gcan.DrawImage(emote.image, emote.offset.X, emote.offset.Y, (float)(emote.image.Width * renderOptions.image_scale), (float)(emote.image.Height * renderOptions.image_scale));
- }
- }
-
- foreach (var emote in to_remove)
- {
- displayedGifs.Remove(emote);
- }
-
- vFWriter.WriteVideoFrame(canvas);
- foreach (var emote in displayedGifs)
- {
- gcan.FillRectangle(new SolidBrush(renderOptions.background_color), emote.offset.X, emote.offset.Y, (float)(emote.image.Width * renderOptions.image_scale), (float)(emote.image.Height * renderOptions.image_scale));
- }
- globalTick += 1;
- double percentDouble = (double)(globalTick - startTick) / (double)(endTick - startTick) * 100.0;
- int percentInt = (int)Math.Floor(percentDouble);
- backgroundRenderManager.ReportProgress(percentInt, new Progress(String.Format("Rendering Video {0}%", percentInt), (int)Math.Floor(stopwatch.Elapsed.TotalSeconds), percentDouble));
- }
- vFWriter.Close();
- stopwatch.Stop();
- }
- }
-
- private void DrawMessage(Graphics g, RenderOptions renderOptions, string downloadFolder, Bitmap sectionImage, List messageSections, List currentGifEmotes, Section currentSection, List finalComments, Font messageFont, Dictionary emojiCache, List> chatEmotes, List thirdPartyEmotes, JToken comment, string userName, Color userColor, ref Size canvasSize, ref Point drawPos, string emojiRegex)
- {
- if (comment["source"].ToString() != "chat")
- return;
- if (comment["message"]["user_notice_params"]["msg-id"] != null)
- return;
-
- int hasEmoteHeight = (int)Math.Floor(32 * renderOptions.image_scale);
- int hasNoEmoteHeight = (int)Math.Floor(20 * renderOptions.image_scale);
-
- foreach (var fragment in comment["message"]["fragments"])
- {
- if (fragment["emoticon"] == null)
- {
- string[] fragmentParts = fragment["text"].ToString().Split(' ');
- for (int i = 0; i < fragmentParts.Length; i++)
- {
- bool isThirdPartyEmote = false;
-
- ThirdPartyEmote currentEmote = null;
- foreach (var thirdPartyEmote in thirdPartyEmotes)
- {
- if (fragmentParts[i] == thirdPartyEmote.name)
- {
- isThirdPartyEmote = true;
- currentEmote = thirdPartyEmote;
- }
- }
-
- if (isThirdPartyEmote)
- {
- if (drawPos.X + currentEmote.emote.Width * renderOptions.image_scale > canvasSize.Width)
- AddNewSection(ref messageSections, ref renderOptions, ref currentGifEmotes, ref currentSection, ref g, ref sectionImage, ref canvasSize, ref drawPos);
-
- if (currentEmote.imageType == "gif")
- {
- GifEmote emote = new GifEmote(new Point(drawPos.X + 2, 0), currentEmote.name, currentEmote.emote);
- currentGifEmotes.Add(emote);
- currentSection.hasEmote = true;
- drawPos.X += (int)Math.Ceiling(currentEmote.emote.Width * renderOptions.image_scale + 3);
- }
- else
- {
- currentSection.hasEmote = true;
- float emoteHeight = (float)(currentEmote.emote.Height * renderOptions.image_scale);
- g.DrawImage(currentEmote.emote, drawPos.X + 2, (hasEmoteHeight - emoteHeight) / 2, (float)(currentEmote.emote.Width * renderOptions.image_scale), emoteHeight);
- drawPos.X += (int)Math.Ceiling(currentEmote.emote.Width * renderOptions.image_scale + 3);
- }
- }
- else
- {
- string output = fragmentParts[i].Trim();
-
- if (output == "")
- continue;
-
- if (Regex.Match(output, emojiRegex).Success)
- {
- if (drawPos.X + (20 * renderOptions.image_scale) + 3 > canvasSize.Width)
- AddNewSection(ref messageSections, ref renderOptions, ref currentGifEmotes, ref currentSection, ref g, ref sectionImage, ref canvasSize, ref drawPos);
-
- Match m = Regex.Match(output, emojiRegex);
- for (var k = 0; k < m.Value.Length; k += char.IsSurrogatePair(m.Value, k) ? 2 : 1)
- {
- string codepoint = String.Format("{0:X4}", char.ConvertToUtf32(m.Value, k)).ToLower();
- codepoint = codepoint.Replace("fe0f", "");
- Console.WriteLine("U+{0:X4}", codepoint);
- if (codepoint != "")
- {
- Bitmap emojiBitmap = emojiCache[codepoint];
- currentSection.hasEmote = true;
- float emoteHeight = (float)(20 * renderOptions.image_scale);
- float emoteWidth = (float)(20 * renderOptions.image_scale);
- g.DrawImage(emojiBitmap, drawPos.X + 2, (hasEmoteHeight - emoteHeight) / 2, emoteWidth, emoteHeight);
- drawPos.X += (int)Math.Ceiling(emoteWidth * renderOptions.image_scale) + 3;
- }
-
- }
- }
- else
- {
- int inputWidth = (int)Math.Ceiling(g.MeasureString(output, messageFont, 0, StringFormat.GenericTypographic).Width);
-
- if (drawPos.X + inputWidth + 3 > canvasSize.Width)
- AddNewSection(ref messageSections, ref renderOptions, ref currentGifEmotes, ref currentSection, ref g, ref sectionImage, ref canvasSize, ref drawPos);
- if (renderOptions.outline)
- {
- GraphicsPath p = new GraphicsPath();
- p.AddString(
- output,
- messageFont.FontFamily,
- (int)messageFont.Style,
- g.DpiY * messageFont.Size / 72, // em size
- new Point(drawPos.X, drawPos.Y + 2), // location where to draw text
- new StringFormat()
- );
- Pen pen = new Pen(Color.Black, 6);
- pen.LineJoin = LineJoin.Round;
- g.DrawPath(pen, p);
- //g.FillPath(new SolidBrush(Color.Black), p);
- }
- g.DrawString(output, messageFont, new SolidBrush(Color.White), drawPos.X, drawPos.Y + 2);
- drawPos.X += inputWidth + (int)Math.Floor(4 * renderOptions.image_scale);
- }
-
- }
- }
- }
- else
- {
- //Is a first party emote
- int emoteId = Int32.Parse(fragment["emoticon"]["emoticon_id"].ToString());
- Image emoteImage = null;
-
- foreach (var emote in chatEmotes)
- {
- if (emoteId == emote.Key)
- emoteImage = emote.Value;
- }
-
- if (emoteImage != null)
- {
- if (drawPos.X + emoteImage.Width * renderOptions.image_scale > canvasSize.Width)
- AddNewSection(ref messageSections, ref renderOptions, ref currentGifEmotes, ref currentSection, ref g, ref sectionImage, ref canvasSize, ref drawPos);
- currentSection.hasEmote = true;
- float emoteHeight = (float)(emoteImage.Height * renderOptions.image_scale);
- g.DrawImage(emoteImage, drawPos.X - 2, (hasEmoteHeight - emoteHeight) / 2, (float)(emoteImage.Width * renderOptions.image_scale), emoteHeight);
- drawPos.X += (int)Math.Floor(emoteImage.Width * renderOptions.image_scale - 2);
- }
- }
- }
-
- messageSections.Add(currentSection);
- List finalGifs = new List();
-
- int finalY = 0;
- int finalHeight = 0;
- for (int i = 0; i < messageSections.Count; i++)
- finalHeight += messageSections[i].hasEmote ? hasEmoteHeight : hasNoEmoteHeight;
- Bitmap final = new Bitmap(canvasSize.Width, finalHeight);
- g.Dispose();
- g = Graphics.FromImage(final);
- for (int i = 0; i < messageSections.Count; i++)
- {
- foreach (var gif in messageSections[i].gifEmotes)
- {
- finalGifs.Add(new GifEmote(new Point(gif.offset.X, finalY), gif.name, gif.image));
- }
-
- if (messageSections[i].hasEmote)
- {
- g.DrawImage(messageSections[i].section, 0, finalY);
- finalY += (int)Math.Floor(32 * renderOptions.image_scale);
- }
- else
- {
- Bitmap temp = new Bitmap(renderOptions.chat_width, (int)Math.Floor(20 * renderOptions.image_scale));
- Graphics gtemp = Graphics.FromImage(temp);
- gtemp.DrawImage(messageSections[i].section, 0, -((hasEmoteHeight - hasNoEmoteHeight) / 2));
- g.DrawImage(temp, 0, finalY);
- temp.Dispose();
- gtemp.Dispose();
- finalY += (int)Math.Floor(20 * renderOptions.image_scale);
- }
- }
- g.Dispose();
-
- currentSection.section.Dispose();
- string imagePath = Path.Combine(downloadFolder, finalComments.Count + ".png");
- finalComments.Add(new TwitchComment(imagePath, Double.Parse(comment["content_offset_seconds"].ToString()), finalGifs));
- final.Save(imagePath);
- }
-
- private void AddNewSection(ref List messageSections, ref RenderOptions renderOptions, ref List currentGifEmotes, ref Section currentSection, ref Graphics g, ref Bitmap bmp, ref Size canvasSize, ref Point drawPos)
- {
- messageSections.Add(currentSection);
- currentGifEmotes = new List();
- bmp = new Bitmap(canvasSize.Width, canvasSize.Height);
- currentSection = new Section(bmp, false, currentGifEmotes);
- g = Graphics.FromImage(bmp);
- SetAntiAlias(g);
- g.FillRectangle(new SolidBrush(renderOptions.background_color), -10, -10, canvasSize.Width + 20, canvasSize.Height + (int)Math.Floor(32 * renderOptions.image_scale) + 20);
- drawPos.X = 2;
- }
-
- private void SetAntiAlias(Graphics g)
- {
- g.PixelOffsetMode = PixelOffsetMode.HighQuality;
- g.SmoothingMode = SmoothingMode.AntiAlias;
- g.InterpolationMode = InterpolationMode.HighQualityBicubic;
- g.TextRenderingHint = TextRenderingHint.AntiAlias;
- g.CompositingQuality = CompositingQuality.HighQuality;
- }
-
- private void GetEmotes(List> chatEmotes, JToken comments, RenderOptions renderOptions)
- {
- List alreadyAdded = new List();
- List failedEmotes = new List();
- using (WebClient client = new WebClient())
- {
- foreach (var comment in comments)
- {
- foreach (var fragment in comment["message"]["fragments"])
- {
- if (fragment["emoticon"] != null)
- {
- int id = fragment["emoticon"]["emoticon_id"].ToObject();
- if (!alreadyAdded.Contains(id) && !failedEmotes.Contains(id))
- {
- try
- {
- byte[] bytes = client.DownloadData(String.Format("https://static-cdn.jtvnw.net/emoticons/v1/{0}/1.0", id));
- alreadyAdded.Add(id);
- MemoryStream ms = new MemoryStream(bytes);
- Image emoteImage = System.Drawing.Image.FromStream(ms);
- chatEmotes.Add(new KeyValuePair(id, emoteImage));
- }
- catch
- {
- string emoteName = fragment["text"].ToString();
- //sometimes emote still exists but id is different, I use twitch metrics because I can't find an api to find an emote by name
- try
- {
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://www.twitchmetrics.net/e/" + emoteName);
- request.AllowAutoRedirect = false;
- HttpWebResponse response = (HttpWebResponse)request.GetResponse();
- string redirUrl = response.Headers["Location"];
- response.Close();
- string newId = redirUrl.Split('/').Last().Split('-').First();
- byte[] bytes = client.DownloadData(String.Format("https://static-cdn.jtvnw.net/emoticons/v1/{0}/1.0", newId));
- alreadyAdded.Add(id);
- MemoryStream ms = new MemoryStream(bytes);
- Image emoteImage = System.Drawing.Image.FromStream(ms);
- chatEmotes.Add(new KeyValuePair(id, emoteImage));
- }
- catch
- {
- AppendLog("Unable to fetch emote " + emoteName);
- failedEmotes.Add(id);
- }
- }
- }
- }
- }
- }
- }
- }
-
- private void AppendLog(string message)
- {
- textLog.BeginInvoke((Action)(() =>
- textLog.AppendText(message + Environment.NewLine)
- ));
- }
-
- private void DrawUsername(Graphics g, RenderOptions renderOptions, Font nameFont, string userName, Color userColor, ref Size canvasSize, ref Point drawPos)
- {
- if (renderOptions.outline)
- {
- drawPos.X += 2;
- GraphicsPath p = new GraphicsPath();
- p.AddString(
- userName + ":",
- nameFont.FontFamily,
- (int)nameFont.Style,
- g.DpiY * nameFont.Size / 72, // em size
- new Point(drawPos.X - 2, drawPos.Y + 2), // location where to draw text
- new StringFormat()
- );
- Pen pen = new Pen(Color.Black, 6);
- pen.LineJoin = LineJoin.Round;
- g.DrawPath(pen, p);
- //g.FillPath(new SolidBrush(Color.Black), p);
- }
- g.DrawString(userName + ":", nameFont, new SolidBrush(userColor), drawPos.X - 2, drawPos.Y + 2);
- drawPos.X += (int)Math.Floor(g.MeasureString(userName + ":", nameFont, 0, StringFormat.GenericTypographic).Width) + (int)Math.Floor(6 * renderOptions.image_scale);
- }
-
- private void DrawBadges(Graphics g, RenderOptions renderOptions, List chatBadges, JToken comment, ref Size canvasSize, ref Point drawPos)
- {
- if (comment["message"]["user_badges"] != null)
- {
- foreach (var badge in comment["message"]["user_badges"])
- {
- string id = badge["_id"].ToString();
- string version = badge["version"].ToString();
-
- Image badgeImage = null;
- foreach (var cachedBadge in chatBadges)
- {
- if (cachedBadge.name == id)
- {
- foreach (var cachedVersion in cachedBadge.versions)
- {
- if (cachedVersion.Key == version)
- {
- badgeImage = cachedVersion.Value;
- }
- }
- }
- }
-
- if (badgeImage != null)
- {
- float imageDim = (float)(18 * renderOptions.image_scale);
- float yPos = (canvasSize.Height - imageDim) / 2;
- g.DrawImage(badgeImage, drawPos.X, yPos, imageDim, imageDim);
- drawPos.X += (int)Math.Floor(20 * renderOptions.image_scale);
- }
- }
- }
- }
-
- private void GetChatBadges(List chatBadges, JToken streamerInfo, RenderOptions renderOptions)
- {
- using (WebClient client = new WebClient())
- {
- //Global chat badges
- JObject globalBadges = JObject.Parse(client.DownloadString("https://badges.twitch.tv/v1/badges/global/display"));
- //Subscriber badges
- JObject subBadges = JObject.Parse(client.DownloadString(String.Format("https://badges.twitch.tv/v1/badges/channels/{0}/display", streamerInfo["id"].ToString())));
-
- foreach (var badge in globalBadges["badge_sets"].Union(subBadges["badge_sets"]))
- {
- JProperty jBadgeProperty = badge.ToObject();
- string name = jBadgeProperty.Name;
- List> versions = new List>();
-
- foreach (var version in badge.First["versions"])
- {
- JProperty jVersionProperty = version.ToObject();
- string versionString = jVersionProperty.Name;
- string downloadUrl = version.First["image_url_2x"].ToString();
- byte[] bytes = client.DownloadData(downloadUrl);
- MemoryStream ms = new MemoryStream(bytes);
- try
- {
- //For some reason, twitch has corrupted images sometimes :) for example
- //https://static-cdn.jtvnw.net/badges/v1/a9811799-dce3-475f-8feb-3745ad12b7ea/1
- Image badgeImage = System.Drawing.Image.FromStream(ms);
- versions.Add(new KeyValuePair(versionString, badgeImage));
- }
- catch (ArgumentException)
- { }
- }
-
- chatBadges.Add(new ChatBadge(name, versions));
- }
- }
- }
-
- private void GetThirdPartyEmotes(List thirdPartyEmotes, JToken streamerInfo, RenderOptions renderOptions)
- {
- using (WebClient client = new WebClient())
- {
- if (renderOptions.bttv_emotes)
- {
- //Global BTTV emotes
- JObject BBTV = JObject.Parse(client.DownloadString("https://api.betterttv.net/2/emotes"));
- foreach (var emote in BBTV["emotes"])
- {
- string id = emote["id"].ToString();
- byte[] bytes = client.DownloadData(String.Format("https://cdn.betterttv.net/emote/{0}/1x", id));
- MemoryStream ms = new MemoryStream(bytes);
- Image temp_emote = System.Drawing.Image.FromStream(ms);
- thirdPartyEmotes.Add(new ThirdPartyEmote(temp_emote, emote["code"].ToString(), emote["imageType"].ToString(), id));
- }
-
- //Channel specific BTTV emotes
- try
- {
- JObject BBTV_channel = JObject.Parse(client.DownloadString("https://api.betterttv.net/2/channels/" + streamerInfo["name"].ToString()));
- foreach (var emote in BBTV_channel["emotes"])
- {
- string id = emote["id"].ToString();
- byte[] bytes = client.DownloadData(String.Format("https://cdn.betterttv.net/emote/{0}/1x", id));
- MemoryStream ms = new MemoryStream(bytes);
- Image temp_emote = System.Drawing.Image.FromStream(ms);
- thirdPartyEmotes.Add(new ThirdPartyEmote(temp_emote, emote["code"].ToString(), emote["imageType"].ToString(), id));
- }
- }
- catch { }
- }
-
- if (renderOptions.ffz_emotes)
- {
- //Global FFZ emotes
- JObject FFZ = JObject.Parse(client.DownloadString("https://api.betterttv.net/2/frankerfacez_emotes/global"));
- foreach (var emote in FFZ["emotes"])
- {
- string id = emote["id"].ToString();
- byte[] bytes = client.DownloadData(String.Format("https://cdn.betterttv.net/frankerfacez_emote/{0}/1", id));
- MemoryStream ms = new MemoryStream(bytes);
- Image temp_emote = System.Drawing.Image.FromStream(ms);
- thirdPartyEmotes.Add(new ThirdPartyEmote(temp_emote, emote["code"].ToString(), emote["imageType"].ToString(), id));
- }
-
- //Channel specific FFZ emotes
- try
- {
- JObject FFZ_channel = JObject.Parse(client.DownloadString("https://api.betterttv.net/2/frankerfacez_emotes/channels/" + streamerInfo["id"].ToString()));
- foreach (var emote in FFZ_channel["emotes"])
- {
- string id = emote["id"].ToString();
- byte[] bytes = client.DownloadData(String.Format("https://cdn.betterttv.net/frankerfacez_emote/{0}/1", id));
- MemoryStream ms = new MemoryStream(bytes);
- Image temp_emote = System.Drawing.Image.FromStream(ms);
- thirdPartyEmotes.Add(new ThirdPartyEmote(temp_emote, emote["code"].ToString(), emote["imageType"].ToString(), id));
- }
- }
- catch { }
- }
- }
- }
- public static Image ScaleImage(Image image, int maxWidth, int maxHeight)
- {
- var ratioX = (double)maxWidth / image.Width;
- var ratioY = (double)maxHeight / image.Height;
- var ratio = Math.Min(ratioX, ratioY);
-
- var newWidth = (int)(image.Width * ratio);
- var newHeight = (int)(image.Height * ratio);
-
- var newImage = new Bitmap(newWidth, newHeight);
-
- using (var graphics = Graphics.FromImage(newImage))
- graphics.DrawImage(image, 0, 0, newWidth, newHeight);
-
- return newImage;
- }
- private void BtnBrowse_Click(object sender, EventArgs e)
- {
- OpenFileDialog openFileDialog = new OpenFileDialog();
- openFileDialog.Filter = "JSON Files | *.json";
- openFileDialog.RestoreDirectory = true;
-
- if (openFileDialog.ShowDialog() == DialogResult.OK)
- {
- textJSON.Text = openFileDialog.FileName;
- }
- }
-
- private void TextColor_TextChanged(object sender, EventArgs e)
- {
- try
- {
- Color color = ColorTranslator.FromHtml(textColor.Text);
- colorDialog.Color = color;
- btnColor.BackColor = color;
- }
- catch { }
- }
-
- private void BackgroundRenderManager_ProgressChanged(object sender, ProgressChangedEventArgs e)
- {
- Progress update = (Progress)e.UserState;
- toolProgressBar.Value = e.ProgressPercentage >= 100 ? 100 : e.ProgressPercentage;
-
- if (e.ProgressPercentage > 0 && !update.justMessage)
- {
- int timeLeftInt = (int)Math.Floor(100.0/ update.percent_double * update.time_passed) - update.time_passed;
- TimeSpan timeLeft = new TimeSpan(0, 0, timeLeftInt);
- toolStatus.Text = String.Format("{0} ({1} left)", update.message, timeLeft.ToString(@"h\hm\ms\s"));
- }
- else
- toolStatus.Text = update.message;
- }
-
- private void BackgroundRenderManager_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
- {
- toolStatus.Text = "Done Rendering";
- toolProgressBar.Value = 0;
- btnRender.Enabled = true;
- }
-
- private void FrmChatRender_Load(object sender, EventArgs e)
- {
- InstalledFontCollection installedFontCollection = new InstalledFontCollection();
- FontFamily[] fontFamilies = installedFontCollection.Families;
- int fontIndex = 0;
- string fontName = Properties.Settings.Default.RENDER_FONT == "" ? "Arial" : Properties.Settings.Default.RENDER_FONT;
- for (int i = 0; i < fontFamilies.Length; i++)
- {
- comboFonts.Items.Add(fontFamilies[i].Name);
- if (fontFamilies[i].Name == fontName)
- fontIndex = i;
- }
- comboFonts.SelectedIndex = fontIndex;
-
- textColor.Text = Properties.Settings.Default.RENDER_COLOR;
- textHeight.Text = Properties.Settings.Default.RENDER_HEIGHT.ToString();
- textWidth.Text = Properties.Settings.Default.RENDER_WIDTH.ToString();
- checkBTTV.Checked = Properties.Settings.Default.RENDER_BTTV;
- checkFFZ.Checked = Properties.Settings.Default.RENDER_FFZ;
- checkOutline.Checked = Properties.Settings.Default.RENDER_OUTLINE;
- textFontSize.Text = Properties.Settings.Default.RENDER_FONT_SIZE.ToString();
- textUpdateTime.Text = Properties.Settings.Default.RENDER_UPDATE_TIME.ToString();
-
- if (textFontSize.Text.IndexOf('.') == -1)
- textFontSize.Text += ".0";
- if (textUpdateTime.Text.IndexOf('.') == -1)
- textUpdateTime.Text += ".0";
- }
- }
-
-}
-
-public class Progress
-{
- public string message = "";
- public int time_passed = 0;
- public double percent_double = 0.0;
- public bool justMessage = false;
- public Progress(string Message, int Time_passed, double Percent_double)
- {
- message = Message;
- time_passed = Time_passed;
- percent_double = Percent_double;
- }
-
- public Progress(string Message)
- {
- message = Message;
- justMessage = true;
- }
-}
-
-public class RenderOptions
-{
- public string json_path { get; set; }
- public string save_path { get; set; }
- public Color background_color { get; set; }
- public int chat_height { get; set; }
- public int chat_width { get; set; }
- public bool bttv_emotes { get; set; }
- public bool ffz_emotes { get; set; }
- public bool outline { get; set; }
- public string font { get; set; }
- public double font_size { get; set; }
- public double image_scale { get; set; }
- public int update_frame { get; set; }
-
- public RenderOptions(string Json_path, string Save_path, Color Background_color, int Chat_height, int Chat_width, bool Bttv_emotes, bool Ffz_emotes, bool Outline, string Font, double Font_size, double Update_rate)
- {
- json_path = Json_path;
- save_path = Save_path;
- background_color = Background_color;
- chat_height = Chat_height;
- chat_width = Chat_width;
- bttv_emotes = Bttv_emotes;
- ffz_emotes = Ffz_emotes;
- outline = Outline;
- font = Font;
- font_size = Font_size;
- image_scale = font_size / 9;
-
- if (Update_rate == 0)
- update_frame = 1;
- else
- update_frame = (int)Math.Floor(Update_rate / (1.0 / 60.0) );
- }
-}
-
-public class ThirdPartyEmote
-{
- public Image emote;
- public string imageType;
- public string name;
- public string id;
- public int width;
- public int height;
- public int fps = 0;
- public int frames = 0;
-
- public ThirdPartyEmote(Image Emote, string Name, string ImageType, string Id)
- {
- emote = Emote;
- name = Name;
- imageType = ImageType;
- id = Id;
- width = emote.Width;
- height = emote.Height;
- if (imageType == "gif")
- {
- FrameDimension dim = new FrameDimension(emote.FrameDimensionsList[0]);
- frames = emote.GetFrameCount(dim);
- PropertyItem item = emote.GetPropertyItem(0x5100);
- fps = (item.Value[0] + item.Value[1] * 256) * 10;
-
- if (fps == 0)
- fps = 2;
- }
- }
-}
-
-public class TwitchComment
-{
- public string section;
- public double secondsOffset;
- public List gifEmotes;
-
- public TwitchComment(string Section, double SecondsOffset, List GifEmotes)
- {
- section = Section;
- secondsOffset = SecondsOffset;
- gifEmotes = GifEmotes;
- }
-}
-
-public class GifEmote
-{
- public Point offset;
- public string name;
- public Image image;
- public FrameDimension dim;
- public int frames;
- public List durations;
- public int total_duration;
-
- public GifEmote(Point Offset, string Name, Image Image)
- {
- offset = Offset;
- name = Name;
- image = Image;
- dim = new FrameDimension(image.FrameDimensionsList[0]);
- frames = image.GetFrameCount(dim);
- var times = image.GetPropertyItem(0x5100).Value;
-
- durations = new List();
- for (int i = 0; i < frames; i++)
- {
- var duration = BitConverter.ToInt32(times, 4 * i);
- durations.Add(duration);
- total_duration += duration;
- }
-
- if (total_duration == 0)
- {
- for (int i = 0; i < durations.Count; i++)
- {
- durations.RemoveAt(i);
- durations.Insert(i, 10);
- }
- total_duration = durations.Count * 10;
- }
- }
-}
-
-public class ChatBadge
-{
- public string name;
- public List> versions;
-
- public ChatBadge(string Name, List> Versions)
- {
- name = Name;
- versions = Versions;
- }
-}
-
-public class Section
-{
- public Bitmap section;
- public bool hasEmote;
- public List gifEmotes;
-
- public Section(Bitmap Section, bool HasEmote, List GifEmotes)
- {
- section = Section;
- hasEmote = HasEmote;
- gifEmotes = GifEmotes;
- }
-}
\ No newline at end of file
diff --git a/TwitchDownloader/frmChatRender.resx b/TwitchDownloader/frmChatRender.resx
deleted file mode 100644
index ddd78fca..00000000
--- a/TwitchDownloader/frmChatRender.resx
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- 17, 17
-
-
- 238, 17
-
-
- 443, 17
-
-
\ No newline at end of file
diff --git a/TwitchDownloader/frmClipDownload.Designer.cs b/TwitchDownloader/frmClipDownload.Designer.cs
deleted file mode 100644
index 5944a6b0..00000000
--- a/TwitchDownloader/frmClipDownload.Designer.cs
+++ /dev/null
@@ -1,281 +0,0 @@
-namespace TwitchDownloader
-{
- partial class frmClipDownload
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.btnGetInfo = new System.Windows.Forms.Button();
- this.textUrl = new System.Windows.Forms.TextBox();
- this.label1 = new System.Windows.Forms.Label();
- this.comboQuality = new System.Windows.Forms.ComboBox();
- this.label2 = new System.Windows.Forms.Label();
- this.labelCreated = new System.Windows.Forms.Label();
- this.labelStreamer = new System.Windows.Forms.Label();
- this.label16 = new System.Windows.Forms.Label();
- this.textTitle = new System.Windows.Forms.TextBox();
- this.label15 = new System.Windows.Forms.Label();
- this.label14 = new System.Windows.Forms.Label();
- this.pictureThumb = new System.Windows.Forms.PictureBox();
- this.label7 = new System.Windows.Forms.Label();
- this.label6 = new System.Windows.Forms.Label();
- this.textLog = new System.Windows.Forms.TextBox();
- this.btnDownload = new System.Windows.Forms.Button();
- this.backgroundDownloadManager = new System.ComponentModel.BackgroundWorker();
- this.statusStrip = new System.Windows.Forms.StatusStrip();
- this.toolStatus = new System.Windows.Forms.ToolStripStatusLabel();
- ((System.ComponentModel.ISupportInitialize)(this.pictureThumb)).BeginInit();
- this.statusStrip.SuspendLayout();
- this.SuspendLayout();
- //
- // btnGetInfo
- //
- this.btnGetInfo.Location = new System.Drawing.Point(510, 33);
- this.btnGetInfo.Name = "btnGetInfo";
- this.btnGetInfo.Size = new System.Drawing.Size(75, 23);
- this.btnGetInfo.TabIndex = 32;
- this.btnGetInfo.Text = "Get Info";
- this.btnGetInfo.UseVisualStyleBackColor = true;
- this.btnGetInfo.Click += new System.EventHandler(this.BtnGetInfo_Click);
- //
- // textUrl
- //
- this.textUrl.Location = new System.Drawing.Point(301, 35);
- this.textUrl.Name = "textUrl";
- this.textUrl.Size = new System.Drawing.Size(203, 20);
- this.textUrl.TabIndex = 0;
- //
- // label1
- //
- this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(221, 38);
- this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(74, 13);
- this.label1.TabIndex = 30;
- this.label1.Text = "Clip Slug (ID) :";
- //
- // comboQuality
- //
- this.comboQuality.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this.comboQuality.Enabled = false;
- this.comboQuality.FormattingEnabled = true;
- this.comboQuality.Location = new System.Drawing.Point(331, 106);
- this.comboQuality.Name = "comboQuality";
- this.comboQuality.Size = new System.Drawing.Size(194, 21);
- this.comboQuality.TabIndex = 34;
- //
- // label2
- //
- this.label2.AutoSize = true;
- this.label2.Location = new System.Drawing.Point(281, 109);
- this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(45, 13);
- this.label2.TabIndex = 33;
- this.label2.Text = "Quality :";
- //
- // labelCreated
- //
- this.labelCreated.AutoSize = true;
- this.labelCreated.Location = new System.Drawing.Point(91, 236);
- this.labelCreated.Name = "labelCreated";
- this.labelCreated.Size = new System.Drawing.Size(0, 13);
- this.labelCreated.TabIndex = 43;
- //
- // labelStreamer
- //
- this.labelStreamer.AutoSize = true;
- this.labelStreamer.Location = new System.Drawing.Point(91, 214);
- this.labelStreamer.Name = "labelStreamer";
- this.labelStreamer.Size = new System.Drawing.Size(0, 13);
- this.labelStreamer.TabIndex = 44;
- //
- // label16
- //
- this.label16.AutoSize = true;
- this.label16.Location = new System.Drawing.Point(19, 62);
- this.label16.Name = "label16";
- this.label16.Size = new System.Drawing.Size(62, 13);
- this.label16.TabIndex = 42;
- this.label16.Text = "Thumbnail :";
- //
- // textTitle
- //
- this.textTitle.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.textTitle.Location = new System.Drawing.Point(22, 279);
- this.textTitle.Multiline = true;
- this.textTitle.Name = "textTitle";
- this.textTitle.ReadOnly = true;
- this.textTitle.Size = new System.Drawing.Size(200, 63);
- this.textTitle.TabIndex = 41;
- //
- // label15
- //
- this.label15.AutoSize = true;
- this.label15.Location = new System.Drawing.Point(22, 236);
- this.label15.Name = "label15";
- this.label15.Size = new System.Drawing.Size(63, 13);
- this.label15.TabIndex = 40;
- this.label15.Text = "Created At :";
- //
- // label14
- //
- this.label14.AutoSize = true;
- this.label14.Location = new System.Drawing.Point(30, 214);
- this.label14.Name = "label14";
- this.label14.Size = new System.Drawing.Size(55, 13);
- this.label14.TabIndex = 39;
- this.label14.Text = "Streamer :";
- //
- // pictureThumb
- //
- this.pictureThumb.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.pictureThumb.Location = new System.Drawing.Point(22, 78);
- this.pictureThumb.Name = "pictureThumb";
- this.pictureThumb.Size = new System.Drawing.Size(200, 125);
- this.pictureThumb.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
- this.pictureThumb.TabIndex = 38;
- this.pictureThumb.TabStop = false;
- //
- // label7
- //
- this.label7.AutoSize = true;
- this.label7.Location = new System.Drawing.Point(32, 258);
- this.label7.Name = "label7";
- this.label7.Size = new System.Drawing.Size(53, 13);
- this.label7.TabIndex = 37;
- this.label7.Text = "Clip Title :";
- //
- // label6
- //
- this.label6.AutoSize = true;
- this.label6.Location = new System.Drawing.Point(606, 62);
- this.label6.Name = "label6";
- this.label6.Size = new System.Drawing.Size(31, 13);
- this.label6.TabIndex = 46;
- this.label6.Text = "Log :";
- //
- // textLog
- //
- this.textLog.Location = new System.Drawing.Point(609, 78);
- this.textLog.Multiline = true;
- this.textLog.Name = "textLog";
- this.textLog.Size = new System.Drawing.Size(175, 264);
- this.textLog.TabIndex = 45;
- //
- // btnDownload
- //
- this.btnDownload.Enabled = false;
- this.btnDownload.Location = new System.Drawing.Point(368, 214);
- this.btnDownload.Name = "btnDownload";
- this.btnDownload.Size = new System.Drawing.Size(111, 41);
- this.btnDownload.TabIndex = 48;
- this.btnDownload.Text = "Download";
- this.btnDownload.UseVisualStyleBackColor = true;
- this.btnDownload.Click += new System.EventHandler(this.BtnDownload_Click);
- //
- // backgroundDownloadManager
- //
- this.backgroundDownloadManager.WorkerReportsProgress = true;
- this.backgroundDownloadManager.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BackgroundDownloadManager_DoWork);
- this.backgroundDownloadManager.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.BackgroundDownloadManager_RunWorkerCompleted);
- //
- // statusStrip
- //
- this.statusStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
- this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.toolStatus});
- this.statusStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow;
- this.statusStrip.Location = new System.Drawing.Point(0, 368);
- this.statusStrip.Name = "statusStrip";
- this.statusStrip.Size = new System.Drawing.Size(812, 22);
- this.statusStrip.SizingGrip = false;
- this.statusStrip.TabIndex = 49;
- this.statusStrip.Text = "statusStrip1";
- //
- // toolStatus
- //
- this.toolStatus.Name = "toolStatus";
- this.toolStatus.Size = new System.Drawing.Size(26, 17);
- this.toolStatus.Text = "Idle";
- //
- // frmClipDownload
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(812, 390);
- this.ControlBox = false;
- this.Controls.Add(this.statusStrip);
- this.Controls.Add(this.btnDownload);
- this.Controls.Add(this.label6);
- this.Controls.Add(this.textLog);
- this.Controls.Add(this.labelCreated);
- this.Controls.Add(this.labelStreamer);
- this.Controls.Add(this.label16);
- this.Controls.Add(this.textTitle);
- this.Controls.Add(this.label15);
- this.Controls.Add(this.label14);
- this.Controls.Add(this.pictureThumb);
- this.Controls.Add(this.label7);
- this.Controls.Add(this.comboQuality);
- this.Controls.Add(this.label2);
- this.Controls.Add(this.btnGetInfo);
- this.Controls.Add(this.textUrl);
- this.Controls.Add(this.label1);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
- this.Name = "frmClipDownload";
- this.Text = "frmClipDownload";
- this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
- ((System.ComponentModel.ISupportInitialize)(this.pictureThumb)).EndInit();
- this.statusStrip.ResumeLayout(false);
- this.statusStrip.PerformLayout();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.Button btnGetInfo;
- private System.Windows.Forms.TextBox textUrl;
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.ComboBox comboQuality;
- private System.Windows.Forms.Label label2;
- private System.Windows.Forms.Label labelCreated;
- private System.Windows.Forms.Label labelStreamer;
- private System.Windows.Forms.Label label16;
- private System.Windows.Forms.TextBox textTitle;
- private System.Windows.Forms.Label label15;
- private System.Windows.Forms.Label label14;
- private System.Windows.Forms.PictureBox pictureThumb;
- private System.Windows.Forms.Label label7;
- private System.Windows.Forms.Label label6;
- private System.Windows.Forms.TextBox textLog;
- private System.Windows.Forms.Button btnDownload;
- private System.ComponentModel.BackgroundWorker backgroundDownloadManager;
- private System.Windows.Forms.StatusStrip statusStrip;
- private System.Windows.Forms.ToolStripStatusLabel toolStatus;
- }
-}
\ No newline at end of file
diff --git a/TwitchDownloader/frmClipDownload.cs b/TwitchDownloader/frmClipDownload.cs
deleted file mode 100644
index 9f3b19be..00000000
--- a/TwitchDownloader/frmClipDownload.cs
+++ /dev/null
@@ -1,171 +0,0 @@
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace TwitchDownloader
-{
- public partial class frmClipDownload : Form
- {
- public frmClipDownload()
- {
- InitializeComponent();
- }
-
- private async void BtnGetInfo_Click(object sender, EventArgs e)
- {
- if (!textUrl.Text.All(char.IsLetter) || textUrl.Text.Length == 0)
- {
- MessageBox.Show("Please enter a valid Clip Slug. For example https://clips.twitch.tv/FrailOutstandingCroissantPhilosoraptor would be FrailOutstandingCroissantPhilosoraptor", "Invalid Clip Slug", MessageBoxButtons.OK, MessageBoxIcon.Error);
- return;
- }
-
- try
- {
- btnGetInfo.Enabled = false;
-
- string clipId = textUrl.Text;
- Task taskInfo = GetInfo(clipId);
- Task taskLinks = GetLinks(clipId);
- await Task.WhenAll(taskInfo, taskLinks);
-
- JToken clipData = taskInfo.Result["data"][0];
- string thumbUrl = clipData["thumbnail_url"].ToString();
- Task taskThumb = GetThumb(thumbUrl);
- await Task.WhenAll(taskThumb);
-
- pictureThumb.Image = taskThumb.Result;
- labelStreamer.Text = clipData["broadcaster_name"].ToString();
- labelCreated.Text = clipData["created_at"].ToString();
- textTitle.Text = clipData["title"].ToString();
-
- foreach (var quality in taskLinks.Result["quality_options"])
- {
- comboQuality.Items.Add(new TwitchClip(quality["quality"].ToString(), quality["frame_rate"].ToString(), quality["source"].ToString()));
- }
-
- comboQuality.SelectedIndex = 0;
- comboQuality.Enabled = true;
- btnDownload.Enabled = true;
- btnGetInfo.Enabled = true;
- }
- catch (WebException)
- {
- MessageBox.Show("Unable to get Clip information. Please double check Clip Slug and try again", "Unable to get info", MessageBoxButtons.OK, MessageBoxIcon.Error);
- btnGetInfo.Enabled = true;
- }
- }
-
- private async Task GetThumb(string thumbUrl)
- {
- Bitmap result = new Bitmap(100, 100);
- using (WebClient client = new WebClient())
- {
- client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
- using (Stream s = await client.OpenReadTaskAsync(thumbUrl))
- {
- result = new Bitmap(s);
- }
- }
- return result;
- }
-
- private async Task GetInfo(object clipId)
- {
- using (WebClient client = new WebClient())
- {
- client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
- string response = await client.DownloadStringTaskAsync(String.Format("https://api.twitch.tv/helix/clips?id={0}", clipId));
- JObject result = JObject.Parse(response);
- return result;
- }
- }
-
- private async Task GetLinks(object clipId)
- {
- using (WebClient client = new WebClient())
- {
- client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
- //API is deprecated - hopefully keeps working for a while. Can genereate full url from thumbnail but fails ocasionally https://discuss.dev.twitch.tv/t/clips-api-does-not-expose-video-url/15763/2
- string response = await client.DownloadStringTaskAsync(String.Format("https://clips.twitch.tv/api/v2/clips/{0}/status", clipId));
- JObject result = JObject.Parse(response);
- return result;
- }
- }
-
- private void BtnDownload_Click(object sender, EventArgs e)
- {
- SaveFileDialog saveFileDialog = new SaveFileDialog();
-
- saveFileDialog.Filter = "MP4 Files | *.mp4";
- saveFileDialog.RestoreDirectory = true;
-
- if (saveFileDialog.ShowDialog() == DialogResult.OK)
- {
- DownloadInfo info = new DownloadInfo((TwitchClip)comboQuality.SelectedItem, saveFileDialog.FileName);
- toolStatus.Text = "Downloading";
- btnGetInfo.Enabled = false;
- comboQuality.Enabled = false;
-
- backgroundDownloadManager.RunWorkerAsync(info);
- }
- }
-
- private void BackgroundDownloadManager_DoWork(object sender, DoWorkEventArgs e)
- {
- DownloadInfo clipInfo = (DownloadInfo)e.Argument;
-
- using (WebClient client = new WebClient())
- {
- client.DownloadFile(clipInfo.clip.url, clipInfo.path);
- }
- }
-
- private void BackgroundDownloadManager_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
- {
- toolStatus.Text = "Done Downloading";
- btnGetInfo.Enabled = true;
- }
- }
-}
-
-public class TwitchClip
-{
- public string quality { get; set; }
- public string framerate { get; set; }
- public string url { get; set; }
-
- public TwitchClip(string Quality, string Framerate, string Url)
- {
- quality = Quality;
- framerate = Framerate;
- url = Url;
- }
-
- override
- public string ToString()
- {
- //Only show framerate if it's not 30fps
- return String.Format("{0}p{1}", quality, framerate == "30" ? "" : framerate);
- }
-}
-
-public class DownloadInfo
-{
- public TwitchClip clip { get; set; }
- public string path { get; set; }
-
- public DownloadInfo(TwitchClip Clip, string Path)
- {
- clip = Clip;
- path = Path;
- }
-}
\ No newline at end of file
diff --git a/TwitchDownloader/frmClipDownload.resx b/TwitchDownloader/frmClipDownload.resx
deleted file mode 100644
index d09dd8e0..00000000
--- a/TwitchDownloader/frmClipDownload.resx
+++ /dev/null
@@ -1,126 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- 17, 17
-
-
- 347, 17
-
-
\ No newline at end of file
diff --git a/TwitchDownloader/frmMain.Designer.cs b/TwitchDownloader/frmMain.Designer.cs
deleted file mode 100644
index 17b1d40a..00000000
--- a/TwitchDownloader/frmMain.Designer.cs
+++ /dev/null
@@ -1,153 +0,0 @@
-namespace TwitchDownloader
-{
- partial class frmMain
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain));
- this.mainSplitContainer = new System.Windows.Forms.SplitContainer();
- this.btnAbout = new System.Windows.Forms.Button();
- this.btnFrmChatRender = new System.Windows.Forms.Button();
- this.btnFrmChatDownload = new System.Windows.Forms.Button();
- this.btnFrmClipDownload = new System.Windows.Forms.Button();
- this.btnFrmVodDownload = new System.Windows.Forms.Button();
- ((System.ComponentModel.ISupportInitialize)(this.mainSplitContainer)).BeginInit();
- this.mainSplitContainer.Panel1.SuspendLayout();
- this.mainSplitContainer.SuspendLayout();
- this.SuspendLayout();
- //
- // mainSplitContainer
- //
- this.mainSplitContainer.IsSplitterFixed = true;
- this.mainSplitContainer.Location = new System.Drawing.Point(16, 15);
- this.mainSplitContainer.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this.mainSplitContainer.Name = "mainSplitContainer";
- this.mainSplitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal;
- //
- // mainSplitContainer.Panel1
- //
- this.mainSplitContainer.Panel1.Controls.Add(this.btnAbout);
- this.mainSplitContainer.Panel1.Controls.Add(this.btnFrmChatRender);
- this.mainSplitContainer.Panel1.Controls.Add(this.btnFrmChatDownload);
- this.mainSplitContainer.Panel1.Controls.Add(this.btnFrmClipDownload);
- this.mainSplitContainer.Panel1.Controls.Add(this.btnFrmVodDownload);
- this.mainSplitContainer.Panel1.RightToLeft = System.Windows.Forms.RightToLeft.No;
- //
- // mainSplitContainer.Panel2
- //
- this.mainSplitContainer.Panel2.RightToLeft = System.Windows.Forms.RightToLeft.No;
- this.mainSplitContainer.RightToLeft = System.Windows.Forms.RightToLeft.No;
- this.mainSplitContainer.Size = new System.Drawing.Size(1083, 567);
- this.mainSplitContainer.SplitterDistance = 82;
- this.mainSplitContainer.SplitterWidth = 1;
- this.mainSplitContainer.TabIndex = 1;
- //
- // btnAbout
- //
- this.btnAbout.Location = new System.Drawing.Point(979, 4);
- this.btnAbout.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this.btnAbout.Name = "btnAbout";
- this.btnAbout.Size = new System.Drawing.Size(100, 28);
- this.btnAbout.TabIndex = 8;
- this.btnAbout.Text = "About";
- this.btnAbout.UseVisualStyleBackColor = true;
- this.btnAbout.Click += new System.EventHandler(this.BtnAbout_Click);
- //
- // btnFrmChatRender
- //
- this.btnFrmChatRender.Location = new System.Drawing.Point(743, 11);
- this.btnFrmChatRender.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this.btnFrmChatRender.Name = "btnFrmChatRender";
- this.btnFrmChatRender.Size = new System.Drawing.Size(189, 60);
- this.btnFrmChatRender.TabIndex = 7;
- this.btnFrmChatRender.Text = "Chat Render";
- this.btnFrmChatRender.UseVisualStyleBackColor = true;
- this.btnFrmChatRender.Click += new System.EventHandler(this.BtnFrmChatRender_Click);
- //
- // btnFrmChatDownload
- //
- this.btnFrmChatDownload.Location = new System.Drawing.Point(545, 11);
- this.btnFrmChatDownload.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this.btnFrmChatDownload.Name = "btnFrmChatDownload";
- this.btnFrmChatDownload.Size = new System.Drawing.Size(189, 60);
- this.btnFrmChatDownload.TabIndex = 6;
- this.btnFrmChatDownload.Text = "Chat Downloader";
- this.btnFrmChatDownload.UseVisualStyleBackColor = true;
- this.btnFrmChatDownload.Click += new System.EventHandler(this.BtnFrmChatDownload_Click);
- //
- // btnFrmClipDownload
- //
- this.btnFrmClipDownload.Location = new System.Drawing.Point(348, 11);
- this.btnFrmClipDownload.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this.btnFrmClipDownload.Name = "btnFrmClipDownload";
- this.btnFrmClipDownload.Size = new System.Drawing.Size(189, 60);
- this.btnFrmClipDownload.TabIndex = 5;
- this.btnFrmClipDownload.Text = "Clip Downloader";
- this.btnFrmClipDownload.UseVisualStyleBackColor = true;
- this.btnFrmClipDownload.Click += new System.EventHandler(this.BtnFrmClipDownload_Click);
- //
- // btnFrmVodDownload
- //
- this.btnFrmVodDownload.Location = new System.Drawing.Point(151, 11);
- this.btnFrmVodDownload.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this.btnFrmVodDownload.Name = "btnFrmVodDownload";
- this.btnFrmVodDownload.Size = new System.Drawing.Size(189, 60);
- this.btnFrmVodDownload.TabIndex = 4;
- this.btnFrmVodDownload.Text = "VOD Downloader";
- this.btnFrmVodDownload.UseVisualStyleBackColor = true;
- this.btnFrmVodDownload.Click += new System.EventHandler(this.BtnFrmVodDownload_Click);
- //
- // frmMain
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(1115, 581);
- this.Controls.Add(this.mainSplitContainer);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
- this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
- this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
- this.Name = "frmMain";
- this.Text = "Twitch Downloader";
- this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmMain_FormClosing);
- this.Load += new System.EventHandler(this.FrmMain_Load);
- this.mainSplitContainer.Panel1.ResumeLayout(false);
- ((System.ComponentModel.ISupportInitialize)(this.mainSplitContainer)).EndInit();
- this.mainSplitContainer.ResumeLayout(false);
- this.ResumeLayout(false);
-
- }
-
- #endregion
- private System.Windows.Forms.SplitContainer mainSplitContainer;
- private System.Windows.Forms.Button btnFrmChatRender;
- private System.Windows.Forms.Button btnFrmChatDownload;
- private System.Windows.Forms.Button btnFrmClipDownload;
- private System.Windows.Forms.Button btnFrmVodDownload;
- private System.Windows.Forms.Button btnAbout;
- }
-}
-
diff --git a/TwitchDownloader/frmMain.cs b/TwitchDownloader/frmMain.cs
deleted file mode 100644
index 3a3c3fe5..00000000
--- a/TwitchDownloader/frmMain.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using Xabe.FFmpeg;
-
-namespace TwitchDownloader
-{
- public partial class frmMain : Form
- {
- frmVodDownload formVodDownload = new frmVodDownload();
- frmClipDownload formClipDownload = new frmClipDownload();
- frmChatDownload formChatDownload = new frmChatDownload();
- frmChatRender formChatRender = new frmChatRender();
- public frmMain()
- {
- InitializeComponent();
- }
-
- private async void FrmMain_Load(object sender, EventArgs e)
- {
- formVodDownload.TopLevel = false;
- formVodDownload.Dock = DockStyle.Fill;
- formVodDownload.Show();
- mainSplitContainer.Panel2.Controls.Add(formVodDownload);
- formClipDownload.TopLevel = false;
- formClipDownload.Dock = DockStyle.Fill;
- mainSplitContainer.Panel2.Controls.Add(formClipDownload);
- formChatDownload.TopLevel = false;
- formChatDownload.Dock = DockStyle.Fill;
- mainSplitContainer.Panel2.Controls.Add(formChatDownload);
- formChatRender.TopLevel = false;
- formChatRender.Dock = DockStyle.Fill;
- mainSplitContainer.Panel2.Controls.Add(formChatRender);
-
- formVodDownload.Select();
-
- await FFmpeg.GetLatestVersion();
- }
-
- private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
- {
- Properties.Settings.Default.Save();
- }
-
- private void HideForms()
- {
- formVodDownload.Hide();
- formClipDownload.Hide();
- formChatDownload.Hide();
- formChatRender.Hide();
- }
-
- private void BtnFrmVodDownload_Click(object sender, EventArgs e)
- {
- HideForms();
- formVodDownload.Show();
- }
-
- private void BtnFrmClipDownload_Click(object sender, EventArgs e)
- {
- HideForms();
- formClipDownload.Show();
- }
-
- private void BtnFrmChatDownload_Click(object sender, EventArgs e)
- {
- HideForms();
- formChatDownload.Show();
- }
-
- private void BtnFrmChatRender_Click(object sender, EventArgs e)
- {
- HideForms();
- formChatRender.Show();
- }
-
- private void BtnAbout_Click(object sender, EventArgs e)
- {
- frmAbout formAbout = new frmAbout();
- formAbout.Show();
- }
- }
-}
diff --git a/TwitchDownloader/frmMain.resx b/TwitchDownloader/frmMain.resx
deleted file mode 100644
index 66003700..00000000
--- a/TwitchDownloader/frmMain.resx
+++ /dev/null
@@ -1,700 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
-
- AAABAAUAEBAAAAEAIABoBAAAVgAAABgYAAABACAAiAkAAL4EAAAgIAAAAQAgAKgQAABGDgAAMDAAAAEA
- IACoJQAA7h4AAEBAAAABACAAKEIAAJZEAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAADXDQAA1w0AAAAA
- AAAAAAAAAAAAmQAAAPsAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD7AAAAmQAAAMoAAAD/AAAA9gAAAO8AAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAA
- AO8AAAD2AAAA/wAAAMoAAADMAAAA/wAAAIwAAAA1AAAAOAAAADgAAAA4AAAAOAAAADgAAAA4AAAAOAAA
- ADgAAAA1AAAAjAAAAP8AAADMAAAAzAAAAP8AAABrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAGsAAAD/AAAAzAAAAMwAAAD/AAAAbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAABsAAAA/wAAAMwAAACWAAAAvgAAAE8AAAAAAAAAAAAAAAAAAAAAAAAABwAA
- AAkAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAL4AAACWAAAACgAAAAwAAAAFAAAAAAAAAAAAAAAAAAAABQAA
- AHcAAACLAAAADAAAAAAAAAAAAAAAAAAAAAUAAAAMAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AFsAAADuAAAA9wAAAG4AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AEEAAADfAAAA/wAAAP8AAADmAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- ACUAAADHAAAA/wAAAP8AAAD/AAAA/wAAAMsAAAAmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAjAAAAWgAAAK0AAAD/AAAA/wAAAL4AAABwAAAAKwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAB/AAAA/wAAAP8AAACJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAAAP8AAAD/AAAAigAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH8AAAD/AAAA/wAAAIoAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA/wAAAP8AAACKAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfQAAAP8AAAD/AAAAiAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/4AAAf+AAAHngAABw4AAD8HwAA+B8AAPAPAADwDwAA/D8AAPw/
- AAD8PwAA/D8AAPw/AAAoAAAAGAAAADAAAAABACAAAAAAAAAJAADXDQAA1w0AAAAAAAAAAAAAAAAATgAA
- ANwAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAANwAAABOAAAAoAAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAACgAAAArAAAAP8AAAD/AAAA+gAAAPMAAADzAAAA8wAAAPMAAADzAAAA8wAAAPMAAADzAAAA8wAA
- APMAAADzAAAA8wAAAPMAAADzAAAA8wAAAPMAAAD6AAAA/wAAAP8AAACsAAAArAAAAP8AAAD/AAAAtQAA
- AEkAAABIAAAASAAAAEgAAABIAAAASAAAAEgAAABIAAAASAAAAEgAAABIAAAASAAAAEgAAABIAAAASAAA
- AEkAAAC1AAAA/wAAAP8AAACsAAAArAAAAP8AAAD/AAAAlwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAACXAAAA/wAAAP8AAACsAAAArAAA
- AP8AAAD/AAAAmAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAIAAACYAAAA/wAAAP8AAACsAAAArAAAAP8AAAD/AAAAmAAAAAIAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACYAAAA/wAA
- AP8AAACsAAAArAAAAP8AAAD/AAAAmAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACZAAAA/wAAAP8AAACsAAAAcAAAAKgAAACpAAAAYwAA
- AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAEAAABjAAAAqQAAAKgAAABwAAAABgAAAAgAAAAIAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAgAAAB6AAAAlgAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAACAAAAAgAAAAGAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAGEAAADuAAAA+gAAAIQAAAAIAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAARQAAAN4AAAD/AAAA/wAAAO0AAABdAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxAAAAzAAAAP8AAAD/AAAA/wAA
- AP8AAADZAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAB4AAAC0AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAuQAAAB8AAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAJYAAAD7AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/AAAAJYAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAHIAAAB/AAAApgAAAPkAAAD/AAAA/wAAAPwAAADCAAAAnwAA
- AI0AAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAATgAAAPIAAAD/AAAA/wAAAPgAAABfAAAAAgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATwAAAPIAAAD/AAAA/wAA
- APgAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAATwAAAPIAAAD/AAAA/wAAAPgAAABcAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATwAA
- APIAAAD/AAAA/wAAAPgAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATwAAAPIAAAD/AAAA/wAAAPgAAABcAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAATwAAAPIAAAD/AAAA/wAAAPgAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATwAAAPIAAAD/AAAA/wAA
- APgAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAASgAAAO8AAAD/AAAA/wAAAPYAAABXAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/4AAH/+AAB//gAAf/4AAH5+AAD8PwAP+B
- /wD/gP8A/wD/AP4AfwD8AD8A/AA/AP+APwD/gf8A/4H/AP+B/wD/gf8A/4H/AP+B/wD/gf8AKAAAACAA
- AABAAAAAAQAgAAAAAAAAEAAA1w0AANcNAAAAAAAAAAAAAAAAABwAAACfAAAA9QAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA9AAAAJ4AAAAcAAAAaQAAAPMAAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8wAAAGgAAACJAAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAiQAA
- AIoAAAD/AAAA/wAAAP8AAAD9AAAA9gAAAPUAAAD2AAAA9gAAAPYAAAD2AAAA9gAAAPYAAAD2AAAA9gAA
- APYAAAD2AAAA9gAAAPYAAAD2AAAA9gAAAPYAAAD2AAAA9gAAAPYAAAD1AAAA9gAAAP0AAAD/AAAA/wAA
- AP8AAACKAAAAigAAAP8AAAD/AAAA/wAAANQAAABjAAAAVwAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAA
- AFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFcAAABkAAAA1AAA
- AP8AAAD/AAAA/wAAAIoAAACKAAAA/wAAAP8AAAD/AAAAvQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- ABEAAAC9AAAA/wAAAP8AAAD/AAAAigAAAIoAAAD/AAAA/wAAAP8AAAC+AAAAEgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAEgAAAL4AAAD/AAAA/wAAAP8AAACKAAAAigAAAP8AAAD/AAAA/wAAAL4AAAASAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAASAAAAvgAAAP8AAAD/AAAA/wAAAIoAAACKAAAA/wAAAP8AAAD/AAAAvgAA
- ABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAC+AAAA/wAAAP8AAAD/AAAAigAAAIoAAAD/AAAA/wAA
- AP8AAAC+AAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAL4AAAD/AAAA/wAAAP8AAACKAAAAiQAA
- AP4AAAD+AAAA/wAAAL0AAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAvQAAAP8AAAD+AAAA/gAA
- AIkAAABPAAAAkgAAAJIAAACTAAAAbAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAALAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAABsAAAAkwAA
- AJIAAACSAAAATwAAAAQAAAAHAAAABwAAAAcAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAADAAAAHsAAACcAAAAIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAUAAAAHAAAABwAAAAcAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAYAAABmAAAA7AAAAPsAAACUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAACAAAATAAAAN0AAAD/AAAA/wAAAPEAAAByAAAACAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADUAAADJAAAA/wAAAP8AAAD/AAAA/wAAAOAAAABQAAAAAQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlAAAAtQAAAP4AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AMkAAAAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAJwAAAD6AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/QAAAKgAAAAbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAACBAAAA8gAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA9AAAAIIAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAYwAAAOgAAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA6AAAAF0AAAACAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAABxAAAAoAAA
- AJ4AAACwAAAA7gAAAP8AAAD/AAAA/wAAAP8AAAD4AAAA0QAAAMMAAADFAAAAiQAAAAsAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- AAgAAAAKAAAACAAAADUAAADUAAAA/wAAAP8AAAD/AAAA/wAAAOQAAABLAAAAFwAAABoAAAATAAAAAgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAANIAAAD/AAAA/wAAAP8AAAD/AAAA4QAAADcAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtAAAA0gAAAP8AAAD/AAAA/wAAAP8AAADhAAAAOAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0AAADSAAAA/wAAAP8AAAD/AAAA/wAA
- AOEAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALQAAANIAAAD/AAAA/wAA
- AP8AAAD/AAAA4QAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtAAAA0gAA
- AP8AAAD/AAAA/wAAAP8AAADhAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AC0AAADSAAAA/wAAAP8AAAD/AAAA/wAAAOEAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAALQAAANIAAAD/AAAA/wAAAP8AAAD/AAAA4QAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAtAAAA0gAAAP8AAAD/AAAA/wAAAP8AAADhAAAAOAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0AAADSAAAA/wAAAP8AAAD/AAAA/wAAAOEAAAA4AAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJwAAAMoAAAD/AAAA/wAAAP8AAAD/AAAA2QAA
- ADIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAP//8AD///AA///wAP//8AD///AA///wAP+f8AH/D/g//gf///wD///8Af//+AH///A
- A///gAH//wAA//8AAP//AAD///AP///wD///8A////AP///wD///8A////AP///wD///8A////AP/ygA
- AAAwAAAAYAAAAAEAIAAAAAAAACQAANcNAADXDQAAAAAAAAAAAAAAAAAAAAAALAAAAJwAAADqAAAA/QAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/QAAAOkAAACaAAAAKwAAAAAAAAAXAAAAmwAA
- APUAAAD+AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP4AAAD1AAAAmQAA
- ABYAAAA6AAAA4QAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA4QAAADoAAABIAAAA9QAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA9QAAAEgAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAA
- AP8AAAD+AAAA+gAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAA
- APgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAA
- APgAAAD4AAAA+AAAAPgAAAD4AAAA+gAAAP4AAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAA
- AP8AAAD/AAAA/wAAAP8AAADzAAAAoQAAAHQAAAB2AAAAdgAAAHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAA
- AHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAA
- AHYAAAB2AAAAdgAAAHYAAAB2AAAAdgAAAHYAAAB0AAAAogAAAPMAAAD/AAAA/wAAAP8AAAD/AAAA9gAA
- AEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAVQAAAAIAAAAFAAAABQAAAAUAAAAFAAAABQAA
- AAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAA
- AAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAAFAAAABQAAAAUAAAADAAAAVQAAAOkAAAD/AAAA/wAA
- AP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAUQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAA
- AOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAUgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAA
- AP8AAADpAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAA
- AP8AAAD/AAAA/wAAAP8AAADpAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAA
- AEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAA
- AP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAUgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAA
- AOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAAAP8AAADpAAAAUgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABJAAAA9gAAAP8AAAD/AAAA/wAA
- AP8AAADpAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAUgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA9gAAAEkAAABDAAAA4gAA
- AOsAAADrAAAA6wAAAOwAAADWAAAASwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASwAAANYAAADsAAAA6wAAAOsAAADrAAAA4gAA
- AEMAAAAgAAAAbQAAAHEAAABxAAAAcQAAAHEAAABnAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAdAAAABAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAGcAAABxAAAAcQAA
- AHEAAABxAAAAbQAAACAAAAABAAAABQAAAAUAAAAFAAAABQAAAAUAAAAEAAAAAgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFwAAAHwAAACeAAAAPgAA
- AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
- AAQAAAAFAAAABQAAAAUAAAAFAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAbwAA
- AOgAAAD7AAAAqwAAAC8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAkAAABYAAAA2AAAAP8AAAD/AAAA9AAAAJEAAAAeAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAABgAAAEMAAADHAAAA/gAAAP8AAAD/AAAA/wAAAOwAAAB1AAAAEgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAACAAAAMAAAAK8AAAD9AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADXAAAAVwAA
- AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAmQAAAPYAAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD9AAAAvwAAAD0AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAACLAAAA8AAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA+gAAAKkAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAHIAAADjAAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPAAAACJAAAAGAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAXAAA
- ANQAAAD+AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADdAAAAZwAA
- AAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAABIAAAAxQAAAPwAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD8AAAAyQAAAEoAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAQAAADMAAACzAAAA9gAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA9wAAALAAAAAuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAAJoAAADyAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPEAAACQAAAAGAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPQAAAK4AAADHAAAAxwAAAMcAAADKAAAA4wAA
- APwAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA9wAAAO0AAADrAAAA6wAAAOsAAADKAAAARAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFQAAADUAAAA4AAAAOAAA
- ADcAAABDAAAAmwAAAPQAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD8AAAAvgAAAGoAAABeAAAAXwAA
- AF8AAABWAAAAIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAANAAAAfgAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmQAA
- ABQAAAABAAAAAgAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAA
- APEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAA
- ABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAA
- APEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAA
- ABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAfwAAAPEAAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAgAAA
- APEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD6AAAAmAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAOAAAAfgAAAPEAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD5AAAAlwAAABIAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAKAAAAbAAAAOgAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADzAAAAhQAA
- AA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAACAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAA/////wAAAAD/////AAAAAP////8AAAAA/////wAAAAD/
- ////AAAAAP////8AAAAA/////wAAAAD/////AAAAAP/+P/8AAAAA//wf/wAAAP//+A///wAA///wB///
- AAD//+AH//8AAP//wAP//wAA///AAf//AAD//4AB//8AAP//AAD//wAA//4AAH//AAD//AAAP/8AAP/4
- AAA//wAA//gAAB//AAD/+AAAH/8AAP/4AAAf/wAA///AAD//AAD//8AD//8AAP//wAP//wAA///AA///
- AAD//8AD//8AAP//wAP//wAA///AA///AAD//8AD//8AAP//wAP//wAA///AA///AAD//8AD//8AAP//
- wAP//wAA///AA///AAD//8AD//8AAP//wAP//wAA///AA///AAAoAAAAQAAAAIAAAAABACAAAAAAAABA
- AADXDQAA1w0AAAAAAAAAAAAAAAAAAAAAAAAAAAAhAAAAkgAAAN8AAAD6AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAPoAAADeAAAAkAAAACAAAAAAAAAAAAAAAAAAAAAjAAAAyAAAAPUAAAD9AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/QAAAPQAAADHAAAAIQAAAAAAAAAAAAAAlAAA
- APAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA8AAA
- AJEAAAAAAAAAAAAAANgAAAD8AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAPwAAADXAAAAAAAAAAQAAADsAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7AAAAAQAAAAFAAAA7gAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAO4AAAAFAAAABQAA
- AO4AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAADuAAAABQAAAAUAAADuAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA7gAAAAUAAAAFAAAA7gAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAADUAAAAkgAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAA
- AJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAA
- AJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAA
- AJMAAADUAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAO4AAAAFAAAABQAAAO4AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAAoAAAABAAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
- AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
- AAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAA
- AAoAAAAKAAAACgAAAAoAAAAQAAAAoQAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADuAAAABQAA
- AAUAAADuAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAJ0AAAAGAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAJ0AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA7gAAAAUAAAAFAAAA7gAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACdAAAABgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAACdAAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAO4AAAAFAAAABQAAAO4AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAAnQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAHAAAAnQAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADuAAAABQAAAAUAAADuAAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAJ0AAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAJ0AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7gAA
- AAUAAAAFAAAA7gAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACdAAAABgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAACdAAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAO4AAAAFAAAABQAAAO4AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAnQAA
- AAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAnQAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADuAAAABQAAAAUAAADuAAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAJ0AAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAABwAAAJ0AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7gAAAAUAAAAFAAAA7gAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACdAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAACdAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AO4AAAAFAAAABQAAAO4AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAnQAAAAYAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAnQAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAADuAAAABQAAAAUAAADuAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AJ0AAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAA
- AJ0AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7gAAAAUAAAAFAAAA7gAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAACdAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAcAAACdAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAO4AAAAFAAAABQAA
- AO4AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAnQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAnQAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAADuAAAABQAAAAQAAADIAAAA1gAAANYAAADWAAAA1gAAANYAAADWAAAA1gAAAIQAAAAFAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAIQAAADWAAAA1gAA
- ANYAAADWAAAA1gAAANYAAADWAAAAyAAAAAQAAAACAAAAUgAAAFcAAABXAAAAVwAAAFcAAABXAAAAVwAA
- AFcAAAA2AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAADwAAACkAAAAEAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAA2AAAAVwAAAFcAAABXAAAAVwAAAFcAAABXAAAAVwAAAFIAAAACAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAFwAAAH0AAACgAAAATgAA
- AAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAEgAA
- AHEAAADyAAAA/wAAAMUAAAA/AAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAADgAAAFgAAADjAAAA/wAAAP8AAAD/AAAAqAAAADAAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAEYAAADOAAAA/wAAAP8AAAD/AAAA/wAAAPwAAACLAAAAJAAA
- AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAADgAAACzAAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA8wAAAG8AAAAWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAACoAAACXAAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADcAAAAVgAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- ABoAAAB8AAAA+QAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAALsAAABBAAAAAwAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAwAAABrAAAA7QAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAAngAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAABlAAAA4QAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPgAAACJAAAAFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABUAAAAyQAAAP0AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA5AAAAHQAAAAIAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDAAAAtgAA
- APkAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- APwAAADKAAAAWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAsAAAApAAAAPMAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA9wAAALAAAAA3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAaAAAAkgAAAOkAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADtAAAAmAAAABsAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAfgAAAN8AAAD+AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/gAA
- AOAAAAB9AAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAZwAAANUAAAD7AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD7AAAA0AAAAFwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASwAA
- AMgAAAD4AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPYAAAC8AAAANgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAIoAAADSAAAA3wAAAN8AAADfAAAA3wAAAN8AAADnAAAA9wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7gAA
- AJIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVAAAAbQAAAHAAAABwAAAAcAAAAHAAAABwAAAAlAAA
- ANsAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA9AAAAMMAAACnAAAApwAA
- AKcAAACnAAAApwAAAKIAAAB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AOEAAABhAAAAFwAAABcAAAAXAAAAFwAAABcAAAAUAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAvwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAADeAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAL8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA3gAAAFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAN4AAABSAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAABAAAAAvwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAADeAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAL8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA3gAAAFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAC/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAN4AAABSAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAABAAAAAvwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADeAAAAUgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAL8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA3gAAAFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAN4AAABSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAvwAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADeAAAAUgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAQAAAAL8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA3gAA
- AFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAN4AAABSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAvwAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADeAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA
- AL8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA3gAAAFIAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AN4AAABSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAvwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAADeAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAL8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA3gAAAFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AEAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAN4AAABSAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAABAAAAAvwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAADeAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAL0AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA2wAAAFEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0AAACeAAAA+QAA
- AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/gAAAL0AAAA+AAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAADgAAAAAAAAAGAAAAAAAAAAYAAAAAAAAABAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//////+AAAH//////4AAAf
- //////gAAB//////+AAAH//////4AAAf//////gAAB//////+AAAH//////4AAAf//////gAAB//////
- +AAAH//////4AAAf//////gAAB//////+AAAH//8P//4AP////gf////////8A/////////wB///////
- /+AD////////wAP///////+AAf///////wAA////////AAD///////4AAH///////AAAP//////8AAA/
- //////gAAB//////8AAAD//////gAAAH/////8AAAAP/////wAAAA//////AAAAD/////8AAAAP/////
- /4AAA///////gAH///////+AAf///////4AB////////gAH///////+AAf///////4AB////////gAH/
- //////+AAf///////4AB////////gAH///////+AAf///////4AB////////gAH///////+AAf//////
- /4AB////////gAH///////+AAf///////4AB////////gAH///////+AAf///////4AB////
-
-
-
\ No newline at end of file
diff --git a/TwitchDownloader/frmVodDownload.Designer.cs b/TwitchDownloader/frmVodDownload.Designer.cs
deleted file mode 100644
index f179a6fd..00000000
--- a/TwitchDownloader/frmVodDownload.Designer.cs
+++ /dev/null
@@ -1,550 +0,0 @@
-namespace TwitchDownloader
-{
- partial class frmVodDownload
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.label1 = new System.Windows.Forms.Label();
- this.textUrl = new System.Windows.Forms.TextBox();
- this.label2 = new System.Windows.Forms.Label();
- this.label3 = new System.Windows.Forms.Label();
- this.label4 = new System.Windows.Forms.Label();
- this.label5 = new System.Windows.Forms.Label();
- this.comboQuality = new System.Windows.Forms.ComboBox();
- this.textFolder = new System.Windows.Forms.TextBox();
- this.textFilename = new System.Windows.Forms.TextBox();
- this.btnFolder = new System.Windows.Forms.Button();
- this.checkCropStart = new System.Windows.Forms.CheckBox();
- this.checkCropEnd = new System.Windows.Forms.CheckBox();
- this.label7 = new System.Windows.Forms.Label();
- this.label8 = new System.Windows.Forms.Label();
- this.labelLength = new System.Windows.Forms.Label();
- this.numStartHour = new System.Windows.Forms.NumericUpDown();
- this.numStartMinute = new System.Windows.Forms.NumericUpDown();
- this.numStartSecond = new System.Windows.Forms.NumericUpDown();
- this.label10 = new System.Windows.Forms.Label();
- this.label11 = new System.Windows.Forms.Label();
- this.label12 = new System.Windows.Forms.Label();
- this.label13 = new System.Windows.Forms.Label();
- this.numEndSecond = new System.Windows.Forms.NumericUpDown();
- this.numEndMinute = new System.Windows.Forms.NumericUpDown();
- this.numEndHour = new System.Windows.Forms.NumericUpDown();
- this.btnGetInfo = new System.Windows.Forms.Button();
- this.pictureThumb = new System.Windows.Forms.PictureBox();
- this.label14 = new System.Windows.Forms.Label();
- this.label15 = new System.Windows.Forms.Label();
- this.textTitle = new System.Windows.Forms.TextBox();
- this.label16 = new System.Windows.Forms.Label();
- this.btnDownload = new System.Windows.Forms.Button();
- this.labelStreamer = new System.Windows.Forms.Label();
- this.labelCreated = new System.Windows.Forms.Label();
- this.textLog = new System.Windows.Forms.TextBox();
- this.backgroundDownloadManager = new System.ComponentModel.BackgroundWorker();
- this.statusStrip = new System.Windows.Forms.StatusStrip();
- this.toolStatus = new System.Windows.Forms.ToolStripStatusLabel();
- this.toolProgressBar = new System.Windows.Forms.ToolStripProgressBar();
- this.label6 = new System.Windows.Forms.Label();
- ((System.ComponentModel.ISupportInitialize)(this.numStartHour)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.numStartMinute)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.numStartSecond)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndSecond)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndMinute)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndHour)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.pictureThumb)).BeginInit();
- this.statusStrip.SuspendLayout();
- this.SuspendLayout();
- //
- // label1
- //
- this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(245, 38);
- this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(50, 13);
- this.label1.TabIndex = 0;
- this.label1.Text = "VOD ID :";
- //
- // textUrl
- //
- this.textUrl.Location = new System.Drawing.Point(301, 35);
- this.textUrl.Name = "textUrl";
- this.textUrl.Size = new System.Drawing.Size(203, 20);
- this.textUrl.TabIndex = 0;
- //
- // label2
- //
- this.label2.AutoSize = true;
- this.label2.Location = new System.Drawing.Point(292, 130);
- this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(45, 13);
- this.label2.TabIndex = 2;
- this.label2.Text = "Quality :";
- //
- // label3
- //
- this.label3.AutoSize = true;
- this.label3.Location = new System.Drawing.Point(295, 158);
- this.label3.Name = "label3";
- this.label3.Size = new System.Drawing.Size(42, 13);
- this.label3.TabIndex = 3;
- this.label3.Text = "Folder :";
- //
- // label4
- //
- this.label4.AutoSize = true;
- this.label4.Location = new System.Drawing.Point(282, 186);
- this.label4.Name = "label4";
- this.label4.Size = new System.Drawing.Size(55, 13);
- this.label4.TabIndex = 4;
- this.label4.Text = "Filename :";
- //
- // label5
- //
- this.label5.AutoSize = true;
- this.label5.Location = new System.Drawing.Point(272, 214);
- this.label5.Name = "label5";
- this.label5.Size = new System.Drawing.Size(65, 13);
- this.label5.TabIndex = 5;
- this.label5.Text = "Crop Video :";
- //
- // comboQuality
- //
- this.comboQuality.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this.comboQuality.Enabled = false;
- this.comboQuality.FormattingEnabled = true;
- this.comboQuality.Location = new System.Drawing.Point(342, 127);
- this.comboQuality.Name = "comboQuality";
- this.comboQuality.Size = new System.Drawing.Size(203, 21);
- this.comboQuality.TabIndex = 7;
- //
- // textFolder
- //
- this.textFolder.Enabled = false;
- this.textFolder.Location = new System.Drawing.Point(342, 155);
- this.textFolder.Name = "textFolder";
- this.textFolder.Size = new System.Drawing.Size(169, 20);
- this.textFolder.TabIndex = 8;
- //
- // textFilename
- //
- this.textFilename.Enabled = false;
- this.textFilename.Location = new System.Drawing.Point(342, 183);
- this.textFilename.Name = "textFilename";
- this.textFilename.Size = new System.Drawing.Size(203, 20);
- this.textFilename.TabIndex = 9;
- //
- // btnFolder
- //
- this.btnFolder.Enabled = false;
- this.btnFolder.Location = new System.Drawing.Point(518, 155);
- this.btnFolder.Name = "btnFolder";
- this.btnFolder.Size = new System.Drawing.Size(28, 20);
- this.btnFolder.TabIndex = 12;
- this.btnFolder.Text = "...";
- this.btnFolder.UseVisualStyleBackColor = true;
- this.btnFolder.Click += new System.EventHandler(this.BtnFolder_Click);
- //
- // checkCropStart
- //
- this.checkCropStart.AutoSize = true;
- this.checkCropStart.Enabled = false;
- this.checkCropStart.Location = new System.Drawing.Point(342, 213);
- this.checkCropStart.Name = "checkCropStart";
- this.checkCropStart.Size = new System.Drawing.Size(48, 17);
- this.checkCropStart.TabIndex = 13;
- this.checkCropStart.Text = "Start";
- this.checkCropStart.UseVisualStyleBackColor = true;
- //
- // checkCropEnd
- //
- this.checkCropEnd.AutoSize = true;
- this.checkCropEnd.Enabled = false;
- this.checkCropEnd.Location = new System.Drawing.Point(342, 239);
- this.checkCropEnd.Name = "checkCropEnd";
- this.checkCropEnd.Size = new System.Drawing.Size(45, 17);
- this.checkCropEnd.TabIndex = 14;
- this.checkCropEnd.Text = "End";
- this.checkCropEnd.UseVisualStyleBackColor = true;
- //
- // label7
- //
- this.label7.AutoSize = true;
- this.label7.Location = new System.Drawing.Point(26, 258);
- this.label7.Name = "label7";
- this.label7.Size = new System.Drawing.Size(59, 13);
- this.label7.TabIndex = 15;
- this.label7.Text = "VOD Title :";
- //
- // label8
- //
- this.label8.AutoSize = true;
- this.label8.Location = new System.Drawing.Point(291, 106);
- this.label8.Name = "label8";
- this.label8.Size = new System.Drawing.Size(46, 13);
- this.label8.TabIndex = 17;
- this.label8.Text = "Length :";
- //
- // labelLength
- //
- this.labelLength.AutoSize = true;
- this.labelLength.Location = new System.Drawing.Point(339, 106);
- this.labelLength.Name = "labelLength";
- this.labelLength.Size = new System.Drawing.Size(49, 13);
- this.labelLength.TabIndex = 18;
- this.labelLength.Text = "00:00:00";
- //
- // numStartHour
- //
- this.numStartHour.Enabled = false;
- this.numStartHour.Location = new System.Drawing.Point(407, 210);
- this.numStartHour.Name = "numStartHour";
- this.numStartHour.Size = new System.Drawing.Size(35, 20);
- this.numStartHour.TabIndex = 19;
- //
- // numStartMinute
- //
- this.numStartMinute.Enabled = false;
- this.numStartMinute.Location = new System.Drawing.Point(458, 210);
- this.numStartMinute.Name = "numStartMinute";
- this.numStartMinute.Size = new System.Drawing.Size(35, 20);
- this.numStartMinute.TabIndex = 20;
- //
- // numStartSecond
- //
- this.numStartSecond.Enabled = false;
- this.numStartSecond.Location = new System.Drawing.Point(510, 210);
- this.numStartSecond.Name = "numStartSecond";
- this.numStartSecond.Size = new System.Drawing.Size(35, 20);
- this.numStartSecond.TabIndex = 21;
- //
- // label10
- //
- this.label10.AutoSize = true;
- this.label10.Enabled = false;
- this.label10.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label10.Location = new System.Drawing.Point(497, 214);
- this.label10.Name = "label10";
- this.label10.Size = new System.Drawing.Size(11, 13);
- this.label10.TabIndex = 22;
- this.label10.Text = ":";
- //
- // label11
- //
- this.label11.AutoSize = true;
- this.label11.Enabled = false;
- this.label11.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label11.Location = new System.Drawing.Point(445, 214);
- this.label11.Name = "label11";
- this.label11.Size = new System.Drawing.Size(11, 13);
- this.label11.TabIndex = 23;
- this.label11.Text = ":";
- //
- // label12
- //
- this.label12.AutoSize = true;
- this.label12.Enabled = false;
- this.label12.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label12.Location = new System.Drawing.Point(445, 240);
- this.label12.Name = "label12";
- this.label12.Size = new System.Drawing.Size(11, 13);
- this.label12.TabIndex = 28;
- this.label12.Text = ":";
- //
- // label13
- //
- this.label13.AutoSize = true;
- this.label13.Enabled = false;
- this.label13.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label13.Location = new System.Drawing.Point(497, 240);
- this.label13.Name = "label13";
- this.label13.Size = new System.Drawing.Size(11, 13);
- this.label13.TabIndex = 27;
- this.label13.Text = ":";
- //
- // numEndSecond
- //
- this.numEndSecond.Enabled = false;
- this.numEndSecond.Location = new System.Drawing.Point(510, 236);
- this.numEndSecond.Name = "numEndSecond";
- this.numEndSecond.Size = new System.Drawing.Size(35, 20);
- this.numEndSecond.TabIndex = 26;
- //
- // numEndMinute
- //
- this.numEndMinute.Enabled = false;
- this.numEndMinute.Location = new System.Drawing.Point(458, 236);
- this.numEndMinute.Name = "numEndMinute";
- this.numEndMinute.Size = new System.Drawing.Size(35, 20);
- this.numEndMinute.TabIndex = 25;
- //
- // numEndHour
- //
- this.numEndHour.Enabled = false;
- this.numEndHour.Location = new System.Drawing.Point(407, 236);
- this.numEndHour.Name = "numEndHour";
- this.numEndHour.Size = new System.Drawing.Size(35, 20);
- this.numEndHour.TabIndex = 24;
- //
- // btnGetInfo
- //
- this.btnGetInfo.Location = new System.Drawing.Point(510, 33);
- this.btnGetInfo.Name = "btnGetInfo";
- this.btnGetInfo.Size = new System.Drawing.Size(75, 23);
- this.btnGetInfo.TabIndex = 29;
- this.btnGetInfo.Text = "Get Info";
- this.btnGetInfo.UseVisualStyleBackColor = true;
- this.btnGetInfo.Click += new System.EventHandler(this.BtnGetInfo_Click);
- //
- // pictureThumb
- //
- this.pictureThumb.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.pictureThumb.Location = new System.Drawing.Point(22, 78);
- this.pictureThumb.Name = "pictureThumb";
- this.pictureThumb.Size = new System.Drawing.Size(200, 125);
- this.pictureThumb.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
- this.pictureThumb.TabIndex = 30;
- this.pictureThumb.TabStop = false;
- //
- // label14
- //
- this.label14.AutoSize = true;
- this.label14.Location = new System.Drawing.Point(30, 214);
- this.label14.Name = "label14";
- this.label14.Size = new System.Drawing.Size(55, 13);
- this.label14.TabIndex = 31;
- this.label14.Text = "Streamer :";
- //
- // label15
- //
- this.label15.AutoSize = true;
- this.label15.Location = new System.Drawing.Point(22, 236);
- this.label15.Name = "label15";
- this.label15.Size = new System.Drawing.Size(63, 13);
- this.label15.TabIndex = 32;
- this.label15.Text = "Created At :";
- //
- // textTitle
- //
- this.textTitle.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.textTitle.Location = new System.Drawing.Point(22, 279);
- this.textTitle.Multiline = true;
- this.textTitle.Name = "textTitle";
- this.textTitle.ReadOnly = true;
- this.textTitle.Size = new System.Drawing.Size(200, 63);
- this.textTitle.TabIndex = 33;
- //
- // label16
- //
- this.label16.AutoSize = true;
- this.label16.Location = new System.Drawing.Point(19, 62);
- this.label16.Name = "label16";
- this.label16.Size = new System.Drawing.Size(62, 13);
- this.label16.TabIndex = 34;
- this.label16.Text = "Thumbnail :";
- //
- // btnDownload
- //
- this.btnDownload.Enabled = false;
- this.btnDownload.Location = new System.Drawing.Point(377, 276);
- this.btnDownload.Name = "btnDownload";
- this.btnDownload.Size = new System.Drawing.Size(111, 41);
- this.btnDownload.TabIndex = 35;
- this.btnDownload.Text = "Download";
- this.btnDownload.UseVisualStyleBackColor = true;
- this.btnDownload.Click += new System.EventHandler(this.BtnDownload_Click);
- //
- // labelStreamer
- //
- this.labelStreamer.AutoSize = true;
- this.labelStreamer.Location = new System.Drawing.Point(91, 214);
- this.labelStreamer.Name = "labelStreamer";
- this.labelStreamer.Size = new System.Drawing.Size(0, 13);
- this.labelStreamer.TabIndex = 36;
- //
- // labelCreated
- //
- this.labelCreated.AutoSize = true;
- this.labelCreated.Location = new System.Drawing.Point(91, 236);
- this.labelCreated.Name = "labelCreated";
- this.labelCreated.Size = new System.Drawing.Size(0, 13);
- this.labelCreated.TabIndex = 36;
- //
- // textLog
- //
- this.textLog.Location = new System.Drawing.Point(609, 78);
- this.textLog.Multiline = true;
- this.textLog.Name = "textLog";
- this.textLog.Size = new System.Drawing.Size(175, 264);
- this.textLog.TabIndex = 37;
- //
- // backgroundDownloadManager
- //
- this.backgroundDownloadManager.WorkerReportsProgress = true;
- this.backgroundDownloadManager.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BackgroundDownloadManager_DoWork);
- this.backgroundDownloadManager.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.BackgroundDownloadManager_ProgressChanged);
- this.backgroundDownloadManager.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.BackgroundDownloadManager_RunWorkerCompleted);
- //
- // statusStrip
- //
- this.statusStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
- this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.toolStatus,
- this.toolProgressBar});
- this.statusStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow;
- this.statusStrip.Location = new System.Drawing.Point(0, 368);
- this.statusStrip.Name = "statusStrip";
- this.statusStrip.Size = new System.Drawing.Size(812, 22);
- this.statusStrip.SizingGrip = false;
- this.statusStrip.TabIndex = 38;
- this.statusStrip.Text = "statusStrip1";
- //
- // toolStatus
- //
- this.toolStatus.Name = "toolStatus";
- this.toolStatus.Size = new System.Drawing.Size(26, 17);
- this.toolStatus.Text = "Idle";
- //
- // toolProgressBar
- //
- this.toolProgressBar.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
- this.toolProgressBar.Name = "toolProgressBar";
- this.toolProgressBar.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
- this.toolProgressBar.Size = new System.Drawing.Size(200, 16);
- //
- // label6
- //
- this.label6.AutoSize = true;
- this.label6.Location = new System.Drawing.Point(606, 62);
- this.label6.Name = "label6";
- this.label6.Size = new System.Drawing.Size(31, 13);
- this.label6.TabIndex = 39;
- this.label6.Text = "Log :";
- //
- // frmVodDownload
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(812, 390);
- this.ControlBox = false;
- this.Controls.Add(this.label6);
- this.Controls.Add(this.statusStrip);
- this.Controls.Add(this.textLog);
- this.Controls.Add(this.labelCreated);
- this.Controls.Add(this.labelStreamer);
- this.Controls.Add(this.btnDownload);
- this.Controls.Add(this.label16);
- this.Controls.Add(this.textTitle);
- this.Controls.Add(this.label15);
- this.Controls.Add(this.label14);
- this.Controls.Add(this.pictureThumb);
- this.Controls.Add(this.btnGetInfo);
- this.Controls.Add(this.label12);
- this.Controls.Add(this.label13);
- this.Controls.Add(this.numEndSecond);
- this.Controls.Add(this.numEndMinute);
- this.Controls.Add(this.numEndHour);
- this.Controls.Add(this.label11);
- this.Controls.Add(this.label10);
- this.Controls.Add(this.numStartSecond);
- this.Controls.Add(this.numStartMinute);
- this.Controls.Add(this.numStartHour);
- this.Controls.Add(this.labelLength);
- this.Controls.Add(this.label8);
- this.Controls.Add(this.label7);
- this.Controls.Add(this.checkCropEnd);
- this.Controls.Add(this.checkCropStart);
- this.Controls.Add(this.btnFolder);
- this.Controls.Add(this.textFilename);
- this.Controls.Add(this.textFolder);
- this.Controls.Add(this.comboQuality);
- this.Controls.Add(this.label5);
- this.Controls.Add(this.label4);
- this.Controls.Add(this.label3);
- this.Controls.Add(this.label2);
- this.Controls.Add(this.textUrl);
- this.Controls.Add(this.label1);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
- this.Name = "frmVodDownload";
- this.Text = "z";
- this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
- ((System.ComponentModel.ISupportInitialize)(this.numStartHour)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.numStartMinute)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.numStartSecond)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndSecond)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndMinute)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.numEndHour)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.pictureThumb)).EndInit();
- this.statusStrip.ResumeLayout(false);
- this.statusStrip.PerformLayout();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.TextBox textUrl;
- private System.Windows.Forms.Label label2;
- private System.Windows.Forms.Label label3;
- private System.Windows.Forms.Label label4;
- private System.Windows.Forms.Label label5;
- private System.Windows.Forms.ComboBox comboQuality;
- private System.Windows.Forms.TextBox textFolder;
- private System.Windows.Forms.TextBox textFilename;
- private System.Windows.Forms.Button btnFolder;
- private System.Windows.Forms.CheckBox checkCropStart;
- private System.Windows.Forms.CheckBox checkCropEnd;
- private System.Windows.Forms.Label label7;
- private System.Windows.Forms.Label label8;
- private System.Windows.Forms.Label labelLength;
- private System.Windows.Forms.NumericUpDown numStartHour;
- private System.Windows.Forms.NumericUpDown numStartMinute;
- private System.Windows.Forms.NumericUpDown numStartSecond;
- private System.Windows.Forms.Label label10;
- private System.Windows.Forms.Label label11;
- private System.Windows.Forms.Label label12;
- private System.Windows.Forms.Label label13;
- private System.Windows.Forms.NumericUpDown numEndSecond;
- private System.Windows.Forms.NumericUpDown numEndMinute;
- private System.Windows.Forms.NumericUpDown numEndHour;
- private System.Windows.Forms.Button btnGetInfo;
- private System.Windows.Forms.PictureBox pictureThumb;
- private System.Windows.Forms.Label label14;
- private System.Windows.Forms.Label label15;
- private System.Windows.Forms.TextBox textTitle;
- private System.Windows.Forms.Label label16;
- private System.Windows.Forms.Button btnDownload;
- private System.Windows.Forms.Label labelStreamer;
- private System.Windows.Forms.Label labelCreated;
- private System.Windows.Forms.TextBox textLog;
- private System.ComponentModel.BackgroundWorker backgroundDownloadManager;
- private System.Windows.Forms.StatusStrip statusStrip;
- private System.Windows.Forms.ToolStripStatusLabel toolStatus;
- private System.Windows.Forms.ToolStripProgressBar toolProgressBar;
- private System.Windows.Forms.Label label6;
- }
-}
\ No newline at end of file
diff --git a/TwitchDownloader/frmVodDownload.resx b/TwitchDownloader/frmVodDownload.resx
deleted file mode 100644
index ecd08eb5..00000000
--- a/TwitchDownloader/frmVodDownload.resx
+++ /dev/null
@@ -1,126 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- 17, 17
-
-
- 238, 17
-
-
\ No newline at end of file
diff --git a/TwitchDownloader/icon_rT9_icon.ico b/TwitchDownloader/icon_rT9_icon.ico
deleted file mode 100644
index efb59909..00000000
Binary files a/TwitchDownloader/icon_rT9_icon.ico and /dev/null differ
diff --git a/TwitchDownloader/packages.config b/TwitchDownloader/packages.config
deleted file mode 100644
index 400f038b..00000000
--- a/TwitchDownloader/packages.config
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/TwitchDownloaderWPF.sln b/TwitchDownloaderWPF.sln
new file mode 100644
index 00000000..3f3d675d
--- /dev/null
+++ b/TwitchDownloaderWPF.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29324.140
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwitchDownloader", "TwitchDownloaderWPF\TwitchDownloader.csproj", "{A5940F4D-027D-4F9E-9F65-C0D842807BE1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A5940F4D-027D-4F9E-9F65-C0D842807BE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A5940F4D-027D-4F9E-9F65-C0D842807BE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A5940F4D-027D-4F9E-9F65-C0D842807BE1}.Debug|x64.ActiveCfg = Debug|x64
+ {A5940F4D-027D-4F9E-9F65-C0D842807BE1}.Debug|x64.Build.0 = Debug|x64
+ {A5940F4D-027D-4F9E-9F65-C0D842807BE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A5940F4D-027D-4F9E-9F65-C0D842807BE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A5940F4D-027D-4F9E-9F65-C0D842807BE1}.Release|x64.ActiveCfg = Release|x64
+ {A5940F4D-027D-4F9E-9F65-C0D842807BE1}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {02B42040-EA74-42BA-B12E-4308284E432A}
+ EndGlobalSection
+EndGlobal
diff --git a/TwitchDownloaderWPF/App.config b/TwitchDownloaderWPF/App.config
new file mode 100644
index 00000000..f8f97f29
--- /dev/null
+++ b/TwitchDownloaderWPF/App.config
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10
+
+
+ Arial
+
+
+ 12
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ 600
+
+
+ 350
+
+
+ 1
+
+
+ True
+
+
+ True
+
+
+ 17
+
+
+ 17
+
+
+ 17
+
+
+
+
\ No newline at end of file
diff --git a/TwitchDownloaderWPF/App.xaml b/TwitchDownloaderWPF/App.xaml
new file mode 100644
index 00000000..cd3d8c15
--- /dev/null
+++ b/TwitchDownloaderWPF/App.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/TwitchDownloaderWPF/App.xaml.cs b/TwitchDownloaderWPF/App.xaml.cs
new file mode 100644
index 00000000..8848d0c2
--- /dev/null
+++ b/TwitchDownloaderWPF/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace TwitchDownloaderWPF
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/TwitchDownloaderWPF/ChatRoot.cs b/TwitchDownloaderWPF/ChatRoot.cs
new file mode 100644
index 00000000..e4874f2a
--- /dev/null
+++ b/TwitchDownloaderWPF/ChatRoot.cs
@@ -0,0 +1,85 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+
+public class Streamer
+{
+ public string name { get; set; }
+ public int id { get; set; }
+}
+
+public class Commenter
+{
+ public string display_name { get; set; }
+ public string _id { get; set; }
+ public string name { get; set; }
+ public string type { get; set; }
+ public string bio { get; set; }
+ public DateTime created_at { get; set; }
+ public DateTime updated_at { get; set; }
+ public string logo { get; set; }
+}
+
+public class Emoticon
+{
+ public string emoticon_id { get; set; }
+ public string emoticon_set_id { get; set; }
+}
+
+public class Fragment
+{
+ public string text { get; set; }
+ public Emoticon emoticon { get; set; }
+}
+
+public class UserBadge
+{
+ public string _id { get; set; }
+ public string version { get; set; }
+}
+
+public class Emoticon2
+{
+ public string _id { get; set; }
+ public int begin { get; set; }
+ public int end { get; set; }
+}
+
+public class Message
+{
+ public string body { get; set; }
+ public List fragments { get; set; }
+ public bool is_action { get; set; }
+ public List user_badges { get; set; }
+ public string user_color { get; set; }
+ public UserNoticeParams user_notice_params { get; set; }
+ public List emoticons { get; set; }
+}
+
+public class UserNoticeParams
+{
+ [JsonProperty("msg-id")]
+ public string msg_id { get; set; }
+}
+
+public class Comment
+{
+ public string _id { get; set; }
+ public DateTime created_at { get; set; }
+ public DateTime updated_at { get; set; }
+ public string channel_id { get; set; }
+ public string content_type { get; set; }
+ public string content_id { get; set; }
+ public double content_offset_seconds { get; set; }
+ public Commenter commenter { get; set; }
+ public string source { get; set; }
+ public string state { get; set; }
+ public Message message { get; set; }
+ public bool more_replies { get; set; }
+}
+
+public class ChatRoot
+{
+ public Streamer streamer { get; set; }
+ public List comments { get; set; }
+}
\ No newline at end of file
diff --git a/TwitchDownloaderWPF/Images/peepoSad.png b/TwitchDownloaderWPF/Images/peepoSad.png
new file mode 100644
index 00000000..afa5da4b
Binary files /dev/null and b/TwitchDownloaderWPF/Images/peepoSad.png differ
diff --git a/TwitchDownloaderWPF/Images/ppHop.gif b/TwitchDownloaderWPF/Images/ppHop.gif
new file mode 100644
index 00000000..ac64af18
Binary files /dev/null and b/TwitchDownloaderWPF/Images/ppHop.gif differ
diff --git a/TwitchDownloaderWPF/Images/ppOverheat.gif b/TwitchDownloaderWPF/Images/ppOverheat.gif
new file mode 100644
index 00000000..539772e3
Binary files /dev/null and b/TwitchDownloaderWPF/Images/ppOverheat.gif differ
diff --git a/TwitchDownloaderWPF/InfoHelper.cs b/TwitchDownloaderWPF/InfoHelper.cs
new file mode 100644
index 00000000..e008d78b
--- /dev/null
+++ b/TwitchDownloaderWPF/InfoHelper.cs
@@ -0,0 +1,100 @@
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media.Imaging;
+
+namespace TwitchDownloaderWPF
+{
+ public class InfoHelper
+ {
+ public static async Task GetThumb(string thumbUrl)
+ {
+ using (HttpClient client = new HttpClient())
+ {
+ BitmapImage img = new BitmapImage();
+ img.CacheOption = BitmapCacheOption.OnLoad;
+ img.BeginInit();
+ img.StreamSource = await client.GetStreamAsync(thumbUrl);
+ img.EndInit();
+ return img;
+ }
+ }
+
+ public static async Task GetVideoInfo(int videoId)
+ {
+ using (WebClient client = new WebClient())
+ {
+ client.Encoding = Encoding.UTF8;
+ client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
+ string response = await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/videos?id=" + videoId);
+ JObject result = JObject.Parse(response);
+ return result;
+ }
+ }
+
+ public static async Task GetVideoToken(int videoId)
+ {
+ using (WebClient client = new WebClient())
+ {
+ client.Encoding = Encoding.UTF8;
+ client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
+ string response = await client.DownloadStringTaskAsync(String.Format("https://api.twitch.tv/api/vods/{0}/access_token", videoId));
+ JObject result = JObject.Parse(response);
+ return result;
+ }
+ }
+
+ public static async Task GetVideoPlaylist(int videoId, string token, string sig)
+ {
+ using (WebClient client = new WebClient())
+ {
+ client.Encoding = Encoding.UTF8;
+ client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
+ string playlist = await client.DownloadStringTaskAsync(String.Format("http://usher.twitch.tv/vod/{0}?nauth={1}&nauthsig={2}&allow_source=true&player=twitchweb", videoId, token, sig));
+ return playlist.Split('\n');
+ }
+ }
+
+ public static async Task GetClipInfo(object clipId)
+ {
+ using (WebClient client = new WebClient())
+ {
+ client.Encoding = Encoding.UTF8;
+ client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
+ string response = await client.DownloadStringTaskAsync(String.Format("https://api.twitch.tv/helix/clips?id={0}", clipId));
+ JObject result = JObject.Parse(response);
+ return result;
+ }
+ }
+
+ public static async Task GetClipInfoChat(object clipId)
+ {
+ using (WebClient client = new WebClient())
+ {
+ client.Headers.Add("Accept", "application/vnd.twitchtv.v5+json");
+ client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
+ string response = await client.DownloadStringTaskAsync(String.Format("https://api.twitch.tv/kraken/clips/{0}", clipId));
+ JObject result = JObject.Parse(response);
+ return result;
+ }
+ }
+
+ public static async Task GetClipLinks(object clipId)
+ {
+ using (WebClient client = new WebClient())
+ {
+ client.Encoding = Encoding.UTF8;
+ client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
+ //API is deprecated - hopefully keeps working for a while. Can genereate full url from thumbnail but fails ocasionally https://discuss.dev.twitch.tv/t/clips-api-does-not-expose-video-url/15763/2
+ string response = await client.DownloadStringTaskAsync(String.Format("https://clips.twitch.tv/api/v2/clips/{0}/status", clipId));
+ JObject result = JObject.Parse(response);
+ return result;
+ }
+ }
+ }
+}
diff --git a/TwitchDownloaderWPF/MainWindow.xaml b/TwitchDownloaderWPF/MainWindow.xaml
new file mode 100644
index 00000000..9adee6b2
--- /dev/null
+++ b/TwitchDownloaderWPF/MainWindow.xaml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TwitchDownloaderWPF/MainWindow.xaml.cs b/TwitchDownloaderWPF/MainWindow.xaml.cs
new file mode 100644
index 00000000..b2d9e676
--- /dev/null
+++ b/TwitchDownloaderWPF/MainWindow.xaml.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Xabe.FFmpeg;
+
+namespace TwitchDownloaderWPF
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ PageVodDownload pageVodDownload = new PageVodDownload();
+ PageClipDownload pageClipDownload = new PageClipDownload();
+ PageChatDownload pageChatDownload = new PageChatDownload();
+ PageChatRender pageChatRender = new PageChatRender();
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+
+ private void btnVodDownload_Click(object sender, RoutedEventArgs e)
+ {
+ Main.Content = pageVodDownload;
+ }
+
+ private void btnClipDownload_Click(object sender, RoutedEventArgs e)
+ {
+ Main.Content = pageClipDownload;
+ }
+
+ private void btnChatDownload_Click(object sender, RoutedEventArgs e)
+ {
+ Main.Content = pageChatDownload;
+ }
+
+ private void btnChatRender_Click(object sender, RoutedEventArgs e)
+ {
+ Main.Content = pageChatRender;
+ }
+
+ private async void Window_Loaded(object sender, RoutedEventArgs e)
+ {
+ Main.Content = pageVodDownload;
+ if (!File.Exists("ffmpeg.exe"))
+ await FFmpeg.GetLatestVersion();
+ }
+
+ private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ string tempFolder = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "TwitchDownloader");
+ try
+ {
+ DeleteDirectory(tempFolder);
+ }
+ catch { }
+ }
+
+ public static void DeleteDirectory(string target_dir)
+ {
+ string[] files = Directory.GetFiles(target_dir);
+ string[] dirs = Directory.GetDirectories(target_dir);
+
+ foreach (string file in files)
+ {
+ File.SetAttributes(file, FileAttributes.Normal);
+ File.Delete(file);
+ }
+
+ foreach (string dir in dirs)
+ {
+ DeleteDirectory(dir);
+ }
+
+ Directory.Delete(target_dir, false);
+ }
+ }
+}
diff --git a/TwitchDownloaderWPF/PageChatDownload.xaml b/TwitchDownloaderWPF/PageChatDownload.xaml
new file mode 100644
index 00000000..31f709fc
--- /dev/null
+++ b/TwitchDownloaderWPF/PageChatDownload.xaml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TwitchDownloaderWPF/PageChatDownload.xaml.cs b/TwitchDownloaderWPF/PageChatDownload.xaml.cs
new file mode 100644
index 00000000..04326835
--- /dev/null
+++ b/TwitchDownloaderWPF/PageChatDownload.xaml.cs
@@ -0,0 +1,375 @@
+using Microsoft.Win32;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using TwitchDownloaderWPF;
+using WpfAnimatedGif;
+
+namespace TwitchDownloaderWPF
+{
+ public enum DownloadType { Clip, Video }
+ ///
+ /// Interaction logic for PageChatDownload.xaml
+ ///
+ public partial class PageChatDownload : Page
+ {
+
+ public DownloadType downloadType;
+ public string downloadId;
+ public int streamerId;
+ JObject videoData = new JObject();
+ public PageChatDownload()
+ {
+ InitializeComponent();
+ }
+
+ private void Page_Initialized(object sender, EventArgs e)
+ {
+ SetEnabled(false, false);
+ }
+
+ private void SetEnabled(bool isEnabled, bool onlyCrop)
+ {
+ checkStart.IsEnabled = isEnabled;
+ checkEnd.IsEnabled = isEnabled;
+ numStartHour.IsEnabled = isEnabled;
+ numStartMinute.IsEnabled = isEnabled;
+ numStartSecond.IsEnabled = isEnabled;
+ numEndHour.IsEnabled = isEnabled;
+ numEndMinute.IsEnabled = isEnabled;
+ numEndSecond.IsEnabled = isEnabled;
+
+ if (!onlyCrop)
+ {
+ btnDownload.IsEnabled = isEnabled;
+ radioJson.IsEnabled = isEnabled;
+ radioText.IsEnabled = isEnabled;
+ }
+ }
+
+ private async void btnGetInfo_Click(object sender, RoutedEventArgs e)
+ {
+ string id = ValidateUrl(textUrl.Text);
+ if (id != "")
+ {
+ btnGetInfo.IsEnabled = false;
+ downloadId = id;
+ if (id.All(Char.IsDigit))
+ downloadType = DownloadType.Video;
+ else
+ downloadType = DownloadType.Clip;
+
+ try
+ {
+ if (downloadType == DownloadType.Video)
+ {
+ Task taskInfo = InfoHelper.GetVideoInfo(Int32.Parse(downloadId));
+ await Task.WhenAll(taskInfo);
+
+ JToken clipData = taskInfo.Result;
+ videoData = taskInfo.Result;
+ string thumbUrl = videoData["data"][0]["thumbnail_url"].ToString().Replace("%{width}", 512.ToString()).Replace("%{height}", 290.ToString());
+ Task taskThumb = InfoHelper.GetThumb(thumbUrl);
+ await Task.WhenAll(taskThumb);
+
+ imgThumbnail.Source = taskThumb.Result;
+ textTitle.Text = taskInfo.Result["data"][0]["title"].ToString();
+ textStreamer.Text = taskInfo.Result["data"][0]["user_name"].ToString();
+ textCreatedAt.Text = taskInfo.Result["data"][0]["created_at"].ToString();
+ streamerId = taskInfo.Result["data"][0]["user_id"].ToObject();
+ SetEnabled(true, false);
+ }
+ else if (downloadType == DownloadType.Clip)
+ {
+ string clipId = downloadId;
+ Task taskInfo = InfoHelper.GetClipInfoChat(clipId);
+ await Task.WhenAll(taskInfo);
+
+ JToken clipData = taskInfo.Result;
+ videoData = taskInfo.Result;
+ string thumbUrl = clipData["thumbnails"]["medium"].ToString();
+ Task taskThumb = InfoHelper.GetThumb(thumbUrl);
+ await Task.WhenAll(taskThumb);
+
+ imgThumbnail.Source = taskThumb.Result;
+ textStreamer.Text = clipData["broadcaster"]["display_name"].ToString();
+ textCreatedAt.Text = clipData["created_at"].ToString();
+ textTitle.Text = clipData["title"].ToString();
+ streamerId = clipData["broadcaster"]["id"].ToObject();
+ SetEnabled(true, false);
+ SetEnabled(false, true);
+ }
+
+ btnGetInfo.IsEnabled = true;
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("Unable to get Clip/Video information. Please double check your link and try again", "Unable to get info", MessageBoxButton.OK, MessageBoxImage.Error);
+ AppendLog("ERROR: " + ex.Message);
+ btnGetInfo.IsEnabled = true;
+ }
+ }
+ else
+ {
+ MessageBox.Show("Please double check the VOD/Clip link", "Unable to parse input", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ private string ValidateUrl(string text)
+ {
+ Regex clipRegex = new Regex(@"twitch.tv\/(\S+)\/clip\/");
+ if (text.All(Char.IsLetter) || text.All(Char.IsDigit))
+ {
+ return text;
+ }
+ else if (text.Contains("twitch.tv/videos/"))
+ {
+ int number;
+ Uri url = new Uri(text);
+ string path = String.Format("{0}{1}{2}{3}", url.Scheme, Uri.SchemeDelimiter, url.Authority, url.AbsolutePath);
+ bool success = Int32.TryParse(Regex.Match(path, @"\d+").Value, out number);
+ if (success)
+ return number.ToString();
+ else
+ return "";
+ }
+ else if (text.Contains("clips.twitch.tv/") || clipRegex.IsMatch(text))
+ {
+ Uri url = new Uri(text);
+ string path = String.Format("{0}{1}{2}{3}", url.Scheme, Uri.SchemeDelimiter, url.Authority, url.AbsolutePath);
+ return path.Split('/').Last();
+ }
+ return "";
+ }
+
+ private void BackgroundDownloadManager_DoWork(object sender, DoWorkEventArgs e)
+ {
+ ChatDownloadInfo clipInfo = (ChatDownloadInfo)e.Argument;
+
+ using (WebClient client = new WebClient())
+ {
+ client.Encoding = Encoding.UTF8;
+ client.Headers.Add("Accept", "application/vnd.twitchtv.v5+json; charset=UTF-8");
+ client.Headers.Add("Client-Id", "kimne78kx3ncx6brgo4mv6wki5h1ko");
+
+ bool isFirst = true;
+ string cursor = "";
+ double latestMessage = clipInfo.offset - 1;
+ double videoStart = clipInfo.offset;
+ double videoDuration = clipInfo.duration;
+ JObject result = new JObject();
+ JArray comments = new JArray();
+ JObject streamer = new JObject();
+
+ streamer["name"] = clipInfo.streamer_name;
+ streamer["id"] = clipInfo.streamer_id;
+
+ while (latestMessage < (videoStart + videoDuration))
+ {
+ string response;
+ if (isFirst)
+ response = client.DownloadString(String.Format("https://api.twitch.tv/v5/videos/{0}/comments?content_offset_seconds={1}", clipInfo.vod_id, clipInfo.offset));
+ else
+ response = client.DownloadString(String.Format("https://api.twitch.tv/v5/videos/{0}/comments?cursor={1}", clipInfo.vod_id, cursor));
+
+ JObject res = JObject.Parse(response);
+
+ foreach (var comment in res["comments"])
+ {
+ if (latestMessage < (videoStart + videoDuration))
+ comments.Add(comment);
+
+ latestMessage = comment["content_offset_seconds"].ToObject();
+ }
+ if (res["_next"] == null)
+ break;
+ else
+ cursor = res["_next"].ToString();
+
+ int percent = (int)Math.Floor((latestMessage - videoStart) / videoDuration * 100);
+ (sender as BackgroundWorker).ReportProgress(percent, String.Format("Downloading {0}%", percent));
+
+ if (isFirst)
+ isFirst = false;
+
+ }
+
+ result["streamer"] = streamer;
+ result["comments"] = comments;
+
+ using (StreamWriter sw = new StreamWriter(clipInfo.path))
+ {
+ if (clipInfo.is_json)
+ {
+ sw.Write(result.ToString(Newtonsoft.Json.Formatting.Indented));
+ }
+ else
+ {
+ foreach (var comment in result["comments"])
+ {
+ string username = comment["commenter"]["display_name"].ToString();
+ string message = comment["message"]["body"].ToString();
+ sw.WriteLine(String.Format("{0}: {1}", username, message));
+ }
+ }
+
+ sw.Flush();
+ sw.Close();
+ clipInfo = null;
+ result = null;
+ }
+ }
+ }
+
+ private void BackgroundDownloadManager_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+ {
+ btnGetInfo.IsEnabled = true;
+ statusProgressBar.Value = 0;
+ if (e.Error == null)
+ {
+ statusMessage.Text = "Done";
+ SetImage("Images/ppHop.gif", true);
+
+ }
+ else
+ {
+ statusMessage.Text = "ERROR";
+ SetImage("Images/peepoSad.png", false);
+ AppendLog("ERROR: " + e.Error.Message);
+ }
+ }
+
+ private void BackgroundDownloadManager_ProgressChanged(object sender, ProgressChangedEventArgs e)
+ {
+ string message = (string)e.UserState;
+ statusMessage.Text = message;
+ statusProgressBar.Value = e.ProgressPercentage >= 100 ? 100 : e.ProgressPercentage;
+ }
+
+ private void AppendLog(string message)
+ {
+ textLog.Dispatcher.BeginInvoke((Action)(() =>
+ textLog.AppendText(message + Environment.NewLine)
+ ));
+ }
+
+ private void btnDownload_Click(object sender, RoutedEventArgs e)
+ {
+ SaveFileDialog saveFileDialog = new SaveFileDialog();
+
+ if (radioJson.IsChecked == true)
+ saveFileDialog.Filter = "JSON Files | *.json";
+ else
+ saveFileDialog.Filter = "TXT Files | *.txt";
+
+ saveFileDialog.RestoreDirectory = true;
+
+ if (saveFileDialog.ShowDialog() == true)
+ {
+ try
+ {
+ ChatDownloadInfo info;
+ if (downloadType == DownloadType.Video)
+ {
+ int startTime = 0;
+ int duration = 0;
+
+ if (checkStart.IsChecked == true)
+ {
+ TimeSpan start = new TimeSpan((int)numStartHour.Value, (int)numStartMinute.Value, (int)numStartSecond.Value);
+ startTime = (int)Math.Round(start.TotalSeconds);
+ }
+
+ if (checkEnd.IsChecked == true)
+ {
+ TimeSpan end = new TimeSpan((int)numEndHour.Value, (int)numEndMinute.Value, (int)numEndSecond.Value);
+ duration = (int)Math.Ceiling(end.TotalSeconds - startTime);
+ }
+ else
+ {
+ TimeSpan vodLength = TimeSpan.Parse(Regex.Replace(videoData["data"][0]["duration"].ToString(), @"[^\d]", ":").TrimEnd(':'));
+ duration = (int)Math.Ceiling(vodLength.TotalSeconds);
+ }
+ info = new ChatDownloadInfo(downloadType, textUrl.Text, saveFileDialog.FileName, videoData["data"][0]["id"].ToString(), startTime, duration, (bool)radioJson.IsChecked, textStreamer.Text, streamerId);
+ }
+ else
+ info = new ChatDownloadInfo(downloadType, textUrl.Text, saveFileDialog.FileName, videoData["vod"]["id"].ToString(), videoData["vod"]["offset"].ToObject(), videoData["duration"].ToObject(), (bool)radioJson.IsChecked, textStreamer.Text, streamerId);
+ statusMessage.Text = "Downloading";
+ btnGetInfo.IsEnabled = false;
+ SetEnabled(false, false);
+
+ BackgroundWorker backgroundDownloadManager = new BackgroundWorker();
+ backgroundDownloadManager.WorkerReportsProgress = true;
+ backgroundDownloadManager.DoWork += BackgroundDownloadManager_DoWork;
+ backgroundDownloadManager.ProgressChanged += BackgroundDownloadManager_ProgressChanged;
+ backgroundDownloadManager.RunWorkerCompleted += BackgroundDownloadManager_RunWorkerCompleted;
+
+ SetImage("Images/ppOverheat.gif", true);
+ statusMessage.Text = "Downloading";
+ backgroundDownloadManager.RunWorkerAsync(info);
+ }
+ catch (Exception ex)
+ {
+ AppendLog("ERROR: " + ex.Message);
+ }
+ }
+ }
+
+ public void SetImage(string imageUri, bool isGif)
+ {
+ var image = new BitmapImage();
+ image.BeginInit();
+ image.UriSource = new Uri(imageUri, UriKind.Relative);
+ image.EndInit();
+ if (isGif)
+ ImageBehavior.SetAnimatedSource(statusImage, image);
+ else
+ {
+ ImageBehavior.SetAnimatedSource(statusImage, null);
+ statusImage.Source = image;
+ }
+ }
+ }
+}
+
+public class ChatDownloadInfo
+{
+ public DownloadType is_vod { get; set; }
+ public string id { get; set; }
+ public string path { get; set; }
+ public string vod_id { get; set; }
+ public int offset { get; set; }
+ public double duration { get; set; }
+ public bool is_json { get; set; }
+ public string streamer_name { get; set; }
+ public int streamer_id { get; set; }
+
+ public ChatDownloadInfo(DownloadType Is_vod, string Id, string Path, string Vod_id, int Offset, double Duration, bool Is_json, string Streamer_name, int Streamer_id)
+ {
+ is_vod = Is_vod;
+ id = Id;
+ path = Path;
+ vod_id = Vod_id;
+ offset = Offset;
+ duration = Duration;
+ is_json = Is_json;
+ streamer_name = Streamer_name;
+ streamer_id = Streamer_id;
+ }
+}
\ No newline at end of file
diff --git a/TwitchDownloaderWPF/PageChatRender.xaml b/TwitchDownloaderWPF/PageChatRender.xaml
new file mode 100644
index 00000000..31285d35
--- /dev/null
+++ b/TwitchDownloaderWPF/PageChatRender.xaml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TwitchDownloaderWPF/PageChatRender.xaml.cs b/TwitchDownloaderWPF/PageChatRender.xaml.cs
new file mode 100644
index 00000000..ca5f85f1
--- /dev/null
+++ b/TwitchDownloaderWPF/PageChatRender.xaml.cs
@@ -0,0 +1,1149 @@
+using Microsoft.Win32;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing.Text;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Data;
+using System.Windows.Input;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using WpfAnimatedGif;
+using System.Net;
+using System.Text.RegularExpressions;
+using System.Diagnostics;
+using Accord.Video.FFMPEG;
+using System.Drawing.Imaging;
+using System.Windows.Markup;
+using System.Collections.Concurrent;
+using Newtonsoft.Json;
+using SkiaSharp;
+using TwitchDownloader.Properties;
+
+namespace TwitchDownloaderWPF
+{
+ ///
+ /// Interaction logic for PageChatRender.xaml
+ ///
+ public partial class PageChatRender : System.Windows.Controls.Page
+ {
+ public bool lastHasEmoteAtEnd = false;
+ public SKPaint imagePaint = new SKPaint() { IsAntialias = true, FilterQuality = SKFilterQuality.High };
+ public SKFontManager fontManager = SKFontManager.CreateDefault();
+ public ConcurrentDictionary fallbackCache = new ConcurrentDictionary();
+
+ public PageChatRender()
+ {
+ InitializeComponent();
+ }
+
+ private void btnBrowse_Click(object sender, RoutedEventArgs e)
+ {
+ OpenFileDialog openFileDialog = new OpenFileDialog();
+ openFileDialog.Filter = "JSON Files | *.json";
+ openFileDialog.RestoreDirectory = true;
+
+ if (openFileDialog.ShowDialog() == true)
+ {
+ textJson.Text = openFileDialog.FileName;
+ }
+ }
+
+ private void btnRender_Click(object sender, RoutedEventArgs e)
+ {
+ bool validInputs = ValidateInputs();
+ if (validInputs)
+ {
+ SaveFileDialog saveFileDialog = new SaveFileDialog();
+
+ saveFileDialog.Filter = "MP4 Files | *.mp4";
+ saveFileDialog.RestoreDirectory = true;
+
+ if (saveFileDialog.ShowDialog() == true)
+ {
+ SKColor backgroundColor = new SKColor(colorBackground.SelectedColor.Value.R, colorBackground.SelectedColor.Value.G, colorBackground.SelectedColor.Value.B);
+ System.Drawing.Color backgroundColorDrawing = System.Drawing.Color.FromArgb((int)colorBackground.SelectedColor.Value.R, (int)colorBackground.SelectedColor.Value.G, (int)colorBackground.SelectedColor.Value.B);
+ RenderOptions info = new RenderOptions(textJson.Text, saveFileDialog.FileName, backgroundColor, Int32.Parse(textHeight.Text), Int32.Parse(textWidth.Text), (bool)checkBTTV.IsChecked, (bool)checkFFZ.IsChecked, (bool)checkOutline.IsChecked, (string)comboFont.SelectedItem, Double.Parse(textFontSize.Text), Double.Parse(textUpdateTime.Text), (bool)checkCompact.IsChecked, backgroundColorDrawing, (bool)checkTimestamp.IsChecked);
+ SaveSettings();
+ BackgroundWorker backgroundRenderManager = new BackgroundWorker();
+ backgroundRenderManager.WorkerReportsProgress = true;
+ backgroundRenderManager.DoWork += BackgroundRenderManager_DoWork;
+ backgroundRenderManager.ProgressChanged += BackgroundRenderManager_ProgressChanged;
+ backgroundRenderManager.RunWorkerCompleted += BackgroundRenderManager_RunWorkerCompleted;
+
+ SetImage("Images/ppOverheat.gif", true);
+ backgroundRenderManager.RunWorkerAsync(info);
+ btnRender.IsEnabled = false;
+ }
+ }
+ else
+ {
+ MessageBox.Show("Please double check your inputs are valid", "Unable to parse inputs", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ private void BackgroundRenderManager_DoWork(object sender, DoWorkEventArgs e)
+ {
+ RenderOptions renderOptions = (RenderOptions)e.Argument;
+ ChatRoot chatJson = JsonConvert.DeserializeObject(File.ReadAllText(renderOptions.json_path));
+ BlockingCollection finalComments = new BlockingCollection();
+ List thirdPartyEmotes = new List();
+ List chatBadges = new List();
+ Dictionary chatEmotes = new Dictionary();
+ Dictionary emojiCache = new Dictionary();
+ Random rand = new Random();
+ string[] defaultColors = { "#FF0000", "#0000FF", "#00FF00", "#B22222", "#FF7F50", "#9ACD32", "#FF4500", "#2E8B57", "#DAA520", "#D2691E", "#5F9EA0", "#1E90FF", "#FF69B4", "#8A2BE2", "#00FF7F" };
+ string emojiRegex = "[#*0-9]\uFE0F\u20E3|[\u00A9\u00AE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618]|\u261D(?:\uD83C[\uDFFB-\uDFFF])?|[\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7\u26F8]|\u26F9(?:\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?|\uFE0F\u200D[\u2640\u2642]\uFE0F)?|[\u26FA\u26FD\u2702\u2705\u2708\u2709]|[\u270A-\u270D](?:\uD83C[\uDFFB-\uDFFF])?|[\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C(?:[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A]|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|[\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF84]|\uDF85(?:\uD83C[\uDFFB-\uDFFF])?|[\uDF86-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFC1]|\uDFC2(?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC3\uDFC4](?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDFC5\uDFC6]|\uDFC7(?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC8\uDFC9]|\uDFCA(?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDFCB\uDFCC](?:\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?|\uFE0F\u200D[\u2640\u2642]\uFE0F)?|[\uDFCD-\uDFF0]|\uDFF3(?:\uFE0F\u200D\uD83C\uDF08)?|\uDFF4(?:\u200D\u2620\uFE0F|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDC73\uDB40\uDC63\uDB40\uDC74|\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F)?|[\uDFF5\uDFF7-\uDFFF])|\uD83D(?:[\uDC00-\uDC14]|\uDC15(?:\u200D\uD83E\uDDBA)?|[\uDC16-\uDC40]|\uDC41(?:\uFE0F\u200D\uD83D\uDDE8\uFE0F)?|[\uDC42\uDC43](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC44\uDC45]|[\uDC46-\uDC50](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC51-\uDC65]|[\uDC66\uDC67](?:\uD83C[\uDFFB-\uDFFF])?|\uDC68(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\u2764\uFE0F\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92])|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|[\uDDAF-\uDDB3\uDDBC\uDDBD])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC]|[\uDDAF-\uDDB3\uDDBC\uDDBD])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD]|[\uDDAF-\uDDB3\uDDBC\uDDBD])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE]|[\uDDAF-\uDDB3\uDDBC\uDDBD])))?))?|\uDC69(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\u2764\uFE0F\u200D\uD83D(?:\uDC8B\u200D\uD83D)?[\uDC68\uDC69]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92])|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF]|[\uDDAF-\uDDB3\uDDBC\uDDBD])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF]|\uDC69\uD83C\uDFFB)|[\uDDAF-\uDDB3\uDDBC\uDDBD])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uDC69\uD83C[\uDFFB\uDFFC])|[\uDDAF-\uDDB3\uDDBC\uDDBD])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:\uDD1D\u200D\uD83D(?:\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF]|\uDC69\uD83C[\uDFFB-\uDFFD])|[\uDDAF-\uDDB3\uDDBC\uDDBD])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFE]|[\uDDAF-\uDDB3\uDDBC\uDDBD])))?))?|\uDC6A|[\uDC6B-\uDC6D](?:\uD83C[\uDFFB-\uDFFF])?|\uDC6E(?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|\uDC6F(?:\u200D[\u2640\u2642]\uFE0F)?|\uDC70(?:\uD83C[\uDFFB-\uDFFF])?|\uDC71(?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|\uDC72(?:\uD83C[\uDFFB-\uDFFF])?|\uDC73(?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDC74-\uDC76](?:\uD83C[\uDFFB-\uDFFF])?|\uDC77(?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|\uDC78(?:\uD83C[\uDFFB-\uDFFF])?|[\uDC79-\uDC7B]|\uDC7C(?:\uD83C[\uDFFB-\uDFFF])?|[\uDC7D-\uDC80]|[\uDC81\uDC82](?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|\uDC83(?:\uD83C[\uDFFB-\uDFFF])?|\uDC84|\uDC85(?:\uD83C[\uDFFB-\uDFFF])?|[\uDC86\uDC87](?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDC88-\uDCA9]|\uDCAA(?:\uD83C[\uDFFB-\uDFFF])?|[\uDCAB-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73]|\uDD74(?:\uD83C[\uDFFB-\uDFFF])?|\uDD75(?:\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?|\uFE0F\u200D[\u2640\u2642]\uFE0F)?|[\uDD76-\uDD79]|\uDD7A(?:\uD83C[\uDFFB-\uDFFF])?|[\uDD87\uDD8A-\uDD8D]|[\uDD90\uDD95\uDD96](?:\uD83C[\uDFFB-\uDFFF])?|[\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE44]|[\uDE45-\uDE47](?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDE48-\uDE4A]|\uDE4B(?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|\uDE4C(?:\uD83C[\uDFFB-\uDFFF])?|[\uDE4D\uDE4E](?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|\uDE4F(?:\uD83C[\uDFFB-\uDFFF])?|[\uDE80-\uDEA2]|\uDEA3(?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDEA4-\uDEB3]|[\uDEB4-\uDEB6](?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDEB7-\uDEBF]|\uDEC0(?:\uD83C[\uDFFB-\uDFFF])?|[\uDEC1-\uDEC5\uDECB]|\uDECC(?:\uD83C[\uDFFB-\uDFFF])?|[\uDECD-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB])|\uD83E(?:[\uDD0D\uDD0E]|\uDD0F(?:\uD83C[\uDFFB-\uDFFF])?|[\uDD10-\uDD17]|[\uDD18-\uDD1C](?:\uD83C[\uDFFB-\uDFFF])?|\uDD1D|[\uDD1E\uDD1F](?:\uD83C[\uDFFB-\uDFFF])?|[\uDD20-\uDD25]|\uDD26(?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDD27-\uDD2F]|[\uDD30-\uDD36](?:\uD83C[\uDFFB-\uDFFF])?|\uDD37(?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDD38\uDD39](?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|\uDD3A|\uDD3C(?:\u200D[\u2640\u2642]\uFE0F)?|[\uDD3D\uDD3E](?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDD3F-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDB4]|[\uDDB5\uDDB6](?:\uD83C[\uDFFB-\uDFFF])?|\uDDB7|[\uDDB8\uDDB9](?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|\uDDBA|\uDDBB(?:\uD83C[\uDFFB-\uDFFF])?|[\uDDBC-\uDDCA]|[\uDDCD-\uDDCF](?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|\uDDD0|\uDDD1(?:\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C(?:\uDFFB(?:\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1\uD83C\uDFFB)?|\uDFFC(?:\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB\uDFFC])?|\uDFFD(?:\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD])?|\uDFFE(?:\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE])?|\uDFFF(?:\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])?))?|[\uDDD2-\uDDD5](?:\uD83C[\uDFFB-\uDFFF])?|\uDDD6(?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDDD7-\uDDDD](?:\u200D[\u2640\u2642]\uFE0F|\uD83C[\uDFFB-\uDFFF](?:\u200D[\u2640\u2642]\uFE0F)?)?|[\uDDDE\uDDDF](?:\u200D[\u2640\u2642]\uFE0F)?|[\uDDE0-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])";
+ string tempFolder = Path.Combine(Path.GetTempPath(), "TwitchDownloader");
+ string downloadFolder = Path.Combine(tempFolder, "Chat Render");
+
+ if (!Directory.Exists(downloadFolder))
+ Directory.CreateDirectory(downloadFolder);
+
+ (sender as BackgroundWorker).ReportProgress(0, new Progress("Fetching Chat Badges"));
+ GetChatBadges(chatBadges, chatJson.streamer, renderOptions);
+ (sender as BackgroundWorker).ReportProgress(0, new Progress("Fetching Emotes"));
+ GetEmotes(chatEmotes, chatJson.comments, renderOptions);
+ (sender as BackgroundWorker).ReportProgress(0, new Progress("Fetching Third Party Emotes"));
+ GetThirdPartyEmotes(thirdPartyEmotes, chatJson.streamer, renderOptions);
+ (sender as BackgroundWorker).ReportProgress(0, new Progress("Fetching Twitter Emojis"));
+ GetTwitterEmojis(emojiCache, chatJson.comments, renderOptions, emojiRegex);
+
+ Size canvasSize = new Size(renderOptions.chat_width, renderOptions.has_emote_height);
+ SKPaint nameFont = new SKPaint() { Typeface = SKTypeface.FromFamilyName(renderOptions.font, SKFontStyle.Bold), LcdRenderText = true, SubpixelText = true, TextSize = (float)renderOptions.font_size, IsAntialias = true, HintingLevel = SKPaintHinting.Full, FilterQuality = SKFilterQuality.High };
+ SKPaint messageFont = new SKPaint() { Typeface = SKTypeface.FromFamilyName(renderOptions.font, SKFontStyle.Normal), LcdRenderText = true, SubpixelText = true, TextSize = (float)renderOptions.font_size, IsAntialias = true, HintingLevel = SKPaintHinting.Full, FilterQuality = SKFilterQuality.High, Color = SKColors.White };
+
+ (sender as BackgroundWorker).ReportProgress(0, new Progress("Rendering Comments"));
+ foreach (Comment comment in chatJson.comments)
+ {
+ if (comment.source != "chat")
+ continue;
+ if (comment.message.user_notice_params.msg_id != null && comment.message.user_notice_params.msg_id != "")
+ continue;
+
+ string userName = comment.commenter.display_name.ToString();
+ int default_x = 2;
+ Point drawPos = new Point(default_x, 0);
+ System.Drawing.Color userColorSystemDrawing = System.Drawing.ColorTranslator.FromHtml(comment.message.user_color != null ? comment.message.user_color : defaultColors[rand.Next(0, defaultColors.Length)]);
+ SKColor userColor = new SKColor(userColorSystemDrawing.R, userColorSystemDrawing.G, userColorSystemDrawing.B);
+
+ List imageList = new List();
+ SKBitmap sectionImage = new SKBitmap((int)canvasSize.Width, (int)canvasSize.Height);
+ List currentGifEmotes = new List();
+ new SKCanvas(sectionImage).Clear(renderOptions.background_color);
+ if (renderOptions.chat_timestamp)
+ sectionImage = DrawTimestamp(sectionImage, imageList, messageFont, renderOptions, comment, canvasSize, ref drawPos, ref default_x);
+ sectionImage = DrawBadges(sectionImage, imageList, renderOptions, chatBadges, comment, canvasSize, ref drawPos);
+ sectionImage = DrawUsername(sectionImage, imageList, renderOptions, nameFont, userName, userColor, canvasSize, ref drawPos);
+ sectionImage = DrawMessage(sectionImage, imageList, renderOptions, currentGifEmotes, messageFont, emojiCache, chatEmotes, thirdPartyEmotes, comment, canvasSize, ref drawPos, emojiRegex, ref default_x);
+
+ int finalHeight = 0;
+ foreach (var img in imageList)
+ finalHeight += img.Height;
+ SKBitmap finalImage = new SKBitmap((int)canvasSize.Width, finalHeight);
+ SKCanvas finalImageCanvas = new SKCanvas(finalImage);
+ finalHeight = 0;
+ foreach (var img in imageList)
+ {
+ finalImageCanvas.DrawBitmap(img, 0, finalHeight);
+ finalHeight += img.Height;
+ img.Dispose();
+ }
+
+ string imagePath = Path.Combine(downloadFolder, Guid.NewGuid() + ".png");
+ finalComments.Add(new TwitchComment(imagePath, Double.Parse(comment.content_offset_seconds.ToString()), currentGifEmotes));
+ using (Stream s = File.OpenWrite(imagePath))
+ {
+ SKImage.FromBitmap(finalImage).Encode(SKEncodedImageFormat.Png, 80).SaveTo(s);
+ }
+ finalImage.Dispose();
+ finalImageCanvas.Dispose();
+ int percent = (int)Math.Floor(((double)finalComments.Count / (double)chatJson.comments.Count) * 100);
+ (sender as BackgroundWorker).ReportProgress(percent, new Progress("Rendering Comments"));
+ }
+
+ (sender as BackgroundWorker).ReportProgress(0, new Progress("Rendering Video 0%"));
+ RenderVideo(renderOptions, new List(finalComments.ToArray()), chatJson.comments, sender);
+
+ (sender as BackgroundWorker).ReportProgress(0, new Progress("Cleaning up..."));
+ string[] files = Directory.GetFiles(downloadFolder);
+ for (int i = 0; i < files.Length; i++)
+ {
+ try
+ {
+ File.Delete(files[i]);
+ }
+ catch { }
+ }
+ }
+
+ private void RenderVideo(RenderOptions renderOptions, List finalComments, List comments, object sender)
+ {
+ System.Drawing.Bitmap canvas = new System.Drawing.Bitmap(renderOptions.chat_width, renderOptions.chat_height);
+ System.Drawing.Graphics gcan = System.Drawing.Graphics.FromImage(canvas);
+ int videoStart = (int)Math.Floor(comments.First().content_offset_seconds);
+ int duration = (int)Math.Ceiling(comments.Last().content_offset_seconds) - videoStart;
+ List displayedGifs = new List();
+ System.Drawing.Color backgroundColor = renderOptions.background_color_drawing;
+ Stopwatch stopwatch = new Stopwatch();
+ using (var vFWriter = new VideoFileWriter())
+ {
+ // create new video file
+ stopwatch.Start();
+ vFWriter.Open(renderOptions.save_path, renderOptions.chat_width, renderOptions.chat_height, 60, VideoCodec.H264, 6000000);
+ gcan.FillRectangle(new System.Drawing.SolidBrush(backgroundColor), 0, 0, renderOptions.chat_width, renderOptions.chat_height);
+ int startTick = (int)Math.Floor(videoStart / (1.0 / 60.0));
+ int endTick = (int)Math.Floor((videoStart + duration) / (1.0 / 60.0));
+ int lastUpdateTick = startTick;
+ int globalTick = startTick;
+ for (int i = startTick; i < endTick; i++)
+ {
+ int height = 0;
+ if (globalTick % renderOptions.update_frame == 0)
+ {
+ int y = 0;
+ List newly_added = new List();
+ List old = new List(displayedGifs);
+ for (int j = 0; j < finalComments.Count; j++)
+ {
+ int commentTick = (int)Math.Floor(finalComments[j].secondsOffset / (1.0 / 60.0));
+ if (commentTick >= lastUpdateTick && commentTick < globalTick)
+ {
+ System.Drawing.Bitmap sectionImage = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromFile(finalComments[j].section);
+ foreach (var emote in finalComments[j].gifEmotes)
+ {
+ GifEmote newGif = new GifEmote(new Point(emote.offset.X, emote.offset.Y + height), emote.name, emote.image, emote.imageScale);
+ displayedGifs.Add(newGif);
+ newly_added.Add(newGif);
+ }
+ height += sectionImage.Height;
+ }
+ }
+ foreach (var emote in old)
+ emote.offset = new Point(emote.offset.X, emote.offset.Y - height);
+ foreach (var emote in newly_added)
+ emote.offset = new Point(emote.offset.X, (renderOptions.chat_height - height) + emote.offset.Y);
+
+ if (height > 0)
+ {
+ System.Drawing.Bitmap buffer = new System.Drawing.Bitmap(renderOptions.chat_width, height);
+ System.Drawing.Graphics bg = System.Drawing.Graphics.FromImage(buffer);
+
+ for (int j = 0; j < finalComments.Count; j++)
+ {
+ int commentTick = (int)Math.Floor(finalComments[j].secondsOffset / (1.0 / 60.0));
+ if (commentTick >= lastUpdateTick && commentTick < globalTick)
+ {
+ System.Drawing.Bitmap sectionImage = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromFile(finalComments[j].section);
+ bg.DrawImage(sectionImage, 0, y);
+ y += sectionImage.Height;
+ }
+ }
+ gcan = System.Drawing.Graphics.FromImage(canvas);
+ gcan.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
+ gcan.DrawImage(canvas, 0, -height);
+ gcan.DrawImage(buffer, 0, renderOptions.chat_height - height);
+ }
+ lastUpdateTick = globalTick;
+ }
+ List to_remove = new List();
+ foreach (var emote in displayedGifs)
+ {
+ if (emote.offset.Y < -emote.image.Width - renderOptions.chat_height)
+ {
+ to_remove.Add(emote);
+ }
+ else
+ {
+ int gifTime = (int)Math.Floor(1.5 * globalTick) % emote.total_duration;
+ int frame = emote.frames - 1;
+ int timeCount = 0;
+ for (int k = 0; k < emote.durations.Count; k++)
+ {
+ if (timeCount + emote.durations[k] > gifTime)
+ {
+ frame = k;
+ break;
+ }
+ timeCount += emote.durations[k];
+ }
+ FrameDimension dim = new FrameDimension(emote.image.FrameDimensionsList[0]);
+ emote.image.SelectActiveFrame(dim, frame);
+ gcan.DrawImage(emote.image, (float)emote.offset.X, (float)emote.offset.Y + (int)Math.Floor((renderOptions.has_emote_height - ((emote.image.Height/emote.imageScale) * renderOptions.image_scale)) /2.0), (float)((emote.image.Width / emote.imageScale)*renderOptions.image_scale), (float)((emote.image.Height / emote.imageScale)*renderOptions.image_scale));
+ }
+ }
+
+ foreach (var emote in to_remove)
+ {
+ displayedGifs.Remove(emote);
+ }
+
+ vFWriter.WriteVideoFrame(canvas);
+ foreach (var emote in displayedGifs)
+ {
+ gcan.FillRectangle(new System.Drawing.SolidBrush(backgroundColor), (float)emote.offset.X, (float)emote.offset.Y + (int)Math.Floor((renderOptions.has_emote_height - ((emote.image.Height / emote.imageScale) * renderOptions.image_scale)) / 2.0), (float)((emote.image.Width / emote.imageScale) * renderOptions.image_scale), (float)((emote.image.Height / emote.imageScale) * renderOptions.image_scale));
+ }
+ globalTick += 1;
+ double percentDouble = (double)(globalTick - startTick) / (double)(endTick - startTick) * 100.0;
+ int percentInt = (int)Math.Floor(percentDouble);
+ (sender as BackgroundWorker).ReportProgress(percentInt, new Progress(String.Format("Rendering Video {0}%", percentInt), (int)Math.Floor(stopwatch.Elapsed.TotalSeconds), percentDouble));
+ }
+ vFWriter.Close();
+ stopwatch.Stop();
+ }
+ }
+
+ private SKBitmap DrawMessage(SKBitmap sectionImage, List imageList, RenderOptions renderOptions, List currentGifEmotes, SKPaint messageFont, Dictionary emojiCache, Dictionary chatEmotes, List thirdPartyEmotes, Comment comment, Size canvasSize, ref Point drawPos, string emojiRegex, ref int default_x)
+ {
+ bool hasEmote = false;
+ foreach (var fragment in comment.message.fragments)
+ {
+ if (fragment.emoticon == null)
+ {
+ string[] fragmentParts = fragment.text.Split(' ');
+ for (int i = 0; i < fragmentParts.Length; i++)
+ {
+ string output = fragmentParts[i].Trim();
+ bool isThirdPartyEmote = false;
+ ThirdPartyEmote currentEmote = null;
+
+ if (output == "" || output == "")
+ continue;
+
+ foreach (var thirdPartyEmote in thirdPartyEmotes)
+ {
+ if (fragmentParts[i] == thirdPartyEmote.name)
+ {
+ isThirdPartyEmote = true;
+ currentEmote = thirdPartyEmote;
+ }
+ }
+
+ if (isThirdPartyEmote)
+ {
+ lock (currentEmote.emote_drawing)
+ {
+ if (drawPos.X + (currentEmote.emote_drawing.Width / currentEmote.imageScale) * renderOptions.image_scale > canvasSize.Width)
+ sectionImage = AddImageSection(sectionImage, imageList, ref hasEmote, renderOptions, currentGifEmotes, canvasSize, ref drawPos, default_x);
+
+ if (currentEmote.imageType == "gif")
+ {
+ GifEmote emote = new GifEmote(new Point(drawPos.X, drawPos.Y), currentEmote.name, currentEmote.emote_drawing, currentEmote.imageScale);
+ currentGifEmotes.Add(emote);
+ hasEmote = true;
+ drawPos.X += (currentEmote.emote_drawing.Width / currentEmote.imageScale) * renderOptions.image_scale + (3 * renderOptions.image_scale);
+ }
+ else
+ {
+ hasEmote = true;
+ using (SKCanvas sectionImageCanvas = new SKCanvas(sectionImage))
+ {
+ float imageRatio = (float)renderOptions.image_scale / currentEmote.imageScale;
+ float imageWidth = currentEmote.emote.Width * imageRatio;
+ float imageHeight = currentEmote.emote.Height * imageRatio;
+ float left = (float)drawPos.X;
+ float right = imageWidth + left;
+ float top = (float)((sectionImage.Height - imageHeight) / 2);
+ float bottom = imageHeight + top;
+ sectionImageCanvas.DrawBitmap(currentEmote.emote, new SKRect(left, top, right, bottom), imagePaint);
+ drawPos.X += (int)Math.Ceiling(imageWidth + (3 * renderOptions.image_scale));
+ }
+ }
+ }
+ }
+ else
+ {
+ if (Regex.Match(output, emojiRegex).Success)
+ {
+ Match m = Regex.Match(output, emojiRegex);
+ for (var k = 0; k < m.Value.Length; k += char.IsSurrogatePair(m.Value, k) ? 2 : 1)
+ {
+ string codepoint = String.Format("{0:X4}", char.ConvertToUtf32(m.Value, k)).ToLower();
+ codepoint = codepoint.Replace("fe0f", "");
+ if (codepoint != "" && emojiCache.ContainsKey(codepoint))
+ {
+ using (SKCanvas sectionImageCanvas = new SKCanvas(sectionImage))
+ {
+ SKBitmap emojiBitmap = emojiCache[codepoint];
+ float emojiSize = (emojiBitmap.Width / 3) * (float)renderOptions.image_scale;
+ if (drawPos.X + (20 * renderOptions.image_scale) + 3 > canvasSize.Width)
+ sectionImage = AddImageSection(sectionImage, imageList, ref hasEmote, renderOptions, currentGifEmotes, canvasSize, ref drawPos, default_x);
+
+ hasEmote = true;
+ float emojiLeft = (float)Math.Floor(drawPos.X);
+ float emojiTop = (float)Math.Floor((renderOptions.has_emote_height - emojiSize) / 2.0);
+ SKRect emojiRect = new SKRect(emojiLeft, emojiTop, emojiLeft+ emojiSize, emojiTop+ emojiSize);
+ sectionImageCanvas.DrawBitmap(emojiBitmap, emojiRect, imagePaint);
+ drawPos.X += emojiSize + (int)Math.Floor(3 * renderOptions.image_scale);
+ }
+ }
+ }
+ }
+ else if (messageFont.Typeface.CountGlyphs(output) < output.Length)
+ {
+ SKPaint renderFont = messageFont;
+ List charList = new List(output.ToArray());
+ string messageBuffer = "";
+
+ //Very rough estimation of width of text, because we don't know the font yet. This is to show ASCII spam properly
+ int textWidth = (int)Math.Floor(charList.Count * (9.0 * renderOptions.image_scale));
+ if (drawPos.X + textWidth > canvasSize.Width)
+ sectionImage = AddImageSection(sectionImage, imageList, ref hasEmote, renderOptions, currentGifEmotes, canvasSize, ref drawPos, default_x);
+
+ for (int j = 0; j < charList.Count; j++)
+ {
+ if (messageFont.Typeface.CountGlyphs(charList[j].ToString()) == 0)
+ {
+ if (messageBuffer != "")
+ sectionImage = DrawText(sectionImage, messageBuffer, messageFont, imageList, ref hasEmote, renderOptions, currentGifEmotes, canvasSize, ref drawPos, true, default_x);
+ SKPaint fallbackFont = GetFallbackFont(charList[j], renderOptions);
+ fallbackFont.Color = SKColors.White;
+ sectionImage = DrawText(sectionImage, charList[j].ToString(), fallbackFont, imageList, ref hasEmote, renderOptions, currentGifEmotes, canvasSize, ref drawPos, false, default_x);
+ messageBuffer = "";
+ }
+ else
+ {
+ messageBuffer += charList[j];
+ }
+ }
+ }
+ else
+ {
+ sectionImage = DrawText(sectionImage, output, messageFont, imageList, ref hasEmote, renderOptions, currentGifEmotes, canvasSize, ref drawPos, true, default_x);
+ }
+ }
+ }
+ }
+ else
+ {
+ //Is a first party emote
+ int emoteId = Int32.Parse(fragment.emoticon.emoticon_id);
+ if (chatEmotes.ContainsKey(emoteId))
+ {
+ SKBitmap emoteImage = chatEmotes[emoteId];
+ float imageWidth = (float)(emoteImage.Width * renderOptions.image_scale);
+ if (drawPos.X + imageWidth > canvasSize.Width)
+ sectionImage = AddImageSection(sectionImage, imageList, ref hasEmote, renderOptions, currentGifEmotes, canvasSize, ref drawPos, default_x);
+ hasEmote = true;
+ using (SKCanvas sectionImageCanvas = new SKCanvas(sectionImage))
+ {
+
+ float imageHeight = (float)(emoteImage.Height * renderOptions.image_scale);
+ float imageLeft = (float)Math.Floor(drawPos.X);
+ float imageTop = (float)((renderOptions.has_emote_height - imageHeight) / 2.0);
+ SKRect emoteRect = new SKRect(imageLeft, imageTop, imageLeft + imageWidth, imageTop + imageHeight);
+ sectionImageCanvas.DrawBitmap(emoteImage, emoteRect, imagePaint);
+ }
+ drawPos.X += emoteImage.Width;
+ }
+ }
+ }
+
+ sectionImage = CropImage(sectionImage, renderOptions, hasEmote);
+ imageList.Add(sectionImage);
+
+ if (!renderOptions.compact_messages && !lastHasEmoteAtEnd && imageList.First().Height == renderOptions.has_no_emote_eight)
+ {
+ SKBitmap paddingImage = new SKBitmap((int)canvasSize.Width, (int)Math.Floor((renderOptions.has_emote_height - renderOptions.has_no_emote_eight) / 2.0));
+ using (SKCanvas paddingImageCanvas = new SKCanvas(paddingImage))
+ paddingImageCanvas.Clear(renderOptions.background_color);
+ imageList.Insert(0, paddingImage);
+ }
+ lastHasEmoteAtEnd = hasEmote;
+ return sectionImage;
+ }
+
+ private SKBitmap DrawText(SKBitmap sectionImage, string message, SKPaint messageFont, List imageList, ref bool hasEmote, RenderOptions renderOptions, List currentGifEmotes, Size canvasSize, ref Point drawPos, bool padding, int default_x)
+ {
+ float textWidth;
+ try
+ {
+ textWidth = messageFont.MeasureText(message);
+ }
+ catch { return sectionImage; }
+ if (drawPos.X + textWidth + 3 > canvasSize.Width)
+ sectionImage = AddImageSection(sectionImage, imageList, ref hasEmote, renderOptions, currentGifEmotes, canvasSize, ref drawPos, default_x);
+
+ float xPos = (float)Math.Floor(drawPos.X);
+ float yPos = (float)(((canvasSize.Height - renderOptions.font_size) / 2) + renderOptions.font_size) - (float)(renderOptions.image_scale * 2);
+ using (SKCanvas sectionImageCanvas = new SKCanvas(sectionImage))
+ {
+ if (renderOptions.outline)
+ {
+ SKPath outlinePath = messageFont.GetTextPath(message, xPos, yPos);
+ SKPaint outlinePaint = new SKPaint() { Style = SKPaintStyle.Stroke, StrokeWidth = (float)(4 * renderOptions.image_scale), StrokeJoin = SKStrokeJoin.Round, Color = SKColors.Black, IsAntialias = true, LcdRenderText = true, SubpixelText = true, HintingLevel = SKPaintHinting.Full, FilterQuality = SKFilterQuality.High };
+ sectionImageCanvas.DrawPath(outlinePath, outlinePaint);
+ }
+
+ sectionImageCanvas.DrawText(message, xPos, yPos, messageFont);
+ }
+ drawPos.X += textWidth + (padding ? (int)Math.Floor(4 * renderOptions.image_scale) : 0);
+ return sectionImage;
+ }
+
+ private SKBitmap AddImageSection(SKBitmap sectionImage, List imageList, ref bool hasEmote, RenderOptions renderOptions, List currentGifEmotes, Size canvasSize, ref Point drawPos, int default_x)
+ {
+ sectionImage = CropImage(sectionImage, renderOptions, hasEmote);
+ imageList.Add(sectionImage);
+ SKBitmap newImage = new SKBitmap((int)canvasSize.Width, (int)canvasSize.Height);
+ using (SKCanvas paddingImageCanvas = new SKCanvas(newImage))
+ paddingImageCanvas.Clear(renderOptions.background_color);
+ hasEmote = false;
+ drawPos.X = default_x;
+ drawPos.Y += sectionImage.Height;
+ return newImage;
+ }
+
+ private SKBitmap CropImage(SKBitmap sectionImage, RenderOptions renderOptions, bool hasEmote)
+ {
+ if (!hasEmote)
+ {
+ SKBitmap newBitmap = new SKBitmap(sectionImage.Width, renderOptions.has_no_emote_eight);
+
+ using (SKCanvas sectionImageCanvas = new SKCanvas(newBitmap))
+ {
+ float sourceTop = (float)((renderOptions.has_emote_height - renderOptions.has_no_emote_eight) / 2);
+ SKRect sourceRect = new SKRect(0, sourceTop, sectionImage.Width, sourceTop + renderOptions.has_no_emote_eight);
+ SKRect destRect = new SKRect(0, 0, newBitmap.Width, newBitmap.Height);
+ sectionImageCanvas.DrawBitmap(sectionImage, sourceRect, destRect);
+ }
+ sectionImage.Dispose();
+ return newBitmap;
+ }
+ return sectionImage;
+ }
+
+ private SKBitmap DrawTimestamp(SKBitmap sectionImage, List imageList, SKPaint messageFont, RenderOptions renderOptions, Comment comment, Size canvasSize, ref Point drawPos, ref int default_x)
+ {
+ SKCanvas sectionImageCanvas = new SKCanvas(sectionImage);
+ float xPos = (float)drawPos.X;
+ float yPos = (float)(((canvasSize.Height - renderOptions.font_size) / 2) + renderOptions.font_size) - (float)(renderOptions.image_scale * 2);
+ TimeSpan timestamp = new TimeSpan(0, 0, (int)comment.content_offset_seconds);
+ string timeString = timestamp.ToString(@"h\:mm\:ss");
+ float textWidth = messageFont.MeasureText(timeString);
+ if (renderOptions.outline)
+ {
+ SKPath outlinePath = messageFont.GetTextPath(timeString, xPos, yPos);
+ SKPaint outlinePaint = new SKPaint() { Style = SKPaintStyle.Stroke, StrokeWidth = (float)(4 * renderOptions.image_scale), StrokeJoin = SKStrokeJoin.Round, Color = SKColors.Black, IsAntialias = true, LcdRenderText = true, SubpixelText = true, HintingLevel = SKPaintHinting.Full, FilterQuality = SKFilterQuality.High };
+ sectionImageCanvas.DrawPath(outlinePath, outlinePaint);
+ }
+ sectionImageCanvas.DrawText(timeString, xPos, yPos, messageFont);
+ drawPos.X += (int)Math.Floor(textWidth) + (int)Math.Floor(6 * renderOptions.image_scale);
+ default_x = (int)drawPos.X;
+ return sectionImage;
+ }
+
+ private SKBitmap DrawUsername(SKBitmap sectionImage, List imageList, RenderOptions renderOptions, SKPaint nameFont, string userName, SKColor userColor, Size canvasSize, ref Point drawPos)
+ {
+ using (SKCanvas sectionImageCanvas = new SKCanvas(sectionImage))
+ {
+ SKPaint userPaint = nameFont;
+ if (userName.Any(isNotAscii))
+ {
+ userPaint = GetFallbackFont(userName.First(), renderOptions);
+ userPaint.Color = userColor;
+ }
+ float textWidth = userPaint.MeasureText(userName + ":");
+ float xPos = (float)drawPos.X;
+ float yPos = (float)(((canvasSize.Height - renderOptions.font_size) / 2) + renderOptions.font_size) - (float)(renderOptions.image_scale * 2);
+ if (renderOptions.outline)
+ {
+ SKPath outlinePath = userPaint.GetTextPath(userName + ":", xPos, yPos);
+ SKPaint outlinePaint = new SKPaint() { Style = SKPaintStyle.Stroke, StrokeWidth = (float)(4 * renderOptions.image_scale), StrokeJoin = SKStrokeJoin.Round, Color = SKColors.Black, IsAntialias = true, LcdRenderText = true, SubpixelText = true, HintingLevel = SKPaintHinting.Full, FilterQuality = SKFilterQuality.High };
+ sectionImageCanvas.DrawPath(outlinePath, outlinePaint);
+ }
+ userPaint.Color = userColor;
+ sectionImageCanvas.DrawText(userName + ":", xPos, yPos, userPaint);
+ drawPos.X += (int)Math.Floor(textWidth) + (int)Math.Floor(6 * renderOptions.image_scale);
+ }
+ return sectionImage;
+ }
+
+ public SKPaint GetFallbackFont(char input, RenderOptions renderOptions)
+ {
+ if (fallbackCache.ContainsKey(input))
+ return fallbackCache[input];
+
+ SKPaint newPaint = new SKPaint() { Typeface = fontManager.MatchCharacter(input), LcdRenderText = true, TextSize = (float)renderOptions.font_size, IsAntialias = true, SubpixelText = true, HintingLevel = SKPaintHinting.Full, FilterQuality = SKFilterQuality.High };
+ fallbackCache.TryAdd(input, newPaint);
+ return newPaint;
+ }
+
+ private bool isNotAscii(char input)
+ {
+ return input > 127;
+ }
+
+ private SKBitmap DrawBadges(SKBitmap sectionImage, List imageList, RenderOptions renderOptions, List chatBadges, Comment comment, Size canvasSize, ref Point drawPos)
+ {
+ if (comment.message.user_badges != null)
+ {
+ foreach (var badge in comment.message.user_badges)
+ {
+ string id = badge._id.ToString();
+ string version = badge.version.ToString();
+
+ SKBitmap badgeImage = null;
+ foreach (var cachedBadge in chatBadges)
+ {
+ if (cachedBadge.name == id)
+ {
+ foreach (var cachedVersion in cachedBadge.versions)
+ {
+ if (cachedVersion.Key == version)
+ {
+ badgeImage = cachedVersion.Value;
+ }
+ }
+ }
+ }
+
+ if (badgeImage != null)
+ {
+ using (SKCanvas sectionImageCanvas = new SKCanvas(sectionImage))
+ {
+ float imageRatio = (float)(renderOptions.image_scale * 0.5);
+ float imageSize = badgeImage.Width * imageRatio;
+ float left = (float)drawPos.X;
+ float right = imageSize + left;
+ float top = (float)((sectionImage.Height - imageSize) / 2);
+ float bottom = imageSize + top;
+ SKRect drawBox = new SKRect(left, top, right, bottom);
+ sectionImageCanvas.DrawBitmap(badgeImage, drawBox, imagePaint);
+ drawPos.X += (int)Math.Floor(20 * renderOptions.image_scale);
+ }
+ }
+ }
+ }
+
+ return sectionImage;
+ }
+
+ private void BackgroundRenderManager_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+ {
+ statusProgressBar.Value = 0;
+ btnRender.IsEnabled = true;
+ if (e.Error == null)
+ {
+ statusMessage.Text = "Done";
+ SetImage("Images/ppHop.gif", true);
+ }
+ else
+ {
+ statusMessage.Text = "ERROR";
+ SetImage("Images/peepoSad.png", false);
+ AppendLog("ERROR: " + e.Error.Message);
+ AppendLog(e.Error.InnerException.ToString());
+ }
+ }
+
+ private void BackgroundRenderManager_ProgressChanged(object sender, ProgressChangedEventArgs e)
+ {
+ Progress update = (Progress)e.UserState;
+ statusProgressBar.Value = e.ProgressPercentage >= 100 ? 100 : e.ProgressPercentage;
+
+ if (e.ProgressPercentage > 0 && !update.justMessage)
+ {
+ int timeLeftInt = (int)Math.Floor(100.0 / update.percent_double * update.time_passed) - update.time_passed;
+ TimeSpan timeLeft = new TimeSpan(0, 0, timeLeftInt);
+ statusMessage.Text = String.Format("{0} ({1} left)", update.message, timeLeft.ToString(@"h\hm\ms\s"));
+ }
+ else
+ statusMessage.Text = update.message;
+ }
+
+ private void GetChatBadges(List chatBadges, Streamer streamerInfo, RenderOptions renderOptions)
+ {
+ using (WebClient client = new WebClient())
+ {
+ //Global chat badges
+ JObject globalBadges = JObject.Parse(client.DownloadString("https://badges.twitch.tv/v1/badges/global/display"));
+ //Subscriber badges
+ JObject subBadges = JObject.Parse(client.DownloadString(String.Format("https://badges.twitch.tv/v1/badges/channels/{0}/display", streamerInfo.id.ToString())));
+
+ foreach (var badge in globalBadges["badge_sets"].Union(subBadges["badge_sets"]))
+ {
+ JProperty jBadgeProperty = badge.ToObject();
+ string name = jBadgeProperty.Name;
+ Dictionary versions = new Dictionary();
+
+ foreach (var version in badge.First["versions"])
+ {
+ JProperty jVersionProperty = version.ToObject();
+ string versionString = jVersionProperty.Name;
+ string downloadUrl = version.First["image_url_2x"].ToString();
+ byte[] bytes = client.DownloadData(downloadUrl);
+ MemoryStream ms = new MemoryStream(bytes);
+ try
+ {
+ //For some reason, twitch has corrupted images sometimes :) for example
+ //https://static-cdn.jtvnw.net/badges/v1/a9811799-dce3-475f-8feb-3745ad12b7ea/1
+ SKBitmap badgeImage = SKBitmap.Decode(ms);
+ versions.Add(versionString, badgeImage);
+ }
+ catch (ArgumentException)
+ { }
+ }
+
+ chatBadges.Add(new ChatBadge(name, versions));
+ }
+ }
+ }
+
+ private void GetThirdPartyEmotes(List thirdPartyEmotes, Streamer streamerInfo, RenderOptions renderOptions)
+ {
+ using (WebClient client = new WebClient())
+ {
+ if (renderOptions.bttv_emotes)
+ {
+ //Global BTTV emotes
+ JObject BBTV = JObject.Parse(client.DownloadString("https://api.betterttv.net/2/emotes"));
+ foreach (var emote in BBTV["emotes"])
+ {
+ string id = emote["id"].ToString();
+ byte[] bytes = client.DownloadData(String.Format("https://cdn.betterttv.net/emote/{0}/2x", id));
+ MemoryStream ms = new MemoryStream(bytes);
+ MemoryStream ms2 = new MemoryStream(bytes);
+ SKBitmap temp_emote = SKBitmap.Decode(ms2);
+ System.Drawing.Image temp_emote_drawing = System.Drawing.Image.FromStream(ms);
+ thirdPartyEmotes.Add(new ThirdPartyEmote(temp_emote, temp_emote_drawing, emote["code"].ToString(), emote["imageType"].ToString(), id, 2));
+ }
+
+ //Channel specific BTTV emotes
+ try
+ {
+ JObject BBTV_channel = JObject.Parse(client.DownloadString("https://api.betterttv.net/2/channels/" + streamerInfo.name));
+ foreach (var emote in BBTV_channel["emotes"])
+ {
+ string id = emote["id"].ToString();
+ byte[] bytes = client.DownloadData(String.Format("https://cdn.betterttv.net/emote/{0}/2x", id));
+ MemoryStream ms = new MemoryStream(bytes);
+ MemoryStream ms2 = new MemoryStream(bytes);
+ SKBitmap temp_emote = SKBitmap.Decode(ms2);
+ System.Drawing.Image temp_emote_drawing = System.Drawing.Image.FromStream(ms);
+ thirdPartyEmotes.Add(new ThirdPartyEmote(temp_emote, temp_emote_drawing, emote["code"].ToString(), emote["imageType"].ToString(), id, 2));
+ }
+ }
+ catch { }
+ }
+
+ if (renderOptions.ffz_emotes)
+ {
+ //Global FFZ emotes
+ JObject FFZ = JObject.Parse(client.DownloadString("https://api.betterttv.net/2/frankerfacez_emotes/global"));
+ foreach (var emote in FFZ["emotes"])
+ {
+ string id = emote["id"].ToString();
+ byte[] bytes = client.DownloadData(String.Format("https://cdn.betterttv.net/frankerfacez_emote/{0}/1", id));
+ MemoryStream ms = new MemoryStream(bytes);
+ MemoryStream ms2 = new MemoryStream(bytes);
+ SKBitmap temp_emote = SKBitmap.Decode(ms2);
+ System.Drawing.Image temp_emote_drawing = System.Drawing.Image.FromStream(ms);
+ thirdPartyEmotes.Add(new ThirdPartyEmote(temp_emote, temp_emote_drawing, emote["code"].ToString(), emote["imageType"].ToString(), id, 1));
+ }
+
+ //Channel specific FFZ emotes
+ try
+ {
+ JObject FFZ_channel = JObject.Parse(client.DownloadString("https://api.betterttv.net/2/frankerfacez_emotes/channels/" + streamerInfo.id));
+ foreach (var emote in FFZ_channel["emotes"])
+ {
+ string id = emote["id"].ToString();
+ byte[] bytes;
+ int scale = 2;
+ try
+ {
+ bytes = client.DownloadData(String.Format("https://cdn.betterttv.net/frankerfacez_emote/{0}/2", id));
+ }
+ catch
+ {
+ bytes = client.DownloadData(String.Format("https://cdn.betterttv.net/frankerfacez_emote/{0}/1", id));
+ scale = 1;
+ }
+ MemoryStream ms = new MemoryStream(bytes);
+ MemoryStream ms2 = new MemoryStream(bytes);
+ SKBitmap temp_emote = SKBitmap.Decode(ms2);
+ System.Drawing.Image temp_emote_drawing = System.Drawing.Image.FromStream(ms);
+ thirdPartyEmotes.Add(new ThirdPartyEmote(temp_emote, temp_emote_drawing, emote["code"].ToString(), emote["imageType"].ToString(), id, scale));
+ }
+ }
+ catch { }
+ }
+ }
+ }
+
+ private void GetTwitterEmojis(Dictionary emojiCache, List comments, RenderOptions renderOptions, string emojiRegex)
+ {
+ using (WebClient client = new WebClient())
+ {
+ foreach (var comment in comments)
+ {
+ foreach (var fragment in comment.message.fragments)
+ {
+ if (fragment.emoticon == null)
+ {
+ string[] fragmentParts = fragment.text.Split(' ');
+ for (int i = 0; i < fragmentParts.Length; i++)
+ {
+ string output = fragmentParts[i].Trim();
+
+ if (output == "")
+ continue;
+
+ Match m = Regex.Match(output, emojiRegex);
+ if (m.Success)
+ {
+ for (var k = 0; k < m.Value.Length; k += char.IsSurrogatePair(m.Value, k) ? 2 : 1)
+ {
+ string codepoint = String.Format("{0:X4}", char.ConvertToUtf32(m.Value, k)).ToLower();
+ codepoint = codepoint.Replace("fe0f", "");
+ Console.WriteLine("U+{0:X4}", codepoint);
+ if (codepoint != "" && !emojiCache.ContainsKey(codepoint))
+ {
+ try
+ {
+ byte[] bytes = client.DownloadData(String.Format("https://abs.twimg.com/emoji/v2/72x72/{0}.png", codepoint));
+ MemoryStream ms = new MemoryStream(bytes);
+ SKBitmap emojiImage = SKBitmap.Decode(ms);
+ emojiCache.Add(codepoint, emojiImage);
+ }
+ catch { }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void GetEmotes(Dictionary chatEmotes, List comments, RenderOptions renderOptions)
+ {
+ List alreadyAdded = new List();
+ List failedEmotes = new List();
+ using (WebClient client = new WebClient())
+ {
+ foreach (var comment in comments)
+ {
+ foreach (var fragment in comment.message.fragments)
+ {
+ if (fragment.emoticon != null)
+ {
+ int id = Int32.Parse(fragment.emoticon.emoticon_id);
+ if (!alreadyAdded.Contains(id) && !failedEmotes.Contains(id))
+ {
+ try
+ {
+ byte[] bytes = client.DownloadData(String.Format("https://static-cdn.jtvnw.net/emoticons/v1/{0}/1.0", id));
+ alreadyAdded.Add(id);
+ MemoryStream ms = new MemoryStream(bytes);
+ SKBitmap emoteImage = SKBitmap.Decode(ms);
+ chatEmotes.Add(id, emoteImage);
+ }
+ catch
+ {
+ string emoteName = fragment.text;
+ //sometimes emote still exists but id is different, I use twitch metrics because I can't find an api to find an emote by name
+ try
+ {
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://www.twitchmetrics.net/e/" + emoteName);
+ request.AllowAutoRedirect = false;
+ HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+ string redirUrl = response.Headers["Location"];
+ response.Close();
+ string newId = redirUrl.Split('/').Last().Split('-').First();
+ byte[] bytes = client.DownloadData(String.Format("https://static-cdn.jtvnw.net/emoticons/v1/{0}/1.0", newId));
+ alreadyAdded.Add(id);
+ MemoryStream ms = new MemoryStream(bytes);
+ SKBitmap emoteImage = SKBitmap.Decode(ms);
+ chatEmotes.Add(id, emoteImage);
+ }
+ catch
+ {
+ AppendLog("Unable to fetch emote " + emoteName);
+ failedEmotes.Add(id);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ private void LoadSettings()
+ {
+ try
+ {
+ comboFont.SelectedItem = Settings.Default.Font;
+ checkOutline.IsChecked = Settings.Default.Outline;
+ checkTimestamp.IsChecked = Settings.Default.Timestamp;
+ checkCompact.IsChecked = Settings.Default.CompactMessages;
+ colorBackground.SelectedColor = System.Windows.Media.Color.FromRgb((byte)Settings.Default.BackgroundColorR, (byte)Settings.Default.BackgroundColorG, (byte)Settings.Default.BackgroundColorB);
+ checkFFZ.IsChecked = Settings.Default.FFZEmotes;
+ checkBTTV.IsChecked = Settings.Default.BTTVEmotes;
+ textHeight.Text = Settings.Default.Height.ToString();
+ textWidth.Text = Settings.Default.Width.ToString();
+ textFontSize.Text = Settings.Default.FontSize.ToString();
+ textUpdateTime.Text = Settings.Default.UpdateTime.ToString();
+ }
+ catch { }
+ }
+ private void SaveSettings()
+ {
+ Settings.Default.Font = comboFont.SelectedItem.ToString();
+ Settings.Default.Outline = (bool)checkOutline.IsChecked;
+ Settings.Default.Timestamp = (bool)checkTimestamp.IsChecked;
+ Settings.Default.CompactMessages = (bool)checkCompact.IsChecked;
+ Settings.Default.BackgroundColorR = colorBackground.SelectedColor.Value.R;
+ Settings.Default.BackgroundColorG = colorBackground.SelectedColor.Value.G;
+ Settings.Default.BackgroundColorB = colorBackground.SelectedColor.Value.B;
+ Settings.Default.FFZEmotes = (bool)checkFFZ.IsChecked;
+ Settings.Default.BTTVEmotes = (bool)checkBTTV.IsChecked;
+ try
+ {
+ Settings.Default.Height = Int32.Parse(textHeight.Text);
+ Settings.Default.Width = Int32.Parse(textWidth.Text);
+ Settings.Default.FontSize = float.Parse(textFontSize.Text);
+ Settings.Default.UpdateTime = float.Parse(textUpdateTime.Text);
+ }
+ catch { }
+ Settings.Default.Save();
+ }
+
+ private bool ValidateInputs()
+ {
+ if (!File.Exists(textJson.Text))
+ {
+ AppendLog("ERROR: JSON File Not Found");
+ return false;
+ }
+
+ try
+ {
+ Double.Parse(textFontSize.Text);
+ Int32.Parse(textHeight.Text);
+ Int32.Parse(textWidth.Text);
+ Double.Parse(textUpdateTime.Text);
+ }
+ catch (Exception ex)
+ {
+ AppendLog("ERROR: " + ex.Message);
+ return false;
+ }
+
+ return true;
+ }
+
+ private void AppendLog(string message)
+ {
+ textLog.Dispatcher.BeginInvoke((Action)(() =>
+ textLog.AppendText(message + Environment.NewLine)
+ ));
+ }
+
+ public void SetImage(string imageUri, bool isGif)
+ {
+ var image = new BitmapImage();
+ image.BeginInit();
+ image.UriSource = new Uri(imageUri, UriKind.Relative);
+ image.EndInit();
+ if (isGif)
+ ImageBehavior.SetAnimatedSource(statusImage, image);
+ else
+ {
+ ImageBehavior.SetAnimatedSource(statusImage, null);
+ statusImage.Source = image;
+ }
+ }
+
+ private void Page_Initialized(object sender, EventArgs e)
+ {
+ List fonts = new List();
+ foreach (var fontFamily in fontManager.FontFamilies)
+ fonts.Add(fontFamily);
+ fonts.Sort();
+ foreach (var font in fonts)
+ {
+ comboFont.Items.Add(font);
+ }
+ if (comboFont.Items.Contains("Arial"))
+ comboFont.SelectedItem = "Arial";
+
+ LoadSettings();
+ }
+
+ private void Page_Unloaded(object sender, RoutedEventArgs e)
+ {
+ SaveSettings();
+ }
+ }
+}
+
+public class Progress
+{
+ public string message = "";
+ public int time_passed = 0;
+ public double percent_double = 0.0;
+ public bool justMessage = false;
+ public Progress(string Message, int Time_passed, double Percent_double)
+ {
+ message = Message;
+ time_passed = Time_passed;
+ percent_double = Percent_double;
+ }
+
+ public Progress(string Message)
+ {
+ message = Message;
+ justMessage = true;
+ }
+}
+
+public class ThirdPartyEmote
+{
+ public SKBitmap emote;
+ public System.Drawing.Image emote_drawing;
+ public string imageType;
+ public string name;
+ public string id;
+ public int width;
+ public int height;
+ public int imageScale;
+
+ public ThirdPartyEmote(SKBitmap Emote, System.Drawing.Image Emote_drawing, string Name, string ImageType, string Id, int ImageScale)
+ {
+ emote = Emote;
+ emote_drawing = Emote_drawing;
+ name = Name;
+ imageType = ImageType;
+ id = Id;
+ width = emote.Width;
+ height = emote.Height;
+ imageScale = ImageScale;
+ }
+}
+
+public class RenderOptions
+{
+ public string json_path { get; set; }
+ public string save_path { get; set; }
+ public SKColor background_color { get; set; }
+ public int chat_height { get; set; }
+ public int chat_width { get; set; }
+ public bool bttv_emotes { get; set; }
+ public bool ffz_emotes { get; set; }
+ public bool outline { get; set; }
+ public string font { get; set; }
+ public double font_size { get; set; }
+ public double image_scale { get; set; }
+ public int update_frame { get; set; }
+ public int has_emote_height { get; set; }
+ public int has_no_emote_eight { get; set; }
+ public bool compact_messages { get; set; }
+ public System.Drawing.Color background_color_drawing { get; set; }
+ public int outline_size { get; set; }
+ public bool chat_timestamp { get; set; }
+ public int default_x { get; set; }
+
+ public RenderOptions(string Json_path, string Save_path, SKColor Background_color, int Chat_height, int Chat_width, bool Bttv_emotes, bool Ffz_emotes, bool Outline, string Font, double Font_size, double Update_rate, bool Compact_messages, System.Drawing.Color Background_color_drawing, bool Chat_timestamp)
+ {
+ json_path = Json_path;
+ save_path = Save_path;
+ background_color = Background_color;
+ chat_height = Chat_height;
+ chat_width = Chat_width;
+ bttv_emotes = Bttv_emotes;
+ ffz_emotes = Ffz_emotes;
+ outline = Outline;
+ font = Font;
+ font_size = Font_size;
+ image_scale = font_size / 12;
+
+ if (Update_rate == 0)
+ update_frame = 1;
+ else
+ update_frame = (int)Math.Floor(Update_rate / (1.0 / 60.0));
+
+ has_emote_height = (int)Math.Floor(36 * image_scale);
+ has_no_emote_eight = (int)Math.Floor(20 * image_scale);
+ compact_messages = Compact_messages;
+ background_color_drawing = Background_color_drawing;
+ outline_size = (int)Math.Round(3 * image_scale);
+ chat_timestamp = Chat_timestamp;
+ default_x = 2;
+ }
+}
+
+public class ChatBadge
+{
+ public string name;
+ public Dictionary versions;
+
+ public ChatBadge(string Name, Dictionary Versions)
+ {
+ name = Name;
+ versions = Versions;
+ }
+}
+
+public class GifEmote
+{
+ public Point offset;
+ public string name;
+ public System.Drawing.Image image;
+ public FrameDimension dim;
+ public int frames;
+ public List durations;
+ public int total_duration;
+ public int imageScale;
+
+ public GifEmote(Point Offset, string Name, System.Drawing.Image Image, int ImageScale)
+ {
+ offset = Offset;
+ name = Name;
+ image = Image;
+ dim = new FrameDimension(image.FrameDimensionsList[0]);
+ frames = image.GetFrameCount(dim);
+ var times = image.GetPropertyItem(0x5100).Value;
+
+ durations = new List();
+ for (int i = 0; i < frames; i++)
+ {
+ var duration = BitConverter.ToInt32(times, 4 * i);
+ durations.Add(duration);
+ total_duration += duration;
+ }
+
+ if (total_duration == 0)
+ {
+ for (int i = 0; i < durations.Count; i++)
+ {
+ durations.RemoveAt(i);
+ durations.Insert(i, 10);
+ }
+ total_duration = durations.Count * 10;
+ }
+
+ imageScale = ImageScale;
+ }
+}
+
+public class TwitchComment
+{
+ public string section;
+ public double secondsOffset;
+ public List gifEmotes;
+
+ public TwitchComment(string Section, double SecondsOffset, List GifEmotes)
+ {
+ section = Section;
+ secondsOffset = SecondsOffset;
+ gifEmotes = GifEmotes;
+ }
+}
\ No newline at end of file
diff --git a/TwitchDownloaderWPF/PageClipDownload.xaml b/TwitchDownloaderWPF/PageClipDownload.xaml
new file mode 100644
index 00000000..711f426d
--- /dev/null
+++ b/TwitchDownloaderWPF/PageClipDownload.xaml
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TwitchDownloaderWPF/PageClipDownload.xaml.cs b/TwitchDownloaderWPF/PageClipDownload.xaml.cs
new file mode 100644
index 00000000..2dbcafa5
--- /dev/null
+++ b/TwitchDownloaderWPF/PageClipDownload.xaml.cs
@@ -0,0 +1,187 @@
+using Microsoft.Win32;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using WpfAnimatedGif;
+
+namespace TwitchDownloaderWPF
+{
+ ///
+ /// Interaction logic for PageClipDownload.xaml
+ ///
+ public partial class PageClipDownload : Page
+ {
+ public PageClipDownload()
+ {
+ InitializeComponent();
+ }
+
+ private async void btnGetInfo_Click(object sender, RoutedEventArgs e)
+ {
+ string clipId = ValidateUrl(textUrl.Text);
+ if (clipId == "")
+ {
+ MessageBox.Show("Please enter a valid clip ID/URL" + Environment.NewLine + "Examples:" + Environment.NewLine + "https://clips.twitch.tv/ImportantPlausibleMetalOSsloth" + Environment.NewLine + "ImportantPlausibleMetalOSsloth", "Invalid Video ID/URL", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ else
+ {
+ try
+ {
+ btnGetInfo.IsEnabled = false;
+ comboQuality.Items.Clear();
+ Task taskInfo = InfoHelper.GetClipInfo(clipId);
+ Task taskLinks = InfoHelper.GetClipLinks(clipId);
+ await Task.WhenAll(taskInfo, taskLinks);
+
+ JToken clipData = taskInfo.Result["data"][0];
+ string thumbUrl = clipData["thumbnail_url"].ToString();
+ Task taskThumb = InfoHelper.GetThumb(thumbUrl);
+ await Task.WhenAll(taskThumb);
+
+ imgThumbnail.Source = taskThumb.Result;
+ textStreamer.Text = clipData["broadcaster_name"].ToString();
+ textCreatedAt.Text = clipData["created_at"].ToString();
+ textTitle.Text = clipData["title"].ToString();
+
+ foreach (var quality in taskLinks.Result["quality_options"])
+ {
+ comboQuality.Items.Add(new TwitchClip(quality["quality"].ToString(), quality["frame_rate"].ToString(), quality["source"].ToString()));
+ }
+
+ comboQuality.SelectedIndex = 0;
+ comboQuality.IsEnabled = true;
+ btnDownload.IsEnabled = true;
+ btnGetInfo.IsEnabled = true;
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show("Unable to get Clip information. Please double check Clip Slug and try again", "Unable to get info", MessageBoxButton.OK, MessageBoxImage.Error);
+ AppendLog("ERROR: " + ex.Message);
+ btnGetInfo.IsEnabled = true;
+ }
+ }
+ }
+
+ private string ValidateUrl(string text)
+ {
+ Regex clipRegex = new Regex(@"twitch.tv\/(\S+)\/clip\/");
+ if (text.All(Char.IsLetter))
+ {
+ return text;
+ }
+ else if (text.Contains("clips.twitch.tv/") || clipRegex.IsMatch(text))
+ {
+ Uri url = new Uri(text);
+ string path = String.Format("{0}{1}{2}{3}", url.Scheme, Uri.SchemeDelimiter, url.Authority, url.AbsolutePath);
+ return path.Split('/').Last();
+ }
+ return "";
+ }
+
+ private void AppendLog(string message)
+ {
+ textLog.Dispatcher.BeginInvoke((Action)(() =>
+ textLog.AppendText(message + Environment.NewLine)
+ ));
+ }
+
+ private void Page_Initialized(object sender, EventArgs e)
+ {
+ comboQuality.IsEnabled = false;
+ btnDownload.IsEnabled = false;
+ }
+
+ private async void btnDownload_Click(object sender, RoutedEventArgs e)
+ {
+ SaveFileDialog saveFileDialog = new SaveFileDialog();
+
+ saveFileDialog.Filter = "MP4 Files | *.mp4";
+ saveFileDialog.RestoreDirectory = true;
+
+ if (saveFileDialog.ShowDialog() == true)
+ {
+ comboQuality.IsEnabled = false;
+ btnGetInfo.IsEnabled = false;
+ btnDownload.IsEnabled = false;
+ SetImage("Images/ppOverheat.gif", true);
+ statusMessage.Text = "Downloading";
+ try
+ {
+ using (WebClient client = new WebClient())
+ {
+ client.DownloadProgressChanged += (sender2, e2) =>
+ {
+ statusMessage.Text = String.Format("Downloading {0}%", e2.ProgressPercentage);
+ statusProgressBar.Value = e2.ProgressPercentage;
+ };
+
+ await client.DownloadFileTaskAsync(new Uri(((TwitchClip)comboQuality.SelectedItem).url), saveFileDialog.FileName);
+ }
+ statusMessage.Text = "Done";
+ SetImage("Images/ppHop.gif", true);
+ }
+ catch (Exception ex)
+ {
+ statusMessage.Text = "ERROR";
+ SetImage("Images/peepoSad.png", false);
+ AppendLog("ERROR: " + ex.Message);
+ }
+ btnGetInfo.IsEnabled = true;
+ btnDownload.IsEnabled = true;
+ statusProgressBar.Value = 0;
+ }
+ }
+
+ public void SetImage(string imageUri, bool isGif)
+ {
+ var image = new BitmapImage();
+ image.BeginInit();
+ image.UriSource = new Uri(imageUri, UriKind.Relative);
+ image.EndInit();
+ if (isGif)
+ ImageBehavior.SetAnimatedSource(statusImage, image);
+ else
+ {
+ ImageBehavior.SetAnimatedSource(statusImage, null);
+ statusImage.Source = image;
+ }
+ }
+ }
+}
+
+public class TwitchClip
+{
+ public string quality { get; set; }
+ public string framerate { get; set; }
+ public string url { get; set; }
+
+ public TwitchClip(string Quality, string Framerate, string Url)
+ {
+ quality = Quality;
+ framerate = Framerate;
+ url = Url;
+ }
+
+ override
+ public string ToString()
+ {
+ //Only show framerate if it's not 30fps
+ return String.Format("{0}p{1}", quality, framerate == "30" ? "" : framerate);
+ }
+}
\ No newline at end of file
diff --git a/TwitchDownloaderWPF/PageVodDownload.xaml b/TwitchDownloaderWPF/PageVodDownload.xaml
new file mode 100644
index 00000000..3d6ade79
--- /dev/null
+++ b/TwitchDownloaderWPF/PageVodDownload.xaml
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TwitchDownloader/frmVodDownload.cs b/TwitchDownloaderWPF/PageVodDownload.xaml.cs
similarity index 50%
rename from TwitchDownloader/frmVodDownload.cs
rename to TwitchDownloaderWPF/PageVodDownload.xaml.cs
index 7cba08c5..39e4a1fd 100644
--- a/TwitchDownloader/frmVodDownload.cs
+++ b/TwitchDownloaderWPF/PageVodDownload.xaml.cs
@@ -1,202 +1,180 @@
-using Microsoft.WindowsAPICodePack.Dialogs;
+using Microsoft.Win32;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
-using System.Data;
-using System.Diagnostics;
using System.Drawing;
-using System.Globalization;
-using System.IO;
using System.Linq;
using System.Net;
+using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
-using System.Windows.Forms;
-using TwitchDownloader;
-using Xabe.FFmpeg;
-using Xabe.FFmpeg.Enums;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.IO;
+using TwitchDownloaderWPF;
using Xabe.FFmpeg.Model;
-using Xabe.FFmpeg.Streams;
+using Xabe.FFmpeg;
+using WpfAnimatedGif;
+using TwitchDownloader.Properties;
-namespace TwitchDownloader
+namespace TwitchDownloaderWPF
{
- public partial class frmVodDownload : Form
+ ///
+ /// Interaction logic for PageVodDownload.xaml
+ ///
+ public partial class PageVodDownload : Page
{
- List> videoQualties = new List>();
+ public Dictionary videoQualties = new Dictionary();
+ public int currentVideoId;
- public frmVodDownload()
+ public PageVodDownload()
{
InitializeComponent();
}
- private async void BtnGetInfo_Click(object sender, EventArgs e)
+ private void SetEnabled(bool isEnabled)
{
- if (!textUrl.Text.All(char.IsDigit) || textUrl.Text.Length == 0)
- {
- MessageBox.Show("Please enter a valid VOD ID", "Invalid VOD ID", MessageBoxButtons.OK, MessageBoxIcon.Error);
- return;
- }
+ comboQuality.IsEnabled = isEnabled;
+ checkStart.IsEnabled = isEnabled;
+ checkEnd.IsEnabled = isEnabled;
+ numStartHour.IsEnabled = isEnabled;
+ numStartMinute.IsEnabled = isEnabled;
+ numStartSecond.IsEnabled = isEnabled;
+ numEndHour.IsEnabled = isEnabled;
+ numEndMinute.IsEnabled = isEnabled;
+ numEndSecond.IsEnabled = isEnabled;
+ btnDownload.IsEnabled = isEnabled;
+ numDownloadThreads.IsEnabled = isEnabled;
+ }
- try
+ private async void btnGetInfo_Click(object sender, RoutedEventArgs e)
+ {
+ int videoId = ValidateUrl(textUrl.Text);
+ if (videoId > 0)
{
- btnGetInfo.Enabled = false;
-
- string vodId = textUrl.Text;
- Task taskInfo = GetInfo(vodId);
- Task taskAccessToken = GetToken(vodId);
- await Task.WhenAll(taskInfo, taskAccessToken);
- string thumbUrl = taskInfo.Result["data"][0]["thumbnail_url"].ToString().Replace("%{width}", pictureThumb.Width.ToString()).Replace("%{height}", pictureThumb.Height.ToString());
- Task taskThumb = GetThumb(thumbUrl);
- Task taskPlaylist = GetPlaylist(vodId, taskAccessToken.Result["token"].ToString(), taskAccessToken.Result["sig"].ToString());
- await Task.WhenAll(taskThumb, taskPlaylist);
-
- string[] playlist = taskPlaylist.Result;
- for (int i = 0; i < playlist.Length; i++)
+ currentVideoId = videoId;
+ try
{
- if (playlist[i].Contains("#EXT-X-MEDIA"))
+ Task taskInfo = InfoHelper.GetVideoInfo(videoId);
+ Task taskAccessToken = InfoHelper.GetVideoToken(videoId);
+ await Task.WhenAll(taskInfo, taskAccessToken);
+ string thumbUrl = taskInfo.Result["data"][0]["thumbnail_url"].ToString().Replace("%{width}", 512.ToString()).Replace("%{height}", 290.ToString());
+ Task thumbImage = InfoHelper.GetThumb(thumbUrl);
+ Task taskPlaylist = InfoHelper.GetVideoPlaylist(videoId, taskAccessToken.Result["token"].ToString(), taskAccessToken.Result["sig"].ToString());
+ await Task.WhenAll(thumbImage, taskPlaylist);
+
+ comboQuality.Items.Clear();
+ videoQualties.Clear();
+ string[] playlist = taskPlaylist.Result;
+ for (int i = 0; i < playlist.Length; i++)
{
- string lastPart = playlist[i].Substring(playlist[i].IndexOf("NAME=\"") + 6);
- string stringQuality = lastPart.Substring(0, lastPart.IndexOf("\""));
-
- videoQualties.Add(new KeyValuePair(stringQuality, playlist[i + 2]));
- comboQuality.Items.Add(stringQuality);
+ if (playlist[i].Contains("#EXT-X-MEDIA"))
+ {
+ string lastPart = playlist[i].Substring(playlist[i].IndexOf("NAME=\"") + 6);
+ string stringQuality = lastPart.Substring(0, lastPart.IndexOf("\""));
+
+ if (!videoQualties.ContainsKey(stringQuality))
+ {
+ videoQualties.Add(stringQuality, playlist[i + 2]);
+ comboQuality.Items.Add(stringQuality);
+ }
+ }
}
+ comboQuality.SelectedIndex = 0;
+
+ imgThumbnail.Source = thumbImage.Result;
+ TimeSpan vodLength = TimeSpan.Parse(Regex.Replace(taskInfo.Result["data"][0]["duration"].ToString(), @"[^\d]", ":").TrimEnd(':'));
+ textStreamer.Text = taskInfo.Result["data"][0]["user_name"].ToString();
+ textTitle.Text = taskInfo.Result["data"][0]["title"].ToString();
+ textCreatedAt.Text = taskInfo.Result["data"][0]["created_at"].ToString();
+ numEndHour.Value = vodLength.Hours;
+ numEndMinute.Value = vodLength.Minutes;
+ numEndSecond.Value = vodLength.Seconds;
+ labelLength.Text = String.Format("{0}:{1}:{2}", vodLength.Hours, vodLength.Minutes, vodLength.Seconds);
+
+ SetEnabled(true);
+ }
+ catch (Exception ex)
+ {
+ btnGetInfo.IsEnabled = true;
+ AppendLog("ERROR: " + ex.Message);
+ MessageBox.Show("Unable to get the video information." + Environment.NewLine + "Please make sure the video ID is correct and try again.", "Unable To Fetch Video Info", MessageBoxButton.OK, MessageBoxImage.Error);
}
-
- comboQuality.SelectedIndex = 0;
- pictureThumb.Image = taskThumb.Result;
- textFilename.Text = String.Format("{0}_{1}", vodId, taskInfo.Result["data"][0]["user_name"].ToString());
- textTitle.Text = taskInfo.Result["data"][0]["title"].ToString();
- labelStreamer.Text = taskInfo.Result["data"][0]["user_name"].ToString();
- labelCreated.Text = taskInfo.Result["data"][0]["created_at"].ToString();
- TimeSpan vodLength = TimeSpan.Parse(Regex.Replace(taskInfo.Result["data"][0]["duration"].ToString(), @"[^\d]", ":").TrimEnd(':'));
- numEndHour.Value = vodLength.Hours;
- numEndMinute.Value = vodLength.Minutes;
- numEndSecond.Value = vodLength.Seconds;
- labelLength.Text = String.Format("{0}:{1}:{2}", vodLength.Hours, vodLength.Minutes, vodLength.Seconds);
- textFolder.Text = Properties.Settings.Default.DOWNLOAD_FOLDER;
-
- btnGetInfo.Enabled = true;
- SetEnabled(true);
}
- catch (WebException)
+ else
{
- MessageBox.Show("Unable to get Twitch VOD information. Please double check VOD ID and try again", "Unable to get info", MessageBoxButtons.OK, MessageBoxIcon.Error);
- btnGetInfo.Enabled = true;
- SetEnabled(false);
+ MessageBox.Show("Please enter a valid video ID/URL" + Environment.NewLine + "Examples:" + Environment.NewLine + "https://www.twitch.tv/videos/470741744" + Environment.NewLine + "470741744", "Invalid Video ID/URL", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
- private async Task GetPlaylist(string vodId, string token, string sig)
+ private void btnDownload_Click(object sender, RoutedEventArgs e)
{
- using (WebClient client = new WebClient())
+ bool isValid = ValidateInput();
+
+ if (isValid)
{
- client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
+ SaveFileDialog saveFileDialog = new SaveFileDialog();
- string playlist = await client.DownloadStringTaskAsync(String.Format("http://usher.twitch.tv/vod/{0}?nauth={1}&nauthsig={2}&allow_source=true&player=twitchweb", vodId, token, sig));
- return playlist.Split('\n');
- }
- }
+ saveFileDialog.Filter = "MP4 Files | *.mp4";
+ saveFileDialog.RestoreDirectory = true;
- private async Task GetThumb(string url)
- {
- Bitmap result = new Bitmap(100, 100);
- using (WebClient client = new WebClient())
- {
- client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
- using (Stream s = await client.OpenReadTaskAsync(url))
+ if (saveFileDialog.ShowDialog() == true)
{
- result = new Bitmap(s);
+ SetEnabled(false);
+ btnGetInfo.IsEnabled = false;
+
+ DownloadOptions options = new DownloadOptions();
+ options.UpdateValues(this);
+ options.filename = saveFileDialog.FileName;
+
+ BackgroundWorker backgroundDownloadManager = new BackgroundWorker();
+ backgroundDownloadManager.WorkerReportsProgress = true;
+ backgroundDownloadManager.DoWork += BackgroundDownloadManager_DoWork;
+ backgroundDownloadManager.ProgressChanged += BackgroundDownloadManager_ProgressChanged;
+ backgroundDownloadManager.RunWorkerCompleted += BackgroundDownloadManager_RunWorkerCompleted;
+
+ SetImage("Images/ppOverheat.gif", true);
+ statusMessage.Text = "Downloading";
+ backgroundDownloadManager.RunWorkerAsync(options);
}
}
- return result;
- }
-
- private async Task GetToken(string vodId)
- {
- using (WebClient client = new WebClient())
+ else
{
- client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
- string response = await client.DownloadStringTaskAsync(String.Format("https://api.twitch.tv/api/vods/{0}/access_token", vodId));
- JObject result = JObject.Parse(response);
- return result;
+ AppendLog("ERROR: Invalid Crop Inputs");
}
}
- private async Task GetInfo(string id)
+ public void SetImage(string imageUri, bool isGif)
{
- using (WebClient client = new WebClient())
+ var image = new BitmapImage();
+ image.BeginInit();
+ image.UriSource = new Uri(imageUri, UriKind.Relative);
+ image.EndInit();
+ if (isGif)
+ ImageBehavior.SetAnimatedSource(statusImage, image);
+ else
{
- client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
- string response = await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/videos?id=" + id);
- JObject result = JObject.Parse(response);
- return result;
+ ImageBehavior.SetAnimatedSource(statusImage, null);
+ statusImage.Source = image;
}
}
- private void SetEnabled(bool isEnabled)
- {
- comboQuality.Enabled = isEnabled;
- textFolder.Enabled = isEnabled;
- btnFolder.Enabled = isEnabled;
- textFilename.Enabled = isEnabled;
- checkCropStart.Enabled = isEnabled;
- numStartHour.Enabled = isEnabled;
- numStartMinute.Enabled = isEnabled;
- numStartSecond.Enabled = isEnabled;
- checkCropEnd.Enabled = isEnabled;
- numEndHour.Enabled = isEnabled;
- numEndMinute.Enabled = isEnabled;
- numEndSecond.Enabled = isEnabled;
- btnDownload.Enabled = isEnabled;
- }
-
- private void BtnFolder_Click(object sender, EventArgs e)
- {
- CommonOpenFileDialog dialog = new CommonOpenFileDialog();
- dialog.IsFolderPicker = true;
- if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
- {
- textFolder.Text = dialog.FileName;
- Properties.Settings.Default.DOWNLOAD_FOLDER = dialog.FileName;
- }
- }
- private void BtnDownload_Click(object sender, EventArgs e)
- {
- SetEnabled(false);
- btnGetInfo.Enabled = false;
- btnDownload.Enabled = false;
- DownloadOptions options = new DownloadOptions();
- options.id = textUrl.Text;
- options.title = textTitle.Text;
- options.quality = (string)comboQuality.SelectedItem;
- options.folder = textFolder.Text;
- options.filename = textFilename.Text;
- options.streamer = labelStreamer.Text;
- options.created = labelCreated.Text;
- options.length = TimeSpan.Parse(labelLength.Text);
- options.cropped_begin = checkCropStart.Checked;
- options.cropped_end = checkCropEnd.Checked;
- options.cropped_begin_time = new TimeSpan((int)numStartHour.Value, (int)numStartMinute.Value, (int)numStartSecond.Value);
- options.cropped_end_time = new TimeSpan((int)numEndHour.Value, (int)numEndMinute.Value, (int)numEndSecond.Value);
- options.crop_end = 0.0;
- options.crop_begin = 0.0;
- toolStatus.Text = "Downloading";
- backgroundDownloadManager.RunWorkerAsync(options);
-
- Properties.Settings.Default.Save();
- }
-
private void BackgroundDownloadManager_DoWork(object sender, DoWorkEventArgs e)
{
DownloadOptions options = (DownloadOptions)e.Argument;
List threads = new List();
- int downloadThreads = 10;
+ int downloadThreads = options.download_threads;
string tempFolder = Path.Combine(Path.GetTempPath(), "TwitchDownloader");
- string downloadFolder = Path.Combine(tempFolder, options.id);
+ string downloadFolder = Path.Combine(tempFolder, options.id.ToString());
if (Directory.Exists(downloadFolder))
DeleteDirectory(downloadFolder);
@@ -243,9 +221,9 @@ private void BackgroundDownloadManager_DoWork(object sender, DoWorkEventArgs e)
doneCount++;
int percent = (int)Math.Floor(((double)doneCount / (double)partCount) * 100);
- backgroundDownloadManager.ReportProgress(percent, String.Format("Downloading {0}% (1/3)", percent));
+ (sender as BackgroundWorker).ReportProgress(percent, String.Format("Downloading {0}% (1/3)", percent));
}
-
+
for (int i = threads.Count - 1; i < downloadThreads - 1; i++)
{
if (videoParts.Count > 0)
@@ -261,7 +239,7 @@ private void BackgroundDownloadManager_DoWork(object sender, DoWorkEventArgs e)
}
}
- backgroundDownloadManager.ReportProgress(0, "Combining Parts (2/3)");
+ (sender as BackgroundWorker).ReportProgress(0, "Combining Parts (2/3)");
if (videoPartsList[0].Contains("muted"))
{
@@ -298,7 +276,8 @@ private void BackgroundDownloadManager_DoWork(object sender, DoWorkEventArgs e)
}
}
- string outputConvert = Path.Combine(options.folder, options.filename + ".mp4");
+ (sender as BackgroundWorker).ReportProgress(0, "Finalizing MP4 (3/3)");
+ string outputConvert = options.filename;
Task info = MediaInfo.Get(Path.Combine(downloadFolder, "output.ts"));
Task.WaitAll(info);
double seekTime = options.crop_begin;
@@ -309,25 +288,6 @@ private void BackgroundDownloadManager_DoWork(object sender, DoWorkEventArgs e)
DeleteDirectory(downloadFolder);
}
- public static void DeleteDirectory(string target_dir)
- {
- string[] files = Directory.GetFiles(target_dir);
- string[] dirs = Directory.GetDirectories(target_dir);
-
- foreach (string file in files)
- {
- File.SetAttributes(file, FileAttributes.Normal);
- File.Delete(file);
- }
-
- foreach (string dir in dirs)
- {
- DeleteDirectory(dir);
- }
-
- Directory.Delete(target_dir, false);
- }
-
private List GenerateCroppedVideoList(List> videoList, DownloadOptions options)
{
double beginTime = 0.0;
@@ -386,7 +346,7 @@ private static void DownloadThread(string videoPart, string baseUrl, string down
{
bool isDone = false;
int errorCount = 0;
- while (!isDone && errorCount < 4)
+ while (!isDone && errorCount < 10)
{
try
{
@@ -399,29 +359,133 @@ private static void DownloadThread(string videoPart, string baseUrl, string down
catch (WebException)
{
errorCount++;
- Thread.Sleep(3000);
+ Thread.Sleep(10000);
}
}
if (!isDone)
- throw new Exception("RIP");
+ throw new Exception("Video part " + videoPart + " failed after 10 retries");
}
private void BackgroundDownloadManager_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
- btnGetInfo.Enabled = true;
- toolStatus.Text = "Done Downloading";
+ btnGetInfo.IsEnabled = true;
+ statusProgressBar.Value = 0;
+ if (e.Error == null)
+ {
+ statusMessage.Text = "Done";
+ SetImage("Images/ppHop.gif", true);
+
+ }
+ else
+ {
+ statusMessage.Text = "ERROR";
+ SetImage("Images/peepoSad.png", false);
+ AppendLog("ERROR: " + e.Error.Message);
+ }
}
private void BackgroundDownloadManager_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
string message = (string)e.UserState;
- toolStatus.Text = message;
- toolProgressBar.Value = e.ProgressPercentage;
+ statusMessage.Text = message;
+ statusProgressBar.Value = e.ProgressPercentage;
+ }
+
+ public static void DeleteDirectory(string target_dir)
+ {
+ string[] files = Directory.GetFiles(target_dir);
+ string[] dirs = Directory.GetDirectories(target_dir);
+
+ foreach (string file in files)
+ {
+ File.SetAttributes(file, FileAttributes.Normal);
+ File.Delete(file);
+ }
+
+ foreach (string dir in dirs)
+ {
+ DeleteDirectory(dir);
+ }
+
+ Directory.Delete(target_dir, false);
+ }
+
+ private int ValidateUrl(string text)
+ {
+ if (text.All(Char.IsDigit))
+ {
+ int number;
+ bool success = Int32.TryParse(text, out number);
+ if (success)
+ return number;
+ else
+ return -1;
+ }
+ else if (text.Contains("twitch.tv/videos/"))
+ {
+ int number;
+ //Extract just the numbers from the URL, also remove query string
+ Uri url = new Uri(text);
+ string path = String.Format("{0}{1}{2}{3}", url.Scheme, Uri.SchemeDelimiter, url.Authority, url.AbsolutePath);
+ bool success = Int32.TryParse(Regex.Match(path, @"\d+").Value, out number);
+ if (success)
+ return number;
+ else
+ return -1;
+ }
+ else
+ return -1;
+ }
+
+ private bool ValidateInput()
+ {
+ TimeSpan videoLength = TimeSpan.Parse(labelLength.Text);
+ TimeSpan beginTime = new TimeSpan((int)numStartHour.Value, (int)numStartMinute.Value, (int)numStartSecond.Value);
+ TimeSpan endTime = new TimeSpan((int)numEndHour.Value, (int)numEndMinute.Value, (int)numEndSecond.Value);
+
+ if ((int)numDownloadThreads.Value < 1)
+ numDownloadThreads.Value = 1;
+
+ if ((bool)checkStart.IsChecked)
+ {
+ if (beginTime.TotalSeconds >= videoLength.TotalSeconds || beginTime.TotalSeconds < 0)
+ return false;
+
+ if ((bool)checkEnd.IsChecked)
+ {
+ if (endTime.TotalSeconds - beginTime.TotalSeconds < 0)
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void AppendLog(string message)
+ {
+ textLog.Dispatcher.BeginInvoke((Action)(() =>
+ textLog.AppendText(message + Environment.NewLine)
+ ));
+ }
+
+ private void Page_Initialized(object sender, EventArgs e)
+ {
+ SetEnabled(false);
+
+ numDownloadThreads.Value = Settings.Default.VodDownloadThreads;
+ }
+
+ private void numDownloadThreads_ValueChanged(object sender, RoutedPropertyChangedEventArgs