#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
if(InStr(A_ScriptFullPath, ".ahk")){
	try Menu, Tray, Icon, %A_ScriptDir%\Assets\FreedomainVideo.ico
}

PassedParameter = %1%

; Add menus to the toolbar icon
Menu, tray, NoStandard

Menu, Tray, Add, Exit, KillScript
Menu, Tray, Add, Pause, PauseScript

Menu, Tray, Add, Open New Project, ReloadScript
; Menu, Tray, Add, Restart to Last Project Upload Results, ReloadToResults ; @todo fix this as it currently just loads the last project
Menu, Tray, Add, Restart with Last Project, RetryUpload
Menu, Tray, Default, Restart with Last Project


global ScriptName
global ScriptVersion
global FullScriptName

ScriptName = Freedomain Video Uploader 
ScriptVersion = 3.1
FullScriptName := ScriptName . " - " . ScriptVersion



;---ToDo---
;------------------------------------------------
; @todo: Update Locals Share link grabbing

; @todo: finish show results functionality on line 430
; @todo: fix uploader saying there's been failures b/c there was no lbry audio upload
; @todo: finish telegram multi-message split functionality.
; @todo: add different icon when update is available
; @todo: fix telegram post getting cut off if too long instead of splitting into 2
; @todo: fix ping always saying that there was failures
; @todo: let user make last minute changes to text before submitting to telegram and discord
; @todo: replace all .Attribute("innerText") with js
; @todo: Fix locals not grabbing url if a post is pinned
; @todo: Add an input box for sources in the new frontend
; @todo: Fix bitchute title getting input twice
; @todo: Add login check for each website and ability to auto login
; @todo: ; add to statistics in statusbar - length of philosophy uploaded... total hours uploaded?

; @todo: add support for unauthorized.tv
; @todo: Bitchute has a 5k char limit for description as well. split description to remove reocurring bits and Add freedomainpodcasts.com/podcast/# link if still not big enough
; @todo: Split long discord/telegram messages into multiple messages
; @todo: Redo Discord posting with "PostErrors" function from social media poster
; @todo: Save updates made to GUi text to .ini file on changes
; @todo: add a SaveDriverURL() next to each RETURN in the code so reusable tabs can be grouped together

;---Global Variables---
;------------------------------------------------
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 ScreenshotResult

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 = 5000

; 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 ChangelogIniFilepath
ChangelogIniFilepath := A_ScriptDir . "\Lib\FreedomScriptsChangelogINI"

global ScriptSettingsSection
ScriptSettingsSection := "VideoUploader"


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


Message = Reading Settings from .ini files
; ToolTip, reading settings
SaveOrPostProgress(Message:=Message,PostType:="Tooltip")



IniRead, RootDirToStartIn, %SettingsIniFilepath%, General, RootDirToStartIn
IniRead, LogErrorsToMsgbox, %SettingsIniFilepath%, General, LogErrorsToMsgbox, %A_Space%
IniRead, UpdateAvailable, %SettingsIniFilepath%, %ScriptSettingsSection%, UpdateAvailable, 0
; Msgbox % "SettingsIniFilepath: " SettingsIniFilepath
; Msgbox % "UpdateAvailable: " UpdateAvailable
IniRead, DevMode, %SettingsIniFilepath%, General, DevMode, 0
IniRead, ScreenshotResult, %SettingsIniFilepath%, General, ScreenshotResult, 0
IniRead, TotalVideosUploaded, %SettingsIniFilepath%, General, TotalVideosUploaded, 0

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

IniRead, ReuseTabs, %SettingsIniFilepath%, General, ReuseTabs, 1
(ReuseTabs)?(ReuseTabsCheckStatus := 1) : (ReuseTabsCheckStatus := 0)

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

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

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")
}

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=
	SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
}

;---Auto Updater Settings---
;------------------------------------------------
global GitReleasesAPIURL
GitReleasesAPIURL = https://git.zinchuk.xyz/api/v1/repos/yuriy/Freedomain-Video-Uploader/releases

global GitReleasesLBRYKillerAPIURL
GitReleasesLBRYKillerAPIURL = https://git.zinchuk.xyz/api/v1/repos/yuriy/LBRY-Process-Killer/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---
;------------------------------------------------
; Ask user to select file within the production folder
if(PassedParameter = "LastPost"){
	IniRead, PassedParameter, %SettingsIniFilepath%, %ScriptSettingsSection%, LastPost, %A_Space%
}

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


; 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:="Starting Up: Moving Old Version",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
}
}


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
}


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

	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%\*.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
	}
}

; 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%\*.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 (If Any)---
;------------------------------------------------
; @todo: Figure out a way to do this with an array
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, ScreenShotSavePath, %VideoLinksIniFile%, Misc, ScreenShotSavePath, %A_Space%

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

}

; Create a directory for errorlogging and screenshots 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
	ScreenShotSavePath = %ErrorLoggingDirectory%

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

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



;---Testing Mode Overrides---
;------------------------------------------------
IniRead, TestingMode, %SettingsIniFilepath%, General, TestingMode, 0
if(TestingMode){ ; 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)
}


; @todo: DELETE
if(DevMode){
	; IniWrite, 0, %SettingsIniFilepath%, %ScriptSettingsSection%, UpdateAvailable
	; UpdateAvailable := 0
	; Menu, Tray, Add, Reload to Results, ReloadToResults

}
; Msgbox % "PassedParameter: " PassedParameter
; Msgbox % "PassedParameter: " PassedParameter
if(PassedParameter = "ShowResults"){
	msgbox, we are showing results
	goto, DisplayResults
}


;---GUI Variables---
;------------------------------------------------
GuiHeight = 800
GuiWidth = 1366
GuiFontSize = 10

ButtonHeights := 30

MarginSpace := 10
MarginSpaceDoubled := MarginSpace * 2

EditBoxWidths := (GuiWidth / 100) * 60
EditBoxHalfWidths := (EditBoxWidths / 2) - (MarginSpace / 2)
OdyseeURLSlugEditWidth := (EditBoxHalfWidths / 4) * 3

PodcastNumberTextXPos := EditBoxHalfWidths + OdyseeURLSlugEditWidth + (MarginSpace * 3)
PodcastNumberEditWidth := (EditBoxHalfWidths / 4) - MarginSpace

EditBoxOneFourthWidth := (EditBoxWidths / 4 )
EditBoxThreeFourthsWidth := (EditBoxWidths / 4 ) * 3


ColumnOneHalfWidthXPos := EditBoxHalfWidths + MarginSpaceDoubled

EditBoxThirdsWidths := (EditBoxWidths / 3) - (MarginSpace / 2)
OdyseeURLSlugXPos := EditBoxHalfWidths + (MarginSpace * 2)

EditBoxFourthWidths := (EditBoxWidths / 4) - (MarginSpace - 2)
VideoTagsTextXPos := EditBoxHalfWidths + (MarginSpace * 2)

; EditBoxHalfWidthsWithMargin := (EditBoxWidths / 2) 
DescriptionCharCountXPos := EditBoxWidths - 40

PageTwoXStartPos := EditBoxWidths + 50

CopyButtonWidths := 150
ResultEditBoxXPos := CopyButtonWidths + MarginSpace + 5
ResultEditBoxWidths := EditBoxWidths - CopyButtonWidths

ResultEditBoxHalfWidths := (ResultEditBoxWidths / 2) - (MarginSpace /2)
ResultLBRYURLEditBoxWidthPieces := (ResultEditBoxWidths / 4)
ResultLBRYURLEditBoxWidths := ResultLBRYURLEditBoxWidthPieces * 3

ResultEditBoxThirdsWidths := (ResultEditBoxWidths / 3) - (MarginSpace /3)


ResultLBRYThumbEditBoxWidth := ResultLBRYURLEditBoxWidthPieces - 5

ErrorLogEditBoxXPos := ResultEditBoxWidths + CopyButtonWidths + 30
ErrorLogEditBoxHeight := GuiHeight - (MarginSpace * 20) - (ButtonHeights * 2)
ErrorLogEditBoxWidth := GuiWidth - ErrorLogEditBoxXPos - (MarginSpace * 12)


ButtonWidths := 150
ButtonXPos := GuiWidth - ButtonWidths - 15

SubmitButtonYLocation := GuiHeight - 50
SubmitButtonXLocation := GuiWidth - 90
CancelButtonXLocation := GuiWidth - 180

EditBoxHeight := 25
ThumbnailPreviewWidth := 300
PageTwoGroupBoxWidth := ThumbnailPreviewWidth + 20

; Size of Description Edit Box and the location of the checkboxes underneath them
VideoDescriptionEditBoxHeight = 100
CheckboxesStartYPos := 630

FilePathEditBoxWidths := EditBoxWidths - MarginSpace - 70
SelectFileButtonWidths := 30

ButtonStartYPos := CheckboxesStartYPos + 10
MarginSquared := MarginSpace * 2

if(DevMode){
	MainButtonHeight := 30
	SecondaryButtonHeights := 30

}
else, {
	MainButtonHeight := 30
	SecondaryButtonHeights := 35
}




;---Check for Update---
;------------------------------------------------
if(AutoUpdateCheck AND !UpdateAvailable){
	; DevModeMsgBox("checking for updates")
	; msgbox, checkin for update 
	; DevModeMsgBox(GitReleasesAPIURL)
	UpdateAvailable := CheckForUpdates(GitReleasesAPIURL)
}

; DevModeMsgBox(AutoUpdateCheck)
; DevModeMsgBox(UpdateAvailable)


; -------------------------------GUI-------------------------------

Gui, Font, s%GuiFontSize%
Gui, Margin, %MarginSpace%, %MarginSpace%

; Video Title
Gui, Font, Bold
Gui, Add, Text,, Show Title
Gui, Add, Text, x%ColumnOneHalfWidthXPos% yp+0,Odysee URL Slug
Gui, Add, Text, x%PodcastNumberTextXPos% yp+0,Podcast #


Gui, Font, Normal
Gui, Add, Edit, y+5 x%MarginSpace% w%EditBoxHalfWidths% h%EditBoxHeight% gUpdateVars vVideoTitle, %VideoTitle%
Gui, Add, Edit, yp+0 x+%Marginspace% w%OdyseeURLSlugEditWidth% h%EditBoxHeight% gUpdateVars vLBRYURLSlug, %LBRYURLSlug%
Gui, Add, Edit, yp+0 x+%Marginspace% w%PodcastNumberEditWidth% h%EditBoxHeight% gUpdateVars vPodcastNumber, %PodcastNumber%

; LBRY URL
Gui, Font, Bold
Gui, Add, Text, x%Marginspace%,Video Tags
Gui, Add, Text,x%ColumnOneHalfWidthXPos% yp+0,Podcast Tags

Gui, Font, Normal
Gui, Add, Edit, x%Marginspace% Y+5 w%EditBoxHalfWidths% h%EditBoxHeight% gUpdateVars vVideoTags, %VideoTags%
Gui, Add, Edit, yp+0 x+%Marginspace% w%EditBoxHalfWidths% h%EditBoxHeight% gUpdateVars vPodcastTags, %PodcastTags%


/*; Podcast Number & Tags
Gui, Font, Bold
Gui, Add, Text,x%MarginSpace% y+%Marginspace%,Podcast Number

Gui, Font, Normal

*/
; Video Description
Gui, Font, Bold
if(NoOriginalVideoDescription)
Gui, Add, Text,cRed y+%Marginspace% x%Marginspace%,Video Description
else, 
Gui, Add, Text,y+%Marginspace% x%Marginspace%,Video Description: 
if(TestingMode){
	Gui, Add, Text,cRed yp+0 xp+150 ,TESTING MODE
}
if(DevMode){
	Gui, Add, Text,cRed yp+0 xp+150 ,DEV MODE
}
Gui, Font, Normal
Gui, Add, Edit,x%Marginspace% y+2 w%EditBoxWidths% h%VideoDescriptionEditBoxHeight% vVideoDescription gSubmitDescription,%VideoDescription%
gui, font, s8
Gui, font, Bold
if(DescriptionCharCount > 3000){
	Gui, Add, Edit,cRed w50 h20 x%DescriptionCharCountXPos% y+1 vDescriptionCharCount, %DescriptionCharCount%
}
else, 
Gui, Add, Edit, w50 h20 x%DescriptionCharCountXPos% y+1 vDescriptionCharCount, %DescriptionCharCount%
Gui, Font, Normal
Gui, Add,Text,  yp+3 xp-310, (Platform Char Limits: DM & Bitchute = 3K, Odysee,Brighteon = 5K)
Gui, Font, s%GuiFontSize%
Gui, font, Bold
Gui, Add, GroupBox,r8.5 x%MarginSpace% yp+10 w%EditBoxWidths% Center, Filepaths

; Video Filepath
Gui, Font, Bold
Gui, Add, Text,xp+5 yp+15,Video Filepath
Gui, Font, Normal
Gui, Add, Edit, x%MarginSquared% y+2 w%FilePathEditBoxWidths% h%EditBoxHeight% gUpdateVars vVideoFilepath,%VideoFilepath%
Gui, Add, Button, x+5 yp+0 h%EditBoxHeight% gSelectVideoFilepath, Select

; Video Thumbnail Filepath
Gui, Font, Bold
if(NoOriginalVideoThumbFilepath)
Gui, Add, Text, x%MarginSquared% CRed y+15,Video Thumbnail Filepath
else, 
Gui, Add, Text,y+15 x%MarginSquared% ,Video Thumbnail Filepath
Gui, Font, Normal
Gui, Add, Edit, x%MarginSquared% y+2 w%FilePathEditBoxWidths% h%EditBoxHeight% gUpdateVars vVideoThumbFilepath,%VideoThumbFilepath%
Gui, Add, Button, x+5 yp+0 h%EditBoxHeight% gSelectVideoThumbFilepath, Select
; WAV Audio File Filepath
Gui, Font, Bold
if(WavAudioFilepath = "")
Gui, Add, Text,cRed x%MarginSquared% y+15,WAV Filepath
else, 
Gui, Add, Text,x%MarginSquared% y+15,WAV Filepath
Gui, Font, Normal
Gui, Add, Edit, x%MarginSquared% y+2 w%FilePathEditBoxWidths% h%EditBoxHeight% gUpdateVars vWavAudioFilepath,%WavAudioFilepath%
Gui, Add, Button, x+5 yp+0 h%EditBoxHeight% gSelectWAVFilepath, Select

Gui, Font, Bold
if(MP3AudioFilepath = "")
Gui, Add, Text,cRed x%MarginSquared% y+15,Podcast MP3 Filepath
else, 
Gui, Add, Text,x%MarginSquared% y+15,Podcast MP3 Filepath
Gui, Font, Normal
Gui, Add, Edit, x%MarginSquared% y+2 w%FilePathEditBoxWidths% h%EditBoxHeight% gUpdateVars vMP3AudioFilepath,%MP3AudioFilepath%
Gui, Add, Button, x+5 yp+0 h%EditBoxHeight% gSelectMP3Filepath, Select


; Submit Button
Gui, Font, s%GuiFontSize%
gui, Font, Bold
if(DevMode)
Gui, Add, Button, x%MarginSpace% w%EditBoxHalfWidths% y+25 h%MainButtonHeight% gCancelPost hwndIcon, Close
else,
Gui, Add, Button, x%MarginSpace% w%EditBoxHalfWidths% y+25 h%MainButtonHeight% gCancelPost hwndIcon, Close

GuiButtonIcon(Icon, "imageres.dll", 208, "s20 a1 r2")
Gui, Add, Button, x+%MarginSpace% w%EditBoxHalfWidths% h%MainButtonHeight% gStartScript hwndIcon, Upload
GuiButtonIcon(Icon, "shell32.dll", 136, "s20 a1 r2")

if(DevMode)
Gui, Add, Button, x%MarginSpace% w%EditBoxFourthWidths% y+%Marginspace% h%SecondaryButtonHeights% gDisplayResults hwndIcon, View Results
else,
Gui, Add, Button, x%MarginSpace% w%EditBoxFourthWidths% y+%Marginspace% h%SecondaryButtonHeights% gDisplayResults hwndIcon, View Results
GuiButtonIcon(Icon, "shell32.dll", 210, "s30 a1 r2")

Gui, Add, Button, w%EditBoxFourthWidths% x+%Marginspace% h%SecondaryButtonHeights% gOpenProjectFolder hwndIcon, Open Project Folder
GuiButtonIcon(Icon, "shell32.dll", 267, "s30 a1 r2")


if(UpdateAvailable)
Gui, Add, Button, w%EditBoxHalfWidths% x+%Marginspace% gUpdateScript vUpdateAvailable h%SecondaryButtonHeights% hwndIcon,  Update Available - Click to Install
else, 
Gui, Add, Button, w%EditBoxHalfWidths% x+%Marginspace% gUpdateScript vUpdateAvailable h%SecondaryButtonHeights% hwndIcon, Program is Up-to-Date
; Gui, Add, Button, w%EditBoxHalfWidths% x+%Marginspace% vUpdateAvailable hwndIcon, Script is Up-to-Date
GuiButtonIcon(Icon, "shell32.dll", 239, "s30 a1 r2")

if(DevMode){
	Gui, Add, Button, x%MarginSpace% w%EditBoxFourthWidths% h30 y+5 h%SecondaryButtonHeights% gOpenErrorLog, Open ErrorLog
	Gui, Add, Button,  x+%MarginSpace% w%EditBoxFourthWidths% h30 h%SecondaryButtonHeights% gClearVideoLinks, Clear VideoLinks
	Gui, Add, Button, x+%MarginSpace% w%EditBoxFourthWidths% h30 h%SecondaryButtonHeights% gCompileScript, Compile
	Gui, Add, Button, x+%MarginSpace% w%EditBoxFourthWidths% h30 h%SecondaryButtonHeights% gUploadFiles, UploadWinscp

	Gui, Add, Button, x%MarginSpace% w%EditBoxFourthWidths% h30 y+5 h%SecondaryButtonHeights% gToggleTestingMode, Toggle TestingMode
	Gui, Add, Button,  x+%MarginSpace% w%EditBoxFourthWidths% h30 h%SecondaryButtonHeights% gToggleDevMode, Toggle DevMode

}



; -------------------------------Page 2 Side of Main GUI Window-------------------------------
LineSplitXPosition := PageTwoXStartPos - ( MarginSpace * 2)
gui, add, text, x%LineSplitXPosition% y20 h500 0x11 ; 0x11 is a "line"  ; refer to here: https://autohotkey.com/board/topic/50910-draw-line-gui/
; Thumbnail Preview
Gui, Font, Normal
gui, Font, s4
; Miscellaneous Settings
DevModToggleButton := PageTwoXStartPos + 160
Gui, Add, Button,  x%DevModToggleButton% y5 w50 h10  gToggleDevMode,DevMode
Gui, Add, Button,  x+5 y5 w50 h10  gToggleTestingMode, Testing Mode
Gui, Add, Button,  x+5 y5 w50 h10  gOpenGiteaPage, Gitea

Gui, Font, s%GuiFontSize%
Gui, Font, Bold
Gui, Add, GroupBox,r5 y+0 x%PageTwoXStartPos% w%PageTwoGroupBoxWidth%,Settings
; Gui, Add, Text, y%CheckboxesStartYPos% x+80, Miscellaneous Settings:
; Gui, Font, Normal
; Gui, Add, Checkbox, vIncludeDescriptionWhenPostingToVideos %IncludeDescriptionWhenPostingToVideos%, Include Description in #videos Posts
Gui, Add, Checkbox, xp+10 yp+20  vReuseTabs Checked%ReuseTabsCheckStatus% gUpdateVars, Try to Re-Use Tabs
Gui, Add, Checkbox, vShowTooltipProgress Checked%ShowTooltipProgressCheckStatus% gUpdateVars,Show Tooltip Progress
Gui, Add, Checkbox, vKillLBRYAfterUpload Checked%KillLBRYAfterUploadCheckStatus% ,Kill LBRY After Uploading
Gui, Add, Checkbox, vAutoUpdateCheck gUpdateVars Checked%AutoUpdateCheckCheckStatus%, Auto Update Check
Gui, Add, Checkbox, vPingOnCompletion gUpdateVars Checked%PingOnCompletionCheckStatus%, Discord Ping Upon Finish
; Gui, Add, Checkbox, vAutoUploadErrorLog gUpdateVars Checked%AutoUploadErrorLog%, Auto-Upload Large Errors


GroupBoxCheckboxPos := PageTwoXStartPos + MarginSpace

; -------------------------------PLATFORMS-------------------------------
Gui, Add, GroupBox,r8 y+15 x%PageTwoXStartPos% w%PageTwoGroupBoxWidth%, Platforms
; Gui, Add, Text,y+25 x%PageTwoXStartPos%, ---Platforms----
; Gui, Font, Bold


; Msgbox % "LocalsURL: " LocalsURL
if(LocalsURL = "LocalsUploadStartedNeedToGrabURL"){
	Gui, Add, Checkbox, xp+10 yp+25 vLocalsGrabURL Checked%LocalsCheckStatus%, Locals (Grab URL)
}
else, {
	Gui, Add, Checkbox, xp+10 yp+25 vLocals Checked%LocalsCheckStatus%, Locals
}
; if(VideoFileSizeInMB < 1792)
; Gui, Add, Checkbox, x+%MarginSpaceDoubled% vFacebook Checked%FacebookCheckStatus%, Facebook

Gui, Add, Checkbox, x%GroupBoxCheckboxPos% y+%MarginSpace% vBitChute Checked%BitChuteCheckStatus%, BitChute
if(VideoFileSizeInMB < 50) 
Gui, Add, Checkbox, vTelegram x+%MarginSpaceDoubled% Checked%TelegramCheckStatus%, Telegram


Gui, Add, Checkbox, x%GroupBoxCheckboxPos% y+%MarginSpace% vOdyseeVideo Checked%OdyseeVideoCheckStatus%, Odysee Video
; Gui, Add, Checkbox, x+%MarginSpace% vOdyseeVideoThumb Checked%OdyseeVideoThumbCheckStatus%,Thumbnail
Gui, Add, Checkbox, x%GroupBoxCheckboxPos% y+%MarginSpace% vOdyseeAudio Checked%OdyseeAudioCheckStatus%, Odysee Audio
; Gui, Add, Checkbox, x+%MarginSpace% vOdyseeAudioThumb Checked%OdyseeAudioThumbCheckStatus%, Thumbnail

Gui, Add, Checkbox, x%GroupBoxCheckboxPos% y+%MarginSpace% vRumble Checked%RumbleCheckStatus%, Rumble

Gui, Add, Checkbox, vBrighteon y+%MarginSpace% Checked%BrighteonCheckStatus%, Brighteon
Gui, Add, Checkbox, vDailyMotion y+%MarginSpace% Checked%DailyMotionCheckStatus%, DailyMotion
; Gui, Add, Checkbox, vStreamanity Checked%StreamanityCheckStatus%, Streamanity

; Gui, Font, s12
gui, Font, Bold
Gui, Add, GroupBox, r6.5 y+15 vImageThumbnail x%PageTwoXStartPos% w%PageTwoGroupBoxWidth%,Thumbnail
gui, Font, Normal
Gui, Add, Picture, xp+10 yp+20 w%ThumbnailPreviewWidth% h-1, %VideoThumbFilepath%


gui, Font, Normal
gui, font, s7
Gui, Add, StatusBar,Center, Total Videos Uploaded: %TotalVideosUploaded%
; SB_SetText("There are " . RowCount . " rows selected.")

; Show GUI to the user
Gui, +Resize +MaximizeBox
Gui, Show,, %FullScriptName% - Upload Settings - %BodyTextFilePath%
ControlFocus, Edit1, %FullScriptName%

ToolTip

; Gui, Maximize
; Gui, Show, w%GuiWidth% h%GuiHeight%, %ScriptName%

if(SkipToDBInfo){
	gui, submit
	goto, DisplayResults
}


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


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://git.zinchuk.xyz/yuriy/Freedomain-Video-Uploader
Return

CompileScript:
IniWrite, %changelog%, %ChangelogIniFilepath%, %ScriptSettingsSection%, Changelog
IniWrite, %ScriptVersion%, %ChangelogIniFilepath%, %ScriptSettingsSection%, ScriptVersion
IniWrite, %UpdateURL%, %ChangelogIniFilepath%, %ScriptSettingsSection%, UpdateURL

run, "C:\Users\yuriy\Syncthing\Freedomain\Uploaders\Lib\Releases\Compile Scripts to EXE.ahk" VideoUploader Production

; msgbox, this does nothign yet
Return

UploadFiles:
; @todo remove this
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)){
	; ToolTip, Thumbnail Copied to Project Folder, 850, 0
	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
; Changelog := FindUpdateChangeLog(ScriptUpdateFilepath)
Return

; now defunt, safe to remove
CreateDescriptionForVideosPosting:
; msgbox, here
Gui, VideoDescriptionTrimmer:New,
Gui, Font, s%GuiFontSize%
Gui, Add, Text,, Discord and Telegram have a maximum API post length of 2000 Characters `nwhich the curent description exceeds.`nPlease Trim down the description and then click submit.
Gui, Font, s%GuiFontSize%
Gui, Add, Edit, w800 h500 gUpdateVars vVideoDescriptionForVideosChannel, %VideoDescription%
Gui, Add, Button, gSubmitDescriptionForVideosChannel, Submit
gui, Show,w820, Video Description Trimmer
; msgbox
Return


SubmitDescriptionForVideosChannel:
Gui, Submit
; msgbox, submitted
if(CurrentSocialMediaPosting = "Discord")
Goto, SubmitDescriptionForDiscordVideosChannel
if(CurrentSocialMediaPosting = "Telegram")
Goto, SubmitDescriptionForTelegramVideosChannel
if(CurrentSocialMediaPosting = "Telegram Video")
goto, SubmitDescriptionForTelegramVideoUpload
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
; Msgbox % "XPosition: " XPosition
; Msgbox % "YPosition: " 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 Testing Mode Info---
;------------------------------------------------

; -------------------------------Save All Info .txt Files-------------------------------

/*; Msgbox % "NOOriginalVideoTitle: " NOOriginalVideoTitle
if(VideoTitleEmpty){
	; msgbox, appending title.
	FileAppend, %VideoTitle%, %VideoFolderDir%\title.txt
}
if(VideoDescriptionEmpty){
	; msgbox, appending description
	FileAppend, %VideoDescription%, %VideoFolderDir%\body.txt
}
if(VideoTagsEmpty){
	; msgbox, appending vieo tags
	FileAppend, %VideoTags%, %VideoFolderDir%\keywords.txt
}
if(PodcastTagsEmpty){
	; msgbox, appending vieo tags
	FileAppend, %VideoTags%, %VideoFolderDir%\keywords.txt
}
*/


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

; -------------------------------/Save All Info .txt Files-------------------------------

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

; Msgbox % "LBRYURLSlug: " 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



; -------------------------------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 = Starting Upload For: **%VideoTitle%**`nTo: %PostedWebsites%`nWith %ScriptVersion%
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 Description into javascript text format for sending to selenium
JSVideoDescription := FormatTextToJSText(VideoDescription) 
JSVideoTitle := FormatTextToJSText(VideoTitle) 

; Save json description to errorlogging file
; Message = JSVideoDescription: `n" %JSVideoDescription%
; SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")
; -------------------------------/Log Info To Text-------------------------------




; Create an array out of the keywords to be used in different places
VideoTags := StrReplace(VideoTags, ", ",",")
VideoTags := StrReplace(VideoTags, " ,",",")
VideoTags := StrReplace(VideoTags, " ",",")

KeywordsArray := StrSplit(VideoTags,",") 

; if(Streamanity){
	; UploadedToSites .= "Streamanity,"
	; Gosub, StreamanityUpload
	; }

	if(Facebook){
		UploadedToSites .= "Facebook,"
		gosub, FacebookUpload
	}

	if(Telegram){
		UploadedToSites .= "Telegram,"
		gosub, TelegramVideoUpload
	}

	; Call each sub one by one, if errors occur then an upload will be stopped and the next upload will then proceed
	if(Locals){
		UploadedToSites .= "Locals,"
		gosub, LocalsUpload
	}

	if(BitChute){
		UploadedToSites .= "Bitchute,"
		Gosub, BitChuteUpload
	}


	if(OdyseeVideo){
		UploadedToSites .= "LBRYVideo,"
		LBRYUploadType := "Video"
		Gosub, LBRYVideoUpload
	}
	if(OdyseeAudio){
		UploadedToSites .= "LBRYAudio,"
		LBRYUploadType := "Audio"
		Gosub, LBRYAudioUpload
	}

	if(Rumble){
		UploadedToSites .= "Rumble,"
		Gosub, RumbleUpload
	}

	if(Brighteon){
		UploadedToSites .= "Brighteon,"
		Gosub, BrighteonUpload
	}

	if(DailyMotion){
		UploadedToSites .= "DailyMotion,"
		Gosub, DailyMotionUpload

	}

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

	if(OdyseeVideoThumb){
		OdyseeUploadType := "Video"
		Gosub, OdyseeVideoThumbUpload
	}

	if(OdyseeAudioThumb){
		OdyseeUploadType := "Audio"
		Gosub, OdyseeAudioThumbUpload
	}

	if(LocalsGrabURL OR LocalsURL = "LocalsUploadStartedNeedToGrabURL"){
		Gosub, LocalsGrabURL
	}


	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(StreamanityURL AND StreamanityCheckStatus)

	; this feels soooooooooooooo ineficient, but i'm not sure how else to do this
	; if(StreamanityCheckStatus AND !InStr(StreamanityURL, "streamanity")) ; if checked and URL is blank, report error
	; Status := "Failures"
/*
if(URLOfLastErrorPage){
	Status := "Failures"
}
else, {
	Status := "Success"
}

	

	if(OdyseeVideoCheckStatus and !InStr(OdyseeVideoURL, "odysee"))
	Status := "Failures"
	else if(OdyseeAudioCheckStatus AND !InStr(OdyseeAudioURL, "odysee"))
	Status := "Failures"
	else if(BitChuteCheckStatus AND !InStr(BitChuteURL, "bitchute"))
	Status := "Failures"
	else if(RumbleCheckStatus AND !InStr(RumbleURL, "rumble"))
	Status := "Failures"
	else if(DailyMotionCheckStatus AND !InStr(DailyMotionURL, "dailymotion"))
	Status := "Failures"
	else if(BrighteonCheckStatus AND !InStr(BrighteonURL, "brighteon"))
	Status := "Failures"

	*/
	; DevModeMsgBox(status)
	; Msgbox % "status: " status

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

/*
if(StreamanityURL != "" AND OdyseeVideoURL != "" AND OdyseeAudioURL != "" and BitChuteURL != "" AND RumbleURL != "" and DailyMotionURL != "" and BrighteonURL != "")
Message = All Videos Uploaded Successfully
else, 
Message = Video Uploading Finished WITH Some Failures

*/


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

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


DisplayResults:
Gui, Destroy
; @todo: Add a way to check if uploads finished with or without errors
Tooltip ; Remove all tooltips
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
		}
	}
}


Gui, Font, s%GuiFontSize%
Gui, Font, Bold
; Gui, Add, Text,x10 y+10, Podcast #:
Gui, Add, Button, x10 y+%Marginspace% h%ButtonHeights% w%CopyButtonWidths% gCopyPodcastNumber, Podcast #
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0 h%ButtonHeights% w%ResultEditBoxWidths% gUpdateVars vPodcastNumber, %PodcastNumber%
; Gui, Add, Edit, x+5 h200 w200, This is some text that goes here!

; Gui, Add, Text,x10 y+20, Title:
; Gui, Font, Bold
; Gui, Add, Button, x10 y+%Marginspace% h%ButtonHeights% w%CopyButtonWidths% gCopyVideoTitle, Title
; Gui, Font, Normal
; Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% w%ResultEditBoxWidths% gUpdateVars vVideoTitle, %VideoTitle%
; Gui, Add, Button, x+1 w20, Copy Title


; Gui, Add, Text,x10 y+20, Bitchute:
Gui, Font, Bold
Gui, Add, Button, x10 y+%Marginspace% h%ButtonHeights% w%CopyButtonWidths% gCopyBitChuteURL, Bitchute
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% vBitChuteURL w%ResultEditBoxWidths% gUpdateVars , %BitChuteURL%
; Gui, Add, Edit, x+5 yp+0  w%ResultLBRYThumbEditBoxWidth% gUpdateVars, Facebook: %FacebookURL%

; Gui, Add, Button, x+1 w20, Copy BitChute

; Gui, Add, Text,x10 y+20, Brighteon:
Gui, Font, Bold
Gui, Add, Button, x10 y+%Marginspace% h%ButtonHeights% w%CopyButtonWidths% gCopyBrighteonURL, Brighteon
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% vBrighteonURL w%ResultEditBoxWidths% gUpdateVars , %BrighteonURL%

; Gui, Add, Text,x10 y+20, DailyMotion:
Gui, Font, Bold
Gui, Add, Button, x10 y+10 h%ButtonHeights% w%CopyButtonWidths% gCopyDailyMotionURL, DailyMotion
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% vDailyMotionURL w%ResultEditBoxWidths% gUpdateVars , %DailyMotionURL%

; Gui, Add, Text,x10 y+20, Odysee:
Gui, Font, Bold
Gui, Add, Button, x10 y+10 h%ButtonHeights% w%CopyButtonWidths% gCopyOdyseeVideoURL, Odysee Video
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% vOdyseeVideoURL w%ResultEditBoxWidths% gUpdateVars, %OdyseeVideoURL%
; Gui, Add, Button, x+5 yp+0, Thumb
; Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% vOdyseeVideoThumb w%ResultLBRYThumbEditBoxWidth% gUpdateVars, Thumb: %OdyseeVideoThumb%

Gui, Font, Bold
Gui, Add, Button, x10 y+10 h%ButtonHeights% w%CopyButtonWidths% gCopyOdyseeAudioURL, Odysee Audio
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% vOdyseeAudioURL w%ResultEditBoxWidths% gUpdateVars , %OdyseeAudioURL%
; Gui, Add, Button, x+5 yp+0, Thumb
; Gui, Add, Edit, x+5 yp+0  vOdyseeAudioThumb w%ResultLBRYThumbEditBoxWidth% gUpdateVars, Thumb: %OdyseeAudioThumb%

Gui, Font, Bold
Gui, Add, Button, x10 y+10 h%ButtonHeights% w%CopyButtonWidths% gCopyRumbleURL, Rumble
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% vRumbleURL w%ResultEditBoxWidths% gUpdateVars , %RumbleURL%

/*Gui, Font, Bold
Gui, Add, Button, x10 y+10 h%ButtonHeights% w%CopyButtonWidths% gCopyStreamanityURL, Streamanity
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% vStreamanityURL w%ResultEditBoxWidths% gUpdateVars , %StreamanityURL%

*/
Gui, Font, Bold
Gui, Add, Button, x10 y+10 h%ButtonHeights% w%CopyButtonWidths%, Locals
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% vLocalsURL w%ResultEditBoxWidths% gUpdateVars, %LocalsURL%

Gui, Font, Bold
Gui, Add, Button, x10 y+10 h%ButtonHeights% w%CopyButtonWidths% gCopyVideoTags, Video Tags
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% vVideoTags w%ResultEditBoxWidths% gUpdateVars , %VideoTags%

Gui, Font, Bold
Gui, Add, Button, x10 y+10 h%ButtonHeights% w%CopyButtonWidths% gCopyPodcastTags, Podcast Tags
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0  h%ButtonHeights% vPodcasttags w%ResultEditBoxWidths% gUpdateVars , %Podcasttags%

Gui, Font, Bold
Gui, Add, Button, x%Marginspace% y+10 h%ButtonHeights% w%CopyButtonWidths% gCopyVideoDescription, Description
Gui, Font, Normal
Gui, Add, Edit, x+5 yp+0  h50 vVideoDescription w%ResultEditBoxWidths% gUpdateVars , %VideoDescription%

Gui, Font, s%GuiFontSize%
Gui, Font, Bold
Gui, Add, Button, y+%MarginSpace% w%ResultEditBoxHalfWidths%gSendErrorLoggingThroughTelegram, Send Errorlog Through Telegram
Gui, Add, Button, x+%MarginSpace% w%ResultEditBoxHalfWidths%  gRetryUpload, Try Failed Again

Gui, Add, Button, x%ResultEditBoxXPos% w%ResultEditBoxHalfWidths% gUpdateINI, Update Project Files with Changes
Gui, Add, Button, x+%MarginSpace% w%ResultEditBoxHalfWidths% gUploadPodcast, Upload Podcast


Gui, Add, Button, x%ResultEditBoxXPos% y+%MarginSpace% w%ResultEditBoxThirdsWidths% gPostToDiscord vPostToDiscordButton, Post to Discord
Gui, Add, Button, x+5 w%ResultEditBoxThirdsWidths% gPostToTelegram vPostToTelegramButton, Post to Telegram 
Gui, Add, Button, x+5 w%ResultEditBoxThirdsWidths% gStartSocialMediaPoster, Start Social Media Poster


Gui, Add, Button, x%ResultEditBoxXPos% w%ResultEditBoxHalfWidths% gOpenLBRYBlobFilesFolder %ButtonWidths% , Open LBRY Blob Files Folder
Gui, Add, Button, x+%MarginSpace% w%ResultEditBoxHalfWidths% gCancelPost %ButtonWidths% , Close
; Gui, Add, Button, x+%MarginSpace% w%ResultEditBoxHalfWidths% gKillScript %ButtonWidths% , Close
; gui, Add, Text, y+10

Gui, Font, s%GuiFontSize%
Gui, Add, Button, x%ErrorLogEditBoxXPos% w%ErrorLogEditBoxWidth% y%MarginSpace% h%ButtonHeights%, Error Log
Gui, Add, Edit,x%ErrorLogEditBoxXPos% h%ErrorLogEditBoxHeight% w%ErrorLogEditBoxWidth% y+10, %ErrorLogVar%

gui, font, Normal
gui, font, s7
Gui, Add, StatusBar,, Total Videos Uploaded: %TotalVideosUploaded%
Gui, +Resize +MaximizeBox

OriginalVideoDescription := VideoDescription
OriginalPodcastTags := PodcastTags

Gui, Show,,%FullScriptName% - Upload Results

SaveCurrentChromeVersionToIniFile()

Return

OpenLBRYBlobFilesFolder:
run, C:\Users\%A_UserName%\AppData\Local\lbry\lbrynet\blobfiles
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, No Filepath 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
		if(ErrorLevel)
		Return

		; Msgbox % "SocialMediaPosterFilepath: " SocialMediaPosterFilepath
		; if(!InStr(SocialMediaPosterFilepath, ".ahk") OR !InStr(SocialMediaPosterFilepath, ".exe"))
		; Return

		} Else IfMsgBox Cancel, {
			Return
		}

		; IniRead, SocialMediaPosterFilepath, %SettingsIniFilepath%, SocialMediaPoster, SocialMediaPosterFilepath, %A_Space%
		IniWrite, SocialMediaPosterFilepath, %SettingsIniFilepath%, SocialMediaPoster, SocialMediaPosterFilepath
		; Return

	}
	; msgbox %SocialMediaPosterFilepath%
	run, %SocialMediaPosterFilepath% "%VideoLinksIniFile%"
	Return
	; Podcast Upload
	;------------------------------------------------

	UploadPodcast:
	CurrentSite := "Podcast"
	PodcastTags := StrReplace(PodcastTags, " ,", ",")
	PodcastTags := StrReplace(PodcastTags, ", ", ",")
	PodcastTags := StrReplace(PodcastTags, " ", "-")
	PodcastTags := StrReplace(PodcastTags, "--", "-")
	PodcastTags := StrReplace(PodcastTags, "--", "-")
	; Msgbox % "PodcastTags: " PodcastTags



	IniRead, FDRRadioURL, %SettingsIniFilepath%, General, FDRRadioURL, %A_Space%
	if(FDRRadioURL = ""){
		Message = FDRRadioURL is blank.`nPlease add URL to Settings.ini file under:`n`n[General]`nFDRRadioURL=
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		MsgBox 0x10,, %Message%
		Return
	}

	IniRead, Username, %SettingsIniFilepath%, General, FDRRadioUN, %A_Space%
	IniRead, Password, %SettingsIniFilepath%, General, FDRRadioPW, %A_Space%

	if(Username = "" or Password = ""){
		Message = Username and/or Password are blank.`nPlease add Login to Settings.ini file under:`n`n[General]`nFDRRadioUN=`nFDRRadioPW=
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	}


	if(MP3AudioFilepath = ""){
		MsgBox 0x33, Unable to Upload Podcast, No MP3 File Was Found/Selected. `nWould you like to select one now?

		IfMsgBox Yes, {
			FileSelectFile, MP3AudioFilepath,, %RootDirToStartIn%, Please Select MP3 File
			if(ErrorLevel)
			Return
			} Else IfMsgBox No, {
				Return
				} Else IfMsgBox Cancel, {
					Return
				}
			}

			if(!InStr(MP3AudioFilepath, ".mp3")){

				Message = Unable to upload podcast, no mp3 file was selected.
				MsgBox 0x40, Error, %Message%
				Return
			}


			Message = Grabbing MP3 file data
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")


			; https://www.autohotkey.com/boards/viewtopic.php?t=59882
			Message = Calculating MP3 File Size and Length
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

			Obj := Filexpro(MP3AudioFilepath,,
				, "Length" 
				, "Size" )    
			MP3AudioFilesize := obj["Size"]                                                     	
			MP3AudioLength := obj["Length"]                                                     	
			; MsgBox % obj["Size"]

			AudioLengthArray := StrSplit(MP3AudioLength,":")
			AudioLength_Hours := AudioLengthArray[1]
			AudioLength_Minutes := AudioLengthArray[2]
			AudioLength_Seconds := AudioLengthArray[3]
			; AudioLength_SecondsOriginal := AudioLength_Seconds
			; AudioLength_Seconds := (AudioLength_Minutes * 60) + ((AudioLength_Hours * 60) * 60) + AudioLength_Seconds

			; Msgbox % "AudioLength_Hours: " AudioLength_Hours
			; Msgbox % "AudioLength_Minutes: " AudioLength_Minutes
			; Msgbox % "AudioLength_Seconds: " AudioLength_Seconds
			; Msgbox % "AudioLength_SecondsOriginal: " AudioLength_SecondsOriginal

			FileGetSize, OutputVar, %MP3AudioFilepath%, K  ; Retrieve the size in Kbytes.
			FIlesizeInBytes := OutputVar * 1024


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




			Status := NavigateFromBaseURLTo(FDRRadioURL)
			if(Status){
				Message = Upload Failed (E#7295)`nUnable to Navigate to Upload Page`nChrome was closed or Internet down possibly?
				SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
				Return
			}

			Message = Logging in
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

			Xpath = //input[@id='email']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=Username)
			if(!Status){ ; if inputting email did NOT fail, then we are on the login page, input the password and then click login.
				Xpath = //input[@id='password']
				Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=Password)

				Xpath = //a[@id='loginButton']
				Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)

				driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding

				sleep, 2000

				try driver.Get(FDRRadioURL) ;Open selected URL
				catch e {
					Message = Upload Failed (E#7295)`nUnable to Navigate to Upload Page`nChrome was closed or Internet down possibly?
					SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")

				}
			}



			Message = Waiting for Page to Load
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

			Xpath = //input[@id='num']
			Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=60,SleepLength:=1000)
			if(Status){
				Message = New Podcast Page did not load after 60 seconds. Check Login Status
				SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
				Return
			}

			Message = Inputting Podcast Info
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

			; Click the "Is Active?" Checkbox
			Xpath = //input[@id='isActive']
			Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)

			; Input Podcast Number
			Xpath = //input[@id='num']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=PodcastNumber)

			; Input Podcast Title
			Xpath = //input[@id='title']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoTitle)

			; INput Audio URL
			Xpath = //input[@id='url-audio']
			SplitPath, MP3AudioFilepath, MP3AudioNameWithExt
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=MP3AudioNameWithExt)

			; INput thumbnail URL
			Xpath = //input[@id='url-thumbnail']
			SplitPath, VideoThumbFilepath, VideoThumbnailFilenameWithExt
			ThumbnailURL = https://cdn.freedomainradio.com/%VideoThumbnailFilenameWithExt%
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=ThumbnailURL)

			; Input BitChute URL
			Xpath = //input[@id='url-bitchute']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=BitChuteURL)

			; Input Brighteon URL
			Xpath = //input[@id='url-brighteon']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=BrighteonURL)

			; Input DailyMotion URL
			Xpath = //input[@id='url-dailymotion']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=DailyMotionURL)

			; Input LBRY URL
			Xpath = //input[@id='url-lbry']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=OdyseeVideoURL)

			; Input LBRY URL
			Xpath = //input[@id='url-locals']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=LocalsURL)

			; Input Rumble URL
			Xpath = //input[@id='url-rumble']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=RumbleURL)


			; Soundcloud but actually LBRY Audio URL
			Xpath = //input[@id='url-lbry-audio']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=OdyseeAudioURL)


			; INput filesize
			Xpath = //input[@id='fileSize']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=FIlesizeInBytes)

			; Msgbox % "FIlesizeInBytes2: " FIlesiz

			; ToolTip


			Xpath = //input[@id='lengthHours']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=AudioLength_Hours)

			Xpath = //input[@id='lengthMinutes']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=AudioLength_Minutes)

			Xpath = //input[@id='lengthSeconds']
			Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=AudioLength_Seconds)

			Message = Inputting Description
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

			Xpath = //textarea[@id='description']
			Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)

			; Input Description
			JSVideoDescription := FormatTextToJSText(VideoDescription) 

			js = document.getElementById('description').value = "%JSVideoDescription%";
			try driver.executeScript(js)    ;Executes a Javascript on the webpage, mostly used for buttons.


			Message = Inputting Tags
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

			Podcasttags := StrReplace(Podcasttags, " , ", ",")
			Podcasttags := StrReplace(Podcasttags, " ,", ",")
			Podcasttags := StrReplace(Podcasttags, ", ", ",")

			ArrayOfPodcastTags := StrSplit(Podcasttags,",")
			LengthOfArrayOfPodcastTags := ArrayOfPodcastTags.Length()	; Save total number of items in the array

			try pagehtml := driver.pagesource
			; Msgbox % "pagehtml: " pagehtml
			Loop, %LengthOfArrayOfPodcastTags% {
				Tag := ArrayOfPodcastTags[A_Index]	; find value from position in array

				SpanID = title">%Tag%</span></div></li><li><div id="_easyui_tree_

				if(InStr(pagehtml, SpanID)){ ; if tag found in page, do this
					number := StrSplit(pagehtml, SpanID)
					Number := Number[2]
					; Msgbox % "number: " number

					var = " class=
					Number := StrSplit(Number, var)

					Number := Number[1]
					; Msgbox % "Grabbed Number from page source: " Number
					Number := Number - 1

					Message = Tag: %Tag% is tag number %number% in the list.
					SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

					if(number = "" or Number < 0){
						Message = Tag Number for "%tag%" is blank or less than 0. Skipping.
						SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
						Continue
					}

					Xpath = //div[@id='_easyui_tree_%number%']//span[@class='tree-checkbox tree-checkbox0']
					Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)

				}
				else, { ; otherwise input the tag and click the plus button. It will automatically get checked when the plus button is clicked
					Xpath = //input[@id='tagSearch']
					Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=Tag)

					Xpath = //a[@id='addPodcastTagInPodcastEdit']
					Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)

					Loop, 10 {
						Xpath = //input[@id='tagSearch']

						try CurrentValue := driver.findelementbyxpath(Xpath).Attribute("value") ;XPath: ID=site-title & span tag
						if(CurrentValue != "")
						{
							sleep, 1000
							Continue
						}
						break ; otherwise break out of the loop
					}
				}
			}

			; Message = Podcast Upload Complete
			; msgbox,4096, Done., Input Done.`n`nPlease confirm input and click the final "Save" button.

			; ToolTip,
/*
OnMessage(0x44, "OnMsgBoxPodcastFinish")
MsgBox 0x40, Finished!,  Input Complete!`n`nPlease confirm input and click the final "Save" button on the page.
OnMessage(0x44, "")

*/
Message = Input Complete! `nPlease Confirm and click Final "Save" Button on Podcast Page
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

sleep, 5000

CurrentSite := 
ToolTip
Return


; -------------------------------Telegram-------------------------------
PostToTelegram:
CurrentSocialMediaPosting := "Telegram"
Message = Posting Video Links to Telegram
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

IniRead, TelegramBotToken, %SettingsIniFilepath%, SocialMediaPoster, TelegramBotToken, %A_Space%
IniRead, TelegramBotChatID, %SettingsIniFilepath%, SocialMediaPoster, TelegramBotChatID, %A_Space%


LineBreakChar = `%0A ; Used for Telegram API

if(TelegramBotToken = "" Or TelegramBotChatID =""){
	Message = TelegramBotToken or TelegramBotChatID is missing from %SettingsIniFilepath%. `nPlease input them and click the button again.
	msgbox, 4096, Error!, %Message%
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	; Msgbox, 4096, Error!, TelegramBotToken or TelegramBotChatID is missing from %SettingsIniFilepath%. `nPlease input them and rerun the script.
	Return
}

/*
; If description is longer than 2k chars, then API will error out. goto section that will allow user to edit video description to shorten it for posting
if(StrLen(SocialMediaDescription) > 2000 AND VideoDescriptionForVideosChannel = ""){
	goto, CreateDescriptionForVideosPosting
}
*/
/*
if(SocialMediaDescription = ""){
	CreateDescriptionForSocialMedia()
}
if(SocialMediaDescription > 1000){	; Telegram has a 1024 char media caption capacity
	SocialMediaDescription := SubStr(SocialMediaDescription, 1, 500)
}
*/
; @todo: split telegram message into multiple posts


SubmitDescriptionForTelegramVideosChannel:
TelegramVideoTitle := ASCIISTRReplace(VideoTitle)
TelegramVideoTitle := "*" . TelegramVideoTitle . "*"

TelegramBodymessage := ASCIISTRReplace(VideoDescription)


LineBreakChar = `%0A ; Used for API

if(BitChuteURL != "")
VideoLinks .= "[BitChute](" . BitChuteURL . ") \| "

if(BrighteonURL != "")
VideoLinks .= "[Brighteon](" . BrighteonURL . ") \| "

if(OdyseeVideoURL != "")
VideoLinks .= "[Odysee](" . OdyseeVideoURL .  ") \| "

if(OdyseeAudioURL != "")
VideoLinks .= "[Odysee \(Audio\)](" . OdyseeAudioURL . ") \| "
/*
if(OdyseeVideoURL != "")
VideoLinks .= "[Odysee](" . OdyseeVideoURL .  ") \| "

if(OdyseeAudioURL != "")
VideoLinks .= "[Odysee Audio](" . OdyseeAudioURL . ") \| "

*/
if(RumbleURL != "")
VideoLinks .= "[Rumble](" . RumbleURL . ") \| "
/*
if(InStr(StreamanityURL, "https://streamanity.com/video/"))
VideoLinks .= "[Streamanity](" . StreamanityURL . ") \| "

*/
if(DailyMotionURL != "")
VideoLinks .= "[DailyMotion](" . DailyMotionURL . ") \| "


TelegramMessage := TelegramVideoTitle . "`n" . TelegramBodymessage . "`n" . VideoLinks



StrLenOfMessageAndVideoLinks := StrLen(TelegramVideoTitle) + StrLen(TelegramBodymessage) + StrLen(VideoLinks)
; DevModeMsgBox(StrLenOfMessageAndVideoLinks)


if(StrLenOfMessageAndVideoLinks > 1024){
	; Telegram SendMessage is limited to 4096 characters
	if(StrLenOfMessageAndVideoLinks < 4096){ ; split into sendphoto and 1 sendmessage
		; DevModeMsgBox("Less than 4096 chars")
		; Photo and Video Title go into SendPhoto
		TelegramVideoTitle := TelegramVideoTitle . "`n" . VideoLinks
		Status := SendTelegramPhoto(TelegramBotToken, TelegramBotChatID, VideoThumbFilepath, caption := TelegramVideoTitle )       ; you could add more options; compare the Telegram API docs
		
		; Video Description goes into TelegramMessage
		Status2 := SendTelegramMessage(TelegramBotToken, TelegramBotChatID, text := TelegramBodymessage)

		} ; split into 2 SendMessages
		else if (StrLenOfMessageAndVideoLinks > 4096 AND StrLenOfMessageAndVideoLinks < 8192){ ; Split into 2 parts
			TelegramVideoTitle := TelegramVideoTitle . "`n" . VideoLinks
			Status := SendTelegramPhoto(TelegramBotToken, TelegramBotChatID, VideoThumbFilepath, caption := TelegramVideoTitle )       ; you could add more options; compare the Telegram API docs

			TelegramBodymessagePiece := SubStr(TelegramBodymessage, 1, 4096)
			Status2 := SendTelegramMessage(TelegramBotToken, TelegramBotChatID, text := TelegramBodymessagePiece)

			TelegramBodymessagePiece := SubStr(TelegramBodymessage, 4097, 8192)
			Status3 := SendTelegramMessage(TelegramBotToken, TelegramBotChatID, text := TelegramBodymessagePiece)

			} ; split into 3 sendMessages
			else if (StrLenOfMessageAndVideoLinks > 8192 AND StrLenOfMessageAndVideoLinks < 12288){ ; Split into 3 parts
				TelegramVideoTitle := TelegramVideoTitle . "`n" . VideoLinks
				Status := SendTelegramPhoto(TelegramBotToken, TelegramBotChatID, VideoThumbFilepath, caption := TelegramVideoTitle )       ; you could add more options; compare the Telegram API docs

				TelegramBodymessagePiece := SubStr(TelegramBodymessage, 1, 4096)
				msgbox % StrLen(TelegramBodymessagePiece)
				Status2 := SendTelegramMessage(TelegramBotToken, TelegramBotChatID, text := TelegramBodymessagePiece)



				TelegramBodymessagePiece := SubStr(TelegramBodymessage, 4097, 8192)
				msgbox % StrLen(TelegramBodymessagePiece)
				DevModeMsgBox(TelegramBodymessagePiece)
				Status3 := SendTelegramMessage(TelegramBotToken, TelegramBotChatID, text := TelegramBodymessagePiece)

				; TelegramBodymessagePiece := SubStr(TelegramBodymessage, 8193, 12288)
				; Status3 := SendTelegramMessage(TelegramBotToken, TelegramBotChatID, text := TelegramBodymessagePiece)
			}


			} else, { ; if less than 1024 characters, send normally
				Status := SendTelegramPhoto(TelegramBotToken, TelegramBotChatID, VideoThumbFilepath, caption := TelegramMessage )       ; you could add more options; compare the Telegram API docs
				if(InStr(Status, "error_code")){
					Message = Telegram Post Failed due to an API Issue. Error was saved to ErrorLogging file. Please send it to Yuriy.
					SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")

					; SaveOrPostProgress(Message:=Status,PostType:=",ErrorLoggingTextFile")
					Message = Telegram Error: %Status%
					SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")

					ToolTip
					Return
				}

			}
			; Msgbox % "SizeOfCaption: " SizeOfCaption
			; SizeOfCaption := SizeOfCaption + 
			; Message .= VideoLinks
			; msgbox % StrLen(VideoLinks)

			; Message := StrReplace(Message, "`n", LineBreakChar) ; replace all new line characters with the global charater

			; msgbox % StrLen(Message)


			; SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,DiscordVideos")

			; SaveOrPostProgress(Message:="Video Links posted to #Videos Successfully.",PostType:="Tooltip,ErrorLoggingTextFile")
			Message = Video Links Posted to Telegram Successfully
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
			GuiControl,, PostToTelegramButton, Telegram - Posted Successfully


			; sleep, 2000


			ToolTip
			CurrentSite := 
			Return
			; -------------------------------/Telegram-------------------------------



			; -------------------------------Discord-------------------------------
			PostToDiscord:
			CurrentSocialMediaPosting := "Discord"
			Message = Posting Video Links to Discord
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")


			IniRead, DiscordVideosWebhookURL, %SettingsIniFilepath%, General, DiscordVideosWebhookURL, %A_Space%
			if(DiscordVideosWebhookURL = ""){
				Message = Unable to Grab DiscordVideosWebhookURL from %SettingsIniFilepath%.`nPlease input the URL and then try again.
				SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
				Msgbox, Unable to Grab DiscordVideosWebhookURL from %SettingsIniFilepath%.`nPlease input the URL and then try again.
				Return
			}

/*
; If description is longer than 2k chars, then API will error out. goto section that will allow user to edit video description to shorten it for posting
if(StrLen(SocialMediaDescription) > 2000 AND VideoDescriptionForVideosChannel = ""){
	Goto, CreateDescriptionForVideosPosting
}

*/
if(SocialMediaDescription = ""){
	CreateDescriptionForSocialMedia()
}

; Msgbox % "SocialMediaDescription: " SocialMediaDescription

SubmitDescriptionForDiscordVideosChannel:
Message := "**" . VideoTitle . "**"  . "`n" . SocialMediaDescription . "`n"
; https://stackoverflow.com/questions/63160401/how-to-create-hyperlink-in-discord-in-an-embed-in-general
; Do this with an array!!
; 

if(BitChuteURL != "")
Message .= "[BitChute](<" . BitChuteURL . ">) \| "

if(BrighteonURL != "")
Message .= "[Brighteon](<" . BrighteonURL . ">) \| "

if(OdyseeVideoURL != "")
Message .= "[Odysee](<" . OdyseeVideoURL .  ">) \| "

if(OdyseeAudioURL != "")
Message .= "[Odysee (Audio)](<" . OdyseeAudioURL . ">) \| "
/*
if(OdyseeVideoURL != "")
Message .= "[Odysee](<" . OdyseeVideoURL .  ") \| "

if(OdyseeAudioURL != "")
Message .= "[Odysee Audio](<" . OdyseeAudioURL . ") \| "

*/
if(RumbleURL != "")
Message .= "[Rumble](<" . RumbleURL . ">) \| "

/*if(StreamanityURL != "" AND InStr(StreamanityURL, "streamanity.com"))
Message .= "[Streamanity](<" . StreamanityURL . ">) \| "

*/
if(DailyMotionURL != "")
Message .= "[DailyMotion](<" . DailyMotionURL . ">)"


UploadImageToDiscord(DiscordVideosWebhookURL, Message, VideoThumbFilepath)



SaveOrPostProgress(Message:="Video Links posted to #Videos Successfully.",PostType:="Tooltip,ErrorLoggingTextFile")
GuiControl,, PostToDiscordButton, Discord - Posted Successfully

sleep, 2000
ToolTip
; Msgbox,,Success,Video Links posted to #Videos Successfully.
; ToolTip
Return
; -------------------------------/Discord-------------------------------





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

/*CopyStreamanityURL:
Clipboard := StreamanityURL
SaveOrPostProgress(Message:=StreamanityURL "`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, %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

IniWrite, %LocalsURL%, %VideoLinksIniFile%, URLs, LocalsURL

IniWrite, %RumbleURL%, %VideoLinksIniFile%, URLs, RumbleURL
; IniWrite, %StreamanityURL%, %VideoLinksIniFile%, URLs, StreamanityURL
IniWrite, %DailyMotionURL%, %VideoLinksIniFile%, URLs, DailyMotionURL
IniWrite, %BrighteonURL%, %VideoLinksIniFile%, URLs, BrighteonURL
IniWrite, %BitChuteURL%, %VideoLinksIniFile%, URLs, BitChuteURL



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:
Message = Uploading Errorlog to FDRBotTesting Telegram Server.
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")


; Credentials to FDRBotTesting Channel
IniRead, TelegramErrorLogBotToken, %SettingsIniFilepath%, General, TelegramErrorLogBotToken, %A_Space%
IniRead, TelegramErrorLogBotChatID, %SettingsIniFilepath%, General, TelegramErrorLogBotChatID, %A_Space%


if(TelegramErrorLogBotToken = "" or TelegramErrorLogBotChatID = ""){
	Message = TelegramErrorLogBotToken and/or TelegramErrorLogBotChatID are blank. Please add them to Settings.ini under: `n`n[General]`nTelegramErrorLogBotToken=`nTelegramErrorLogBotChatID=
}


Status := SendTelegramFile(TelegramErrorLogBotToken, TelegramErrorLogBotChatID, ErrorLoggingFilePath, caption := "" )
if(InStr(Status, "error_code")){
	Message = Telegram Post Failed due to an API Issue. Error was saved to ErrorLogging file. Please send it manually.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")

	; SaveOrPostProgress(Message:=Status,PostType:=",ErrorLoggingTextFile")
	Message = Telegram Error: %Status%
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")

	; msgbox, 4096, Error!, %Message%
	ToolTip
	Return
}
ToolTip
Message = ErrorLog was successfully uploaded to the FDRBotTesting Telegram Server.`nThank You!
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")

sleep, 5000
ToolTip
; msgbox, 4096, Success!, %Message%

; Clipboard := ErrorLoggingFilePath
; Message = %ErrorLoggingFilePath% `n`nwas copied to the clipboard for easy attachment
; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
; msgbox, 4096, Filepath Copied to Clipboard, %ErrorLoggingFilePath%`n`nwas copied to the clipboard for easy attachment.
Return 



;--------------Locals----------------------------------
LocalsUpload:
CurrentSite := "Locals"


SaveOrPostProgress(Message:="Navigating to Post Creation Page",PostType:="Tooltip,ErrorLoggingTextFile")
; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

IniRead, LocalsPostPageURL, %SettingsIniFilepath%, General, LocalsPostPageURL, %A_Space%
if(LocalsPostPageURL = ""){
	Message = LocalsURL is blank.`nPlease add Locals URL to Settings.ini file under:`n`n[General]`nLocalsPostPageURL=
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}

if(!InStr(LocalsPostPageURL, "/share/post")){
	LocalsPostPageURL .= "/share/post"
}

; replace any double slashes that migth have come from the combining
; LocalsPostPageURL := StrReplace(LocalsPostPageURL, "//", "/")


Status := NavigateFromBaseURLTo(LocalsPostPageURL)
if(Status = "Failed")
Return

/*
if(DevMode){
	MsgBox 0x4, DevMode Skip, Skip uploading section and skip straight to grab URL?

	IfMsgBox Yes, {
		goto, Devmodeskip
		} Else IfMsgBox No, {

		}
	}

	*/


	Message = Waiting for Page to fully load
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
	Xpath = //textarea[@id='body']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=10,SleepLength:=1000)
	if(Status){
		Message = Page did not load after 10 seconds. Force stopping refresh and trying to continue
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

		send, {Escape} ; Temporary workaround, as Page seems to endlessly load for Stef

		Xpath = //textarea[@id='body']
		Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)
		if(Status){
			SaveOrPostProgress(Message:="Post Failed: Check Login Status, or Website is Down",PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
			; TakeScreenshotOfPage(ScreenShotSavePath)

			Return
		}
	}

	Message = Inputting Title
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

	Xpath = //input[@id='title']
	Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000,StringTextContent:=VideoTitle)
	if(Status){
		Message = Failed to input Title
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	}

	sleep, 1000

/*Xpath = //textarea[@id='body']
Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000,StringTextContent:=VideoDescription)
if(Status){
	Message = Failed to input Body
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
}
*/

; Input Description
TooltipThis("Inputting Description")
Loop, 5 { ; Attempt to input video description a couple of times


	if(A_index = 5){
		Clipboard := VideoDescription
		Message = Unable to Input Video Description`nDescription copied to clipboard, please paste it in at your earliest convenience. 
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
		Return
	}

	js = document.getElementsByName('body')[0].value = "%JSVideoDescription%";  ; Send content through javascript (Great for getting around emoji chrome limitaitons)
	try driver.executeScript(js)    ;Executes a Javascript on the webpage, mostly used for buttons.

	; msgbox 
	try driver.findElementsByName("body").item[1].SendKeys(driver.Keys.SPACE)
	; driver.findElementsByID("ELEMENTID").item[1].SendKeys(driver.Keys.ENTER)
	; msgbox

	jsCheck = return document.getElementsByName('body')[0].value;  ; Send content through javascript (Great for getting around emoji chrome limitaitons)
	try Description := driver.executeScript(jsCheck)    ;Executes a Javascript on the webpage, mostly used for buttons.


	; try Description := driver.findElementsByName("body").item[1].Attribute("value") ;XPath: ID=site-title & span tag
	if(Description != "")
	Break
	sleep, 2000
}

SaveOrPostProgress(Message:="Waiting Video to finish uploading",PostType:="Tooltip,ErrorLoggingTextFile")
Message = Uploading Video File
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
Xpath = //div[@class='uploadvideo-wrapper']//input[@name='Filedata']
Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoFilepath)
if(Status){
	Message = Failed to Upload Video
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}


; check if the "Auto Submit Post" checkbox is checked, and if not check it
js = return document.querySelector("#autosubmit_enabled").checked;
try AutoSubmitstatus := driver.executeScript(js)
; DevModeMsgBox(status)
; message = AutoSubmitstatus: %AutoSubmitstatus%
; DevModeMsgBox(message)

if(AutoSubmitstatus = "0"){
	js = document.querySelector("li[id='autosubmit_container'] small").click() ; ; CHECK YES
	try driver.executeScript(js)    ; DevModeMsgBox(status)

	; double check that it got selected
	js = return document.querySelector("#autosubmit_enabled").checked;
	try AutoSubmitstatus := driver.executeScript(js)

	Message = AutoSubmitstatus after clicking checkbox: %AutoSubmitstatus%
	DevModeMsgBox(message)

	if(AutoSubmitstatus != "-1"){
		Message = Failed to check Auto-Submit Post checkbox
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
		; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	}
}


DevModeMsgBox("autosubmit status -1 string here")
; msgbox % AutoSubmitstatus = "-1"
if(AutoSubmitstatus = "-1"){ ; if checked YES

	; check that there are no error messages
	js = return document.querySelector("div[class='form-error']").textContent; 
	try status := driver.executeScript(js)
	; DevModeMsgBox(status)
	if(status){ ;if element contains error text
		Message = Auto Publish failed: %status%
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}


	if(VideoThumbFilepath){
		Message = Uploading Thumbnail
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
		Xpath = //div[contains(@class,'post-video-attachments post-video-attachments_upd')]//div[contains(@class,'uploadfile-wrapper')]//input[contains(@name,'Filedata')]
		Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoThumbFilepath)
		if(Status){
			Message = Failed to Attach Thumbnail
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
			Return
		}
	}

	; otherwise everything is good and we can move on to the next site and come back to grab the URL later
	; LocalsURL := "UploadedButNeedToGrabLink"
	; Return


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

	LocalsURL := "LocalsUploadStartedNeedToGrabURL"
	; Msgbox % "LocalsURL: " LocalsURL
	IniWrite, %LocalsURL%, %VideoLinksIniFile%, URLs, LocalsURL
	AddToTotalVideosUploadedCount()

	; Msgbox % "LocalsURL: " LocalsURL
	; Msgbox % "VideoLinksIniFile: " VideoLinksIniFile
; 
	; FileRead, inicontents, %VideoLinksIniFile% ; , Filename
	; Msgbox % "inicontents: " inicontents

	; IniWrite, Value, Filename, Section, Key

	; LocalsTabURL := SaveDriverURL()

	Return
}
Return



;--------------\Locals----------------------------------





;--------------LocalsGrabURL----------------------------------
LocalsGrabURL:

SaveOrPostProgress(Message:="Navigating to Locals Feed to grab URL",PostType:="Tooltip,ErrorLoggingTextFile")
; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

IniRead, LocalsPostPageURL, %SettingsIniFilepath%, General, LocalsPostPageURL, %A_Space%
if(LocalsPostPageURL = ""){
	Message = LocalsURL is blank.`nPlease add Locals URL to Settings.ini file under:`n`n[General]`nLocalsPostPageURL=
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}

if(InStr(LocalsPostPageURL, "/share/post")){
	LocalsFeedPageURL := StrReplace(LocalsPostPageURL, "/share/post", "")
}


Status := ActivateChromeTab(LocalsPostPageURL)
if(Status = "Failed"){
	Message = Failed to Activate Locals Tab. Please grab URL manually
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return 
}
; Msgbox % "Status: " Status


try currentpageURL := driver.url
if(InStr(currentpageURL,"share/post")){ ; we're still on create new post page
Message = Locals is still on the Create New Post page. Please double check if post was published successfully.
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
SaveDriverURLOFErrorPage()
Return
}


; otherwise we should be on locals.com home feed page
; check for "Retrieve Draft button"
js = return document.querySelector("a[class='btn']").innerText; 
try, status := driver.executeScript(js)
if(status){
	Message = Video was uploaded but Locals saved it as a draft instead of instantly publishing it. Please go to the Locals Page and Retrieve Draft and manually Publish it.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}



; Get word that's longer than 4 characters in video title
VideoTitleArray := StrSplit(VideoTitle, " ")
; Iterate from 1 to the end of the array:
Loop % VideoTitleArray.Length(){
	VideoTitleFirstWord := VideoTitleArray[A_Index]
	VideoTitleFirstWord := StrReplace(VideoTitleFirstWord, "_","-")
	if(StrLen(VideoTitleFirstWord) > 4)
	Break

	; MsgBox % VideoTitleArray[A_Index]

}


loop, 7 {
	ElementIndexNum := A_index - 1
	Message = ElementIndexNum: %ElementIndexNum%
	DevModeMsgBox(Message)
	; Msgbox % "ElementIndexNum: " ElementIndexNum


	jscheck = return document.getElementsByClassName('post-bottom')[%ElementIndexNum%].outerHTML;
	try outerHTML := driver.executeScript(jsCheck)

	if(DevMode){
		Message = Looking for VideoTitleFirstWord: %VideoTitleFirstWord% `nwithin outerHTML
		DevModeMsgBox(message)
		Clipboard := outerHTML
		DevModeMsgBox(outerHTML)
	}


	; msgbox % "outerHTML: " . outerHTML

	if(InStr(OuterHTML,VideoTitleFirstWord)){
		; @todo replace with regex
		Message = %VideoTitleFirstWord% is in`n`n %OuterHTML%
		DevModeMsgBox(Message)

		Message = Found at at index: %A_index%
		DevModeMsgBox(message)
		; MsgBox, found match at %A_index%


		DevModeMsgBox("Pulling out url from outerhtml")

		ShareLink := StrSplit(OuterHTML, "data-url=")
		ShareLink := ShareLink[2]

		DevModeMsgBox(ShareLink)
		; Msgbox % "ShareLink: " ShareLink

		URLEndString = ">
		ShareLink := StrSplit(ShareLink, URLEndString)
		ShareLink := ShareLink[1]
		DevModeMsgBox(ShareLink)

		QuotationMark = "
		ShareLink := StrReplace(ShareLink,QuotationMark, "")
		DevModeMsgBox(ShareLink)
		Break
	}

	ShareLink :=
}

DevModeMsgBox(ShareLink)

; ShareLink := "Successful"

Message = Upload Complete: %ShareLink%
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")


IniWrite, %ShareLink%, %VideoLinksIniFile%, URLs, LocalsURL
AddToTotalVideosUploadedCount()

SaveDriverURL()
; TakeScreenshotOfPage(ScreenShotSavePath)


Return



;--------------/LocalsGrabURL----------------------------------







; GetLocals
; Xpath = //div[@class='uppy-StatusBar-statusPrimary']

; sleep, 30000 ; wait 30 seconds
; sleep, 2000 

/*; Attach Custom Thumbnail
if(VideoThumbFilepath != ""){
	Message = Attaching Custom Thumbnail
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

	Xpath = //div[@class='custom-thumb-uploader']//input[@name='Filedata']
	Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoThumbFilepath)

	if(Status){
		Message = Failed to Attach Custom Thumbnail
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	}

}

*/


sleep, 10000 
Loop, %Number_of_loops_to_Check_Upload_status% {
	sleep, %Time_Between_Loops_Upload_Status%

	jscheck = return document.getElementsByClassName('uppy-StatusBar-statusPrimary')[0].textContent;
	try UploadStatus := driver.executeScript(jsCheck)

	; UploadStatus := StrSplit(UploadStatus, ": ")
	; UploadStatus := UploadStatus[2]


	; message = Waiting for Video To Finish Uploading. `nCurrent Status: %UploadStatus%
	; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")


	; Clipboard := jsCheck
	; msgbox % "textContent: " . textContent


	/*	try UploadStatus := driver.findelementbyxpath(Xpath).Attribute("innerText") ; Grabb innertext
		catch e {
			if(A_index = 1){
				Message = Unable to find Progress Upload Percentage. Upload Most Likely Failed.
				SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
			}
			else, 
			Break
		}
		*/

		if(InStr(UploadStatus, "100%")){
			Message = Video Upload Complete. Waiting 20 seconds for Video to finalize before submitting.
			sleep, 20000
			break
		}

		; if(UploadStatus != ""){
			; 	Message = 
			; 	sleep, 30000 ; 30 seconds
			; 	Continue

			; }

			if(UploadStatus = "" and A_index = 1){
				Message = Upload Failed. Unable to Grab Upload Status
				SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
				SaveDriverURLOFErrorPage()
				Return
			}

			; if(UploadStatus = ""){
				; Break
				; }


				Status := Check_For_Stuck_Video_Upload(A_index, UploadStatus)
				if(Status = "Failed")
				Return
			}

	/*; attach custom thumbnail
	xpath = //label[normalize-space()='Upload Custom Video Thumbnail']
	Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoThumbFilepath)
	if(Status){
		Message = Failed to Attach Thumbnail
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		; SaveDriverURLOFErrorPage()
		; Return
	}
	Status := InputFilePathIntoOpenWindow(VideoThumbFilepath)

	*/

	; DevModeMsgBox("pause")

	; Click the publish button
	js = document.getElementsByName('submitPost')[0].click();
	try driver.executeScript(js)  


	Message = Waiting 5 seconds for Video to Get Processed
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
	sleep, 5000


	try currentpage := driver.url
	if(CUrrentpage = LocalsPostPageURL){
		Message = Final page is same as post page. Please double check if post was published successfully.
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}
	; sleep, 500
	; ToolTip
	; AddToTotalPostsPostedCount()


	Devmodeskip:

	Message = Trying to Grab Share Link
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")


	; refresh page
	try driver.executeScript("history.go(0)")
	try driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding

	; check for "Retrieve Draft button"
	js = return document.querySelector("a[class='btn']").innerText; 
	try, status := driver.executeScript(js)
	if(status = "Retrieve Draft"){
		Message = Video was uploaded but Locals saved it as a draft instead of instantly publishing it. Please go to the Locals Page and Retrieve Draft and manually Publish it.
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}



	; Get word that's longer than 4 characters in video title
	VideoTitleArray := StrSplit(VideoTitle, " ")
	; Iterate from 1 to the end of the array:
	Loop % VideoTitleArray.Length(){
		VideoTitleFirstWord := VideoTitleArray[A_Index]
		VideoTitleFirstWord := StrReplace(VideoTitleFirstWord, "_","-")
		if(StrLen(VideoTitleFirstWord) > 4)
		Break

		; MsgBox % VideoTitleArray[A_Index]

	}

	; DevModeMsgBox(VideoTitleFirstWord)

	; Message = VideoTitleFirstWord: %VideoTitleFirstWord%
	; SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")

	; VideoTitleFirstWord := VideoTitleFirstWord[1]
	; Msgbox % "VideoTitleFirstWord: " VideoTitleFirstWord

/*	; Format the post title to remove all spaces and special characters to match with Locals Post
	ShareLinkFormatted := StrReplace(VideoTitle, " ", "-")
	ShareLinkFormatted := StrReplace(ShareLinkFormatted, "?", "")
	ShareLinkFormatted := StrReplace(ShareLinkFormatted, "!", "")
	ShareLinkFormatted := StrReplace(ShareLinkFormatted, ".", "")
	ShareLinkFormatted := StrReplace(ShareLinkFormatted, "", "")
	ShareLinkFormattedFirst5Chars := SubStr(ShareLinkFormatted, 1, 5)

	*/

	

	LocalsBaseURL := StrReplace(LocalsURL, "/share/post", "")
	; Msgbox % "LocalsPostPageURL: " LocalsPostPageURL
	; Msgbox % "LocalsURL: " LocalsURL
	; Msgbox % "LocalsBaseURL: " LocalsBaseURL
	loop, 5 {
		ElementIndexNum := A_index - 1
		DevModeMsgBox(ElementIndexNum)
		; Msgbox % "ElementIndexNum: " ElementIndexNum


		jscheck = return document.getElementsByClassName('post-bottom')[%ElementIndexNum%].outerHTML;
		try outerHTML := driver.executeScript(jsCheck)

		; Clipboard := outerHTML
		; DevModeMsgBox(outerHTML)
		
		; msgbox % "outerHTML: " . outerHTML

		if(InStr(OuterHTML,VideoTitleFirstWord)){

			Message = %VideoTitleFirstWord% is in %OuterHTML%
			; DevModeMsgBox(Message)

			; MsgBox, found match at %A_index%




			ShareLink := StrSplit(OuterHTML, "data-url=")
			ShareLink := ShareLink[2]
			; DevModeMsgBox(ShareLink)
			; Msgbox % "ShareLink: " ShareLink

			URLEndString = ">
			ShareLink := StrSplit(ShareLink, URLEndString)
			; ShareLink := ShareLink[1]

			QuotationMark = "
			ShareLink := StrReplace(ShareLink,QuotationMark, "")

			Break
		}

		ShareLink :=
	}

	DevModeMsgBox(ShareLink)

	; ShareLink := "Successful"

	Message = Upload Complete: %ShareLink%
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")


	IniWrite, %ShareLink%, %VideoLinksIniFile%, URLs, LocalsURL
	AddToTotalVideosUploadedCount()

	SaveDriverURL()
	; TakeScreenshotOfPage(ScreenShotSavePath)


	Return

	; 
	;------------------/Locals------------------------------

	; 
	;--------------------Telegram----------------------------
	TelegramVideoUpload:

	if(VideoFileSizeInMB > 50){
		Message = Telegram Upload Skipped. Video is larger than 50MB
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}

	CurrentSocialMediaPosting := "Telegram Video"
	Message = Uploading Video to Telegram
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

	IniRead, TelegramBotToken, %SettingsIniFilepath%, SocialMediaPoster, TelegramBotToken, %A_Space%
	IniRead, TelegramBotChatID, %SettingsIniFilepath%, SocialMediaPoster, TelegramBotChatID, %A_Space%


	LineBreakChar = `%0A ; Used for Telegram API

	SaveOrPostProgress(Message:="Posting to Telegram",PostType:="Tooltip,ErrorLoggingTextFile")

	if(TelegramBotToken = "" Or TelegramBotChatID =""){
		Message = TelegramBotToken or TelegramBotChatID is missing from %SettingsIniFilepath%. `nPlease input them and click the button again.
		msgbox, 4096, Error!, %Message%
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		; Msgbox, 4096, Error!, TelegramBotToken or TelegramBotChatID is missing from %SettingsIniFilepath%. `nPlease input them and rerun the script.
		Return
	}


	; If description is longer than 2k chars, then API will error out. goto section that will allow user to edit video description to shorten it for posting
	if(StrLen(SocialMediaDescription) > 2000){
		TelegramVideoUploadDescription := SubStr(SocialMediaDescription, 1, 990)
		TelegramVideoUploadDescription .= "...."
		; msgbox, here goes
		; Goto, CreateDescriptionForVideosPosting
	}


	SubmitDescriptionForTelegramVideoUpload:
	TelegramVideoTitle := ASCIISTRReplace(VideoTitle)

	TelegramBodymessage := ASCIISTRReplace(TelegramVideoUploadDescription)

	LineBreakChar = `%0A ; Used for API


	Message := "*" . TelegramVideoTitle . "*" . LineBreakChar . TelegramBodymessage . LineBreakChar

	Message := StrReplace(Message, "`n", LineBreakChar) ; replace all new line characters with the global charater

	; Msgbox % "Message: " Message

	Status := SendTelegramVideo(TelegramBotToken, TelegramBotChatID, VideoFilepath, caption := Message )       ; you could add more options; compare the Telegram API docs
	if(InStr(Status, "error_code")){
		Message = Telegram Post Failed due to an API Issue. Error was saved to ErrorLogging file. Please send it to Yuriy.
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")

		; SaveOrPostProgress(Message:=Status,PostType:=",ErrorLoggingTextFile")
		Message = Telegram Error: %Status%
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")

		ToolTip
		Return
	}
	; msgbox


	Message = Upload Complete to Telegram
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	IniWrite, Successful, %VideoLinksIniFile%, Misc, Telegram
	; SaveDriverURL()
	AddToTotalVideosUploadedCount()

	Return

	; -------------------------------BitChute-------------------------------
	BitChuteUpload:
	CurrentSite := "Bitchute"

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


	Status := NavigateFromBaseURLTo("https://www.bitchute.com/myupload", "BitChute Video Uploader")
	if(Status){
		Message = Upload Failed (E#7295)`nUnable to Navigate to Upload Page`nChrome was closed or Internet down possibly?
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}



	Message = Uploading Video
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
	; sleep, 5000

	; Try to input video title and if fail try to login again
	loop, 2 {
		Xpath = //input[@id='title']
		Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=1,SleepLength:=1000,StringTextContent:=VideoTitle)

		if(!Status)
		Break

		; Try to login
		Message = Checking Login Status
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
		Xpath = //input[@id='id_username']
		Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=1,SleepLength:=1000)
		if(!Status){
			Xpath = //button[normalize-space()='Submit']
			Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)

			Message = Waiting for Upload Page to Load
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip")
			try driver.executeScript("return document.readyState").equals("complete") 
			sleep, 5000
			Continue
		}
		
	}


	; DevModeMsgBox("stop")
	
	; BitchuteDescription := SubStr(VideoDescription, 0, 2995) . "..."
	; JSBitchuteDescription := FormatTextToJSText(BitchuteDescription) 

	BitchuteDescription := VideoDescription
	if(StrLen(BitchuteDescription) > 2995){
		BitchuteDescription := SubStr(BitchuteDescription, 1, 2995)
		JSBitchuteDescription := FormatTextToJSText(BitchuteDescription) 
	}
	else, 
	JSBitchuteDescription := FormatTextToJSText(BitchuteDescription) 

	Message = Inputting Description
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
	Loop, 10 { ; Attempt to input video description a couple of times
		LogErrorToTextFile("Inputting Description")

		; Input text
		; try BitChuteUploadProgress := driver.executeScript("return document.getElementsByClassName('progress-bar')[0].innerHTML;") ;navigate using javascript 
		; send text to page
		; jsSend = document.getElementsByClassName('form-control')[1].value = "%JSBitchuteDescription%";
		
		jsSend = document.getElementById('description').value = "%JSBitchuteDescription%"; 
		; try driver.executeScript(js)   

		; Check text in the box
		jsCheck = return document.getElementById('description').value;

		; send text to the page
		try driver.executeScript(jsSend)  
		
		; check contents of page
		try VideoDescriptionOnPage := driver.executeScript(jsCheck)    ;Executes a Javascript on the webpage, mostly used for buttons.

		if (A_index = 1){
			message := SubStr(VideoDescriptionOnPage, 1, 250)
			message = Bitchute Inputted description: %message% 
			SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile,DiscordErrorLogging")
		}

		if(VideoDescriptionOnPage = ""){
			Message = Failed to input Video Description
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
			SaveDriverURLOFErrorPage()
			Return
		}

	}


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

	; Convert tags into #hasthtags
	Loop, 3 {
		Value := KeywordsArray[A_Index]
		Value := StrReplace(Value, " ", "") ; Remove spaces if hashtag has two words
		; HashTag := "#" . Value
		BitchuteHashtags .= Value . " "
	}

	; input hashtags
	Xpath = //input[@placeholder='Search Terms']
	Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=BitchuteHashtags)

	; Upload Thumbnail
	Message = Attaching Thumbnail
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

	if(VideoThumbFilepath != ""){
		; Upload Cover Image Button
		Message = Uploading Thumbnail
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")


		Xpath = //input[@name='thumbnailInput']
		Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoThumbFilepath)
		if(Status){
			Message = Failed to Attach Thumbnail
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
			SaveDriverURLOFErrorPage()
			Return
		}
		; sleep, 5000
	}

	; Upload Video button
	Xpath = //input[@name='videoInput']
	Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoFilepath)
	if(Status){
		Message = Failed to Upload Video
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}


	Message = Waiting for Video to Finish Uploading`nChecking Progress Every 5 seconds
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
	Xpath = //div[@role='progressbar'] ; Xpath to progress %
	Loop, %Number_of_loops_to_Check_Upload_status% {
		sleep, %Time_Between_Loops_Upload_Status%

		if(A_index = 5){ ; while waiting for bitchute video to finish uploading, start up lbry
			if(OdyseeVideo OR OdyseeAudio){
				SaveOrPostProgress(Message:="Starting up LBRY while waiting for Bitchute Video to finish uploading",PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
				CheckLBRYProcess()
			}
		}
		; Selenium
		; try BitChuteUploadProgress := driver.findelementbyxpath(Xpath).Attribute("innerText") ;GREAT FOR GRABBING INNER CONTENTS/Values

		try BitChuteUploadProgress := driver.executeScript("return document.querySelector('.filepond--file-status').innerHTML;") ;navigate using javascript 
		; Msgbox % "BitChuteUploadProgress: " BitChuteUploadProgress

		if(BitChuteUploadProgress = ""){
			Message = Unable to Grab Upload Progress, Upload Possibly Failed
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
			SaveDriverURLOFErrorPage()
			Return
		}

		if(InStr(BitChuteUploadProgress, "Upload complete")){
			Message = Waiting 10 Seconds before clicking "Proceed" button
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
			sleep, 10000
			Break ; Break out of the loop when 100% upload status

		}

		; split_text = ">
		; Pull out upload percentage
		BitChuteUploadProgress := StrSplit(BitChuteUploadProgress, ">")
		BitChuteUploadProgress := BitChuteUploadProgress[2]
		BitChuteUploadProgress := StrSplit(BitChuteUploadProgress, "</span")
		BitChuteUploadProgress := BitChuteUploadProgress[1]
		; DevModeMsgBox(BitChuteUploadProgress)

		Status := Check_For_Stuck_Video_Upload(A_index, BitChuteUploadProgress)
		if(Status = "Failed")
		Return
	}

	try UploadPageURL := driver.url ; save the active URL to a variable

	; Finish Uploading Button
	Xpath = //button[normalize-space()='Proceed']  ; Finish button
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=10,SleepLength:=5000)
	if(Status){
		Message = Failed to Click "Finish" button
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	}
	; try driver.FindElementByXPath(Xpath).click()    ;Try to click on the "Finish" button

	; Error Popup Location if something goes wrong.
	Xpath = /html/body/div[2]/div
	try BitChuteError := driver.findelementbyxpath(Xpath).Attribute("innerText") ; Grabb innertext


	TooltipThis("Waiting for video page to finish loading")
	try driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding

	; Loop for 2 minutes and keep checking if the active page has moved on to the video page

	Message = Waiting 30 Seconds Before Refreshing Page to Find Newest Video
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

	Loop, 6 { ; 6 loops X 30 seconds
		sleep, 5000 
		try CurrentWindow := driver.URL
		if(CurrentWindow != UploadPageURL AND A_index = 6) ; could also check for: https://www.bitchute.com/channel in str
		Break

		if(A_index = 6){
			Message = Upload Likely Failed: Videos Page did not Appear after 2 minutes
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
			SaveDriverURLOFErrorPage()
			Return
		}
	}

	try driver.executeScript("history.go(0)") ;refresh page 


	try FirstResultVideoTitle := driver.findElementsByClass("channel-videos-title").item[1].Attribute("innerText") ; Grabb innertext

	; msgbox % FirstResultVideoTitle = VideoTitle

	try FirstResultIDAndTag := driver.findElementsByClass("channel-videos-title").item[1].Attribute("outerHTML") ;XPath: ID=site-title & span tag
	; Msgbox % "FirstResultIDAndTag: " FirstResultIDAndTag
	VideoHref := StrSplit(FirstResultIDAndTag, "<a href=")[2]
	VideoHref := StrSplit(VideoHref, " class=")[1]
	SingleQuote = "
	VideoHref := StrReplace(VideoHref, SingleQuote, "")

	if(VideoHref = ""){
		Message = Failed to Grab Video URL. Please Copy and Paste it into Result Window
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}

	BitChuteURL := "https://www.bitchute.com/" . VideoHref

	; navigate to video page
	try driver.Get(BitChuteURL)	;Open selected URL
	driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding


	Xpath = //a[@data-toggle='tab'][normalize-space()='Settings']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=15,SleepLength:=5000)
	if(Status){
		Message = Failed to Navigate to Video Settings Page to Uncheck "Allow Comments"
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	}


	; Unclick the "Discussion Allowed on This Video" checkbox
	js = document.querySelector("form[id='save-settings'] div div label span").click()
	try driver.executeScript(js)

	try Status := driver.findElementsByID("id_is_discussable").item[1].isSelected()
	Message = Checked Status = %Status%`n-1 is checked. 0 is unchecked
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")


	; Click the save button
	Xpath = //button[normalize-space()='Save']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)

	Message = Upload Complete:`n%BitChuteURL%
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	IniWrite, %BitChuteURL%, %VideoLinksIniFile%, URLs, BitChuteURL

	SaveDriverURL()
	AddToTotalVideosUploadedCount()
	; TakeScreenshotOfPage(ScreenShotSavePath)


	Return
	; -------------------------------/BitChute Upload-------------------------------




	; -------------------------------Brighteon Upload-------------------------------
	BrighteonUpload:

	CurrentSite := "Brighteon"
	SaveOrPostProgress(Message:="Starting Upload",PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	URLAttempt := NavigateFromBaseURLTo("https://www.brighteon.com/dashboard/video-upload")
	if(URLAttempt = "Failed")
	Return
	; try driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding



	JSBrighteonVideoDescription := FormatTextToJSText(VideoDescription)
	; Msgbox % "JSBrighteonVideoDescription: " JSBrighteonVideoDescription

	; descriptions longer than 5k characters just fail to get input so trim them to below 5000 characters
	if(StrLen(VideoDescription) >= 5000){
		BrighteonVideoDescription := SubStr(VideoDescription, 1, 4800)
		BrighteonVideoDescription .= "...."
		JSBrighteonVideoDescription := FormatTextToJSText(BrighteonVideoDescription) 

		if(StrLen(JSBrighteonVideoDescription) > 5000){
			BrighteonVideoDescription := SubStr(VideoDescription, 1, 4500)
			BrighteonVideoDescription .= "...."
			JSBrighteonVideoDescription := FormatTextToJSText(BrighteonVideoDescription) 
		}
	}

/*; Closing any popups that might appear
loop, 3 {
Xpath = //body/div[@id='__next']/div[@id='modal-root']/div/div/div[1] ; get our free newsletter
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=1,SleepLength:=1000)

; try driver.FindElementByXPath(Xpath).click()

; If newsletter pop up exists then close it.
Xpath = //div[@class='overlay__close inside']
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=1,SleepLength:=1000)


}
*/


Message = Checking Login Status
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
try CurrentTab := driver.url
if(InStr(CurrentTab, "login")) ; we're logged out
{

	Message = Closing out of any popups that might appear on loin page
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
	
	Xpath = //body/div[@id='__next']/div[@id='modal-root']/div[2]/div[1]/div[1]//*[local-name()='svg']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=1,SleepLength:=100)

	Xpath = //body/div[@id='__next']/div[@id='modal-root']/div/div/div[1] ; get our free newsletter
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=1,SleepLength:=100)

	; If newsletter pop up exists then close it.
	Xpath = //div[@class='overlay__close inside']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=1,SleepLength:=100)

	; Try clicking the login button, sometimes this will auto log you back in without having to input credentials
	xpath = //a[normalize-space()='Log In']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=1,SleepLength:=100)
	DevModeMsgBox(Status)


	Message = Checking Login Status
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

	try PageURL := driver.url
	if(InStr(PageURL, "auth.brighteon.com/login?state")){ ; we're logged out and need to manually log back in


	if(AutoLogin){
		Message = Trying to Log Back In
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

		js = return document.querySelector("input[placeholder='username/email']").value;
		status := try driver.executeScript(JS)			;Execute Javascript

		if(StrLen(Status) > 0){
			; msgbox, clicking login button
			Xpath = //a[normalize-space()='Log In'] ; click login button
			Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=6,SleepLength:=1000) 

			sleep, 2000
			Xpath = //button[@type='submit'] ; click login button on login page
			Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)
			try driver.executeScript("return document.readyState").equals("complete") 

			sleep, 2000
		}


	}
	else, {
		SaveOrPostProgress(Message:="Login Expired. Please log back in",PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}
}
}



; Navigate to Upload Page 
try driver.executeScript("window.location = 'https://www.brighteon.com/dashboard/video-upload'") ;navigate using javascript 

try driver.executeScript("return document.readyState").equals("complete") 

; Click out of the "Support free speech" pop-up if it pops up
Xpath = //body/div[@id='__next']/div[@id='modal-root']/div/div/div[1]//*[local-name()='svg']
try driver.FindElementByXPath(Xpath).click()

; Upload Video
Xpath = //input[@type='file']
Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoFilepath)
if(Status){
	Message = Failed to Upload Video, Please check Login Status
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}

; Input Title of the Video
Xpath = /html/body/div/section[2]/div[2]/div/form/div[1]/div[1]/div[2]/div[1]/div/input
try driver.FindElementByXPath(Xpath).SendKeys(VideoTitle)     ;Sends Variable to an Xpath Item


TooltipThis("Inputting Video Description")

; sleep, 5000
; @todo this doesn't do anything anymore.
; DevModeMsgBox("rework me here")
; Xpath = //textarea[@id='description']
; try, driver.FindElementByXPath(XPATH).SendKeys(driver.Keys.SPACE)

; sleep, 1000


; Attempt to input video description a couple of times
Loop, 10 {
	Message = Inputting Description. `nAttempt Number: %A_index%
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	; SaveOrPostProgress(Message:=Message,PostType:="DiscordErrorLogging")

	; SaveOrPostProgress(Message:="Inputting Video Description",PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar")
	; TooltipThis("Inputting Description)

	Xpath = //div[@class='e-content e-lib e-keyboard']
	Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoDescription)
	if(Status){
		SaveOrPostProgress(Message:="Failed to input Video Description",PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}

	; DevModeMsgBox("pause")

	; driver.FindElementByXPath(Xpath).SendKeys(VideoDescription)

	; js = document.getElementById('description').value = "%JSBrighteonVideoDescription%"; 
	; try driver.executeScript(js)   


	; sleep, 1000
	; TooltipThis("checking description input")
	; try driver.findElementsByID("description").item[1].SendKeys(driver.Keys.ENTER)
	; sleep, 1000

	sleep, 5000


	js = return document.querySelector("div[class='e-content e-lib e-keyboard'] p").innerText;
	try Input_Description := driver.executeScript(JS)            ;Execute Javascript

	; if text in description box is longer than x chars, then description input worked
	if(StrLen(Input_Description) > 15){
		Input_Description := SubStr(Description, 1, 200)
		Message = Description that got input: %Input_Description% ...
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
		Break
	}

}



; Thumbnail 
if(VideoThumbFilepath != "") {
	TooltipThis("Uploading Thumbnail")
	Xpath = //input[@type='file']
	Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoThumbFilepath)
	if(Status){
		Message = Failed to Upload Thumbnail
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	}
}


; Keywords (Tags)
; DevModeMsgBox(VideoTags)
TooltipThis("Inputting Keywords")
XPath = //input[@id='keywords']
try driver.FindElementByXPath(Xpath).SendKeys(VideoTags)     ;Sends Variable to an Xpath Item
catch e {
	Message = Error (E#2312)`nVideo Uploaded but Unable to Input Video Tags
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
}


; double check on video description after inputting tags
js = return document.querySelector("div[class='e-content e-lib e-keyboard'] p").innerText;
try Input_Description := driver.executeScript(JS)            ;Execute Javascript
DevModeMsgBox(Input_Description)

; if text in description box is longer than x chars, then description input worked
if(StrLen(Input_Description) > 5){
	SaveOrPostProgress(Message:="Video Description second double check was successful",PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
}
else, {
	SaveOrPostProgress(Message:="Secondary video description check failed",PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}



TooltipThis("Waiting for Video to Finish Uploading")
Loop, %Number_of_loops_to_Check_Upload_status% {
	sleep, %Time_Between_Loops_Upload_Status%

	; Get progress status through javascript
	jsCheck = return document.getElementsByClassName('video-upload--details')[0].textContent;
	try ProgressStatus := driver.executeScript(jsCheck)  

	if(ProgressStatus = ""){
		Message = Failed to Grab Video Upload Status. Upload Most Likely Failed
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}

	if(InStr(ProgressStatus, "Upload complete.")){
		Break
	}

	; Pull out progress Percentage from full string
	UploadPercent := StrSplit(ProgressStatus, "(")
	UploadPercent := UploadPercent[2]
	UploadPercent := StrSplit(UploadPercent, ")")
	UploadPercent := UploadPercent[1]

	; Message = Waiting for Video to Finish Uploading`nCurrent Upload Status: %UploadPercent%
	; SaveOrPostProgress(Message:=Message,PostType:="Tooltip")

	Status := Check_For_Stuck_Video_Upload(A_index, UploadPercent)
	if(Status = "Failed")
	Return
}

; Save Video button
TooltipThis("Clicking Save Video Button to finalize Upload")
try BrighteonUploadPageURL := driver.url
try driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding


TooltipThis("Waiting for Result page to finish loading")
Loop, 60 { ; 5 loops of 1 minute each
	if(A_index = 10){
		Message = Upload Failed: Clicking "Save Video" did not Finalize the Upload
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
		SaveDriverURLOFErrorPage()
		Return ; Break out of gosub
	}
	js = document.getElementsByClassName('mr-2 btn btn-primary btn-sm')[0].click(); ; Save Video Button
	try driver.executeScript(js)
	driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding

	sleep, 5000 ; 30 seconds
	try CurrentURL := driver.url
	if(BrighteonUploadPageURL != CurrentURL)
	Break
}


Message = Trying to Grab Uploaded Video URL
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

; Message = Waiting 60 Seconds Before Checking Results Page for URL
; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

; Navigate to Videos page and loop through the videos and grab the URL of the latest upload
try driver.Get("https://www.brighteon.com/dashboard/videos")	;Open selected URL
try driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding



; Get First word in video title to use in grabbing video URL
VideoTitleArray := StrSplit(VideoTitle, " ")
; Iterate from 1 to the end of the array:
Loop % VideoTitleArray.Length(){
	VideoTitleLongWord := VideoTitleArray[A_Index]
	; VideoTitleFirstWord := StrReplace(VideoTitleFirstWord, "_","-")
	if(StrLen(VideoTitleLongWord) > 4)
	Break

	; MsgBox % VideoTitleArray[A_Index]
}


Message = VideoTitleLongWord: %VideoTitleLongWord%
SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")


Loop, 4 {
	ElementIndexNumber := A_index + 1

	jsCheck = return document.getElementsByClassName('col')[%ElementIndexNumber%].outerHTML;
	try BrighteonURL := driver.executeScript(jsCheck)

	jsCheck = return document.getElementsByClassName('col')[%ElementIndexNumber%].textContent;
	try InnerText := driver.executeScript(jsCheck)

	Message = InnerText: %InnerText%
	SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")

	Message = BrighteonURL: %BrighteonURL%
	SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")

	; Msgbox % "VideoTitleLongWord: " VideoTitleLongWord "`nInnerText: " InnerText
	; clipboard := Message
	; msgbox % Message
	; Msgbox % "InnerText: " InnerText . "`n" . "BrighteonURL: " . BrighteonURL

	if(InStr(InnerText, VideoTitleLongWord)){
		BrighteonURL := StrSplit(BrighteonURL, "/dashboard/videos/")
		BrighteonURL := BrighteonURL[2]
		BrighteonURL := StrSplit(BrighteonURL, "><div")
		BrighteonURL := BrighteonURL[1]
		BrighteonURL := StrReplace(BrighteonURL, """", "")
		BrighteonURL := "https://www.brighteon.com/" . BrighteonURL
		; Msgbox % "BrighteonURL: " BrighteonURL

		Break
	}
	BrighteonURL := 

}



; Convert dashboard URL to Public URL
; BrighteonURL := StrReplace(BrighteonURL, "dashboard/videos/", "")

if(BrighteonURL = ""){
	Message = Upload Completed Successfully but failed to grab Share URL. Please Copy and Paste it in.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}

Message = Upload Complete:`n%BrighteonURL%
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")  
IniWrite, %BrighteonURL%, %VideoLinksIniFile%, URLs, BrighteonURL
SaveDriverURL()
AddToTotalVideosUploadedCount()
; TakeScreenshotOfPage(ScreenShotSavePath)

Return
; -------------------------------/Brighteon Upload-------------------------------




; -------------------------------DailyMotion-------------------------------
DailyMotionUpload:

CurrentSite := "DailyMotion"
SaveOrPostProgress(Message:="Starting Upload",PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

; @todo: remove This section later after update 1.92 
IniRead, DailyMotionParnerUploadPage, %SettingsIniFilepath%, General, DailyMotionPostPageURL, %A_Space%
if(!DailyMotionParnerUploadPage){
	DailyMotionParnerUploadPage := "https://www.dailymotion.com/partner/x7e48a/media/video/upload"
	IniWrite, %DailyMotionParnerUploadPage%, %SettingsIniFilepath%, General, DailyMotionPostPageURL
}

Status := NavigateFromBaseURLTo(DailyMotionParnerUploadPage,"Partner HQ - Dailymotion")
if(Status)
Return

Message = Waiting for Page to Finish Fully Loading
SaveOrPostProgress(Message:=Message,PostType:="Tooltip")
try driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding
sleep, 1500


Message = Uploading Video
SaveOrPostProgress(Message:=Message,PostType:="Tooltip")

Xpath = //input[@type='file']
Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=1,SleepLength:=2000,StringTextContent:=VideoFilepath)
if(Status){
	; DevModeMsgBox(Status)
	Message = Trying to Log Back In 
	; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	Xpath = //button[normalize-space()='Log in']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)
	sleep, 5000
	; Upload file again
	Xpath = //input[@type='file']
	Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=1,SleepLength:=2000,StringTextContent:=VideoFilepath)
}
; DevModeMsgBox("test")
sleep, 2000
; Click on Upload Thumbnail Button
TooltipThis("Uploading Thumbnail")

Xpath = //input[@type='file']
Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoThumbFilepath)
if(Status){
	Message = Failed to Upload Thumbnail: Check Login Status
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
}

Message = Inputting Video Details
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")


; @todo: uncomment this and replace the selenium funciton
; Clear video title that is input automatically and input the real title
/*Msgbox % "JSVideoTitle: " JSVideoTitle
js_SendAndCheckWithNAME(Element:="title",ClassIndexNum:=0,ValueToCheck:="value",SleepLength:=1000,JSStringText:=JSVideoTitle)
Msgbox % "Status: " Status
if(Status){
	Message = Failed to input Video Title
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}
*/

; Clear out the pre-input title
; js = return document.getElementsByName('title')[0].value = "";  ; Send content through javascript (Great for getting around emoji chrome limitaitons)
; try driver.executeScript(js)    ;Executes a Javascript on the webpage, mostly used for buttons.

; try driver.findElementsByName("title").item[1].clear() 

Message = Inputting Title
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

loop, 5 { ; sometimes the pre-inserted title doesn't get cleaned out when inputting title

if(A_index = 5){
	Message = Failed to input title after 5 attempts.
	; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	; Return
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}


Xpath = (//input[@placeholder='Enter text'])[1]
try, driver.FindElementByXPath(Xpath).click()

js = document.querySelector("input[placeholder='Enter text']").value = "%JSVideoTitle%";
try driver.executeScript(js)

Xpath = (//input[@placeholder='Enter text'])[1]
try driver.FindElementByXPath(Xpath).SendKeys(driver.Keys.SPACE)

try driver.FindElementByXPath(Xpath).SendKeys(driver.Keys.BackSpace)



/*
Status := Selenium_LoopToSendValueByName(ElementName:="title",NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoTitle)
if(Status){
	Message = Upload Failed: Check Login Status: Failed to Input Title
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}


*/

; get text in title box and see if it matches video title
js = return document.querySelector("input[placeholder='Enter text']").value;
try CurrentTitle := driver.executeScript(js)
; Msgbox % "CurrentTitle: " CurrentTitle

if(CurrentTitle != VideoTitle){
	Message = Failed to input title on attempt %A_index%
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	sleep, 1000
	; DevModeMsgBox("title doesn't match")
	; msgbox, title doesn't match
	; continue
}
else,
Break


}



; Make a couple attempts to Click on Drop down menu and select the "Education" Category
TooltipThis("Selecting Education Category")

Xpath = //div[@name='channel']
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)
if(Status){
	SaveOrPostProgress(Message:="Failed to click the Category dropdown button",PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}


js = document.querySelector("div[title='Education'] div[class='ant-select-item-option-content']").click()
try status := driver.executeScript(js)
catch e {
	SaveOrPostProgress(Message:="Failed to select Education category",PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}




/*sleep, 2000 ; sleep 2 seconds for everything to catch up GUI wise
loop, 5 {
	if(A_index = 4) ; if this is attempt number 5 then category wasn't able to be selected
	{
		Message = Upload Incomplete (E#5874)`nUnable to Select "Education" category`nPlease Select it and click the save button to finalize upload
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		; Return ; Kick out of the gosub 
	}

	; ; click dropdown menu
	; JsToExecute = document.getElementsByClassName('ant-select-selection__rendered')[1].click(); ; Save Video Button
	; Status := JS_TryToExecute(JsToExecute)

	xpath = (//div[@role='combobox'])[3]
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)
	; driver.FindElementByXPath(Xpath).click()


	; select "educaiton" category
	Xpath = //li[normalize-space()='Education']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)


	jsCheck = return document.getElementsByClassName('ant-select-selection-selected-value')[1].textContent;
	try SelectedCategory := driver.executeScript(jsCheck)
	if(SelectedCategory = "Education")
	Break

	try SelectedCategory := driver.findelementbyxpath(CategoryBoxXpath).Attribute("innerText") ;GREAT FOR GRABBING INNER CONTENTS/Values
	if(SelectedCategory = "Education")
	Break
	
}
*/


TooltipThis("Checking Not for Kids checkbox")
try driver.findElementsByName("is_created_for_kids").item[2].click()
catch e {
	sleep, 2000
	try driver.findElementsByName("is_created_for_kids").item[2].click()
	catch e {
		Message = Failed to Click on the "Not Made For Kids" checkbox. Please switch to tab and finalize upload.
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}
}


/*
; Disable monitization for video
SaveOrPostProgress(Message:="Unchecking monetizaton checkbox",PostType:="Tooltip,ErrorLoggingTextFile")
Xpath = //button[normalize-space()='Advanced'] ; advanced tab button
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
if(Status = "Failed"){
	Message = Unable to Navigate to Advanced Settings Page to turn off monetization
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
}


*/
SaveOrPostProgress(Message:="Unchecking monetizaton checkbox",PostType:="Tooltip,ErrorLoggingTextFile")

; switch over to advanced tab
js = document.getElementsByName('advanced')[0].click();
try driver.executeScript(js)


sleep, 1000
Loop, 5 { ; Loop to uncheck the "monetization button"

if(A_index = 5){
	Message = Failed to uncheck "monetization enabled" checkbox
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
}

Xpath = //input[@name='advertising_instream_blocked'] ; monetization checkbox 
try Status := driver.FindElementByXPath(Xpath).isSelected() 

if(Status = 0) ; -1 is checked, 0 is unchecked 
Break

; Click to uncheck the "allow monetization" checkbox
Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)
}


; Switch back to Basic tab
js = document.getElementsByName('basic')[0].click();
try driver.executeScript(js)



/*Xpath = //button[normalize-space()='Basic']
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)

*/
sleep, 1000
/*
TooltipThis("Inputting Tags")
; Input Each tag one by one
Loop % KeywordsArray.Length()
{
	Tag := KeywordsArray[A_Index]
	xpath = (//input[@class='ant-select-search__field'])[1]
	try driver.FindElementByXPath(Xpath).SendKeys(Tag)
	catch e {
		Message = Failed to input tag: %tag%
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	}
	try driver.FindElementByXPath(Xpath).SendKeys(driver.Keys.Tab)  
	sleep, 250


	; OLD Method
	; xpath = (//input[@class='ant-select-search__field'])[1]
	; driver.FindElementByXPath(Xpath).SendKeys(Tag)
	; Tag := KeywordsArray[A_Index]
	; try driver.findElementsByName("tags").item[1].SendKeys(Tag) 
	; sleep, 100  
	; try driver.findElementsByName("tags").item[1].SendKeys(driver.Keys.Enter)    
	; sleep, 100
}


*/
; DevModeMsgBox("tags input?")

; Grab the Share URL and pull out the Video Link from it and save it to the Video Linsk ini file, so double uploads are not tried if fialure occurs
Message = Grabbing Share URL
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

Xpath = //span[contains(text(),'Share link:')]
try ShareLink := driver.findelementbyxpath(Xpath).Attribute("innerText") 
; Message = %ShareLink%
SaveOrPostProgress(Message:=ShareLink,PostType:="Tooltip,ErrorLoggingTextFile")

DailyMotionURL := StrReplace(ShareLink, "Share link: ","") ; remove the share link text from string

IniWrite, %DailyMotionURL%, %VideoLinksIniFile%, URLs, DailyMotionURL ; save URL


Message = Inputting Video Description

DailyMotionJSDescription := FormatTextToJSText(VideoDescription)

if(StrLen(DailyMotionJSDescription) > 3000){
	DailyMotionJSDescription := SubStr(VideoDescription, 1, 2990)
	DailyMotionJSDescription := FormatTextToJSText(DailyMotionDescription)
	DailyMotionJSDescription .= "....."
}


; Input Video Description

Message = Inputting Video Description
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
Loop, 5 { ; make a couple attempts to input description

	if(A_index = 5){
		Message = Failed to input Description after %A_index% attempts.
		; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		; Return
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}


	; click into element
	Xpath = //textarea[@placeholder='Enter a description']
	driver.FindElementByXPath(Xpath).click()

	; inut description with javascript
	js = document.querySelector("textarea[placeholder='Enter a description']").value = "%JSVideoDescription%";
	try driver.executeScript(js)

	sleep, 1000

	; send a space and then backspace so element registers the input
	Xpath = //textarea[@placeholder='Enter a description']
	try driver.FindElementByXPath(Xpath).SendKeys(driver.Keys.SPACE)

	try driver.FindElementByXPath(Xpath).SendKeys(driver.Keys.BackSpace)

	sleep, 1000

	js = return document.querySelector("textarea[placeholder='Enter a description']").textContent; 
	try, InputDescription := driver.executeScript(js)

	message = InputDescription: %InputDescription%
	DevModeMsgBox(InputDescription)

	; if input description is less than 15 chars, try again
	if(StrLen(InputDescription) < 15){
		Continue
	}
	else, {
		Break
	}



}

; DevModeMsgBox("done")

/*
; Input Video Description
Loop, 15 { ; make a couple attempts to input description
	TooltipThis("Inputting Video Description")
	js = document.getElementsByName('description')[0].value = ""; ; clear any text from box
	driver.executeScript(js)    ;Executes a Javascript on the webpage, mostly used for buttons.

	; try driver.findElementsByName("description").item[1].SendKeys(driver.Keys.Space) ; send an ENTER keystroke to make it register that data has been input and refresh
	; sleep, 500
	; Clear any text from a previous loop
	; try driver.findElementsByName("description").item[1].clear()

	
	; try driver.findElementsByName("description").item[1].SendKeys(driver.Keys.SPACE)   ;;Clicks Item based on the Element Name
	
	; ValueToCheckOptions = innertext,textContent,InnerHTML,outerHTML,value,href,option value
	; JSText := FormatTextToJSText(TEXT)
	js = document.getElementsByName('description')[0].value = "%DailyMotionJSDescription%";   
	try driver.executeScript(js)

	sleep, 2000

	try driver.findElementsByName("description").item[1].SendKeys(driver.Keys.Space) ; send an ENTER keystroke to make it register that data has been input and refresh

	sleep, 2000

	jsCheck = return document.getElementsByName('description')[0].value;  ; Send content through javascript (Great for getting around emoji chrome limitaitons)
	DescriptionInput := driver.executeScript(jsCheck)    ;Executes a Javascript on the webpage, mostly used for buttons.
	; Msgbox % "DescriptionInput: " DescriptionInput

	if(StrLen(DescriptionInput) > 5)
	break
}


*/
; Progress Percentage
TooltipThis("Waiting for Video to Finish Uploading`nChecking Progress Every 5 seconds")
; Xpath = //span[contains(text(),'Upload at')]

Loop, %Number_of_loops_to_Check_Upload_status% {
	sleep, %Time_Between_Loops_Upload_Status%

	jsCheck = return document.getElementsByClassName('src-routes-media-common-components-progress-bar-index__details--3_P1L')[0].textContent;
	try UploadPercentage := driver.executeScript(jsCheck)

	if(UploadPercentage = "")
	{
		Message = Upload Failed (E#2735)`nUnable to find Progress Upload Percentage
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return ; Kick out of the gosub 
	}

	if(InStr(UploadPercentage, "100%")) ; If at 100% uploaded, break out of loop
	Break

	Status := Check_For_Stuck_Video_Upload(A_index, UploadPercentage)
	if(Status = "Failed")
	Return


	; if(HasVal(Array_Index_Num_of_Upload_StatusChecks, A_index)) { ; 30 minutes and 60 minutes - send a notification message
		; 	Message = Upload Progress: %UploadPercentage%
		; 	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")  
		; }
	}

	; Grab the Share URL and pull out the Video Link from it. 
	SaveOrPostProgress(Message:="Grabbing Share URL",PostType:="Tooltip,ErrorLoggingTextFile")

/*Xpath = //span[contains(text(),'Share link:')]
try ShareLink := driver.findelementbyxpath(Xpath).Attribute("innerText") 

*/

jsCheck = return document.getElementsByClassName('src-routes-media-pages-upload-components-slot-index__shareLink--nc1-O')[0].textContent;
try ShareLink := driver.executeScript(jsCheck)

Message = ShareLink: %ShareLink%
SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile")

if(!InStr(ShareLink, "https")){
	Message = Upload Successful but Failed to Grab Video URL
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	; Return
}


DailyMotionURL := StrReplace(ShareLink, "Share link: ","") ; remove the share link text from string

; Click the publish button
Xpath = //button[@name='submit']
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
if(Status){
	Message = Failed to click Publish button
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")

	js = document.getElementsByClassName('ant-btn ant-btn-primary ant-btn-sm')[1].click(); 
	try driver.executeScript(js)
}



Message = Upload Complete: %DailyMotionURL%
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
IniWrite, %DailyMotionURL%, %VideoLinksIniFile%, URLs, DailyMotionURL
SaveDriverURL()
AddToTotalVideosUploadedCount()
; TakeScreenshotOfPage(ScreenShotSavePath)

Return
; -------------------------------/DailyMotion-------------------------------



; -------------------------------streamanity-------------------------------
StreamanityUpload:
Return
CurrentSite := "Streamanity"
SaveOrPostProgress(Message:="Starting Upload",PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
URLAttempt := NavigateFromBaseURLTo("https://streamanity.com/upload", "Upload - Streamanity")
if(URLAttempt = "Failed")
Return
driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding


/*
; Connect Wallet Button - if it exists than not logged in
Xpath = /html/body/div[1]/div[3]/div[2]/div/div/div/div[2]/div/div/button
try LoginStatus := driver.findelementbyxpath(Xpath).Attribute("innerText") ;GREAT FOR GRABBING INNER CONTENTS/Values
if(LoginStatus != ""){
	Message = Upload Failed (E#8755)`nLogin Cookies have expired. Please Re-login
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}

*/

/*; Close button on "A new Beginning" popup
; this can probably be removed now. Popup was around as of 2020-10ish or so
Xpath = /html/body/div[3]/div[2]/div/div/a/i 
try driver.FindElementByXPath(Xpath).click()    ;Clicks on Xpath based on variable.
sleep, 500
try driver.FindElementByXPath(Xpath).click()    ;Clicks on Xpath based on variable.
; sleep, 2000 ; wait for pop up to go away

*/

Message = Checking Login Status
SaveOrPostProgress(Message:=Message,PostType:="Tooltip")

; Check the page for "Connect Wallet" text which means the user is logged out
try html := driver.pagesource ; save page's entire HTML to a variable
if(InStr(HTML, "Connect Wallet"))
{
	Message = Upload Failed: Please Check Login Status
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}


Message = Selecting Video File
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

Xpath = //div[@class='uploader-body']//input[@type='file']
Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoFilepath)
if(Status){
	Message = Failed to Upload Video, Please check login status
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}
/*Xpath = //div[@class='uploader-body']
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
if(Status){
	Message = Upload Failed:`nUnable to Find "Open File" window to input filepath into
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}

Status := InputFilePathIntoOpenWindow(VideoFilepath)
if(Status)
{
	Message = Upload Failed:`nUnable to Find "Open File" window to input filepath into
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}

*/

if(VideoThumbFilepath != "") {
	Message = Uploading Thumbnail
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

	Xpath = //input[@accept='image/*']
	Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoThumbFilepath)
	if(Status){
		Message = Failed to Upload Thumbnail
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}
/*
	Xpath = //div[@class='thumb-cover has-preview']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
	if(Status){
		Xpath = /html/body/div[1]/div[3]/div[2]/div/div/div/div[1]/div/div[2]/div/div/div[2]/div[2]/div[1]/div[1] ; Upload thumbnail
		Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
		if(Status){
			Message =Upload Error (#5803): Unable to click on Upload Thumbnail button with Relative and Direct Xpath
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
			Return
		}
	}

	Status := InputFilePathIntoOpenWindow(VideoThumbFilepath)
	if(Status)
	{
		Message = Upload Failed:`nUnable to Find "Open File" window to input filepath into
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}
	*/
}


; Input Title
TooltipThis("Inputting Video Title")
Status := js_SendAndCheckWithClassName(ClassName:="ivu-input",ClassIndexNum:=1,ValueToCheck:="value",SleepLength:=1000,JSStringText:=JSVideoTitle)
if(Status){
	Message = Upload Failed: Failed to input Video Title
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}

Xpath = //input[@placeholder="What's the name of your video"]
try driver.FindElementByXPath(Xpath).SendKeys(driver.Keys.SPACE)

/*Xpath = //input[@placeholder="What's the name of your video"]
try driver.FindElementByXPath(Xpath).clear() ; clear the auto generated video title
catch e {
	sleep, 5000
	try driver.FindElementByXPath(Xpath).clear() ; clear the auto generated video title
	catch e {
		Message = Failed to clear Auto Generated Video Title.
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}
}

Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000,StringTextContent:=VideoTitle)
if(Status){

	Xpath = /html/body/div[1]/div[3]/div[2]/div/div/div/div[1]/div/div[3]/div/div/div/div[2]/div[1]/form/div[1]/div/div/input
	try driver.FindElementByXPath(Xpath).clear() 
	try driver.FindElementByXPath(Xpath).SendKeys(VideoTitle)     ;Sends Variable to an Xpath Item
	catch e {
		Message = Failed to input Video Title through both Relative and Direct Xpath
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
		Return
	}
}

*/

; Input Description 
Message = Inputting Description
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

/*Loop, 5 { ; Attempt to input video description a couple of times
	Status := js_SendAndCheckWithClassName(ClassName:="ivu-input",ClassIndexNum:=2,ValueToCheck:="value",SleepLength:=2000,JSStringText:=JSVideoDescription)
	if(!Status) ; if no errors then text got input correctly, break out of loop
	Break

}


*/

; Input Description 
Loop, 5 { ; Attempt to input video description a couple of times
	Message = Inputting Description `nAttempt Number: %A_index%
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

	; TooltipThis("Inputting Description `nAttempt Number: " A_index)

	Xpath = //textarea[@placeholder='What is this video about?']
	try DescriptionContents := driver.findelementbyxpath(Xpath).Attribute("value") ;XPath: ID=site-title & span tag

/*	if(A_index = 5){
		Clipboard := VideoDescription
		Message = Unable to Input Video Description`nDescription copied to clipboard, please paste it in at your earliest convenience. 
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}

	*/
	StreamanityVidDescjs = document.getElementsByClassName('ivu-input')[2].value = "%JSVideoDescription%"; ; Send content through javascript (Great for getting around emoji chrome limitaitons)
	try driver.executeScript(StreamanityVidDescjs)    ;Executes a Javascript on the webpage, mostly used for buttons.

	sleep, 1000
	Xpath = //textarea[@placeholder='What is this video about?']
	try DescriptionContents := driver.findelementbyxpath(Xpath).SendKeys(driver.Keys.SPACE) ;XPath: ID=site-title & span tag


/*	try driver.executeScript(StreamanityVidDescjs)    ;Executes a Javascript on the webpage, mostly used for buttons.

	try StreamanityDescription := driver.findElementsByClass("ivu-input").item[3].Attribute("value") 
	if(StreamanityDescription != ""){
		try driver.findElementsByClass("ivu-input").item[3].SendKeys(driver.Keys.ENTER) ; Send enter to add extra line to end of description. This is the fix for description not dissapearing upon moneybutton swipe
		Break
	}

	*/
	sleep, 2000


	jscheck = return document.getElementsByClassName('ivu-input')[2].value;
	if(strlen(jscheck) > 10) ; if no errors then text got input correctly, break out of loop
	Break


	; sleep, 2000
}



; Input Video Tags. We need to send them one item at a time to Streamanity
; StreamanityTagsArray := StrSplit(VideoTags,",")


Message = Inputting Video Tags
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

; Xpath to Tags Input Box
; Xpath = /html/body/div[1]/div[3]/div[2]/div/div/div/div[1]/div/div[3]/div/div/div/div[2]/div[1]/form/div[3]/div/div/div/div/div/input
Xpath = /html/body/div[1]/div[3]/div[2]/div/div/div/div[1]/div/div[3]/div/div/div/div[2]/div[1]/form/div[3]/div/div/div/div/div/input
; Input Each tag one by one
Loop % KeywordsArray.Length()
{
	Tag := KeywordsArray[A_Index]
	; Msgbox % "Tag: " Tag
	try driver.FindElementByXPath(Xpath).SendKeys(Tag)     ;Sends Variable to an Xpath Item
	try driver.FindElementByXPath(Xpath).SendKeys(driver.Keys.Enter)    ;Sends Enter key to Xpath.
	; msgbox, pause
	sleep, 250
}


; ASK STEF FOR INPUT HERE 
TooltipThis("Waiting for User to Swipe Payment Button")
Xpath = //div[@class='video-title']
; MsgBox,,Xpath Value,% driver.findelementbyxpath(Xpath).Attribute("value") ;XPath: ID=site-title & span tag

Loop, 20 {

	if(A_index = 20){
		Message = Payment was not swiped. Skipping to Next Website
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}


	try Status := driver.findelementbyxpath(Xpath).Attribute("innerText") ; Grabb innertext
	if !InStr(Status, "Waiting for payment")
	break

	; otherwise sleep and re-run check
	sleep, 5000
}





; Status := StrSplit(status, "`n")
; msgbox % Status[1]
; msgbox % Status[2]


; MsgBox,,XPATH Text Content,% driver.findelementbyxpath(Xpath).Attribute("textContent") ;XPath: ID=site-title & span tag
; MsgBox,,HREF Link Location: ,% driver.findelementbyxpath(Xpath).Attribute("href") ;XPath: Href (Link location) value
; MsgBox,,XPATH-ID & Tag,% driver.findelementbyxpath(Xpath).Attribute("outerHTML") ;XPath: ID=site-title & span tag
; MsgBox,,XPATH Option Value,% driver.findelementbyxpath(Xpath).Attribute("option value") ;XPath: ID=site-title & span tag



TooltipThis("Waiting for Video to Finish Uploading")

; Upload status text at the top left of the page
Xpath = /html/body/div[1]/div[3]/div[2]/div/div/div/div[1]/div/div[1]/div/div[1]/span

Loop, %Number_of_loops_to_Check_Upload_status% {
	sleep, %Time_Between_Loops_Upload_Status%

	jsCheck = return document.querySelector("div[class='video-title'] span").textContent;
	try UploadStatus := driver.executeScript(jsCheck)

	; try UploadStatus := driver.findelementbyxpath(Xpath).Attribute("innerText") ; Grab innertext
	
	if(UploadStatus = ""){
		Message = Failed to Grab Video Upload Status. Upload Most Likely Failed
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}
	; Msgbox % "UploadStatus: " UploadStatus

	if(InStr(UploadStatus, "Complete")){ ; If upload is complete then we're ready to click the Publish Button
	sleep, 5000 ; 5 seconds
	Break


	Status := Check_For_Stuck_Video_Upload(A_index, UploadStatus)
	if(Status = "Failed")
	Return

	; if(A_index = 240){
		; 	Message = Upload Failed. Upload did not complete after 2 hours of waiting. Something possibly went wrong? 
		; 	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		; 	SaveDriverURLOFErrorPage()
		; 	Return
		; }


		; if(HasVal(Array_Index_Num_of_Upload_StatusChecks, A_index)) { ; 30 minutes and 60 minutes - send a notification message
			; 	Message = Upload Status: %UploadStatus%
			; 	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
			; }


		}

	}

	; Publish Button at the very bottom
	SaveOrPostProgress(Message:="Trying to Click Publish Button",PostType:="Tooltip,ErrorLoggingTextFile")
	Xpath = //span[normalize-space()='P U B L I S H']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
	if(Status){
		Message = Streamanity Upload Incomplete (E#4701)`nVideo Uploaded But Unable to click final "Publish" button
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	}

	; Wait for Confirmation Page to load and grab the Video URL from here
	Message = Waiting for Confirmation Page to Load
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")


	Xpath = //div[@class='link'] ; Xpath to URL of the video
	Loop, 60 { ; loop for a couple of minutes to wait for confirmation page to load
		jsCheck = return document.getElementsByClassName('link')[0].textContent;
		try StreamanityURL := driver.executeScript(jsCheck)

		if(InStr(StreamanityURL, "https://streamanity.com"))
		Break

		if(A_index = 60){
			try PageURL := driver.URL
			Message = Upload Complete: But Failed to Grab Video Link`nPage Stuck At at: %PageURL%
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
			IniWrite, Failed to Grab Link. Please copy and paste into here, %VideoLinksIniFile%, URLs, StreamanityURL
			SaveDriverURLOFErrorPage()
			Return
		}
		Sleep, 1000
	}

	if(StreamanityURL = ""){
		Message = Upload Successfull but unable to automatically grab URL.
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	}

	Message = Upload Complete:`n%StreamanityURL%
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	IniWrite, %StreamanityURL%, %VideoLinksIniFile%, URLs, StreamanityURL
	SaveDriverURL()
	AddToTotalVideosUploadedCount()
	; TakeScreenshotOfPage(ScreenShotSavePath)

	Return
	; -------------------------------/streamanity-------------------------------





	; -------------------------------LBRY-------------------------------
	LBRYVideoUpload:
	LBRYAudioUpload:
	if(LBRYUploadType = "Video"){
		CurrentSite := "LBRY Video"
		IniRead, LBRYPermanentURL, %VideoLinksIniFile%, Misc, LBRYVideoPermanentURL, %A_Space%

	}
	if(LBRYUploadType = "Audio"){
		CurrentSite := "LBRY Audio"
		IniRead, LBRYPermanentURL, %VideoLinksIniFile%, Misc, LBRYAudioPermanentURL, %A_Space%
	}

	; if LBRY permanent URL was already grabbed before, exit
	if(LBRYPermanentURL != "")
	Return

	CheckLBRYProcess() ; double check lbry process


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


	; If LBRY Killer not found, then download it
	; @todo: Add LBRY kill download functionality from gitea

	LBRYKillerPath := LibFolder . "\LBRY Process Killer.exe" 
	if(!FileExist(LBRYKillerPath)){

		; Msgbox % "LBRYKillerPath: " LBRYKillerPath
		; Msgbox % "LBRYProcessKillerURL: " LBRYProcessKillerURL
		LBRYKillerPath = %A_ScriptDir%\Lib\LBRY Process Killer.exe
		LBRYKillerUpdateURL = https://git.zinchuk.xyz/attachments/7865dc8d-5aad-4f9f-8a30-94bab0192b1d

		UrlDownloadToFile, %LBRYKillerUpdateURL%, %LBRYKillerPath%
		; msgbox, work?
		; UrlDownloadToFile, URL, Filename
		Message = LBRY Process Killer Not Found. Automatically Downloading.
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	}

	

	TooltipThis("Uploading Video through API")
	; Variables of items that need to be replaced before argument is passed to API
	Apostrophe = '
	LBRYTags =  ; Create empty variable
	SingleQuotationmark = " 
	EscapedQuotationMark = \"

	; Replace all items to make text passable to API
	LBRYVideoTitle :=  StrReplace(VideoTitle, SingleQuotationmark, EscapedQuotationMark) ; replace all spaces with dashes 
	LBRYVideoDescription := StrReplace(VideoDescription, SingleQuotationmark, EscapedQuotationMark)

	if(StrLen(LBRYVideoDescription) >= 5000){
		LBRYVideoDescription := SubStr(LBRYVideoDescription, 1, 4990)
		LBRYVideoDescription .= "...."
	}

	if(LBRYUploadType = "Video"){
		Message = Uploading through API with URL Slug: %LBRYURLSlug%
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

		FilePathForLBRYAPI := VideoFilepath

	}

	if(LBRYUploadType = "Audio"){
		; Replace all items to make text passable to API
		LBRYVideoTitle .= " (Audio)"
		LBRYURLSlug .= "_Audio"
		Message = Uploading through API with URL Slug: %LBRYURLSlug%
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

		FilePathForLBRYAPI := WavAudioFilepath
	}

	; if no lbry slug, then error out
	if(LBRYURLSlug = "" OR LBRYURLSlug = "_Audio"){
		Message = Upload Failed because no URL Slug was provided.
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}



	; loops through array and creates a string of: --tags="tag1" --tags="tag2" --tags="tag3" so that it can be passed to lbrynet
	Loop % KeywordsArray.Length(){ 
		LBRYTags .= "--tags=" . SingleQuotationmark KeywordsArray[A_Index] . SingleQuotationmark . " "
	}

	; Msgbox % "FilePathForLBRYAPI: " FilePathForLBRYAPI

	SplitPath, VideoThumbFilepath, ThumbnailFileNameWExt, OutDir, OutExtension, OutNameNoExt, OutDrive

	FDRThumbnailURL = https://cdn.freedomainradio.com/%ThumbnailFileNameWExt%
	message = FDRThumbnailURL: %FDRThumbnailURL%
	SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,DiscordErrorLogging")

	; Msgbox % "FDRThumbnailURL: " FDRThumbnailURL
	; Create API Command and save it to variable
	LBRYAPICommand = "%LBRYNetFilepath%" publish --name="%LBRYURLSlug%" --bid="%LBRYNewVideoStakeAmount%" --file_path="%FilePathForLBRYAPI%" --title="%LBRYVideoTitle%" --description="%LBRYVideoDescription%" %LBRYTags% --thumbnail_url="%FDRThumbnailURL%" --channel_id="%LBRYChannelID%"

	; LogErrorToTextFile(LBRYAPICommand) ; Log to file
	LogErrorToTextFile("LBRYAPICommand: " LBRYAPICommand)

	; Parse returned API json for success status
	UploadResult := StdOutToVar(LBRYAPICommand)
	if(InStr(UploadResult, "Could not connect")){
		Message = Upload Failed. Reason: %UploadResult%
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}

	if(UploadResult = ""){
		Message = LBRYNet did not return anything. LBRY not running?
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}

	; Msgbox % "UploadResult: " UploadResult
	try parsed := JSON.Load(UploadResult)
	try UploadStatus := parsed.height

	; Msgbox % "UploadStatus: " UploadStatus

	; -2 is returned if upload was successful
	if(UploadStatus != "-2"){
		; msgbox, error
		ErrorCode := parsed.message
		ErrorCode := parsed.message
		ErrorCode := StrSplit(ErrorCode, "code")
		ErrorCode := ErrorCode[1]

		Message = LBRY Upload Failed`nReason: %ErrorCode%
		; Msgbox % "Message: " Message
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}



	; Clipboard := UploadResult
	; Msgbox % "UploadResult: " UploadResult


	LogErrorToTextFile("UploadResult: " UploadResult)

	if(InStr(UploadResult, "Could not connect to daemon")){
		if(LBRYAttemptNumber = 2){

			Message = Upload Error (E#4081)`nVideo Upload Failed due to daemon not running.`nPlease start it manually and re-run the upload.		
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

			try run, %LBRYKillerPath% "Kill"
			catch e {
				; Message = Unable to Kill LBRYKiller.ahk
				; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
			}
			Return
		}
		else, { ; if attempt number 1
			Process, Close, LBRY.exe ; terminate LBRY if it's running
			LBRYAttemptNumber := 2
			Message = Upload Failed (E#1980)`nDue to daemon not running.`nTrying to restart LBRY.exe and try the upload again. 
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
			Goto, LBRYVideoUpload
		}
	}

	; Clipboard := UploadResult
	; Msgbox % "UploadResult: " UploadResult

/*if(DevMode){
	Clipboard := UploadResult
	Msgbox % "UploadResult: " UploadResult
}
*/
; Create an object out of the API Return
LBRYJSONResult := JSON.Load(UploadResult)

if(!InStr(UploadResult, "permanent_url")){ ; if no permanent_url is generated then API issue
	LBRYAPIError := LBRYJSONResult.message
	; LBRYAPIError := GetLBRYAPIErrorFromString(UploadResult)
	; if the returned string does not have "permanent_url" in it, then upload failed
	Message = Upload Error (E#6930)`nVideo Upload Failed due to API Issue. Please send errorlog to Yuriy.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}

if(KillLBRYAfterUpload){
	try run, %LBRYKillerPath%
	catch e {
		Message = LBRYKiller not found. Unable to find File.
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	}
}

; Transform the Upload Result json into the LBRY.tv link
; PermanentURL := GetPermanentLBRYURL(UploadResult) ; get permanentURL from the upload result json
LBRYPermanentURL := LBRYJSONResult.outputs[1].permanent_url
if(LBRYPermanentURL = ""){
	Message = Failed to grab permanent_url with json.ahk. Please send errorlog to Yuriy.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	Return
}


Message = Claim Was Successfully Submitted to lbrynet with: %LBRYPermanentURL%
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

; Message = LBRYPermanentURL: %LBRYPermanentURL%
; SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")

if(CurrentSite = "LBRY Video"){
	IniWrite, %LBRYPermanentURL%, %VideoLinksIniFile%, Misc, LBRYVideoPermanentURL
}

if(CurrentSite = "LBRY Audio"){
	IniWrite, %LBRYPermanentURL%, %VideoLinksIniFile%, Misc, LBRYAudioPermanentURL
}
Return

; -------------------------------LBRY URL-------------------------------

LBRYGetURL:
if(LBRYUploadType = "Video"){

	CurrentSite := "LBRY Video"
	; IniWrite, %PermanentURL%, %VideoLinksIniFile%, URLs, LBRYVideoPermanentURL
	IniRead, LBRYPermanentURL, %VideoLinksIniFile%, Misc, LBRYVideoPermanentURL, %A_Space%
}
if(LBRYUploadType = "Audio"){

	CurrentSite := "LBRY Audio"
	IniRead, LBRYPermanentURL, %VideoLinksIniFile%, Misc, LBRYAudioPermanentURL, %A_Space%

}

if(LBRYPermanentURL = ""){
	Message = Upload Skipped. LBRYPermanentURL is blank (Upload Failed due to some API issue)
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}

; Message := "Waiting a couple of minutes for lbrynet blockchain to generate blockchain metadata for newest video"
Message = Waiting for LBRYNet to Generate LBRY URL
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
; sleep, 60000 ; 1 minute
; sleep, 300000 ; sleep for 5 minutes so LBRYNet blockchain has a chance to register the new video ; as recomended by LBRY Devs
; sleep, 360000 ; sleep for 6 minutes so LBRYNet blockchain has a chance to register the new video ; LBRY devs recommend 5 mins


LBRYResolveAPICommand = "%LBRYNetFilepath%" resolve %LBRYPermanentURL% ; create variable with the text that's needed for the API command
Message := "LBRYResolveAPICommand: " . LBRYResolveAPICommand ; Save the result to the errorlogging file
SaveOrPostProgress(Message:=Message,PostType:=",ErrorLoggingTextFile")

; msgbox

loop, 15 {
	LBRYResolveResult := StdOutToVar(LBRYResolveAPICommand) ; Save API call to a variable 

	if(A_index = 1 OR a_index = 10){
		Message := "LBRYResolveResult: " . LBRYResolveResult ; Save result to the errorlogging file
		SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile")
	}

	if(InStr(LBRYResolveResult, "could not find claim") AND A_Index < 10) ; try 4 times to get the resolveURL, sometimes the blockchain is quite slow
	{
		; @todo: Make it check every 2 minutes?
		; TooltipThis("Not Able to Grab URL from API. `nWaiting another 5 for blockchain to sync claim before trying again")
		; MessageNumber := A_index + 5

		if(A_index < 5)
		Message = Waiting for LBRYNet to Generate LBRY URL`nChecking Every 2 Minutes
		if(A_index > 5)
		Message = Still Waiting for LBRYNet to Generate LBRY URL`nLBRY Network is most likely congested.`nChecking Every 2 Minutes

		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
		; sleep, 300000 ; 5 minutes
		sleep, 120000 ; 2 minute

		Continue
	}

	if(InStr(LBRYResolveResult, "could not find claim") AND A_index = 15){
		Message = Failed to Grab URL from LBRY after 30 minutes. Either LBRY IS REALLY congested or there is a bug and the API commands were passed incorrectly.
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}

	if(InStr(LBRYResolveResult, "canonical_url"))
	Break
}


if(LBRYUploadType = "Video"){
	LBRYVideoURL := GetLBRYCanonicalURL(LBRYResolveResult)  ; Transform the API resulting json into the LBRY.tv link
	if(LBRYVideoURL = ""){
		Message = Failed to Grab LBRY URL from LBRYNet
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}

	; DevModeMsgBox(LBRYVideoURL)

	Message = LBRYVideoURL from GetLBRYCanonicalURL: %LBRYVideoURL%
	SaveOrPostProgress(Message, PostType:=",ErrorLoggingTextFile")

	OpenLBRYVideoURL := StrReplace(LBRYVideoURL, "https://lbry.tv", "https://open.lbry.com")
	OpenLBRYVideoURL := StrReplace(OpenLBRYVideoURL, "#", ":")


	OdyseeVideoURL := StrReplace(LBRYVideoURL, "https://lbry.tv", "https://odysee.com")
	OdyseeVideoURL := StrReplace(OdyseeVideoURL, "#", ":")

	Message = Upload Complete: <%OpenLBRYVideoURL%> + <%OdyseeVideoURL%>
	SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,DiscordErrorLogging")

	IniWrite, %OpenLBRYVideoURL%, %VideoLinksIniFile%, URLs, LBRYVideoURL
	IniWrite, %OdyseeVideoURL%, %VideoLinksIniFile%, URLs, OdyseeVideoURL

}
if(LBRYUploadType = "Audio"){
	LBRYAudioURL := GetLBRYCanonicalURL(LBRYResolveResult)  ; Transform the API resulting json into the LBRY.tv link
	if(LBRYAudioURL = ""){
		Message = Failed to Grab LBRY URL from LBRYNet
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}

	Message = LBRYAudioURL from GetLBRYCanonicalURL: %LBRYAudioURL%
	SaveOrPostProgress(Message, PostType:=",ErrorLoggingTextFile")

	OpenLBRYAudioURL := StrReplace(LBRYAudioURL, "https://lbry.tv", "https://open.lbry.com")
	OpenLBRYAudioURL := StrReplace(OpenLBRYAudioURL, "#", ":")

	OdyseeAudioURL := StrReplace(LBRYAudioURL, "https://lbry.tv", "https://odysee.com")
	OdyseeAudioURL := StrReplace(OdyseeAudioURL, "#", ":")

	Message = Upload Complete: <%OpenLBRYAudioURL%> + <%OdyseeAudioURL%>
	SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,DiscordErrorLogging")

	IniWrite, %OpenLBRYAudioURL%, %VideoLinksIniFile%, URLs, LBRYAudioURL
	IniWrite, %OdyseeAudioURL%, %VideoLinksIniFile%, URLs, OdyseeAudioURL
}


; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
; SaveDriverURL()
AddToTotalVideosUploadedCount()
Return
; -------------------------------/LBRY Video-------------------------------





; -------------------------------LBRY Thumb---Odysee Thumb-----------------------
OdyseeVideoThumbUpload:
OdyseeAudioThumbUpload:


if(VideoThumbFilepath = "") {
	Message = Thumbnail Upload Skipped. Thumbnail Filepath not provided
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
	Return
}


if(OdyseeUploadType = "Audio"){
	OdyseeURLToUploadThumbnailFor := OdyseeAudioURL
	CurrentSite := "Odysee Audio"

}
if(OdyseeUploadType = "Video"){
	OdyseeURLToUploadThumbnailFor := OdyseeVideoURL
	CurrentSite := "Odysee Video"
}


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

if(OdyseeUploadType = "Audio" AND OdyseeAudioURL = "")
{
	Message = Audio Thumbnail Upload Skipped. OdyseeAudioURL is blank.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
	Return
}

if(OdyseeUploadType = "Video" AND OdyseeVideoURL = "")
{
	Message = Video Thumbnail Upload Skipped. OdyseeVideoURL is blank.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
	Return
}

; Msgbox % "LBRYAudioURL: " LBRYAudioURL
; Msgbox % "LBRYUploadType: " LBRYUploadType


; Msgbox % "OdyseeURLToUploadThumbnailFor: " OdyseeURLToUploadThumbnailFor

/*Message = Uploading %OdyseeUploadType% Thumbnail through Odysee. `nNavigating to: %OdyseeURLToUploadThumbnailFor%
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

*/
Message = Uploading Thumbnail through Odysee
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

/*try driver.ExecuteScript("window.open();")      ;Opens a new Window or tab (Depends on your Chrome Prefs)
catch e {
	Message = Failed to Open New Window 
}

try driver.SwitchToNextWindow

*/

URLAttempt := NavigateFromBaseURLTo(OdyseeURLToUploadThumbnailFor)
if(URLAttempt = "Failed"){
	Message =Unable to Navigate to Video Page (E#2816)`nInternet Connectivity issue or LBRY link not properly grabbed from API`nPlease upload Thumbnail manually at your earliest convenience.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
	Return
}
driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding

TooltipThis("Waiting 10 Seconds for Video Page to Fully Load")
sleep, 10000


/*; Check login status
Message = Checking Login Status
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
try LoginStatus := driver.findelementbyxpath(Xpath).Attribute("innerText") ; Grabb innertext

if(!LoginStatus){
	Message = Upload Failed (E#3985)`nLogin Cookies have expired. Please Re-login
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}

*/

Message = Checking Login Status
SaveOrPostProgress(Message:=Message,PostType:="Tooltip")
try html := driver.pagesource ; save page's entire HTML to a variable
if(!InStr(HTML, "Edit</span>")){
	Message = Upload Failed: Unable to Find Edit Button: Check Login Status
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}


Message = Clicking "Edit" on PageURL %OdyseeURLToUploadThumbnailFor%
SaveOrPostProgress(Message:=Message,PostType:="DiscordErrorLogging")

; Click Edit button to check if logged in or not. 
Xpath = //span[contains(text(),'Edit')]
loop, 3 {
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=5000)
	if(Status){
		; msgbox, click failed
		Sleep, 60000
		try driver.executeScript("history.go(0)") ;refresh page 
	}
	else, 
	Break
}

if(Status){
	try CurrentPage := driver.url
	Message = Unable to click "Edit" button. Most likely Reason is Video is Still Confirming OR Login Cookies Have Expired.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}


/*
; Close the video preview floating window
Xpath = //button[@title='Close']
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)

*/

; "Use thumbnail upload tool"
TooltipThis("Selecting Thumbnail Upload Tool")
Xpath = //span[contains(text(),'Use thumbnail upload tool')]
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
if(Status){
	Message = Thumbnail Upload Failed (E#5617)`nUnable to click on "Use thumbnail upload tool"
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}

/*
try CurrentPage := driver.url
Message = Trying to Click Browse for Thumbnail Button on Page: %CurrentPage%
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

*/
/*
Xpath = /html/body/div/div/div[1]/main/div/div/section[2]/div/div/fieldset-section/input-submit/button/span/span
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
if(Status){
	Message = Failed to Click "Browse" button with Direct Xpath to input thumbnail filepath. Trying with Relative
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

	
}

*/

/*; Select Use Thumbnail upload tool button
Xpath = //span[contains(text(),'Use thumbnail upload tool')]
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
if(Status){
	Message = Failed to click "Use Thumbanil Upload Tool"
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
}

*/
/*
Xpath = //div[@class='card__main-actions']//div//span[@class='button__label'][normalize-space()='Browse']
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
if(Status){
	Message = Failed to click "Browse" button using relative and direct Xpath

	Xpath = //div[@class='card__main-actions']//div//button[@aria-label='Browse']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
	if(Status){
		Message = Failed to click "Browse" button using Relative Xpath of parent element as well
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}
}

*/


/*
Message = Trying to select thumbnail to upload
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

*/

/*
Status := InputFilePathIntoOpenWindow(VideoThumbFilepath)
if(Status)
{
	Message = Upload Failed:`nUnable to Find "Open File" window to input filepath into
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}

*/

Xpath = //input[@accept='.png, .jpg, .jpeg, .gif']
Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoThumbFilepath)
if(Status){
	Message = Failed to Upload Thumbnail Image
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
	; Return
}
; try driver.FindElementByXPath(Xpath).SendKeys(VideoThumbFilepath)


; "Upload thumbnail" popup
; Confirmation Upload Popup - popup box 
Xpath = //span[contains(text(),'Upload')]
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=1000)
if(Status){
	Message = Thumbnail Upload Failed (E#2866)`nUnable to click upload confirmation button
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
	SaveDriverURLOFErrorPage()
	Return
}
/*
Xpath = /html/body/div[4]/div/div/div/button[1]/span/span
loop, 15 {
	if(A_index = 15){
		Message = Thumbnail Upload Failed (E#2866)`nUnable to click upload confirmation button
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
		Break
	} 
	try driver.FindElementByXPath(Xpath).click()    ;click on confirmaiton button
	catch e {
		Sleep, 1000
		Continue
	}
	Break
}

*/
/*; "Upload Complete" Text
Xpath = /html/body/div/div/div[1]/main/div/div/section[2]/div/div/div/div[2]/p
Loop, 15 {
	if(A_index = 15){
		Message = Thumbnail Upload Failed (E#5580)`nUnable to find upload confirmation text on page.
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
		Break
	}
	try UploadStatus := driver.findelementbyxpath(Xpath).Attribute("innerText") ;XPATH Inner Text
	if(!InStr(UploadStatus, "Complete"))
	{
		sleep, 2000
		Continue
	}
	Break
}
*/

; sleep, 5000 ; sleep 5 seconds for everything to catch up. 

Message = Waiting for Thumbnail to Finish Uploading
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
sleep, 5000

; Hit the save button
Xpath = //button[@class='button button--primary'] ; Save button popup
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=5,SleepLength:=5000)
if(Status = Failed){
/*	Message = Failed to click last "Save" button. Please click it to finalize the upload.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
	*/
}

sleep, 5000

; Click off the confirmation popup and Check the "Skip Preview and Confirmation" checkbox
; xpath = //label[normalize-space()='Skip preview and confirmation']
; try SkipPreviewCheck := driver.findelementbyxpath(Xpath).Attribute("innerText") ; Grabb innertext

; if(SkipPreviewCheck != ""){
	; Check skip preview checkbox so the box doesn't pop up again

	TooltipThis("Checking for Confirmation Popup")
	xpath = //label[normalize-space()='Skip preview and confirmation']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)

	Message = Unchecked "Confirm Edit" on each video Checkbox 
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	; msgbox ?

	; Save Button
	Xpath = //button[@aria-label='Save']
	Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=1,SleepLength:=1000)
	; }


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

	if(OdyseeUploadType = "Video")
	IniWrite, Successful, %VideoLinksIniFile%, Misc, OdyseeVideoThumb
	if(OdyseeUploadType = "Audio")
	IniWrite, Successful, %VideoLinksIniFile%, Misc, OdyseeAudioThumb

	; TakeScreenshotOfPage(ScreenShotSavePath)

	Return


	; ---------------------/LBRY Thumb--------/Odysee Thumb-----------------------





	; -------------------------------Rumble-------------------------------
	RumbleUpload:
	CurrentSite := "Rumble"
	SaveOrPostProgress(Message:="Starting Upload",PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
	URLAttempt := NavigateFromBaseURLTo("https://rumble.com/upload.php")
	if(URLAttempt)
	Return
	try driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding

/*
; "Select Video to Upload" Button
Xpath = /html/body/main/div/div/div/section/form[1]/div/div[1]
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)
if(Status){
	Message =Upload Skipped (E#6044)`nLogin Cookies have expired. Please Re-login
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
	Return
}


Status := InputFilePathIntoOpenWindow(VideoFilepath)
if(Status)
{
	Message = Upload Failed:`nUnable to Find "Open File" window to input filepath into
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	Return
}


*/

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

try CurrentURL := driver.URL
if(InStr(CurrentURL, "/login.php")){


	AutoLogin := 1
	; Msgbox % "AutoLogin: " AutoLogin

	if(AutoLogin){
		Message = Logging in Automatically by clicking into the UN+PW fields for info to register
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

		; have to click into username and password field for page to register that there's input
		; clicking with JS doesn't make it register, but with xpath selenium it does
		Xpath = //input[@id='login-username']
		driver.FindElementByXPath(Xpath).click()

		Xpath = //input[@id='login-password']
		driver.FindElementByXPath(Xpath).click()


		js = document.querySelector("button[type='submit']").click(); 
		driver.executeScript(js)


		; Do a double check to make sure that login worked
		Message = Checking Login Status
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

		try CurrentURL := driver.URL

		if(!InStr(CurrentURL, "/upload")){
			Message = Failed to log back in. Please Log Back In Manually
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
			SaveDriverURLOFErrorPage()
			Return
		}


	} 
	else, { ; notify user and return
		Message = Login Expired. Please Log Back in
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}

	Message = Waiting 5 seconds for page to fully load
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")
	sleep, 5000
}


Message = Uploading Video File
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

Xpath = //input[@id='Filedata']
Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoFilepath)
if(Status){
	Message = Failed to Upload Video File
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}


; Input Title
try driver.findElementsByName("title").item[1].SendKeys(VideoTitle)     ;selects element based on Name and sends variable to it.
catch e {
	Message = Video Upload Failed, Please Check Login Status
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}
; Input Description
Loop, 5 { ; Attempt to input video description a couple of times
	TooltipThis("Inputting Description `nAttempt Number: " A_index)

	status := js_SendAndCheckWithID(Element:="description",ValueToCheck:="value",SleepLength:=3000,JSStringText:=JSVideoDescription)
	if(!Status)
	Break

/*	if(A_index = 5){
		Clipboard := VideoDescription
		Message = Unable to Input Video Description`nDescription copied to clipboard, please paste it in at your earliest convenience. 
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
		Return
	}

	js = document.getElementsByName('description')[1].value = "%JSVideoDescription%";  ; Send content through javascript (Great for getting around emoji chrome limitaitons)
	try driver.executeScript(js)    ;Executes a Javascript on the webpage, mostly used for buttons.

	try Description := driver.findElementsByName("description").item[2].Attribute("value") ;XPath: ID=site-title & span tag
	if(Description != "")
	Break
	sleep, 2000
	*/
}




; sleep, 5000


Message = Selecting Channel
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")



; try driver.findElementsByID("channelId").item[1].click()

; @todo replace with regex
js = return document.querySelector("#channelId").innerHTML; 
try, ChannelIDNumber := driver.executeScript(js)
; Msgbox % "ChannelIDNumber: " ChannelIDNumber
ChannelIDNumber := StrSplit(ChannelIDNumber, "option value=")

; Msgbox % "ChannelIDNumber: " ChannelIDNumber

ChannelIDNumber := ChannelIDNumber[3]
; Msgbox % "ChannelIDNumber: " ChannelIDNumber

SingleQuote = "
ChannelIDNumber := StrSplit(ChannelIDNumber, "data-private")
ChannelIDNumber := ChannelIDNumber[1]
ChannelIDNumber := StrReplace(ChannelIDNumber, SingleQuote, "")
ChannelIDNumber := StrReplace(ChannelIDNumber, " ", "")

; Msgbox % "ChannelIDNumber: " ChannelIDNumber


; js = return document.querySelector("#channelId").value; 
; try, ChannelIDNumber := driver.executeScript(js)
; Msgbox % "ChannelIDNumber: " ChannelIDNumber
if(ChannelIDNumber = ""){
	Message = ChannelIDNumber is blank. Unable to select Upload Channel
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}


; //option[@value='762377'] ; freedomain
Xpath = //option[@value='%ChannelIDNumber%']
try driver.FindElementByXPath(Xpath).click()
catch e {
	Message = Failed to click on Channel using %ChannelIDNumber%.
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
	; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
}



; Input Tags
Message = Inputting Tags
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

try driver.findElementsByName("tags").item[1].SendKeys(VideoTags)     ;selects element based on Name and sends variable to it.



; Custom Thumbnail
if(VideoThumbFilepath != "") {
	TooltipThis("Uploading Thumbnail")
	Xpath = //input[@name='customThumb']
	Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoThumbFilepath)
	if(Status){
		Message = Failed to Upload Thumbanil
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	}


	; @todo: Add a check to see if progress gets stuck
	; Check Upload Percentage
	TooltipThis("Waiting for Video to Finish Uploading")
	Loop, %Number_of_loops_to_Check_Upload_status% {
		sleep, %Time_Between_Loops_Upload_Status%

		jscheck = return document.getElementsByClassName('num_percent')[0].textContent;
		try RumbleUploadPercent := driver.executeScript(jsCheck)

		; try RumbleUploadPercent := driver.findelementbyxpath(Xpath).Attribute("textContent") 
		RumbleUploadPercent := StrSplit(RumbleUploadPercent, " ")
		RumbleUploadPercent := RumbleUploadPercent[1]

		if(InStr(RumbleUploadPercent, "100%")) ; once variable contains 100%, then we can break out of loop and continue
		Break


		Status := Check_For_Stuck_Video_Upload(A_index, RumbleUploadPercent)
		if(Status = "Failed")
		Return
		; if(HasVal(Array_Index_Num_of_Upload_StatusChecks, A_index)) { ; 30 minutes and 60 minutes - send a notification message
			; 	Message = Upload Progress: %RumbleUploadPercent%
			; 	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")  
			; }

		}

		; Msgbox % "RumbleUploadPercent: " RumbleUploadPercent

		; Click on one of the video thumbnail options first
		; Seems to be a bug on rumble, in order to be able to select a custom thumb through js, gotta select on of the generated ones first.
		; Xpath = /html/body/main/div/div/div/section/form[1]/div/div[2]/div[3]/a[2] ; thumbnail option #3
		; try driver.FindElementByXPath(Xpath).click()    ;Clicks on Xpath based on variable.




/*	
	js = document.getElementById('customThumb').click(); 
	driver.executeScript(js)    ;Executes a Javascript on the webpage, mostly used for buttons.
	Status := InputFilePathIntoOpenWindow(VideoThumbFilepath)
	if(Status)
	{
		Message = Upload Failed:`nUnable to Find "Open File" window to input filepath into
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		Return
	}

	*/


}

try UploadPageURL := driver.URL

; Submit Button
js = document.getElementById('submitForm').click(); 
try driver.executeScript(js)    ;


try driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding


; Select Rumble Only Licensing
js = document.getElementsByClassName('greenLink mRight last')[0].click(); ; Send content through javascript (Great for getting around emoji chrome limitaitons)
try driver.executeScript(js)    ;Executes a Javascript on the webpage, mostly used for buttons.

; Check off condition 1
js = document.getElementById("crights").click()
try driver.executeScript(js)

; Check off condition 2
js = document.getElementById("cterms").click()
try driver.executeScript(js)

; Click the Submit Button
js = document.getElementById("submitForm2").click()
try driver.executeScript(js)


; Loop until able to grab the direct link from the result page.
Loop, 24 {
	TooltipThis("Waiting for Result Page to load to grab Video URL")
	Sleep, 5000 

	js = return document.getElementById("error_files_2").textContent;
	RumbleError := driver.executeScript(js)    ;Executes a Javascript on the webpage, mostly used for buttons.
	if(RumbleError != "") {
		Message = Rumble Upload Failed due to:`n%RumbleError%
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
		SaveDriverURLOFErrorPage()
		Return
	}

	js = return document.getElementById('direct').value;
	try RumbleURL := driver.executeScript(js)    ;Executes a Javascript on the webpage, mostly used for buttons.

/*	try RumbleURL := driver.findElementsByID("direct").item[1].Attribute("value") ;grab Direct Link from the result page
	catch e { ; if not able to grab it, then sleep for 5 seconds and then loop again
		Continue
	}
	*/
	if(RumbleURL != ""){  ; If URL is grabbed from result page, then kick out of loop
		Break
	}
	if(A_Index = 10) ; if looped for 5 minutes and still no URL grabbed
	{ ; @todo: add error check if submit button clicked and error appears

		Xpath = /html/body/main/div/div/div/section/form[2]/div/div[9] ; grab inner content of where error usually appears.
		try RumbleUploadError := driver.findelementbyxpath(Xpath).Attribute("innerText") ; Grabb innertext
		; Msgbox % "UseThumbUploadToolTextExist: " UseThumbUploadToolTextExist


		Message = Upload Error (E#1341)`nVideo Uploaded but not able to be finalized.`nPlease fix the issue and click the final submit button. `nError: %RumbleUploadError%
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
		SaveDriverURLOFErrorPage()
		Return
	}
}

IniWrite, %RumbleURL%, %VideoLinksIniFile%, URLs, RumbleURL

Message = Upload Complete: %RumbleURL%
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")  
SaveDriverURL()
AddToTotalVideosUploadedCount()
; TakeScreenshotOfPage(ScreenShotSavePath)

Return

; -------------------------------/Rumble-------------------------------


;---Facebook---
;------------------------------------------------
FacebookUpload:
CurrentSite := "Facebook"
SaveOrPostProgress(Message:="Starting Upload",PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")
URLAttempt := NavigateFromBaseURLTo("https://www.facebook.com/")
if(URLAttempt)
Return
try driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding


; Create a description for Facebook
SplitText = Free Documentaries:
FacebookDescription := StrSplit(VideoDescription, SplitText)
FacebookDescription := FacebookDescription[1]
FacebookTitleAndDescription := VideoTitle . "`n`n" . FacebookDescription
JSFacebookTitleAndDescription := FormatTextToJSText(FacebookTitleAndDescription)


Message = Calculating Video Length
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

try Obj := Filexpro(VideoFilepath,,
	, "Length" 
	, "Size" )    
VideoFilesize := obj["Size"]                                                     	
VideoLength := obj["Length"]

; Msgbox % "VideoLength: " VideoLength

VideoLengthArray := StrSplit(VideoLength, ":")
VideoLengthInMinutes := (VideoLengthArray[1] * 60) + VideoLengthArray[2]
; Msgbox % "VideoLengthInMinutes: " VideoLengthInMinutes

if(VideoLengthInMinutes >= 240){
	Message = Skipped: Longer than 240 Minutes
	IniWrite, %Message%, %VideoLinksIniFile%, URLs, FacebookURL
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}


; Upload Video
Xpath = //div[@aria-label='Create a post']//div//input[@type='file']
Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000,StringTextContent:=VideoFilepath)
if(Status){
	Message =Post Failed: Check Login Status
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}

; 
Message = Waiting 15 Seconds for Video Preview to Load
SaveOrPostProgress(Message:=Message,PostType:="Tooltip")
sleep, 15000

Xpath = //div[@data-block='true']//div
Status := Selenium_LoopToSendValueToXpath(Xpath:=Xpath,NumOfLoops:=3,SleepLength:=2000,StringTextContent:=FacebookTitleAndDescription)
if(Status){
	Message = Failed to Input Video Description
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}
; msgbox

; Click submit button
xpath = //div[@aria-label='Post']//div//div//div//span[contains(text(),'Post')]
Status := Selenium_LoopToClickXpath(Xpath:=Xpath,NumOfLoops:=2,SleepLength:=1000)
if(Status){
	Message = Failed to click "Post" button
	SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
	SaveDriverURLOFErrorPage()
	Return
}


IniWrite, Submitted, %VideoLinksIniFile%, URLs, FacebookURL

Message = Upload Started Successfully
SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")  
SaveDriverURL()
AddToTotalVideosUploadedCount()
Return

;---\Facebook---
;------------------------------------------------


; -------------------------------Functions-------------------------------

; Included Files
#include %A_ScriptDir%\Lib\StdOutToVar.ahk  ; used for chrome debugging mode connection
#Include %A_ScriptDir%\Lib\SharedFunctions.ahk
#Include %A_ScriptDir%\Lib\JSON.ahk
#Include %A_ScriptDir%\Lib\ChromeAutomationFunctions.ahk
#Include %A_ScriptDir%\Lib\\RunCMD.ahk

; #Include %A_ScriptDir%\Lib\ChromeAutomationFunctions.ahk



CheckLBRYProcess(){
	; Check if LBRY Process exists
	Process, Exist,LBRY.exe
	if(ErrorLevel = 0) ; if doesn't exist
	{
		Message = Not Running. Starting up LBRY.exe
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile")

		LBRYExeFilepath = C:\Program Files\LBRY\LBRY.exe
		if(!FileExist(LBRYExeFilepath)){
			Message = Failed to Find LBRY.exe executable. LBRY not installed? 
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
			Return
		}
		try run, "%LBRYExeFilepath%"
		Message = Waiting 1 Minute for LBRY to start up
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip")
		Sleep, 60000 ; 1 minute

		Process, Exist,LBRY.exe
		if(ErrorLevel = 0) ; if doesn't exist
		{
			Message = Failed to Start LBRY.exe after 60 seconds of waiting
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")
			Return
		}
		WinMinimize, LBRY
	}
	Return
}


GetPermanentLBRYURL(UploadResult){
	SingleQuotationmark = "

	UploadResult := StrSplit(UploadResult, "`n") ; split results by new line

	; Iterate through the array of the results
	Loop % UploadResult.Length() {
		PermanentURL := UploadResult[A_Index]
		if(InStr(PermanentURL, "permanent_url"))
		Break
	}

	; Starting Result: "permanent_url": "lbry://Test-Video-161-Numbered#c9ad9afe54c7178d6f870b59bbe129aef8efc3ff",
	PermanentURL := StrSplit(PermanentURL, "lbry:")
	PermanentURL := "lbry:" . PermanentURL[2]
	PermanentURL := StrReplace(PermanentURL, ",", "")
	PermanentURL := StrReplace(PermanentURL, SingleQuotationmark, "")
	PermanentURL := StrReplace(PermanentURL, "`n", "")
	PermanentURL := StrReplace(PermanentURL, "`r", "")

	; End Result lbry://Test-Video-161-Numbered#c9ad9afe54c7178d6f870b59bbe129aef8efc3ff
	Return PermanentURL
}


GetLBRYCanonicalURL(LBRYJSONObject){ ; input json string
	; ResolveURL := StrSplit(LBRYResolveAPICommand, "lbry://")
	; ResolveURL := "lbry://" . ResolveURL[2]
	; StrReplace(Haystack, SearchText [, ReplaceText, OutputVarCount, Limit := -1])
	LBRYPermanentURLJsonOBJ := StrReplace(LBRYJSONObject, LBRYPermanentURL, "LBRYPermanentURL")
	; clipboard := LBRYPermanentURLJsonOBJ
	; DevModeMsgBox(LBRYPermanentURLJsonOBJ)

	try parsed := JSON.Load(LBRYPermanentURLJsonOBJ)
	try LBRYCanonicalURL := parsed.LBRYPermanentURL.canonical_url

	; DevModeMsgBox(LBRYCanonicalURL)

	if(LBRYCanonicalURL = ""){
		Return "" ; return blank
	}

	; otherwise return the LBRY url
	LBRYCanonicalURL := StrReplace(LBRYCanonicalURL, "lbry://", "https://lbry.tv/")
	Return LBRYCanonicalURL
}


LBRYCMDTextReplacement(LBRYURLSlug){
	SingleQUote = "
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, " ", "_") ; replace all spaces with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, ":", "_") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, ",", "_") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, "?", "") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, "!", "") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, "`;", "_") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, "/", "_") ; replace all colons with dashes 
	; LBRYURLSlug :=  StrReplace(LBRYURLSlug, "?", "") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, "<", "_") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, ">", "_") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, SingleQUote, "") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, "'", "") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, "=", "") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, ";", "") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, ")", "") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, "(", "") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, "___", "_") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, "__", "_") ; replace all colons with dashes 
	LBRYURLSlug :=  StrReplace(LBRYURLSlug, "__", "_") ; replace all colons with dashes 
	Return LBRYURLSlug
}

GetLBRYAPIErrorFromString(UploadResult){
	UploadResultArray := StrSplit(UploadResult, "message")
	LBRYAPIError := UploadResultArray[2]
	; LBRYAPIErrorStrLen := StrLen(LBRYAPIError)

	; LBRYAPIErrorStrToTrim := LBRYAPIErrorStrLen - 3
	; Msgbox % "LBRYAPIErrorStrToTrim: " LBRYAPIErrorStrToTrim
	LBRYAPIError := SubStr(LBRYAPIError, 4)
	LBRYAPIError := StrReplace(LBRYAPIError, "}", "")


	; Msgbox % "LBRYAPIError: " LBRYAPIError
	Return LBRYAPIError

}


LogErrorToTextFile(Error){
/*	if(LogErrorsToTextFile != 1)
	Return
	*/
	ErrorLoggingFile := VideoFolderDir . "\" . "ErrorLogging.txt"
	FormatTime, TodayDate , YYYYMMDDHH24MISS, yyyyMMdd_hhmmss
	text =
	(


		---------------%TodayDate%---------------
		%CurrentSite%: %Error%


		)
	if(LogErrorsToMsgbox)
	Msgbox % "Text: " Text

	FileAppend, %Text%, %ErrorLoggingFile%
	} ; End of Function



	SaveDriverURL()
	AddToTotalVideosUploadedCount(){
		IniRead, TotalVideosUploaded, %SettingsIniFilepath%, General, TotalVideosUploaded, %A_Space%
		TotalVideosUploaded += 1
		IniWrite, %TotalVideosUploaded%, %SettingsIniFilepath%, General, TotalVideosUploaded
	}



	OnMsgBoxPodcastFinish() {
		DetectHiddenWindows, On
		Process, Exist
		If (WinExist("ahk_class #32770 ahk_pid " . ErrorLevel)) {
			WinMove,, 0
		}
	}

	OnMsgBoxSocialMediaPoster() {
		DetectHiddenWindows, On
		Process, Exist
		If (WinExist("ahk_class #32770 ahk_pid " . ErrorLevel)) {
			ControlSetText Button1, Yes
			ControlSetText Button2, Not Now
		}
	}



	Check_For_Stuck_Video_Upload(Index_Number, Upload_Status){
		if(A_index = 1){ ; Create a blank array
			ProgressStatusArray := [] 
			Return
		}

		Message = Upload Status: %Upload_Status%
		SaveOrPostProgress(Message:=Message,PostType:="Tooltip")

		; if we reached the last loop number:
		if(A_index = %Number_of_loops_to_Check_Upload_status%){
			Message = Upload Most Likely Failed: Video Hasn't Finished Uploading after 1 hour. 
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
			SaveDriverURLOFErrorPage()
			Return "Failed"
		}

		; If progress is still the same after a ten minute interval then error out
		if(HasVal(Array_Index_Num_of_Upload_StatusChecks, A_index)){ ; if current index is in Array of index numbers to check status during

			; Send a notification message of upload status
			Message = Upload Status: %Upload_Status%
			SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging")

			; if current upload_status is in the array of values that are updated every 10 mins
			if(HasVal(ProgressStatusArray, Upload_Status)){ 
				Message = Upload Failed (E#4508)`nUpload Stuck at same point for 10 minutes. Stuck Status: %ProgressStatus%
				SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging")  
				SaveDriverURLOFErrorPage()
				Return "Failed"
			}
			ProgressStatusArray.Push(Upload_Status)	; append current status to array
		}
	} ; end of func