Commit 245a3556 authored by Rob Nelson's avatar Rob Nelson
Browse files

Initial commit

parents
*.pyc
*.bak
"""
4chan Site Plugin
"""
from pychan.plugins import BasePlugin
from site_4chan.handler_4chan import FourchanHandler
class FourChanPlugin(BasePlugin):
ID = 'b327f53e-63b6-44af-b1ca-3dfab48c1752'
NAME = '4chan Site Plugin'
AUTHORS = [
'nexisentertainment@gmail.com'
]
VERSION = '0.0.1-alpha'
def Load(self):
return [FourchanHandler]
4chan:
domains:
- boards.4chan.org
software: 4chan
delays:
site: 5
catalog: 30
thread: 30
\ No newline at end of file
swagger: '2.0'
info:
title: 4chan
# Y.M.D
version: 2018.09.05
description: An unofficial description of the endpoints available to developers
on 4chan, derived from 4chan's API repository on GitHub.
termsOfService: https://github.com/4chan/4chan-API
license:
name: MIT Opensource License
host: a.4cdn.org
schemes:
- https
- http
basePath: /
externalDocs:
description: Find out more about 4chan's API
url: https://github.com/4chan/4chan-API
definitions:
CatalogEntry:
$ref: definitions/CatalogEntry.yml
Board:
$ref: definitions/Board.yml
Post:
$ref: definitions/Post.yml
paths:
/{boardID}/{pageIdx}.json:
parameters:
- name: boardID
in: path
description: ID of the board.
required: true
type: string
pattern: ^[a-zA-Z0-9]+$
- name: pageIdx
in: path
required: true
minimum: 1
description: Page number, starting from 1
type: integer
get:
tags:
- boards
summary: Get threads on a board page.
description: Retrieves a list of thread IDs for a particular page on a particular board.
produces:
- application/json
responses:
404:
description: Board not found
200:
description: Board contents page
schema:
type: array
items:
type: object
properties:
page:
type: integer
description: index of the page.
example: 0
threads:
type: array
items:
$ref: definitions/CatalogEntry.yml
/{boardID}/catalog.json:
parameters:
- in: path
name: boardID
description: ID of the board.
required: true
type: string
pattern: ^[a-zA-Z0-9]+$
get:
tags:
- boards
summary: Get all threads on a board.
description: Presents all available threads on a given board.
produces:
- application/json
responses:
404:
description: Board does not exist.
200:
description: Paged thread list.
schema:
type: array
description: An array of pages.
items:
type: object
properties:
page:
type: integer
description: Index of the page.
threads:
type: array
items:
$ref: definitions/Post.yml
/{boardID}/threads.json:
parameters:
- in: path
name: boardID
description: ID of the board.
required: true
type: string
pattern: ^[a-zA-Z0-9]+$
get:
tags:
- boards
summary: Get all thread IDs and timestamps on a board.
description: Presents all available thread IDs and timestamps on a given board.
produces:
- application/json
responses:
404:
description: Board does not exist.
200:
description: Paged thread list.
schema:
type: array
description: An array of pages.
items:
type: object
description: Representation of a board page.
properties:
page:
type: integer
description: Index of the page.
threads:
type: array
items:
type: object
required:
- 'no'
- last_modified
properties:
'no':
type: integer
example: 7613594
description: Number of this post in each board. NOT unique
globally.
last_modified:
type: integer
description: Unix timestamp of the last change made to the
thread.
example: 1512937329
/{boardID}/thread/{threadID}.json:
parameters:
- in: path
name: boardID
description: ID of the board.
required: true
type: string
pattern: ^[a-zA-Z0-9]+$
- in: path
name: threadID
description: ID of the thread.
required: true
type: integer
get:
tags:
- threads
summary: Get all of the posts in a thread
description: Presents all available thread IDs and timestamps on a given board.
produces:
- application/json
responses:
404:
description: Board and/or thread does not exist.
200:
description: Paged thread list.
schema:
type: object
description: An object containing the post array.
required:
- posts
properties:
posts:
type: array
description: A list of all of the posts in the thread.
items:
$ref: definitions/Post.yml
/boards.json:
get:
tags:
- boards
summary: Get all of the boards currently hosted on 4chan.
description: A list of all boards present on 4chan.
produces:
- application/json
responses:
200:
description: Array of boards.
schema:
type: object
properties:
boards:
type: array
items:
$ref: definitions/Board.yml
troll_flags:
type: object
description: A key => name associative list of troll country codes.
title: Board
description: 4chan's representation of a board's settings.
type: object
required:
- board
- title
- per_page
- pages
- max_filesize
- max_comment_chars
- bump_limit
- image_limit
- cooldowns
- meta_description
properties:
board:
type: string
example: aco
description: Board ID
title:
type: string
example: Adult Cartoons
description: Name of the board in question
ws_board:
type: integer
example: 1
enum:
- 0
- 1
description: Work-safe board
per_page:
type: integer
example: 15
minimum: 0
description: Threads per page
pages:
type: integer
example: 10
minimum: 0
description: Number of pages
max_filesize:
type: integer
example: 4194304
minimum: 0
description: Maximum file size in, bytes.
max_webm_filesize:
type: integer
example: 3145728
minimum: 0
description: Maximum webm file size, in bytes.
max_comment_chars:
type: integer
example: 2000
minimum: 0
description: How many characters each post's comment is permitted to have.
max_webm_duration:
type: integer
example: 120
minimum: 0
description: How many seconds each webm is permitted to last.
bump_limit:
type: integer
example: 300
minimum: 0
description: Bump (reply) limit
image_limit:
type: integer
example: 250
minimum: 0
description: Image limit
cooldowns:
type: object
description: Various cooldowns implemented on the board
properties:
threads:
type: integer
example: 600
description: How many seconds must pass before you can post a new thread.
replies:
type: integer
example: 60
description: How many seconds must pass before you can post a new reply.
images:
type: integer
example: 30
description: How many seconds must pass before you can post a new image.
meta_description:
type: string
example: "\u0026quot;\/aco\/ - Adult Cartoons\u0026quot; is 4chan's imageboard for posting western-styled adult cartoon artwork.",
description: Meta description tag for SEO
is_archived:
type: integer
example: 1
enum:
- 0
- 1
description: Whether the board can archive threads or not.
custom_spoilers:
type: integer
example: 1
minimum: 0
maximum: 10
description: Custom spoilers are enabled when this is greater than 0. The actual value is used to select a specific set of spoiler images.
spoilers:
type: integer
example: 1
enum:
- 0
- 1
description: Spoilers are enabled when this is greater than 0.
user_ids:
type: integer
enum:
- 0
- 1
example: 1
description: Whether user IDs are enabled
country_flags:
type: integer
enum:
- 0
- 1
example: 1
description: Whether country flags are enabled
title: Catalog Entry
description: A simple object that just contains the first and last post of the thread.
type: object
required:
- posts
properties:
posts:
type: array
items:
$ref: ../definitions/Post.yml
title: Post
description: A post as seen in a catalog endpoint.
type: object
required:
- 'no'
- time
- last_modified
- resto
properties:
'no':
type: integer
example: 9001
description: Number of this post in each board. NOT unique globally.
resto:
type: integer
example: 0
description: Reply To
sticky:
type: integer
example: 1
description: Stickied thread
closed:
type: integer
example: 1
description: Locked thread
archived:
type: integer
example: 1
description: Archived thread
archived_on:
type: integer
example: 1344571233
description: UNIX timestamp of when the thread was archived.
now:
type: string
example: 08/08/12(Wed)01:11
description: MM/DD/YY(Day)HH:MM (:SS on some boards), EST/EDT timezone
time:
type: integer
example: 1344570123
description: UNIX timestamp
name:
type: string
example: moot
description: Name of the user
trip:
type: string
example: "!Ep8pui8Vw2"
description: text (format: !tripcode!!securetripcode)
id:
type: string
example: Admin
description: ID
capcode:
type: string
example: admin
description: Capcode
country:
type: string
example: XX
description: Country code
country_name:
type: string
example: Unknown
description: Country name
sub:
type: string
example: This is a subject
description: Subject
com:
type: string
example: This is a comment
description: Comment
tim:
type: integer
example: 1344402680740
description: Renamed filename
filename:
type: string
example: OPisa
description: Original filename
ext:
type: string
example: .jpg
description: File extension
fsize:
type: integer
example: 2500
description: File size
md5:
type: string
example: NOetrLVnES3jUn1x5ZPVAg==
description: File MD5
w:
type: integer
example: 500
description: Image width
h:
type: integer
example: 500
description: Image height
tn_w:
type: integer
example: 250
description: Thumbnail width
tn_h:
type: integer
example: 250
description: Thumbnail height
filedeleted:
type: integer
example: 0
description: File deleted?
spoiler:
type: integer
example: 0
description: Spoiler image?
custom_spoiler:
type: integer
example: 3
description: Custom spoilers?
omitted_posts:
type: integer
example: 33
description: replies omitted
omitted_images:
type: integer
example: 21
description: image replies omitted
replies:
type: integer
example: 231
description: replies total
images:
type: integer
example: 132
description: images total
bumplimit:
type: integer
example: 0
description: Bump limit met?
imagelimit:
type: integer
example: 1
description: Image limit met?
capcode_replies:
type: object
additionalProperties: true
example: {"admin":[1234,1267]}
description: Capcode user replies
last_modified:
type: integer
example: 1344571233
description: Time when last modified
tag:
type: string
example: Loop
description: Thread tag
semantic_url:
type: string
example: daily-programming-thread
description: Thread URL slug
since4pass:
type: integer
example: 2016
description: Year 4chan Pass bought
import json
import os
from collections import OrderedDict
import yaml
def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict):
class OrderedLoader(Loader):
pass
def construct_mapping(loader, node):
loader.flatten_mapping(node)
return object_pairs_hook(loader.construct_pairs(node))
OrderedLoader.add_constructor(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
construct_mapping)
return yaml.load(stream, OrderedLoader)
def ordered_dump(data, stream=None, Dumper=yaml.Dumper, **kwds):
class OrderedDumper(Dumper):
pass
def _dict_representer(dumper, data):
return dumper.represent_mapping(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
data.items())
OrderedDumper.add_representer(OrderedDict, _dict_representer)
return yaml.dump(data, stream, OrderedDumper, **kwds)
def renameRefsToJSON(yml):
newdata = OrderedDict()
for k, v in yml.items():
if k == '$ref' and '.' in v:
basename, ext = os.path.splitext(