Permalink
Browse files

examples, tests, posting on threads

  • Loading branch information...
1 parent 12c3633 commit 0b7af2deed6eb630036ca0a9f8749a78bda50131 @d1ffuz0r committed Jan 7, 2012
Showing with 265 additions and 49 deletions.
  1. +1 −10 README
  2. +1 −1 __init__.py
  3. +169 −18 api2ch.py
  4. +1 −0 examples/__init__.py
  5. +11 −0 examples/getboard.py
  6. +15 −0 examples/getthread.py
  7. +26 −0 examples/sendpost.py
  8. +2 −7 setup.py
  9. +0 −1 tests/__init__.py
  10. +1 −0 tests/pr/captcha.json
  11. +1 −0 tests/pr/settings.json
  12. +37 −12 tests/tests.py
View
@@ -1,12 +1,3 @@
About
========
-Object oriented wrapper for 2ch.so JSON-API
-
-Example
-========
- Fetching threads from /b/ board
- >>>from api2ch import Api
- >>>api = Api()
- >>>api.board = "b"
- >>>api.get_board()
- [<Thread: 1>, <Thread: 2>, <Thread: 3>]
+Object oriented wrapper for http://2ch.so JSON-API for Python
View
@@ -1 +1 @@
-__author__ = 'd1ffuz0r'
+__author__ = 'd1ffuz0r'
View
@@ -1,17 +1,36 @@
+# -*- coding:utf-8 -*-
"""2ch.so API"""
-
__author__ = "d1ffuz0r"
__version__ = "0.0.1"
-__all__ = ["Api", "Thread", "Post", "Captcha"]
+__all__ = ["Api", "Thread", "Post", "Captcha", "Settings", "BOARDS"]
import json
import urllib2
+from urllib import urlencode
+
+# List sections on board
+BOARDS = {
+ "thematics": ["au", "bi", "biz", "bo", "c", "em", "ew", "fa", "fiz",
+ "fl", "hi", "hw", "me", "mlp", "mo", "mu", "ne", "ph",
+ "po", "pr", "psy", "ra", "re", "s", "sf", "sci", "sn",
+ "sp", "t", "tr", "tv", "un", "w", "wh", "wm"],
+ "creation": ["di", "de", "diy", "f", "pa", "p", "wp", "td"],
+ "games": ["bg", "mc", "mmo", "vg", "wr"],
+ "japanese": ["a", "aa", "fd", "ma", "vn"],
+ "other": ["b", "soc", "r", "abu", "int"],
+ "adults": ["fg", "fur", "g", "ga", "h", "ho", "per", "sex"],
+ "test": ["fag", "rm", "mg", "adv", "ls", "gb", "spc", "to", "tes", "gd"]
+}
+
+listmerge = lambda s: reduce(lambda d, el: d.extend(el) or d, s, [])
+BOARDS_ALL = listmerge(BOARDS)
class Post(object):
- """Post object. make object from dict"""
+ """Post object"""
def __init__(self, post):
"""
+ Create object from dict with post info
@param post: dict with post info
"""
self.lasthit = post[u"lasthit"]
@@ -39,15 +58,39 @@ def __repr__(self):
return "<Post: {num}>".format(num=self.num)
+class Message(object):
+ """Message object"""
+ def __init__(self, parent="", comment="", subject=""):
+ """
+ @param parent: parent id (№ OP post)
+ @param comment: text your comment
+ @param subject: subject message example( SAGE )
+ @return:
+ """
+ self.captcha_key = ""
+ self.video = ""
+ self.nofile = ""
+ self.subject = subject
+ self.parent = parent
+ self.submit = ""
+ self.file = ""
+ self.name = ""
+ self.task = "pоst"
+ self.captcha = ""
+ self.email = ""
+ self.comment = comment
+
+
class Thread(object):
"""Thread object"""
def __init__(self, thread):
"""
+ Create object from dict with thread info
@param thread: dict with thread info
"""
self.reply_count = int(thread[u"reply_count"])
- self.posts = Post(thread[u"posts"][0][0])
- self.num = self.posts.num
+ self.post = Post(thread[u"posts"][0][0])
+ self.num = self.post.num
def __repr__(self):
return "<Thread: {num}>".format(num=self.num)
@@ -57,35 +100,107 @@ class Captcha(object):
"""Captcha object"""
def __init__(self, captcha):
"""
+ Create object from dict with captcha info
@param captcha: dict with captcha info
"""
self.key = captcha[u"key"]
self.url = captcha[u"url"]
+class Settings(object):
+ """Settings object"""
+ def __init__(self, settings):
+ """
+ Create object from dict with settings info
+ @param settings: dict with settings info
+ """
+ self.query_interval = settings[u"query_interval"]
+ self.query_limit = settings[u"query_limit"]
+ self.ban_time = settings[u"ban_time"]
+
+ postfields = settings[u"postfields"]
+ self.postfields = {
+ "captcha_key": postfields[u"captcha_key"],
+ "video": postfields[u"video"],
+ "nofile": postfields[u"nofile"],
+ "subject": postfields[u"subject"],
+ "submit": postfields[u"submit"],
+ "file": postfields[u"file"],
+ "name": postfields[u"name"],
+ "task": postfields[u"task"],
+ "captcha": postfields[u"captcha"],
+ "email": postfields[u"email"],
+ "comment": postfields[u"comment"],
+ }
+
+ board = settings[u"board"]
+ self.board = {
+ "thumb_dir": board[u"thumb_dir"],
+ "shortname": board[u"shortname"],
+ "wakaba_version": board[u"wakaba_version"],
+ "enable_wakabamark": board[u"enable_wakabamark"],
+ "imagesize": board[u"imagesize"],
+ "favicon": board[u"favicon"],
+ "name": board[u"name"],
+ "charset": board[u"charset"],
+ "max_comment_length": board[u"max_comment_length"],
+ "enable_bbcode": board[u"enable_bbcode"],
+ "threads_per_page": board[u"threads_per_page"],
+ "img_dir": board[u"img_dir"],
+ "page_ext": board[u"page_ext"],
+ "image_h": board[u"image_h"],
+ "image_w": board[u"image_w"],
+ "max_field_length": board[u"max_field_length"],
+ "res_dir": board[u"res_dir"],
+ }
+
+ def __repr__(self): # pragma: no cover
+ return "<Settings: %s>" % self.board["shortname"]
+
+
class Api(object):
"""Api object"""
def __init__(self, board=None):
"""
- @param board: board code
+ @param board: board code example( "b" )
"""
+ self.logging = False
self.board = board
self._url = "http://2ch.so/"
+ self.settings = None
+ self.captcha_key = None
+ self.thread = None
+
+ if board and self.board_exist(board): # pragma: no cover
+ self.settings = self.get_settings()
+
+ def board_exist(self, board):
+ """
+ Checking exist section on board or not
+ @param board: name section. example( "b" )
+ @return: boolean
+ """
+ return True if board in BOARDS_ALL else False
def get_board(self, board=None):
"""
- Get all threads from :board:
- @param board: code of board
- @return: list threads on board
+ Get all threads from board
+ @param board: board code
+ @return: List of threads on board
"""
- if self.board is None:
+ if board and self.board_exist(board): # pragma: no cover
self.board = board
threads = self._get(url="wakaba.json")[u'threads']
return [Thread(thread) for thread in threads]
def _get(self, url):
+ """
+ Get page
+ @param url: url for request
+ @return: raise or json object
+ """
if not self.board:
raise ValueError("Board is not selected")
else:
@@ -97,21 +212,57 @@ def get_thread(self, thread):
"""
Get thread
@param thread: id of thread
- @return: dict of Posts
+ @return: List of Posts object
"""
if isinstance(thread, Thread):
thread = thread.num
+ self.thread = thread
- posts = self._get("res/" + str(thread) + ".json")[u"thread"]
+ posts = self._get("res/" + str(self.thread) + ".json")[u"thread"]
return [Post(post[0]) for post in posts]
- def get_captcha(self):
+ def get_captcha(self): # pragma: no cover
+ """
+ Fetching captcha
+ @return: captcha info object
+ """
+ captcha = Captcha(
+ self._get("/wakaba.pl?task=api&code=getcaptcha")
+ )
+ self.captcha_key = captcha.key
+ return captcha
+
+ def get_settings(self): # pragma: no cover
+ """Fetching settings"""
+ self.settings = Settings(
+ self._get("/wakaba.pl?task=api&code=getsettings")
+ )
+
+ def send_post(self, msg): # pragma: no cover
"""
- @return: captcha info
+ Send post
+ @param msg: Post object
+ @return json:
"""
- captcha = self._get(self._url +
- self.board +
- "/wakaba.pl?task=api&code=getcaptcha")
+ params = self.settings.postfields
+ post = urlencode({
+ "parent": msg.parent,
+ params["captcha_key"]: self.captcha_key,
+ params["video"]: msg.video,
+ params["nofile"]: msg.nofile,
+ params["subject"]: msg.subject,
+ params["submit"]: msg.submit,
+ params["file"]: msg.file,
+ params["name"]: msg.name,
+ "task": msg.task,
+ params["captcha"]: msg.captcha,
+ params["email"]: msg.email,
+ params["comment"]: msg.comment
+ })
- return Captcha(captcha)
+ try:
+ urllib2.urlopen(self._url + self.board + "/wakaba.pl", data=post)
+ return True
+ except urllib2.HTTPError:
+ print "Error send post"
@@ -0,0 +1 @@
+__author__ = 'd1ffuz0r'
View
@@ -0,0 +1,11 @@
+from api2ch import Api
+
+# create object api
+dvach = Api()
+
+# select section
+dvach.board = "pr"
+
+# fetch list of threads
+for thread in dvach.get_board():
+ print thread
View
@@ -0,0 +1,15 @@
+import random
+from api2ch import Api
+
+# create object api
+dvach = Api()
+
+# select section
+dvach.board = "pr"
+
+# fetch list of threads
+threads = dvach.get_board()
+
+# select random thread and fetch posts
+for post in dvach.get_thread(random.choice(threads)):
+ print post
View
@@ -0,0 +1,26 @@
+from api2ch import Api, Message
+
+# create object api
+dvach = Api()
+
+# select section
+dvach.board = 'pr'
+
+# get settings (important)
+dvach.get_settings()
+
+# make message
+post = Message(96266, "python api 3", "SAGE")
+
+# fetch captcha
+captcha = dvach.get_captcha()
+
+# input decrypt captcha code
+print captcha.url
+cap = raw_input("enter captcha code: ")
+
+# set decrypt captcha code
+post.captcha = cap
+
+# send post
+dvach.send_post(post)
View
@@ -5,22 +5,17 @@
from ez_setup import use_setuptools
use_setuptools()
-from setuptools import setup, find_packages
-
import api2ch
-setup(name=api2ch.__doc__,
+setup(name="api2ch",
description="Object oriented wrapper for 2ch.so json-api",
long_description=open("README").read(),
author=api2ch.__author__,
version=api2ch.__version__,
author_email="d1fffuz0r@gmail.com",
py_modules=["api2ch"],
- url="http://github.com/d1ffuz0r/api2ch",
- license="GNU/GPL v3",
- platforms="Linux, Windows, Max OS X",
+ url="https://github.com/d1ffuz0r/2ch-API",
classifiers=[
- "License :: GNU/GPL v3",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Topic :: Internet :: API",
View
@@ -1 +0,0 @@
-__author__ = 'd1ffuz0r'
@@ -0,0 +1 @@
+{"url":"http://www.google.com/recaptcha/api/image?c=03AHJ_VuthHEpF99A4DiVV_qkWZtKXVJ4CXnMDkIY_S0t9-4Hp0dCjCTwvaFWCEIvv_MIwoAnfz8-XGqwuHNjQys0_nqUheFckKm409fMdPpPsVbTrHx8GEDfaKKcXPdxSUkzR5O_DsH_tgZkrZkRKsbMxHNJ6_P0hKQ","key":"03AHJ_VuthHEpF99A4DiVV_qkWZtKXVJ4CXnMDkIY_S0t9-4Hp0dCjCTwvaFWCEIvv_MIwoAnfz8-XGqwuHNjQys0_nqUheFckKm409fMdPpPsVbTrHx8GEDfaKKcXPdxSUkzR5O_DsH_tgZkrZkRKsbMxHNJ6_P0hKQ"}
@@ -0,0 +1 @@
+{"query_interval":60,"query_limit":55,"ban_time":600,"postfields":{"captcha_key":"recaptcha_challenge_field","video":"video","nofile":"nofile","subject":"kasumi","submit":"submit","file":"file","name":"akane","task":"post","captcha":"recaptcha_response_field","email":"nabiki","comment":"shampoo"},"board":{"thumb_dir":"thumb/","shortname":"pr","wakaba_version":"3.0.8-mk2","enable_wakabamark":1,"imagesize":4536,"favicon":"/favicon.ico","name":"Два.ч — Программирование","charset":"utf-8","max_comment_length":15360,"enable_bbcode":1,"threads_per_page":10,"img_dir":"src/","page_ext":".html","image_h":4096,"image_w":4096,"max_field_length":80,"res_dir":"res/"}}
Oops, something went wrong.

0 comments on commit 0b7af2d

Please sign in to comment.