Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;README (INSTRUCTIONS START ON LINE 47; CODE STARTS ON LINE 197)
- ;
- ;Pastebin API Hotkeys (MS Windows only) for syncing files and folders
- ;AutoHotkey V2 32-Bit program (Compatible with 64-bit MS Windows)
- ;
- ;FIRST THINGS FIRST
- ;
- ;1. Since this is a program for backing up and syncing files (i.e., not for
- ;sharing them), we recommend that you have a Pro membership to pastebin.com so
- ;that you can have unlimited private pastes. Regular members can only have 2
- ;private pastes. Of course, regular members can paste publicly, but that is
- ;probably not what you want to do.
- ;
- ;FEATURES:
- ;
- ;0. Correctly handles UTF-8 http request responses from pastebin.com
- ;1. Syncs specified files and folder to reflect updated files, deleted files,
- ;and changed filenames on pastebin.com (creates timestamped backup copies locally
- ;of all changed, deleted, and renamed files)(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 597 and 624)
- ;2. Backup pastes based on regular expression (creates time_stamped local folder
- ;of downloaded pastes)
- ;3. Delete pastes based on regular expression (creates timestamped backup copies
- ;stored locally)
- ;4. List pastes based on regular expression
- ;5. Log into Pastebin.com (automates your browser through programmatic key
- ;strokes) (currently works when Opera is default browser)
- ;6. Add files/folders to your sync path via hotkey (highlight files/folders with
- ;mouse and press hotkey)
- ;7. Remove files/folders to your sync path via hotkey (highlight files/folders
- ;with mouse and press hotkey)
- ;8. Display help message
- ;
- ;HOTKEYS (numbers correspond to the above 1 through 8):
- ;
- ;1. Create or sync new paste from files/folders = ^!1 (Ctrl+Alt+1)
- ;2. Backup pastes = ^!2 (Ctrl+Alt+2)
- ;3. Delete pastes = ^!3 (Ctrl+Alt+3)
- ;4. List pastes = ^!4 (Ctrl+Alt+4)
- ;5. Log into pastebin = ^!5 (Ctrl+Alt+5)
- ;6. Add files/folders to sync file = ^!6 (Ctrl+Alt+6)
- ;7. Remove files/folders from sync file = ^!7 (Ctrl+Alt+7)
- ;8. 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 77-126 for more information on this step.
- ;
- ;8. In the "configuration" folder, create a "sync.txt" file (see lines 128-144)
- ;
- ;9. In the folder containing the "AutoHotkeyU32.exe" executable, open Windows
- ;Powershell by clicking File -> Open Windows Powershell from Windows Explorer.
- ;
- ;10. Type ".\AutoHotkeyU32.exe pastebin_api.ahk"
- ;
- ;11. Use the Hotkeys in lines 38-45 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 85-92). 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.
- ;
- ;3. Files and folders to sync are stored in local file: configuration/sync.txt
- ;
- ;Please put the full path to the file or folder on separate lines (line breaks
- ;separating each file and folder entry), or use the hotkeys to add or remove
- ;files/folders (Add files/folders = Ctrl+Alt+6; Remove files/folders =
- ;Ctrl+Alt+7).
- ;
- ;4. Files and folders are synced by checking md5 checksums and filenames. md5
- ;checksums and filenames are automatically stored locally in your working
- ;directory in a file located at sync_checksums/md5checksums_names.txt. When a
- ;file subject to syncing is changed, deleted, or renamed, the checksum/names will
- ;not match any of the checksums/names in the md5checksum_names.txt file,
- ;indicating that it needs to be synced. After syncing it, the checksums/names in
- ;the md5checksum_names.txt file are updated. This step requires no action by the
- ;user. If something goes wrong during the process, please check the
- ;pastebin_backup folder for the previous version of the md5checksum_names.txt
- ;file.
- ;
- ;CURRENTLY KNOWN LIMITATIONS:
- ;
- ;1. When files are overwritten for the sync operation, the original Pastebin.com
- ;link is deleted and a new link is generated and written to the sync response
- ;pop-up. Furthermore, when syncing a file, it is overwritten silently (the
- ;overwritten file is backed up locally to the pastebin_backup folder).
- ;2. Since the pastebin.com API does not support folders, please ensure that
- ;there are no files with duplicated names in your sync folder. 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. Since md5 checksums are recalculated every time the program is run, it is
- ;expected that there will be performance slowdowns when syncing hundreds of
- ;files.
- ;5. This program works with UTF-8 encoded files. If your files use another
- ;encoding, strange things may happen.
- ;6. 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
- ;7. 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.
- ;8. Due to the nature of the pastebin.com service, it only handles text-based
- ;files up to 10 MB (500 KB for non-pro members).
- ;
- ;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()
- }
- }
- ;##########Get files and folders for syncing#####
- sync_file := A_WorkingDir . '\configuration\sync.txt'
- If !FileExist(sync_file)
- {
- MsgBox("You need to create your sync file at:`n`n" . sync_file . "`n`nCheck the help information provided at the top of the script for instructions on creating this file.")
- ExitApp()
- }
- files_folders := Trim(FileRead(sync_file, "UTF-8"), "`n`r")
- ;##########Get md5 checksums#####################
- md5checksums_names := ''
- md5checksums_dir := A_WorkingDir . '\sync_checksums'
- md5checksums_names_file := md5checksums_dir . '\md5checksums_names.txt'
- If !DirExist(md5checksums_dir)
- {
- DirCreate(md5checksums_dir)
- FileAppend(md5checksums_names, md5checksums_names_file, "UTF-8")
- }
- Else If (FileExist(md5checksums_names_file))
- {
- md5checksums_names := RTrim(FileRead(md5checksums_names_file, "UTF-8"), "`n`r")
- }
- Else
- {
- MsgBox("The checksums file is missing from " . md5checksums_dir . ". To fix this error, you may need to delete " . md5checksums_dir . " including any files in it and start again.")
- ExitApp()
- }
- ;##########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)
- }
- BcryptMd5File(filename)
- {
- 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(pbHash, cbHash, 0)
- if !(f := FileOpen(filename, "r", "UTF-8"))
- throw Exception("Failed to open file: " filename, -1)
- f.Seek(0)
- while (dataread := f.RawRead(data, 262144))
- if (NT_STATUS := DllCall("bcrypt\BCryptHash", "ptr", hAlgo, "ptr", 0, "uint", 0, "ptr", &data, "uint", dataread, "ptr", &pbHash, "uint", cbHash) != 0)
- throw Exception("BCryptHash: " NT_STATUS, -1)
- f.Close()
- 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###################
- ; File & folder sync
- ^!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
- global files_folders
- global md5checksums_names
- global md5checksums_names_file
- paste_results := '' ; summary of files pasted
- paste_count := 0
- paste_errors := 0
- delete_count := 0
- delete_errors := 0
- delete_results := ''
- files := []
- files_unique := {}
- newMd5checksums_names := ''
- Loop Parse, files_folders, "`n", "`r"
- {
- If !InStr(FileGetAttrib(A_LoopField), "D")
- {
- If RegExMatch(A_LoopField, "\.txt$|\.md$|\.ahk$|\.p[ylhs][p1]?$|\.html?$|\.js$|\.[ct]sv$")
- {
- RegExMatch(A_LoopField, "[^\\]*$", match) ; get file name only (no path)
- file_name := match[0]
- file_md5checksum := BcryptMd5File(A_LoopField)
- file_md5checksum_name := file_md5checksum . '::' . file_name
- file_md5checksum_name_regex := RegExReplace(file_md5checksum_name , "([\.\^\$\*\+\?\(\)\[\{\\\|])", '\$1') ; escape regex
- If RegExMatch(md5checksums_names, '(?m)^' . file_md5checksum_name_regex . '$')
- {
- newMd5checksums_names .= file_md5checksum_name . '`n'
- Continue
- }
- Else
- {
- files.Push(A_LoopField)
- newMd5checksums_names .= file_md5checksum_name . '`n'
- files_unique[match[0]] := 1
- ; Clearer to write files_unique[file_name] := 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$")
- {
- RegExMatch(A_LoopFileFullPath, "[^\\]*$", match) ; get file name only
- file_name := match[0]
- file_md5checksum := BcryptMd5File(A_LoopFileFullPath)
- file_md5checksum_name := file_md5checksum . '::' . file_name
- file_md5checksum_name_regex := RegExReplace(file_md5checksum_name , "([\.\^\$\*\+\?\(\)\[\{\\\|])", '\$1') ; escape regex
- If RegExMatch(md5checksums_names, '(?m)^' . file_md5checksum_name_regex . '$')
- {
- newMd5checksums_names .= file_md5checksum_name . '`n'
- Continue
- }
- Else
- {
- files.Push(A_LoopFileFullPath)
- newMd5checksums_names .= file_md5checksum_name . '`n'
- files_unique[match[0]] := 1
- ; Clearer to write files_unique[file_name] := 1 ??
- }
- }
- }
- }
- }
- }
- backup_names_file := pastebin_backup_dir . "\md5checksums_names.txt"
- FileCopy(md5checksums_names_file, backup_names_file, '1')
- If !(FileExist(backup_names_file) And CheckAgeConfig(md5checksums_names_file, backup_names_file))
- {
- MsgBox("Local backup of " . md5checksums_names_file . " failed! Aborting sync...")
- CheckKeyState()
- Exit()
- }
- FileDelete(md5checksums_names_file)
- FileAppend(newMd5checksums_names, md5checksums_names_file, "UTF-8")
- ; Post each file
- ; If there are no files with duplicate names, we can grab the pastes 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
- }
- 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)*$', '')
- ; 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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_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 := ''
- regexp := 's)<paste_key>.*?</paste_title>'
- 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, '<paste_title>' . api_paste_name_regex . '</paste_title>')
- {
- match_pos := RegExMatch(string, '<paste_key>(.*?)</paste_key>', match)
- api_paste_key := match[1]
- exists := 1
- Break
- }
- }
- If exists = 1
- {
- ; Overwrite it, but first create backup of it locally
- 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 in file backup 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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_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()
- ; Create backup
- 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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_results
- MsgBox(paste_results)
- CheckKeyState()
- Exit()
- }
- }
- }
- ; 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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_results
- MsgBox(paste_results)
- CheckKeyState()
- Exit()
- }
- }
- Else
- {
- paste_results .= A_Tab . paste_name . ":" . A_Tab . response . "`n"
- paste_count++
- }
- }
- ; Delete files from Pastebin that have been deleted from sync folders
- start_pos := 1
- find_pos := ''
- current_files := []
- regexp := 'm)::(.*)$'
- Loop
- {
- find_pos := RegExMatch(md5checksums_names, regexp, match, start_pos)
- If find_pos
- {
- current_files.Push(match[1])
- start_pos := match.Pos(0) + match.Len(0)
- }
- } Until find_pos = 0
- delete_files := []
- Loop current_files.Length()
- {
- current_file_regex := RegExReplace(current_files[A_Index], "([\.\^\$\*\+\?\(\)\[\{\\\|])", '\$1')
- If !RegExMatch(newMd5checksums_names, 'm)::' . current_file_regex . '$')
- {
- delete_files.Push(current_files[A_Index])
- }
- }
- ; Get list of files on Pastebin.com
- 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'
- {
- error_message := "Http request failure in retrieving pastes listing for syncing files! Error code: " . status . "`nPossibly a network error occurred. Please try again later by deleting files via regular expression hotkey Ctrl+Alt+3.`n`n"
- paste_results := error_message . paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_results
- MsgBox(paste_results)
- Exit()
- }
- If !(InStr(response,"paste"))
- {
- error_message := "Http request failure in retrieving pastes listing for syncing files! Error code: " . status . "`nPossibly a network error occurred. Please try again later by deleting files via regular expression hotkey Ctrl+Alt+3.`n`n"
- paste_results := error_message . paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_results
- MsgBox(paste_results)
- Exit()
- }
- ; Get keys for delete_files
- start_pos := 1
- find_pos := ''
- list_matches := []
- regexp := 's)<paste_key>.*?</paste_title>'
- 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
- delete_keys := [] ; We will extract this in order to use it when backing up and deleting files
- delete_titles := []
- exists := 0
- Loop delete_files.Length()
- {
- api_paste_name := delete_files[A_Index]
- Loop list_matches.Length()
- {
- string := list_matches[A_Index]
- api_paste_name_regex := RegExReplace(api_paste_name, "([\.\^\$\*\+\?\(\)\[\{\\\|])", '\$1')
- If RegExMatch(string, '<paste_title>' . api_paste_name_regex . '</paste_title>')
- {
- match_pos := RegExMatch(string, '<paste_key>(.*?)</paste_key>', match)
- delete_keys.Push(match[1])
- delete_titles.Push(api_paste_name)
- exists := 1
- Break
- }
- }
- }
- If exists
- {
- ; Create local backups
- Loop delete_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=' . delete_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 " . delete_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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_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()
- ; Write paste to local backup directory
- backup_file := pastebin_backup_dir . delete_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 " . delete_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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_results
- MsgBox(paste_results)
- CheckKeyState()
- Exit()
- }
- }
- }
- ; Delete pastes from Pastebin.com
- Loop delete_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=' . delete_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! " . 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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_results
- MsgBox(paste_results)
- CheckKeyState()
- Exit()
- }
- }
- If !(InStr(response,"removed"))
- {
- result := MsgBox("Delete failure occurred! " . delete_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
- {
- paste_results := paste_count . " file(s) were pasted to pastebin.com with " . ++paste_errors . " error(s)!`n" . paste_results . "`n" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_results
- MsgBox(paste_results)
- CheckKeyState()
- Exit()
- }
- }
- delete_count++
- delete_results .= A_Tab . delete_titles[A_Index] . '`n'
- }
- }
- 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" . delete_count . " files were deleted from pastebin.com with " . delete_errors . " error(s)!`n" . delete_results
- Clipboard := paste_results
- MsgBox(paste_results)
- CheckKeyState()
- Reload ; Necessary for syncing correctly
- Return
- ; Backup pastes based on regular expression
- ^!2::
- 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)<paste_key>.*?</paste_title>'
- 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, '<paste_title>(.*?)</paste_title>', title_match)
- title_match := title_match[1]
- If RegExMatch(title_match, regexp)
- {
- match_pos := RegExMatch(string, '<paste_key>(.*?)</paste_key>', match)
- keys.Push(match[1])
- ;match_pos := RegExMatch(string, '<paste_title>(.*?)</paste_title>', 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
- ^!3::
- 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)<paste_key>.*?</paste_title>'
- 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, '<paste_title>(.*?)</paste_title>', title_match)
- title_match := title_match[1]
- If RegExMatch(title_match, regexp)
- {
- match_pos := RegExMatch(string, '<paste_key>(.*?)</paste_key>', match)
- keys.Push(match[1])
- ;match_pos := RegExMatch(string, '<paste_title>(.*?)</paste_title>', 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
- ; List pastes based on regular expression
- ^!4::
- 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)<paste_key>.*?</paste_title>'
- 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, '<paste_title>(.*?)</paste_title>', title_match)
- title_match := title_match[1]
- If RegExMatch(title_match, regexp_search)
- {
- match_pos := RegExMatch(string, '<paste_key>(.*?)</paste_key>', 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
- ; Login to Pastebin.com (Default browser is Opera)
- ^!5::
- 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
- ; Add files/folders to the configuration/sync.txt file
- ^!6::
- global sync_file
- global files_folders
- global pastebin_backup_dir
- old_clipboard := ClipboardAll
- Clipboard := ""
- SendInput("^c")
- Clipwait(1.0)
- If ErrorLevel
- {
- MsgBox("Clipboard operation failed!")
- Clipboard := old_clipboard
- CheckKeyState()
- Exit()
- }
- new_files_folders := files_folders
- Loop Parse, Clipboard, "`n", "`r"
- {
- new_files_folders .= "`r`n" . A_LoopField
- }
- backup_sync_file := pastebin_backup_dir . "\sync.txt"
- FileCopy(sync_file, backup_sync_file, '1')
- If !(FileExist(backup_sync_file) And CheckAgeConfig(sync_file, backup_sync_file))
- {
- MsgBox("Local backup of " . sync_file . " failed! Aborting sync file update...")
- Clipboard := old_clipboard
- CheckKeyState()
- Exit()
- }
- FileDelete(sync_file)
- FileAppend(new_files_folders, sync_file, "UTF-8")
- MsgBox("Your sync file contains the following files:`n" . new_files_folders)
- CheckKeyState()
- Reload
- Return
- ; Remove files/folders to the configuration/sync.txt file
- ^!7::
- global sync_file
- global files_folders
- global pastebin_backup_dir
- old_clipboard := ClipboardAll
- Clipboard := ""
- SendInput("^c")
- Clipwait(1.0)
- If ErrorLevel
- {
- MsgBox("Clipboard operation failed!")
- Clipboard := old_clipboard
- CheckKeyState()
- Exit()
- }
- remove_files_folders := Clipboard
- new_files_folders := ""
- Loop Parse, files_folders, "`n", "`r"
- {
- path := A_LoopField
- path := RegExReplace(path, "([\.\^\$\*\+\?\(\)\[\{\\\|])", '\$1') ;escape path for regex
- If !RegExMatch(remove_files_folders, "m)^" . path . "$")
- {
- new_files_folders .= A_LoopField . "`r`n"
- }
- }
- new_files_folders := RTrim(new_files_folders, "`r`n")
- backup_sync_file := pastebin_backup_dir . "\sync.txt"
- FileCopy(sync_file, backup_sync_file, '1')
- If !(FileExist(backup_sync_file) And CheckAgeConfig(sync_file, backup_sync_file))
- {
- MsgBox("Local backup of " . sync_file . " failed! Aborting sync file update...")
- Clipboard := old_clipboard
- CheckKeyState()
- Exit()
- }
- FileDelete(sync_file)
- FileAppend(new_files_folders, sync_file, "UTF-8")
- remove_files_folders := RTrim(remove_files_folders, "`n`r")
- MsgBox("Removed the following files and folders to your sync file:`n" . remove_files_folders)
- CheckKeyState()
- Reload
- Return
- ; Help message
- ^!h::
- help_message := "1. Sync your files/folders = ^!1 (Ctrl+Alt+1)`n2. Backup pastes = ^!2 (Ctrl+Alt+2)`n3. Delete pastes = ^!3 (Ctrl+Alt+3)`n4. List pastes = ^!4 (Ctrl+Alt+4)`n5. Log into pastebin.com (Opera only) = ^!5 (Ctrl+Alt+5)`n6. Add to sync path = ^!6 (Ctrl+Alt+6)`n7. Remove from sync path = ^!7 (Ctrl+Alt+7)`n8. Help message = ^!h (Ctrl+Alt+h)"
- MsgBox(help_message)
- CheckKeyState()
- Return
Add Comment
Please, Sign In to add comment