Title: [Python] yotsuba.py Author: Anonymous Pastebin link: http://pastebin.com/0Tswud8e First Edit: Tuesday 20th of September 2016 12:35:43 PM CDT Last Edit: Tuesday 20th of September 2016 12:35:43 PM CDT import io import requests import json import re   REQUEST_TIMEOUT = 10   def post(_args):     args = {         "board": None,         "thread": None,         "options": None,         "name": None,         "subject": None,         "comment": None,         "file": None,         "filename": None,         "delpass": None,         "passid": None     }         args.update(_args)         if not args["board"]:         raise PostInvalidError("No board specified")         if not (args["subject"] or args["comment"] or args["file"]):         raise PostInvalidError("No subject, comment or file specified")         if not args["passid"]:         raise PostInvalidError("No 4chan pass id specified")         if args["file"] and not isinstance(args["file"], io.IOBase):         args["file"] = (open(args["file"], "rb") if args["file"] else None)         try:         request = requests.request(             method = "post",             url = ("https://sys.4chan.org/" + args["board"] + "/imgboard.php"),             timeout = REQUEST_TIMEOUT,             data = {                 "mode": "regist",                 "resto": (str(args["thread"]) if args["thread"] else ""),                 "name": (args["name"] if args["name"] else ""),                 "email": (args["options"] if args["options"] else ""),                 "sub": (args["subject"] if args["subject"] else ""),                 "com": (args["comment"] if args["comment"] else ""),                 "pwd": (args["delpass"] if args["delpass"] else ""),             },             files = {                 "upfile": (                     (args["filename"] if args["filename"] else "file"),                     args["file"]                 ) if args["file"] else ()             },             cookies = {                 "pass_enabled": "1",                 "pass_id": args["passid"]             }         )     except requests.exceptions.RequestException as exception:         raise PostFailedError from exception         postedno = re.search(r"", request.text)     postedno = int(postedno.group(1)) if postedno else None         if not postedno:         errmsg = re.search(r"(.+?)", request.text)         errmsg = errmsg.group(1) if errmsg else "(no error message found)"                 errmsg = re.sub(r"(
)+", r" ", errmsg)         errmsg = re.sub(r"<.*?>", r"", errmsg)         errmsg = re.sub(r"^Error: ", r"", errmsg)                 raise PostRejectedError(errmsg)         return postedno   def get(_args):     args = {         "type": None,         "board": None,         "page": None,         "thread": None     }         args.update(_args)         url = "https://a.4cdn.org"         if not args["type"] in ["thread", "index", "catalog", "threads", "archive", "boards"]:         raise GetInvalidError("Invalid type")         if args["type"] == "boards":         url = (url + "/boards.json")         if args["type"] == "thread":         if not (args["board"] and args["thread"]):             raise GetInvalidError("Type 'thread' requires args 'board' and 'thread'")                 url = (url + "/" + args["board"] + "/thread/" + str(args["thread"]) + ".json")         if args["type"] == "index":         if not (args["board"] and args["page"]):             raise GetInvalidError("Type 'index' requires args 'board' and 'page'")                 url = (url + "/" + args["board"] + "/" + str(args["page"]) + ".json")         if args["type"] == "catalog":         if not args["board"]:             raise GetInvalidError("Type 'catalog' requires args 'board'")                 url = (url + "/" + args["board"] + "/catalog.json")         if args["type"] == "threads":         if not args["board"]:             raise GetInvalidError("Type 'threads' requires args 'board'")                 url = (url + "/" + args["board"] + "/threads.json")         if args["type"] == "archive":         if not args["board"]:             raise GetInvalidError("Type 'archive' requires args 'board'")                 url = (url + "/" + args["board"] + "/archive.json")         try:         request = requests.request(             method = "get",             url = url,             timeout = REQUEST_TIMEOUT         )     except requests.exceptions.RequestException as exception:         raise GetFailedError(str(exception))         if request.status_code >= 400:         errmsg = (str(request.status_code) + " " + request.reason)                 if request.status_code == 404:             raise GetNotFoundError(errmsg)         else:             raise GetFailedError(errmsg)         data = json.loads(request.text)         if data == []:         raise GetFailedError         return data     class YotsubaError(Exception):     pass   class PostError(YotsubaError):     pass   class PostInvalidError(PostError):     pass   class PostFailedError(PostError):     pass   class PostRejectedError(PostError):     pass   class GetError(YotsubaError):     pass   class GetInvalidError(GetError):     pass   class GetFailedError(GetError):     pass   class GetNotFoundError(GetError):     pass