Search code examples
pythonpython-requestspastebin

POSTing Pastebin API to create a past in Python and get a correct reply, yet the pasted data is incorrect


So I am attempting to code a program that POSTs towards Pastebin and creates a new paste. The posting, requesting, etc is all going fine - yet when I check the actual Paste, it is just a single word in the source code. I sent the POSTed data to https://httpbin.org/post and all the data is fine, yet I get the wrong pasted data.

Code:

#!/usr/bin/python3

import requests
import argparse
import sys

epilog = """Usage: sourcepaste [ FILENAME ] [ LANGUAGE ] [ OPTIONS ]

          Example use(s):
                sourcepaste testfile.py python 2 6M
                sourcepaste source.cpp cpp
                sourcepaste js.js javascript 1
                """

parser = argparse.ArgumentParser(description='A CLI-based way to post on Pastebin',
                                 prog="sourcepaste",
                                 epilog=epilog)
parser.add_argument('source',
                    help='the file of your source code')
parser.add_argument('language',
                    help='the language of your source code | check langs.txt for all available languages')
parser.add_argument('privacy', nargs='?',
                    help='how private you want your post | 0 = Public, 1 = Unlisted, 2 = Private | Default = 0')
parser.add_argument('time', nargs='?',
                    help="""when your post should expire | N(ever), 10M(inutes), 1H(our), 1D(ay),
                         1W(eek), 2W(eeks), 1M(onth), 6M(onths), 1Y(ear) | Default = 1W(eek)""")

parse_args = parser.parse_args()

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36',
    'Content-Type': 'application/x-www-form-urlencoded'
}

with open(parse_args.source, "r") as source_code_read:
    source_code_content = source_code_read.read()

if (len(sys.argv) - 1) == 2:
    data = f"api_dev_key=<my-dev-key>&api_paste_code={source_code_content}&api_option=paste&api_user_key=<my-user-key>&api_paste_expire_date=1W&api_paste_private=0&api_paste_name={parse_args.source}@{parse_args.language}&api_paste_format={parse_args.language}"
elif (len(sys.argv) - 1) == 3:
    data = f"api_dev_key=<my-dev-key>&api_paste_code={source_code_content}&api_option=paste&api_user_key=<my-user-key>&api_paste_expire_date=1W&api_paste_private={parse_args.privacy}&api_paste_name={parse_args.source}@{parse_args.language}&api_paste_format={parse_args.language}"
elif (len(sys.argv) - 1) == 4:
    data = f"api_dev_key=<my-dev-key>&api_paste_code={source_code_content}&api_option=paste&api_user_key=<my-user-key>&api_paste_expire_date={parse_args.time}&api_paste_private={parse_args.privacy}&api_paste_name={parse_args.source}@{parse_args.language}&api_paste_format={parse_args.language}"

pageget = requests.post("https://pastebin.com/api/api_post.php", headers=headers, data=data)

print(pageget.content)

My shell inputs:

./sourcepaste test.py python 2 N

Example reply:

https://pastebin.com/IuHbDt

Content at link:

{test_content} - no other pieces of the code

Would love some help on this; to me it's very strange how the POST data is correct, the reply is fine, yet the actual paste is incorrect.

Thanks!


Solution

  • Your mistake is trying to gather data into a string. It should be a dict. On the other, it works well. However, there are some technical issues with it. For example, the way you collect POST parameters into data, it could be done much better. But I feel the aren't the reason for your question.

    So I reworked your solution a little, now it works:

    import requests
    import argparse
    import sys
    
    API_DEV_KEY = "<MY_API_DEV_KEY>"
    
    epilog = """Usage: sourcepaste [ FILENAME ] [ LANGUAGE ] [ OPTIONS ]
    
              Example use(s):
                    sourcepaste testfile.py python 2 6M
                    sourcepaste source.cpp cpp
                    sourcepaste js.js javascript 1
                    """
    
    parser = argparse.ArgumentParser(description='A CLI-based way to post on Pastebin',
                                     prog="sourcepaste",
                                     epilog=epilog)
    parser.add_argument('source',
                        help='the file of your source code')
    parser.add_argument('language',
                        help='the language of your source code | check langs.txt for all available languages')
    parser.add_argument('privacy', nargs='?',
                        help='how private you want your post | 0 = Public, 1 = Unlisted, 2 = Private | Default = 0')
    parser.add_argument('time', nargs='?',
                        help="""when your post should expire | N(ever), 10M(inutes), 1H(our), 1D(ay),
                             1W(eek), 2W(eeks), 1M(onth), 6M(onths), 1Y(ear) | Default = 1W(eek)""")
    
    parse_args = parser.parse_args()
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36',
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    
    with open(parse_args.source, "r") as source_code_read:
        source_code_content = source_code_read.read()
    
    data = None
    if (len(sys.argv) - 1) == 2:
        data = {
            "api_dev_key": API_DEV_KEY,
            "api_paste_code": source_code_content,
            "api_option": "paste",
            "api_paste_expire_date": "1W",
            "api_paste_private": "0",
            "api_paste_name": f"{parse_args.source}@{parse_args.language}",
            "api_paste_format": parse_args.language,
        }
    
    if data:
        response = requests.post("https://pastebin.com/api/api_post.php", headers=headers, data=data)
        print(response.content)
    
    

    Result:

    enter image description here

    You can see, I reworked your script only for two params: source and language. I have no doubts, now you can add all extra params you need by yourself.