Skip to content

Commit

Permalink
Code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
pablouser1 committed Jan 28, 2023
1 parent 8ee7efd commit 4426ee9
Show file tree
Hide file tree
Showing 18 changed files with 183 additions and 111 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.3.4.0
2.3.4.1
3 changes: 1 addition & 2 deletions src/Api.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
<?php

namespace TikScraper;

use TikScraper\Interfaces\CacheInterface;
use TikScraper\Items\User;
use TikScraper\Items\Hashtag;
use TikScraper\Items\Music;
use TikScraper\Items\Video;
use TikScraper\Items\Trending;
use TikScraper\Models\Discover;
use TikScraper\Interfaces\CacheInterface;

class Api {
private Sender $sender;
Expand Down
3 changes: 1 addition & 2 deletions src/Constants/Codes.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ class Codes {
* Get status message from ID
*/
public static function fromId(int $id): string {
$keys = array_keys(Codes::list);
return in_array($id, $keys) ? Codes::list[$id] : "UNKNOWN_ERROR";
return isset(self::list[$id]) ? self::list[$id] : "UNKNOWN_ERROR";
}
}
2 changes: 1 addition & 1 deletion src/Constants/SignMethods.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
namespace TikScraper\Constants;

abstract class SignMethods {
const BROWSER = 'browser';
const REMOTE = 'remote';
const BROWSER = 'browser';
}
1 change: 0 additions & 1 deletion src/Constants/UserAgents.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@

abstract class UserAgents {
const DEFAULT = "Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-G973U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/14.2 Chrome/87.0.4280.141 Mobile Safari/537.36";
const DOWNLOAD = "Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-G973U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/14.2 Chrome/87.0.4280.141 Mobile Safari/537.36";
}
17 changes: 17 additions & 0 deletions src/Downloaders/BaseDownloader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php
namespace TikScraper\Downloaders;

use TikScraper\Constants\UserAgents;
use TikScraper\Traits\ProxyTrait;

abstract class BaseDownloader {
use ProxyTrait;

protected const BUFFER_SIZE = 256 * 1024;
protected string $userAgent;

function __construct(array $config = []) {
$this->initProxy($config['proxy'] ?? []);
$this->userAgent = $config['user_agent'] ?? UserAgents::DEFAULT;
}
}
42 changes: 30 additions & 12 deletions src/Downloaders/DefaultDownloader.php
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
<?php
namespace TikScraper\Downloaders;

use TikScraper\Constants\UserAgents;
use TikScraper\Helpers\Algorithm;
use TikScraper\Helpers\Converter;
use TikScraper\Interfaces\DownloaderInterface;
use TikScraper\Traits\CookieTrait;

class DefaultDownloader extends BaseDownloader implements DownloaderInterface {
use CookieTrait;

public function __construct(array $config = []) {
parent::__construct($config);
$this->initCookies();
}

class DefaultDownloader implements DownloaderInterface {
public function watermark(string $url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_USERAGENT, UserAgents::DEFAULT);
curl_setopt($ch, CURLOPT_REFERER, "https://www.tiktok.com/");
curl_setopt($ch, CURLOPT_BUFFERSIZE, self::BUFFER_SIZE);
$ch = curl_init($url);

curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => false,
CURLOPT_HEADER => false,
CURLOPT_USERAGENT => $this->userAgent,
CURLOPT_COOKIEFILE => $this->cookieFile,
CURLOPT_REFERER => "https://www.tiktok.com/",
CURLOPT_BUFFERSIZE => self::BUFFER_SIZE
]);

$this->setProxy($ch);

curl_exec($ch);
curl_close($ch);
}
Expand Down Expand Up @@ -64,9 +77,14 @@ public function noWatermark(string $url) {
];

$ch = curl_init('https://api-h2.tiktokv.com/aweme/v1/feed/?' . http_build_query($query));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, UserAgents::DOWNLOAD);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$this->setProxy($ch);

curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERAGENT => $this->userAgent,
CURLOPT_FOLLOWLOCATION => true
]);

$data = curl_exec($ch);
if (!curl_errno($ch)) {
$json = json_decode($data);
Expand Down
10 changes: 0 additions & 10 deletions src/Helpers/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ static public function extractCookies(string $data): array {
return $cookies;
}

static public function handleProxy(&$ch, array $proxy): void {
if (isset($proxy['host'], $proxy['port'])) {
curl_setopt($ch, CURLOPT_PROXY, $proxy['host'] . ":" . $proxy['port']);
if (isset($proxy['username'], $proxy['password'])) {
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy['username'] . ":" . $proxy['password']);
}
curl_setopt($ch, CURLOPT_NOPROXY, '127.0.0.1,localhost');
}
}

/**
* Builds query for TikTok Api
*/
Expand Down
2 changes: 0 additions & 2 deletions src/Interfaces/DownloaderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
namespace TikScraper\Interfaces;

interface DownloaderInterface {
const BUFFER_SIZE = 256 * 1024;

public function watermark(string $payload);
public function noWatermark(string $payload);
}
2 changes: 1 addition & 1 deletion src/Items/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ private function handleFeedZero(string $key): bool {
// Building Feed
$realCursor = $nav->cursor === 0 ? count($items) : $nav->cursor; // Fixes bug that sets cursor to 0 even then there are multiple posts already
$feed = new Feed;
$feed->setMeta(new Response(200, 0, "PLACEHOLDER"));
$feed->setMeta(new Response(200, "PLACEHOLDER"));
$feed->setItems($items);
$feed->setNav($nav->hasMore, 0, $realCursor);

Expand Down
2 changes: 1 addition & 1 deletion src/Items/Video.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function feed(): self {
$response = new Feed;
$response->setItems([$this->item]);
$response->setNav(false, null, '');
$response->setMeta(new Response(true, 200, "PLACEHOLDER"));
$response->setMeta(new Response(200, "PLACEHOLDER"));
$this->feed = $response;
}
return $this;
Expand Down
2 changes: 1 addition & 1 deletion src/Models/Info.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function setStats(object $stats) {
}

public function fromCache(object $cache) {
$this->setMeta(new Response(true, 200, 'PLACEHOLDER'));
$this->setMeta(new Response(200, 'PLACEHOLDER'));
if (isset($cache->meta->og)) {
$this->meta->og = $cache->meta->og;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Models/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ class Response {
public int $code;
public $data;

function __construct(bool $http_success, int $code, $data) {
$this->http_success = $http_success;
function __construct(int $code, $data) {
$this->http_success = $code >= 200 && $code < 400;
$this->code = $code;
$this->data = $data;
}
Expand Down
86 changes: 42 additions & 44 deletions src/Sender.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
use TikScraper\Helpers\Algorithm;
use TikScraper\Helpers\Request;
use TikScraper\Models\Response;
use TikScraper\Traits\ProxyTrait;
use TikScraper\Traits\CookieTrait;

class Sender {
private const REFERER = 'https://www.tiktok.com/';
use ProxyTrait;
use CookieTrait;

private const REFERER = 'https://www.tiktok.com/';
private const DEFAULT_API_HEADERS = [
"authority: m.tiktok.com",
"method: GET",
Expand All @@ -23,25 +27,21 @@ class Sender {
];

private Signer $signer;
private array $proxy = [];
private bool $use_test_endpoints = false;
private string $useragent = UserAgents::DEFAULT;
private string $cookie_file = '';
private bool $testEndpoints = false;
private string $userAgent = UserAgents::DEFAULT;

function __construct(array $config) {
// Signing
if (!isset($config['signer'])) {
throw new \Exception("You need to send a signer config! Please check the README for more info");
}

$signer_config = $config['signer'];
$this->signer = new Signer($config['signer']);
if (isset($config['use_test_endpoints']) && $config['use_test_endpoints']) $this->testEndpoints = true;
$this->userAgent = $config['user_agent'] ?? UserAgents::DEFAULT;

$this->signer = new Signer($signer_config);

$this->proxy = $config['proxy'] ?? [];
if (isset($config['use_test_endpoints']) && $config['use_test_endpoints']) $this->use_test_endpoints = true;
$this->useragent = $config['user_agent'] ?? UserAgents::DEFAULT;
$this->cookie_file = sys_get_temp_dir() . '/tiktok.txt';
$this->initProxy($config['proxy'] ?? []);
$this->initCookies();
}

/**
Expand All @@ -62,14 +62,14 @@ public function sendApi(
string $static_url = ''
): Response {
// Use test subdomain if test endpoints are enabled
if ($this->use_test_endpoints && $subdomain === 'm') {
if ($this->testEndpoints && $subdomain === 'm') {
$subdomain = 't';
}
$headers = [];
$cookies = '';
$ch = curl_init();
$url = 'https://' . $subdomain . '.tiktok.com' . $endpoint;
$useragent = $this->useragent;
$useragent = $this->userAgent;
$device_id = Algorithm::deviceId();

$headers[] = "Path: $endpoint";
Expand All @@ -88,42 +88,44 @@ public function sendApi(
}
} else {
// Signing error
return new Response(false, 500, (object) [
return new Response(500, (object) [
'statusCode' => 20
]);
}

$this->setProxy($ch);
curl_setopt_array($ch, [
CURLOPT_URL => $static_url ? $static_url : $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_COOKIEJAR => $this->cookieFile,
CURLOPT_COOKIEFILE => $this->cookieFile,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_REFERER => self::REFERER,
CURLOPT_AUTOREFERER => true,
CURLOPT_USERAGENT => $useragent,
CURLOPT_ENCODING => 'utf-8',
CURLOPT_AUTOREFERER => true,
CURLOPT_REFERER => self::REFERER,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_CONNECTTIMEOUT => 30,
CURLOPT_TIMEOUT => 30,
CURLOPT_MAXREDIRS => 5,
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4
CURLOPT_MAXREDIRS => 5
]);

if ($cookies) {
curl_setopt($ch, CURLOPT_COOKIE, $cookies);
}

Request::handleProxy($ch, $this->proxy);
$data = curl_exec($ch);
$error = curl_errno($ch);
$code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($data && !$error) {
if (!$error && $data) {
// Request sent
return new Response($code >= 200 && $code < 400, $code, json_decode($data));
return new Response($code, json_decode($data));
}

// Return an error if the request didn't happen (timeouts for example)
return new Response(false, 503, (object) [
// Request went bad (timeouts, empty responses...)
return new Response(503, (object) [
'statusCode' => 10
]);
}
Expand All @@ -141,72 +143,68 @@ public function sendHTML(
): Response {
$ch = curl_init();
$url = 'https://' . $subdomain . '.tiktok.com' . $endpoint;
$useragent = $this->useragent;
// Add query
if (!empty($query)) $url .= '?' . http_build_query($query);
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_COOKIEJAR => $this->cookieFile,
CURLOPT_COOKIEFILE => $this->cookieFile,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => $useragent,
CURLOPT_USERAGENT => $this->userAgent,
CURLOPT_ENCODING => 'utf-8',
CURLOPT_AUTOREFERER => true,
CURLOPT_CONNECTTIMEOUT => 30,
CURLOPT_TIMEOUT => 30,
CURLOPT_MAXREDIRS => 5,
CURLOPT_COOKIEJAR => $this->cookie_file,
CURLOPT_COOKIEFILE => $this->cookie_file,
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4
]);
Request::handleProxy($ch, $this->proxy);
$this->setProxy($ch);
$data = curl_exec($ch);
$error = curl_errno($ch);
$code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if (!$error) {
if (!$error && $data) {
// Request sent
return new Response($code >= 200 && $code < 400, $code, $data);
return new Response($code, $data);
}
return new Response(false, 503, '');
return new Response(503, '');
}

/**
* Sends a GET/HEAD request to TikTok, usually used to get some required cookies/headers for later
* @param $url URL to be used
* @param $headMethod Send a HEAD request if true or a GET request if false
* @param $reqHeaders Optional aditional headers to send
* @return array 'cookies' and 'headers'
*/
public function sendHead(string $url, bool $headMethod = false, array $reqHeaders = []): array {
$headers = [];
public function sendHead(string $url, bool $headMethod = false): array {
$resHeaders = [];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_NOBODY => $headMethod,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => $this->useragent,
CURLOPT_USERAGENT => $this->userAgent,
CURLOPT_ENCODING => 'utf-8',
CURLOPT_AUTOREFERER => true,
CURLOPT_HTTPHEADER => $reqHeaders
CURLOPT_AUTOREFERER => true
]);

curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header) use (&$headers) {
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header) use (&$resHeaders) {
$len = strlen($header);
$header = explode(':', $header, 2);
if (count($header) < 2) return $len;
$headers[strtolower(trim($header[0]))][] = trim($header[1]);
$resHeaders[strtolower(trim($header[0]))][] = trim($header[1]);
return $len;
});

Request::handleProxy($ch, $this->proxy);
$this->setProxy($ch);

$data = curl_exec($ch);
curl_close($ch);
return [
'cookies' => Request::extractCookies($data),
'headers' => $headers
'headers' => $resHeaders
];
}
}
Loading

0 comments on commit 4426ee9

Please sign in to comment.