TWITTER_PAGE_DOES_NOT_EXISTS_ERROR = 34 TWITTER_TWEET_NOT_FOUND_ERROR = 144 TWITTER_USER_NOT_FOUND_ERROR = 50 TWITTER_DELETE_OTHER_USER_TWEET = 183 TWITTER_ACCOUNT_SUSPENDED_ERROR = 64 TWITTER_USER_IS_NOT_LIST_MEMBER_SUBSCRIBER = 109 TWITTER_AUTOMATED_REQUEST_ERROR = 226 TWITTER_OVER_CAPACITY_ERROR = 130 TWITTER_DAILY_STATUS_UPDATE_LIMIT_ERROR = 185 TWITTER_CHARACTER_LIMIT_ERROR_1 = 186 TWITTER_CHARACTER_LIMIT_ERROR_2 = 354 TWITTER_STATUS_DUPLICATE_ERROR = 187 class APIQuotaError(APIError):
    """
    Exception indicate some API quota breached.
    """
    pass class AutomatedRequestError(ResponseBotError):
    """
    Error to indicate a request is deemed automated by Twitter.
    """
    pass class OverCapacityError(ResponseBotError):
    """
    Error to indicate Twitter is currently over capacity.
    """
    pass class DailyStatusUpdateError(ResponseBotError):
    """
    Error to indicate your account reached the daily status update limit.
    """
    pass class CharacterLimitError(ResponseBotError):
    """
    Error to indicate your tweet reached the character limit.
    """
    pass class StatusDuplicateError(ResponseBotError):
    """
    Error to indicate your status is a duplicate.
    """
    pass class Tweet(object):
    """
    Represents a tweet. E.g. you can get a tweet's text via it's :code:`text` property (:code:`tweet.text`).
    All properties except :code:`retweeted_status`, :code:`quoted_status`, :code:`quoted_status_id_str`, :code:`in_reply_to_status_id`
    and :code:`in_reply_sto_status_id_str` have the same name as Twitter defined them `here <https://dev.twitter.com/overview/api/tweets>`_.
    :code:`retweeted_status` is renamed to :code:`retweeted_tweet`, similar for other properties above.
    """
    def __init__(self, data):
        """
        :param data: Parsed JSON data
        :type data: dictionary
        """
        self.raw_data = data

        # TODO: handle place. source, quoted_status_id_str
        for key, value in data.items():
            if key == 'user':
                setattr(self, key, User(value))
            elif key == 'created_at':
                setattr(self, key, parse(value))
            elif key == 'retweeted_status':
                setattr(self, 'retweeted_tweet', Tweet(value))
            elif key == 'quoted_status':
                setattr(self, 'quoted_tweet', Tweet(value))
            elif key == 'quoted_status_id_str':
                setattr(self, 'quoted_tweet_id_str', value)
            elif key == 'in_reply_to_status_id':
                setattr(self, 'in_reply_to_tweet_id', value)
            elif key == 'in_reply_to_status_id_str':
                setattr(self, 'in_reply_to_tweet_id_str', value)
            else:
                setattr(self, key, value) class User(object):
    """
    Represents a user. E.g. you can get a user's screen name via it's :code:`screen_name` property
    (:code:`user.screen_name`). All properties except :code:`status` have the same name as Twitter defined them `here
    <https://dev.twitter.com/overview/api/users>`_. :code:`status` is renamed to :code:`tweet`.
    """
    def __init__(self, data):
        """
        :param data: Parsed JSON data
        :type data: dictionary
        """
        self.raw_data = data

        for key, value in data.items():
            if key == 'created_at':
                setattr(self, key, parse(value))
            elif key == 'status':
                setattr(self, 'tweet', Tweet(value))
            elif key == 'following':
                setattr(self, key, value is True)
            else:
                setattr(self, key, value) class List(object):
    """
    Represent a user list.
    """
    def __init__(self, data):
        """
        :param data: Parsed JSON data
        :type data: dictionary
        """
        self.raw_data = data

        for key, value in data.items():
            if key == 'user':
                setattr(self, key, User(value))
            elif key == 'created_at':
                setattr(self, key, parse(value))
            else:
                setattr(self, key, value) def tweepy_list_to_json(tweepy_list):
    json = dict(tweepy_list.__dict__)

    json.pop('_api')
    # Set default timezone to +0000 here since datetime does not contain tz info
    json['created_at'] = datetime.strftime(json['created_at'], '%a %b %d %H:%M:%S +0000 %Y')
    json['user'] = json['user']._json

    return json
from decorator import decorate
from tweepy.error import TweepError, RateLimitError
from responsebot.common.constants import TWITTER_PAGE_DOES_NOT_EXISTS_ERROR, TWITTER_TWEET_NOT_FOUND_ERROR, \
    TWITTER_USER_NOT_FOUND_ERROR, TWITTER_DELETE_OTHER_USER_TWEET, TWITTER_ACCOUNT_SUSPENDED_ERROR,\
    TWITTER_USER_IS_NOT_LIST_MEMBER_SUBSCRIBER, TWITTER_AUTOMATED_REQUEST_ERROR, TWITTER_OVER_CAPACITY_ERROR,\
    TWITTER_DAILY_STATUS_UPDATE_LIMIT_ERROR, TWITTER_CHARACTER_LIMIT_ERROR_1, TWITTER_CHARACTER_LIMIT_ERROR_2, \
    TWITTER_STATUS_DUPLICATE_ERROR
from responsebot.common.exceptions import APIQuotaError, AutomatedRequestError, OverCapacityError,\
    DailyStatusUpdateError, CharacterLimitError, StatusDuplicateError
from responsebot.models import Tweet, User, List
from responsebot.utils.tweepy import tweepy_list_to_json
from __future__ import absolute_import




def api_error_handle(func):
    def func_wrapper(f, *args, **kwargs):
        try:
            return f(*args, **kwargs)
        except RateLimitError as e:
            raise APIQuotaError(str(e))
        except TweepError as e:

            if e.api_code == TWITTER_AUTOMATED_REQUEST_ERROR: