Compare commits

...

23 Commits

Author SHA1 Message Date
Pablo Ferreiro 6fafcdcd11 Added some icons and bump scraper 2022-10-24 20:38:31 +02:00
Pablo Ferreiro 5e1b009f75 Fixed no watermark download, added settings icon 2022-10-23 21:35:04 +02:00
Pablo Ferreiro 7aa869f567 Download services, scraper bump 2022-09-25 19:53:00 +02:00
Pablo Ferreiro c076ba65a6 Merge pull request #79 from j9d3it/patch-2
Example Redirector config change
2022-09-07 16:15:03 +02:00
j9d3it 2504ba6e93 Example Redirector config change
I changed the example Redirector config to use the new official instance instead of the old Heroku one.
2022-09-06 16:00:00 +09:00
Pablo Ferreiro 38557fafa6 Nicer error display 2022-09-03 14:01:03 +02:00
Pablo Ferreiro 96fb2fd428 Proxy support 2022-09-03 13:21:43 +02:00
Pablo Ferreiro af4d98b8dd Fixed rss item link 2022-09-03 12:59:36 +02:00
Pablo Ferreiro 40e5d45956 Merge pull request #71 from NoPlagiarism/vm_t_support
vt.tiktok.com + tiktok.com/t support in TikTok URL option
2022-09-03 00:17:03 +02:00
Pablo Ferreiro 2f20cf8c02 updated wrapper 2022-08-17 14:47:32 +02:00
NoPlagiarism aa2fff2b31 www, http, + /t/ fix 2022-08-16 03:03:48 +05:00
NoPlagiarism fbc9061b21 vt.tiktok.com + tiktok.com/t support 2022-08-16 02:30:08 +05:00
Pablo Ferreiro 67c080e5f4 Funding 2022-08-13 14:47:29 +02:00
Pablo Ferreiro 086c95ca71 Added public instance template 2022-08-13 13:32:46 +02:00
Pablo Ferreiro 931191bcaf Added issue templates 2022-08-13 13:28:16 +02:00
Pablo Ferreiro ebe5941fa2 temp favicon, updated scrapper and .env changes 2022-08-13 13:09:39 +02:00
Pablo Ferreiro 574ae51582 bump 2022-08-11 23:34:16 +02:00
Pablo Ferreiro 90a2d2ec28 Updated TikScrapper 2022-08-11 23:33:16 +02:00
Pablo Ferreiro 3880da35ea Merge pull request #63 from chrisnovakovic/tiktok-url
Accept TikTok URLs as search terms
2022-08-04 14:04:04 +02:00
Chris Novakovic 8d8fe43431 Add type declarations, fix function reference 2022-07-31 17:20:38 +01:00
Chris Novakovic e7ee03e3cc Accept TikTok URLs as search terms
On the home page, allow TikTok URLs to be entered as search terms for
the new category "TikTok URL", and redirect to a ProxiTok-compatible
URL when a valid one is entered.

Closes #58.
2022-07-27 00:49:14 +01:00
Pablo Ferreiro d0057e77e3 Fixing error message 2022-07-03 18:35:30 +02:00
Pablo Ferreiro d52dc8687f Some anti-crash fixes 2022-07-03 18:19:10 +02:00
61 changed files with 506 additions and 180 deletions
+9 -3
View File
@@ -2,9 +2,9 @@
# LATTE_CACHE=/tmp/proxitok_api # Path for Latte cache, leave commented for ./cache/latte
# API CONFIG
# API_SIGNER_URL="https://example.com" # External signing service
# API_BROWSER_URL="http://localhost:4444" # chromedriver url
# API_TEST_ENDPOINTS=true # Discomment for usage of testing TikTok endpoints, may help sometimes
# API_SIGNER="remote"
# API_SIGNER_URL="http://localhost:8080"
# API_TEST_ENDPOINTS=true # Uncomment for usage of testing TikTok endpoints, may help sometimes
# API_CACHE=redis
# Redis cache, used on Helpers\CacheEngines\RedisCache (CHOOSE ONE)
@@ -14,3 +14,9 @@
# JSON cache, used on Helpers\CacheEngines\JSONCache
# API_CACHE_JSON=/tmp/proxitok_api # Path for JSON API Cache, leave commented for ./cache/api
# Proxy Config
# PROXY_HOST=http://EXAMPLE_IP # Host to be used as proxy, make sure to type a valid protocol. Available: http:// | https:// | socks4:// | socks5://
# PROXY_PORT=8080
# PROXY_USERNAME=username
# PROXY_PASSWORD=password
+2
View File
@@ -0,0 +1,2 @@
liberapay: 'pablouser1'
custom: 'https://paypal.me/pablouser1'
+12
View File
@@ -0,0 +1,12 @@
---
name: Add my instance
about: Add public instance to the list
title: "[INSTANCES] New public instance"
labels: ''
assignees: ''
---
- URL: https://proxitok.example.com
- Cloudflare: Yes / No
- Country: Type the name of the country you are hosting the instance here
+35
View File
@@ -0,0 +1,35 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: pablouser1
---
Before submitting an issue, please make sure you are using the latest version of ProxiTok.
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Logs**
If applicable, add PHP logs to help explain the issue.
**Enviroment (please complete the following information):**
- Deployment method (if possible): [e.g docker, heroku, manual...]
- Frontend version: [e.g. 2.2.0.0]
- Scrapper version: [e.g. 2.4.0.0]
- PHP Version: [e.g. 8.0]
You can find the frontend and scrapper version on /about
+17
View File
@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
+1 -1
View File
@@ -1,4 +1,4 @@
FROM php:8-apache
FROM php:8.1-apache
WORKDIR /var/www/html
COPY --from=composer /usr/bin/composer /usr/bin/composer
RUN apt update -y && apt upgrade -y \
+1 -1
View File
@@ -1 +1 @@
web: vendor/bin/heroku-php-nginx -C setup/nginx_heroku.conf
web: vendor/bin/heroku-php-nginx -C setup/heroku/nginx.conf
+4 -3
View File
@@ -21,18 +21,19 @@ If you want to automatically redirect Tiktok links to ProxiTok you can use:
* [Libredirect](https://github.com/libredirect/libredirect)
* [Redirector](https://github.com/einaregilsson/Redirector)
You can use the following config if you want to use Redirector (you can change https://proxitok.herokuapp.com with whatever instance you want to use):
You can use the following config if you want to use Redirector (you can change https://proxitok.pabloferreiro.es with whatever instance you want to use):
```
Description: TikTok to ProxiTok
Example URL: https://www.tiktok.com/@tiktok
Include pattern: (.*//.*)(tiktok.com)(.*)
Redirect to: https://proxitok.herokuapp.com$3
Example result: https://proxitok.herokuapp.com/@tiktok
Redirect to: https://proxitok.pabloferreiro.es$3
Example result: https://proxitok.pabloferreiro.es/@tiktok
Pattern type: Regular Expression
Apply to: Main window (address bar)
```
## TODO / Known issues
* Replace placeholder favicon
* Make video on /video fit screen and don't overflow
* Fix embed styling
* Fix crash when invalid vm.tiktok.com/CODE or www.tiktok.com/t/CODE is provided
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

+4 -2
View File
@@ -1,7 +1,9 @@
<?php
namespace App\Cache;
class JSONCache {
use TikScraper\Interfaces\CacheInterface;
class JSONCache implements CacheInterface {
private string $cache_path = __DIR__ . '/../../cache/api';
function __construct() {
@@ -24,7 +26,7 @@ class JSONCache {
return is_file($filename);
}
public function set(string $cache_key, mixed $data, $timeout = 3600) {
public function set(string $cache_key, string $data, $timeout = 3600) {
file_put_contents($this->cache_path . '/' . $cache_key . '.json', $data);
}
}
+4 -5
View File
@@ -1,7 +1,9 @@
<?php
namespace App\Cache;
class RedisCache {
use TikScraper\Interfaces\CacheInterface;
class RedisCache implements CacheInterface {
private \Redis $client;
function __construct(string $host, int $port, ?string $password) {
$this->client = new \Redis();
@@ -21,10 +23,7 @@ class RedisCache {
public function get(string $cache_key): ?object {
$data = $this->client->get($cache_key);
if ($data) {
return json_decode($data);
}
return null;
return $data ? json_decode($data) : null;
}
public function exists(string $cache_key): bool {
+7
View File
@@ -0,0 +1,7 @@
<?php
namespace App\Constants;
class CacheMethods {
const JSON = 'json';
const REDIS = 'redis';
}
+7
View File
@@ -0,0 +1,7 @@
<?php
namespace App\Constants;
abstract class Themes {
const DEFAULT = "default";
const CARD = "card";
}
+1 -1
View File
@@ -14,7 +14,7 @@ class DiscoverController {
$latte = Wrappers::latte();
$latte->render(Misc::getView('discover'), new FeedTemplate('Discover', $feed));
} else {
ErrorHandler::show($feed->meta);
ErrorHandler::showMeta($feed->meta);
}
}
}
+6 -4
View File
@@ -9,12 +9,14 @@ use App\Models\VideoTemplate;
class EmbedController {
static public function v2(int $id) {
$api = Wrappers::api();
$feed = $api->getVideoByID($id);
if ($feed->meta->success) {
$video = $api->video($id);
$video->feed();
if ($video->ok()) {
$data = $video->getFull();
$latte = Wrappers::latte();
$latte->render(Misc::getView('video'), new VideoTemplate($feed->items[0], $feed->info->detail, true));
$latte->render(Misc::getView('video'), new VideoTemplate($data->feed->items[0], $data->info->detail, true));
} else {
ErrorHandler::show($feed->meta);
ErrorHandler::showMeta($video->error());
}
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ class MusicController {
$latte = Wrappers::latte();
$latte->render(Misc::getView('music'), new FullTemplate('Music', $data));
} else {
ErrorHandler::show($music->error());
ErrorHandler::showMeta($music->error());
}
}
}
+17 -17
View File
@@ -1,6 +1,9 @@
<?php
namespace App\Controllers;
use App\Helpers\Cookies;
use TikScraper\Helpers\Converter;
class ProxyController {
const VALID_TIKTOK_DOMAINS = [
"tiktokcdn.com", "tiktokcdn-us.com", "tiktok.com"
@@ -30,11 +33,9 @@ class ProxyController {
}
static private function getFileName(): string {
$filename = 'tiktok-video';
if (isset($_GET['user'])) {
$filename .= '-' . $_GET['user'] . '-' . $_GET['id'];
}
static private function getFilename(string $url, string $user): string {
$id = Converter::urlToId($url);
$filename = 'tiktok-video-' . $id . '-' . $user;
return $filename;
}
@@ -46,18 +47,17 @@ class ProxyController {
}
static public function download() {
$downloader = new \TikScraper\Download();
self::checkUrl();
$method = Cookies::downloader();
$downloader = new \TikScraper\Download($method);
// Params
$watermark = isset($_GET['watermark']);
if ($watermark) {
self::checkUrl();
$filename = self::getFileName();
$downloader->url($_GET['url'], $filename, true);
} else {
if (!isset($_GET['id'])) {
die('You need to send an ID!');
}
$filename = self::getFileName();
$downloader->url($_GET['id'], $filename, false);
}
$url = $_GET['url'];
$user = $_GET['user'] ?? '';
// Filename
$filename = self::getFilename($url, $user);
// Running
$downloader->url($_GET['url'], $filename, $watermark);
}
}
+38 -1
View File
@@ -1,5 +1,6 @@
<?php
namespace App\Controllers;
use App\Helpers\ErrorHandler;
use App\Helpers\Misc;
/**
@@ -9,8 +10,15 @@ class RedirectController {
static public function redirect() {
$endpoint = '/';
if (isset($_GET['type'], $_GET['term'])) {
$term = trim($_GET['term']);
$term = urlencode(trim($_GET['term']));
switch ($_GET['type']) {
case 'url':
$endpoint = self::to_endpoint($term);
if (!$endpoint) {
ErrorHandler::showText(400, 'Invalid TikTok URL');
return;
}
break;
case 'user':
// Remove @ if sent
if ($term[0] === '@') {
@@ -39,4 +47,33 @@ class RedirectController {
$url = Misc::url($endpoint);
header("Location: {$url}");
}
/**
* to_endpoint maps a TikTok URL into a ProxiTok-compatible endpoint URL.
*/
static private function to_endpoint(string $url): string {
if (preg_match('%^(?:https?://|www\.)?(?:vm\.|vt\.)?tiktok\.com/(?:t/)?([A-Za-z0-9]+)%', $url, $m)) {
// Short video URL
return '/@placeholder/video/' . $m[1];
} elseif (preg_match('%^https://www\.tiktok\.com/(.+)%', $url, $m)) {
// Username component (which may indicate a user profile URL or a video URL)
if (preg_match('%^(@[A-Za-z0-9_.]+)(?:/|$)(.*)%', $m[1], $u)) {
if ($u[2] == '') {
// User profile URL
return '/' . $u[1];
} elseif (preg_match('%^video/(\d+)%', $u[2], $v)) {
// Video URL
return '/' . $u[1] . '/video/' . $v[1];
}
} elseif (preg_match('%^tag/([^ ]+?)(?:/|$)%', $m[1], $t)) {
// Tag URL
return '/tag/' . $t[1];
} elseif (preg_match('%^music/([^ ]+?)(?:/|$)%', $m[1], $m)) {
// Music URL
return '/music/' . $m[1];
}
}
return '';
}
}
+7 -2
View File
@@ -4,12 +4,12 @@ namespace App\Controllers;
use App\Helpers\Misc;
use App\Helpers\Cookies;
use App\Helpers\Wrappers;
use App\Models\BaseTemplate;
use App\Models\SettingsTemplate;
class SettingsController {
static public function index() {
$latte = Wrappers::latte();
$latte->render(Misc::getView('settings'), new BaseTemplate('Settings'));
$latte->render(Misc::getView('settings'), new SettingsTemplate());
}
static public function general() {
@@ -25,6 +25,11 @@ class SettingsController {
$test_endpoints = $_POST['api-test_endpoints'];
Cookies::set('api-test_endpoints', $test_endpoints);
}
if (isset($_POST['api-downloader'])) {
$downloader = $_POST['api-downloader'];
Cookies::set("api-downloader", $downloader);
}
self::redirect();
}
+2 -2
View File
@@ -16,9 +16,9 @@ class TagController {
if ($hashtag->ok()) {
$data = $hashtag->getFull();
$latte = Wrappers::latte();
$latte->render(Misc::getView('tag'), new FullTemplate('Tag', $data));
$latte->render(Misc::getView('tag'), new FullTemplate($data->info->detail->title, $data));
} else {
ErrorHandler::show($hashtag->error());
ErrorHandler::showMeta($hashtag->error());
}
}
+1 -1
View File
@@ -20,7 +20,7 @@ class TrendingController {
$latte = Wrappers::latte();
$latte->render(Misc::getView('trending'), new FeedTemplate('Trending', $feed));
} else {
ErrorHandler::show($trending->error());
ErrorHandler::showMeta($trending->error());
}
}
+4 -5
View File
@@ -17,14 +17,13 @@ class UserController {
if ($user->ok()) {
$data = $user->getFull();
if ($data->info->detail->privateAccount) {
http_response_code(403);
echo 'Private account detected! Not supported';
exit;
ErrorHandler::showText(401, "Private account detected! Not supported");
return;
}
$latte = Wrappers::latte();
$latte->render(Misc::getView('user'), new FullTemplate($data->info->detail->nickname, $data));
} else {
ErrorHandler::show($user->error());
ErrorHandler::showMeta($user->error());
}
}
@@ -37,7 +36,7 @@ class UserController {
$latte = Wrappers::latte();
$latte->render(Misc::getView('video'), new VideoTemplate($data->feed->items[0], $data->info->detail));
} else {
ErrorHandler::show($video->error());
ErrorHandler::showMeta($video->error());
}
}
+10 -3
View File
@@ -1,9 +1,9 @@
<?php
namespace App\Helpers;
class Cookies {
const ALLOWED_THEMES = ['default', 'card'];
use App\Constants\Themes;
class Cookies {
static public function get(string $name, string $default_value = ''): string {
if (isset($_COOKIE[$name]) && !empty($_COOKIE[$name])) {
return $_COOKIE[$name];
@@ -13,12 +13,19 @@ class Cookies {
static public function theme(): string {
$theme = self::get('theme');
if ($theme && in_array($theme, self::ALLOWED_THEMES)) {
$ref = new \ReflectionClass(Themes::class);
$themes = $ref->getConstants();
if ($theme && in_array($theme, $themes)) {
return $theme;
}
return 'default';
}
static public function downloader(): string {
$downloader = self::get('api-downloader', 'default');
return $downloader;
}
static public function exists(string $name): bool {
return isset($_COOKIE[$name]);
}
+8 -2
View File
@@ -5,9 +5,15 @@ use App\Models\ErrorTemplate;
use TikScraper\Models\Meta;
class ErrorHandler {
static public function show(Meta $meta) {
static public function showMeta(Meta $meta) {
http_response_code($meta->http_code);
$latte = Wrappers::latte();
$latte->render(Misc::getView('error'), new ErrorTemplate($meta));
$latte->render(Misc::getView('error'), new ErrorTemplate($meta->http_code, $meta->tiktok_msg, $meta->tiktok_code));
}
static public function showText(int $code, string $msg) {
http_response_code($code);
$latte = Wrappers::latte();
$latte->render(Misc::getView('error'), new ErrorTemplate($code, $msg));
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace App\Helpers;
class UrlBuilder {
static public function stream(string $url): string {
return Misc::url('/stream?url=' . urlencode($url));
}
static public function download(string $url, string $username, bool $watermark): string {
// {path('/download?url=' . urlencode($playAddr) . '&id=' . $id . '&user=' . $uniqueId) . '&watermark=1'}
$down_url = Misc::url('/download?url=' . urlencode($url) . '&user=' . $username);
if ($watermark) $down_url .= '&watermark=1';
return $down_url;
}
static public function user(string $username): string {
return Misc::url('/@' . $username);
}
static public function video_internal(string $username, string $id): string {
return Misc::url('/@' . $username . "/video/" . $id);
}
static public function video_external(string $username, string $id): string {
return "https://www.tiktok.com/@" . $username . "/video/" . $id;
}
}
+50 -5
View File
@@ -3,6 +3,7 @@ namespace App\Helpers;
use App\Cache\JSONCache;
use App\Cache\RedisCache;
use App\Constants\CacheMethods;
class Wrappers {
/**
@@ -28,6 +29,23 @@ class Wrappers {
$latte->addFunction('theme', function(): string {
return Cookies::theme();
});
// UrlBuilder
$latte->addFunction('url_stream', function (string $url): string {
return UrlBuilder::stream($url);
});
$latte->addFunction('url_user', function (string $username): string {
return UrlBuilder::user($username);
});
$latte->addFunction('url_video_internal', function (string $username, string $id): string {
return UrlBuilder::video_internal($username, $id);
});
$latte->addFunction('url_video_external', function (string $username, string $id): string {
return UrlBuilder::video_external($username, $id);
});
$latte->addFunction('url_download', function (string $url, string $username, bool $watermark): string {
return UrlBuilder::download($url, $username, $watermark);
});
// https://stackoverflow.com/a/36365553
$latte->addFunction('number', function (float $x) {
if($x > 1000) {
@@ -49,22 +67,49 @@ class Wrappers {
* Setup of TikTok Api wrapper
*/
static public function api(): \TikScraper\Api {
$method = Misc::env('API_SIGNER', '');
$url = Misc::env('API_SIGNER_URL', '');
if (!$method) {
// Legacy support
$browser_url = Misc::env('API_BROWSER_URL', '');
if ($url) {
$method = 'remote';
} elseif ($browser_url) {
$url = $browser_url;
$method = 'browser';
}
}
$options = [
'use_test_endpoints' => Misc::env('API_TEST_ENDPOINTS', false) || isset($_COOKIE['api-test_endpoints']) && $_COOKIE['api-test_endpoints'] === 'yes',
'signer' => [
'remote_url' => Misc::env('API_SIGNER_URL', ''),
'browser_url' => Misc::env('API_BROWSER_URL', ''),
'method' => $method,
'url' => $url,
'close_when_done' => false
]
];
// -- PROXY CONFIG -- //
$proxy_host = Misc::env('PROXY_HOST', '');
$proxy_port = Misc::env('PROXY_PORT', '');
if ($proxy_host && $proxy_port) {
$options['proxy'] = [
'host' => $proxy_host,
'port' => $proxy_port,
'username' => Misc::env('PROXY_USERNAME', null),
'password' => Misc::env('PROXY_PASSWORD', null)
];
}
// Cache config
$cacheEngine = false;
$cacheEngine = null;
if (isset($_ENV['API_CACHE'])) {
switch ($_ENV['API_CACHE']) {
case 'json':
case CacheMethods::JSON:
$cacheEngine = new JSONCache();
break;
case 'redis':
case CacheMethods::REDIS:
if (!(isset($_ENV['REDIS_URL']) || isset($_ENV['REDIS_HOST'], $_ENV['REDIS_PORT']))) {
throw new \Exception('You need to set REDIS_URL or REDIS_HOST and REDIS_PORT to use Redis Cache!');
}
+8 -5
View File
@@ -1,13 +1,16 @@
<?php
namespace App\Models;
use TikScraper\Models\Meta;
class ErrorTemplate extends BaseTemplate {
public Meta $error;
public int $http_code = 502;
public ?int $tiktok_code = -1;
public string $msg = '';
function __construct(object $error) {
function __construct(int $http_code, string $msg, ?int $tiktok_code = null) {
parent::__construct('Error');
$this->error = $error;
$this->http_code = $http_code;
$this->msg = $msg;
$this->tiktok_code = $tiktok_code;
}
}
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace App\Models;
use App\Constants\Themes;
use App\Helpers\Cookies;
use TikScraper\Constants\DownloadMethods;
/**
* Base for templates with a feed
*/
class SettingsTemplate extends BaseTemplate {
public array $downloaders = [];
public array $themes = [];
public bool $isTestEndpoints = false;
public string $currentDownloader;
public string $currentTheme;
function __construct() {
parent::__construct("Settings");
// Downloaders list
$ref = new \ReflectionClass(DownloadMethods::class);
$this->downloaders = $ref->getConstants();
// Themes list
$ref = new \ReflectionClass(Themes::class);
$this->themes = $ref->getConstants();
// Cookies data
$this->isTestEndpoints = Cookies::check('api-test_endpoints', 'yes');
$this->currentDownloader = Cookies::downloader();
$this->currentTheme = Cookies::theme();
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

+4
View File
@@ -2,6 +2,10 @@
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="apple-touch-icon" sizes="180x180" href="{path('/apple-touch-icon.png')}">
<link rel="icon" type="image/png" sizes="32x32" href="{path('/favicon-32x32.png')}">
<link rel="icon" type="image/png" sizes="16x16" href="{path('/favicon-16x16.png')}">
<link rel="manifest" href="{path('/site.webmanifest')}">
<meta property="og:title" content="ProxiTok" />
<meta property="og:description" content="Alternative frontend for TikTok" />
<meta property="og:type" content="website" />
+10 -3
View File
@@ -1,5 +1,8 @@
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a href="{path('/')}" class="navbar-item">
{include './icon.latte', icon: 'home', text: 'ProxiTok'}
</a>
<a role="button" id="navbar-burger" class="navbar-burger" aria-label="menu" aria-expanded="false">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
@@ -9,14 +12,18 @@
<div id="navbar-menu" class="navbar-menu">
<div class="navbar-start">
<a href="{path('/')}" class="navbar-item">
{include './icon.latte', icon: 'home', text: 'Home'}
<a href="{path('/settings')}" class="navbar-item">
{include './icon.latte', icon: 'options', text: 'Settings'}
</a>
<a href="{path('/settings')}" class="navbar-item">Settings</a>
<a href="{path('/about')}" class="navbar-item">
{include './icon.latte', icon: 'info', text: 'About'}
</a>
</div>
<div class="navbar-end">
<a href="https://github.com/pablouser1/ProxiTok" class="navbar-item" target="_blank">
{include './icon.latte', icon: 'code-slash', text: 'Source'}
</a>
</div>
</div>
</nav>
<script src="{path('/scripts/navbar.js')}"></script>
+15 -3
View File
@@ -1,19 +1,31 @@
{embed '../form.latte', path: '/settings/api', method: 'POST', submit: true}
{block fields}
{var $use_endpoints = \App\Helpers\Cookies::check('api-test_endpoints', 'yes')}
<div class="field">
<label class="label">Use test endpoints</label>
<div class="control">
<label class="radio">
<input type="radio" name="api-test_endpoints" value="yes" n:attr="checked => $use_endpoints" />
<input type="radio" name="api-test_endpoints" value="yes" n:attr="checked => $isTestEndpoints" />
<span>Yes</span>
</label>
<label class="radio">
<input type="radio" name="api-test_endpoints" value="no" n:attr="checked => !$use_endpoints" />
<input type="radio" name="api-test_endpoints" value="no" n:attr="checked => !$isTestEndpoints" />
<span>No</span>
</label>
</div>
<p class="help">This <i>may</i> help bypass rate limits</p>
</div>
<div class="field">
<label class="label">Downloader</label>
<div class="control">
<div class="select">
<select name="api-downloader">
{foreach $downloaders as $downloader}
<option value="{$downloader}" n:attr="selected => $currentDownloader === $downloader">{$downloader|firstUpper}</option>
{/foreach}
</select>
</div>
</div>
<p class="help">Watermark downloads will <i>not</i> use third party methods</p>
</div>
{/block}
{/embed}
+9 -7
View File
@@ -2,13 +2,15 @@
{block fields}
<div class="field">
<label class="label">Theme</label>
<div class="select">
<select name="theme">
<option hidden disabled selected value> -- Select an option -- </option>
<option value="default">Default</option>
<option value="card">Card</option>
</select>
<div class="control">
<div class="select">
<select name="theme">
{foreach $themes as $theme}
<option value="{$theme}" n:attr="selected => $currentTheme === $theme">{$theme|firstUpper}</option>
{/foreach}
</select>
</div>
</div>
</div>
</div>
{/block}
{/embed}
+7 -7
View File
@@ -3,18 +3,18 @@
<section class="section">
<div class="columns is-multiline is-vcentered">
{foreach $data->feed->items as $item}
{do $share_url = 'https://tiktok.com/@' . $item->author->uniqueId . '/video/' . $item->id}
{do $share_url = url_video_external($item->author->uniqueId, $item->id)}
<div class="column is-one-quarter clickable-img" id="{$item->id}" onclick="openVideo(this.id)"
data-video_url="{path('/stream?url=' . urlencode($item->video->playAddr))}"
data-video_download_watermark="{path('/download?url=' . urlencode($item->video->playAddr) . '&id=' . $item->id . '&user=' . $item->author->uniqueId) . '&watermark='}"
data-video_download_nowatermark="{path('/download?id=' . $item->id . '&user=' . $item->author->uniqueId)}"
data-video_url="{url_stream($item->video->playAddr)}"
data-video_download_watermark="{url_download($item->video->playAddr, $item->author->uniqueId, true)}"
data-video_download_nowatermark="{url_download($item->video->playAddr, $item->author->uniqueId, false)}"
data-video_share_url="{$share_url}"
data-desc="{$item->desc}"
data-createtime="{$item->createTime}"
data-music_title="{$item->music->title}"
data-music_url="{path('/stream?url=' . urlencode($item->music->playUrl))}">
<img loading="lazy" src="{path('/stream?url=' . urlencode($item->video->originCover))}" />
<img class="hidden" loading="lazy" data-src="{path('/stream?url=' . urlencode($item->video->dynamicCover))}" />
data-music_url="{url_stream($item->music->playUrl)}">
<img loading="lazy" src="{url_stream($item->video->originCover)}" />
<img class="hidden" loading="lazy" data-src="{url_stream($item->video->dynamicCover)}" />
</div>
{/foreach}
{if empty($data->feed->items)}
+2 -2
View File
@@ -6,8 +6,8 @@
</div>
<div class="dropdown-menu" role="menu">
<div class="dropdown-content">
<a target="_blank" href="{path('/download?url=' . urlencode($playAddr) . '&id=' . $id . '&user=' . $uniqueId) . '&watermark=1'}" class="dropdown-item">Watermark</a>
<a target="_blank" href="{path('/download?id=' . $id . '&user=' . $uniqueId)}" class="dropdown-item">No watermark</a>
<a target="_blank" href="{url_download($playAddr, $uniqueId, true)}" class="dropdown-item">Watermark</a>
<a target="_blank" href="{url_download(url_video_external($uniqueId, $id), $uniqueId, false)}" class="dropdown-item">No watermark</a>
</div>
</div>
</div>
+2 -2
View File
@@ -1,5 +1,5 @@
{do $endpoint = '/@' . $uniqueId . '/video/' . $id}
<div class="buttons is-centered">
<a class="button is-success is-small" href="{path($endpoint)}">Instance Link</a>
<a class="button is-danger is-small" href="https://www.tiktok.com{$endpoint}">Original Link</a>
<a class="button is-success is-small" href="{url_video_internal($uniqueId, $id)}">Instance Link</a>
<a class="button is-danger is-small" href="{url_video_external($uniqueId, $id)}">Original Link</a>
</div>
+15 -17
View File
@@ -3,27 +3,25 @@
<article class="media">
<figure class="media-left">
<p class="image is-64x64">
<img src="{path('/stream?url=' . urlencode($item->author->avatarThumb))}" />
<img src="{url_stream($item->author->avatarThumb)}" />
</p>
</figure>
<div class="media-content">
<div class="content">
<p>
<strong>{$item->author->nickname}</strong>
<small>
<a href="{path('/@' . $item->author->uniqueId)}">@{$item->author->uniqueId}</a>
</small>
<small title="{date('M d, Y H:i:s e', $item->createTime)}">{date('M d, Y', $item->createTime)}</small>
</p>
{if !empty($item->challenges)}
<p>{include './common/tags.latte', challenges: $item->challenges}</p>
{/if}
<p n:ifcontent>{$item->desc}</p>
{include './common/stats.latte', playCount: $item->stats->playCount, diggCount: $item->stats->diggCount, commentCount: $item->stats->commentCount, shareCount: $item->stats->shareCount}
</div>
<p>
<strong>{$item->author->nickname}</strong>
<small>
<a href="{url_user($item->author->uniqueId)}">@{$item->author->uniqueId}</a>
</small>
<small title="{date('M d, Y H:i:s e', $item->createTime)}">{date('M d, Y', $item->createTime)}</small>
</p>
{if !empty($item->challenges)}
<p>{include './common/tags.latte', challenges: $item->challenges}</p>
{/if}
<p n:ifcontent>{$item->desc}</p>
{include './common/stats.latte', playCount: $item->stats->playCount, diggCount: $item->stats->diggCount, commentCount: $item->stats->commentCount, shareCount: $item->stats->shareCount}
<div class="has-text-centered">
<video width="{$item->video->width}" height="{$item->video->height}" controls preload="none" poster="{path('/stream?url=' . urlencode($item->video->originCover))}">
<source src="{path('/stream?url=' . $item->video->playAddr)}" type="video/mp4" />
<video width="{$item->video->width}" height="{$item->video->height}" controls preload="none" poster="{url_stream($item->video->originCover)}">
<source src="{url_stream($item->video->playAddr)}" type="video/mp4" />
</video>
</div>
<div class="has-text-centered">
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "pablouser1/proxitok",
"description": "An alternative frontend for TikTok",
"version": "2.3.2.0",
"version": "2.4.2.3",
"license": "AGPL-3.0-or-later",
"type": "project",
"authors": [
@@ -24,7 +24,7 @@
"latte/latte": "^2.11",
"bramus/router": "^1.6",
"josegonzalez/dotenv": "dev-master",
"pablouser1/tikscraper": "^2.1"
"pablouser1/tikscraper": "^2.3"
},
"autoload": {
"psr-4": {
Generated
+24 -21
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "5c6b3247dd4d2f94f65a47d2eb39717a",
"content-hash": "0b40437551f24ae25f01113a85564867",
"packages": [
{
"name": "bramus/router",
@@ -263,26 +263,28 @@
},
{
"name": "pablouser1/tikscraper",
"version": "v2.1.0.2",
"version": "v2.3.2.0",
"source": {
"type": "git",
"url": "https://github.com/pablouser1/TikScraperPHP.git",
"reference": "1d330412c4767e3e4f9131ff54ccde18e60407c5"
"reference": "4b3c5952e1f9e126e2e1c80d006e70e759338c45"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pablouser1/TikScraperPHP/zipball/1d330412c4767e3e4f9131ff54ccde18e60407c5",
"reference": "1d330412c4767e3e4f9131ff54ccde18e60407c5",
"url": "https://api.github.com/repos/pablouser1/TikScraperPHP/zipball/4b3c5952e1f9e126e2e1c80d006e70e759338c45",
"reference": "4b3c5952e1f9e126e2e1c80d006e70e759338c45",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-json": "*",
"ext-xml": "*",
"php": ">=7.4|^8.0",
"php-webdriver/webdriver": "^1.12",
"sapistudio/seleniumstealth": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
"pestphp/pest": "^1.22"
},
"type": "library",
"autoload": {
@@ -296,28 +298,29 @@
],
"authors": [
{
"name": "Pablo Ferreiro"
"name": "Pablo Ferreiro",
"homepage": "https://pabloferreiro.es"
}
],
"description": "Get data from TikTok API",
"support": {
"issues": "https://github.com/pablouser1/TikScraperPHP/issues",
"source": "https://github.com/pablouser1/TikScraperPHP/tree/v2.1.0.2"
"source": "https://github.com/pablouser1/TikScraperPHP/tree/v2.3.2.0"
},
"time": "2022-06-16T09:17:37+00:00"
"time": "2022-10-24T18:36:21+00:00"
},
{
"name": "php-webdriver/webdriver",
"version": "1.12.1",
"version": "1.13.1",
"source": {
"type": "git",
"url": "https://github.com/php-webdriver/php-webdriver.git",
"reference": "b27ddf458d273c7d4602106fcaf978aa0b7fe15a"
"reference": "6dfe5f814b796c1b5748850aa19f781b9274c36c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/b27ddf458d273c7d4602106fcaf978aa0b7fe15a",
"reference": "b27ddf458d273c7d4602106fcaf978aa0b7fe15a",
"url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/6dfe5f814b796c1b5748850aa19f781b9274c36c",
"reference": "6dfe5f814b796c1b5748850aa19f781b9274c36c",
"shasum": ""
},
"require": {
@@ -367,9 +370,9 @@
],
"support": {
"issues": "https://github.com/php-webdriver/php-webdriver/issues",
"source": "https://github.com/php-webdriver/php-webdriver/tree/1.12.1"
"source": "https://github.com/php-webdriver/php-webdriver/tree/1.13.1"
},
"time": "2022-05-03T12:16:34+00:00"
"time": "2022-10-11T11:49:44+00:00"
},
{
"name": "sapistudio/seleniumstealth",
@@ -569,16 +572,16 @@
},
{
"name": "symfony/process",
"version": "v5.4.8",
"version": "v5.4.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "597f3fff8e3e91836bb0bd38f5718b56ddbde2f3"
"reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/597f3fff8e3e91836bb0bd38f5718b56ddbde2f3",
"reference": "597f3fff8e3e91836bb0bd38f5718b56ddbde2f3",
"url": "https://api.github.com/repos/symfony/process/zipball/6e75fe6874cbc7e4773d049616ab450eff537bf1",
"reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1",
"shasum": ""
},
"require": {
@@ -611,7 +614,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v5.4.8"
"source": "https://github.com/symfony/process/tree/v5.4.11"
},
"funding": [
{
@@ -627,7 +630,7 @@
"type": "tidelift"
}
],
"time": "2022-04-08T05:07:18+00:00"
"time": "2022-06-27T16:58:25+00:00"
}
],
"packages-dev": [],
+1
View File
@@ -11,6 +11,7 @@ services:
- API_CACHE=redis
- REDIS_HOST=proxitok-redis
- REDIS_PORT=6379
- API_SIGNER=remote
- API_SIGNER_URL=http://proxitok-signer:8080/signature
volumes:
- proxitok-cache:/cache
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+6
View File
@@ -1,9 +1,15 @@
<?php
/** @var \Bramus\Router\Router $router */
use App\Helpers\ErrorHandler;
use App\Helpers\Misc;
use App\Helpers\Wrappers;
use App\Models\BaseTemplate;
$router->set404(function () {
ErrorHandler::showText(404, "That endpoint doesn't exist");
});
$router->get('/', function () {
$latte = Wrappers::latte();
$latte->render(Misc::getView('home'), new BaseTemplate('Home'));
+3 -3
View File
@@ -1,11 +1,11 @@
This facilities making the bulma.min.css and fontawesome.min.css files, install all dependencies using:
This facilities making the compressed bulma.min.css and cssgg.min.css files, install all dependencies using:
```
yarn install
```
And then use:
```
yarn bulma && yarn fa
yarn bulma && yarn cssgg
```
This compiles bulma.scss and fontawesome.scss to a css file and helps lowering the size of the css that will be sent to the user.
This compiles bulma.scss and cssgg.scss to a css file and helps lowering the size of the css that will be sent to the user.
+2
View File
@@ -10,8 +10,10 @@ $bulmaswatch-import-font: false;
@import "./node_modules/bulma/sass/base/_all.sass";
// Elements
@import "./node_modules/bulma/sass/elements/box.sass";
@import "./node_modules/bulma/sass/elements/button.sass";
@import "./node_modules/bulma/sass/elements/container.sass";
@import "./node_modules/bulma/sass/elements/content.sass";
@import "./node_modules/bulma/sass/elements/icon.sass";
@import "./node_modules/bulma/sass/elements/image.sass";
@import "./node_modules/bulma/sass/elements/other.sass";
+5
View File
@@ -1,7 +1,9 @@
@charset "utf-8";
// Common
@import "./node_modules/css.gg/icons/scss/home.scss";
@import "./node_modules/css.gg/icons/scss/options.scss";
@import "./node_modules/css.gg/icons/scss/info.scss";
@import "./node_modules/css.gg/icons/scss/code-slash.scss";
// Home
@import "./node_modules/css.gg/icons/scss/search.scss";
@@ -13,3 +15,6 @@
@import "./node_modules/css.gg/icons/scss/comment.scss";
@import "./node_modules/css.gg/icons/scss/share.scss";
@import "./node_modules/css.gg/icons/scss/software-download.scss";
// Video
@import "./node_modules/css.gg/icons/scss/music.scss";
+3 -3
View File
@@ -118,9 +118,9 @@ readdirp@~3.6.0:
picomatch "^2.2.1"
sass@^1.46.0:
version "1.53.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.53.0.tgz#eab73a7baac045cc57ddc1d1ff501ad2659952eb"
integrity sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==
version "1.55.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.55.0.tgz#0c4d3c293cfe8f8a2e8d3b666e1cf1bff8065d1c"
integrity sha512-Pk+PMy7OGLs9WaxZGJMn7S96dvlyVBwwtToX895WmCpAOr5YiJYEUJfiJidMuKb613z2xNWcXCHEuOvjZbqC6A==
dependencies:
chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0"
+23
View File
@@ -0,0 +1,23 @@
{
"name": "ProxiTok",
"short_name": "ProxiTok",
"description": "Use TikTok with a privacy-friendly alternative frontend",
"orientation": "portrait-primary",
"icons": [
{
"src": "./android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"id": "./",
"start_url": "./",
"theme_color": "#4040ff",
"background_color": "#ffffff",
"display": "standalone"
}
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../scss/node_modules/css.gg/icons/scss/home.scss","../../scss/node_modules/css.gg/icons/scss/info.scss","../../scss/node_modules/css.gg/icons/scss/search.scss","../../scss/node_modules/css.gg/icons/scss/feed.scss","../../scss/node_modules/css.gg/icons/scss/eye.scss","../../scss/node_modules/css.gg/icons/scss/heart.scss","../../scss/node_modules/css.gg/icons/scss/comment.scss","../../scss/node_modules/css.gg/icons/scss/share.scss","../../scss/node_modules/css.gg/icons/scss/software-download.scss"],"names":[],"mappings":"AAAA,SACE,yLACA,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,aACA,gBACA,4BACA,2BACA,6BACA,4BACA,mBAEA,gBACE,WACA,cACA,sBACA,kBAGF,iBACE,WACA,cACA,sBACA,kBACA,qBACA,sBACA,2BACA,wBACA,SACA,kBACA,WACA,YACA,OAGF,gBACE,UACA,YACA,iBACA,oBACA,4BACA,6BACA,gBACA,SACA,SCjDJ,SACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,mBAEA,iCACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,wBACA,SAGF,gBACE,WACA,WAGF,iBACE,WACA,QC5BN,WACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,mBACA,iBACA,gBAEA,kBACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,WACA,wBACA,yBACA,SACA,UCvBN,SACI,cACA,sBACA,wBACA,sBASA,iBACA,gBACA,kBACA,+BACA,UACA,WACA,kBAbA,iCACE,cACA,sBACA,wBACA,sBAWF,iCACE,WACA,kBACA,kBACA,WACA,WACA,QACA,SACA,WAGF,gBACE,UACA,QACA,WCnCN,QACI,kBACA,cACA,+BACA,WACA,YACA,iCACA,gCACA,gBACA,sBAEA,+BACE,WACA,cACA,oBACA,kBACA,sBAGF,eACE,QACA,8CACA,WACA,YAGF,gBACE,UACA,WACA,iBACA,WACA,SC/BN,UACI,iBACA,6BACA,8BACA,WACA,WACA,gBAeA,sBACA,kBACA,gHACA,cAhBA,iBACE,iBACA,6BACA,8BACA,WACA,WACA,gBACA,WACA,cACA,sBACA,kBAQF,kBACE,WACA,cACA,sBACA,kBAGF,iBACE,WACA,wBACA,QAGF,kBACE,WACA,YACA,sBACA,wBACA,UACA,QC7CN,YACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,gBACA,0CAEA,mBACE,WACA,cACA,sBACA,kBACA,UAGF,oBACE,WACA,cACA,sBACA,kBACA,UACA,iBACA,+BACA,+BACA,UACA,YACA,WAGF,mBACE,WACA,wBACA,qBACA,SACA,QCtCN,UACI,sBACA,kBACA,cACA,+BACA,UACA,WACA,wBACA,oBACA,kCAEA,iBACE,WACA,cACA,sBACA,kBACA,kBACA,WACA,WACA,wBACA,SAGF,kBACE,WACA,cACA,sBACA,kBACA,kBACA,WACA,WACA,wBACA,SACA,MACA,yBAGF,iBACE,SACA,wBCvCN,sBACI,sBACA,kBACA,cACA,+BACA,WACA,WACA,iBACA,aACA,8BACA,+BACA,eAEA,6BACE,WACA,cACA,sBACA,kBACA,UACA,WACA,sBACA,wBACA,yBACA,SACA,WAGF,8BACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,YACA,wBACA,SACA","file":"cssgg.min.css"}
{"version":3,"sourceRoot":"","sources":["../../scss/node_modules/css.gg/icons/scss/home.scss","../../scss/node_modules/css.gg/icons/scss/options.scss","../../scss/node_modules/css.gg/icons/scss/info.scss","../../scss/node_modules/css.gg/icons/scss/code-slash.scss","../../scss/node_modules/css.gg/icons/scss/search.scss","../../scss/node_modules/css.gg/icons/scss/feed.scss","../../scss/node_modules/css.gg/icons/scss/eye.scss","../../scss/node_modules/css.gg/icons/scss/heart.scss","../../scss/node_modules/css.gg/icons/scss/comment.scss","../../scss/node_modules/css.gg/icons/scss/share.scss","../../scss/node_modules/css.gg/icons/scss/software-download.scss","../../scss/node_modules/css.gg/icons/scss/music.scss"],"names":[],"mappings":"AAAA,SACE,yLACA,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,aACA,gBACA,4BACA,2BACA,6BACA,4BACA,mBAEA,gBACE,WACA,cACA,sBACA,kBAGF,iBACE,WACA,cACA,sBACA,kBACA,qBACA,sBACA,2BACA,wBACA,SACA,kBACA,WACA,YACA,OAGF,gBACE,UACA,YACA,iBACA,oBACA,4BACA,6BACA,gBACA,SACA,SCjDJ,YACI,sBACA,kBACA,cACA,+BACA,WACA,WACA,qCAEA,mBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,iBACA,mBAGF,oBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,iBACA,mBACA,SACA,UAGF,mBACE,YACA,WCnCN,SACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,mBAEA,iCACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,wBACA,SAGF,gBACE,WACA,WAGF,iBACE,WACA,QC5BN,eACI,cACA,kBACA,sBACA,6CACA,UACA,YACA,wBAEA,sBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,yBAGF,uBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,yBACA,sBACA,qBACA,UACA,QAGF,sBACE,uBACA,wBACA,WACA,QCrCN,WACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,mBACA,iBACA,gBAEA,kBACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,WACA,wBACA,yBACA,SACA,UCvBN,SACI,cACA,sBACA,wBACA,sBASA,iBACA,gBACA,kBACA,+BACA,UACA,WACA,kBAbA,iCACE,cACA,sBACA,wBACA,sBAWF,iCACE,WACA,kBACA,kBACA,WACA,WACA,QACA,SACA,WAGF,gBACE,UACA,QACA,WCnCN,QACI,kBACA,cACA,+BACA,WACA,YACA,iCACA,gCACA,gBACA,sBAEA,+BACE,WACA,cACA,oBACA,kBACA,sBAGF,eACE,QACA,8CACA,WACA,YAGF,gBACE,UACA,WACA,iBACA,WACA,SC/BN,UACI,iBACA,6BACA,8BACA,WACA,WACA,gBAeA,sBACA,kBACA,gHACA,cAhBA,iBACE,iBACA,6BACA,8BACA,WACA,WACA,gBACA,WACA,cACA,sBACA,kBAQF,kBACE,WACA,cACA,sBACA,kBAGF,iBACE,WACA,wBACA,QAGF,kBACE,WACA,YACA,sBACA,wBACA,UACA,QC7CN,YACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,gBACA,0CAEA,mBACE,WACA,cACA,sBACA,kBACA,UAGF,oBACE,WACA,cACA,sBACA,kBACA,UACA,iBACA,+BACA,+BACA,UACA,YACA,WAGF,mBACE,WACA,wBACA,qBACA,SACA,QCtCN,UACI,sBACA,kBACA,cACA,+BACA,UACA,WACA,wBACA,oBACA,kCAEA,iBACE,WACA,cACA,sBACA,kBACA,kBACA,WACA,WACA,wBACA,SAGF,kBACE,WACA,cACA,sBACA,kBACA,kBACA,WACA,WACA,wBACA,SACA,MACA,yBAGF,iBACE,SACA,wBCvCN,sBACI,sBACA,kBACA,cACA,+BACA,WACA,WACA,iBACA,aACA,8BACA,+BACA,eAEA,6BACE,WACA,cACA,sBACA,kBACA,UACA,WACA,sBACA,wBACA,yBACA,SACA,WAGF,8BACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,YACA,wBACA,SACA,WCrCN,UACI,cACA,sBACA,iBAQA,2BACA,4BACA,gBACA,gBACA,kBACA,6CACA,WACA,YAbA,mCACE,cACA,sBACA,iBAYF,mCACE,WACA,kBACA,UACA,WACA,QACA,UACA,uBACA,mBAGF,iBACE","file":"cssgg.min.css"}
+30 -26
View File
@@ -1,36 +1,40 @@
{layout '../layouts/default.latte'}
{block header}
<p class="title">Welcome to Proxitok!</p>
<p class="title">Welcome to ProxiTok!</p>
<p class="subtitle">
Made with <span style="color: #e25555;">&#9829;</span> in <a href="https://github.com/pablouser1/ProxiTok">Github</a>
</p>
{/block}
{block content}
<p class="title">About this instance</p>
<p>Frontend version: {version_frontend()}</p>
<p>Scraper version: {version_scraper()}</p>
<hr />
<p class="title">Why would I want to use ProxiTok?</p>
<p>
There are already
<a rel="nofollow" href="https://penetrum.com/tiktok/Penetrum_TikTok_Security_Analysis_whitepaper.pdf">multiple</a>
<a rel="nofollow" href="https://rufposten.de/blog/2019/12/05/privacy-analysis-of-tiktoks-app-and-website">articles</a>
<a rel="nofollow" href="https://citizenlab.ca/2021/03/tiktok-vs-douyin-security-privacy-analysis">explaining</a>
Tiktok's privacy issues.
This program allows you to browse TikTok without having to worry about privacy concerns.
</p>
<hr />
<p class="title">Third party</p>
<p>
This project wouldn't be possible without the help of the following projects:
<ul>
<li><a rel="nofollow" href="https://github.com/pablouser1/TikScraperPHP">TikScraperPHP</a></li>
<li><a rel="nofollow" href="https://github.com/nette/latte">Latte</a></li>
<li><a rel="nofollow" href="https://github.com/bramus/router">bramus/router</a></li>
<li><a rel="nofollow" href="https://github.com/vlucas/phpdotenv">PHP dotenv</a></li>
<li><a rel="nofollow" href="https://github.com/jgthms/bulma">Bulma</a> and <a href="https://github.com/jenil/bulmaswatch">Bulmaswatch</a></li>
</ul>
</p>
<div class="content">
<p class="title">About this instance</p>
<p>Frontend version: <b>{version_frontend()}</b></p>
<p>Scraper version: <b>{version_scraper()}</b></p>
</div>
<div class="content">
<p class="title">Why would I want to use ProxiTok?</p>
<p>
There are already
<a rel="nofollow" href="https://penetrum.com/tiktok/Penetrum_TikTok_Security_Analysis_whitepaper.pdf">multiple</a>
<a rel="nofollow" href="https://rufposten.de/blog/2019/12/05/privacy-analysis-of-tiktoks-app-and-website">articles</a>
<a rel="nofollow" href="https://citizenlab.ca/2021/03/tiktok-vs-douyin-security-privacy-analysis">explaining</a>
Tiktok's privacy issues.
This program allows you to browse TikTok without having to worry about privacy concerns.
</p>
</div>
<div class="content">
<p class="title">Third party</p>
<p>
This project wouldn't be possible without the help of the following projects:
<ul>
<li><a rel="nofollow" href="https://github.com/pablouser1/TikScraperPHP">TikScraperPHP</a></li>
<li><a rel="nofollow" href="https://github.com/nette/latte">Latte</a></li>
<li><a rel="nofollow" href="https://github.com/bramus/router">bramus/router</a></li>
<li><a rel="nofollow" href="https://github.com/josegonzalez/php-dotenv">php-dotenv</a></li>
<li><a rel="nofollow" href="https://github.com/jgthms/bulma">Bulma</a> and <a href="https://github.com/jenil/bulmaswatch">Bulmaswatch</a></li>
</ul>
</p>
</div>
{/block}
+12 -6
View File
@@ -2,11 +2,17 @@
{block content}
<p class="title">There was an error processing your request!</p>
<p class="subtitle">HTTP Code: {$error->http_code}</p>
{if $error->tiktok_code}
<p class="subtitle">API error code {$error->tiktok_code} ({$error->tiktok_msg})</p>
{if $error->tiktok_code === 10000}
<a href="{path('/verify')}">What does this mean?</a>
<div class="content">
<p>HTTP Code: {$http_code}</p>
{if isset($tiktok_code)}
<p>
<span>API error code {$tiktok_code} ({$msg})</span>
{if $tiktok_code === 10000 || $tiktok_code === -1}
<a href="{path('/verify')}">What does this mean?</a>
{/if}
</p>
{else}
<p>{$msg}</p>
{/if}
{/if}
</div>
{/block}
+1
View File
@@ -12,6 +12,7 @@
<div class="control">
<div class="select">
<select name="type">
<option value="url">TikTok URL</option>
<option value="user">Username</option>
<option value="tag">Tag</option>
<option value="music">Music ID</option>
+1 -1
View File
@@ -1,6 +1,6 @@
{contentType application/rss+xml}
{do header('Content-Disposition: attachment; filename="' . $title . '.rss' . '"')}
{do $full_link = path($link)}
{var $full_link = path($link)}
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
+1 -1
View File
@@ -7,7 +7,7 @@
{block content}
<p>TL;DR You probably have to search for another instance or wait some hours (or even better, have your own self-hosted instance)</p>
<p>TikTok has some mecanisms in order to stop scraping on their latest api (/api/...):</p>
<p>TikTok has some mecanisms in order to stop scraping on their api:</p>
<hr />
<div class="block">
<p class="is-size-4">Rate limits</p>
+10 -8
View File
@@ -1,22 +1,24 @@
{layout "../layouts/{$layout}.latte"}
{block content}
<div class="columns is-centered is-vcentered is-gapless">
<div class="column is-three-quarters">
<video controls autoplay playsinline poster="{path('/stream?url=' . urlencode($item->video->originCover))}">
<source src="{path('/stream?url=' . urlencode($item->video->playAddr))}" type="video/mp4" />
<div class="columns has-text-centered is-centered is-vcentered is-gapless">
<div class="column">
<video controls autoplay poster="{url_stream($item->video->originCover)}">
<source src="{url_stream($item->video->playAddr)}" type="video/mp4" />
</video>
</div>
<div class="column has-text-centered">
<div class="column">
<div class="box">
<p class="title">Video by <a href="{path('/@'.$detail->uniqueId)}">{$detail->uniqueId}</a></p>
<p class="title">Video by <a href="{url_user($detail->uniqueId)}">{$detail->uniqueId}</a></p>
<p class="subtitle">{$item->desc}</p>
{include '../components/themes/common/stats.latte', playCount: $item->stats->playCount, diggCount: $item->stats->diggCount, commentCount: $item->stats->commentCount, shareCount: $item->stats->shareCount}
<div class="container mt-4">
<p>{include '../components/icon.latte', icon: 'music', text: $item->music->title}</p>
<audio src="{url_stream($item->music->playUrl)}" controls preload="none"></audio>
</div>
<hr />
{include '../components/themes/common/share.latte', uniqueId: $detail->uniqueId, id: $item->id}
{include '../components/themes/common/download.latte', playAddr: $item->video->playAddr, id: $item->id, uniqueId: $detail->uniqueId}
<p>{$item->music->title}</p>
<audio src="{path('/stream?url=' . urlencode($item->music->playUrl))}" controls preload="none"></audio>
</div>
</div>
</div>