; ENVIRONMENT ;------------------------------------------------ #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. ;#Warn ; Enable warnings to assist with detecting common errors. ;DetectHiddenWindows, On #SingleInstance, Force SendMode Input ; Recommended for new scripts due to its superior speed and reliability. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. ;SetKeyDelay, 500 CoordMode, ToolTip, Screen CoordMode, Mouse, Screen ; #NoTrayIcon ; MyGlobalVars() ; import custom global variables ;Menu, Tray, Icon, %A_AHKSyncthingDir%\Icons\ICONNAMEHERE ; Notes/Extra Info/#Includes ;------------------------------------------------ #Include %A_scriptdir%\Libs\RunCMD.ahk ; ENVIRONMENT ;------------------------------------------------ #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. #SingleInstance, Force SendMode Input ; Recommended for new scripts due to its superior speed and reliability. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. Argument = %1% ; Icon taken from: https://github.com/PapirusDevelopmentTeam/papirus-icon-theme/tree/master/Papirus Menu, Tray, Icon, %A_scriptdir%/icon.ico ;------------------------------------------------ ; SETTINGS AND VARIABLES ;------------------------------------------------ ; Filepaths of Browsers Brave = C:\Users\%A_Username%\AppData\Local\BraveSoftware\Brave-Browser\Application\brave.exe BraveIncognito = %Brave% --incognito Chrome = C:\Program Files\Iridium\iridium.exe ChromeIncognito = %Chrome% --incognito ; IniRead, Chromium, C:\Program Files\Iridium\iridium.exe ; Msgbox % "Chromium: " Chromium Chromium = C:\Program Files\Iridium\iridium.exe ChromiumIncognito = %Chromium% --incognito Firefox = C:\Program Files\Mozilla Firefox\firefox.exe FirefoxPrivate = %Firefox% -private-window Librewolf = C:\Program Files\LibreWolf\librewolf.exe LibrewolfPrivate = %Librewolf% -private-window ; https://codeberg.org/strubbl/wallabag-add-article WallabagAddArticleExe = %A_scriptdir%\Libs\wallabag-add-article.exe ; Pocket Settings PocketAccessToken= PocketConsumerKey= ; Telegram Settings TelegramChatID= TelegramBotToken= ; KDE Connect Settings KDEConnectCLIExeFilepath=C:\Program Files\KDE Connect\bin\kdeconnect-cli.exe KDEConnectDeviceOne=OP7 KDEConnectDeviceTwo=S4 KDEConnectDeviceThree= ; yt-dlp Settings AudioDownloadFolder = C:\Users\%A_UserName%\Downloads VideoDownloadFolder = C:\Users\%A_UserName%\Downloads VideoResolution = 720 AudioQuality = Best ; Best OR MP3 ; Todo.txt filepath todotxtFilepath = C:\Users\%A_UserName%\Syncthing\WhiteMountain\Todo\WMT-todo.txt ; Trigger Within These Applications Only GroupAdd, GroupOfBrowsers, ahk_exe firefox.exe GroupAdd, GroupOfBrowsers, ahk_exe chrome.exe GroupAdd, GroupOfBrowsers, ahk_exe brave.exe GroupAdd, GroupOfBrowsers, ahk_exe librewolf.exe GroupAdd, GroupOfBrowsers, ahk_exe iridium.exe #IfWinActive, ahk_group GroupOfBrowsers ; Key Shortcuts: ;Complete List can be found at: ; https://autohotkey.com/docs/KeyList.htm#Advanced_buttons ;# : Windows ;+ : Shift ;^ : Ctrl ;! : Alt ; Open with Browser ; Function arguments should match the variable that contains your browser filepath !f::OpenWithBrowser(Firefox) !+f::OpenWithBrowser(FirefoxPrivate) !b::OpenWithBrowser(Brave) !+b::OpenWithBrowser(BraveIncognito) ; !+c::OpenWithBrowser(Chromium) !c::OpenWithBrowser(ChromiumIncognito) ; Open with Archive.org !a::OpenWithArchiveOrg("SameTab") !+a::OpenWithArchiveOrg("NewTab") ; KDE Connect !o::OpenOnKDEConnectDevice(KDEConnectDeviceOne, KDEConnectCLIExeFilepath) !+o::OpenOnKDEConnectDevice(KDEConnectDeviceTwo, KDEConnectCLIExeFilepath) ; yt-dlp !y::YouTubeDL("Video", VideoResolution, VideoDownloadFolder) !+y::YouTubeDL("Audio", AudioQuality, AudioDownloadFolder) ; pocket ; !p::SavePageToPocket(PocketConsumerKey, PocketAccessToken) ; Wallabag !p::SavePageToWallabag(WallabagAddArticleExe) !d::SaveToLinkDing() ; Telegram !m::SaveToTelegram(TelegramBotToken, TelegramChatID) !+m::SaveToTelegram(TelegramBotToken, TelegramChatID) !t::SaveToTelegram(TelegramBotToken, TelegramChatID) ; Clipboard !x::CopyURLToClipboard() !q::EmailWithOutlook() #if ; Functions ;------------------------------------------------ EmailWithOutlook(){ TabURL := GetURLofActiveTab() if(TabURL = "") Return WindowTitle := GetTitleofActiveTab() ; If outlook is NOT currently open, start it If !WinExist("ahk_class rctrl_renwnd32") ; { run, Outlook WinWait, ahk_class rctrl_renwnd32 sleep, 500 ; Wait for animation to catch up } ; Create outlook COM connection Ol := ComObjCreate("Outlook.Application").CreateItem(0) ;Connect to Outlook object ; Ol.TO := "test@gmail.com" ;Send to Variable content that resides within "Email" Ol.Subject := WindowTitle Ol.HTMLBody := TabURL Ol.Display ; Create gui window of Outlook message ; Ol.Send() ;Sends the email ; CenterTooltipOnScreen("URL Emailed with Outlook", 1000) Return } CopyURLToClipboard(){ TabURL := GetURLofActiveTab() if(TabURL = "") Return Clipboard := TabURL CenterTooltipOnScreen("Tab URL Copied to Clipboard Successfully", 1000) ; ShowTooltip("Tab URL Copied to Clipboard Successfully", 1000) return } AppendToDoTxt(todotxtFilepath){ TabURL := GetURLofActiveTab() if(TabURL = "") Return WindowTitle := GetTitleofActiveTab() InputBox, WindowTitle, Note Title: , Please Input Note Title:,,,,,,,,%WindowTitle% if ErrorLevel return FormatTime, todaydate,,yyyy-MM-dd FileAppend, `n%todaydate% %WindowTitle%: %TabURL% @rl,%todotxtFilepath% return } YouTubeDL(Type, Quality, DownloadFolder){ ; Requires yt-dlp to be installed ; https://github.com/yt-dlp/yt-dlp TabURL := GetURLofActiveTab() if(TabURL = "") Return if(Type = "Video") Command = yt-dlp -f "bestvideo[height<=%Quality%]+bestaudio" --embed-thumbnail --add-metadata --no-mtime -o `"%DownloadFolder%\`%(title)s.`%(ext)s`" %TabURL% if(Type = "Audio"){ if(Quality = "Best") command = yt-dlp -f bestaudio --extract-audio --embed-thumbnail --add-metadata --no-mtime -o `"%DownloadFolder%\`%(title)s.`%(ext)s`" %TabURL% else, command = yt-dlp --extract-audio --audio-format mp3 --audio-quality 5 --no-mtime -o `"%DownloadFolder%\`%(title)s.`%(ext)s`" %TabURL% } run, %comspec% /C %command% Return } OpenWithArchiveOrg(TabOption){ TabURL := GetURLofActiveTab() if(TabURL = "") Return NewURL = https://web.archive.org/web/2/%TabURL% if(TabOption = "SameTab"){ send, %NewURL% send, {Enter} } if(TabOption = "NewTab"){ send, ^t ; new tab sleep, 250 send, %NewURL% send, {Enter} } return } SaveToTelegram(TelegramBotToken, TelegramChatID){ TabURL := GetURLofActiveTab() if(TabURL = "") Return PostURL = https://api.telegram.org/bot%TelegramBotToken%/sendmessage?chat_id=%TelegramChatID%&text=%TabURL% PostStatus := URLDownloadToVar(PostURL) SuccessString = "message_id" if(!InStr(PostStatus, SuccessString)){ MsgBox, Failed to Submit Post return } ; MsgBox CenterTooltipOnScreen("Tab Posted to Telegram Successfully", 1000) ; TrayTip, Browser Tab, Tap Posted to Telegram Successfully, 5 ;, Seconds, Options] ; msgbox ; ShowTooltip("Tab Posted to Telegram Successfully", 1000) return } SaveToLinkDing(){ ; Requires linkding extension to be installed ; https://addons.mozilla.org/en-US/firefox/addon/linkding-extension/ ; TabURL := GetURLofActiveTab() TabTitle := GetTitleofActiveTab() Clipboard := TabTitle send, !+l return } SavePageToWallabag(WallabagAddArticleExe){ ; requires ; https://codeberg.org/strubbl/wallabag-add-article TabURL := GetURLofActiveTab() if(TabURL = "") Return ; Msgbox % "TabURL: " TabURL command = "%WallabagAddArticleExe%" %TabURL% Status := RunCMD(command) TrayTip, Browser Tab, Tap Posted to wallabag Successfully, 5 ;, Seconds, Options] ; Clipboard := command ; run, %comspec% /k "%WallabagAddArticleExe%" %TabURL% ; msgbox ; run, %WallabagAddArticleExe% %TabURL% ; msgbox } SavePageToPocket(PocketConsumerKey, PocketAccessToken){ ; https://getpocket.com/developer/docs/v3/add TabURL := GetURLofActiveTab() if(TabURL = "") Return url_str := "https://getpocket.com/v3/add" objParam := { "url" : TabURL ,"consumer_key" : PocketConsumerKey ,"access_token" : PocketAccessToken } Status := SubmitJsonObject(url_str, objParam) SuccessStatusCode = response_code":"200" if(!InStr(Status, SuccessStatusCode)){ MsgBox, Failed to Submit to Pocket return } CenterTooltipOnScreen("Tab Saved to Pocket Successfully", 1000) return } ShowTooltip(Text, LengthOfTime){ ToolTip, %Text% sleep, %LengthOfTime% ToolTip return } OpenOnKDEConnectDevice(DeviceID, KDEConnectCLIExeFilepath){ TabURL := GetURLofActiveTab() if(TabURL = "") Return command = "%KDEConnectCLIExeFilepath%" -n "%DeviceID%" --share "%TabURL%" ; Clipboard := command Status := RunCMD(command) if(InStr(Status, "error") OR InStr(Status, "Couldn't find device")){ MsgBox, Failed to Send URL.`nIs Device Connected? return } CenterTooltipOnScreen("Tab Sent Successfully", 1000) return } OpenWithBrowser(BrowserFilepath){ TabURL := GetURLofActiveTab() if(TabURL = "") Return run, %BrowserFilepath% %TabURL% } GetURLofActiveTab(){ ClipBackup := ClipboardAll ; Backup the clipboard contents Clipboard := ; Empty clipboard send, {Escape} ; send the escape key to click out of ALT menu in case user is using an ALT+Letter shortcut Loop, 5 { send, ^l ; Send control + l ; Default shortcut to select URL bar in most browsers sleep, 250 send, ^c ; send control + c ClipWait, .5 ; Wait for clipboard to get contents if(ErrorLevel){ ; if error, wait .5 seconds and try sending control + c again sleep, 500 Continue } else, break } send, {Escape} ; escape out of url bar activation TabURL := Clipboard Clipboard := ClipBackup ; restore clipboard contents Return TabURL } GetTitleofActiveTab(){ WinGetTitle, WindowTitle, A WindowTitle := StrReplace(WindowTitle, "LibreWolf", "") ; StrReplace(Haystack, SearchText [, ReplaceText, OutputVarCount, Limit := -1]) WindowTitle := StrReplace(WindowTitle, "Brave", "") WindowTitle := StrReplace(WindowTitle, "Chromium", "") WindowTitle := StrReplace(WindowTitle, "Chrome", "") WindowTitle := StrReplace(WindowTitle, "GitHub - ", "") TitleLen := StrLen(WindowTitle) TitleLen := TitleLen - 3 WindowTitle := SubStr(WindowTitle, 1, TitleLen) ; WindowTitle := StrReplace(WindowTitle, "—", "") ; Msgbox % "WindowTitle: " WindowTitle return WindowTitle } ; ------------------------------- ; CreateFormData - Creates "multipart/form-data" for http post ; Needed for Pocket Posting ; ------------------------------- SubmitJsonObject(url_str, objParam){ CreateFormData(postData, hdr_ContentType, objParam) whr := ComObjCreate("WinHttp.WinHttpRequest.5.1") whr.Open("POST", url_str, true) whr.SetRequestHeader("Content-Type", hdr_ContentType) ; whr.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko") ; ??????? whr.Option(6) := False ; No auto redirect whr.Send(postData) whr.WaitForResponse() json_resp := whr.ResponseText whr := ; Clipboard := json_resp ; free COM object return json_resp ; if(InStr(json_resp, "error_code")) ; Return json_resp } ; Used for WinHttp.WinHttpRequest.5.1, Msxml2.XMLHTTP ... CreateFormData(ByRef retData, ByRef retHeader, objParam) { New CreateFormData(retData, retHeader, objParam) } ; Used for WinInet CreateFormData_WinInet(ByRef retData, ByRef retHeader, objParam) { New CreateFormData(safeArr, retHeader, objParam) size := safeArr.MaxIndex() + 1 VarSetCapacity(retData, size, 1) DllCall("oleaut32\SafeArrayAccessData", "ptr", ComObjValue(safeArr), "ptr*", pdata) DllCall("RtlMoveMemory", "ptr", &retData, "ptr", pdata, "ptr", size) DllCall("oleaut32\SafeArrayUnaccessData", "ptr", ComObjValue(safeArr)) } Class CreateFormData { __New(ByRef retData, ByRef retHeader, objParam) { CRLF := "`r`n" Boundary := this.RandomBoundary() BoundaryLine := "------------------------------" . Boundary ; Loop input paramters binArrs := [] For k, v in objParam { If IsObject(v) { For i, FileName in v { str := BoundaryLine . CRLF . "Content-Disposition: form-data; name=""" . k . """; filename=""" . FileName . """" . CRLF . "Content-Type: " . this.MimeType(FileName) . CRLF . CRLF binArrs.Push( BinArr_FromString(str) ) binArrs.Push( BinArr_FromFile(FileName) ) binArrs.Push( BinArr_FromString(CRLF) ) } } Else { str := BoundaryLine . CRLF . "Content-Disposition: form-data; name=""" . k """" . CRLF . CRLF . v . CRLF binArrs.Push( BinArr_FromString(str) ) } } str := BoundaryLine . "--" . CRLF binArrs.Push( BinArr_FromString(str) ) retData := BinArr_Join(binArrs*) retHeader := "multipart/form-data; boundary=----------------------------" . Boundary } RandomBoundary() { str := "0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z" Sort, str, D| Random str := StrReplace(str, "|") Return SubStr(str, 1, 12) } MimeType(FileName) { n := FileOpen(FileName, "r").ReadUInt() Return (n = 0x474E5089) ? "image/png" : (n = 0x38464947) ? "image/gif" : (n&0xFFFF = 0x4D42 ) ? "image/bmp" : (n&0xFFFF = 0xD8FF ) ? "image/jpeg" : (n&0xFFFF = 0x4949 ) ? "image/tiff" : (n&0xFFFF = 0x4D4D ) ? "image/tiff" : "application/octet-stream" } } ;############################################################################################################# ; Update: 2015-6-4 - Added BinArr_ToFile() BinArr_FromString(str) { oADO := ComObjCreate("ADODB.Stream") oADO.Type := 2 ; adTypeText oADO.Mode := 3 ; adModeReadWrite oADO.Open oADO.Charset := "UTF-8" oADO.WriteText(str) oADO.Position := 0 oADO.Type := 1 ; adTypeBinary oADO.Position := 3 ; Skip UTF-8 BOM return oADO.Read, oADO.Close } BinArr_FromFile(FileName) { oADO := ComObjCreate("ADODB.Stream") oADO.Type := 1 ; adTypeBinary oADO.Open oADO.LoadFromFile(FileName) return oADO.Read, oADO.Close } BinArr_Join(Arrays*) { oADO := ComObjCreate("ADODB.Stream") oADO.Type := 1 ; adTypeBinary oADO.Mode := 3 ; adModeReadWrite oADO.Open For i, arr in Arrays oADO.Write(arr) oADO.Position := 0 return oADO.Read, oADO.Close } BinArr_ToString(BinArr, Encoding := "UTF-8") { oADO := ComObjCreate("ADODB.Stream") oADO.Type := 1 ; adTypeBinary oADO.Mode := 3 ; adModeReadWrite oADO.Open oADO.Write(BinArr) oADO.Position := 0 oADO.Type := 2 ; adTypeText oADO.Charset := Encoding return oADO.ReadText, oADO.Close } BinArr_ToFile(BinArr, FileName) { oADO := ComObjCreate("ADODB.Stream") oADO.Type := 1 ; adTypeBinary oADO.Open oADO.Write(BinArr) oADO.SaveToFile(FileName, 2) oADO.Close } ; -------------------------------/CreateFormData - Creates "multipart/form-data" for http post-------------------------------