hyerob icon

pastebin_api.ahk

hyerob | PRO | 04/03/19 02:10:14 PM UTC | 0 ⭐ | 1634 👁️ | Never ⏰ | []
Autohotkey |

75.36 KB

|

None

|

0 👍

/

0 👎

;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)<paste_key>.*?</paste_title>'
        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, '<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
        {
            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)<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
        {
            ; 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)<paste_key>.*?</paste_title>'
        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, '<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
        {
            ; 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)<paste_key>.*?</paste_title>'
        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, '<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
        {
            ; 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)<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
^!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)<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
 
; 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)<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
    file_count := matches.Length()
    file_list := 'You have ' . matches.Length() . ' pastes.`n`n'
    Loop matches.Length()
    {
        string := matches[A_Index]
        match_pos := RegExMatch(string, '<paste_title>(.*?)</paste_title>', title_match)
        title_match := title_match[1]
        match_pos := RegExMatch(string, '<paste_key>(.*?)</paste_key>', 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)<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
 
; 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)<paste_key>.*?</paste_title>'
        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, '<paste_title>' . api_paste_name_regex . '</paste_title>') 
            {
                match_pos := RegExMatch(string, '<paste_key>(.*?)</paste_key>', 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

Comments