Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- Script shall be called every X minutes. Pseudocode:
- get catalog at http://a.4cdn.org/ic/catalog.json
- for each thread with prefix "/las/" and "last_modified" greater than locally saved:
- get thread at http://a.4cdn.org/ic/thread/{threadnumber}.json
- for each new reply:
- if name, image and securetrip are valid:
- if name isn't already used:
- create folder (name!!securetrip)
- if folder exists (thus securetrip is valid):
- add image to the folder ({timestamp in millis}.{ext})
- """
- import requests, re, os
- USER_DIR = "users/"
- STATE_FILE = "state.txt"
- BOARD = "ic"
- GENERAL_PREFIX = "/las/"
- def get(url):
- return requests.get(url).json()
- def get_catalog(board):
- catalog = get("http://a.4cdn.org/{}/catalog.json".format(board))
- threads = []
- for page in catalog:
- threads.extend(page["threads"])
- return threads
- def get_thread(board, thread):
- return get("http://a.4cdn.org/{}/thread/{}.json".format(board, thread))["posts"]
- def get_new_posts(board, thread, time):
- return [post for post in get_thread(board, thread) if post["time"] > time]
- def load_state():
- try:
- with open(STATE_FILE, "r") as file:
- return tuple(int(time) for time in file.read().split(" "))
- except FileNotFoundError:
- return (0, 0)
- def save_state(last_report, last_update):
- with open(STATE_FILE, "w") as file:
- file.write("{} {}".format(last_report, last_update))
- def is_name_valid(name):
- return name is not "Anonymous" and re.match(r"^[a-zA-Z0-9 \-_]{1,32}$", name)
- def is_submission(post):
- return "name" in post and is_name_valid(post["name"]) and "trip" in post and post["trip"].startswith("!!") and "tim" in post
- def load_users():
- if not os.path.exists(USER_DIR):
- os.makedirs(USER_DIR)
- users = {}
- for dir in os.listdir(USER_DIR):
- tokens = dir.split("!!")
- users[tokens[0]] = "!!" + tokens[1]
- return users
- def save_remote_file(url, path):
- if not os.path.exists(path):
- request = requests.get(url, stream=True)
- if request.status_code == 200:
- with open(path, 'wb') as file:
- for chunk in request.iter_content(1024):
- file.write(chunk)
- else:
- print("FAILED: {} {} {}".format(url, path, request.status_code))
- def merge_user(users, name, trip):
- if name not in users:
- users[name] = trip
- return True
- else:
- return users[name] == trip
- def merge_submission(board, post):
- path = USER_DIR + post["name"] + post["trip"]
- if not os.path.exists(path):
- os.makedirs(path)
- filename = "{}{}".format(post["tim"], post["ext"])
- save_remote_file("http://i.4cdn.org/{}/{}".format(board, filename), path + "/" + filename)
- if __name__ == "__main__":
- last_report, last_update = load_state()
- users = load_users()
- current = last_update
- for thread in get_catalog(BOARD):
- if "sub" in thread and thread["sub"].startswith(GENERAL_PREFIX) and thread["last_modified"] > current:
- last_update = max(last_update, thread["last_modified"])
- print("UPDATE: {} at {}".format(thread["no"], thread["last_modified"]))
- for post in get_new_posts(BOARD, thread["no"], current):
- if is_submission(post) and merge_user(users, post["name"], post["trip"]):
- merge_submission(BOARD, post)
- save_state(last_report, last_update)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement