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.
video-uploader/Freedomain Video Uploader.ahk

1150 lines
39 KiB
Plaintext

2 years ago
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
#SingleInstance, Force
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
CoordMode, ToolTip, Screen
CoordMode, Mouse, Screen
FileEncoding, UTF-8-RAW ; Needed for special symbols that are used in video descritions
DetectHiddenWindows, ON ; used for finding Running .ahk scripts
; Only Set tool tray icon if this is the source .ahk script.
; The .exe has the icon compiled into it
2 years ago
if(InStr(A_ScriptFullPath, ".ahk")){
try Menu, Tray, Icon, %A_ScriptDir%\Assets\FreedomainVideo.ico
}
; Parameter passed in to script
; ------------------------------------------------
PassedInArgument1_Filepath = %1% ; Filepath of one of the files in the directory of the video project
PassedInArgument2_Action = %2% ; "Scheduled", "ShowResults", "Delete"
PassedInArgument3_Details = %3% ; Details of Argument2, eg list of Sites to Upload to
; Msgbox % "PassedInArgument1_Filepath: " PassedInArgument1_Filepath
; Msgbox % "PassedInArgument2: " PassedInArgument2
; Msgbox % "PassedInArgument3: " PassedInArgument3
2 years ago
; Customize the Toolbar Icon Menu
; ------------------------------------------------
2 years ago
Menu, tray, NoStandard
Menu, Tray, Add, Exit, KillScript
Menu, Tray, Add, Pause, PauseScript
Menu, Tray, Add, Show Results, DisplayResults
2 years ago
Menu, Tray, Add, Open New Project, ReloadScript
Menu, Tray, Add, Restart with Last Project, RetryUpload
Menu, Tray, Default, Restart with Last Project
; Track how long sections of code take to run
UStartTime := A_TickCount ; start time
; 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\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 ; Misc functions for video uploading specifically
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\LBRY-Functions.ahk ; LBRY Specific Functions
2 years ago
;---Global Variables---
;------------------------------------------------
2 years ago
global LBRYResolveAPICommand
global LBRYPermanentURL
global VideoTitle
global VideoFilepath
global VideoThumbFilepath
global VideoTags
global VideoDescription
global DiscordErrorLoggingWebhookBotURL
global DiscordVideosWebhookURL
global VideoFolderDir
global LogErrorsToMsgbox
; global LogErrorsToTextFile
global CurrentSite
global Driver
global DriverStatus
global ChromeProfile
global ShowTooltipProgress
global ErrorLogSummary
global DiscordParlerWebhookURL
global ErrorLoggingFilePath
; global TotalTabLoops
2 years ago
global ErrorLogVar
2 years ago
ErrorLogVar :=
2 years ago
global DevMode
global LBRYNetFilepath
LBRYNetFilepath := "C:\Program Files\LBRY\resources\static\daemon\lbrynet.exe"
global Number_of_loops_to_Check_Upload_status
Number_of_loops_to_Check_Upload_status = 720
; 720 loops, at 5 seonds each = 3600 seconds (60 mins)
; number of seconds to wait between loops when checking video upload status
global Time_Between_Loops_Upload_Status
Time_Between_Loops_Upload_Status = 15000 ;
2 years ago
; loop Index number to check if video is stuck uploading
global Array_Index_Num_of_Upload_StatusChecks
Array_Index_Num_of_Upload_StatusChecks := [144,288,432, 576,720,864]
; loop number that discord message gets sent off at to track upload progress
; 144 x 5 seconds = 12 minutes
; 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 := "VideoUploader"
global ScriptNameAcronym
ScriptNameAcronym := "FVU"
2 years ago
global ScriptName
global ScriptVersion
global FullScriptName
VersionIniFilepath = %A_ScriptDir%\Lib\Version-%ScriptNameAcronym%.ini
; Install the Version.ini file in lib folder (Used by .exe file)
FileInstall, Version.ini, %VersionIniFilepath%, 1
IniRead, ScriptVersion, %VersionIniFilepath%,Video-Uploader, Version, 0.0
IniRead, ScriptName, %VersionIniFilepath%,Video-Uploader, Name,
FullScriptName := ScriptName . " - " . ScriptVersion
2 years ago
;---Script Settings---
;------------------------------------------------
; Checkbox Settings
IniRead, XPosition, %SettingsIniFilepath%, General, XPosition, 0
IniRead, YPosition, %SettingsIniFilepath%, General, YPosition, 0
2 years ago
IniRead, RootDirToStartIn, %SettingsIniFilepath%, General, RootDirToStartIn
IniRead, LogErrorsToMsgbox, %SettingsIniFilepath%, General, LogErrorsToMsgbox, %A_Space%
IniRead, UpdateAvailable, %SettingsIniFilepath%, %ScriptSettingsSection%, UpdateAvailable, 0
IniRead, DevMode, %SettingsIniFilepath%, General, DevMode, 0
IniRead, TotalVideosUploaded, %SettingsIniFilepath%, General, TotalVideosUploaded, 0
IniRead, MouseClicksSaved, %SettingsIniFilepath%, General, MouseClicksSaved, 0
2 years ago
IniRead, ShowTooltipProgress, %SettingsIniFilepath%, General, ShowTooltipProgress, 1
IniRead, AutoUpdateCheck, %SettingsIniFilepath%, General, AutoUpdateCheck, 1
; AutoLogin setting
IniRead, AutoLogin, %SettingsIniFilepath%, General, AutoLogin, 1
IniRead, KillLBRYAfterUpload, %SettingsIniFilepath%, General, KillLBRYAfterUpload, 1
IniRead, ConfirmBeforeSubmit, %SettingsIniFilepath%, %ScriptSettingsSection%, ConfirmBeforeSubmit, 0
; Discord Error Logging
; ------------------------------------------------
IniRead, ErrorLogToDiscord, %SettingsIniFilepath%, %ScriptSettingsSection%, ErrorLogToDiscord, 1
IniRead, DiscordPingOnCompletion, %SettingsIniFilepath%, %ScriptSettingsSection%, DiscordPingOnCompletion, 1
2 years ago
if(ErrorLogToDiscord || DiscordPingOnCompletion){
IniRead, DiscordUsernameID, %SettingsIniFilepath%, General, DiscordUsernameID, %A_space%
if(!DiscordUsernameID){
Message = DiscordUsernameID is blank. Will not be able to ping to notify when uploads are complete.`nPlease add user ID in settings.ini under: `n`n[General]`nDiscordUsernameID=`nOr Uncheck "Discord Ping on Completion"
; SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile")
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar")
}
}
2 years ago
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,DiscordErrorLogging")
}
; Auto Updater Settings
; ------------------------------------------------
2 years ago
global GitReleasesAPIURL
GitReleasesAPIURL = https://freedomain.dev/api/v1/repos/yuriy/video-uploader/releases
; Post Scheduler Settings
; ------------------------------------------------
global PostSchedulerGitReleasesAPIURL
PostSchedulerGitReleasesAPIURL = https://freedomain.dev/api/v1/repos/yuriy/post-scheduler/releases
IniRead, PostSchedulerVersion, %SettingsIniFilepath%, Freedomain Post Scheduler, Version, 0.0
IniRead, PostSchedulerFilepath, %SettingsIniFilepath%, Filepaths, PostScheduler, %A_Space%
; Msgbox % "PostSchedulerVersion: " PostSchedulerVersion
; IniRead, OutputVar, Filename, Section, Key [, Default]
2 years ago
;---LBRY Settings---
;------------------------------------------------
IniRead, LBRYNewVideoStakeAmount, %SettingsIniFilepath%, General, LBRYNewVideoStakeAmount, 1.0
2 years ago
IniRead, LBRYChannelID, %SettingsIniFilepath%, General, LBRYChannelID, %A_Space%
if(LBRYChannelID = ""){
LBRYChannelID = b89ed227c49e726fcccf913bdc9dec4c8fec99c2
IniWrite, %LBRYChannelID%, %SettingsIniFilepath%, General, LBRYChannelID
}
; Set Settings based on Passed in Arguments
; ------------------------------------------------
; if passed argument is .exe file, then script has just been updated and we need to move the old version
if(InStr(PassedInArgument1_Filepath,ScriptName) and InStr(PassedInArgument1_Filepath,".exe")){
; create backups folder if it doesn't exist
BackupsFolder = %LibFolder%\Backups\
; Msgbox % "BackupsFolder: " BackupsFolder
if(!FileExist(BackupsFolder)){
FileCreateDir, %BackupsFolder%
}
; move old version to backups folder, overwrite if name conflict
FileDelete, %PassedInArgument1_Filepath%
if(ErrorLevel){ ; most likely because the old version hasn't finished exiting yet
SaveOrPostProgress(Message:="Moving Old Version to Backups",PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar")
sleep, 2000
FileDelete, %PassedInArgument1_Filepath%
if(ErrorLevel){
MsgBox,,Update Successful, Update was successful`, but failed to delete the old version, most likely due to it running.`nPlease delete it manually.
}
ToolTip
}
; Change parameter to "LastPost" so last post now gets automatically opened instead of user having to re-select the file again
PassedInArgument1_Filepath = LastPost
}
if(PassedInArgument1_Filepath = "LastPost"){
IniRead, PassedInArgument1_Filepath, %SettingsIniFilepath%, %ScriptSettingsSection%, LastPost, %A_Space%
}
if(PassedInArgument2_Action = "ShowResults"){
IniRead, PassedInArgument1_Filepath, %SettingsIniFilepath%, %ScriptSettingsSection%, LastPost, %A_Space%
}
; Show File Selection Dialogue
; ------------------------------------------------
PassedInArgument1_FilepathLength := StrLen(PassedInArgument1_Filepath)
if(PassedInArgument1_FilepathLength < 5 and !InStr(PassedInArgument1_Filepath, ".exe")){
2 years ago
FileSelectFile, BodyTextFilePath,,%RootDirToStartIn%,Please Select ANY File Within the Project Folder
if(ErrorLevel)
Return
}
else, {
SkipUpdateCheckThisRun := 1
BodyTextFilePath := PassedInArgument1_Filepath
2 years ago
}
; Read Info From Project Files
;------------------------------------------------
; get project directory from the "BodyTextFilePath"
; BodyTextFilePath will be any file from within the update directory
2 years ago
SplitPath, BodyTextFilePath, OutFileName, VideoFolderDir, OutExtension, OutNameNoExt, OutDrive
Loop, files, %VideoFolderDir%\*.*, F ; loop through the files in the directory
{ ; D = Directories, F = Files, R = Recursive
SplitPath, A_LoopFileFullPath, FileNameWExt, FileDir, FileExt, FileNameNoExt,
if(FileNameWExt = "title.txt"){
FileRead, VideoTitle, %A_LoopFileFullPath%
; Generate the LBRY URL Slug on each startup in case Title changes between runs
2 years ago
LBRYURLSlug := VideoTitle
LBRYURLSlug := LBRYCMDTextReplacement(LBRYURLSlug)
2 years ago
OriginalVideoTitle := VideoTitle
}
if(FileNameWExt = "body.txt"){
FileRead, VideoDescription, %A_LoopFileFullPath%
DescriptionCharCount := StrLen(VideoDescription)
OriginalVideoDescription := VideoDescription
}
if(FileNameWExt = "summary.txt"){
FileRead, VideoSummary, %A_LoopFileFullPath%
; DescriptionCharCount := StrLen(VideoDescription)
OriginalVideoSummary := VideoSummary
}
2 years ago
if(FileNameWExt = "keywords.txt"){
FileRead, VideoTags, %A_LoopFileFullPath%
FileRead, PodcastTags, %A_LoopFileFullPath%
OriginalVideoTags := VideoTags
OriginalPodcastTags := PodcastTags ; set in case there is no keywords_podcast file
2 years ago
}
if(FileNameWExt = "keywords_podcast.txt"){
FileRead, PodcastTags, %A_LoopFileFullPath%
OriginalPodcastTags := PodcastTags
}
if(FileExt = "mp4"){
VideoFilepath := A_LoopFileFullPath
SplitPath, A_LoopFileFullPath,,,, VideoFileNameNoExt
FileGetSize, VideoFileSizeInMB, %A_LoopFileFullPath%, M
VideoInfoObj := Filexpro(VideoFilepath,
, "System.Video.TotalBitrate"
, "System.Video.FrameHeight"
, "System.Video.FrameWidth" )
try, VideoTotalBitrate := VideoInfoObj["System.Video.TotalBitrate"]
try, VideoHeight := VideoInfoObj["System.Video.FrameHeight"]
try, VideoWidth := VideoInfoObj["System.Video.FrameWidth"]
VideoAspectRatio := getAspectRatio(VideoWidth, VideoHeight)
2 years ago
}
if(FileExt = "png" OR FileExt = "jpg" OR FileExt = "jpeg"){
2 years ago
VideoThumbFilepath := A_LoopFileFullPath
}
}
; Loop through the folder again to find the correct .WAV audio file as Stef has multiple in there and we need the .mp4 file to be found first so we know what to look for file name wise.
Loop, files, %VideoFolderDir%\*.flac, F ; loop through the files in the directory
2 years ago
{ ; D = Directories, F = Files, R = Recursive
SplitPath, A_LoopFileFullPath, FileNameWExt, FileDir, FileExt, FileNameNoExt
if(FileNameNoExt = VideoFileNameNoExt){
WavAudioFilepath := A_LoopFileFullPath
}
}
; if no FLAC file, then loop through folder and select WAV file instead
if(WavAudioFilepath = ""){
; Loop through the folder again to find the correct .WAV audio file as Stef has multiple in there and we need the .mp4 file to be found first so we know what to look for file name wise.
Loop, files, %VideoFolderDir%\*.WAV, F ; loop through the files in the directory
{ ; D = Directories, F = Files, R = Recursive
SplitPath, A_LoopFileFullPath, FileNameWExt, FileDir, FileExt, FileNameNoExt
if(FileNameNoExt = VideoFileNameNoExt){
WavAudioFilepath := A_LoopFileFullPath
}
}
}
; Find the .mp3 podcast file
2 years ago
Loop, files, %VideoFolderDir%\*.mp3, F ; loop through the files in the directory
{ ; D = Directories, F = Files, R = Recursive
SplitPath, A_LoopFileFullPath, FileNameWExt, FileDir, FileExt, FileNameNoExt
if(FileNameNoExt = VideoFileNameNoExt){
MP3AudioFilepath := A_LoopFileFullPath
}
}
;---Read Info From Previous Run And Set Upload Options---
;--------------------------------------------------------
2 years ago
VideoLinksIniFile = %VideoFolderDir%\VideoLinks.ini
if(FileExist(VideoLinksIniFile)){
IniRead, BitChuteURL, %VideoLinksIniFile%, URLs, BitChuteURL, %A_Space%
2 years ago
; LBRY
; removed on 2024/06/24, let's regenerate the slug each time in case the video file changes between runs
; IniRead, LBRYURLSlug, %VideoLinksIniFile%, Misc, LBRYURLSlug, %A_Space%
2 years ago
; LBRY Video
IniRead, LBRYVideoURL, %VideoLinksIniFile%, URLs, LBRYVideoURL, %A_Space%
IniRead, LBRYVideoThumb, %VideoLinksIniFile%, Misc, LBRYVideoThumb, %A_Space%
IniRead, LBRYVideoPermanentURL, %VideoLinksIniFile%, URLs, LBRYVideoPermanentURL, %A_Space%
IniRead, OdyseeVideoURL, %VideoLinksIniFile%, URLs, OdyseeVideoURL, %A_Space%
IniRead, OdyseeVideoThumb, %VideoLinksIniFile%, Misc, OdyseeVideoThumb, %A_Space%
OdyseeVideoThumb := StrReplace(OdyseeVideoThumb, "Thumb:", "")
; LBRY Audio
IniRead, LBRYAudioURL, %VideoLinksIniFile%, URLs, LBRYAudioURL, %A_Space%
IniRead, LBRYAudioThumb, %VideoLinksIniFile%, Misc, LBRYAudioThumb, %A_Space%
IniRead, LBRYAudioPermanentURL, %VideoLinksIniFile%, URLs, LBRYAudioPermanentURL, %A_Space%
IniRead, OdyseeAudioURL, %VideoLinksIniFile%, URLs, OdyseeAudioURL, %A_Space%
IniRead, OdyseeAudioThumb, %VideoLinksIniFile%, Misc, OdyseeAudioThumb, %A_Space%
OdyseeAudioThumb := StrReplace(OdyseeAudioThumb, "Thumb:", "")
; Others
IniRead, RumbleURL, %VideoLinksIniFile%, URLs, RumbleURL, %A_Space%
IniRead, BrighteonURL, %VideoLinksIniFile%, URLs, BrighteonURL, %A_Space%
IniRead, DailyMotionURL, %VideoLinksIniFile%, URLs, DailyMotionURL, %A_Space%
IniRead, PodcastNumber, %VideoLinksIniFile%, Misc, PodcastNumber, %A_Space%
IniRead, LocalsURL, %VideoLinksIniFile%, URLs, LocalsURL, %A_Space%
IniRead, PodcastTranscriptURL, %VideoLinksIniFile%, URLs, PodcastTranscriptURL, %A_Space%
IniRead, UnauthorizedTVURL, %VideoLinksIniFile%, URLs, UnauthorizedTVURL, %A_Space%
2 years ago
; MISC
IniRead, ErrorLoggingFilePath, %VideoLinksIniFile%, Misc, ErrorLoggingFilePath, %A_Space%
; I don't remember why I added this, commenting this out on 2024/06/22 for now
; IniRead, TempVideoThumbFilepath, %VideoLinksIniFile%, Misc, VideoThumbFilepath, %A_Space%
/* if(TempVideoThumbFilepath){ ; if Video Thumbnail was saved in last run, overwrite variable path that was grabbed in the file loop above
VideoThumbFilepath := TempVideoThumbFilepath
}
*/
2 years ago
}
; Create a directory for errorlogging if this is the first time working on this project
2 years ago
if(ErrorLoggingFilePath = ""){
FormatTime, TodayDate , YYYYMMDDHH24MISS, yyyyMMdd_hhmmss
ErrorLoggingDirectory := ErrorLoggingFolder . "\" . TodayDate . "_" . ScriptNameAcronym
2 years ago
FileCreateDir, %ErrorLoggingDirectory%
ErrorLoggingFilePath := ErrorLoggingFolder . "\" . TodayDate . "_" . ScriptNameAcronym . "\ErrorLogging.txt" ; Set locaiton where error logging text will go
2 years ago
; Save ErrorLoggingFilePath to project settings file so it can be reused if doing multiple runs
2 years ago
IniWrite, %ErrorLoggingFilePath%, %VideoLinksIniFile%, Misc, ErrorLoggingFilePath
}
if(PodcastNumber = ""){
PodcastNumber := StrSplit(VideoFileNameNoExt, "_")
PodcastNumber := PodcastNumber[2]
}
; Set Websites to Upload to
; ------------------------------------------------
2 years ago
; Set the checkmark status of each item based on the variable status
(BitChuteURL)?(BitChute := 0) : (BitChute := 1)
(RumbleURL)?(Rumble := 0) : (Rumble := 1)
(DailyMotionURL)?(DailyMotion := 0) : (DailyMotion := 1)
2 years ago
; if user tried to upload to locals already and still needs to grab the url
if(LocalsURL = "" OR LocalsURL = "LocalsUploadStartedNeedToGrabURL"){
Locals := 1
2 years ago
}
else,
Locals := 0
2 years ago
(OdyseeVideoURL)?(OdyseeVideo := 0) : (OdyseeVideo := 1)
(OdyseeAudioURL || WavAudioFilepath = "")?(OdyseeAudio := 0) : (OdyseeAudio := 1)
2 years ago
; Brighteon has 6GB video file size limit
(BrighteonURL)?(Brighteon := 0) : (Brighteon := 1)
if(VideoFileSizeInMB > 6144){
VideoFileSizeOver6GB := 1
Brighteon := 0
}
2 years ago
; Brighteon will fail if video does not have one of the following aspect ratios
BrighteonAcceptedAspectRatios := ["4:3","3:4","16:9","9:16"]
; Msgbox % "VideoAspectRatio: " VideoAspectRatio
VideoHasBrighteonCompatibleAspectRatio := HasVal(BrighteonAcceptedAspectRatios, VideoAspectRatio)
2 years ago
; Override Website statuses if this is a schedule post based on Argument3
; ------------------------------------------------
if(PassedInArgument2_Action = "Scheduled"){
; if(PassedInArgument3_Details){
(InStr(PassedInArgument3_Details, "Locals"))?(Locals := 1) : (Locals := 0)
(InStr(PassedInArgument3_Details, "Bitchute"))?(Bitchute := 1) : (Bitchute := 0)
(InStr(PassedInArgument3_Details, "OdyseeVideo"))?(OdyseeVideo := 1) : (OdyseeVideo := 0)
(InStr(PassedInArgument3_Details, "OdyseeAudio"))?(OdyseeAudio := 1) : (OdyseeAudio := 0)
(InStr(PassedInArgument3_Details, "Rumble"))?(Rumble := 1) : (Rumble := 0)
(InStr(PassedInArgument3_Details, "Brighteon"))?(Brighteon := 1) : (Brighteon := 0)
(InStr(PassedInArgument3_Details, "DailyMotion"))?(DailyMotion := 1) : (DailyMotion := 0)
; }
goto, StartScheduledPost
}
/*
*/
2 years ago
;---/Read Info From Previous Run And Set Upload Options---
;--------------------------------------------------------
2 years ago
if(PassedInArgument2_Action = "ShowResults"){
goto, DisplayResults
}
2 years ago
; Main GUI Window
; ------------------------------------------------
; Write current project to ini file for easy reloading
IniWrite, %BodyTextFilePath%, %SettingsIniFilepath%, %ScriptSettingsSection%, LastPost
2 years ago
gosub, SetAndShowMainGUI
RunTimeToShowGui := round(((A_TickCount - UStartTime) / 1000), 2)
Return
2 years ago
; -------------------------------GUI GoSubs-------------------------------
; Kill the script if user clicks on cancel button
KillScript:
; GuiClose:
ExitApp
Return
2 years ago
PauseScript:
Pause,Toggle
Return
2 years ago
CancelPost:
GuiClose:
; ExitApp
Gui, Submit,
Return
2 years ago
ReloadScript:
Reload
Return
2 years ago
; Gets activated each time that text gets input into any of the text boxes
; updates the variables with the new text
UpdateVars:
Gui, Submit, NoHide
Return
2 years ago
SubmitDescription:
Gui, Submit, NoHide
DescriptionCharCount := StrLen(VideoDescription)
GuiControl,, DescriptionCharCount, %DescriptionCharCount%
Return
2 years ago
; Open folder of the project
OpenProjectFolder:
if(FileExist(VideoFolderDir))
run, %VideoFolderDir%
else,
msgbox, Cannot Open Folder as it no longer exists at:`n%VideoFolderDir%
Return
2 years ago
ClearVideoLinks:
FileDelete, %VideoLinksIniFile%
Return
2 years ago
ToggleTestingMode:
ToggleTestingMode()
run, "%A_ScriptFullPath%" "LastPost"
Return
2 years ago
ToggleDevMode:
ToggleDevMode()
run, "%A_ScriptFullPath%" "LastPost"
Return
2 years ago
/*
2 years ago
OpenGiteaPage:
run, https://freedomain.dev/yuriy/video-uploader
2 years ago
Return
OpenErrorLog:
run, %ErrorLoggingFilePath%
Return
*/
UncheckAllPlatforms:
GuiControl,,Bitchute, 0
GuiControl,,Locals, 0
GuiControl,,OdyseeVideo, 0
GuiControl,,OdyseeAudio, 0
GuiControl,,Rumble, 0
GuiControl,,DailyMotion, 0
GuiControl,,Brighteon, 0
Return
2 years ago
SelectVideoFilepath:
FileSelectFile, VideoFilepath,, %FileDir%, Select Video File
GuiControl,, VideoFilepath, %VideoFilepath%
Return
SelectWAVFilepath:
FileSelectFile, WavAudioFilepath,, %FileDir%, Select WAV File
GuiControl,, WavAudioFilepath, %WavAudioFilepath%
GuiControl,, OdyseeAudio, 1
GuiControl,, OdyseeAudioThumb, 1
Return
SelectMP3Filepath:
FileSelectFile, MP3AudioFilepath,, %FileDir%, Select MP3 File
if(!InStr(MP3AudioFilepath, ".mp3")){
msgbox, 4096, Error, Selected File is not an .mp3 file. `nPlease try again.
Return
}
GuiControl,, MP3AudioFilepath, %MP3AudioFilepath%
Return
SelectVideoThumbFilepath:
FileSelectFile, VideoThumbFilepath,, %FileDir%, Select Thumbnail File
if(!InStr(VideoThumbFilepath, FileDir)){
TimedToolTip("Thumbnail Copied to Project Folder",,,1000)
SplitPath, VideoThumbFilepath, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
FileCopy, %VideoThumbFilepath%, %FileDir%\*,1
VideoThumbFilepath = %FileDir%\%OutFileName%
; Msgbox % "VideoThumbFilepath: " VideoThumbFilepath
}
GuiControl,, VideoThumbFilepath, %VideoThumbFilepath%
; GuiControl,, ImageThumbnail,%VideoThumbFilepath%
Return
; Download updates from google drive and save it to the location of the script and then reload the script
UpdateScript:
UpdateScript()
; @todo: Save any changes made to the script before installing update
Return
/*
*/
2 years ago
; -------------------------------Upload Video Functionality-------------------------------
StartScript:
WinGetPos, XPosition, YPosition, , , A
IniWrite, %XPosition%, %SettingsIniFilepath%, General, XPosition
IniWrite, %YPosition%, %SettingsIniFilepath%, General, YPosition
2 years ago
Gui, Submit, NoHide
2 years ago
if(VideoFilepath = ""){
Msgbox,4096,Error,No Video Filepath Found.`nPlease Input Video Filepath to Upload a Video.
Return
}
2 years ago
; Destroy GUI after checking everything is working
Gui, Destroy
; Save Video Info
;------------------------------------------------
; if changes made, delete the original file and save the new content to it
2 years ago
if(VideoTitle != OriginalVideoTitle){
VideoTitleFilepath = %VideoFolderDir%\title.txt
2 years ago
FileDelete, %VideoTitleFilepath%
FileAppend, %VideoTitle%, %VideoTitleFilepath%
}
2 years ago
if(VideoTags != OriginalVideoTags){
VideoTagsFilepath = %VideoFolderDir%\keywords.txt
2 years ago
FileDelete, %VideoTagsFilepath%
FileAppend, %VideoTags%, %VideoTagsFilepath%
}
2 years ago
if(PodcastTags != OriginalPodcastTags){
PodcastTagsFilepath = %VideoFolderDir%\keywords_podcast.txt
2 years ago
FileDelete, %PodcastTagsFilepath%
FileAppend, %PodcastTags%, %PodcastTagsFilepath%
}
2 years ago
if(VideoDescription != OriginalVideoDescription){
VideoBodyFilepath = %VideoFolderDir%\body.txt
2 years ago
FileDelete, %VideoBodyFilepath%
FileAppend, %VideoDescription%, %VideoBodyFilepath%
}
2 years ago
; Save Script Settings to File
; ------------------------------------------------
; Save settings to config file
IniWrite, %ShowTooltipProgress%, %SettingsIniFilepath%, General, ShowTooltipProgress
IniWrite, %AutoUpdateCheck%, %SettingsIniFilepath%, General, AutoUpdateCheck
IniWrite, %AutoLogin%, %SettingsIniFilepath%, General, AutoLogin
IniWrite, %ErrorLogToDiscord%, %SettingsIniFilepath%, %ScriptSettingsSection%, ErrorLogToDiscord
IniWrite, %DiscordPingOnCompletion%, %SettingsIniFilepath%, %ScriptSettingsSection%, DiscordPingOnCompletion
IniWrite, %KillLBRYAfterUpload%, %SettingsIniFilepath%, General, KillLBRYAfterUpload
IniWrite, %ConfirmBeforeSubmit%, %SettingsIniFilepath%, %ScriptSettingsSection%, ConfirmBeforeSubmit
2 years ago
; Used by Post Scheduler, filepath changes between script updates
IniWrite, %A_ScriptFullPath%, %SettingsIniFilepath%, Filepaths, VideoUploaderFilepath
2 years ago
StartScheduledPost:
2 years ago
; Format the LBRYURLSlug to be API Compatible
if(LBRYURLSlug = "") ; if slug spot is blank, then set it to video title
LBRYURLSlug := VideoTitle
LBRYURLSlug := LBRYCMDTextReplacement(LBRYURLSlug)
2 years ago
; Save the LBRY URL Slug to .ini file in case it's needed later
; removed on 2024/06/24, generating the URL SLugh each run going forward
; IniWrite, %LBRYURLSlug%, %VideoLinksIniFile%, Misc, LBRYUrlSlug
IniWrite, %VideoThumbFilepath%, %VideoLinksIniFile%, Misc, VideoThumbFilepath
IniWrite, %PodcastNumber%, %VideoLinksIniFile%, Misc, PodcastNumber
IniWrite, %VideoThumbFilepath%, %VideoLinksIniFile%, Misc, VideoThumbFilepath
2 years ago
; -------------------------------Log Info To Text-------------------------------s
(Bitchute)?(PostedWebsites .= "Bitchute|") : ()
(Locals)?(PostedWebsites .= "Locals|") : ()
(Rumble)?(PostedWebsites .= "Rumble|") : ()
(Brighteon)?(PostedWebsites .= "Brighteon|") : ()
(DailyMotion)?(PostedWebsites .= "DailyMotion|") : ()
(OdyseeVideo)?(PostedWebsites .= "OdyseeVideo|") : ()
(OdyseeAudio)?(PostedWebsites .= "OdyseeAudio|") : ()
2 years ago
; Log Basic info to the errorlogging file
Message = Starting Upload with %ScriptName% v%ScriptVersion%:`nFor: **%VideoTitle%**`nTo: %PostedWebsites%
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
Message := "VideoTitle: " VideoTitle
SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")
Message := "VideoDescription: `n" VideoDescription
SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")
Message := "VideoTags: " VideoTags
SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")
Message := "VideoFilepath: " VideoFilepath
SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")
Message := "VideoThumbFilepath: " VideoThumbFilepath
SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")
Message := "TotalVideosUploaded: " TotalVideosUploaded
SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")
2 years ago
Message := "Video Information:`n VideoTotalBitrate:" . VideoTotalBitrate . "`nVideoAspectRatio:" . VideoAspectRatio
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
; Convert Video Title and Description into javascript formatting for sending to pages through js instead of plain selenium
JSVideoTitle := FormatTextToJSText(VideoTitle)
JSVideoDescription := FormatTextToJSText(VideoDescription)
JSVideoSummary := FormatTextToJSText(VideoSummary)
2 years ago
Message = JSVideoSummary:`n %JSVideoSummary%
SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")
; -------------------------------/Log Info To Text-------------------------------
2 years ago
; Cleanup Tag Formatting
; ------------------------------------------------
; @todo: note: it would be better to replace accented chars w/ their pure latin equivalents but that seems a bit
; beyond the scope of this change. here's a link talking about how to do that tho
; https://www.autohotkey.com/boards/viewtopic.php?t=61626
2 years ago
; Create an array out of the keywords to be used in different places
ArrayOfVideoTags := []
ArrayOfPodcastTags := []
2 years ago
; VIDEO Tags
For index, val in StrSplit(VideoTags, ",") {
; for each element in the split videotags array, trim leading & trailing spaces
val := Trim(val)
2 years ago
; and remove any chars that are not a letter, number, or space (i = case-insensitive)
val := RegexReplace(val, "i)[^a-z0-9 ]", "")
ArrayOfVideoTags.InsertAt(index, val)
}
; PODCAST Tags
For index, val in StrSplit(PodcastTags, ",") {
; for each element in the split videotags array, trim leading & trailing spaces
val := Trim(val)
; and remove any chars that are not a letter, number, or space (i = case-insensitive)
val := RegexReplace(val, "i)[^a-z0-9 ]", "")
ArrayOfPodcastTags.InsertAt(index, val)
}
; update VideoTags with sanitized keywords list
VideoTags := Join(",", ArrayOfVideoTags*)
; update PodcastTags with sanitized keywords list
PodcastTags := Join(",", ArrayOfPodcastTags*)
2 years ago
; // Cleanup Tag Formatting
; ------------------------------------------------
2 years ago
; Upload to Sites
; ------------------------------------------------
; Call each submodule one by one
; if errors occur then an upload for that site will be stopped and the next upload will then proceed
if(Locals)
gosub, LocalsUpload
if(BitChute)
Gosub, BitChuteUpload
2 years ago
if(OdyseeVideo){
LBRYUploadType := "Video"
Gosub, LBRYVideoUpload
}
if(OdyseeAudio){
LBRYUploadType := "Audio"
Gosub, LBRYAudioUpload
}
2 years ago
if(Rumble)
Gosub, RumbleUpload
2 years ago
if(Brighteon)
Gosub, BrighteonUpload
if(DailyMotion)
Gosub, DailyMotionUpload
2 years ago
; grab the LBRY Video/Audio URLs
if(OdyseeVideo){
LBRYUploadType := "Video"
Gosub, LBRYGetURL
}
if(OdyseeAudio){
LBRYUploadType := "Audio"
Gosub, LBRYGetURL
}
2 years ago
if(LocalsGrabURL){
Gosub, LocalsGrabURL
}
5 months ago
; // Upload to Sites
; ------------------------------------------------
if(URLOfLastErrorPage){
Message = Activating Tab of last failed post.
SaveOrPostProgress(Message:=Message,PostType:="Tooltip")
2 years ago
; @todo: replaceme with working funciton to activate tab
; FindAndActivateTab(URLOfLastErrorPage)
}
CurrentSite := ""
2 years ago
if(URLOfLastErrorPage)
2 years ago
Message = Video Uploading Finished WITH Some Failures
else,
Message = All Videos Uploaded Successfully
2 years ago
if(DiscordPingOnCompletion)
2 years ago
Message = <@%DiscordUsernameID%>: %Message%
else,
Message = %Message%
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
; Read Info for Results Window GUI
; ------------------------------------------------
DisplayResults:
2 years ago
Tooltip ; Remove all tooltips
Gui, Destroy ; destroy GUI in case we're going from the main screen to results without uploading.
IniRead, MouseClicksSaved, %SettingsIniFilepath%, General, MouseClicksSaved, %A_Space%
2 years ago
IniRead, TotalVideosUploaded, %SettingsIniFilepath%, General, TotalVideosUploaded, %A_Space%
IniRead, BitChuteURL, %VideoLinksIniFile%, URLs, BitChuteURL, %A_Space%
IniRead, OdyseeVideoURL, %VideoLinksIniFile%, URLs, OdyseeVideoURL, %A_Space%
IniRead, OdyseeVideoThumb, %VideoLinksIniFile%, Misc, OdyseeVideoThumb, %A_Space%
OdyseeVideoThumb := StrReplace(OdyseeVideoThumb, "Thumb:", "")
IniRead, OdyseeAudioURL, %VideoLinksIniFile%, URLs, OdyseeAudioURL, %A_Space%
IniRead, OdyseeAudioThumb, %VideoLinksIniFile%, Misc, OdyseeAudioThumb, %A_Space%
OdyseeAudioThumb := StrReplace(OdyseeAudioThumb, "Thumb:", "")
IniRead, LocalsURL, %VideoLinksIniFile%, URLs, LocalsURL, %A_Space%
IniRead, RumbleURL, %VideoLinksIniFile%, URLs, RumbleURL, %A_Space%
IniRead, BrighteonURL, %VideoLinksIniFile%, URLs, BrighteonURL, %A_Space%
IniRead, DailyMotionURL, %VideoLinksIniFile%, URLs, DailyMotionURL, %A_Space%
IniRead, PodcastNumber, %VideoLinksIniFile%, Misc, PodcastNumber, %A_Space%
if(PodcastNumber = "") {
SplitPath, VideoFilepath,,,, VideoNameNoExt
; Remove the FDR_#### from video title for LBRY URL
if(InStr(VideoNameNoExt, "FDR_")){
FoundPos := InStr(VideoNameNoExt, "_",,,2) ; get position of second instance of an "_"
if(FoundPos < 11){
; FoundPos += 1
; Msgbox % "FoundPos: " FoundPos
PodcastNumber := SubStr(VideoNameNoExt,1, FoundPos)
PodcastNumber := StrReplace(PodcastNumber, "FDR", "")
PodcastNumber := StrReplace(PodcastNumber, "_", "")
; Msgbox % "PodcastNumber: " PodcastNumber
}
}
}
; Show Results GUI Window
; ------------------------------------------------
gosub, SetGUIVariables
gosub, SetAndShowResultsGUI
2 years ago
SaveCurrentChromeVersionToIniFile()
Return
; GoTo's
; ------------------------------------------------
SubmitScheduler:
Gui, Submit
; format and combine date and time
FormatTime, ScheduledDateOnly , %ScheduledDate%, yyyyMMdd
FormatTime, ScheduledTimeOnly , %ScheduledTime%, HHmmss
TimeStamp := ScheduledDateOnly . ScheduledTimeOnly
; create schedule post ini file
ScheduleFileFilepath = %A_scriptDir%/Scheduled-Posts
if(!FileExist(ScheduleFileFilepath)){
FileCreateDir, %ScheduleFileFilepath%
}
ScheduleFileFilepath = %ScheduleFileFilepath%\%TimeStamp%.ini
IniWrite, %TimeStamp%, %ScheduleFileFilepath%, Schedule-Info, Timestamp
IniWrite, %BodyTextFilePath%, %ScheduleFileFilepath%, Schedule-Info, ProjectFilepath
IniWrite, Video, %ScheduleFileFilepath%, Schedule-Info, PostType
IniWrite, %VideoTitle%, %ScheduleFileFilepath%, Schedule-Info, Title
; Generate variable with each of the checked ON sites
(BitChute)?(VideoSites .= "Bitchute" . "|"):()
(Locals)?(VideoSites .= "Locals" . "|"):()
(OdyseeVideo)?(VideoSites .= "OdyseeVideo" . "|"):()
(OdyseeAudio)?(VideoSites .= "OdyseeAudio" . "|"):()
(Brighteon)?(VideoSites .= "Brighteon" . "|"):()
(DailyMotion)?(VideoSites .= "DailyMotion" . "|"):()
(Rumble)?(VideoSites .= "Rumble" . "|"):()
IniWrite, %VideoSites%, %ScheduleFileFilepath%, Schedule-Info, Sites
if(!FileExist(PostSchedulerFilepath)){
gosub, UpdatePostScheduler
}
else,
run, %PostSchedulerFilepath%
Return
2 years ago
OpenLBRYBlobFilesFolder:
try,
2 years ago
run, C:\Users\%A_UserName%\AppData\Local\lbry\lbrynet\blobfiles
catch e {
msgbox, Unable to open lbrynet blobfiles folder. `nIs LBRY installed?
}
2 years ago
Return
StartSocialMediaPoster:
; IniRead, SocialMediaPosterFilepath, %SettingsIniFilepath%, General, FDRRadioUN, %A_Space%
IniRead, SocialMediaPosterFilepath, %SettingsIniFilepath%, SocialMediaPoster, SocialMediaPosterFilepath, %A_Space%
if(!SocialMediaPosterFilepath or !FileExist(SocialMediaPosterFilepath)){
2 years ago
OnMessage(0x44, "OnMsgBoxSocialMediaPoster")
MsgBox 0x21, Filepath Not Found, Unable to find filepath for Social Media Poster`nWould you like to add it?
2 years ago
OnMessage(0x44, "")
IfMsgBox OK, {
FileSelectFile, SocialMediaPosterFilepath,,, Please Select Social Media Poster Filepath
2 years ago
if(ErrorLevel)
Return
if(!InStr(SocialMediaPosterFilepath, ".exe"))
Return
2 years ago
} Else IfMsgBox Cancel, {
Return
}
IniWrite, %SocialMediaPosterFilepath%, %SettingsIniFilepath%, Filepaths, SocialMediaPosterFilepath
2 years ago
}
run, %SocialMediaPosterFilepath% "%VideoLinksIniFile%"
Return
/*
*/
2 years ago
; Copy Info from GUI to Clipboard
; ------------------------------------------------
5 months ago
CopyToClipboard:
Message = Copying %A_GuiControl% to Clipboard
SaveOrPostProgress(Message:=Message,PostType:="Tooltip")
(A_GuiControl = "Transcript URL")?(Clipboard := PodcastTranscriptURL):()
(A_GuiControl = "Bitchute")?(Clipboard := BitChuteURL):()
(A_GuiControl = "Brighteon")?(Clipboard := BrighteonURL):()
(A_GuiControl = "DailyMotion")?(Clipboard := DailyMotionURL):()
(A_GuiControl = "Odysee Video")?(Clipboard := OdyseeVideoURL):()
(A_GuiControl = "Odysee Audio")?(Clipboard := OdyseeAudioURL):()
(A_GuiControl = "Rumble")?(Clipboard := RumbleURL):()
(A_GuiControl = "Locals")?(Clipboard := LocalsURL):()
(A_GuiControl = "Unauthorized")?(Clipboard := UnauthorizedTVURL):()
(A_GuiControl = "Video Tags")?(Clipboard := VideoTags):()
(A_GuiControl = "Podcast Tags")?(Clipboard := PodcastTags):()
(A_GuiControl = "Description")?(Clipboard := VideoDescription):()
(A_GuiControl = "Summary")?(Clipboard := VideoSummary):()
2 years ago
sleep, 1000
ToolTip
Return
2 years ago
; @todo: Add thumbnail status to this
; @todo: add podcast tags to this
UpdateINI:
IniWrite, %UnauthorizedTVURL%, %VideoLinksIniFile%, URLs, UnauthorizedTVURL
IniWrite, %PodcastTranscriptURL%, %VideoLinksIniFile%, URLs, PodcastTranscriptURL
2 years ago
IniWrite, %VideoTitle%, %VideoLinksIniFile%, Misc, VideoTitle
IniWrite, %LocalsURL%, %VideoLinksIniFile%, URLs, LocalsURL
IniWrite, %RumbleURL%, %VideoLinksIniFile%, URLs, RumbleURL
IniWrite, %DailyMotionURL%, %VideoLinksIniFile%, URLs, DailyMotionURL
IniWrite, %BrighteonURL%, %VideoLinksIniFile%, URLs, BrighteonURL
IniWrite, %BitChuteURL%, %VideoLinksIniFile%, URLs, BitChuteURL
2 years ago
; LBRY/Odysee:
2 years ago
IniWrite, %LBRYVideoURL%, %VideoLinksIniFile%, URLs, LBRYVideoURL
IniWrite, %LBRYAudioURL%, %VideoLinksIniFile%, URLs, LBRYAudioURL
IniWrite, %OdyseeVideoURL%, %VideoLinksIniFile%, URLs, OdyseeVideoURL
OdyseeVideoThumb := StrReplace(OdyseeVideoThumb, "Thumb:", "")
IniWrite, %OdyseeVideoThumb%, %VideoLinksIniFile%, Misc, OdyseeVideoThumb
IniWrite, %OdyseeAudioURL%, %VideoLinksIniFile%, URLs, OdyseeAudioURL
OdyseeAudioThumb := StrReplace(OdyseeAudioThumb, "Thumb:", "")
IniWrite, %OdyseeAudioThumb%, %VideoLinksIniFile%, Misc, OdyseeAudioThumb
if(VideoDescription != OriginalVideoDescription){
VideoBodyFilepath = %VideoFolderDir%\body.txt
FileDelete, %VideoBodyFilepath%
FileAppend, %VideoDescription%, %VideoBodyFilepath%
}
if(PodcastTags != OriginalPodcastTags){
PodcastTagsFilepath = %VideoFolderDir%\keywords_podcast.txt
FileDelete, %PodcastTagsFilepath%
FileAppend, %PodcastTags%, %PodcastTagsFilepath%
}
msgbox,4096, Updated!, VideoLinks.ini file updated with any edits that you've made.`n`n%VideoLinksIniFile%
Return
RetryUpload:
run, "%A_ScriptFullPath%" "LastPost"
ExitApp
ReloadToResults:
run, "%A_ScriptFullPath%" "ShowResults"
ExitApp
SendErrorLoggingThroughTelegram:
msgbox, I don't do nothin atm
2 years ago
Return
; Post-To-Telegram
;------------------------------------------------
#Include %A_ScriptDir%\Modules\Post-To-Telegram.ahk
; Post-Video-To-Telegram
;------------------------------------------------
#Include %A_ScriptDir%\Modules\Post-Video-To-Telegram.ahk
; Post-To-Discord
;------------------------------------------------
#Include %A_ScriptDir%\Modules\Post-To-Discord.ahk
; BitChute
;------------------------------------------------
#Include %A_ScriptDir%\Modules\Bitchute-Upload.ahk
; Brighteon
;------------------------------------------------
#Include %A_ScriptDir%\Modules\Brighteon-Upload.ahk
; DailyMotion
;------------------------------------------------
#Include %A_ScriptDir%\Modules\DailyMotion-Upload.ahk
; LBRY
;------------------------------------------------
#Include %A_ScriptDir%\Modules\LBRY-Upload.ahk
; Rumble
;------------------------------------------------
#Include %A_ScriptDir%\Modules\Rumble-Upload.ahk
; Locals
;------------------------------------------------
#Include %A_ScriptDir%\Modules\Locals-Upload.ahk
; Podcast
;------------------------------------------------
#Include %A_ScriptDir%\Modules\Podcast-Upload.ahk
; Update Functionality
; ------------------------------------------------
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\Shared-GoTos.ahk
; Special Website Functions
; ------------------------------------------------
#Include %A_ScriptDir%\Lib\Freedomain-Posters-Shared-Functions\Locals-Functions.ahk
; GUI Windows
; ------------------------------------------------
#include C:\Users\%A_Username%\Syncthing\Git\Freedomain-Video-Uploader\Modules\GUI-Main-Window.ahk