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