Skip to content
Create a gist now

Instantly share code, notes, and snippets.

anonymous /dump.py secret
Created

# -*- coding: utf-8 -*-
from warnings import filterwarnings
from random import randint
from pprint import pprint
from time import sleep
import webbrowser
import argparse
import requests
import json
import sys
import os
import re
py3 = sys.version_info[0] > 2
filterwarnings('ignore')
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i+n]
# https://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python/312464#312464
def natural_sort(l):
convert = lambda text: int(text) if text.isdigit() else text.lower()
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
return sorted(l, key=alphanum_key)
# https://stackoverflow.com/questions/4836710/does-python-have-a-built-in-function-for-string-natural-sort/4836734#4836734
def has_numbers(input_string):
return any(char.isdigit() for char in input_string)
# https://stackoverflow.com/questions/19859282/check-if-a-string-contains-a-number/19859308#19859308
def is_installed(module):
try:
__import__(module)
except ImportError:
return False
return True
parser = argparse.ArgumentParser(description='Dump a folder to a thread')
parser.add_argument('-f', '--folder', help='Folder to upload images from', type=str, required=True)
parser.add_argument('-u', '--url', help='URL of thread', required=True)
parser.add_argument('-d', '--delay', help='Delay between posting', type=int, required=True)
parser.add_argument('-i', '--images', help='Number of images to post', type=int)
parser.add_argument('-n', '--name', help='Name to post with', type=str, default='')
parser.add_argument('-e', '--email', help='Email to post with', type=str, default='')
parser.add_argument('-p', '--progress', help='Post with dump progress? (default y)', choices=('y', 'n'), default='y')
args = vars(parser.parse_args())
# https://stackoverflow.com/questions/9234258/in-python-argparse-is-it-possible-to-have-paired-no-something-something-arg
delay = args['delay']
DIRECTORY = args['folder']
filelist = []
for file in os.listdir(DIRECTORY):
if os.path.splitext(file)[1].lower() in ('.jpg', '.jpeg', '.png', '.gif', '.webm', '.mp4'):
filelist.append(os.path.join(DIRECTORY, file))
# I stole this from stackoverflow somewhere, I can't find the link
if len(args['url'].split('/')) == 6:
spliturl = args['url'].split('/')
if has_numbers(spliturl[5]) and '.html' in args['url']:
url = '{}//{}'.format(spliturl[0], spliturl[2])
board = spliturl[3]
thread = spliturl[5].split('.')[0]
else:
sys.exit('\nBad URL. --u/--url should be the URL of a thread.\nExample: https://8ch.net/b/res/1.html')
else:
sys.exit('\nBad URL. --u/--url should be the URL of a thread.\nExample: https://8ch.net/b/res/1.html')
boardindex = requests.get('{}/{}/index.html'.format(url, board))
if args['images'] == None:
if is_installed('bs4') == True:
from bs4 import BeautifulSoup
soup = BeautifulSoup(boardindex.text)
script_tag = str(soup.find_all('script')[1])
print('-i/--images not specified. Defaulting to the maximum number of allowed images on this board.')
maxfiles = int(re.search('var max_images=[1-5]', script_tag).group(0).split('=')[1])
elif is_installed('bs4') == False:
sys.exit('Unable to automatically detect the maximum number of images per post, please specify -i/--images')
else:
if args['images'] >= 1 and args['images'] <= 5:
maxfiles = args['images']
else:
sys.exit('-i/--images must be between 1 and 5')
filelist = natural_sort(filelist)
total = len(filelist)
chunked_list = list(chunks(filelist, maxfiles))
r = requests.get('{}/settings.php?board={}'.format(url, board))
try:
j = json.loads(r.text)
if j['max_newlines'] != 0:
max_newlines = j['max_newlines']
else:
max_newlines = 100
except ValueError:
sys.exit('Server error while getting board settings')
data = {
'board': board,
'thread': thread,
'name': args['name'],
'email': args['email'],
'subject': '',
'body': '',
'embed': '',
'dx': '',
'dy': '',
'dz': '',
'password': 'ayylmao',
'json_response': '1',
'post': 'New Reply',
}
headers = {
'referer': '',
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'en-US,en;q=0.5',
'cache-control': 'max-age=0',
}
headers['referer'] = '{}/{}/'.format(url, board)
progress = maxfiles
for chunk in range(len(chunked_list)):
number_of_files = len(chunked_list[chunk])
status = ''
while 'redirect' not in status:
for x in range(len(chunked_list[chunk])):
l = natural_sort(chunked_list[chunk])
files = []
for file in range(len(l)):
if file == 0:
files.append(['file', open(l[file], 'rb')])
else:
files.append(['file' + str(file), open(l[file], 'rb')])
files = tuple(files)
newlines = '\n' * randint(1, max_newlines)
if progress > total:
progress = total
if args['progress'] == 'y':
data['body'] = '{}/{}{}'.format(progress, total, newlines)
else:
data['body'] = newlines
if j['captcha']['enabled'] == True:
r = requests.get('https://8ch.net/8chan-captcha/entrypoint.php?mode=get&extra=abcdefghijklmnopqrstuvwxyz&nojs=true')
try:
match = 'CAPTCHA ID: [a-z]*'
captcha_cookie = re.search(match, r.text).group().split(': ')[1]
match = '<image src="data:image/png;base64,[A-Za-z0-9+/=]*">'
with open('captcha_image.png', 'wb') as f:
f.write(re.search(match, r.text).group().split(',')[1].strip('>').strip('"').decode('base64'))
webbrowser.open('captcha_image.png')
if py3:
captcha_text = input('Enter the captcha: ')
else:
captcha_text = raw_input('Enter the captcha: ')
os.remove('captcha_image.png')
data['captcha_cookie'] = captcha_cookie
data['captcha_text'] = captcha_text
except AttributeError:
print('Server error while fetching captcha')
pass
status = requests.post('{}/post.php'.format(url), data=data, headers=headers, files=files).text
print(status)
if 'already exists' in status:
status = 'redirect'
if 'Maximum file size' in status:
print('THE FOLLOWING FILE(S) WERE OVER THE FILE SIZE LIMIT AND WERE NOT POSTED:')
pprint(l)
print('Consider setting -i/--images to a lower number so your files fit under the limit')
status = 'redirect'
del files
print('{}/{} - Waiting {} seconds...').format(progress, total, delay)
sleep(delay)
progress += number_of_files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.