You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
livestream-scheduler/Freedomain Livestream Sched...

643 lines
19 KiB
Plaintext

; ENVIRONMENT
;------------------------------------------------
#Requires AutoHotkey v1.0
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
;#Warn ; Enable warnings to assist with detecting common errors.
;DetectHiddenWindows, On
#SingleInstance, Force
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
;SetKeyDelay, 500
CoordMode, ToolTip, Screen
CoordMode, Mouse, Screen
;#NoTrayIcon
; Customize the Toolbar Icon Menu
; ------------------------------------------------
Menu, tray, NoStandard
Menu, Tray, Add, Exit, KillScript
Menu, Tray, Add, Pause, PauseScript
; Menu, Tray, Add, Show Results, DisplayResults
Menu, Tray, Add, Schedule New Livestream, ReloadScript
Menu, Tray, Add, Restart with Last Item, RetryUpload
Menu, Tray, Default, Restart with Last Item
; Notes/Extra Info/#Includes
;------------------------------------------------
PassedInArgument = %1%
; Check if Update was just installed and delete the old .exe if so
CheckIfUpdateInstalled(PassedInArgument)
; Included Files and Libraries
; ------------------------------------------------
; These have to be included at the top for the Global variables to get registered early
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\Locals-Functions.ahk
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\General-Functions.ahk
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\Selenium-Functions.ahk
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\Chrome-Functions.ahk
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\Gitea-Functions.ahk
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\API-Functions.ahk
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\JSON.ahk
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\RunCMD.ahk
#include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\StdOutToVar.ahk
#include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\Zip.ahk
#include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\URLDownloadToVar.ahk
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\Miscellaneous-Functions.ahk
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\LBRY-Functions.ahk
; VARIABLES
;------------------------------------------------
;---Global Variables---
;------------------------------------------------
global ScriptNameav
global ScriptVersion
global FullScriptName
global PostStatusesFilepath
global ErrorLoggingDirectory
global DiscordErrorLoggingWebhookBotURL
global DiscordVideosWebhookURL
global VideoFolderDir
global LogErrorsToMsgbox
global ErrorLogToDiscord
; global LogErrorsToTextFile
global CurrentSite
global Driver
global DriverStatus
global ChromeProfile
global ShowTooltipProgressCheckStatus
global ShowTooltipProgress
ShowTooltipProgress := 1
global ErrorLogSummary
global DiscordParlerWebhookURL
global ErrorLoggingFilePath
; global TotalTabLoops
global ErrorLogVar
ErrorLogVar :=
global DevMode
; Check if Lib folder exists and create it if not
LibFolder := A_ScriptDir . "\Lib"
ErrorLoggingFolder := A_ScriptDir . "\Lib\ErrorLogging"
FileCreateDir, %ErrorLoggingFolder%
; Set filepaths for different files and folders
global SettingsIniFilepath
SettingsIniFilepath := A_ScriptDir . "\Settings.ini"
global ScriptSettingsSection
ScriptSettingsSection := "Livestream-Scheduler"
FileInstall, Version.ini, %A_ScriptDir%\Lib\Version.ini, 1
IniRead, ScriptVersion, %A_ScriptDir%\Lib\Version.ini,%ScriptSettingsSection%, Version, 0.0
; IniRead, ScriptName, %A_ScriptDir%\Lib\Version.ini,%ScriptSettingsSection%, Name, %ScriptSettingsSection%
global ScriptName := "Freedomain Livestream Scheduler"
global ScriptAbbreviatedName := "FLS" ; used for error logging
FullScriptName := ScriptName . " - " . ScriptVersion
; Msgbox % "FullScriptName: " FullScriptName
global GitReleasesAPIURL
GitReleasesAPIURL = https://freedomain.dev/api/v1/repos/yuriy/livestream-scheduler/releases
; Read Info From Files
; ------------------------------------------------
; For Templates and re-trying a failed previous run
if(StrLen(PassedInArgument) > 5 and !InStr(PassedInArgument, ".exe")){
/*FileAppend, %LivestreamTitle%, %PostTitleFilePath% ; save post content to txt file
FileAppend, %LivestreamDescription%, %PostBodyFilePath% ; save post content to txt file
FileAppend, %LivestreamTags%, %PostTagsFilePath% ; save post content to txt file
if(LivestreamThumbnail){ ; copy thumbnail into folder
SplitPath, LivestreamThumbnail, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
FileCopy, %LivestreamThumbnail%, %ErrorLoggingDirectory%\Thumbnail.%OutExtension%
}
*/
TemplateDirectory := PassedInArgument
FileRead, LivestreamTitle, %TemplateDirectory%\PostTitle.txt
FileRead, LivestreamDescription, %TemplateDirectory%\PostBody.txt
FileRead, LivestreamTags, %TemplateDirectory%\PostTags.txt
ThumbnailPNGFilepath = %TemplateDirectory%\Thumbnail.png
ThumbnailJPGFilepath = %TemplateDirectory%\Thumbnail.jpg
ThumbnailJPEGFilepath = %TemplateDirectory%\Thumbnail.jpg
if(FileExist(ThumbnailPNGFilepath))
LivestreamThumbnail := ThumbnailPNGFilepath
if(FileExist(ThumbnailJPGFilepath))
LivestreamThumbnail := ThumbnailJPGFilepath
if(FileExist(ThumbnailJPEGFilepath))
LivestreamThumbnail := ThumbnailJPEGFilepath
}
; Read settings.ini
; ------------------------------------------------
IniRead, ConfirmBeforeSubmit, %SettingsIniFilepath%, %ScriptSettingsSection%, ConfirmBeforeSubmit, 1
IniRead, AutoUpdateCheck, %SettingsIniFilepath%, %ScriptSettingsSection%, AutoUpdateCheck, 1
IniRead, ErrorLogToDiscord, %SettingsIniFilepath%, %ScriptSettingsSection%, ErrorLogToDiscord, 1
if(ErrorLogToDiscord){
; Discord
IniRead, DiscordErrorLoggingWebhookBotURL, %SettingsIniFilepath%, General, DiscordWebhookBotURL, %A_space%
if(DiscordErrorLoggingWebhookBotURL = ""){
Message = DiscordErrorLoggingWebhookBotURL is blank. `nWill not be able to post error messages or upload status to discord.`nPlease add discord webhook URL in settings.ini under: `n`n[General]`DiscordErrorLoggingWebhookBotURL=
SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,ErrorSummaryVar")
}
}
; GUI Variables
; ------------------------------------------------
MarginSize := 10
MarginSizeDoubled := MarginSize * 2
ButtonHeights := 30
ThumbnailPreviewWidth := 200
GuiHeight := 440
; Column One
ColumnOneWidth := 500
ColumnOneEditBoxWidth := ColumnOneWidth - (MarginSize * 2)
ColumnOneEditBoxHalfWidth := (ColumnOneEditBoxWidth / 2) + 5
GuiFontSize = 15
; Column Two
ColumnTwoXPosition := ColumnOneWidth + (MarginSize * 2)
ColumnTwoEditBoxWidth := 200
ColumnTwoEditBoxHalfWidth := ColumnTwoEditBoxWidth / 2
; Results Screen
ResultButtonWidth := 250
ResultButtonEditWidth := 250
ResultButtonHeights := 30
; START OF GUI
; ------------------------------------------------
Gui, Font, s%GuiFontSize%
; Column One
;------------------------------------------------
Gui, Font, Bold
Gui, Font, s8
Gui, Add, Text,, Title
Gui, Font, Normal
Gui, Font, s%GuiFontSize%
Gui, Add, Edit,w%ColumnOneEditBoxWidth% vLivestreamTitle, %LivestreamTitle%
Gui, Font, Bold
Gui, Font, s8
Gui, Add, Text,, Description
Gui, Font, Normal
Gui, Font, s%GuiFontSize%
Gui, Add, Edit,w%ColumnOneEditBoxWidth% h150 vLivestreamDescription, %LivestreamDescription%
Gui, Font, Bold
Gui, Font, s8
Gui, Add, Text,, Tags (Comma Seperated)
Gui, Font, Normal
Gui, Font, s%GuiFontSize%
Gui, Add, Edit,w%ColumnOneEditBoxWidth% vLivestreamTags, %LivestreamTags%
Gui, Font, Bold
Gui, Font, s8
Gui, Add, Text,, Thumbnail
Gui, Add, Button, x+%MarginSize% yp-3 gSelectThumbnail, Select
Gui, Font, Normal
Gui, Font, s%GuiFontSize%
Gui, Add, Picture, x%MarginSize% w%ThumbnailPreviewWidth% h-1 vThumbnailPreview, %LivestreamThumbnail%
Gui, Font, Bold
Gui, Font, S10
Gui, Add, Button, x%ColumnOneEditBoxHalfWidth% yp-%marginsize% w%ColumnOneEditBoxHalfWidth% h40 gSaveAsTemplate, Save As Template
Gui, Add, Button,gSchedulePost w%ColumnOneEditBoxHalfWidth% gLoadTemplate h40 , Load Template
; Gui, Add, Button, yp+0 x%ColumnOneEditBoxHalfWidth% w%ColumnOneEditBoxHalfWidth%, Text button here
; Gui, Add, Edit,w%ColumnOneEditBoxWidth% h150 vLivestreamDescription, This livestream is happening soon!
; Column Two
; ------------------------------------------------
Gui, Font, s%GuiFontSize%
Gui, Font, Bold
Gui, Add, Text,y0 x%ColumnTwoXPosition%, Settings
Gui, Font, Normal
Gui, Font, s8
Gui, Add, Checkbox, vErrorLogToDiscord Checked%ErrorLogToDiscord%, Error Log to Discord
Gui, Add, Checkbox, vConfirmBeforeSubmit checked%ConfirmBeforeSubmit%, Confirm Before Submit
Gui, Add, Checkbox, vAutoUpdateCheck Checked%AutoUpdateCheck%, Auto Update Check
if(UpdateAvailable){
Gui, Add, Button, cRed w%ColumnTwoEditBoxWidth% gUpdateScript vUpdateAvailable center, Update Available!
}
else, {
Gui, Add, Button, w%ColumnTwoEditBoxWidth% gUpdateScript vUpdateAvailable center, No Updates Available
}
Gui, Font, s%GuiFontSize%
Gui, Font, Bold
; Gui, Add, Text, , Settings
Gui, Add, Text, y+%MarginSizeDoubled% , Date and Time
Gui, Font, Normal
Gui, Add, DateTime, vLivestreamDate w%ColumnTwoEditBoxWidth%, MM/dd/yyyy
Gui, Add, DateTime, vLivestreamTime w%ColumnTwoEditBoxWidth% Choose200505311900, Time
Gui, Font, s8
Gui, Font, Normal
Gui, Add, Button, gSetLivestreamTimeMorning yp+35 w%ColumnTwoEditBoxHalfWidth%,Morning
Gui, Add, Button,yp+0 x+0 gSetLivestreamTimeMorning w%ColumnTwoEditBoxHalfWidth%,Evening
Gui, Font, s%GuiFontSize%
Gui, Font, Bold
Gui, Add, Text,y+%MarginSizeDoubled% x%ColumnTwoXPosition%, Platforms
Gui, Font, Normal
; Gui, Add, Checkbox,, Dlive
Gui, Add, Checkbox,checked vOdysee, Odysee
Gui, Add, Checkbox, x+%marginSize% yp+0 checked vLocals, Locals
Gui, Add, Checkbox,x%ColumnTwoXPosition% y+%marginsize% checked vRumble, Rumble
Gui, Font, S8
Gui, Add, Checkbox, x+10 yp+5 Checked vInputRumbleCustomRTMP, Input RTMP
Gui, Font, s15
Gui, Font, Bold
Gui, Add, Button, x%ColumnTwoXPosition% y+%marginsizeDoubled% gSchedulePost w%ColumnTwoEditBoxWidth% h60, Schedule
; Gui, Font, Normal
Gui, Show, h%GuiHeight%, %FullScriptName%
;---Check for Updates---
;------------------------------------------------
if(AutoUpdateCheck AND !UpdateAvailable){
SetTimer, CheckForUpdates, -1000
}
Return
SetLivestreamTimeMorning:
if(A_GuiControl = "Morning")
GuiControl, , LivestreamTime, 200505311100
if(A_GuiControl = "Evening")
GuiControl, , LivestreamTime, 200505311900
Return
; Functions
;------------------------------------------------
GUIUpdateVars:
Gui, Submit, NoHide
Return
SaveAsTemplate:
Gui, submit, NoHide ; Update variables for all modified fields
TemplateDirectory = %A_ScriptDir%\Lib\Templates-%ScriptAbbreviatedName%
if(!FileExist(TemplateDirectory)){
FileCreateDir, %TemplateDirectory%
}
InputBox, TemplateName, Input Name, Please Input Name for the Template:
if(ErrorLevel)
Return
TemplateDirectory = %TemplateDirectory%\%TemplateName%
ErrorLoggingDirectory := TemplateDirectory
; FileCreateDir, %TemplateDirectory%
CreateErrorLoggingFiles(ErrorLoggingDirectory)
; Save all the post settings to the Error Logging Directory
FileAppend, %LivestreamTitle%, %PostTitleFilePath% ; save post content to txt file
FileAppend, %LivestreamDescription%, %PostBodyFilePath% ; save post content to txt file
FileAppend, %LivestreamTags%, %PostTagsFilePath% ; save post content to txt file
if(LivestreamThumbnail){ ; copy thumbnail into folder
SplitPath, LivestreamThumbnail, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
FileCopy, %LivestreamThumbnail%, %ErrorLoggingDirectory%\Thumbnail.%OutExtension%
}
Return
LoadTemplate:
Message = Loading Template
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,DiscordErrorLogging")
ErrorLoggingDirectory = %A_ScriptDir%\Lib\Templates-%ScriptAbbreviatedName%\
FileSelectFolder, ErrorLoggingDirectory, %ErrorLoggingDirectory%
if(ErrorLevel){
Tooltip
Return
}
RetryUpload:
run, "%A_ScriptFullPath%" "%ErrorLoggingDirectory%"
ExitApp
SelectThumbnail:
FileSelectFile, LivestreamThumbnail,
GuiControl, , ThumbnailPreview, *w%ThumbnailPreviewWidth% *h-1 %LivestreamThumbnail%
Return
SchedulePost:
Gui, submit, NoHide
; Save Settings.ini
; ------------------------------------------------
IniWrite, %ConfirmBeforeSubmit%, %SettingsIniFilepath%, %ScriptSettingsSection%, ConfirmBeforeSubmit
IniWrite, %AutoUpdateCheck%, %SettingsIniFilepath%, %ScriptSettingsSection%, AutoUpdateCheck
IniWrite, %ErrorLogToDiscord%, %SettingsIniFilepath%, %ScriptSettingsSection%, ErrorLogToDiscord
; Re-use an existing errorlog or create new directory
if(InStr(PassedInArgument, "\ErrorLogging\"))
CreateErrorLoggingFiles(PassedInArgument)
else, {
CreateErrorLoggingFiles()
; Save all the post settings to the Error Logging Directory
FileAppend, %LivestreamTitle%, %PostTitleFilePath% ; save post content to txt file
FileAppend, %LivestreamDescription%, %PostBodyFilePath% ; save post content to txt file
FileAppend, %LivestreamTags%, %PostTagsFilePath% ; save post content to txt file
if(LivestreamThumbnail){ ; copy thumbnail into folder
SplitPath, LivestreamThumbnail, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
FileCopy, %LivestreamThumbnail%, %ErrorLoggingDirectory%\Thumbnail.%OutExtension%
}
}
if(Odysee){
Gosub, OdyseeSchedule
}
if(Locals){
Gosub, LocalsSchedule
}
if(Rumble)
gosub, RumbleSchedule
if(InputRumbleCustomRTMP){
gosub, RumbleSetRTMP
}
; msgbox, done!
; Gui, Add,
ToolTip ; hide any existing tooltips
Gui, Destroy
; ------------------------------------------------
; RESULTS SCREEN
; ------------------------------------------------
; Read Info From .ini Files
; ------------------------------------------------
IniRead, LocalsRTMPURL, %PostStatusesFilepath%, Livestream,LocalsRTMPURL, %A_Space%
IniRead, LocalsRTMPKey, %PostStatusesFilepath%, Livestream,LocalsRTMPKey, %A_Space%
IniRead, LocalsLivestreamURL, %PostStatusesFilepath%, Livestream,LocalsLivestreamURL, %A_Space%
IniRead, OdyseeLivestreamURL, %PostStatusesFilepath%, Livestream,OdyseeLivestreamURL, %A_Space%
IniRead, RumbleLivestreamURL, %PostStatusesFilepath%, Livestream,RumbleLivestreamURL, %A_Space%
Gui, Font, Bold
Gui, Font, s%GuiFontSize%
Gui, Add, Button,x%MarginSize% y+10 h%ResultButtonHeights% w%ResultButtonWidth% gResultsGUIAction, Locals RTMP URL
Gui, Add, Edit, x+5 yp+0 h%ResultButtonHeights% w%ResultButtonEditWidth% vLocalsRTMPURL center, %LocalsRTMPURL%
Gui, Add, Button, x%MarginSize% y+10 h%ResultButtonHeights% w%ResultButtonWidth% gResultsGUIAction, Locals RTMP Key
Gui, Add, Edit, x+5 yp+0 h%ResultButtonHeights% w%ResultButtonEditWidth% vLocalsRTMPKey gGUIUpdateVars center, %LocalsRTMPKey%
Gui, Add, Button, x%MarginSize% y+10 h%ResultButtonHeights% w%ResultButtonWidth% gResultsGUIAction, Locals URL
Gui, Add, Edit, x+5 yp+0 h%ResultButtonHeights% w%ResultButtonEditWidth% vLocalsLivestreamURL gGUIUpdateVars center, %LocalsLivestreamURL%
Gui, Add, Button, x%MarginSize% y+10 h%ResultButtonHeights% w%ResultButtonWidth% gResultsGUIAction, Odysee URL
Gui, Add, Edit, x+5 yp+0 h%ResultButtonHeights% w%ResultButtonEditWidth% vOdyseeLivestreamURL gGUIUpdateVars center, %OdyseeLivestreamURL%
Gui, Add, Button, x%MarginSize% y+10 h%ResultButtonHeights% w%ResultButtonWidth% gResultsGUIAction, Rumble URL
Gui, Add, Edit, x+5 yp+0 h%ResultButtonHeights% w%ResultButtonEditWidth% vRumbleLivestreamURL gGUIUpdateVars center, %RumbleLivestreamURL%
Gui, Add, Button, x%MarginSize% y+%marginsizeDoubled% gResultsGUIAction h%ResultButtonHeights% w%ResultButtonEditWidth%, Open Post Folder
Gui, Add, Button, x+%marginsize% gResultsGUIAction h%ResultButtonHeights% w%ResultButtonEditWidth%,Save Changes
Gui, Add, Button, x%MarginSize% gResultsGUIAction h%ResultButtonHeights% w%ResultButtonEditWidth%,Copy Title
Gui, Add, Button, x+%marginsize% gResultsGUIAction h%ResultButtonHeights% w%ResultButtonEditWidth%,Copy Description
Gui, Add, Button, x%MarginSize% h%ResultButtonHeights% w%ResultButtonEditWidth% gStartSMP, Start SMP
Gui, Add, Button, x+%marginsize% h%ResultButtonHeights% w%ResultButtonEditWidth% gRetryUpload ,Try Failed Again
Gui, Font, s8
Gui, Font, Normal
Gui, Add, Button, y%MarginSize% w%ResultButtonEditWidth% Center, Error Log
Gui, Add, Edit, y+5 h300 w%ResultButtonEditWidth%, %ErrorLogVar%
; Gui, Add, Button, x%MarginSize% gRetryUpload h%ResultButtonHeights% w%ResultButtonEditWidth%,Try Failed Again
Gui, Show
Return
; GoSubs
; ------------------------------------------------
StartSMP:
; IniWrite, %A_ScriptFullPath%, %SettingsIniFilepath%, Filepaths, SMPFilepath
IniRead, SocialMediaPosterFilepath, %SettingsIniFilepath%, Filepaths, SocialMediaPosterFilepath, %A_Space%
if(SocialMediaPosterFilepath = "" or !FileExist(SocialMediaPosterFilepath)){
OnMessage(0x44, "OnMsgBoxSocialMediaPoster")
MsgBox 0x21, Filepath Not Found, Unable to find filepath for Social Media Poster`nWould you like to add it?
OnMessage(0x44, "")
IfMsgBox OK, {
FileSelectFile, SocialMediaPosterFilepath,,, Please Select Social Media Poster Filepath
if(ErrorLevel)
Return
if(!InStr(SocialMediaPosterFilepath, ".exe"))
Return
} Else IfMsgBox Cancel, {
Return
}
IniWrite, %SocialMediaPosterFilepath%, %SettingsIniFilepath%, Filepaths, SocialMediaPosterFilepath
}
run, %SocialMediaPosterFilepath% %StatusFileFilePath%
Return
/*
*/
ResultsGUIAction:
; Msgbox % "A_GuiControl: " A_GuiControl
if(A_GuiControl = "Open Post Folder"){
run, %ErrorLoggingDirectory%
Return
}
if(A_GuiControl = "Save Changes"){
IniWrite, %LocalsRTMPURL%, %PostStatusesFilepath%, Livestream,LocalsRTMPURL
IniWrite, %LocalsRTMPKey%, %PostStatusesFilepath%, Livestream,LocalsRTMPKey
IniWrite, %LivestreamURL%, %PostStatusesFilepath%, Livestream,LivestreamURL
IniWrite, %RumbleLivestreamURL%, %PostStatusesFilepath%, Livestream,RumbleLivestreamURL
IniWrite, %OdyseeLivestreamURL%, %PostStatusesFilepath%, Livestream,OdyseeLivestreamURL
Return
}
Message = Copying %A_GuiControl% to Clipboard
SaveOrPostProgress(Message:=Message,PostType:="Tooltip")
if(A_GuiControl = "Copy Title"){
Clipboard := LivestreamTitle
}
if(A_GuiControl = "Copy Description"){
Clipboard := LivestreamDescription
}
if(A_GuiControl = "Rumble URL"){
Clipboard := RumbleLivestreamURL
}
if(A_GuiControl = "Odysee URL"){
Clipboard := OdyseeLivestreamURL
}
if(A_GuiControl = "Locals URL"){
Clipboard := LocalsLivestreamURL
}
if(A_GuiControl = "Locals RTMP URL"){
Clipboard := LocalsRTMPURL
}
if(A_GuiControl = "Locals RTMP Key"){
Clipboard := LocalsRTMPKey
}
sleep, 1000
ToolTip
Return
KillScript:
ExitApp
ReloadScript:
Reload
PauseScript:
Pause
Return
; GoSubs for Selenium Automation
; ------------------------------------------------
#Include %A_ScriptDir%\Modules\Locals-Schedule.ahk
#Include %A_ScriptDir%\Modules\Odysee-Schedule.ahk
#Include %A_ScriptDir%\Modules\Odysee-Grab-URL.ahk
#Include %A_ScriptDir%\Modules\Rumble-Schedule.ahk
#Include %A_ScriptDir%\Modules\Rumble-Set-RTMP.ahk
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\Update-Functions.ahk
; Misc
;------------------------------------------------
; Escape::ExitApp