├── requirements.txt ├── .gitignore ├── env_example ├── LICENSE ├── example-raw.py ├── example-new.py ├── example-fetch.py ├── example-delete.py ├── example-edit.py ├── README.md └── rentry.py /requirements.txt: -------------------------------------------------------------------------------- 1 | python-dotenv -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | venv 3 | .env 4 | -------------------------------------------------------------------------------- /env_example: -------------------------------------------------------------------------------- 1 | BASE_PROTOCOL="https://" 2 | BASE_URL="rentry.co" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /example-raw.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import getopt 4 | import http.cookiejar 5 | import sys 6 | import urllib.parse 7 | import urllib.request 8 | from http.cookies import SimpleCookie 9 | from json import loads as json_loads 10 | from os import environ 11 | from dotenv import load_dotenv, dotenv_values 12 | 13 | load_dotenv() 14 | env = dotenv_values() 15 | 16 | _headers = {"Referer": f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"} 17 | 18 | class UrllibClient: 19 | """Simple HTTP Session Client, keeps cookies.""" 20 | 21 | def __init__(self): 22 | self.cookie_jar = http.cookiejar.CookieJar() 23 | self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar)) 24 | urllib.request.install_opener(self.opener) 25 | 26 | def get(self, url, headers={}): 27 | request = urllib.request.Request(url, headers=headers) 28 | return self._request(request) 29 | 30 | def post(self, url, data=None, headers={}): 31 | postdata = urllib.parse.urlencode(data).encode() 32 | request = urllib.request.Request(url, postdata, headers) 33 | return self._request(request) 34 | 35 | def _request(self, request): 36 | response = self.opener.open(request) 37 | response.status_code = response.getcode() 38 | response.data = response.read().decode('utf-8') 39 | return response 40 | 41 | client, cookie = UrllibClient(), SimpleCookie() 42 | cookie.load(vars(client.get(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"))['headers']['Set-Cookie']) 43 | csrftoken = cookie['csrftoken'].value 44 | 45 | # This example does not work without further adjustments! 46 | # To use the /raw endpoint you must have a SECRET_RAW_ACCESS_CODE. You can request one from support@rentry.co. 47 | # Either set this value in each of your page, or use it below as a custom header. 48 | 49 | example_url = '10' 50 | 51 | payload = { 52 | 'csrfmiddlewaretoken': csrftoken, 53 | } 54 | 55 | _headers['rentry-auth'] = '' 56 | 57 | result_raw = json_loads(client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + f'/api/raw/{example_url}', payload, headers=_headers).data) 58 | print(result_raw) 59 | -------------------------------------------------------------------------------- /example-new.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import getopt 4 | import http.cookiejar 5 | import sys 6 | import urllib.parse 7 | import urllib.request 8 | from http.cookies import SimpleCookie 9 | import json 10 | from os import environ 11 | from dotenv import load_dotenv, dotenv_values 12 | 13 | load_dotenv() 14 | env = dotenv_values() 15 | 16 | _headers = {"Referer": f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"} 17 | 18 | class UrllibClient: 19 | """Simple HTTP Session Client, keeps cookies.""" 20 | 21 | def __init__(self): 22 | self.cookie_jar = http.cookiejar.CookieJar() 23 | self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar)) 24 | urllib.request.install_opener(self.opener) 25 | 26 | def get(self, url, headers={}): 27 | request = urllib.request.Request(url, headers=headers) 28 | return self._request(request) 29 | 30 | def post(self, url, data=None, headers={}): 31 | postdata = urllib.parse.urlencode(data).encode() 32 | request = urllib.request.Request(url, postdata, headers) 33 | return self._request(request) 34 | 35 | def _request(self, request): 36 | response = self.opener.open(request) 37 | response.status_code = response.getcode() 38 | response.data = response.read().decode('utf-8') 39 | return response 40 | 41 | client, cookie = UrllibClient(), SimpleCookie() 42 | 43 | cookie.load(vars(client.get(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"))['headers']['Set-Cookie']) 44 | csrftoken = cookie['csrftoken'].value 45 | 46 | # Provide metadata as a newline separated string, as on the website 47 | metadata = 'OPTION_DISABLE_VIEWS = true \n \ 48 | CONTAINER_MAX_WIDTH = 600px ' 49 | 50 | # Or, Format metadata as JSON 51 | metadata_obj = { 52 | 'OPTION_DISABLE_VIEWS' : True, 53 | 'CONTENT_TEXT_COLOR' : ['grey', 'red'], 54 | } 55 | metadata = json.dumps(metadata_obj) 56 | 57 | 58 | payload = { 59 | 'csrfmiddlewaretoken': csrftoken, 60 | 'text': 'test', 61 | 'metadata' : metadata 62 | } 63 | result = json.loads(client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + '/api/new', payload, headers=_headers).data) 64 | print(result) -------------------------------------------------------------------------------- /example-fetch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import getopt 4 | import http.cookiejar 5 | import sys 6 | import urllib.parse 7 | import urllib.request 8 | from http.cookies import SimpleCookie 9 | from json import loads as json_loads 10 | from os import environ 11 | from dotenv import load_dotenv, dotenv_values 12 | 13 | load_dotenv() 14 | env = dotenv_values() 15 | 16 | _headers = {"Referer": f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"} 17 | 18 | class UrllibClient: 19 | """Simple HTTP Session Client, keeps cookies.""" 20 | 21 | def __init__(self): 22 | self.cookie_jar = http.cookiejar.CookieJar() 23 | self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar)) 24 | urllib.request.install_opener(self.opener) 25 | 26 | def get(self, url, headers={}): 27 | request = urllib.request.Request(url, headers=headers) 28 | return self._request(request) 29 | 30 | def post(self, url, data=None, headers={}): 31 | postdata = urllib.parse.urlencode(data).encode() 32 | request = urllib.request.Request(url, postdata, headers) 33 | return self._request(request) 34 | 35 | def _request(self, request): 36 | response = self.opener.open(request) 37 | response.status_code = response.getcode() 38 | response.data = response.read().decode('utf-8') 39 | return response 40 | 41 | client, cookie = UrllibClient(), SimpleCookie() 42 | 43 | cookie.load(vars(client.get(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"))['headers']['Set-Cookie']) 44 | csrftoken = cookie['csrftoken'].value 45 | 46 | ## First, create 47 | payload = { 48 | 'csrfmiddlewaretoken': csrftoken, 49 | 'text': 'test', 50 | 'metadata' : 'OPTION_DISABLE_VIEWS = true', 51 | } 52 | result_create = json_loads(client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + '/api/new', payload, headers=_headers).data) 53 | print(result_create) 54 | 55 | ## Then, fetch 56 | payload = { 57 | 'csrfmiddlewaretoken': csrftoken, 58 | 'edit_code' : result_create['edit_code'], 59 | } 60 | result_fetch = client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + f"/api/fetch/{result_create['url_short']}", payload, headers=_headers).data 61 | print(result_fetch) 62 | 63 | -------------------------------------------------------------------------------- /example-delete.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import getopt 4 | import http.cookiejar 5 | import sys 6 | import urllib.parse 7 | import urllib.request 8 | from http.cookies import SimpleCookie 9 | from json import loads as json_loads 10 | from os import environ 11 | from dotenv import load_dotenv, dotenv_values 12 | 13 | load_dotenv() 14 | env = dotenv_values() 15 | 16 | _headers = {"Referer": f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"} 17 | 18 | class UrllibClient: 19 | """Simple HTTP Session Client, keeps cookies.""" 20 | 21 | def __init__(self): 22 | self.cookie_jar = http.cookiejar.CookieJar() 23 | self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar)) 24 | urllib.request.install_opener(self.opener) 25 | 26 | def get(self, url, headers={}): 27 | request = urllib.request.Request(url, headers=headers) 28 | return self._request(request) 29 | 30 | def post(self, url, data=None, headers={}): 31 | postdata = urllib.parse.urlencode(data).encode() 32 | request = urllib.request.Request(url, postdata, headers) 33 | return self._request(request) 34 | 35 | def _request(self, request): 36 | response = self.opener.open(request) 37 | response.status_code = response.getcode() 38 | response.data = response.read().decode('utf-8') 39 | return response 40 | 41 | client, cookie = UrllibClient(), SimpleCookie() 42 | 43 | cookie.load(vars(client.get(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"))['headers']['Set-Cookie']) 44 | csrftoken = cookie['csrftoken'].value 45 | 46 | ## First, create 47 | payload = { 48 | 'csrfmiddlewaretoken': csrftoken, 49 | 'text': 'test', 50 | 'metadata' : 'OPTION_DISABLE_VIEWS = true', 51 | #'edit_code' : 'custom_edit_code', 52 | #'url' : 'custom_url', 53 | } 54 | result_create = json_loads(client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + '/api/new', payload, headers=_headers).data) 55 | print(result_create) 56 | 57 | ## Then, delete 58 | payload = { 59 | 'csrfmiddlewaretoken': csrftoken, 60 | 'edit_code' : result_create['edit_code'], 61 | } 62 | #result_delete = client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + f"/api/delete/{result_create['url_short']}", payload, headers=_headers).data 63 | result_delete = client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + f"/api/delete/{result_create['url_short']}", payload, headers=_headers).data 64 | print(result_delete) 65 | -------------------------------------------------------------------------------- /example-edit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import getopt 4 | import http.cookiejar 5 | import sys 6 | import urllib.parse 7 | import urllib.request 8 | from http.cookies import SimpleCookie 9 | from json import loads as json_loads 10 | from os import environ 11 | from dotenv import load_dotenv, dotenv_values 12 | 13 | load_dotenv() 14 | env = dotenv_values() 15 | 16 | _headers = {"Referer": f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"} 17 | 18 | class UrllibClient: 19 | """Simple HTTP Session Client, keeps cookies.""" 20 | 21 | def __init__(self): 22 | self.cookie_jar = http.cookiejar.CookieJar() 23 | self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar)) 24 | urllib.request.install_opener(self.opener) 25 | 26 | def get(self, url, headers={}): 27 | request = urllib.request.Request(url, headers=headers) 28 | return self._request(request) 29 | 30 | def post(self, url, data=None, headers={}): 31 | postdata = urllib.parse.urlencode(data).encode() 32 | request = urllib.request.Request(url, postdata, headers) 33 | return self._request(request) 34 | 35 | def _request(self, request): 36 | response = self.opener.open(request) 37 | response.status_code = response.getcode() 38 | response.data = response.read().decode('utf-8') 39 | return response 40 | 41 | client, cookie = UrllibClient(), SimpleCookie() 42 | 43 | cookie.load(vars(client.get(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"))['headers']['Set-Cookie']) 44 | csrftoken = cookie['csrftoken'].value 45 | 46 | ## First, create 47 | payload = { 48 | 'csrfmiddlewaretoken': csrftoken, 49 | 'text': 'test', 50 | 'metadata' : 'SECRET_EMAIL_ADDRESS = support@rentry.co', 51 | } 52 | result_create = json_loads(client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + '/api/new', payload, headers=_headers).data) 53 | print(result_create) 54 | 55 | ## Then, edit 56 | payload = { 57 | 'csrfmiddlewaretoken': csrftoken, 58 | 'text': 'test updated!', 59 | 'edit_code' : result_create['edit_code'], 60 | 'new_modify_code' : 'm:abc', 61 | 'update_mode' : 'upsert', # This causes only these metadata options to change, rather than a full replacement. Remove if you want to replace fully. 62 | 'metadata' : 'CONTAINER_PADDING = 10px \n \ 63 | CONTAINER_MAX_WIDTH = 600px \n \ 64 | CONTAINER_INNER_FOREGROUND_COLOR = RGBA(123,123,123,0.2) \n \ 65 | CONTAINER_INNER_BACKGROUND_COLOR = transparent \n \ 66 | CONTAINER_INNER_BACKGROUND_IMAGE = https://rentry.co/static/icons/512.png' 67 | } 68 | result_edit = client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + f"/api/edit/{result_create['url_short']}", payload, headers=_headers).data 69 | print(result_edit) 70 | 71 | ## Edit Using modify code 72 | payload = { 73 | 'csrfmiddlewaretoken': csrftoken, 74 | 'text': 'test updated using modify', 75 | 'edit_code' : 'm:abc', 76 | 'update_mode' : 'upsert', 77 | 'metadata' : "CONTENT_FONT_WEIGHT = 600 \n \ 78 | " 79 | } 80 | result_edit = client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + f"/api/edit/{result_create['url_short']}", payload, headers=_headers).data 81 | print(result_edit) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rentry 2 | 3 | rentry.co markdown paste repository 4 | 5 | [Rentry.co](https://rentry.co) is markdown-powered paste/publishing service with preview, custom urls and editing. 6 | 7 | This repository contains a simple script that allows pasting and editing from command line interface. It also gives examples for accessing each endpoint programatically. 8 | 9 | ## Installation 10 | 11 | ##### Manually: 12 | ```sh 13 | wget https://raw.githubusercontent.com/radude/rentry/master/rentry -O ./rentry && chmod +x ./rentry 14 | ``` 15 | 16 | 17 | 18 | pip install -r 'requirements.txt' 19 | cp env_example .env 20 | 21 | ## Usage (Command Interface) 22 | 23 | ```console 24 | $ rentry --help 25 | 26 | Usage: rentry {new | edit | raw} {-h | --help} {-u | --url} {-p | --edit-code} text 27 | 28 | Commands: 29 | new create a new entry 30 | edit edit an existing entry's text 31 | raw get raw markdown text of an existing entry 32 | delete delete an entry 33 | 34 | Options: 35 | -h, --help show this help message and exit 36 | -u, --url URL url for the entry, random if not specified 37 | -p, --edit-code EDIT-CODE edit code for the entry, random if not specified 38 | -f, --field FIELD-NAME the field you wish to update (use on update command only) 39 | -v, --value VALUE the value you wish to update (use on update command only) 40 | 41 | Fields: (for use on update command only) 42 | edit_code 43 | url 44 | modify_code 45 | 46 | Examples: 47 | rentry new 'markdown text' # new entry with random url and edit code 48 | rentry new -p pw -u example 'text' # with custom edit code and url 49 | rentry edit -p pw -u example 'text' # edit the example entry 50 | cat FILE | rentry new # read from FILE and paste it to rentry 51 | cat FILE | rentry edit -p pw -u example # read from FILE and edit the example entry 52 | rentry raw -u example # get raw markdown text 53 | rentry raw -u https://rentry.co/example # -u accepts absolute and relative urls 54 | 55 | rentry delete -p pw -u example # deletes an entry 56 | rentry update -p pw -u example -f 'edit_code' -v 'new-pw' # Sets the edit code to something new 57 | rentry update -p pw -u example -f 'url' -v 'new_url' # Sets the url to something new 58 | rentry update -p pw -u example -f 'modify_code' -v 'm:1' # Sets the modify code to something new 59 | rentry update -p pw -u example -f 'modify_code' -v '' # Unsets the modify code 60 | 61 | ``` 62 | 63 | ##### Url 64 | 65 | Optional Url can be set (`-u, --url URL`) 66 | It goes rentry.co/HERE. If no Url was set then random Url will be generated automatically. 67 | 68 | ##### Edit code 69 | 70 | Optional edit code can be set (`-p, --edit-code EDIT-CODE`) 71 | It can be used to edit the entry later. If no edit code was set then random edit code will be generated automatically. Generated edit code will be shown to you only once, so remember it or save it. You can share this code with anyone so a group of people can edit the same entry. 72 | 73 | ## Usage (API) 74 | 75 | See the example scripts for a quick start. 76 | 77 | Send a standard POST request to the below endpoints. Make sure to provide a csrf token and a request header. 78 | 79 | Starred fields are required. replace [url] with the actual URL in question (without brackets). 80 | 81 | Example endpoint (Editing rentry.co/example): /edit/example 82 | 83 | All fields that can be used as well as set (url, edit_code, modify_code) have new_ appended to their names when setting them. 84 | 85 | ### Returns 86 | 87 | * status 88 | * content (if status is not 200, the error will be displayed here. Otherwise, all return values below are returned contained within this field) 89 | 90 | ### /new 91 | 92 | Fields: 93 | 94 | * csrfmiddlewaretoken * 95 | * text * 96 | * metadata 97 | * url 98 | * edit_code 99 | 100 | ### /edit/[url] 101 | 102 | You may provide a modify code to the edit_code field if one is set. Use this to give other people edit access to a page without the ability to steal it. 103 | 104 | Fields: 105 | 106 | * csrfmiddlewaretoken * 107 | * edit_code * 108 | * text 109 | * metadata 110 | * update_mode 111 | * new_url 112 | * new_edit_code 113 | * new_modify_code (provide 'm:' to unset, this matches the website's functionality) 114 | 115 | ### /raw/[url] 116 | 117 | Fields: 118 | 119 | * csrfmiddlewaretoken * 120 | * url 121 | 122 | Headers: 123 | 124 | rentry-auth (contact support@rentry.co for a code to use here. This header then gives access to all posts at /raw). Or use it as a page's metadata value : SECRET_RAW_ACCESS_CODE to permit raw access without this header. 125 | 126 | Returns: 127 | 128 | * text 129 | 130 | To fetch metadata, please use /fetch endpoint 131 | 132 | ### /fetch/[url] 133 | 134 | Fields: 135 | 136 | * csrfmiddlewaretoken * 137 | * edit_code * 138 | 139 | Returns: 140 | 141 | * url 142 | * url_case (if you set the URL with a different case structure than all lowercase, this will reflect that) 143 | * views 144 | * pub_date (YYYY-MM-DD T HH:MM:SS) (will not change if deleted and re-created) 145 | * activated_date (if deleted and re-created, this is when this occured last) 146 | * edit_date 147 | * modify_code_set (bool) 148 | * text 149 | * metadata (returns as an object with key/value pairs. Each value is the entire set metadata value as a single string) 150 | * metadata_version 151 | 152 | ### /delete/[url] 153 | 154 | Fields: 155 | 156 | * csrfmiddlewaretoken * 157 | * edit_code * 158 | -------------------------------------------------------------------------------- /rentry.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import getopt 4 | import http.cookiejar 5 | import sys 6 | import urllib.parse 7 | import urllib.request 8 | from http.cookies import SimpleCookie 9 | from json import loads as json_loads 10 | from os import environ 11 | from dotenv import load_dotenv, dotenv_values 12 | 13 | load_dotenv() 14 | env = dotenv_values() 15 | 16 | _headers = {"Referer": f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"} 17 | 18 | 19 | class UrllibClient: 20 | """Simple HTTP Session Client, keeps cookies.""" 21 | 22 | def __init__(self): 23 | self.cookie_jar = http.cookiejar.CookieJar() 24 | self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar)) 25 | urllib.request.install_opener(self.opener) 26 | 27 | def get(self, url, headers={}): 28 | request = urllib.request.Request(url, headers=headers) 29 | return self._request(request) 30 | 31 | def post(self, url, data=None, headers={}): 32 | postdata = urllib.parse.urlencode(data).encode() 33 | request = urllib.request.Request(url, postdata, headers) 34 | return self._request(request) 35 | 36 | def _request(self, request): 37 | response = self.opener.open(request) 38 | response.status_code = response.getcode() 39 | response.data = response.read().decode('utf-8') 40 | return response 41 | 42 | 43 | def raw(url): 44 | client = UrllibClient() 45 | endpoint = f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + '/api/raw/{}'.format(url) 46 | print(endpoint) 47 | return json_loads(client.get(endpoint).data) 48 | 49 | 50 | def new(url, edit_code, text): 51 | client, cookie = UrllibClient(), SimpleCookie() 52 | 53 | cookie.load(vars(client.get(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"))['headers']['Set-Cookie']) 54 | csrftoken = cookie['csrftoken'].value 55 | 56 | payload = { 57 | 'csrfmiddlewaretoken': csrftoken, 58 | 'url': url, 59 | 'edit_code': edit_code, 60 | 'text': text 61 | } 62 | return json_loads(client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + '/api/new', payload, headers=_headers).data) 63 | 64 | 65 | def edit(url, edit_code, text): 66 | client, cookie = UrllibClient(), SimpleCookie() 67 | 68 | cookie.load(vars(client.get(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}"))['headers']['Set-Cookie']) 69 | csrftoken = cookie['csrftoken'].value 70 | 71 | payload = { 72 | 'csrfmiddlewaretoken': csrftoken, 73 | 'edit_code': edit_code, 74 | 'text': text 75 | } 76 | 77 | return json_loads(client.post(f"{env['BASE_PROTOCOL']}{env['BASE_URL']}" + '/api/edit/{}'.format(url), payload, headers=_headers).data) 78 | 79 | 80 | def usage(): 81 | print(''' 82 | Usage: rentry {new | edit | raw} {-h | --help} {-u | --url} {-p | --edit-code} text 83 | 84 | Commands: 85 | new create a new entry 86 | edit edit an existing entry 87 | raw get raw markdown text of an existing entry 88 | 89 | Options: 90 | -h, --help show this help message and exit 91 | -u, --url URL url for the entry, random if not specified 92 | -p, --edit-code EDIT-CODE edit code for the entry, random if not specified 93 | 94 | Examples: 95 | rentry new 'markdown text' # new entry with random url and edit code 96 | rentry new -p pw -u example 'text' # with custom edit code and url 97 | rentry edit -p pw -u example 'text' # edit the example entry 98 | cat FILE | rentry new # read from FILE and paste it to rentry 99 | cat FILE | rentry edit -p pw -u example # read from FILE and edit the example entry 100 | rentry raw -u example # get raw markdown text 101 | rentry raw -u https://rentry.co/example # -u accepts absolute and relative urls 102 | ''') 103 | 104 | 105 | if __name__ == '__main__': 106 | try: 107 | environ.pop('POSIXLY_CORRECT', None) 108 | opts, args = getopt.gnu_getopt(sys.argv[1:], "hu:p:", ["help", "url=", "edit-code="]) 109 | except getopt.GetoptError as e: 110 | sys.exit("error: {}".format(e)) 111 | 112 | command, url, edit_code, text = None, '', '', None 113 | 114 | for o, a in opts: 115 | if o in ("-h", "--help"): 116 | usage() 117 | sys.exit() 118 | elif o in ("-u", "--url"): 119 | url = urllib.parse.urlparse(a).path.strip('/') 120 | elif o in ("-p", "--edit-code"): 121 | edit_code = a 122 | 123 | command = (args[0:1] or [None])[0] 124 | command or sys.exit(usage()) 125 | command in ['new', 'edit', 'raw'] or sys.exit('error: command must be new, edit or raw') 126 | 127 | text = (args[1:2] or [None])[0] 128 | if not text and command != 'raw': 129 | text = sys.stdin.read().strip() 130 | text or sys.exit('error: text is required') 131 | 132 | if command == 'new': 133 | response = new(url, edit_code, text) 134 | if response['status'] != '200': 135 | print('error: {}'.format(response['content'])) 136 | try: 137 | for i in response['errors'].split('.'): 138 | i and print(i) 139 | sys.exit(1) 140 | except: 141 | sys.exit(1) 142 | else: 143 | print('Url: {}\nEdit code: {}'.format(response['url'], response['edit_code'])) 144 | 145 | elif command == 'edit': 146 | url or sys.exit('error: url is required') 147 | edit_code or sys.exit('error: edit code is required') 148 | 149 | response = edit(url, edit_code, text) 150 | if response['status'] != '200': 151 | print('error: {}'.format(response['content'])) 152 | try: 153 | for i in response['errors'].split('.'): 154 | i and print(i) 155 | sys.exit(1) 156 | except: 157 | sys.exit(1) 158 | else: 159 | print('Ok') 160 | 161 | elif command == 'raw': 162 | url or sys.exit('error: url is required') 163 | response = raw(url) 164 | if response['status'] != '200': 165 | sys.exit('error: {}'.format(response['content'])) 166 | print(response['content']) 167 | --------------------------------------------------------------------------------