;README (INSTRUCTIONS START ON LINE 44; CODE STARTS ON LINE 169) ; ;Pastebin API Hotkeys (MS Windows only) ;AutoHotkey V2 32-Bit program (Compatible with 64-bit MS Windows) ; ;FEATURES: ; ;0. Correctly handles UTF-8 http request responses from pastebin.com ;1. Create a new paste from highlighted text (confirms overwrite if an existing ;filename is specified and creates timestamped backup copy locally) ;2. Create new pastes from highlighted files and/or folders (confirms overwrite ;for existing files and creates timestamped backup copies locally)(currenty ;supports files that match extensions .txt, .md, .ahk, .xml, .py, .pl, .php, ;.ps1, .js, .csv, and .tsv -- More extensions can be added by simply ;adjusting the regular expression on lines 760 and 773) ;3. Download the content of an existing paste ;4. Append to an existing paste (creates timestamped backup copy of original ;locally)(Adds a Windows new line character `r`n to separate original content and ;appended content) ;5. Backup pastes based on regular expression (creates time_stamped local folder ;of downloaded pastes) ;6. Delete pastes based on regular expression (creates timestamped backup copies ;stored locally) ;7. List all pastes ;8. List pastes based on regular expression ;9. Get a paste link for an existing paste name ;10. Log into Pastebin.com (automates your browser through programmatic key ;strokes) (currently works when Opera is default browser) ; ;HOTKEYS (numbers correspond to the above 1 through 10): ; ;1. Create new paste = ^!1 (Ctrl+Alt+1) ;2. Create new paste from files/folders = ^!2 (Ctrl+Alt+2) ;3. Download existing paste = ^!3 (Ctrl+Alt+3) ;4. Append to existing paste = ^!4 (Ctrl+Alt+4) ;5. Backup pastes = ^!5 (Ctrl+Alt+5) ;6. Delete pastes = ^!6 (Ctrl+Alt+6) ;7. List all pastes = ^!7 (Ctrl+Alt+7) ;8. List pastes = ^!8 (Ctrl+Alt+8) ;9. Get paste link = ^!9 (Ctrl+Alt+9) ;10. Log into pastebin = ^!0 (Ctrl+Alt+0) ;11. Help message = ^!h (Ctrl+Alt+h) ; ;HOW TO USE: ; ;1. Download the latest version of AutoHotkey Version 2 (as of 2019-1-23) ;https://www.autohotkey.com/download/2.0/AutoHotkey_2.0-a100-52515e2.zip ; ;2. Unzip the file "AutoHotkey_2.0-a100-52515e2.zip" ; ;3. Double click the folder "AutoHotkey_2.0-a100-52515e2" ; ;4. Copy the executable "AutoHotkeyU32.exe" and place it a separate folder. ; ;5. Put this file "pastebin_api.ahk" in the same folder as the ;"AutoHotkeyU32.exe" executable. ; ;6. Create a folder called "configuration" ; ;7. In the "configuration" folder, create the "pastebin.txt" configuration file ;(see lines 72-121 for more information on this step. ; ;8. In the folder containing the "AutoHotkeyU32.exe" executable, open Windows ;Powershell by clicking File -> Open Windows Powershell from Windows Explorer. ; ;9. Type ".\AutoHotkeyU32.exe pastebin_api.ahk" ; ;10. Use the Hotkeys in lines 32-42 to interact with the Pastebin.com API ; ;CONFIGURATION & EXTRA INFORMATION: ; ;1. Configuration information is stored in local file: ;configuration/pastebin.txt ; ;Please create the folder "configuration" in the same folder as the script, and ;then create the "pastebin.txt" configuration file in the "configuration" folder ;you just created. ; ;###Sample configuration configuration/pastebin.txt file (lines 81-87). Please ;create a similar one### ;api_dev_key=APIKEY ;api_user_name=USERNAME ;api_user_password=PASSWORD ;api_user_key= ;api_paste_format=text ;api_paste_private=2 ;api_paste_expire_date=N ;######################################################################### ; ;Get your api_dev_key by logging into Pastebin.com and going to ;https://pastebin.com/api ; ;api_user_name is your Pastebin.com login username. ; ;api_user_password is your Pastebin.com login password. ; ;If the api_user_key is blank, the program will automatically generate it and ;store it after starting the program. If you already have an api_user_key, enter ;it after the "=" sign. No whitespace allowed. ; ;Valid api_paste_format values are available at https://pastebin.com/api ;An api_paste_format of "text" means "no syntax highlighting" ; ;Valid api_paste_private values are 0, 1, 2, which mean public, unlisted, and ;private, respectively. ; ;Value api_paste_expire_date values are the following: ;N = Never ;10M = 10 Minutes ;1H = 1 Hour ;1D = 1 Day ;1W = 1 Week ;2W = 2 Weeks ;1M = 1 Month ;6M = 6 Months ;1Y = 1 Year ; ;2. The program will not make any changes to existing Pastebin.com pastes ;without first backing up the existing file locally. If the backup fails, the ;thread will exit and nothing will be changed to the paste at Pastebin.com. This ;is important when overwriting, appending to, and deleting pastes. ; ;CURRENTLY KNOWN LIMITATIONS: ; ;1. When files are overwritten for paste or append, the original Pastebin.com ;link is deleted and a new link is generated and saved to the clipboard. ;2. Since the pastebin.com API does not support folders, please ensure that ;there are no files with duplicated names when using the file/folder paste hotkey ;(Ctrl+Alt+2). In the event that there are duplicated names and something gets ;deleted from pastebin.com, please check your local pastebin_backup folder for ;timestamped backups. ;3. This program only supports up to 1,000 files since this is the limitation ;imposed by the pastebin.com API when retrieving a list of pastes. ;4. This program works with UTF-8 encoded files. If your files use another ;encoding, strange things may happen. ;5. Due to the nature of the pastebin.com service, original file permissions and ;attributes such as modification date are not reflected in files downloaded or ;backed up from pastebin.com ;6. The pastebin.com API seems to remove trailing carriage returns and newlines ;from pastes, so if your paste require that these carriage returns and newlines ;be maintained (for example, C language files), then please be forewarned about ;this. ; ;SUPPORT ;No support is provided. ; ;LICENSE ; ;This software is completely free. You can do whatever you want with it. ; ;LEGAL DISCLAIMER ; ;Short Version ;USE AT YOUR OWN RISK. ; ;Long Version ;THIS SOFTWARE IS PROVIDED FOR THE PURPOSE OF ILLUSTRATION ONLY AND IS NOT ;INTENDED TO BE USED IN A PRODUCTION ENVIRONMENT. ; ;THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ;FROM, OUT OF OR IN CONNECTION WITH THIS SOFTWARE OR THE USE OR OTHER DEALINGS ;IN THIS SOFTWARE. ;###########CODE STARTS HERE#################### ;#Warn ; Enable warnings to assist with detecting common errors. SendMode("Input") ; Recommended for new scripts due to its superior speed and reliability. SetWorkingDir(A_ScriptDir) ; Ensures a consistent starting directory. ;AUTOHOTKEY V2 32-BIT SCRIPT ;##########Default settings##################### pastebin_backup_dir := A_WorkingDir . '\pastebin_backup\' If !DirExist(pastebin_backup_dir) { DirCreate(pastebin_backup_dir) } ;##########Get Pastebin.com credentials##################### credentials_file := A_WorkingDir . '\configuration\pastebin.txt' If !FileExist(credentials_file) { MsgBox("You need to create your credentials file at:`n`n" . credentials_file . "`n`nCheck the help information provided at the top of the script for instructions on creating this file.") ExitApp() } api_dev_key := '' api_user_name := '' api_user_password := '' api_user_key := '' api_paste_format := '' api_paste_private := '' api_paste_expire_date := '' Loop Read, credentials_file { line := StrSplit(A_LoopReadLine, "=") If line[1] = 'api_dev_key' { api_dev_key := line[2] } Else If line[1] = 'api_user_name' { api_user_name := line[2] } Else If line[1] = 'api_user_password' { api_user_password := line[2] } Else If line[1] = 'api_user_key' { api_user_key := line[2] } Else If line[1] = 'api_paste_format' { api_paste_format := line[2] } Else If line[1] = 'api_paste_private' { api_paste_private := line[2] } Else If line[1] = 'api_paste_expire_date' { api_paste_expire_date := line[2] } } If !api_user_key { result := MsgBox("No api_user_key! Would you like to generate one? (Press Yes or No)",, "YesNo") If result = "Yes" { api_user_name := UriEncode(api_user_name) api_user_password := UriEncode(api_user_password) post_fields := 'api_dev_key=' . api_dev_key . '&api_user_name=' . api_user_name . '&api_user_password=' . api_user_password url := "https://pastebin.com/api/api_login.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response backup_file := pastebin_backup_dir . "pastebin.txt" response := HttpObj.ResponseText status := HttpObj.Status If status = '200' { api_user_key := response FileCopy(credentials_file, backup_file, '1') If !(FileExist(backup_file) And FileGetSize(backup_file) And CheckAgeConfig(credentials_file, backup_file)) { MsgBox("Local backup of " . credentials_file . " failed! Aborting overwrite...") CheckKeyState() Exit() } FileDelete(credentials_file) content := "api_dev_key=" . api_dev_key . "`napi_user_name=" . api_user_name . "`napi_user_password=" . api_user_password . "`napi_user_key=" . api_user_key . "`napi_paste_format=" . api_paste_format . "`napi_paste_private=" . api_paste_private . "`napi_paste_expire_date=" . api_paste_expire_date FileAppend(content, credentials_file) MsgBox('api_user_key ' . api_user_key . ' appended to `n' . credentials_file) } Else { MsgBox("There was a problem generating the api_user_key. Make sure your credentials file is correct or try again a little later.") CheckKeyState() Exit() } } Else { CheckKeyState() Exit() } } ;##########Utility functions##################### OpenWindowPastebin(win_title, tab_title, run_command, username, password) { If WinExist(win_title) { WinActivate(win_title) Sleep(150) If WinActive(tab_title) { Loop 23 { SendInput("{Tab}") Sleep(150) } SendInput(username) Sleep(500) SendInput("{Tab}") Sleep(250) SendInput(password) Sleep(500) SendInput("{Enter}") Sleep(250) Return } Loop 9 { SendInput("{Ctrl down}{" . A_Index . "}") Sleep(200) SendInput("{Ctrl up}") Sleep(200) If WinActive(tab_title) { Loop 23 { SendInput("{Tab}") Sleep(150) } SendInput(username) Sleep(500) SendInput("{Tab}") Sleep(250) SendInput(password) Sleep(500) SendInput("{Enter}") Sleep(250) Return } } Run(run_command) While !WinActive(tab_title) { Sleep(100) } Sleep(7000) Loop 23 { SendInput("{Tab}") Sleep(150) } SendInput(username) Sleep(500) SendInput("{Tab}") Sleep(250) SendInput(password) Sleep(500) SendInput("{Enter}") Sleep(250) Return } Else { Run(run_command) While !WinActive(tab_title) { Sleep(100) } Sleep(7000) Loop 23 { SendInput("{Tab}") Sleep(150) } SendInput(username) Sleep(500) SendInput("{Tab}") Sleep(250) SendInput(password) Sleep(500) SendInput("{Enter}") Sleep(250) Return } } CheckAge(file) { ; check that file modification date is < 10 seconds old time_now := A_Now file_mod_time := FileGetTime(file, "M") age := DateDiff(time_now, file_mod_time, "seconds") If age < 10 { Return(True) } Else { Return(False) } } CheckAgeConfig(orig, copy) { ; check that file modification date is the same orig_mod_time := FileGetTime(orig, "M") copy_mod_time := FileGetTime(copy, "M") age := DateDiff(orig_mod_time, copy_mod_time, "seconds") If age = 0 { Return(True) } Else { Return(False) } } CheckKeyState() { Sleep(1000) While 1 { If GetKeyState("Control") { MsgBox("Control key is down") Continue } If GetKeyState("Alt") { MsgBox("Alt key is down") Continue } Break } } UriEncode(string) { string := RegExReplace(string, "%([025789ACD]{2})", "%25$1") string := RegExReplace(string, "'", "%27") string := RegExReplace(string, '"', "%22") string := RegExReplace(string, "\\", "%5C") string := RegExReplace(string, "\n", "%0A") string := RegExReplace(string, "\r", "%0D") string := RegExReplace(string, "\(", "%28") string := RegExReplace(string, "\)", "%29") oSC := ComObjCreate("ScriptControl") oSC.Language := "JScript" Script := 'var Encoded = encodeURIComponent(' . '"' . string . '")' oSC.ExecuteStatement(Script) string := oSC.Eval("Encoded") string := RegExReplace(string, "%2527", "%27") string := RegExReplace(string, "%2522", "%22") string := RegExReplace(string, "%255C", "%5C") string := RegExReplace(string, "%250A", "%0A") string := RegExReplace(string, "%250D", "%0D") string := RegExReplace(string, "%2528", "%28") string := RegExReplace(string, "%2529", "%29") string := RegExReplace(string, "%2525([025789ACD]{2})", "%25$1") Return(string) } BcryptMd5(string) { Static BCRYPT_MD5_ALGORITHM := "MD5" Static BCRYPT_HASH_LENGTH := "HashDigestLength" If !(hBCRYPT := DllCall("LoadLibrary", "str", "bcrypt.dll", "ptr")) throw Exception("Failed to load bcrypt.dll", -1) If (NT_STATUS := DllCall("bcrypt\BCryptOpenAlgorithmProvider", "ptr*", hAlgo, "ptr", &BCRYPT_MD5_ALGORITHM, "ptr", 0, "uint", 0) != 0) throw Exception("BCryptOpenAlgorithmProvider: " NT_STATUS, -1) If (NT_STATUS := DllCall("bcrypt\BCryptGetProperty", "ptr", hAlgo, "ptr", &BCRYPT_HASH_LENGTH, "uint*", cbHash, "uint", 4, "uint*", cbResult, "uint", 0) != 0) throw Exception("BCryptGetProperty: " NT_STATUS, -1) VarSetCapacity(pbInput, StrPut(string, "UTF-8"), 0) && cbInput := StrPut(string, &pbInput, "UTF-8") - 1, VarSetCapacity(pbHash, cbHash, 0) If (NT_STATUS := DllCall("bcrypt\BCryptHash", "ptr", hAlgo, "ptr", 0, "uint", 0, "ptr", &pbInput, "uint", cbInput, "ptr", &pbHash, "uint", cbHash) != 0) throw Exception("BCryptHash: " NT_STATUS, -1) Loop cbHash hash .= Format("{:02x}", NumGet(pbHash, A_Index - 1, "uchar")) DllCall("bcrypt\BCryptCloseAlgorithmProvider", "ptr", hAlgo, "uint", 0) DllCall("FreeLibrary", "ptr", hBCRYPT) Return(hash) } ;#########Pastebin hotkeys################### ; Pastebin API paste ^!1:: global api_dev_key global api_user_key global api_paste_format global api_paste_private global api_paste_expire_date global pastebin_backup_dir old_clipboard := ClipboardAll Clipboard := "" SendInput("^c") Clipwait(1.0) If ErrorLevel { MsgBox("Clipboard operation failed!") Clipboard := old_clipboard CheckKeyState() Exit() } api_paste_code := Clipboard ; content of the paste ; Get api_paste_name Gui := GuiCreate(, "Create filename for Pastebin paste") Gui.Add("Text",, "Please name the file:") Gui.Add("Edit", "w400 vsearch") Gui.Add("Button", "default", "OK").OnEvent("Click", () => ProcessUserInputPaste(Gui)) Gui.Add("Button", "x+5", "Cancel").OnEvent("Click", () => CancelUserInputPaste(Gui)) Gui.OnEvent("Close", "ProcessUserInputPaste") Gui.OnEvent("Close", "CancelUserInputPaste") Gui.Show() Sleep(300) ProcessUserInputPaste(this) { global api_paste_code ; required global saved := this.Submit() ; Save the contents of named controls into an object. api_paste_name := saved.search ; Check to see if the file already exists by calling API for existing pastes api_results_limit := '1000' api_option := 'list' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_results_limit=' . api_results_limit url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in file listing! Error code: " . status) Clipboard := old_clipboard CheckKeyState() Exit() } If !(InStr(response,"paste")) { MsgBox("Could not get list of pastes to compare file names.`nStatus = " . status . "`nPlease make sure your configuration file is correct.`n" . response) Clipboard := old_clipboard CheckKeyState() Exit() } ; Check to see if the file name already exists api_paste_key := '' ; We will extract this in order to use it when backing up and overwriting files start_pos := 1 find_pos := '' matches := [] regexp := 's).*?' Loop { find_pos := RegExMatch(response, regexp, match, start_pos) If find_pos { matches.Push(match[0]) start_pos := match.Pos(0) + match.Len(0) } } Until find_pos = 0 exists := 0 Loop matches.Length() { string := matches[A_Index] api_paste_name_regex := RegExReplace(api_paste_name, "([\.\^\$\*\+\?\(\)\[\{\\\|])", '\$1') If RegExMatch(string, '' . api_paste_name_regex . '') { match_pos := RegExMatch(string, '(.*?)', match) api_paste_key := match[1] exists := 1 Break } } If exists { result := MsgBox("The file already exists! Would you like to overwrite it? (Press Yes or No)",, "YesNo") If result = "Yes" { ; Create local backup api_option := 'show_paste' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_paste_key=' . api_paste_key url := "https://pastebin.com/api/api_raw.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in file backup! Error code: " . status . "`nOriginal file not overwritten.") Clipboard := old_clipboard CheckKeyState() Exit() } ; Decode bytes (WinHttp.WinHttpRequest.5.1 ResponseText wrongly decodes encoding) stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() ; Write paste to local backup directory backup_file := pastebin_backup_dir . api_paste_name t := A_NOW ts := FormatTime(t, "_yyyyMMdd-HHmmss") backup_file := RegExReplace(backup_file, '(.*?)(\.[^.]*$)', '$1' . ts . '$2') FileDelete(backup_file) FileAppend(response, backup_file, "UTF-8") If !(FileExist(backup_file) And CheckAge(backup_file)) { MsgBox("Local backup of " . api_paste_name . "failed! Aborting overwrite...") Clipboard := old_clipboard CheckKeyState() Exit() } ; Delete paste (Irreversible in event of interruption between delete and paste!) api_option := 'delete' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_paste_key=' . api_paste_key url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response response := HttpObj.ResponseText status := HttpObj.Status If !status = '200' { MsgBox("Http request failure deleting file for overwrite! Error code: " . status . "`nOriginal file not overwritten.") Clipboard := old_clipboard CheckKeyState() Exit() } If !(InStr(response,"removed")) { MsgBox("Overwrite failure occurred! File not overwritten.`n" . response) Clipboard := old_clipboard CheckKeyState() Exit() } } Else { Clipboard := old_clipboard CheckKeyState() Exit() } } ; Create paste api_option := 'paste' api_paste_name := UriEncode(api_paste_name) api_paste_code := UriEncode(api_paste_code) post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_paste_private=' . api_paste_private . '&api_paste_name=' . api_paste_name . '&api_paste_expire_date=' . api_paste_expire_date . '&api_paste_format=' . api_paste_format . '&api_dev_key=' . api_dev_key . '&api_paste_code=' . api_paste_code ;MsgBox(post_fields) ;Exit() url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response response := HttpObj.ResponseText status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in paste! Error code: " . status . "`nPlease check your backup folder if the previous version of the file was deleted from pastebin.com") Clipboard := old_clipboard CheckKeyState() Exit() } If !(InStr(response,"pastebin")) { MsgBox("Paste failure occurred! File not pasted to Pastebin.com.`nPlease make sure your configuration file is correct.`n" . response . "`nPlease check your backup folder if the previous version of the file was deleted from pastebin.com") Clipboard := old_clipboard CheckKeyState() Exit() } Else { Clipboard := response ; send paste link to the clipboard MsgBox("Sucessfully pasted!" . response . "`nPaste link copied to clipboard") CheckKeyState() Exit() } } CancelUserInputPaste(this) { saved := this.Submit() ; Save the contents of named controls into an object. Clipboard := old_clipboard CheckKeyState() Exit() } Return ; Folder and file paste ^!2:: global api_dev_key global api_user_key global api_paste_format global api_paste_private global api_paste_expire_date global pastebin_backup_dir old_clipboard := ClipboardAll Clipboard := "" SendInput("^c") Clipwait(1.0) If ErrorLevel { MsgBox("Clipboard operation failed!") Clipboard := old_clipboard CheckKeyState() Exit() } files := [] files_unique := {} Loop Parse, Clipboard, "`n", "`r" { If !InStr(FileGetAttrib(A_LoopField), "D") { If RegExMatch(A_LoopField, "\.txt$|\.md$|\.ahk$|\.p[ylhs][p1]?$|\.html?$|\.js$|\.[ct]sv$") { files.Push(A_LoopField) RegExMatch(A_LoopField, "[^\\]*$", match) ; get file name only (no path) files_unique[match[0]] := 1 } } Else { Loop Files, A_LoopField . "\*.*", "FDR" { If !InStr(FileGetAttrib(A_LoopFileFullPath), "D") { If RegExMatch(A_LoopFileFullPath, "\.txt$|\.md$|\.ahk$|\.p[ylhs][p1]?$|\.html?$|\.js$|\.[ct]sv$") { files.Push(A_LoopFileFullPath) RegExMatch(A_LoopFileFullPath, "[^\\]*$", match) ; get file name only files_unique[match[0]] := 1 } } } } } ; If there are no files with duplicate names, we can grab the list only once ; So we need to create a flag list_flag := 0 list_loop := 1 If files.Length() = files_unique.Length() { ; No duplicate names list_flag := 1 } paste_results := '' ; summary of files pasted paste_count := 0 paste_errors := 0 duplicate_results := '' ; summary of files with duplicate content (not overwritten or re-pasted) duplicate_count := 0 list_matches := [] Loop files.Length() { match_pos := RegExMatch(files[A_Index], "[^\\]*$", match) ; get file name only (no path) api_paste_name := match[0] api_paste_code := FileRead(files[A_Index], "UTF-8") ; NEED TO STRIP OFF NEWLINES BECAUSE PASTEBIN.COM STRIPS OFF ALL TRAILING NEWLINES FROM API-BASED PASTES api_paste_code_stripped := RegExReplace(api_paste_code, '(?:\r?\n)*$', '') api_paste_code_md5 := BcryptMd5(api_paste_code_stripped) ; for checking file content ; Check to see if the file already exists by calling API for existing pastes If list_loop { api_results_limit := '1000' api_option := 'list' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_results_limit=' . api_results_limit url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() status := HttpObj.Status If !status = '200' { result := MsgBox("Http request failure in file listing for " . api_paste_name . "! Error code: " . status . "`nPlease make sure your configuration file is correct.`nDo you want to try to continue pasting the rest of the files? This error may occur repeatedly.",, "YesNo") If result = "Yes" { paste_errors++ Continue } Else { Clipboard := old_clipboard paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . duplicate_count . " duplicate(s)`n" . duplicate_results MsgBox(paste_results) CheckKeyState() Exit() } } If !(InStr(response,"paste")) { result := MsgBox("Could not get list of pastes to compare file names for " . api_paste_name . "! Error code: " . status . "`nPlease make sure your configuration file is correct.`nResponse: " . response . "`nDo you want to try to continue pasting the rest of the files? This error may occur repeatedly.",, "YesNo") If result = "Yes" { paste_errors++ Continue } Else { Clipboard := old_clipboard paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . duplicate_count . " duplicate(s)`n" . duplicate_results MsgBox(paste_results) CheckKeyState() Exit() } } ; Check to see if the file name already exists api_paste_key := '' ; We will extract this in order to use it when backing up and overwriting files start_pos := 1 find_pos := '' list_matches := [] regexp := 's).*?' Loop { find_pos := RegExMatch(response, regexp, match, start_pos) If find_pos { list_matches.Push(match[0]) start_pos := match.Pos(0) + match.Len(0) } } Until find_pos = 0 If list_flag { list_loop := 0 } } exists := 0 Loop list_matches.Length() { string := list_matches[A_Index] api_paste_name_regex := RegExReplace(api_paste_name, "([\.\^\$\*\+\?\(\)\[\{\\\|])", '\$1') If RegExMatch(string, '' . api_paste_name_regex . '') { match_pos := RegExMatch(string, '(.*?)', match) api_paste_key := match[1] exists := 1 Break } } If exists = 1 { ; Get paste content from pastebin.com to check md5 and possibly backup and overwrite api_option := 'show_paste' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_paste_key=' . api_paste_key url := "https://pastebin.com/api/api_raw.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response status := HttpObj.Status If !status = '200' { result := MsgBox("Http request failure while checking for duplicate files for " . api_paste_name . "! Error code: " . status "`nOriginal file not overwritten.`nDo you want to try to continue pasting the rest of the files? This error may occur repeatedly.",, "YesNo") If result = "Yes" { paste_errors++ Continue } Else { Clipboard := old_clipboard paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . duplicate_count . " duplicate(s)`n" . duplicate_results MsgBox(paste_results) CheckKeyState() Exit() } } ; Decode bytes (WinHttp.WinHttpRequest.5.1 ResponseText wrongly decodes encoding) stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() ; Get and check md5 response_md5 := BcryptMd5(response) If response_md5 = api_paste_code_md5 { ; Paste content is the same. Don't backup or re-paste duplicate_count++ duplicate_results .= A_Tab . api_paste_name . "`n" Continue } result := MsgBox(api_paste_name . " already exists! Would you like to overwrite it? (Press Yes or No)",, "YesNo") If result = "Yes" { ; Write paste to local backup directory backup_file := pastebin_backup_dir . api_paste_name t := A_NOW ts := FormatTime(t, "_yyyyMMdd-HHmmss") backup_file := RegExReplace(backup_file, '(.*?)(\.[^.]*$)', '$1' . ts . '$2') FileDelete(backup_file) FileAppend(response, backup_file, "UTF-8") If !(FileExist(backup_file) And CheckAge(backup_file)) { result := MsgBox("Local backup of " . api_paste_name . "failed! Aborting overwrite. Do you want to try to continue pasting the rest of the files? This error may occur repeatedly.",, "YesNo") If result = "Yes" { paste_errors++ Continue } Else { Clipboard := old_clipboard paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . duplicate_count . " duplicate(s)`n" . duplicate_results MsgBox(paste_results) CheckKeyState() Exit() } } ; Delete paste (Irreversible in event of interruption between delete and paste!) api_option := 'delete' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_paste_key=' . api_paste_key url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response response := HttpObj.ResponseText status := HttpObj.Status If !status = '200' { result := MsgBox("Http request failure deleting " . api_paste_name . " for overwrite! Error code: " . status . "`nDo you want to try to continue pasting the rest of the files? This error may occur repeatedly.",, "YesNo") If result = "Yes" { paste_errors++ Continue } Else { Clipboard := old_clipboard paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . duplicate_count . " duplicate(s)`n" . duplicate_results MsgBox(paste_results) CheckKeyState() Exit() } } If !(InStr(response,"removed")) { result := MsgBox("Overwrite failure occurred for " . api_paste_name . " ! File not overwritten.`nResponse: " . response . "`nDo you want to try to continue pasting the rest of the files? This error may occur repeatedly.",, "YesNo") If result = "Yes" { paste_errors++ Continue } Else { Clipboard := old_clipboard paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . duplicate_count . " duplicate(s)`n" . duplicate_results MsgBox(paste_results) CheckKeyState() Exit() } } } Else { Continue ; keep processing the rest of the files } } ; Create paste api_option := 'paste' paste_name := api_paste_name api_paste_name := UriEncode(api_paste_name) api_paste_code := UriEncode(api_paste_code) post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_paste_private=' . api_paste_private . '&api_paste_name=' . api_paste_name . '&api_paste_expire_date=' . api_paste_expire_date . '&api_paste_format=' . api_paste_format . '&api_dev_key=' . api_dev_key . '&api_paste_code=' . api_paste_code ;MsgBox(post_fields) ;Exit() url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response response := HttpObj.ResponseText status := HttpObj.Status If !status = '200' { result := MsgBox("Http request failure in paste for " . paste_name . " ! Error code: " . status . "`nDo you want to try to continue pasting the rest of the files? This error may occur repeatedly.",, "YesNo") If result = "Yes" { paste_errors++ Continue } Else { Clipboard := old_clipboard paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . duplicate_count . " duplicate(s)`n" . duplicate_results MsgBox(paste_results) CheckKeyState() Exit() } } If !(InStr(response,"pastebin")) { result := MsgBox("Paste failure occurred for " . paste_name . " ! Error code: " . status . "`nResponse: " . response . "`nDo you want to try to continue pasting the rest of the files? This error may occur repeatedly.",, "YesNo") If result = "Yes" { paste_errors++ Continue } Else { Clipboard := old_clipboard paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . duplicate_count . " duplicate(s)`n" . duplicate_results MsgBox(paste_results) CheckKeyState() Exit() } } Else { paste_results .= A_Tab . paste_name . ":" . A_Tab . response . "`n" paste_count++ } } paste_results := "Results summary (also copied to your computer's clipboard):`n`n" . paste_count . " file(s) were pasted to pastebin.com with " . paste_errors . " error(s)!`n" . paste_results . "`n" . duplicate_count . " duplicate(s)`n" . duplicate_results Clipboard := paste_results MsgBox(paste_results) CheckKeyState() Return ; Pastebin API grab content to clipboard ^!3:: global api_dev_key global api_user_key ; Get api_paste_name Gui := GuiCreate(, "Enter filename for Pastebin download") Gui.Add("Text",, "Please enter the filename:") Gui.Add("Edit", "w400 vsearch") Gui.Add("Button", "default", "OK").OnEvent("Click", () => ProcessUserInputDownload(Gui)) Gui.Add("Button", "x+5", "Cancel").OnEvent("Click", () => CancelUserInputDownload(Gui)) Gui.OnEvent("Close", "ProcessUserInputDownload") Gui.OnEvent("Close", "CancelUserInputDownload") Gui.Show() Sleep(300) ProcessUserInputDownload(this) { saved := this.Submit() ; Save the contents of named controls into an object. api_paste_name := saved.search ; Check to see if the file exists by calling API for existing pastes api_results_limit := '1000' api_option := 'list' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_results_limit=' . api_results_limit url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in file listing! Error code: " . status . "`nPlease make sure your configuration file is correct.") CheckKeyState() Exit() } If !(InStr(response,"paste")) { MsgBox("Could not get list of pastes to compare file names.`nPlease make sure your configuration file is correct.`n" . response) CheckKeyState() Exit() } ; Check to see if the file name already exists api_paste_key := '' ; We will extract this in order to use it when backing up and overwriting files start_pos := 1 find_pos := '' matches := [] regexp := 's).*?' Loop { find_pos := RegExMatch(response, regexp, match, start_pos) If find_pos { matches.Push(match[0]) start_pos := match.Pos(0) + match.Len(0) } } Until find_pos = 0 exists := 0 Loop matches.Length() { string := matches[A_Index] api_paste_name_regex := RegExReplace(api_paste_name, "([\.\^\$\*\+\?\(\)\[\{\\\|])", '\$1') If RegExMatch(string, '' . api_paste_name_regex . '') { match_pos := RegExMatch(string, '(.*?)', match) api_paste_key := match[1] exists := 1 Break } } If exists { ; Download the paste to the clipboard api_option := 'show_paste' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_paste_key=' . api_paste_key url := "https://pastebin.com/api/api_raw.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in paste download! Error code: " . status) Clipboard := old_clipboard CheckKeyState() Exit() } ; Decode bytes (WinHttp.WinHttpRequest.5.1 ResponseText wrongly decodes encoding) stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'utf-8' response := stream.ReadText() stream.Close() ; Paste to clipboard Clipboard := response MsgBox(api_paste_name . " copied to clipboard.") CheckKeyState() Exit() } Else { MsgBox(api_paste_name . " does not exist!") CheckKeyState() Exit() } } CancelUserInputDownload(this) { saved := this.Submit() ; Save the contents of named controls into an object. Clipboard := old_clipboard CheckKeyState() Exit() } Return ; Pastebin API paste append ^!4:: global api_dev_key global api_user_key global api_paste_format global api_paste_private global api_paste_expire_date global pastebin_backup_dir api_paste_name := '' old_clipboard := ClipboardAll Clipboard := "" SendInput("^c") Clipwait(1.0) If ErrorLevel { MsgBox("Clipboard operation failed!") Clipboard := old_clipboard CheckKeyState() Exit() } api_paste_code := Clipboard ; content to append ; Get api_paste_name Gui := GuiCreate(, "Enter the filename for appending") Gui.Add("Text",, "Please enter the filename:") Gui.Add("Edit", "w400 vsearch") Gui.Add("Button", "default", "OK").OnEvent("Click", () => ProcessUserInputAppend(Gui)) Gui.Add("Button", "x+5", "Cancel").OnEvent("Click", () => CancelUserInputAppend(Gui)) Gui.OnEvent("Close", "ProcessUserInputAppend") Gui.OnEvent("Close", "CancelUserInputAppend") Gui.Show() Sleep(300) ProcessUserInputAppend(this) { global api_paste_code ; required global saved := this.Submit() ; Save the contents of named controls into an object. api_paste_name := saved.search ; Check to see if the file already exists by calling API for existing pastes api_results_limit := '1000' api_option := 'list' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_results_limit=' . api_results_limit url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in file listing! Error code: " . status . "`nPlease make sure your configuration file is correct.") Clipboard := old_clipboard CheckKeyState() Exit() } If !(InStr(response,"paste")) { MsgBox("Could not get list of pastes to compare file names.`nPlease make sure your configuration file is correct.`n" . response) Clipboard := old_clipboard CheckKeyState() Exit() } ; Check to see if the filename already exists api_paste_key := '' ; We will extract this in order to use it when backing up and overwriting files start_pos := 1 find_pos := '' matches := [] regexp := 's).*?' Loop { find_pos := RegExMatch(response, regexp, match, start_pos) If find_pos { matches.Push(match[0]) start_pos := match.Pos(0) + match.Len(0) } } Until find_pos = 0 exists := 0 Loop matches.Length() { string := matches[A_Index] api_paste_name_regex := RegExReplace(api_paste_name, "([\.\^\$\*\+\?\(\)\[\{\\\|])", '\$1') If RegExMatch(string, '' . api_paste_name_regex . '') { match_pos := RegExMatch(string, '(.*?)', match) api_paste_key := match[1] exists := 1 Break } } If exists { ; Create local backup api_option := 'show_paste' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_paste_key=' . api_paste_key url := "https://pastebin.com/api/api_raw.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in file backup! Error code: " . status) Clipboard := old_clipboard CheckKeyState() Exit() } ; Decode bytes (WinHttp.WinHttpRequest.5.1 ResponseText wrongly decodes encoding) stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() ; Write paste to local backup directory backup_file := pastebin_backup_dir . api_paste_name t := A_NOW ts := FormatTime(t, "_yyyyMMdd-HHmmss") backup_file := RegExReplace(backup_file, '(.*?)(\.[^.]*$)', '$1' . ts . '$2') FileDelete(backup_file) FileAppend(response, backup_file, "UTF-8") If !(FileExist(backup_file) And CheckAge(backup_file)) { MsgBox("Local backup of " . api_paste_name . "failed! File not updated. Aborting append...") Exit() } ; Update api_paste_code api_paste_code := response . "`r`n" . api_paste_code ; Windows new line ; Delete paste (Irreversible in event of interruption between delete and paste!) api_option := 'delete' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_paste_key=' . api_paste_key url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response response := HttpObj.ResponseText status := HttpObj.Status If !status = '200' { MsgBox("Http request failure during append! Original file not changed. Error code: " . status) Clipboard := old_clipboard CheckKeyState() Exit() } If !(InStr(response,"removed")) { MsgBox("Append failure occurred! File not appended to.`n" . response) Clipboard := old_clipboard CheckKeyState() Exit() } ; Create appended paste api_option := 'paste' api_paste_name := UriEncode(api_paste_name) api_paste_code := UriEncode(api_paste_code) post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_paste_private=' . api_paste_private . '&api_paste_name=' . api_paste_name . '&api_paste_expire_date=' . api_paste_expire_date . '&api_paste_format=' . api_paste_format . '&api_dev_key=' . api_dev_key . '&api_paste_code=' . api_paste_code ;MsgBox(post_fields) url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response response := HttpObj.ResponseText status := HttpObj.Status If !status = '200' { MsgBox("Http request failure! File not appended to and original file deleted! Please check local backup.`nError code: " . status) Clipboard := old_clipboard CheckKeyState() Exit() } If !(InStr(response,"pastebin")) { MsgBox("Paste append failed! File not appended to and original file deleted! Please check local backup.`n" . response) Clipboard := old_clipboard CheckKeyState() Exit() } Else { Clipboard := response ; copy paste link to clipboard MsgBox("Sucessfully appended paste!" . response . "`nPaste link copied to clipboard") CheckKeyState() Exit() } } Else { result := MsgBox(api_paste_name . " does not exist! Do you want to create it? (Press Yes or No)",, "YesNo") If result = "Yes" { ; Create paste api_option := 'paste' api_paste_name := UriEncode(api_paste_name) api_paste_code := UriEncode(api_paste_code) post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_paste_private=' . api_paste_private . '&api_paste_name=' . api_paste_name . '&api_paste_expire_date=' . api_paste_expire_date . '&api_paste_format=' . api_paste_format . '&api_dev_key=' . api_dev_key . '&api_paste_code=' . api_paste_code ;MsgBox(post_fields) url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response response := HttpObj.ResponseText status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in paste! Error code: " . status) Clipboard := old_clipboard CheckKeyState() Exit() } If !(InStr(response,"pastebin")) { MsgBox("Paste failure occurred! File not pasted to Pastebin.com`n" . response) Clipboard := old_clipboard CheckKeyState() Exit() } Else { Clipboard := response ; paste copied to clipboard MsgBox("Sucessfully pasted!" . response . "`nPaste link copied to clipboard") CheckKeyState() Exit() } } Else { Clipboard := old_clipboard CheckKeyState() Exit() } } } CancelUserInputAppend(this) { saved := this.Submit() ; Save the contents of named controls into an object. Clipboard := old_clipboard CheckKeyState() Exit() } Return ; Backup pastes based on regular expression ^!5:: global api_dev_key global api_user_key ; Create backup folder time_stamp := A_Now paste_backup_dir := A_WorkingDir . '\paste_backup_' . time_stamp . '\' If !DirExist(paste_backup_dir) { DirCreate(paste_backup_dir) } ; Get regexp Gui := GuiCreate(, "Enter a search query (e.g., regex) for files to backup") Gui.Add("Text",, "Search query:") Gui.Add("Edit", "w400 vsearch") Gui.Add("Button", "default", "OK").OnEvent("Click", () => ProcessUserInputBackup(Gui)) Gui.Add("Button", "x+5", "Cancel").OnEvent("Click", () => CancelUserInputBackup(Gui)) Gui.OnEvent("Close", "ProcessUserInputBackup") Gui.OnEvent("Close", "CancelUserInputBackup") Gui.Show() Sleep(300) ProcessUserInputBackup(this) { global paste_backup_dir saved := this.Submit() ; Save the contents of named controls into an object. regexp := saved.search ; Get list of all pastes api_results_limit := '1000' api_option := 'list' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_results_limit=' . api_results_limit url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in file listing! Error code: " . status . "`nPlease make sure your configuration file is correct.") CheckKeyState() Exit() } If !(InStr(response,"paste")) { MsgBox("Could not get list of pastes to compare file names.`nPlease make sure your configuration file is correct.`n" . response) CheckKeyState() Exit() } ; Check to see if regexp matches any paste titles ; First grab titles and keys api_paste_key := '' ; We will extract this in order to use it when backing up start_pos := 1 find_pos := '' matches := [] response_regexp := 's).*?' Loop { find_pos := RegExMatch(response, response_regexp, match, start_pos) If find_pos { matches.Push(match[0]) start_pos := match.Pos(0) + match.Len(0) } } Until find_pos = 0 exists := 0 titles := [] keys := [] Loop matches.Length() { string := matches[A_Index] match_pos := RegExMatch(string, '(.*?)', title_match) title_match := title_match[1] If RegExMatch(title_match, regexp) { match_pos := RegExMatch(string, '(.*?)', match) keys.Push(match[1]) ;match_pos := RegExMatch(string, '(.*?)', match) ;titles.Push(match[1]) titles.Push(title_match) exists := 1 } } If exists { ; Print out files that match and confirm backup message := "Do you want to backup all of these files?`nList of files also copied to your computer's clipboard.`n" Loop titles.Length() { message .= titles[A_Index] . '`n' } Clipboard := message result := MsgBox(message,, "YesNo") If result = "Yes" { ; Create local backups backup_count := 0 backup_names := "" errors := 0 Loop keys.Length() { api_option := 'show_paste' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_paste_key=' . keys[A_Index] url := "https://pastebin.com/api/api_raw.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response status := HttpObj.Status If !status = '200' { result := MsgBox("Http request failure in " . titles[A_Index] . " backup! Error code: " . status . "`nDo you want to continue with the rest of the backups?",, "YesNo") If result = "Yes" { errors++ Continue } Else { MsgBox(backup_count . " pastes backed up from Pastebin.com.`n" . ++errors . "occurred.`nBackups stored in local timestamped backups folder:`n" . backup_names) CheckKeyState() Exit() } } ; Decode bytes (WinHttp.WinHttpRequest.5.1 ResponseText wrongly decodes encoding) stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() ; Write paste to local backup directory backup_file := paste_backup_dir . titles[A_Index] FileDelete(backup_file) FileAppend(response, backup_file, "UTF-8") If !(FileExist(backup_file) And CheckAge(backup_file)) { result := MsgBox("Local backup of " . titles[A_Index] . "failed! File not backed up from Pastebin.com.`nDo you want to continue with the rest of the backups?",, "YesNo") If result = "Yes" { errors++ Continue } Else { MsgBox(backup_count . " pastes backed up from Pastebin.com.`n" . ++errors . "occurred.`nBackups stored in local timestamped backups folder:`n" . backup_names) CheckKeyState() Exit() } } backup_count++ backup_names .= '`t' . titles[A_Index] . '`n' } If backup_count = keys.Length() { MsgBox(backup_count . " pastes backed up from Pastebin.com.`nBackups stored in local timestamped backups folder:`n" . backup_names) } Else { MsgBox(backup_count . " pastes backed up from Pastebin.com.`n" . errors . "occurred.`nBackups stored in local timestamped backups folder:`n" . backup_names) } } Else { DirDelete(paste_backup_dir) MsgBox("Backup aborted by user. No pastes backed up.") CheckKeyState() Exit() } } Else { MsgBox("No pastes match that search query! Nothing backed up!") CheckKeyState() Exit() } } CancelUserInputBackup(this) { saved := this.Submit() ; Save the contents of named controls into an object. CheckKeyState() Exit() } Return ; Delete pastes based on regular expression ^!6:: global api_dev_key global api_user_key global pastebin_backup_dir ; Get regexp Gui := GuiCreate(, "Enter a search query (e.g., regex) for files to delete") Gui.Add("Text",, "Search query:") Gui.Add("Edit", "w400 vsearch") Gui.Add("Button", "default", "OK").OnEvent("Click", () => ProcessUserInputDelete(Gui)) Gui.Add("Button", "x+5", "Cancel").OnEvent("Click", () => CancelUserInputDelete(Gui)) Gui.OnEvent("Close", "ProcessUserInputDelete") Gui.OnEvent("Close", "CancelUserInputDelete") Gui.Show() Sleep(300) ProcessUserInputDelete(this) { saved := this.Submit() ; Save the contents of named controls into an object. regexp := saved.search ; Get list of all pastes api_results_limit := '1000' api_option := 'list' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_results_limit=' . api_results_limit url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in file listing! Error code: " . status . "`nPlease make sure your configuration file is correct.") CheckKeyState() Exit() } If !(InStr(response,"paste")) { MsgBox("Could not get list of pastes to compare file names.`nPlease make sure your configuration file is correct.`n" . response) CheckKeyState() Exit() } ; Check to see if regexp matches any paste titles ; First grab titles and keys api_paste_key := '' ; We will extract this in order to use it when backing up and overwriting files start_pos := 1 find_pos := '' matches := [] response_regexp := 's).*?' Loop { find_pos := RegExMatch(response, response_regexp, match, start_pos) If find_pos { matches.Push(match[0]) start_pos := match.Pos(0) + match.Len(0) } } Until find_pos = 0 exists := 0 titles := [] keys := [] Loop matches.Length() { string := matches[A_Index] match_pos := RegExMatch(string, '(.*?)', title_match) title_match := title_match[1] If RegExMatch(title_match, regexp) { match_pos := RegExMatch(string, '(.*?)', match) keys.Push(match[1]) ;match_pos := RegExMatch(string, '(.*?)', match) ;titles.Push(match[1]) titles.Push(title_match) exists := 1 } } If exists { ; Print out files that match and confirm delete message := "Do you want to delete all of these files? (Backups are still made locally.)`nList of files also copied to your computer's clipboard.`n" Loop titles.Length() { message .= titles[A_Index] . '`n' } Clipboard := message result := MsgBox(message,, "YesNo") If result = "Yes" { ; Create local backups delete_count := 0 delete_errors := 0 delete_names := '' Loop keys.Length() { api_option := 'show_paste' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_paste_key=' . keys[A_Index] url := "https://pastebin.com/api/api_raw.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response status := HttpObj.Status If !status = '200' { result := MsgBox("Http request failure in " . titles[A_Index] . " backup before delete! Error code: " . status . "`nDo you want to continue deleting the rest of the files?",, "YesNo") If result = "Yes" { delete_errors++ Continue } Else { MsgBox(delete_count . " pastes deleted from Pastebin.com.`n" . ++delete_errors . "occurred.`nThe following files were deleted:`n" . delete_names) CheckKeyState() Exit() } } ; Decode bytes (WinHttp.WinHttpRequest.5.1 ResponseText wrongly decodes encoding) stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() ; Write paste to local backup directory backup_file := pastebin_backup_dir . titles[A_Index] t := A_NOW ts := FormatTime(t, "_yyyyMMdd-HHmmss") backup_file := RegExReplace(backup_file, '(.*?)(\.[^.]*$)', '$1' . ts . '$2') FileDelete(backup_file) FileAppend(response, backup_file, "UTF-8") If !(FileExist(backup_file) And CheckAge(backup_file)) { result := MsgBox("Local backup of " . titles[A_Index] . "failed! File not deleted from Pastebin.com.`nDo you want to continue deleting the rest of the files?",, "YesNo") If result = "Yes" { delete_errors++ Continue } Else { MsgBox(delete_count . " pastes deleted from Pastebin.com.`n" . ++delete_errors . "occurred.`nThe following files were deleted:`n" . delete_names) CheckKeyState() Exit() } } } ; Delete pastes from Pastebin.com Loop keys.Length() { api_option := 'delete' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_paste_key=' . keys[A_Index] url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response response := HttpObj.ResponseText status := HttpObj.Status If !status = '200' { result := MsgBox("Http request failure during delete! " . titles[A_Index] . " not deleted. Error code: " . status . "`nDo you want to continue deleting the rest of the files?", "YesNo") If result = "Yes" { delete_errors++ Continue } Else { MsgBox(delete_count . " pastes deleted from Pastebin.com.`n" . ++delete_errors . "occurred.`nThe following files were deleted:`n" . delete_names) CheckKeyState() Exit() } } If !(InStr(response,"removed")) { result := MsgBox("Delete failure occurred! " . titles[A_Index] . " not deleted.`nResponse: " . response . "`nDo you want to continue deleting the rest of the files?", "YesNo") If result = "Yes" { delete_errors++ Continue } Else { MsgBox(delete_count . " pastes deleted from Pastebin.com.`n" . ++delete_errors . "occurred.`nThe following files were deleted:`n" . delete_names) CheckKeyState() Exit() } } delete_count++ delete_names .= '`t' . titles[A_Index] . '`n' } If delete_count = keys.Length() { MsgBox(delete_count . " pastes deleted from Pastebin.com.:`n" . delete_names) } Else { MsgBox(delete_count . " pastes deleted from Pastebin.com.`n" . errors . "occurred.`nThe following files were deleted:`n" . delete_names) } } Else { DirDelete(paste_backup_dir) MsgBox("Delete aborted by user. No pastes deleted.") CheckKeyState() Exit() } } Else { MsgBox("No pastes match that search query! Nothing deleted!") CheckKeyState() Exit() } } CancelUserInputDelete(this) { saved := this.Submit() ; Save the contents of named controls into an object. CheckKeyState() Exit() } Return ; Show all pastes ^!7:: global api_dev_key global api_user_key ; Get list of all pastes api_results_limit := '1000' api_option := 'list' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_results_limit=' . api_results_limit url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in file listing! Error code: " . status . "`nPlease make sure your configuration file is correct.") CheckKeyState() Exit() } If !(InStr(response,"paste")) { MsgBox("Could not get list of pastes to compare file names.`nPlease make sure your configuration file is correct.`n" . response) CheckKeyState() Exit() } ; Grab titles start_pos := 1 find_pos := '' matches := [] response_regexp := 's).*?' Loop { find_pos := RegExMatch(response, response_regexp, match, start_pos) If find_pos { matches.Push(match[0]) start_pos := match.Pos(0) + match.Len(0) } } Until find_pos = 0 file_count := matches.Length() file_list := 'You have ' . matches.Length() . ' pastes.`n`n' Loop matches.Length() { string := matches[A_Index] match_pos := RegExMatch(string, '(.*?)', title_match) title_match := title_match[1] match_pos := RegExMatch(string, '(.*?)', key_match) key_match := "https://pastebin.com/" . key_match[1] file_list .= title_match . '`n' . key_match . '`n`n' } Clipboard := file_list MsgBox("You have " . file_count . " pastes.`nA list of your pastes has been copied to your clipboard.") Return ; List pastes based on regular expression ^!8:: global api_dev_key global api_user_key ; Get regex for listing pastes Gui := GuiCreate(, "Enter search query for listing pastes") Gui.Add("Text",, "Please enter search query (regular expression):") Gui.Add("Edit", "w400 vsearch") Gui.Add("Button", "default", "OK").OnEvent("Click", () => ProcessUserInputList(Gui)) Gui.Add("Button", "x+5", "Cancel").OnEvent("Click", () => CancelUserInputList(Gui)) Gui.OnEvent("Close", "ProcessUserInputList") Gui.OnEvent("Close", "CancelUserInputList") Gui.Show() Sleep(300) ProcessUserInputList(this) { saved := this.Submit() ; Save the contents of named controls into an object. regexp_search := saved.search ; Check to see if the file exists by calling API for existing pastes api_results_limit := '1000' api_option := 'list' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_results_limit=' . api_results_limit url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in file listing! Error code: " . status . "`nPlease make sure your configuration file is correct.") CheckKeyState() Exit() } If !(InStr(response,"paste")) { MsgBox("Could not get list of pastes to compare file names.`nPlease make sure your configuration file is correct.`n" . response) CheckKeyState() Exit() } ; Check to see if any filenames match the regular expression start_pos := 1 find_pos := '' matches := [] response_regexp := 's).*?' Loop { find_pos := RegExMatch(response, response_regexp, match, start_pos) If find_pos { matches.Push(match[0]) start_pos := match.Pos(0) + match.Len(0) } } Until find_pos = 0 list_results := '' result_count := 0 Loop matches.Length() { string := matches[A_Index] match_pos := RegExMatch(string, '(.*?)', title_match) title_match := title_match[1] If RegExMatch(title_match, regexp_search) { match_pos := RegExMatch(string, '(.*?)', key_match) key_match := "https://pastebin.com/" . key_match[1] list_results .= title_match . '`n' . key_match . '`n`n' result_count++ } } list_results := 'You have ' . result_count . ' pastes.`n`n' . list_results If list_results { Clipboard := list_results MsgBox(result_count . ' search results copied to clipboard.') CheckKeyState() Exit() } Else { MsgBox('0 search results.') CheckKeyState() Exit() } } CancelUserInputList(this) { saved := this.Submit() ; Save the contents of named controls into an object. CheckKeyState() Exit() } Return ; Get paste link ^!9:: global api_dev_key global api_user_key ; Get api_paste_name Gui := GuiCreate(, "Get link for Pastebin paste") Gui.Add("Text",, "Please enter the file name:") Gui.Add("Edit", "w400 vsearch") Gui.Add("Button", "default", "OK").OnEvent("Click", () => ProcessUserInputLink(Gui)) Gui.Add("Button", "x+5", "Cancel").OnEvent("Click", () => CancelUserInputLink(Gui)) Gui.OnEvent("Close", "ProcessUserInputLink") Gui.OnEvent("Close", "CancelUserInputLink") Gui.Show() Sleep(300) ProcessUserInputLink(this) { saved := this.Submit() ; Save the contents of named controls into an object. api_paste_name := saved.search ; Check to see if the file already exists by calling API for existing pastes api_results_limit := '1000' api_option := 'list' post_fields := 'api_option=' . api_option . '&api_user_key=' . api_user_key . '&api_dev_key=' . api_dev_key . '&api_results_limit=' . api_results_limit url := "https://pastebin.com/api/api_post.php" HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1") HttpObj.Open("POST", url) HttpObj.SetRequestHeader("Content-Type","application/x-www-form-urlencoded") HttpObj.Send(post_fields) ; Check response stream := ComObjCreate("adodb.stream") stream.Type := 1 stream.Mode := 3 stream.Open() stream.Write(HttpObj.ResponseBody) ; get bytes from ResponseBody stream.Position := 0 stream.Type := 2 stream.Charset := 'UTF-8' response := stream.ReadText() stream.Close() status := HttpObj.Status If !status = '200' { MsgBox("Http request failure in file listing! Error code: " . status . "`nPlease make sure your configuration file is correct.") Clipboard := old_clipboard CheckKeyState() Exit() } If !(InStr(response,"paste")) { MsgBox("Could not get list of pastes to compare file names.`nPlease make sure your configuration file is correct.`n" . response) Clipboard := old_clipboard CheckKeyState() Exit() } ; Check to see if the file name already exists api_paste_key := '' ; We will extract this in order to use it when backing up and overwriting files start_pos := 1 find_pos := '' matches := [] regexp := 's).*?' Loop { find_pos := RegExMatch(response, regexp, match, start_pos) If find_pos { matches.Push(match[0]) start_pos := match.Pos(0) + match.Len(0) } } Until find_pos = 0 exists := 0 Loop matches.Length() { string := matches[A_Index] api_paste_name_regex := RegExReplace(api_paste_name, "([\.\^\$\*\+\?\(\)\[\{\\\|])", '\$1') If RegExMatch(string, '' . api_paste_name_regex . '') { match_pos := RegExMatch(string, '(.*?)', match) api_paste_key := match[1] exists++ } } If exists = 1 { Clipboard := "https://pastebin.com/" . api_paste_key MsgBox("The link has been copied to the clipboard.`n" . Clipboard) CheckKeyState() Exit() } Else If exists > 1 { MsgBox("More than 1 file with the same name exists. Please check your Pastebin.com pastes.") CheckKeyState() Exit() } Else { MsgBox("That file does not exist") CheckKeyState() Exit() } } CancelUserInputLink(this) { saved := this.Submit() ; Save the contents of named controls into an object. CheckKeyState() Exit() } Return ; Login to Pastebin.com (Default browser is Opera) ^!0:: global api_user_name global api_user_password win_title := "ahk_class Chrome_WidgetWin_1" ; Opera (found with Window Spy) tab_title := "Pastebin.com - Login Page" run_command := "https://pastebin.com/login" OpenWindowPastebin(win_title, tab_title, run_command, api_user_name, api_user_password) CheckKeyState() Return ; Help message ^!h:: help_message := "1. Create new paste = ^!1 (Ctrl+Alt+1)`n2. Create new paste from files/folders = ^!2 (Ctrl+Alt+2)`n3. Download existing paste = ^!3 (Ctrl+Alt+3)`n4. Append to existing paste = ^!4 (Ctrl+Alt+4)`n5. Backup pastes = ^!5 (Ctrl+Alt+5)`n6. Delete pastes = ^!6 (Ctrl+Alt+6)`n7. List all pastes = ^!7 (Ctrl+Alt+7)`n8. List pastes = ^!8 (Ctrl+Alt+8)`n9. Get paste link = ^!9 (Ctrl+Alt+9)`n10. Log into pastebin = ^!0 (Ctrl+Alt+0)`n11. Help message = ^!h (Ctrl+Alt+h)" MsgBox(help_message) CheckKeyState() Return