#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

; Only Set tool tray icon if this is the source .ahk script.
; The .exe has the icon compiled into it
if(InStr(A_ScriptFullPath, ".ahk")){
	try Menu, Tray, Icon, %A_ScriptDir%\Assets\FreedomainVideo.ico
}

; Parameter passed in to script
; ------------------------------------------------
PassedParameter = %1%


; 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, 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


;---Global Variables---
;------------------------------------------------
global ScriptNameav
global ScriptVersion
global FullScriptName
global LBRYResolveAPICommand
global LBRYPermanentURL
global VideoTitle
global VideoFilepath
global VideoThumbFilepath
global VideoTags
global VideoDescription
global SocialMediaDescription
global DiscordErrorLoggingWebhookBotURL
global DiscordVideosWebhookURL
global VideoFolderDir
global LogErrorsToMsgbox
; global LogErrorsToTextFile
global CurrentSite
global Driver
global DriverStatus
global ChromeProfile
global ShowTooltipProgressCheckStatus
global ShowTooltipProgress
global ErrorLogSummary
global DiscordParlerWebhookURL
global ErrorLoggingFilePath
; global TotalTabLoops

global ErrorLogVar
ErrorLogVar := 

global ReuseTabs ; reuse tabs variable
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 ; 

; 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"


FileInstall, Version.ini, %A_ScriptDir%\Lib\Version.ini, 1
IniRead, ScriptVersion, %A_ScriptDir%\Lib\Version.ini,Video-Uploader, Version, 0.0
IniRead, ScriptName, %A_ScriptDir%\Lib\Version.ini,Video-Uploader, Name, "Video Uploader"

FullScriptName := ScriptName . " - " . ScriptVersion


;---Script Settings---
;------------------------------------------------
; Checkbox Settings
IniRead, ShowTooltipProgress, %SettingsIniFilepath%, General, ShowTooltipProgress, 1
(ShowTooltipProgress)?(ShowTooltipProgressCheckStatus := 1) : (ShowTooltipProgressCheckStatus := 0)

IniRead, XPosition, %SettingsIniFilepath%, General, XPosition, 0
IniRead, YPosition, %SettingsIniFilepath%, General, YPosition, 0

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

; Checkbox Settings
IniRead, ShowTooltipProgress, %SettingsIniFilepath%, General, ShowTooltipProgress, 1
(ShowTooltipProgress)?(ShowTooltipProgressCheckStatus := 1) : (ShowTooltipProgressCheckStatus := 0)

ReuseTabs := 1 ; ReuseTabs is permanantly on. There is never a time where you want to create new tabs for every website

IniRead, AutoUpdateCheck, %SettingsIniFilepath%, General, AutoUpdateCheck, 1
(AutoUpdateCheck)?(AutoUpdateCheckCheckStatus := 1) : (AutoUpdateCheckCheckStatus := 0)

; AutoLogin setting
IniRead, AutoLogin, %SettingsIniFilepath%, General, AutoLogin, 1
(AutoUpdateCheck)?(AutoUpdateCheckCheckStatus := 1) : (AutoUpdateCheckCheckStatus := 0)

IniRead, PingOnCompletion, %SettingsIniFilepath%, General, PingOnCompletion, 1
(PingOnCompletion)?(PingOnCompletionCheckStatus := 1) : (PingOnCompletionCheckStatus := 0)

if(PingOnCompletion){
	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")
	}
}


IniRead, KillLBRYAfterUpload, %SettingsIniFilepath%, General, KillLBRYAfterUpload, 1
(KillLBRYAfterUpload)?(=KillLBRYAfterUploadCheckStatus := 1) : (KillLBRYAfterUploadCheckStatus := 0)

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---
;------------------------------------------------
global GitReleasesAPIURL
GitReleasesAPIURL = https://freedomain.dev/api/v1/repos/yuriy/Freedomain-Video-Uploader/releases


;---LBRY Settings---
;------------------------------------------------
IniRead, LBRYNewVideoStakeAmount, %SettingsIniFilepath%, General, LBRYNewVideoStakeAmount, %A_Space%
if(LBRYNewVideoStakeAmount = ""){
	LBRYNewVideoStakeAmount = 1.0
	IniWrite, %LBRYNewVideoStakeAmount%, %SettingsIniFilepath%, General, LBRYNewVideoStakeAmount
}

IniRead, LBRYChannelID, %SettingsIniFilepath%, General, LBRYChannelID, %A_Space%
if(LBRYChannelID = ""){
	LBRYChannelID = b89ed227c49e726fcccf913bdc9dec4c8fec99c2
	IniWrite, %LBRYChannelID%, %SettingsIniFilepath%, General, LBRYChannelID
}



;---Read Info From Project Files---
;------------------------------------------------

; if passed argument is .exe file, then script has just been udpated and we need to move the old version
if(InStr(PassedParameter,ScriptName) and InStr(PassedParameter,".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
	FileMove, %PassedParameter%, %BackupsFolder%\*, 1
	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 
	FileMove, %PassedParameter%, %BackupsFolder%\*, 1
	if(ErrorLevel){
		MsgBox,,Update Successful, Update was successful`, but unable to move old version to the Backups folder.`nPlease move it or delete it manually.
	}
	ToolTip
}
; Change paramter to LastPost so last post gets automatically opened instead of user having to re-select the file again
PassedParameter = LastPost
}

if(PassedParameter = "LastPost"){
	IniRead, PassedParameter, %SettingsIniFilepath%, %ScriptSettingsSection%, LastPost, %A_Space%
}

if(PassedParameter = "ShowResults"){
	IniRead, PassedParameter, %SettingsIniFilepath%, %ScriptSettingsSection%, LastPost, %A_Space%
}



PassedParameterLength := StrLen(PassedParameter)
if(PassedParameterLength < 5  and !InStr(PassedParameter, ".exe")){
	FileSelectFile, BodyTextFilePath,,%RootDirToStartIn%,Please Select ANY File Within the Project Folder
	if(ErrorLevel)
	Return
}
else, {
	SkipUpdateCheckThisRun := 1
	BodyTextFilePath := PassedParameter
}


; @todo Do this with an array. Add all filepaths to array and then pull out the ones with the extension.
; get directory from the filepath grabbed
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%
		LBRYURLSlug := VideoTitle
		OriginalVideoTitle := VideoTitle
		OriginalLBRYURLSlug := LBRYURLSlug
	}

	if(FileNameWExt = "body.txt"){
		FileRead, VideoDescription, %A_LoopFileFullPath%
		DescriptionCharCount := StrLen(VideoDescription)
		OriginalVideoDescription := VideoDescription
	}

	if(FileNameWExt = "keywords.txt"){
		FileRead, VideoTags, %A_LoopFileFullPath%
		FileRead, PodcastTags, %A_LoopFileFullPath%
		OriginalVideoTags := VideoTags
		OriginalPodcastTags := PodcastTags
	}

	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" )                 	
		VideoTotalBitrate := VideoInfoObj["System.Video.TotalBitrate"]

	}

	if(FileExt = "png" OR FileExt = "jpg"){
		VideoThumbFilepath := A_LoopFileFullPath
	}
}

if(VideoDescription = ""){
	; @todo: is this used anymore?
	FileRead, VideoDescription, %A_scriptDir%\Lib\DescriptionTemplate.txt
}

; 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
{       ; 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
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---
;--------------------------------------------------------
VideoLinksIniFile = %VideoFolderDir%\VideoLinks.ini

if(FileExist(VideoLinksIniFile)){
	; IniRead, StreamanityURL, %VideoLinksIniFile%, URLs, StreamanityURL, %A_Space%
	IniRead, BitChuteURL, %VideoLinksIniFile%, URLs, BitChuteURL, %A_Space%
	; LBRY
	IniRead, LBRYURLSlug, %VideoLinksIniFile%, Misc, LBRYURLSlug, %A_Space%
	if(LBRYURLSlug = ""){
		LBRYURLSlug := OriginalLBRYURLSlug ; video title
	}
	; 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, FacebookURL, %VideoLinksIniFile%, URLs, FacebookURL, %A_Space%

	; MISC
	IniRead, ErrorLoggingFilePath, %VideoLinksIniFile%, Misc, ErrorLoggingFilePath, %A_Space%
	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
	}

	if(VideoFileSizeInMB < 50){
		IniRead, Telegram, %VideoLinksIniFile%, Misc, Telegram, %A_Space%
	}

}

; Create a directory for errorlogging if this is the first time working on this project
if(ErrorLoggingFilePath = ""){
	; DevModeMsgBox("generating filepath")
	FormatTime, TodayDate , YYYYMMDDHH24MISS, yyyyMMdd_hhmmss
	ErrorLoggingDirectory := ErrorLoggingFolder . "\" . TodayDate . "_FVU"
	FileCreateDir, %ErrorLoggingDirectory%
	ErrorLoggingFilePath := ErrorLoggingFolder . "\" . TodayDate . "_FVU\ErrorLogging.txt" ; Set locaiton where error logging text will go

	; Write both filepaths to .ini file
	IniWrite, %ErrorLoggingFilePath%, %VideoLinksIniFile%, Misc, ErrorLoggingFilePath
}

if(PodcastNumber = ""){
	PodcastNumber := StrSplit(VideoFileNameNoExt, "_")
	PodcastNumber := PodcastNumber[2]
}

; Set the checkmark status of each item based on the variable status
; (StreamanityURL != "")?(StreamanityCheckStatus := 0) : (StreamanityCheckStatus := 1)
(BitChuteURL != "")?(BitChuteCheckStatus := 0) : (BitChuteCheckStatus := 1)

(OdyseeVideoURL != "")?(OdyseeVideoCheckStatus := 0) : (OdyseeVideoCheckStatus := 1)
(OdyseeVideoThumb != "")?(OdyseeVideoThumbCheckStatus := 0) : (OdyseeVideoThumbCheckStatus := 0)
OdyseeAudioThumbCheckStatus := 0
if(OdyseeAudioURL OR WavAudioFilepath = "")
OdyseeAudioCheckStatus := 0
/*
if(OdyseeAudioThumb OR WavAudioFilepath = "")
OdyseeAudioThumbCheckStatus := 0

*/
(RumbleURL != "")?(RumbleCheckStatus := 0) : (RumbleCheckStatus := 1)
; if user tried to upload to locals already and still needs to grab the url, check 
(LocalsURL = "LocalsUploadStartedNeedToGrabURL")?(LocalsCheckStatus := 1) : (LocalsCheckStatus := 0)
(BrighteonURL != "")?(BrighteonCheckStatus := 0) : (BrighteonCheckStatus := 1)
if(VideoFileSizeInMB > 6144){
	VideoFileSizeOver6GB := 1
	BrighteonCheckStatus := 0
}

(DailyMotionURL != "")?(DailyMotionCheckStatus := 0) : (DailyMotionCheckStatus := 1)
FacebookCheckStatus := 0
TelegramCheckStatus := 0

;---/Read Info From Previous Run And Set Upload Options---
;--------------------------------------------------------



;---Testing Mode Overrides---
;------------------------------------------------
IniRead, TestingMode, %SettingsIniFilepath%, General, TestingMode, 0
if(TestingMode OR DevMode){ ; save currently seelcted sites to ini file for next test
	; IniRead, Streamanity, %SettingsIniFilepath%, Testing, Streamanity, %A_Space%
	; (Streamanity)?(StreamanityCheckStatus := 1) : (StreamanityCheckStatus := 0)
	IniRead, BitChute, %SettingsIniFilepath%, Testing, BitChute,  %A_Space%
	(BitChute)?(BitChuteCheckStatus := 1) : (BitChuteCheckStatus := 0)

	IniRead, OdyseeVideo, %SettingsIniFilepath%, Testing, OdyseeVideo,  %A_Space%
	(OdyseeVideo)?(OdyseeVideoCheckStatus := 1) : (OdyseeVideoCheckStatus := 0)

	IniRead, OdyseeVideoThumb, %SettingsIniFilepath%, Testing, OdyseeVideoThumb,  %A_Space%
	(OdyseeVideoThumb)?(OdyseeVideoThumbCheckStatus := 1) : (OdyseeVideoThumbCheckStatus := 0)

	IniRead, OdyseeAudio, %SettingsIniFilepath%, Testing, OdyseeAudio,  %A_Space%
	(OdyseeAudio)?(OdyseeAudioCheckStatus := 1) : (OdyseeAudioCheckStatus := 0)

	IniRead, OdyseeAudioThumb, %SettingsIniFilepath%, Testing, OdyseeAudioThumb,  %A_Space%
	(OdyseeAudioThumb)?(OdyseeAudioThumbCheckStatus := 1) : (OdyseeAudioThumbCheckStatus := 0)

	IniRead, Rumble, %SettingsIniFilepath%, Testing, Rumble,  %A_Space%
	(Rumble)?(RumbleCheckStatus := 1) : (RumbleCheckStatus := 0)

	IniRead, Brighteon, %SettingsIniFilepath%, Testing, Brighteon,  %A_Space%
	(Brighteon)?(BrighteonCheckStatus := 1) : (BrighteonCheckStatus := 0)

	IniRead, DailyMotion, %SettingsIniFilepath%, Testing, DailyMotion,  %A_Space%
	(DailyMotion)?(DailyMotionCheckStatus := 1) : (DailyMotionCheckStatus := 0)

	IniRead, Locals, %SettingsIniFilepath%, Testing, Locals,  %A_Space%
	(Locals)?(LocalsCheckStatus := 1) : (LocalsCheckStatus := 0)

	IniRead, Telegram, %SettingsIniFilepath%, Testing, Telegram,  %A_Space%
	(Telegram)?(TelegramCheckStatus := 1) : (TelegramCheckStatus := 0)

	IniRead, Facebook, %SettingsIniFilepath%, Testing, Facebook,  %A_Space%
	(Facebook)?(FacebookCheckStatus := 1) : (FacebookCheckStatus := 0)
}


if(PassedParameter = "ShowResults"){
	goto, DisplayResults
}


; Main GUI Window
; ------------------------------------------------
#include %A_scriptDir%\Modules\GUI-Main-Window.ahk


; Write current project to ini file for easy reloading
IniWrite, %BodyTextFilePath%, %SettingsIniFilepath%, %ScriptSettingsSection%, LastPost


URunTime1 := round(((A_TickCount - UStartTime) / 1000), 2)

;---Check for Updates---
;------------------------------------------------
if(AutoUpdateCheck AND !UpdateAvailable){
	Message = Checking for Updates
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

	if(CheckForUpdates(GitReleasesAPIURL))
	GuiControl,,UpdateAvailable, Uploader Update Available!

	if(CheckForChromeUpdates(ChromeFilepath)){
		GuiControl,,ChromeUpdateAvailable, Chrome Update Available!
		ChromeUpdateAvailable := 1

	}
}

; calculate run time and convert to seconds
URunTime2 := round(((A_TickCount - UStartTime) / 1000), 2)

Return

; -------------------------------GUI GoSubs-------------------------------
; Kill the script if user clicks on cancel button
KillScript: 
; GuiClose:
ExitApp
Return

PauseScript:
Pause,Toggle
Return

CancelPost:
GuiClose:
; ExitApp
Gui, Submit,
Return

ReloadScript:
Reload
Return

; 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

SubmitDescription:
Gui, Submit, NoHide
DescriptionCharCount := StrLen(VideoDescription)
GuiControl,, DescriptionCharCount, %DescriptionCharCount%
Return



; Open folder of the project
OpenProjectFolder:
run, %VideoFolderDir%
Return

ClearVideoLinks:
FileDelete, %VideoLinksIniFile%
Return

OpenErrorLog:
run, %ErrorLoggingFilePath%
Return

ToggleTestingMode:
ToggleTestingMode()
run, "%A_ScriptFullPath%" "LastPost"
Return

ToggleDevMode:
ToggleDevMode()
run, "%A_ScriptFullPath%" "LastPost"
Return


OpenGiteaPage:
run, https://freedomain.dev/yuriy/video-uploader
Return



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

UpdateChrome:


if(CheckForChromeUpdates = "")
Status := CheckForChromeUpdates(ChromeFilepath)

if(!status){
	OnMessage(0x44, "OnMsgBoxConfirmChromiumOverwrite")
	MsgBox 0x41, Already Up-to-Date, Yor current Chromium version is already up to date. `nDo you want to download and overwrite it?
	OnMessage(0x44, "")

	IfMsgBox OK, {
		Return
		} Else IfMsgBox Cancel, {

		}
	}


	Status := DownloadLatestChromium()
	if(Status)
	GuiControl,,ChromeUpdateAvailable, Chrome Up-to-Dat


	Return
/*
*/



CreateDescriptionForSocialMedia(){
	SplitText = Free Documentaries:

	SocialMediaDescription := StrSplit(VideoDescription, SplitText)
	SocialMediaDescription := SocialMediaDescription[1]

	if(strlen(SocialMediaDescription) > 1400){
		SocialMediaDescription := SubStr(SocialMediaDescription, 1, 1400)
		SocialMediaDescription .= "..."
	}

	Return
}
; -------------------------------Upload Video Functionality-------------------------------
StartScript:
WinGetPos, XPosition, YPosition, , ,  A
IniWrite, %XPosition%, %SettingsIniFilepath%, General, XPosition
IniWrite, %YPosition%, %SettingsIniFilepath%, General, YPosition

Gui, Submit
Gui, Destroy




; Save Testing Mode Info
;------------------------------------------------
if(TestingMode){ ; save currently seelcted sites to ini file for next test
	; IniWrite, %Streamanity%, %SettingsIniFilepath%, Testing, Streamanity
	IniWrite, %BitChute%, %SettingsIniFilepath%, Testing, BitChute
	IniWrite, %OdyseeVideo%, %SettingsIniFilepath%, Testing, OdyseeVideo
	IniWrite, %OdyseeVideoThumb%, %SettingsIniFilepath%, Testing, OdyseeVideoThumb
	IniWrite, %OdyseeAudio%, %SettingsIniFilepath%, Testing, OdyseeAudio
	IniWrite, %OdyseeAudioThumb%, %SettingsIniFilepath%, Testing, OdyseeAudioThumb
	IniWrite, %Rumble%, %SettingsIniFilepath%, Testing, Rumble
	IniWrite, %Brighteon%, %SettingsIniFilepath%, Testing, Brighteon
	IniWrite, %DailyMotion%, %SettingsIniFilepath%, Testing, DailyMotion
	IniWrite, %Locals%, %SettingsIniFilepath%, Testing, Locals
	IniWrite, %Telegram%, %SettingsIniFilepath%, Testing, Telegram
	IniWrite, %Facebook%, %SettingsIniFilepath%, Testing, Facebook
}

; Save Video Info
;------------------------------------------------
; if changes made, delete the original file and save the new content to it

if(VideoTitle != OriginalVideoTitle){ 
	VideoTitleFilepath = %VideoFolderDir%\title.txt

	FileDelete, %VideoTitleFilepath%
	FileAppend, %VideoTitle%, %VideoTitleFilepath%
}


if(VideoTags != OriginalVideoTags){
	VideoTagsFilepath = %VideoFolderDir%\keywords.txt

	FileDelete, %VideoTagsFilepath%
	FileAppend, %VideoTags%, %VideoTagsFilepath%
}


if(PodcastTags != OriginalPodcastTags){
	PodcastTagsFilepath = %VideoFolderDir%\keywords_podcast.txt

	FileDelete, %PodcastTagsFilepath%
	FileAppend, %PodcastTags%, %PodcastTagsFilepath%
}

if(VideoDescription != OriginalVideoDescription){
	VideoBodyFilepath = %VideoFolderDir%\body.txt

	FileDelete, %VideoBodyFilepath%
	FileAppend, %VideoDescription%, %VideoBodyFilepath%
}



; -------------------------------/Save Video Info-------------------------------

; Save settings to config file
IniWrite, %ReuseTabs%, %SettingsIniFilepath%, General, ReuseTabs
IniWrite, %ShowTooltipProgress%, %SettingsIniFilepath%, General, ShowTooltipProgress
IniWrite, %AutoUpdateCheck%, %SettingsIniFilepath%, General, AutoUpdateCheck
IniWrite, %AutoLogin%, %SettingsIniFilepath%, General, AutoLogin
IniWrite, %PingOnCompletion%, %SettingsIniFilepath%, General, PingOnCompletion
IniWrite, %KillLBRYAfterUpload%, %SettingsIniFilepath%, General, KillLBRYAfterUpload


if(VideoFilepath = ""){
	Msgbox,4096,Error,No Video Filepath Found.`nPlease Input Video Filepath to Upload a Video.
	run, "%A_ScriptFullPath%" "LastPost"
	ExitApp
}

; 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)

; Save the LBRY URL Slug to .ini file in case it's needed later
IniWrite, %LBRYURLSlug%, %VideoLinksIniFile%, Misc, LBRYUrlSlug
IniWrite, %VideoThumbFilepath%, %VideoLinksIniFile%, Misc, VideoThumbFilepath
IniWrite, %PodcastNumber%, %VideoLinksIniFile%, Misc, PodcastNumber
IniWrite, %VideoThumbFilepath%, %VideoLinksIniFile%, Misc, VideoThumbFilepath



; -------------------------------Log Info To Text-------------------------------

(Facebook = 1)?(PostedWebsites .= "Facebook|") : ()
(Bitchute = 1)?(PostedWebsites .= "Bitchute|") : ()
(Locals = 1)?(PostedWebsites .= "Locals|") : ()
(Rumble = 1)?(PostedWebsites .= "Rumble|") : ()
(Brighteon = 1)?(PostedWebsites .= "Brighteon|") : ()
; (Streamanity = 1)?(PostedWebsites .= "Streamanity|") : ()
(Telegram = 1)?(PostedWebsites .= "Telegram|") : ()
(DailyMotion = 1)?(PostedWebsites .= "DailyMotion|") : ()
(OdyseeVideo = 1)?(PostedWebsites .= "OdyseeVideo|") : ()
(OdyseeAudio = 1)?(PostedWebsites .= "OdyseeAudio|") : ()


; Log Basic info to the errorlogging file
Message = %ScriptName% v%ScriptVersion%: Starting Upload `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")

; Convert Video Title and Description into javascript formatting for sending to pages through js instead of plain selenium
JSVideoTitle := FormatTextToJSText(VideoTitle) 
JSVideoDescription := FormatTextToJSText(VideoDescription) 

; -------------------------------/Log Info To Text-------------------------------


; 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

; Create an array out of the keywords to be used in different places
ArrayOfVideoTags := []
ArrayOfPodcastTags := []

; VIDEO Tags
For index, val in StrSplit(VideoTags, ",") {
	; 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 ]", "")
	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*)

; // Cleanup Tag Formatting
; ------------------------------------------------



; 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

if(OdyseeVideo){
	LBRYUploadType := "Video"
	Gosub, LBRYVideoUpload
}

if(OdyseeAudio){
	LBRYUploadType := "Audio"
	Gosub, LBRYAudioUpload
}

if(Rumble)
Gosub, RumbleUpload

if(Brighteon)
Gosub, BrighteonUpload

if(DailyMotion)
Gosub, DailyMotionUpload


; grab the LBRY Video/Audio URLs
if(OdyseeVideo){
	LBRYUploadType := "Video"
	Gosub, LBRYGetURL
}
if(OdyseeAudio){
	LBRYUploadType := "Audio"
	Gosub, LBRYGetURL
}

if(LocalsGrabURL){
	Gosub, LocalsGrabURL
}
; // Upload to Sites
; ------------------------------------------------




if(URLOfLastErrorPage != ""){
	Message = Activating Tab of last failed post.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip")

	; @todo: replaceme with working funciton to activate tab
	; FindAndActivateTab(URLOfLastErrorPage)
}

CurrentSite := ""

if(URLOfLastErrorPage)
Message = Video Uploading Finished WITH Some Failures
else, 
Message = All Videos Uploaded Successfully


if(PingOnCompletion)
Message = <@%DiscordUsernameID%>: %Message%
else, 
Message = %Message%

SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")



; Read Info for Results Window GUI
; ------------------------------------------------
DisplayResults:
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%
IniRead, TotalVideosUploaded, %SettingsIniFilepath%, General, TotalVideosUploaded, %A_Space%
; IniRead, StreamanityURL, %VideoLinksIniFile%, URLs, StreamanityURL, %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, FacebookURL, %VideoLinksIniFile%, URLs, FacebookURL, %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
; ------------------------------------------------
#include %A_scriptDir%\Modules\GUI-Results-Window.ahk

SaveCurrentChromeVersionToIniFile()

Return

OpenLBRYBlobFilesFolder:
try, 
run, C:\Users\%A_UserName%\AppData\Local\lbry\lbrynet\blobfiles
catch e {
	msgbox, Unable to open lbrynet blobfiles folder. `nIs LBRY installed?
}
Return

StartSocialMediaPoster:
; IniRead, SocialMediaPosterFilepath, %SettingsIniFilepath%, General, FDRRadioUN, %A_Space%
IniRead, SocialMediaPosterFilepath, %SettingsIniFilepath%, SocialMediaPoster, 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%, SocialMediaPoster, SocialMediaPosterFilepath

	}
	run, %SocialMediaPosterFilepath% "%VideoLinksIniFile%"
	Return

/*
*/


; Copy Info from GUI to Clipboard
; ------------------------------------------------
; @todo: this can be converted into 1 gosub, with if/else statements based on the button clicked

CopyPodcastNumber: 
Clipboard := PodcastNumber
SaveOrPostProgress(Message:=PodcastNumber "`nCopied to Clipboard",PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 1000
ToolTip
Return


CopyVideoTitle:
Clipboard := VideoTitle
SaveOrPostProgress(Message:=VideoTitle "`nCopied to Clipboard",PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 1000
ToolTip
Return

CopyBitChuteURL:
Clipboard := BitChuteURL
SaveOrPostProgress(Message:=BitChuteURL "`nCopied to Clipboard",PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 1000
ToolTip
Return

CopyBrighteonURL:
Clipboard := BrighteonURL
SaveOrPostProgress(Message:=BrighteonURL "`nCopied to Clipboard",PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 1000
ToolTip
Return

CopyDailyMotionURL:
Clipboard := DailyMotionURL
SaveOrPostProgress(Message:=DailyMotionURL "`nCopied to Clipboard",PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 1000
ToolTip
Return

CopyOdyseeVideoURL:
Clipboard := OdyseeVideoURL
SaveOrPostProgress(Message:=OdyseeVideoURL "`nCopied to Clipboard",PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 1000
ToolTip
Return

CopyOdyseeAudioURL:
Clipboard := OdyseeAudioURL
SaveOrPostProgress(Message:=OdyseeAudioURL "`nCopied to Clipboard",PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 1000
ToolTip
Return

CopyRumbleURL:
Clipboard := RumbleURL
SaveOrPostProgress(Message:=RumbleURL "`nCopied to Clipboard",PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 1000
ToolTip
Return


CopyVideoTags:
Clipboard := VideoTags
SaveOrPostProgress(Message:=VideoTags "`nCopied to Clipboard",PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 1000
ToolTip
Return

CopyPodcastTags:
Clipboard := PodcastTags
SaveOrPostProgress(Message:=PodcastTags "`nCopied to Clipboard",PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 1000
ToolTip
Return

CopyVideoDescription:
Clipboard := VideoDescription
SaveOrPostProgress(Message:="Video Description`nCopied to Clipboard",PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 1000
ToolTip
Return

; @todo: Add thumbnail status to this
; @todo: add podcast tags to this
UpdateINI:
IniWrite, %PodcastNumber%, %VideoLinksIniFile%, URLs, PodcastNumber
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

; LBRY/Odysee:
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
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

; Miscellaneous-Functions
;------------------------------------------------
#Include %A_ScriptDir%\Modules\Miscellaneous-Functions.ahk
