;---FUNCTIONS----------------------------------------------------------------------- ; Misc Functions that are called by both the Video and Social Media poster ; -------------------------------Variables------------------------------- ; Declare global variables here so they don't have to be declared in each script global ChromeTabsURLArray global DriverTitleArray global LastWebsitePostURL global CurrentTabURL global URLOfLastErrorPage DevModeMsgBox(Message){ if(!DevMode) return Msgbox, 4096, DevModeMsgBox, %Message% return } ; -------------------------------SaveOrPostProgress------------------------------- ; PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging,DiscordVideos" SaveOrPostProgress(Message:="",PostType:=""){ MessageBU := Message ; Msgbox % "PostType: " PostType ; Msgbox % "CurrentSite: " CurrentSite if(CurrentSite != "") Message := CurrentSite . ": " . Message if(InStr(PostType, "Tooltip")){ TooltipThis(Message) } if(InStr(PostType, "ErrorLoggingTextFile")){ Func_LogErrorsToTextFile(Message) } if(InStr(PostType, "ErrorSummaryVar")){ Func_LogErrorsToVar(Message) } if(InStr(PostType, "DiscordErrorLogging")){ PostToDiscordChannel(Message,DiscordErrorLoggingWebhookBotURL) } if(InStr(PostType, "DevModeMsgBox")){ DevModeMsgBox(Message) } if(InStr(PostType, "DiscordVideos")){ Message := MessageBU PostToDiscordChannel(Message,DiscordVideosWebhookURL) } if(InStr(PostType, "DiscordParler")){ Message := MessageBU PostToDiscordChannel(Message,DiscordParlerWebhookURL) } } ; -------------------------------/SaveOrPostProgress------------------------------- ; -------------------------------TooltipThis------------------------------- TooltipThis(String){ ; Xposition := StrLen(String) StringFirstLine := StrSplit(String, "`n") StringFirstLine := StringFirstLine[1] Xposition := StrLen(StringFirstLine) ; Msgbox % "String: " String Xposition := Xposition * 4 X := (A_ScreenWidth / 2) - Xposition ; Msgbox % "X: " X if(ShowTooltipProgress){ ToolTip, %String%, %X%, 0 } } ; -------------------------------/TooltipThis------------------------------- ;------------------------------------------------ TimedToolTip(Text, x="", y="",RemoveAfterTime:=2000, SetWhichToolTip="") { if(X = ""){ Xposition := StrLen(Text) ; Msgbox % "Xposition: " Xposition Xposition := Xposition * 4 ; Xposition := 0 X := (A_ScreenWidth / 2) - Xposition ; Msgbox % "X: " X } (y = "")?(y:=0):(y:=y) ; Msgbox % "y: " y ToolTip, %Text%, %X%, %Y% SetTimer, RMApp_ToolTipRASub, % - RemoveAfterTime return RMApp_ToolTipRASub: ToolTip,,,, %WhichToolTip% return } ; -------------------------------LogErrorsToTextFile------------------------------- Func_LogErrorsToTextFile(Text){ ; Do not log if we do not have an errorlog filepath if(ErrorLoggingFilePath = "") return ; ErrorLoggingFile := Filepath FormatTime, TodayDate , YYYYMMDDHH24MISS, yyyyMMdd_hhmmss text =`n`n---------------%TodayDate%---------------`n%Text% FileAppend, %Text%, %ErrorLoggingFilePath% } ; -------------------------------/LogErrorsToTextFile------------------------------- ; -------------------------------LogErrorsToVar------------------------------- Func_LogErrorsToVar(Text){ ErrorLogVar .= "`n" . Text } ; -------------------------------/LogErrorsToVar------------------------------- ; -------------------------------CheckDirExistAndCreate------------------------------- ; Check if directory exists and if not, create it CheckDirExistAndCreate(Path){ if(!FileExist(Path)){ FileCreateDir, %Path% } } ; -------------------------------/CheckDirExistAndCreate------------------------------- ; Script Updates ; ------------------------------------------------ CheckIfUpdateAvailable(Filepath, CurrentVersion){ FileRead, ScriptUpdateContents, %Filepath% FileContents := StrSplit(ScriptUpdateContents, "ScriptVersion") FileContents := FileContents[2] FileContents := StrSplit(FileContents, "`n") UpdateVersion := FileContents[1] ; msgbox % UpdateVersion if(!InStr(UpdateVersion, CurrentVersion)){ ; Update found for file, write to settings.ini for next time script is run Message = Update Available to Download SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile") Return True } Return False } /* */ InputFilePathIntoOpenWindow(Filepath){ ; Msgbox % "Filepath: " Filepath Message = Waiting for "Open" window to appear to input filepath into SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile") ; Tooltip,Waiting for "Open" window to appear to input filepath into,850,0 ; WinWait, Open WinWait,Open,,5 ; Wait for 10 seconds for window if(ErrorLevel) { ; msgbox, failed to find window. Return "Failed" } WinActivate, Open sleep, 1000 ControlSetText, Edit1, %Filepath%, Open sleep, 1000 ControlSend, Edit1, {Enter}, Open sleep, 1000 ; Do an extra check in case the Open window is still open. OpenWindowExist := WinExist("Open") if(OpenWindowExist) ControlSend, Edit1, {Enter}, Open ToolTip, } /* */ ; -------------------------------FileXPro Get File Attributes------------------------------- ;https://www.autohotkey.com/boards/viewtopic.php?t=59882 Filexpro( sFile := "", Kind := "", P* ) { ; v.90 By SKAN on D1CC @ goo.gl/jyXFo9 Local Static xDetails If ( sFile = "" ) { ; Deinit static variable xDetails := "" Return } fex := {}, _FileExt := "" Loop, Files, % RTrim(sfile,"\*/."), DF { If not FileExist( sFile:=A_LoopFileLongPath ) { Return } SplitPath, sFile, _FileExt, _Dir, _Ext, _File, _Drv If ( p[p.length()] = "xInfo" ) ; Last parameter is xInfo { p.Pop() ; Delete parameter fex.SetCapacity(11) ; Make room for Extra info fex["_Attrib"] := A_LoopFileAttrib fex["_Dir"] := _Dir fex["_Drv"] := _Drv fex["_Ext"] := _Ext fex["_File"] := _File fex["_File.Ext"] := _FileExt fex["_FilePath"] := sFile fex["_FileSize"] := A_LoopFileSize fex["_FileTimeA"] := A_LoopFileTimeAccessed fex["_FileTimeC"] := A_LoopFileTimeCreated fex["_FileTimeM"] := A_LoopFileTimeModified } Break } If Not ( _FileExt ) ; Filepath not resolved { Return } objShl := ComObjCreate("Shell.Application") objDir := objShl.NameSpace(_Dir) objItm := objDir.ParseName(_FileExt) If ( VarSetCapacity(xDetails) = 0 ) ; Init static variable { i:=-1, xDetails:={}, xDetails.SetCapacity(309) While ( i++ < 309 ) { xDetails[ objDir.GetDetailsOf(0,i) ] := i } xDetails.Delete("") } If ( Kind and Kind <> objDir.GetDetailsOf(objItm,11) ) ; File isn't desired kind { Return } i:=0, nParams:=p.Count(), fex.SetCapacity(nParams + 11) While ( i++ < nParams ) { Prop := p[i] If ( (Dot:=InStr(Prop,".")) and (Prop:=(Dot=1 ? "System":"") . Prop) ) { fex[Prop] := objItm.ExtendedProperty(Prop) Continue } If ( PropNum := xDetails[Prop] ) > -1 { fex[Prop] := ObjDir.GetDetailsOf(objItm,PropNum) Continue } } fex.SetCapacity(-1) Return fex } ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; GuiButtonIcon ;------------------------------------------------ GuiButtonIcon(Handle, File, Index := 1, Options := "") { RegExMatch(Options, "i)w\K\d+", W), (W="") ? W := 16 : RegExMatch(Options, "i)h\K\d+", H), (H="") ? H := 16 : RegExMatch(Options, "i)s\K\d+", S), S ? W := H := S : RegExMatch(Options, "i)l\K\d+", L), (L="") ? L := 0 : RegExMatch(Options, "i)t\K\d+", T), (T="") ? T := 0 : RegExMatch(Options, "i)r\K\d+", R), (R="") ? R := 0 : RegExMatch(Options, "i)b\K\d+", B), (B="") ? B := 0 : RegExMatch(Options, "i)a\K\d+", A), (A="") ? A := 4 : Psz := A_PtrSize = "" ? 4 : A_PtrSize, DW := "UInt", Ptr := A_PtrSize = "" ? DW : "Ptr" VarSetCapacity( button_il, 20 + Psz, 0 ) NumPut( normal_il := DllCall( "ImageList_Create", DW, W, DW, H, DW, 0x21, DW, 1, DW, 1 ), button_il, 0, Ptr ) ; Width & Height NumPut( L, button_il, 0 + Psz, DW ) ; Left Margin NumPut( T, button_il, 4 + Psz, DW ) ; Top Margin NumPut( R, button_il, 8 + Psz, DW ) ; Right Margin NumPut( B, button_il, 12 + Psz, DW ) ; Bottom Margin NumPut( A, button_il, 16 + Psz, DW ) ; Alignment SendMessage, BCM_SETIMAGELIST := 5634, 0, &button_il,, AHK_ID %Handle% return IL_Add( normal_il, File, Index ) } ; \GuiButtonIcon ;------------------------------------------------ ToggleTestingMode(){ IniRead, TestingMode, Settings.ini, General, TestingMode, 0 ; Msgbox % "TestingMode: " TestingMode if(TestingMode) IniWrite, 0, Settings.ini, General, TestingMode else, IniWrite, 1, Settings.ini, General, TestingMode } ToggleManualSubmit(){ IniRead, ManualSubmit, Settings.ini, General, ManualSubmit, 0 ; Msgbox % "TestingMode: " TestingMode if(ManualSubmit) IniWrite, 0, Settings.ini, General, ManualSubmit else, IniWrite, 1, Settings.ini, General, ManualSubmit } ToggleDevMode(){ IniRead, DevMode, Settings.ini, General, DevMode, 0 ; Msgbox % "TestingMode: " TestingMode if(DevMode) IniWrite, 0, Settings.ini, General, DevMode else, IniWrite, 1, Settings.ini, General, DevMode } FormatTextToJSText(Var){ ; Replaces AHK newline characters with javascript ones /*\b Backspace \f Form Feed \n New Line - done \r Carriage Return \t Horizontal Tabulator \v Vertical Tabulator \' Single quote - done \" Double quote - done \\ Backslash - done */ SingleQuotationmark = " ; Variable of Escaped Symbols EscapedSingleQuote = \' EscapedDoubleQuote = \" EscapedBackslash = \\ EscapedNewLine = \n ; Replace each character that needs replacing in the text string Var := StrReplace(Var, "\", EscapedBackslash) ; needed otherwise selenium will error out Var := StrReplace(Var, "`n", EscapedNewLine) ; needed otherwise selenium will error out Var := StrReplace(Var, "`r", "") ; needed otherwise selenium will error out Var := StrReplace(Var, SingleQuotationmark, EscapedDoubleQuote) ; needed otherwise selenium will error out Var := StrReplace(Var, "'", EscapedSingleQuote) ; needed otherwise selenium will error out ; Var := StrReplace(Var, "`r", "") ; needed otherwise selenium will error out Return Var } SaveCurrentChromeVersionToIniFile(){ if(InstalledChromeVersion = "") InstalledChromeVersion := GetInstalledChromeVersion() IniWrite, %InstalledChromeVersion%, Settings.ini, Misc, ChromeVersion } ; -------------------------------HasVal------------------------------- ; Function needed for finding a value in an array HasVal(haystack, needle) { if !(IsObject(haystack)) || (haystack.Length() = 0) return 0 for index, value in haystack if (value = needle) return index return 0 } HasSubstringVal(haystack, needle) { if !(IsObject(haystack)) || (haystack.Length() = 0) return 0 for index, value in haystack if (InStr(value, Needle)) return index return 0 } ; -------------------------------Functions------------------------------- ; https://www.autohotkey.com/docs/v2/Functions.htm#Variadic Join(sep, params*) { For index, param in params str .= param . sep return SubStr(str, 1, -StrLen(sep)) } 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 /* */ AddToTotalVideosUploadedCount(){ ; IniRead, TotalVideosUploaded, %SettingsIniFilepath%, General, TotalVideosUploaded, %A_Space% TotalVideosUploaded += 1 ; IniWrite, %TotalVideosUploaded%, %SettingsIniFilepath%, General, TotalVideosUploaded } 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 /* */ ; Find the longest word in a string of words FindLongestWordInString(m, calloutNumber, pos, haystack, pattern){ Global wordLength, longestWord len := StrLen(m) If ( len > wordLength ) { wordLength := len longestWord := m ; MsgBox, %m% } } /* */ ; Split a long string into multiple pieces based on the string lengtht you want and return an array with all strings SplitStringWithSentences(text, maxChunkSize) { sentences := StrSplit(text, "\. ") ; split at period with space after it currentChunk := "" chunks := [] Loop, % sentences.Length() { sentence := sentences[A_Index] CurrentChunkAndSentence := currentChunk . sentence ; Msgbox % "CurrentChunkAndSentence: " CurrentChunkAndSentence ; msgbox % StrLen(CurrentChunkAndSentence) if (StrLen(CurrentChunkAndSentence) <= maxChunkSize) { currentChunk .= sentence . "\. " } else { chunks.Push(currentChunk) currentChunk := sentence . "\. " } } if (currentChunk != "") chunks.Push(currentChunk) return chunks } CreateErrorLoggingFiles(Directory := ""){ FormatTime, TodayDate, YYYYMMDDHH24MISS, yyyyMMdd_hhmmss ErrorLoggingDirectory := Directory if(ErrorLoggingDirectory = ""){ ErrorLoggingDirectory := A_ScriptDir . "\Lib\ErrorLogging" ; If directory for error logging doesn't exist, create it if(!FileExist(ErrorLoggingDirectory)) FileCreateDir, %ErrorLoggingDirectory% ErrorLoggingDirectory := ErrorLoggingDirectory . "\" . TodayDate . "_" . ScriptAbbreviatedName } ; Msgbox % "ErrorLoggingDirectory: " ErrorLoggingDirectory FileCreateDir, %ErrorLoggingDirectory% ; Create variables with filepaths that content will be saved to. global ErrorLoggingFilePath := ErrorLoggingDirectory . "\" . "ErrorLogging.txt" global StatusFileFilePath := ErrorLoggingDirectory . "\" . "PostStatus.ini" global PostTitleFilePath := ErrorLoggingDirectory . "\" . "PostTitle.txt" global PostBodyFilePath := ErrorLoggingDirectory . "\" . "PostBody.txt" global PostTagsFilePath := ErrorLoggingDirectory . "\" . "PostTags.txt" PostStatusesFilepath := ErrorLoggingDirectory . "\" . "Status.ini" ; Msgbox % "ErrorLoggingDirectory: " ErrorLoggingDirectory Return } ; if passed argument is .exe file, then script has just been updated and we need to delete the old .exe file CheckIfUpdateInstalled(PassedInArgument :=""){ if(InStr(PassedInArgument,".exe")){ FileDelete, %PassedInArgument% if(ErrorLevel){ ; most likely because the old version hasn't finished exiting yet Message = Failed to Delete Old .exe file after Updating SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar") } } } ; https://www.autohotkey.com/boards/viewtopic.php?t=59936 GetDateOrdinalSuffix(D) { Static Special := {1: "st", 2: "nd", 3: "rd", 21: "st", 22: "nd", 23: "rd", 31: "st"} Return D . ((S := Special[D]) ? S : "th") } ; Calculate the aspect ratio of a video/image using the width + height getAspectRatio(width, height) { gcd := gcdFunc(width, height) return round(width/gcd) ":" round(height/gcd) } ; The gcdFunc() is a helper function that calculates the GCD (greatest common divisor) of two numbers using the Euclidean algorithm. ; Used for calculating aspect ratio of Videos gcdFunc(a, b) { while b t := b, b := Mod(a, b), a := t return a } ; OnMsgbox - Custom Msgbox Screens ;------------------------------------------------ ConfirmBeforeSubmitMsgboxFunc(){ /* ; Snippet to for check: if (ConfirmBeforeSubmit && ConfirmBeforeSubmitMsgboxFunc() != true) { Message = User Selected STOP button when asked for confirmation. Cancelling Rest of Site Upload. SaveOrPostProgress(Message:=Message, PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging") return } */ OnMessage(0x44, "OnMsgBoxUserConfirmation") MsgBox 0x21, User Confirmation, Please check that all data was input correctly and fix any mistakes and then click PROCEED to finalize the Upload.`n`nClick STOP to cancel the rest of this Upload and move on to the next website. OnMessage(0x44, "") IfMsgBox OK, { return true } Else IfMsgBox Cancel, { Message = User Selected STOP button when asked for confirmation. Cancelling Rest of Site Upload. Return %Message% } } OnMsgBoxUpdateAvailable() { DetectHiddenWindows, On Process, Exist If (WinExist("ahk_class #32770 ahk_pid " . ErrorLevel)) { ControlSetText Button1, Cancel ControlSetText Button2, Install } } ; Show a user confirmation msgbox with a PROCEED and STOP buttons ; Used by the "Confirm before Submit" checkbox OnMsgBoxUserConfirmation() { DetectHiddenWindows, On Process, Exist If (WinExist("ahk_class #32770 ahk_pid " . ErrorLevel)) { ControlSetText Button1, PROCEED ControlSetText Button2, STOP } } OnMsgBoxConfirmChromiumOverwrite() { DetectHiddenWindows, On Process, Exist If (WinExist("ahk_class #32770 ahk_pid " . ErrorLevel)) { ControlSetText Button1, Cancel ControlSetText Button2, Yes } } 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 } }