diff --git a/TryUTF8Read.py b/TryUTF8Read.py
new file mode 100755
index 0000000..53a196a
--- /dev/null
+++ b/TryUTF8Read.py
@@ -0,0 +1,26 @@
+#!/usr/bin/python3
+import sys
+import codecs
+
+def test_utf8_encoding(filepath):
+ try:
+ with codecs.open(filepath, 'r', 'utf-8') as testfile:
+ testfile.read()
+ #print(f"{filepath} is openable with UTF-8 encoding.")
+ except UnicodeDecodeError:
+ print(f"{filepath} is not openable with UTF-8 encoding.")
+ print(f"Converting {filepath} from ISO-8859-1 to UTF-8...")
+ with codecs.open(filepath, 'r', 'iso-8859-1') as f:
+ content = f.read()
+ utf8_content = content.decode('iso-8859-1').encode('utf-8')
+ with codecs.open(filepath, 'w', 'utf-8') as f:
+ f.write(utf8_content)
+ print(f"{filepath} has been converted to UTF-8.")
+
+if len(sys.argv) < 2:
+ print("Please provide a file name as a command line argument.")
+ sys.exit(1)
+
+filepath = sys.argv[1]
+test_utf8_encoding(filepath)
+
diff --git a/btc_timeseries.db b/btc_timeseries.db
index 7100493..7274b2c 100644
Binary files a/btc_timeseries.db and b/btc_timeseries.db differ
diff --git a/btc_tracker/01042023/TheClient/bin/TheClient.py b/btc_tracker/01042023/TheClient/bin/TheClient.py
new file mode 100644
index 0000000..e747167
--- /dev/null
+++ b/btc_tracker/01042023/TheClient/bin/TheClient.py
@@ -0,0 +1,20 @@
+
+import os
+import configparser
+import requests
+from datetime import datetime
+from TheClient.database.db_utils import Database
+from TheClient.graphing.graph_utils import Graph
+
+def load_config(config_file):
+ config = configparser.ConfigParser()
+ config.read(config_file)
+ return config
+
+def get_btc_price():
+ response = requests.get('https://api.binance.com/api/v3/avgPrice', params={'symbol': 'BTCUSDT'})
+ json_data = response.json()
+ return float(json_data['price'])
+
+def main():
+ config = load_config(os.path.join(os.path.dirname(__file__), '..', 'config', 'The
diff --git a/btc_tracker/01042023/TheClient/config/TheClient.conf b/btc_tracker/01042023/TheClient/config/TheClient.conf
new file mode 100644
index 0000000..e69de29
diff --git a/btc_tracker/01042023/TheClient/database/__init__.py b/btc_tracker/01042023/TheClient/database/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/btc_tracker/01042023/TheClient/database/db_utils.py b/btc_tracker/01042023/TheClient/database/db_utils.py
new file mode 100644
index 0000000..d5bf201
--- /dev/null
+++ b/btc_tracker/01042023/TheClient/database/db_utils.py
@@ -0,0 +1,27 @@
+import sqlite3
+
+class Database():
+ def __init__(self, db_file):
+ self.db_file = db_file
+ self._create_table()
+
+ def _create_table(self):
+ with sqlite3.connect(self.db_file) as conn:
+ cursor = conn.cursor()
+ cursor.execute('''CREATE TABLE IF NOT EXISTS timeseries
+ (timestamp INTEGER PRIMARY KEY, value REAL)''')
+ conn.commit()
+
+ def insert_data(self, timestamp, value):
+ with sqlite3.connect(self.db_file) as conn:
+ cursor = conn.cursor()
+ cursor.execute('''INSERT INTO timeseries (timestamp, value)
+ VALUES (?, ?)''', (timestamp, value))
+ conn.commit()
+
+ def fetch_data(self, limit):
+ with sqlite3.connect(self.db_file) as conn:
+ cursor = conn.cursor()
+ cursor.execute('''SELECT timestamp, value FROM timeseries
+ ORDER BY timestamp DESC LIMIT ?''', (limit,))
+ return cursor.fetchall()
diff --git a/btc_tracker/01042023/TheClient/fetch/__init__.py b/btc_tracker/01042023/TheClient/fetch/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/btc_tracker/01042023/TheClient/graphing/__init__.py b/btc_tracker/01042023/TheClient/graphing/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/btc_tracker/01042023/TheClient/graphing/graph_utils.py b/btc_tracker/01042023/TheClient/graphing/graph_utils.py
new file mode 100644
index 0000000..cf9ba9f
--- /dev/null
+++ b/btc_tracker/01042023/TheClient/graphing/graph_utils.py
@@ -0,0 +1,12 @@
+import matplotlib.pyplot as plt
+
+class Graph():
+ def __init__(self, xdata, ydata):
+ self.fig, self.ax = plt.subplots()
+ self.line, = self.ax.plot(xdata, ydata)
+
+ def update_graph(self, xdata, ydata):
+ self.line.set_data(xdata, ydata)
+ self.ax.relim()
+ self.ax.autoscale_view()
+ self.fig.canvas.draw()
diff --git a/btc_tracker/01042023/TheClient/requirements.txt b/btc_tracker/01042023/TheClient/requirements.txt
new file mode 100644
index 0000000..290591c
--- /dev/null
+++ b/btc_tracker/01042023/TheClient/requirements.txt
@@ -0,0 +1,2 @@
+requests==2.25.1
+matplotlib==3.6.2
diff --git a/btc_tracker/01042023/TheClient/tests/__init__.py b/btc_tracker/01042023/TheClient/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/btc_tracker/01042023/TheClient/tests/test_TheClient.py b/btc_tracker/01042023/TheClient/tests/test_TheClient.py
new file mode 100644
index 0000000..e69de29
diff --git a/btc_tracker/01042023/TheClient/tests/test_db_utils.py b/btc_tracker/01042023/TheClient/tests/test_db_utils.py
new file mode 100644
index 0000000..e69de29
diff --git a/btc_tracker/01042023/TheClient/tests/test_graph_utils.py b/btc_tracker/01042023/TheClient/tests/test_graph_utils.py
new file mode 100644
index 0000000..e69de29
diff --git a/chat.html b/chat.html
new file mode 100644
index 0000000..42bca1a
--- /dev/null
+++ b/chat.html
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
User ID: null
+
+
+
+
+
+
+
+
+
+
diff --git a/conver-iso-to-utf8.py b/conver-iso-to-utf8.py
new file mode 100755
index 0000000..8ca1282
--- /dev/null
+++ b/conver-iso-to-utf8.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python3
+import sys
+import io
+
+def convert_iso8859_to_utf8(filepath):
+ # open the file with ISO-8859-1 encoding
+ with io.open(filepath, 'r', encoding='iso-8859-1') as f:
+ # read the file's content
+ content = f.read()
+ # write the UTF-8 encoded content to a new file
+ with io.open(filepath, 'w', encoding='utf-8') as f:
+ f.write(content)
+ print(f"{filepath} has been converted to UTF-8.")
+
+
+filepath = sys.argv[1]
+convert_iso8859_to_utf8(filepath)
diff --git a/letters/fifo-sample.py b/letters/fifo-sample.py
new file mode 100755
index 0000000..6a91bcb
--- /dev/null
+++ b/letters/fifo-sample.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python3
+import os
+import sys
+import queue
+import threading
+
+def listen_to_fifo(q):
+ fifo = "/tmp/my_fifo"
+ if not os.path.exists(fifo):
+ os.mkfifo(fifo)
+ with open(fifo, 'r') as f:
+ while True:
+ data = f.readline().strip()
+ if not data:
+ break
+ q.put(data)
+
+def read_queue(q):
+ while True:
+ data = q.get()
+ if data == "reboot":
+ # Restart the script
+ print('## RESTARTING SCRIPT')
+ os.execv(sys.executable, [sys.executable] + sys.argv)
+ else:
+ print(data)
+ sys.stdout.flush()
+ q.task_done()
+
+if __name__ == '__main__':
+ q = queue.Queue()
+ t1 = threading.Thread(target=listen_to_fifo, args=(q,))
+ t2 = threading.Thread(target=read_queue, args=(q,))
+ t1.start()
+ t2.start()
+ q.join()
diff --git a/letters/fifo-sample_with-commands.py b/letters/fifo-sample_with-commands.py
new file mode 100755
index 0000000..4af7f79
--- /dev/null
+++ b/letters/fifo-sample_with-commands.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python3
+import os
+import sys
+import queue
+import threading
+
+command_queue = queue.Queue()
+fifo_file = "/tmp/my_fifo"
+
+def listen_to_fifo(queue):
+ if not os.path.exists(fifo_file):
+ os.mkfifo(fifo_file)
+ with open(fifo_file, 'r') as f:
+ while True:
+ data = f.readline().strip()
+ if not data:
+ break
+ queue.put(data)
+
+def read_queue(queue):
+ while True:
+ data = queue.get()
+ if data == "reboot":
+ fifo_file.close()
+ os.execv(sys.executable, [sys.executable] + sys.argv)
+ print(data)
+ sys.stdout.flush()
+ queue.task_done()
+
+if __name__ == '__main__':
+ t1 = threading.Thread(target=listen_to_fifo, args=(command_queue,))
+ t2 = threading.Thread(target=read_queue, args=(command_queue,))
+ t1.start()
+ t2.start()
+ command_queue.join()
diff --git a/letters/sample_function.py b/letters/sample_function.py
new file mode 100644
index 0000000..2b466d0
--- /dev/null
+++ b/letters/sample_function.py
@@ -0,0 +1,27 @@
+import requests
+import json
+import ecdsa
+import binascii
+
+def get_btc_ohlc_data(server_url, user_private_key):
+ # Load user's ECDSA private key
+ user_private_key = ecdsa.SigningKey.from_string(binascii.unhexlify(user_private_key), curve=ecdsa.SECP256k1)
+ # Get server public key from endpoint
+ server_public_key_hex = requests.get(server_url + "/serverkey").text
+ server_public_key = ecdsa.VerifyingKey.from_string(binascii.unhexlify(server_public_key_hex), curve=ecdsa.SECP256k1)
+ # Get timestamp
+ timestamp = str(int(time.time()))
+ # Create signature using user's private key
+ signature = binascii.hexlify(user_private_key.sign(bytes(timestamp, 'utf-8'))).decode("utf-8")
+ # Create authentication header
+ auth_header = {"auth": timestamp + ":" + signature}
+ # Make request to server with auth header
+ response = requests.get(server_url + "/t", headers=auth_header)
+ # Verify server's signature
+ server_signature = response.headers["signature"]
+ if server_public_key.verify(bytes(server_signature, 'utf-8'), bytes(timestamp, 'utf-8')):
+ # If signature is valid, return json data
+ return json.loads(response.text)
+ else:
+ # If signature is invalid, return error message
+ return {"error": "Invalid signature from server"}
diff --git a/pastedb/cpaste.py b/pastedb/cpaste.py
new file mode 100755
index 0000000..d7f872f
--- /dev/null
+++ b/pastedb/cpaste.py
@@ -0,0 +1,377 @@
+#!/usr/bin/env python3
+#
+#######################################################################
+#
+# A script to paste to https://cpaste.org/
+#
+# Copyright (c) 2013-2019 Andreas Schneider
+# Copyright (c) 2013 Alexander Bokovoy
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#######################################################################
+#
+# Requires: python3-requests
+# Requires: python3-cryptography
+#
+# Optionally requires: python-Pygments
+#
+
+import os
+import sys
+import json
+import base64
+import zlib
+import requests
+from cryptography.hazmat.primitives.ciphers.aead import AESGCM
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
+from cryptography.hazmat.backends import default_backend
+from optparse import OptionParser
+from mimetypes import guess_type
+try:
+ from pygments.lexers import guess_lexer, guess_lexer_for_filename
+ from pygments.util import ClassNotFound
+ guess_lang = True
+except ImportError:
+ guess_lang = False
+
+
+def base58_encode(v: bytes):
+ # 58 char alphabet
+ alphabet = b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
+ alphabet_len = len(alphabet)
+
+ nPad = len(v)
+ v = v.lstrip(b'\0')
+ nPad -= len(v)
+
+ x = 0
+ for (i, c) in enumerate(v[::-1]):
+ if isinstance(c, str):
+ c = ord(c)
+ x += c << (8 * i)
+
+ string = b''
+ while x:
+ x, idx = divmod(x, alphabet_len)
+ string = alphabet[idx:idx+1] + string
+
+ return (alphabet[0:1] * nPad + string)
+
+
+def json_encode(d):
+ return json.dumps(d, separators=(',', ':')).encode('utf-8')
+
+
+#
+# The encryption format is described here:
+# https://github.com/PrivateBin/PrivateBin/wiki/Encryption-format
+#
+def privatebin_encrypt(paste_passphrase,
+ paste_password,
+ paste_plaintext,
+ paste_formatter,
+ paste_attachment_name,
+ paste_attachment,
+ paste_compress,
+ paste_burn,
+ paste_opendicussion):
+ if paste_password:
+ paste_passphrase += bytes(paste_password, 'utf-8')
+
+ # PBKDF
+ kdf_salt = bytes(os.urandom(8))
+ kdf_iterations = 100000
+ kdf_keysize = 256 # size of resulting kdf_key
+
+ backend = default_backend()
+ kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),
+ length=int(kdf_keysize / 8), # 256bit
+ salt=kdf_salt,
+ iterations=kdf_iterations,
+ backend=backend)
+ kdf_key = kdf.derive(paste_passphrase)
+
+ # AES-GCM
+ adata_size = 128
+
+ cipher_iv = bytes(os.urandom(int(adata_size / 8)))
+ cipher_algo = "aes"
+ cipher_mode = "gcm"
+
+ compression_type = "none"
+ if paste_compress:
+ compression_type = "zlib"
+
+ # compress plaintext
+ paste_data = {'paste': paste_plaintext}
+ if paste_attachment_name and paste_attachment:
+ paste_data['attachment'] = paste_attachment
+ paste_data['attachment_name'] = paste_attachment_name
+ print(paste_attachment_name)
+ print(paste_attachment)
+
+ if paste_compress:
+ zobj = zlib.compressobj(wbits=-zlib.MAX_WBITS)
+ paste_blob = zobj.compress(json_encode(paste_data)) + zobj.flush()
+ else:
+ paste_blob = json_encode(paste_data)
+
+ # Associated data to authenticate
+ paste_adata = [
+ [
+ base64.b64encode(cipher_iv).decode("utf-8"),
+ base64.b64encode(kdf_salt).decode("utf-8"),
+ kdf_iterations,
+ kdf_keysize,
+ adata_size,
+ cipher_algo,
+ cipher_mode,
+ compression_type,
+ ],
+ paste_formatter,
+ int(paste_opendicussion),
+ int(paste_burn),
+ ]
+
+ paste_adata_json = json_encode(paste_adata)
+
+ aesgcm = AESGCM(kdf_key)
+ ciphertext = aesgcm.encrypt(cipher_iv, paste_blob, paste_adata_json)
+
+ # Validate
+ # aesgcm.decrypt(cipher_iv, ciphertext, paste_adata_json)
+
+ paste_ciphertext = base64.b64encode(ciphertext).decode("utf-8")
+
+ return paste_adata, paste_ciphertext
+
+
+def privatebin_send(paste_url,
+ paste_password,
+ paste_plaintext,
+ paste_formatter,
+ paste_attachment_name,
+ paste_attachment,
+ paste_compress,
+ paste_burn,
+ paste_opendicussion,
+ paste_expire):
+ paste_passphrase = bytes(os.urandom(32))
+
+ paste_adata, paste_ciphertext = privatebin_encrypt(paste_passphrase,
+ paste_password,
+ paste_plaintext,
+ paste_formatter,
+ paste_attachment_name,
+ paste_attachment,
+ paste_compress,
+ paste_burn,
+ paste_opendicussion)
+
+ # json payload for the post API
+ # https://github.com/PrivateBin/PrivateBin/wiki/API
+ payload = {
+ "v": 2,
+ "adata": paste_adata,
+ "ct": paste_ciphertext,
+ "meta": {
+ "expire": paste_expire,
+ }
+ }
+
+ # http content type
+ headers = {'X-Requested-With': 'JSONHttpRequest'}
+
+ r = requests.post(paste_url,
+ data=json_encode(payload),
+ headers=headers)
+ r.raise_for_status()
+
+ try:
+ result = r.json()
+ except:
+ print('Oops, error: %s' % (r.text))
+ sys.exit(1)
+
+ paste_status = result['status']
+ if paste_status:
+ paste_message = result['message']
+ print("Oops, error: %s" % paste_message)
+ sys.exit(1)
+
+ paste_id = result['id']
+ paste_url_id = result['url']
+ paste_deletetoken = result['deletetoken']
+
+ print('Delete paste: %s/?pasteid=%s&deletetoken=%s' %
+ (paste_url, paste_id, paste_deletetoken))
+ print('')
+ print('### Paste (%s): %s%s#%s' %
+ (paste_formatter,
+ paste_url,
+ paste_url_id,
+ base58_encode(paste_passphrase).decode('utf-8')))
+
+
+def guess_lang_formatter(paste_plaintext, paste_filename=None):
+ paste_formatter = 'plaintext'
+
+ # Map numpy to python because the numpy lexer gives false positives
+ # when guessing.
+ lexer_lang_map = {'numpy': 'python'}
+
+ # If we have a filename, try guessing using the more reliable
+ # guess_lexer_for_filename function.
+ # If that fails, try the guess_lexer function on the code.
+ lang = None
+ if paste_filename:
+ try:
+ lang = guess_lexer_for_filename(paste_filename,
+ paste_plaintext).name.lower()
+ except ClassNotFound:
+ print("No guess by filename")
+ pass
+ else:
+ try:
+ lang = guess_lexer(paste_plaintext).name.lower()
+ except ClassNotFound:
+ pass
+
+ if lang:
+ if lang == 'markdown':
+ paste_formatter = 'markdown'
+ if lang != 'text only':
+ paste_formatter = 'syntaxhighlighting'
+
+ return paste_formatter
+
+
+def main():
+ parser = OptionParser()
+
+ parser.add_option("-f", "--file", dest="filename",
+ help="Read from a file instead of stdin",
+ metavar="FILE")
+ parser.add_option("-p", "--password", dest="password",
+ help="Create a password protected paste",
+ metavar="PASSWORD")
+ parser.add_option("-e", "--expire",
+ action="store", dest="expire", default="1day",
+ choices=["5min",
+ "10min",
+ "1hour",
+ "1day",
+ "1week",
+ "1month",
+ "1year",
+ "never"],
+ help="Expiration time of the paste (default: 1day)")
+ parser.add_option("-s", "--sourcecode",
+ action="store_true", dest="source", default=False,
+ help="Use source code highlighting")
+ parser.add_option("-m", "--markdown",
+ action="store_true", dest="markdown", default=False,
+ help="Parse paste as markdown")
+ parser.add_option("-b", "--burn",
+ action="store_true", dest="burn", default=False,
+ help="Burn paste after reading")
+ parser.add_option("-o", "--opendiscussion",
+ action="store_true", dest="opendiscussion",
+ default=False,
+ help="Allow discussion for the paste")
+ parser.add_option("-a", "--attachment", dest="attachment",
+ help="Specify path to a file to attachment to the paste",
+ metavar="FILE")
+
+ (options, args) = parser.parse_args()
+
+ paste_url = 'https://cpaste.org'
+ paste_formatter = 'plaintext'
+ paste_compress = True
+ paste_expire = '1day'
+ paste_opendiscussion = 0
+ paste_burn = 0
+ paste_password = None
+ paste_attachment_name = None
+ paste_attachment = None
+
+ if options.filename:
+ f = open(options.filename)
+ if not f:
+ print("Oops, could not open file!")
+
+ paste_plaintext = f.read()
+ f.close()
+ else:
+ paste_plaintext = sys.stdin.read()
+
+ if not paste_plaintext:
+ print("Oops, we have no data")
+ sys.exit(1)
+
+ if options.burn:
+ paste_burn = 1
+
+ if options.opendiscussion:
+ paste_opendiscussion = 1
+
+ if options.source:
+ paste_formatter = 'syntaxhighlighting'
+ elif options.markdown:
+ paste_formatter = 'markdown'
+ elif guess_lang:
+ paste_formatter = guess_lang_formatter(paste_plaintext,
+ options.filename)
+
+ if options.expire:
+ paste_expire = options.expire
+
+ if options.password:
+ paste_password = options.password
+
+ if options.attachment:
+ paste_attachment_name = os.path.basename(options.attachment)
+ mime = guess_type(options.attachment, strict=False)[0]
+ if not mime:
+ mime = 'application/octet-stream'
+
+ f = open(options.attachment, mode='rb')
+ if not f:
+ print("Oops, could not open file for attachment!")
+
+ data = f.read()
+ f.close()
+
+ paste_attachment = 'data:%s;base64,' % (mime)
+ paste_attachment += base64.b64encode(data).decode('utf-8')
+
+ privatebin_send(paste_url,
+ paste_password,
+ paste_plaintext,
+ paste_formatter,
+ paste_attachment_name,
+ paste_attachment,
+ paste_compress,
+ paste_burn,
+ paste_opendiscussion,
+ paste_expire)
+
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
+
diff --git a/pastedb/example_post.py b/pastedb/example_post.py
new file mode 100755
index 0000000..bd8d754
--- /dev/null
+++ b/pastedb/example_post.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+
+import requests
+import json
+
+# Define your JSON object
+my_json = {'name': 'John', 'age': 30, 'city': 'New York'}
+
+# Define the API endpoints for the services you want to use
+gist_url = 'https://api.github.com/gists'
+hastebin_url = 'https://hastebin.com/documents'
+pastie_url = 'https://pastie.io/documents'
+ghostbin_url = 'https://ghostbin.com/paste/new'
+codepad_url = 'https://codepad.co/snippet_api'
+termbin_url = 'https://termbin.com/documents'
+
+# Define a function to upload the JSON object to each service
+def upload_to_service(url, data):
+ response = requests.post(url, json=data)
+ if response.status_code == 200:
+ return response.json().get('key') or response.json().get('id')
+ else:
+ return None
+
+# Upload the JSON object to each service and print the URLs
+gist_key = upload_to_service(gist_url, {'public': True, 'files': {'my_json.json': {'content': json.dumps(my_json)}}})
+if gist_key:
+ print(f'Gist URL: https://gist.github.com/{gist_key}')
+
+hastebin_key = upload_to_service(hastebin_url, json.dumps(my_json))
+if hastebin_key:
+ print(f'Hastebin URL: https://hastebin.com/{hastebin_key}.json')
+
+pastie_key = upload_to_service(pastie_url, json.dumps(my_json))
+if pastie_key:
+ print(f'Pastie URL: https://pastie.io/{pastie_key}')
+
+ghostbin_key = upload_to_service(ghostbin_url, {'text': json.dumps(my_json)})
+if ghostbin_key:
+ print(f'Ghostbin URL: https://ghostbin.com/{ghostbin_key}')
+
+codepad_key = upload_to_service(codepad_url, {'code': json.dumps(my_json)})
+if codepad_key:
+ print(f'Codepad URL: https://codepad.co/{codepad_key}.json')
+
+termbin_key = upload_to_service(termbin_url, json.dumps(my_json))
+if termbin_key:
+ print(f'Termbin URL: https://termbin.com/{termbin_key}')
+
diff --git a/pastedb/example_post_controlc.py b/pastedb/example_post_controlc.py
new file mode 100644
index 0000000..32a7e9e
--- /dev/null
+++ b/pastedb/example_post_controlc.py
@@ -0,0 +1,15 @@
+import requests
+
+url = "https://controlc.com/api.php?action=save"
+
+# Text to be pasted
+text = "Hello, world!"
+
+# Create a new paste
+response = requests.post(url, data={"c": text})
+
+# Extract the URL of the newly created paste
+paste_url = response.text
+
+print(f"Paste URL: {paste_url}")
+
diff --git a/pastedb/example_post_hastebin.py b/pastedb/example_post_hastebin.py
new file mode 100644
index 0000000..c375213
--- /dev/null
+++ b/pastedb/example_post_hastebin.py
@@ -0,0 +1,18 @@
+import requests
+import json
+
+# Define your JSON object
+my_json = {'name': 'John', 'age': 30, 'city': 'New York'}
+
+# Define the API endpoint for Hastebin
+hastebin_url = 'https://hastebin.com/documents'
+
+# Upload the JSON object to Hastebin and get the URL
+response = requests.post(hastebin_url, data=json.dumps(my_json))
+if response.status_code == 200:
+ key = response.json()['key']
+ hastebin_url = f'https://hastebin.com/{key}'
+ print(f'JSON object uploaded to Hastebin: {hastebin_url}')
+else:
+ print('Error uploading JSON object to Hastebin')
+
diff --git a/pastedb/example_post_multi_backends.py b/pastedb/example_post_multi_backends.py
new file mode 100644
index 0000000..b5e7f24
--- /dev/null
+++ b/pastedb/example_post_multi_backends.py
@@ -0,0 +1,52 @@
+import json
+import requests
+import hashlib
+import time
+import random
+
+# generate random name for upload
+def generate_name():
+ timestamp = str(int(time.time()))
+ rand = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz', k=3))
+ return timestamp + '-' + rand
+
+# define json object to upload
+data = {
+ "name": "Alice",
+ "age": 25,
+ "city": "New York"
+}
+
+# add timestamp and md5sum to the json object
+data['timestamp'] = int(time.time())
+json_str = json.dumps(data)
+hash_md5 = hashlib.md5(json_str.encode())
+data['md5sum'] = hash_md5.hexdigest()
+
+# upload to pastie
+pastie_url = 'https://www.pastie.io/documents'
+pastie_resp = requests.post(pastie_url, data=json_str.encode(), headers={'Content-Type': 'application/json'})
+pastie_key = pastie_resp.json()['key']
+pastie_name = 'pastie-' + generate_name()
+
+# store pastie info in dictionary
+paste_dict = {}
+paste_dict[pastie_name] = {'service': 'pastie', 'key': pastie_key, 'md5sum': data['md5sum']}
+
+# upload to termbin
+termbin_url = 'https://termbin.com'
+termbin_resp = requests.post(termbin_url, data=json_str.encode(), headers={'Content-Type': 'text/plain'})
+termbin_key = termbin_resp.text.strip()
+termbin_name = 'termbin-' + generate_name()
+
+# store termbin info in dictionary
+paste_dict[termbin_name] = {'service': 'termbin', 'key': termbin_key, 'md5sum': data['md5sum']}
+
+# write paste dictionary to file
+with open('paste_dict.json', 'a') as f:
+ f.write(json.dumps(paste_dict, indent=4))
+ f.write('\n')
+
+# print out paste dictionary
+print(json.dumps(paste_dict, indent=4))
+
diff --git a/pastedb/example_post_multi_handling.py b/pastedb/example_post_multi_handling.py
new file mode 100644
index 0000000..8702d83
--- /dev/null
+++ b/pastedb/example_post_multi_handling.py
@@ -0,0 +1,71 @@
+import json
+import hashlib
+import requests
+import time
+import random
+
+
+# Function to generate a unique name for the upload
+def generate_upload_name():
+ timestamp = int(time.time())
+ rand_str = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz', k=3))
+ return f"{timestamp}-{rand_str}"
+
+
+# Function to upload JSON data to termbin
+def upload_to_termbin(data):
+ try:
+ resp = requests.post('https://termbin.com', data=data.encode('utf-8'), timeout=5)
+ if resp.status_code == 200:
+ key = resp.text.strip()
+ md5sum = hashlib.md5(data.encode('utf-8')).hexdigest()
+ return {'service': 'termbin', 'key': key, 'md5sum': md5sum}
+ else:
+ print(f"Failed to upload to termbin.com. Response code: {resp.status_code}")
+ return None
+ except requests.exceptions.RequestException as e:
+ print(f"Failed to upload to termbin.com. Error: {str(e)}")
+ return None
+
+
+# Function to upload JSON data to pastie
+def upload_to_pastie(data):
+ try:
+ resp = requests.post('https://pastie.io/documents', data=data.encode('utf-8'), timeout=5)
+ if resp.status_code == 200:
+ key = resp.json()['key']
+ md5sum = hashlib.md5(data.encode('utf-8')).hexdigest()
+ return {'service': 'pastie', 'key': key, 'md5sum': md5sum}
+ else:
+ print(f"Failed to upload to pastie.io. Response code: {resp.status_code}")
+ return None
+ except requests.exceptions.RequestException as e:
+ print(f"Failed to upload to pastie.io. Error: {str(e)}")
+ return None
+
+
+# Upload data to both termbin and pastie
+def upload_data_to_services(data):
+ upload_name = generate_upload_name()
+ print(f"\nUploading data to services with name {upload_name}...\n")
+ paste_dict = {'name': upload_name}
+ services = {'termbin': upload_to_termbin, 'pastie': upload_to_pastie}
+ for service, upload_function in services.items():
+ result = upload_function(data)
+ if result is not None:
+ paste_dict[service] = result
+ print(f"JSON object uploaded to {service}: https://{service}.com/{result['key']}")
+ with open('paste_dict.json', 'a+') as f:
+ f.write(json.dumps(paste_dict) + '\n')
+ print(f"\nUploads completed successfully.")
+
+
+# Test function
+def test():
+ data = '{"name": "John Doe", "age": 30, "city": "New York"}'
+ upload_data_to_services(data)
+
+
+if __name__ == '__main__':
+ test()
+
diff --git a/pastedb/example_post_paste2org.py b/pastedb/example_post_paste2org.py
new file mode 100644
index 0000000..a0db45f
--- /dev/null
+++ b/pastedb/example_post_paste2org.py
@@ -0,0 +1,19 @@
+import requests
+
+# Set the URL of the Paste2.org API endpoint
+url = 'https://paste2.org/'
+
+# Get the input from the user
+text = 'Enter text to upload'
+
+# Send the HTTP POST request to the Paste2.org API with the text as the request body
+response = requests.post(url, data=text.encode('utf-8'))
+
+# Get the URL of the uploaded text from the response JSON
+if response.status_code == 200:
+ paste_id = response.json().get('id')
+ paste_url = f'https://paste2.org/{paste_id}'
+ print('Uploaded to:', paste_url)
+else:
+ print('Error uploading text:', response.text)
+
diff --git a/pastedb/example_post_pastie.py b/pastedb/example_post_pastie.py
new file mode 100644
index 0000000..2246305
--- /dev/null
+++ b/pastedb/example_post_pastie.py
@@ -0,0 +1,46 @@
+import requests
+import json
+import os
+import time
+import hashlib
+
+# Define your JSON object with a unique timestamp and MD5 hash
+my_json = {'timestamp': int(time.time()), 'name': 'John', 'age': 30, 'city': 'New York'}
+json_str = json.dumps(my_json, sort_keys=True)
+md5_hash = hashlib.md5(json_str.encode()).hexdigest()
+my_json['md5'] = md5_hash
+
+# Define the API endpoint for Pastie
+pastie_url = 'https://pastie.io/documents'
+
+# Upload the JSON object to Pastie and get the URL
+response = requests.post(pastie_url, data=json.dumps(my_json))
+if response.status_code == 200:
+ key = response.json()['key']
+ pastie_url = f'https://pastie.io/{key}'
+ print(f'JSON object uploaded to Pastie: {pastie_url}')
+
+ # Add the URL and service name to the dictionary for later querying
+ paste_dict = {}
+ if os.path.isfile('paste_dict.json'):
+ with open('paste_dict.json', 'r') as f:
+ paste_dict = json.load(f)
+ paste_dict[key] = {'url': pastie_url, 'service': 'Pastie'}
+
+ # Write the URL dictionary to a file on disk
+ with open('paste_dict.json', 'w') as f:
+ json.dump(paste_dict, f, indent=4)
+else:
+ print('Error uploading JSON object to Pastie')
+
+# Query the dictionary for the URL of a specific paste
+if os.path.isfile('paste_dict.json'):
+ with open('paste_dict.json', 'r') as f:
+ paste_dict = json.load(f)
+ key_to_query = key if key in paste_dict else list(paste_dict.keys())[0]
+ url = paste_dict[key_to_query]['url']
+ service = paste_dict[key_to_query]['service']
+ print(f'URL for paste with key {key_to_query} (stored on {service}): {url}')
+else:
+ print('URL dictionary file not found')
+
diff --git a/pastedb/example_post_snippet.py b/pastedb/example_post_snippet.py
new file mode 100644
index 0000000..8c862ba
--- /dev/null
+++ b/pastedb/example_post_snippet.py
@@ -0,0 +1,18 @@
+import requests
+
+url = "https://snippet.host/api/documents"
+
+# Text to be pasted
+text = "Hello, world!"
+
+# Create a new paste
+response = requests.post(url, data=text)
+
+if response.status_code == 200:
+ # Extract the URL of the newly created paste
+ paste_url = f"https://snippet.host/{response.json()['key']}"
+ print(f"Paste URL: {paste_url}")
+else:
+ # If the response code is not 200, print the response body for debugging
+ print(f"Error: {response.text}")
+
diff --git a/pastedb/example_post_sprunge.py b/pastedb/example_post_sprunge.py
new file mode 100644
index 0000000..fcc8fe7
--- /dev/null
+++ b/pastedb/example_post_sprunge.py
@@ -0,0 +1,39 @@
+import requests
+import json
+import hashlib
+
+url = 'http://sprunge.us'
+
+def upload(data):
+ try:
+ json_data = json.dumps(data)
+ md5sum = hashlib.md5(json_data.encode('utf-8')).hexdigest()
+
+ # Send the HTTP POST request to the Sprunge API
+ response = requests.post(url, data={'sprunge': json_data})
+ if response.status_code == 200:
+
+ # Get the URL of the uploaded text from the response body
+ sprunge_url = response.text.strip()
+
+ print('Uploaded to:', sprunge_url)
+
+ # Use a regular expression to extract the random ID from the URL
+ match = re.match(r'^http://sprunge\.us/(\w+)$', sprunge_url)
+ if match:
+ random_id = match.group(1)
+ print('Random ID:', random_id)
+ key = "sprunge_" + random_id + '_' + md5sum[:5]
+ else:
+ print('Invalid Sprunge URL:', sprunge_url)
+
+ return {
+ "service": "sprunge",
+ "name": key,
+ "key": sprunge_url,
+ "md5sum": md5sum
+ }
+ else:
+ return None
+ except requests.exceptions.RequestException:
+ return None
diff --git a/pastedb/example_post_zerobin.py b/pastedb/example_post_zerobin.py
new file mode 100644
index 0000000..15b4b69
--- /dev/null
+++ b/pastedb/example_post_zerobin.py
@@ -0,0 +1,5 @@
+import requests
+
+data = {"data": 'print("Hello!")'}
+r = requests.post("https://zerobin.net/?paste", data=data)
+print(f"URL: {r.text}")
diff --git a/pastedb/lodgeit.py b/pastedb/lodgeit.py
new file mode 100755
index 0000000..6a406d2
--- /dev/null
+++ b/pastedb/lodgeit.py
@@ -0,0 +1,331 @@
+#!/usr/bin/env python
+"""
+ LodgeIt!
+ ~~~~~~~~
+
+ A script that pastes stuff into the lodgeit pastebin.
+
+ .lodgeitrc / _lodgeitrc
+ -----------------------
+
+ Under UNIX create a file called ``~/.lodgeitrc``, under Windows
+ create a file ``%APPDATA%/_lodgeitrc`` to override defaults::
+
+ language=default_language
+ clipboard=true/false
+ open_browser=true/false
+ encoding=fallback_charset
+
+ :authors: 2007-2010 Georg Brandl ,
+ 2006 Armin Ronacher ,
+ 2006 Matt Good ,
+ 2005 Raphael Slinckx
+"""
+from __future__ import print_function
+import os
+import sys
+from six import text_type
+from optparse import OptionParser
+
+
+SCRIPT_NAME = os.path.basename(sys.argv[0])
+VERSION = '0.3'
+SETTING_KEYS = ['author', 'title', 'language', 'private', 'clipboard',
+ 'open_browser']
+
+# global server proxy
+_xmlrpc_service = None
+_server_name = None
+
+
+def fail(msg, code):
+ """Bail out with an error message."""
+ print('ERROR: %s' % msg, file=sys.stderr)
+ sys.exit(code)
+
+
+def load_default_settings():
+ """Load the defaults from the lodgeitrc file."""
+ settings = {
+ 'language': None,
+ 'clipboard': True,
+ 'open_browser': False,
+ 'encoding': 'iso-8859-15',
+ 'server_name': 'http://paste.openstack.org',
+ }
+ rcfile = None
+ if os.name == 'posix':
+ rcfile = os.path.expanduser('~/.lodgeitrc')
+ elif os.name == 'nt' and 'APPDATA' in os.environ:
+ rcfile = os.path.expandvars(r'$APPDATA\_lodgeitrc')
+ if rcfile:
+ try:
+ f = open(rcfile)
+ for line in f:
+ if line.strip()[:1] in '#;':
+ continue
+ p = line.split('=', 1)
+ if len(p) == 2:
+ key = p[0].strip().lower()
+ if key in settings:
+ if key in ('clipboard', 'open_browser'):
+ settings[key] = p[1].strip().lower() in \
+ ('true', '1', 'on', 'yes')
+ else:
+ settings[key] = p[1].strip()
+ f.close()
+ except IOError:
+ pass
+ settings['tags'] = []
+ settings['title'] = None
+ return settings
+
+
+def make_utf8(text, encoding):
+ """Convert a text to UTF-8, brute-force."""
+ try:
+ u = text_type(text, 'utf-8')
+ uenc = 'utf-8'
+ except UnicodeError:
+ try:
+ u = text_type(text, encoding)
+ uenc = 'utf-8'
+ except UnicodeError:
+ u = text_type(text, 'iso-8859-15', 'ignore')
+ uenc = 'iso-8859-15'
+ try:
+ import chardet
+ except ImportError:
+ return u.encode('utf-8')
+ d = chardet.detect(text)
+ if d['encoding'] == uenc:
+ return u.encode('utf-8')
+ return text_type(text, d['encoding'], 'ignore').encode('utf-8')
+
+
+def get_xmlrpc_service():
+ """Create the XMLRPC server proxy and cache it."""
+ global _xmlrpc_service
+ import xmlrpclib
+ if _xmlrpc_service is None:
+ try:
+ _xmlrpc_service = xmlrpclib.ServerProxy(_server_name + 'xmlrpc/',
+ allow_none=True)
+ except Exception as err:
+ fail('Could not connect to Pastebin: %s' % err, -1)
+ return _xmlrpc_service
+
+
+def copy_url(url):
+ """Copy the url into the clipboard."""
+ # try windows first
+ try:
+ import win32clipboard
+ except ImportError:
+ # then give pbcopy a try. do that before gtk because
+ # gtk might be installed on os x but nobody is interested
+ # in the X11 clipboard there.
+ from subprocess import Popen, PIPE
+ for prog in 'pbcopy', 'xclip':
+ try:
+ client = Popen([prog], stdin=PIPE)
+ except OSError:
+ continue
+ else:
+ client.stdin.write(url)
+ client.stdin.close()
+ client.wait()
+ break
+ else:
+ try:
+ import pygtk
+ pygtk.require('2.0')
+ import gtk
+ import gobject
+ except ImportError:
+ return
+ gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD).set_text(url)
+ gobject.idle_add(gtk.main_quit)
+ gtk.main()
+ else:
+ win32clipboard.OpenClipboard()
+ win32clipboard.EmptyClipboard()
+ win32clipboard.SetClipboardText(url)
+ win32clipboard.CloseClipboard()
+
+
+def open_webbrowser(url):
+ """Open a new browser window."""
+ import webbrowser
+ webbrowser.open(url)
+
+
+def language_exists(language):
+ """Check if a language alias exists."""
+ xmlrpc = get_xmlrpc_service()
+ langs = xmlrpc.pastes.getLanguages()
+ return language in langs
+
+
+def get_mimetype(data, filename):
+ """Try to get MIME type from data."""
+ try:
+ import gnomevfs
+ except ImportError:
+ from mimetypes import guess_type
+ if filename:
+ return guess_type(filename)[0]
+ else:
+ if filename:
+ return gnomevfs.get_mime_type(os.path.abspath(filename))
+ return gnomevfs.get_mime_type_for_data(data)
+
+
+def print_languages():
+ """Print a list of all supported languages, with description."""
+ xmlrpc = get_xmlrpc_service()
+ languages = xmlrpc.pastes.getLanguages().items()
+ languages.sort(key=lambda a: a[1].lower())
+ print('Supported Languages:')
+ for alias, name in languages:
+ print(' %-30s%s' % (alias, name))
+
+
+def download_paste(uid):
+ """Download a paste given by ID."""
+ xmlrpc = get_xmlrpc_service()
+ paste = xmlrpc.pastes.getPaste(uid)
+ if not paste:
+ fail('Paste "%s" does not exist.' % uid, 5)
+ print(paste['code'].encode('utf-8'))
+
+
+def create_paste(code, language, filename, mimetype, private):
+ """Create a new paste."""
+ xmlrpc = get_xmlrpc_service()
+ rv = xmlrpc.pastes.newPaste(language, code, None, filename, mimetype,
+ private)
+ if not rv:
+ fail('Could not create paste. Something went wrong '
+ 'on the server side.', 4)
+ return rv
+
+
+def compile_paste(filenames, langopt):
+ """Create a single paste out of zero, one or multiple files."""
+ def read_file(f):
+ try:
+ return f.read()
+ finally:
+ f.close()
+ mime = ''
+ lang = langopt or ''
+ if not filenames:
+ data = read_file(sys.stdin)
+ print('Pasting...')
+ if not langopt:
+ mime = get_mimetype(data, '') or ''
+ fname = ''
+ elif len(filenames) == 1:
+ fname = filenames[0]
+ data = read_file(open(filenames[0], 'rb'))
+ if not langopt:
+ mime = get_mimetype(data, filenames[0]) or ''
+ else:
+ result = []
+ for fname in filenames:
+ data = read_file(open(fname, 'rb'))
+ if langopt:
+ result.append('### %s [%s]\n\n' % (fname, langopt))
+ else:
+ result.append('### %s\n\n' % fname)
+ result.append(data)
+ result.append('\n\n')
+ data = ''.join(result)
+ lang = 'multi'
+ fname = ''
+ return data, lang, fname, mime
+
+
+def main():
+ """Main script entry point."""
+ global _server_name
+
+ usage = ('Usage: %%prog [options] [FILE ...]\n\n'
+ 'Read the files and paste their contents to LodgeIt pastebin.\n'
+ 'If no file is given, read from standard input.\n'
+ 'If multiple files are given, they are put into a single paste.')
+ parser = OptionParser(usage=usage)
+
+ settings = load_default_settings()
+
+ parser.add_option('-v', '--version', action='store_true',
+ help='Print script version')
+ parser.add_option('-L', '--languages', action='store_true', default=False,
+ help='Retrieve a list of supported languages')
+ parser.add_option('-l', '--language', default=settings['language'],
+ help='Used syntax highlighter for the file')
+ parser.add_option('-e', '--encoding', default=settings['encoding'],
+ help='Specify the encoding of a file (default is '
+ 'utf-8 or guessing if available)')
+ parser.add_option('-b', '--open-browser', dest='open_browser',
+ action='store_true',
+ default=settings['open_browser'],
+ help='Open the paste in a web browser')
+ parser.add_option('-p', '--private', action='store_true', default=False,
+ help='Paste as private')
+ parser.add_option('--no-clipboard', dest='clipboard',
+ action='store_false',
+ default=settings['clipboard'],
+ help="Don't copy the url into the clipboard")
+ parser.add_option('--download', metavar='UID',
+ help='Download a given paste')
+ parser.add_option('-s', '--server', default=settings['server_name'],
+ dest='server_name',
+ help="Specify the pastebin to send data")
+ opts, args = parser.parse_args()
+
+ # The global available server name
+ _server_name = opts.server_name
+ if not _server_name.endswith('/'):
+ _server_name += '/'
+
+ # special modes of operation:
+ # - paste script version
+ if opts.version:
+ print('%s: version %s' % (SCRIPT_NAME, VERSION))
+ sys.exit()
+ # - print list of languages
+ elif opts.languages:
+ print_languages()
+ sys.exit()
+ # - download Paste
+ elif opts.download:
+ download_paste(opts.download)
+ sys.exit()
+
+ # check language if given
+ if opts.language and not language_exists(opts.language):
+ fail('Language %s is not supported.' % opts.language, 3)
+
+ # load file(s)
+ try:
+ data, language, filename, mimetype = compile_paste(args, opts.language)
+ except Exception as err:
+ fail('Error while reading the file(s): %s' % err, 2)
+ if not data:
+ fail('Aborted, no content to paste.', 4)
+
+ # create paste
+ code = make_utf8(data, opts.encoding)
+ pid = create_paste(code, language, filename, mimetype, opts.private)
+ url = '%sshow/%s/' % (_server_name, pid)
+ print(url)
+ if opts.open_browser:
+ open_webbrowser(url)
+ if opts.clipboard:
+ copy_url(url)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/pastedb/lodgeit_python3.py b/pastedb/lodgeit_python3.py
new file mode 100755
index 0000000..304ec70
--- /dev/null
+++ b/pastedb/lodgeit_python3.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+"""
+ LodgeIt!
+ ~~~~~~~~
+
+ A script that pastes stuff into the lodgeit pastebin.
+"""
+import os
+import sys
+import argparse
+import urllib.parse
+import urllib.request
+
+VERSION = '0.3'
+SERVER_NAME = 'http://paste.openstack.org/'
+
+def upload_paste(paste_content, title=None, language=None, private=None):
+ """
+ Uploads a paste to LodgeIt!
+
+ :param paste_content: the content of the paste to upload
+ :param title: the title of the paste (optional)
+ :param language: the language of the paste (optional)
+ :param private: whether the paste should be private (optional)
+ :return: the URL of the uploaded paste
+ """
+ # build the POST data
+ data = {
+ 'content': paste_content.encode('utf-8'),
+ 'format': 'text',
+ }
+ if title is not None:
+ data['name'] = title
+ if language is not None:
+ data['language'] = language
+ if private is not None:
+ data['private'] = private
+
+ # make the request
+ url = urllib.parse.urljoin(SERVER_NAME, '/pastes')
+ request = urllib.request.Request(url, data=urllib.parse.urlencode(data).encode('utf-8'))
+ response = urllib.request.urlopen(request)
+
+ # parse the response and return the URL of the new paste
+ location = response.getheader('Location')
+ if location is None:
+ raise ValueError('Could not find the URL of the new paste')
+ return location
+
+def main():
+ # parse the command-line arguments
+ parser = argparse.ArgumentParser(description='Upload a paste to LodgeIt!')
+ parser.add_argument('filename', help='the name of the file to upload')
+ parser.add_argument('--title', help='the title of the paste')
+ parser.add_argument('--language', help='the language of the paste')
+ parser.add_argument('--private', action='store_true', help='make the paste private')
+ args = parser.parse_args()
+
+ # read the content of the file to upload
+ with open(args.filename, 'r') as f:
+ paste_content = f.read()
+
+ # upload the paste and print the URL of the new paste
+ url = upload_paste(paste_content, args.title, args.language, args.private)
+ print(url)
+
+if __name__ == '__main__':
+ main()
+
diff --git a/pastedb/opendev.py b/pastedb/opendev.py
new file mode 100755
index 0000000..d33c52c
--- /dev/null
+++ b/pastedb/opendev.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+import sys
+import requests
+
+url = 'https://paste.opendev.org/json/'
+
+# read input from stdin
+input_str = sys.stdin.read()
+
+# create data for new paste
+data = {
+ 'language': '',
+ 'code': input_str,
+ 'private': False
+}
+
+# send request to create new paste
+response = requests.post(url + '?method=pastes.newPaste', data=data)
+
+# extract URL of newly created paste from response
+paste_id = response.text.strip()
+paste_url = f'https://paste.opendev.org/show/{paste_id}'
+
+# print URL of newly created paste
+print(paste_url)
+
diff --git a/pastedb/opendev_2nd.py b/pastedb/opendev_2nd.py
new file mode 100755
index 0000000..4dc376b
--- /dev/null
+++ b/pastedb/opendev_2nd.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+
+import requests
+import json
+import hashlib
+
+url = 'https://paste.opendev.org/json/'
+
+# read input from stdin
+data = '{ "name": "joe", "age": 55}'
+
+def upload(data):
+ try:
+ content = json.dumps(data)
+
+ # create JSON payload for new paste
+ payload = {
+ 'language': 'text',
+ 'code': content,
+ 'private': False
+ #'expire': '1day'
+ }
+
+ # send request to create new paste
+ response = requests.post(url + '?method=pastes.newPaste', json=payload)
+
+ status = response.status_code
+ paste_id = response.json()['data']
+
+ if status == 200:
+ #print(f'JSON object uploaded to dpaste.com: {dpaste_url}')
+ md5sum = hashlib.md5(content.encode('utf-8')).hexdigest()
+
+ return {
+ 'service': 'url',
+ 'key': paste_id,
+ 'md5sum': md5sum,
+ 'name': 'opendev_' + paste_id + '_' + md5sum[:5]
+ }
+ else:
+ return None
+ except requests.exceptions.RequestException:
+ return None
+# we can get the paste back by:
+## $ > curl -d '{"paste_id":819463}' -H 'Content-Type: application/json' https://paste.opendev.org/json/?method=pastes.getPaste |jq .data.code
diff --git a/pastedb/paste_dict.json b/pastedb/paste_dict.json
new file mode 100644
index 0000000..ca93a08
--- /dev/null
+++ b/pastedb/paste_dict.json
@@ -0,0 +1,12 @@
+{
+ "name": "1680462198-dxx",
+ "pastie": {
+ "service": "pastie",
+ "key": "jpllic",
+ "md5sum": "5e87ba1e0d151a399c0418343842b94d"
+ },
+ "ogqfsh": {
+ "url": "https://pastie.io/ogqfsh",
+ "service": "Pastie"
+ }
+}
\ No newline at end of file
diff --git a/pastedb/pastedb01/data.json b/pastedb/pastedb01/data.json
new file mode 100644
index 0000000..c39e9ba
--- /dev/null
+++ b/pastedb/pastedb01/data.json
@@ -0,0 +1 @@
+{"name": "Joe Chuck", "age": 222, "city": "New Jersey"}
diff --git a/pastedb/pastedb01/external/pastebinit_1.5.1-1_all.deb b/pastedb/pastedb01/external/pastebinit_1.5.1-1_all.deb
new file mode 100644
index 0000000..0093e78
Binary files /dev/null and b/pastedb/pastedb01/external/pastebinit_1.5.1-1_all.deb differ
diff --git a/pastedb/pastedb01/external/rentry b/pastedb/pastedb01/external/rentry
new file mode 100755
index 0000000..3169b91
--- /dev/null
+++ b/pastedb/pastedb01/external/rentry
@@ -0,0 +1,161 @@
+#!/usr/bin/env python3
+
+import getopt
+import http.cookiejar
+import sys
+import urllib.parse
+import urllib.request
+from http.cookies import SimpleCookie
+from json import loads as json_loads
+from os import environ
+
+_headers = {"Referer": 'https://rentry.co'}
+
+
+class UrllibClient:
+ """Simple HTTP Session Client, keeps cookies."""
+
+ def __init__(self):
+ self.cookie_jar = http.cookiejar.CookieJar()
+ self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar))
+ urllib.request.install_opener(self.opener)
+
+ def get(self, url, headers={}):
+ request = urllib.request.Request(url, headers=headers)
+ return self._request(request)
+
+ def post(self, url, data=None, headers={}):
+ postdata = urllib.parse.urlencode(data).encode()
+ request = urllib.request.Request(url, postdata, headers)
+ return self._request(request)
+
+ def _request(self, request):
+ response = self.opener.open(request)
+ response.status_code = response.getcode()
+ response.data = response.read().decode('utf-8')
+ return response
+
+
+def raw(url):
+ client = UrllibClient()
+ return json_loads(client.get('https://rentry.co/api/raw/{}'.format(url)).data)
+
+
+def new(url, edit_code, text):
+ client, cookie = UrllibClient(), SimpleCookie()
+
+ cookie.load(vars(client.get('https://rentry.co'))['headers']['Set-Cookie'])
+ csrftoken = cookie['csrftoken'].value
+
+ payload = {
+ 'csrfmiddlewaretoken': csrftoken,
+ 'url': url,
+ 'edit_code': edit_code,
+ 'text': text
+ }
+
+ return json_loads(client.post('https://rentry.co/api/new', payload, headers=_headers).data)
+
+
+def edit(url, edit_code, text):
+ client, cookie = UrllibClient(), SimpleCookie()
+
+ cookie.load(vars(client.get('https://rentry.co'))['headers']['Set-Cookie'])
+ csrftoken = cookie['csrftoken'].value
+
+ payload = {
+ 'csrfmiddlewaretoken': csrftoken,
+ 'edit_code': edit_code,
+ 'text': text
+ }
+
+ return json_loads(client.post('https://rentry.co/api/edit/{}'.format(url), payload, headers=_headers).data)
+
+
+def usage():
+ print('''
+Usage: rentry {new | edit | raw} {-h | --help} {-u | --url} {-p | --edit-code} text
+
+Commands:
+ new create a new entry
+ edit edit an existing entry
+ raw get raw markdown text of an existing entry
+
+Options:
+ -h, --help show this help message and exit
+ -u, --url URL url for the entry, random if not specified
+ -p, --edit-code EDIT-CODE edit code for the entry, random if not specified
+
+Examples:
+ rentry new 'markdown text' # new entry with random url and edit code
+ rentry new -p pw -u example 'text' # with custom edit code and url
+ rentry edit -p pw -u example 'text' # edit the example entry
+ cat FILE | rentry new # read from FILE and paste it to rentry
+ cat FILE | rentry edit -p pw -u example # read from FILE and edit the example entry
+ rentry raw -u example # get raw markdown text
+ rentry raw -u https://rentry.co/example # -u accepts absolute and relative urls
+ ''')
+
+
+if __name__ == '__main__':
+ try:
+ environ.pop('POSIXLY_CORRECT', None)
+ opts, args = getopt.gnu_getopt(sys.argv[1:], "hu:p:", ["help", "url=", "edit-code="])
+ except getopt.GetoptError as e:
+ sys.exit("error: {}".format(e))
+
+ command, url, edit_code, text = None, '', '', None
+
+ for o, a in opts:
+ if o in ("-h", "--help"):
+ usage()
+ sys.exit()
+ elif o in ("-u", "--url"):
+ url = urllib.parse.urlparse(a).path.strip('/')
+ elif o in ("-p", "--edit-code"):
+ edit_code = a
+
+ command = (args[0:1] or [None])[0]
+ command or sys.exit(usage())
+ command in ['new', 'edit', 'raw'] or sys.exit('error: command must be new, edit or raw')
+
+ text = (args[1:2] or [None])[0]
+ if not text and command != 'raw':
+ text = sys.stdin.read().strip()
+ text or sys.exit('error: text is required')
+
+ if command == 'new':
+ response = new(url, edit_code, text)
+ if response['status'] != '200':
+ print('error: {}'.format(response['content']))
+ try:
+ for i in response['errors'].split('.'):
+ i and print(i)
+ sys.exit(1)
+ except:
+ sys.exit(1)
+ else:
+ print('Url: {}\nEdit code: {}'.format(response['url'], response['edit_code']))
+
+ elif command == 'edit':
+ url or sys.exit('error: url is required')
+ edit_code or sys.exit('error: edit code is required')
+
+ response = edit(url, edit_code, text)
+ if response['status'] != '200':
+ print('error: {}'.format(response['content']))
+ try:
+ for i in response['errors'].split('.'):
+ i and print(i)
+ sys.exit(1)
+ except:
+ sys.exit(1)
+ else:
+ print('Ok')
+
+ elif command == 'raw':
+ url or sys.exit('error: url is required')
+ response = raw(url)
+ if response['status'] != '200':
+ sys.exit('error: {}'.format(response['content']))
+ print(response['content'])
diff --git a/pastedb/pastedb01/paste_dict.json b/pastedb/pastedb01/paste_dict.json
new file mode 100644
index 0000000..b3ef4db
--- /dev/null
+++ b/pastedb/pastedb01/paste_dict.json
@@ -0,0 +1,34 @@
+
+{
+ "name": "1680551932-b74d72",
+ "pastie_blzoeg": {
+ "service": "pastie",
+ "key": "https://pastie.io/blzoeg",
+ "md5sum": "9fd3002da661e6ca38a2e8a49daafb1b"
+ },
+ "rentry_QDmcP3gr": {
+ "service": "Rentry",
+ "key": "https://rentry.co/hqcohp",
+ "md5sum": "9fd3002da661e6ca38a2e8a49daafb1b"
+ },
+ "dpaste_9W5AB4Y2V": {
+ "service": "dpaste",
+ "key": "https://dpaste.com/9W5AB4Y2V",
+ "md5sum": "9fd3002da661e6ca38a2e8a49daafb1b"
+ },
+ "sprunge_j9uXbd_9fd30": {
+ "service": "sprunge",
+ "key": "http://sprunge.us/j9uXbd",
+ "md5sum": "9fd3002da661e6ca38a2e8a49daafb1b"
+ },
+ "defau_9fd30": {
+ "service": "p.defau.lt",
+ "key": "https://p.defau.lt/?ExQfLnJ_aDEKYIqkpwv6cQ",
+ "md5sum": "9fd3002da661e6ca38a2e8a49daafb1b"
+ },
+ "opendev_819477_9fd30": {
+ "service": "opendev",
+ "key": "https://paste.opendev.org/json/",
+ "md5sum": "9fd3002da661e6ca38a2e8a49daafb1b"
+ }
+}
\ No newline at end of file
diff --git a/pastedb/pastedb01/services/__init__.py b/pastedb/pastedb01/services/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/pastedb/pastedb01/services/__pycache__/__init__.cpython-310.pyc b/pastedb/pastedb01/services/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000..48b7e1a
Binary files /dev/null and b/pastedb/pastedb01/services/__pycache__/__init__.cpython-310.pyc differ
diff --git a/pastedb/pastedb01/services/__pycache__/defau.cpython-310.pyc b/pastedb/pastedb01/services/__pycache__/defau.cpython-310.pyc
new file mode 100644
index 0000000..25380ef
Binary files /dev/null and b/pastedb/pastedb01/services/__pycache__/defau.cpython-310.pyc differ
diff --git a/pastedb/pastedb01/services/__pycache__/dpaste.cpython-310.pyc b/pastedb/pastedb01/services/__pycache__/dpaste.cpython-310.pyc
new file mode 100644
index 0000000..f6c8bb6
Binary files /dev/null and b/pastedb/pastedb01/services/__pycache__/dpaste.cpython-310.pyc differ
diff --git a/pastedb/pastedb01/services/__pycache__/opendev.cpython-310.pyc b/pastedb/pastedb01/services/__pycache__/opendev.cpython-310.pyc
new file mode 100644
index 0000000..58a30fa
Binary files /dev/null and b/pastedb/pastedb01/services/__pycache__/opendev.cpython-310.pyc differ
diff --git a/pastedb/pastedb01/services/__pycache__/paste2.cpython-310.pyc b/pastedb/pastedb01/services/__pycache__/paste2.cpython-310.pyc
new file mode 100644
index 0000000..9d47d71
Binary files /dev/null and b/pastedb/pastedb01/services/__pycache__/paste2.cpython-310.pyc differ
diff --git a/pastedb/pastedb01/services/__pycache__/pastie.cpython-310.pyc b/pastedb/pastedb01/services/__pycache__/pastie.cpython-310.pyc
new file mode 100644
index 0000000..2db3226
Binary files /dev/null and b/pastedb/pastedb01/services/__pycache__/pastie.cpython-310.pyc differ
diff --git a/pastedb/pastedb01/services/__pycache__/rentry.cpython-310.pyc b/pastedb/pastedb01/services/__pycache__/rentry.cpython-310.pyc
new file mode 100644
index 0000000..b976736
Binary files /dev/null and b/pastedb/pastedb01/services/__pycache__/rentry.cpython-310.pyc differ
diff --git a/pastedb/pastedb01/services/__pycache__/rentry_upload.cpython-310.pyc b/pastedb/pastedb01/services/__pycache__/rentry_upload.cpython-310.pyc
new file mode 100644
index 0000000..2195976
Binary files /dev/null and b/pastedb/pastedb01/services/__pycache__/rentry_upload.cpython-310.pyc differ
diff --git a/pastedb/pastedb01/services/__pycache__/sprunge.cpython-310.pyc b/pastedb/pastedb01/services/__pycache__/sprunge.cpython-310.pyc
new file mode 100644
index 0000000..44caa46
Binary files /dev/null and b/pastedb/pastedb01/services/__pycache__/sprunge.cpython-310.pyc differ
diff --git a/pastedb/pastedb01/services/__pycache__/termbin.cpython-310.pyc b/pastedb/pastedb01/services/__pycache__/termbin.cpython-310.pyc
new file mode 100644
index 0000000..9ff5460
Binary files /dev/null and b/pastedb/pastedb01/services/__pycache__/termbin.cpython-310.pyc differ
diff --git a/pastedb/pastedb01/services/defau.py b/pastedb/pastedb01/services/defau.py
new file mode 100644
index 0000000..fead69e
--- /dev/null
+++ b/pastedb/pastedb01/services/defau.py
@@ -0,0 +1,26 @@
+import requests
+import json
+import hashlib
+
+def serviceTag():
+ return 'p.defau.lt'
+
+def upload(data):
+ json_data = json.dumps(data)
+ md5sum = hashlib.md5(json_data.encode('utf-8')).hexdigest()
+
+ url = 'https://p.defau.lt/submit.php'
+ response = requests.post(url, data={'code': json_data})
+
+ if response.status_code == 200:
+ key = response.url
+ name = 'defau_' + md5sum[:5]
+ return {'name': name, 'service': 'p.defau.lt', 'key': key, 'md5sum': md5sum}
+ else:
+ return None
+
+def get(trace):
+ url = trace[key]
+ response = requests.request.get(url)
+ return response.content
+
diff --git a/pastedb/pastedb01/services/dpaste.py b/pastedb/pastedb01/services/dpaste.py
new file mode 100644
index 0000000..53cba79
--- /dev/null
+++ b/pastedb/pastedb01/services/dpaste.py
@@ -0,0 +1,32 @@
+import hashlib
+import json
+import requests
+
+def upload(data):
+ try:
+ content = json.dumps(data)
+ syntax = 'json'
+ expiry_days = ''
+
+ r = requests.post('https://dpaste.com/api/v2/',
+ data={'content': content,
+ 'syntax': syntax,
+ 'expiry_days': expiry_days},
+ headers={'User-Agent': 'My Python Project'})
+
+ if r.status_code == 201:
+ dpaste_url = r.headers['Location']
+ #print(f'JSON object uploaded to dpaste.com: {dpaste_url}')
+ md5sum = hashlib.md5(content.encode('utf-8')).hexdigest()
+
+ return {
+ 'service': 'dpaste',
+ 'key': dpaste_url,
+ 'md5sum': md5sum,
+ 'name': 'dpaste_' + dpaste_url.rsplit('/', 1)[-1]
+ }
+ else:
+ return None
+ except requests.exceptions.RequestException:
+ return None
+
diff --git a/pastedb/pastedb01/services/old_rentry.py b/pastedb/pastedb01/services/old_rentry.py
new file mode 100644
index 0000000..78004f9
--- /dev/null
+++ b/pastedb/pastedb01/services/old_rentry.py
@@ -0,0 +1,70 @@
+import json
+import hashlib
+import http.cookiejar
+import urllib.parse
+import urllib.request
+from http.cookies import SimpleCookie
+
+_headers = {
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
+
+class UrllibClient:
+ """Simple HTTP Session Client, keeps cookies."""
+
+ def __init__(self):
+ self.cookie_jar = http.cookiejar.CookieJar()
+ self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar))
+ urllib.request.install_opener(self.opener)
+
+ def get(self, url, headers={}):
+ request = urllib.request.Request(url, headers=headers)
+ return self._request(request)
+
+ def post(self, url, data=None, headers={}):
+ postdata = urllib.parse.urlencode(data).encode()
+ request = urllib.request.Request(url, postdata, headers)
+ return self._request(request)
+
+ def _request(self, request):
+ response = self.opener.open(request)
+ response.status_code = response.getcode()
+ response.data = response.read().decode('utf-8')
+ return response
+
+
+def json_loads(string):
+ try:
+ return json.loads(string)
+ except:
+ return None
+
+
+def upload(data):
+ client, cookie = UrllibClient(), SimpleCookie()
+
+ cookie.load(vars(client.get('https://rentry.co'))['headers']['Set-Cookie'])
+ csrftoken = cookie['csrftoken'].value
+
+ json_data = json.dumps(data)
+ md5sum = hashlib.md5(json_data.encode('utf-8')).hexdigest()
+
+ payload = {
+ 'csrfmiddlewaretoken': csrftoken,
+ 'url': md5sum,
+ 'edit_code': '',
+ 'text': json_data
+ }
+
+ response = client.post('https://rentry.co/api/new', payload, headers=_headers)
+
+ if response.status_code == 200:
+ json_response = json_loads(response.data)
+ return {
+ "service": "rentry",
+ "name": json_response["slug"],
+ "key": f"https://rentry.co/{json_response['slug']}",
+ "md5sum": md5sum
+ }
+ else:
+ return None
+
diff --git a/pastedb/pastedb01/services/opendev.py b/pastedb/pastedb01/services/opendev.py
new file mode 100755
index 0000000..7a2d6c9
--- /dev/null
+++ b/pastedb/pastedb01/services/opendev.py
@@ -0,0 +1,40 @@
+import requests
+import json
+import hashlib
+
+url = 'https://paste.opendev.org/json/'
+
+def upload(data):
+ try:
+ content = json.dumps(data)
+
+ # create JSON payload for new paste
+ payload = {
+ 'language': 'text',
+ 'code': content,
+ 'private': False
+ #'expire': '1day'
+ }
+
+ # send request to create new paste
+ response = requests.post(url + '?method=pastes.newPaste', json=payload)
+
+ status = response.status_code
+ paste_id = response.json()['data']
+
+ if status == 200:
+ #print(f'JSON object uploaded to dpaste.com: {dpaste_url}')
+ md5sum = hashlib.md5(content.encode('utf-8')).hexdigest()
+
+ return {
+ 'service': "opendev",
+ 'key': url,
+ 'md5sum': md5sum,
+ 'name': 'opendev_' + paste_id + '_' + md5sum[:5]
+ }
+ else:
+ return None
+ except requests.exceptions.RequestException:
+ return None
+# we can get the paste back by:
+## $ > curl -d '{"paste_id":819463}' -H 'Content-Type: application/json' https://paste.opendev.org/json/?method=pastes.getPaste |jq .data.code
diff --git a/pastedb/pastedb01/services/paste2.py b/pastedb/pastedb01/services/paste2.py
new file mode 100644
index 0000000..f5d295e
--- /dev/null
+++ b/pastedb/pastedb01/services/paste2.py
@@ -0,0 +1,20 @@
+import requests
+
+def upload(data):
+ url = 'https://paste2.org/'
+
+ response = requests.post(url, data={'data': data})
+ response.raise_for_status()
+
+ # Extract the URL of the uploaded paste from the response
+ paste_url = None
+ for line in response.text.splitlines():
+ if line.startswith('https?://[^\s]+)", lines[0]).group("url")
+ edit_code = lines[1].split(':')[-1].strip()
+ return {'name': 'rentry_' + edit_code, 'service': 'Rentry', 'key': url, 'md5sum': md5sum}
+
diff --git a/pastedb/pastedb01/services/sprunge.py b/pastedb/pastedb01/services/sprunge.py
new file mode 100644
index 0000000..2d8c266
--- /dev/null
+++ b/pastedb/pastedb01/services/sprunge.py
@@ -0,0 +1,40 @@
+import requests
+import json
+import hashlib
+import re
+
+url = 'http://sprunge.us'
+
+def upload(data):
+ try:
+ json_data = json.dumps(data)
+ md5sum = hashlib.md5(json_data.encode('utf-8')).hexdigest()
+
+ # Send the HTTP POST request to the Sprunge API
+ response = requests.post(url, data={'sprunge': json_data})
+ if response.status_code == 200:
+
+ # Get the URL of the uploaded text from the response body
+ sprunge_url = response.text.strip()
+
+ #print('Uploaded to:', sprunge_url)
+
+ # Use a regular expression to extract the random ID from the URL
+ match = re.match(r'^http://sprunge\.us/(\w+)$', sprunge_url)
+ if match:
+ random_id = match.group(1)
+ #print('Random ID:', random_id)
+ key = "sprunge_" + random_id + '_' + md5sum[:5]
+ else:
+ print('Invalid Sprunge URL:', sprunge_url)
+
+ return {
+ "service": "sprunge",
+ "name": key,
+ "key": sprunge_url,
+ "md5sum": md5sum
+ }
+ else:
+ return None
+ except requests.exceptions.RequestException:
+ return None
diff --git a/pastedb/pastedb01/services/termbin.py b/pastedb/pastedb01/services/termbin.py
new file mode 100644
index 0000000..ccdce8f
--- /dev/null
+++ b/pastedb/pastedb01/services/termbin.py
@@ -0,0 +1,26 @@
+import subprocess
+import hashlib
+import time
+import random
+import string
+
+def generate_name():
+ """Generate a random name for the paste"""
+ ts = int(time.time())
+ rand_str = ''.join(random.choices(string.ascii_lowercase, k=5))
+ name = f"termbin-{ts}-{rand_str}"
+ return name
+
+def upload(data):
+ """Upload the data to termbin.com"""
+ name = generate_name()
+ try:
+ cmd = f"echo '{data}' | nc termbin.com 9999"
+ response = subprocess.check_output(cmd, shell=True, timeout=5).decode()
+ url = f"https://termbin.com/{name}"
+ md5sum = hashlib.md5(data.encode('utf-8')).hexdigest()
+ return {'service': 'termbin', 'key': url, 'md5sum': md5sum}
+ except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e:
+ print(f"Upload failed with error: {e}")
+ return None
+
diff --git a/pastedb/pastedb01/upload.py b/pastedb/pastedb01/upload.py
new file mode 100644
index 0000000..43aaf48
--- /dev/null
+++ b/pastedb/pastedb01/upload.py
@@ -0,0 +1,46 @@
+import json
+import time
+import hashlib
+from services import pastie, dpaste, rentry, defau, sprunge, opendev
+
+# Load the JSON object from file
+with open('data.json') as f:
+ data = json.load(f)
+
+# Generate a unique name for the upload
+name = f"{time.time():.0f}-{hashlib.sha256(str(data).encode()).hexdigest()[:6]}"
+
+# Upload to the available services
+paste_dict = {'name': name}
+successes = []
+failures = []
+for service in [pastie, rentry, dpaste, sprunge, defau, opendev]:
+ try:
+ result = service.upload(data)
+ paste_dict[result['name']] = {
+ 'service': result['service'],
+ 'key': result['key'],
+ 'md5sum': result['md5sum'],
+ }
+ successes.append(result['name'])
+ except Exception as e:
+ failures.append(f"{service.__name__}: {str(e)}")
+
+# Update the paste_dict file
+with open('paste_dict.json', 'r+') as f:
+ try:
+ paste_dict.update(json.load(f))
+ f.seek(0)
+ except json.decoder.JSONDecodeError:
+ pass # ignore error if file is empty
+ json.dump(paste_dict, f, indent=2)
+
+# Print upload results
+print(f"Upload successful to {len(successes)}/{len(successes)+len(failures)} services:")
+for name in successes:
+ print(f"- {name}")
+if failures:
+ print("Upload failed to the following services:")
+ for error in failures:
+ print(f"- {error}")
+
diff --git a/pastedb/rentry b/pastedb/rentry
new file mode 100755
index 0000000..3169b91
--- /dev/null
+++ b/pastedb/rentry
@@ -0,0 +1,161 @@
+#!/usr/bin/env python3
+
+import getopt
+import http.cookiejar
+import sys
+import urllib.parse
+import urllib.request
+from http.cookies import SimpleCookie
+from json import loads as json_loads
+from os import environ
+
+_headers = {"Referer": 'https://rentry.co'}
+
+
+class UrllibClient:
+ """Simple HTTP Session Client, keeps cookies."""
+
+ def __init__(self):
+ self.cookie_jar = http.cookiejar.CookieJar()
+ self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar))
+ urllib.request.install_opener(self.opener)
+
+ def get(self, url, headers={}):
+ request = urllib.request.Request(url, headers=headers)
+ return self._request(request)
+
+ def post(self, url, data=None, headers={}):
+ postdata = urllib.parse.urlencode(data).encode()
+ request = urllib.request.Request(url, postdata, headers)
+ return self._request(request)
+
+ def _request(self, request):
+ response = self.opener.open(request)
+ response.status_code = response.getcode()
+ response.data = response.read().decode('utf-8')
+ return response
+
+
+def raw(url):
+ client = UrllibClient()
+ return json_loads(client.get('https://rentry.co/api/raw/{}'.format(url)).data)
+
+
+def new(url, edit_code, text):
+ client, cookie = UrllibClient(), SimpleCookie()
+
+ cookie.load(vars(client.get('https://rentry.co'))['headers']['Set-Cookie'])
+ csrftoken = cookie['csrftoken'].value
+
+ payload = {
+ 'csrfmiddlewaretoken': csrftoken,
+ 'url': url,
+ 'edit_code': edit_code,
+ 'text': text
+ }
+
+ return json_loads(client.post('https://rentry.co/api/new', payload, headers=_headers).data)
+
+
+def edit(url, edit_code, text):
+ client, cookie = UrllibClient(), SimpleCookie()
+
+ cookie.load(vars(client.get('https://rentry.co'))['headers']['Set-Cookie'])
+ csrftoken = cookie['csrftoken'].value
+
+ payload = {
+ 'csrfmiddlewaretoken': csrftoken,
+ 'edit_code': edit_code,
+ 'text': text
+ }
+
+ return json_loads(client.post('https://rentry.co/api/edit/{}'.format(url), payload, headers=_headers).data)
+
+
+def usage():
+ print('''
+Usage: rentry {new | edit | raw} {-h | --help} {-u | --url} {-p | --edit-code} text
+
+Commands:
+ new create a new entry
+ edit edit an existing entry
+ raw get raw markdown text of an existing entry
+
+Options:
+ -h, --help show this help message and exit
+ -u, --url URL url for the entry, random if not specified
+ -p, --edit-code EDIT-CODE edit code for the entry, random if not specified
+
+Examples:
+ rentry new 'markdown text' # new entry with random url and edit code
+ rentry new -p pw -u example 'text' # with custom edit code and url
+ rentry edit -p pw -u example 'text' # edit the example entry
+ cat FILE | rentry new # read from FILE and paste it to rentry
+ cat FILE | rentry edit -p pw -u example # read from FILE and edit the example entry
+ rentry raw -u example # get raw markdown text
+ rentry raw -u https://rentry.co/example # -u accepts absolute and relative urls
+ ''')
+
+
+if __name__ == '__main__':
+ try:
+ environ.pop('POSIXLY_CORRECT', None)
+ opts, args = getopt.gnu_getopt(sys.argv[1:], "hu:p:", ["help", "url=", "edit-code="])
+ except getopt.GetoptError as e:
+ sys.exit("error: {}".format(e))
+
+ command, url, edit_code, text = None, '', '', None
+
+ for o, a in opts:
+ if o in ("-h", "--help"):
+ usage()
+ sys.exit()
+ elif o in ("-u", "--url"):
+ url = urllib.parse.urlparse(a).path.strip('/')
+ elif o in ("-p", "--edit-code"):
+ edit_code = a
+
+ command = (args[0:1] or [None])[0]
+ command or sys.exit(usage())
+ command in ['new', 'edit', 'raw'] or sys.exit('error: command must be new, edit or raw')
+
+ text = (args[1:2] or [None])[0]
+ if not text and command != 'raw':
+ text = sys.stdin.read().strip()
+ text or sys.exit('error: text is required')
+
+ if command == 'new':
+ response = new(url, edit_code, text)
+ if response['status'] != '200':
+ print('error: {}'.format(response['content']))
+ try:
+ for i in response['errors'].split('.'):
+ i and print(i)
+ sys.exit(1)
+ except:
+ sys.exit(1)
+ else:
+ print('Url: {}\nEdit code: {}'.format(response['url'], response['edit_code']))
+
+ elif command == 'edit':
+ url or sys.exit('error: url is required')
+ edit_code or sys.exit('error: edit code is required')
+
+ response = edit(url, edit_code, text)
+ if response['status'] != '200':
+ print('error: {}'.format(response['content']))
+ try:
+ for i in response['errors'].split('.'):
+ i and print(i)
+ sys.exit(1)
+ except:
+ sys.exit(1)
+ else:
+ print('Ok')
+
+ elif command == 'raw':
+ url or sys.exit('error: url is required')
+ response = raw(url)
+ if response['status'] != '200':
+ sys.exit('error: {}'.format(response['content']))
+ print(response['content'])
diff --git a/pastedb/rentry_upload.py b/pastedb/rentry_upload.py
new file mode 100644
index 0000000..8317d0e
--- /dev/null
+++ b/pastedb/rentry_upload.py
@@ -0,0 +1,34 @@
+import hashlib
+import json
+import subprocess
+
+def upload(data):
+ json_data = json.dumps(data)
+ md5sum = hashlib.md5(json_data.encode('utf-8')).hexdigest()
+
+ # Run rentry client as subprocess
+ p = subprocess.Popen(
+ ['./services/rentry', 'new', {json_data}],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE
+ )
+
+ # Send JSON data to rentry client
+ stdout, stderr = p.communicate(json_data.encode('utf-8'))
+
+ if p.returncode != 0:
+ # Rentry client failed
+ print(f"Error running rentry client: {stderr.decode('utf-8')}")
+ return None
+
+ # Parse JSON response from rentry client
+ json_response = json.loads(stdout.decode('utf-8'))
+
+ return {
+ "service": "rentry",
+ "name": json_response["slug"],
+ "key": f"https://rentry.co/{json_response['slug']}",
+ "md5sum": md5sum
+ }
+
diff --git a/webpage-stuff/button-example.html b/webpage-stuff/button-example.html
new file mode 100644
index 0000000..a6e2d5b
--- /dev/null
+++ b/webpage-stuff/button-example.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+