Skip to content

Commit

Permalink
V5.2.2 - added error_code and the response to tiktok exceptions (#916)
Browse files Browse the repository at this point in the history
  • Loading branch information
ctaity authored Jul 15, 2022
1 parent 31967d0 commit 75aea86
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 88 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ build
MANIFEST
src
.vscode
.env
.env
/.idea/
/TikTok-Api.iml
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ authors:
orcid: "https://orcid.org/0000-0002-9467-4676"
title: "TikTokAPI"
url: "https://github.com/davidteather/tiktok-api"
version: 5.2.1
date-released: 2022-7-7
version: 5.2.2
date-released: 2022-7-12
2 changes: 1 addition & 1 deletion TikTokApi/api/sound.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def __extract_from_data(self):

def __ensure_valid(self):
if self.id == "":
raise SoundRemovedException("This sound has been removed!")
raise SoundRemovedException(0, None, "This sound has been removed!")

def __repr__(self):
return self.__str__()
Expand Down
10 changes: 8 additions & 2 deletions TikTokApi/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
class TikTokException(Exception):
"""Generic exception that all other TikTok errors are children of."""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def __init__(self, error_code, raw_response, message):
self.error_code = error_code
self.raw_response = raw_response
self.message = message
super().__init__(self.message)

def __str__(self):
return f'{self.error_code} -> {self.message}'


class CaptchaException(TikTokException):
Expand Down
2 changes: 1 addition & 1 deletion TikTokApi/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def extract_tag_contents(html):
if sigi_json:
return sigi_json.group(1)
else:
raise CaptchaException(
raise CaptchaException(0, None,
"TikTok blocks this request displaying a Captcha \nTip: Consider using a proxy or a custom_verify_fp as method parameters"
)

Expand Down
157 changes: 77 additions & 80 deletions TikTokApi/tiktok.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
import asyncio
import json
import logging
import os
import threading
import asyncio
import random
import string
import threading
import time
from typing import ClassVar, Optional
from urllib import request
from urllib.parse import quote, urlencode
from dataclasses import dataclass
from typing import Optional
from urllib.parse import urlencode

import requests

from .api.comment import Comment
from .api.hashtag import Hashtag
from .api.search import Search
from .api.sound import Sound
from .api.trending import Trending
from .api.user import User
from .api.search import Search
from .api.hashtag import Hashtag
from .api.video import Video
from .api.trending import Trending
from .api.comment import Comment

from playwright.sync_api import sync_playwright

from .exceptions import *
from .utilities import LOGGER_NAME, update_messager
from .browser_utilities.browser import browser
from dataclasses import dataclass
from .exceptions import *
from .utilities import LOGGER_NAME

os.environ["no_proxy"] = "127.0.0.1,localhost"

Expand All @@ -33,6 +30,47 @@

_thread_lock = threading.Lock()

ERROR_CODES = {
"0": "OK",
"450": "CLIENT_PAGE_ERROR",
"10000": "VERIFY_CODE",
"10101": "SERVER_ERROR_NOT_500",
"10102": "USER_NOT_LOGIN",
"10111": "NET_ERROR",
"10113": "SHARK_SLIDE",
"10114": "SHARK_BLOCK",
"10119": "LIVE_NEED_LOGIN",
"10202": "USER_NOT_EXIST",
"10203": "MUSIC_NOT_EXIST",
"10204": "VIDEO_NOT_EXIST",
"10205": "HASHTAG_NOT_EXIST",
"10208": "EFFECT_NOT_EXIST",
"10209": "HASHTAG_BLACK_LIST",
"10210": "LIVE_NOT_EXIST",
"10211": "HASHTAG_SENSITIVITY_WORD",
"10212": "HASHTAG_UNSHELVE",
"10213": "VIDEO_LOW_AGE_M",
"10214": "VIDEO_LOW_AGE_T",
"10215": "VIDEO_ABNORMAL",
"10216": "VIDEO_PRIVATE_BY_USER",
"10217": "VIDEO_FIRST_REVIEW_UNSHELVE",
"10218": "MUSIC_UNSHELVE",
"10219": "MUSIC_NO_COPYRIGHT",
"10220": "VIDEO_UNSHELVE_BY_MUSIC",
"10221": "USER_BAN",
"10222": "USER_PRIVATE",
"10223": "USER_FTC",
"10224": "GAME_NOT_EXIST",
"10225": "USER_UNIQUE_SENSITIVITY",
"10227": "VIDEO_NEED_RECHECK",
"10228": "VIDEO_RISK",
"10229": "VIDEO_R_MASK",
"10230": "VIDEO_RISK_MASK",
"10231": "VIDEO_GEOFENCE_BLOCK",
"10404": "FYP_VIDEO_LIST_LIMIT",
"undefined": "MEDIA_ERROR",
}


class TikTokApi:
_is_context_manager = False
Expand All @@ -46,17 +84,17 @@ class TikTokApi:
logger = logging.getLogger(LOGGER_NAME)

def __init__(
self,
logging_level: int = logging.WARNING,
request_delay: Optional[int] = None,
custom_device_id: Optional[str] = None,
generate_static_device_id: Optional[bool] = False,
custom_verify_fp: Optional[str] = None,
use_test_endpoints: Optional[bool] = False,
proxy: Optional[str] = None,
executable_path: Optional[str] = None,
*args,
**kwargs,
self,
logging_level: int = logging.WARNING,
request_delay: Optional[int] = None,
custom_device_id: Optional[str] = None,
generate_static_device_id: Optional[bool] = False,
custom_verify_fp: Optional[str] = None,
use_test_endpoints: Optional[bool] = False,
proxy: Optional[str] = None,
executable_path: Optional[str] = None,
*args,
**kwargs,
):
"""The TikTokApi class. Used to interact with TikTok. This is a singleton
class to prevent issues from arising with playwright
Expand Down Expand Up @@ -302,87 +340,46 @@ def get_data(self, path, subdomain="m", **kwargs) -> dict:
try:
parsed_data = r.json()
if (
parsed_data.get("type") == "verify"
or parsed_data.get("verifyConfig", {}).get("type", "") == "verify"
parsed_data.get("type") == "verify"
or parsed_data.get("verifyConfig", {}).get("type", "") == "verify"
):
self.logger.error(
"Tiktok wants to display a captcha.\nResponse:\n%s\nCookies:\n%s\nURL:\n%s",
r.text,
self._get_cookies(**kwargs),
url,
)
raise CaptchaException(
raise CaptchaException(0, None,
"TikTok blocks this request displaying a Captcha \nTip: Consider using a proxy or a custom_verify_fp as method parameters"
)

# statusCode from props->pageProps->statusCode thanks @adiantek on #403
error_codes = {
"0": "OK",
"450": "CLIENT_PAGE_ERROR",
"10000": "VERIFY_CODE",
"10101": "SERVER_ERROR_NOT_500",
"10102": "USER_NOT_LOGIN",
"10111": "NET_ERROR",
"10113": "SHARK_SLIDE",
"10114": "SHARK_BLOCK",
"10119": "LIVE_NEED_LOGIN",
"10202": "USER_NOT_EXIST",
"10203": "MUSIC_NOT_EXIST",
"10204": "VIDEO_NOT_EXIST",
"10205": "HASHTAG_NOT_EXIST",
"10208": "EFFECT_NOT_EXIST",
"10209": "HASHTAG_BLACK_LIST",
"10210": "LIVE_NOT_EXIST",
"10211": "HASHTAG_SENSITIVITY_WORD",
"10212": "HASHTAG_UNSHELVE",
"10213": "VIDEO_LOW_AGE_M",
"10214": "VIDEO_LOW_AGE_T",
"10215": "VIDEO_ABNORMAL",
"10216": "VIDEO_PRIVATE_BY_USER",
"10217": "VIDEO_FIRST_REVIEW_UNSHELVE",
"10218": "MUSIC_UNSHELVE",
"10219": "MUSIC_NO_COPYRIGHT",
"10220": "VIDEO_UNSHELVE_BY_MUSIC",
"10221": "USER_BAN",
"10222": "USER_PRIVATE",
"10223": "USER_FTC",
"10224": "GAME_NOT_EXIST",
"10225": "USER_UNIQUE_SENSITIVITY",
"10227": "VIDEO_NEED_RECHECK",
"10228": "VIDEO_RISK",
"10229": "VIDEO_R_MASK",
"10230": "VIDEO_RISK_MASK",
"10231": "VIDEO_GEOFENCE_BLOCK",
"10404": "FYP_VIDEO_LIST_LIMIT",
"undefined": "MEDIA_ERROR",
}

statusCode = parsed_data.get("statusCode", 0)
self.logger.debug(f"TikTok Returned: %s", json)
if statusCode == 10201:
# Invalid Entity
raise NotFoundException(
"TikTok returned a response indicating the entity is invalid"
)
raise NotFoundException(10201, r,
"TikTok returned a response indicating the entity is invalid"
)
elif statusCode == 10219:
# Not available in this region
raise NotAvailableException("Content not available for this region")
raise NotAvailableException(10219, r, "Content not available for this region")
elif statusCode != 0 and statusCode != -1:
raise TikTokException(
error_codes.get(
statusCode, f"TikTok sent an unknown StatusCode of {statusCode}"
)
)
raise TikTokException(statusCode, r,
ERROR_CODES.get(statusCode, f"TikTok sent an unknown StatusCode of {statusCode}")
)

return r.json()
except ValueError as e:
text = r.text
self.logger.debug("TikTok response: %s", text)
if len(text) == 0:
raise EmptyResponseException(
raise EmptyResponseException(0, None,
"Empty response from Tiktok to " + url
) from None
else:
raise InvalidJSONException("TikTok sent invalid JSON") from e
raise InvalidJSONException(0, r, "TikTok sent invalid JSON") from e

def get_data_no_sig(self, path, subdomain="m", **kwargs) -> dict:
processed = self._process_kwargs(kwargs)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
setuptools.setup(
name="TikTokApi",
packages=setuptools.find_packages(),
version="5.2.1",
version="5.2.2",
license="MIT",
description="The Unofficial TikTok API Wrapper in Python 3.",
author="David Teather",
Expand Down

1 comment on commit 75aea86

@Rasifali
Copy link

@Rasifali Rasifali commented on 75aea86 Jul 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.