mirror of
https://github.com/pablouser1/ProxiTok.git
synced 2024-12-06 19:27:30 +01:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ebe5941fa2 | |||
| 574ae51582 | |||
| 90a2d2ec28 | |||
| 3880da35ea | |||
| 8d8fe43431 | |||
| e7ee03e3cc | |||
| d0057e77e3 | |||
| d52dc8687f | |||
| bc3777d74c | |||
| 9acc40618a | |||
| 5e33b93031 | |||
| 76bfcbe34a | |||
| e2282f9dcc | |||
| cfe3a0c51b | |||
| 3b0ed28ad9 | |||
| 9d37bc433d | |||
| 26bde1e4a8 | |||
| 59029e48ad | |||
| e12d26562d | |||
| bdba336d3c | |||
| 578277d251 | |||
| 240b8d7540 | |||
| 08a28ffc3a | |||
| e1fbf75281 | |||
| c041e84967 | |||
| 6c7c0272d4 | |||
| f1728257f2 | |||
| 0c100d650b |
+4
-5
@@ -1,11 +1,10 @@
|
||||
# APP_PATH="/proxitok" # Relative path, PLEASE LEAVE EMPTY IF /
|
||||
# APP_URL="http://localhost:8000" # Absolute path to proxitok instance
|
||||
# LATTE_CACHE=/tmp/proxitok_api # Path for Latte cache, leave commented for ./cache/latte
|
||||
|
||||
# API CONFIG
|
||||
# API_FORCE_LEGACY=true # Force legacy mode for wrapper
|
||||
# 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)
|
||||
|
||||
@@ -35,13 +35,16 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
# Install the cosign tool except on PR
|
||||
# https://github.com/sigstore/cosign-installer
|
||||
- name: Install cosign
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: sigstore/cosign-installer@v2.3.0
|
||||
uses: sigstore/cosign-installer@main
|
||||
with:
|
||||
cosign-release: 'v1.7.1'
|
||||
cosign-release: 'v1.9.0'
|
||||
|
||||
|
||||
# Workaround: https://github.com/docker/build-push-action/issues/461
|
||||
@@ -68,14 +71,20 @@ jobs:
|
||||
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Set some variables for the image
|
||||
run: |
|
||||
echo "IMAGE_VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
|
||||
echo "IMAGE_NAME=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV
|
||||
- name: Build and push Docker image
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
tags: |
|
||||
ghcr.io/${{ env.IMAGE_NAME }}:latest
|
||||
ghcr.io/${{ env.IMAGE_NAME }}:${{ env.IMAGE_VERSION }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
+2
-1
@@ -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 \
|
||||
@@ -22,3 +22,4 @@ RUN composer update --no-cache \
|
||||
&& rm -rf /usr/bin/composer
|
||||
|
||||
EXPOSE 80
|
||||
CMD apachectl -D FOREGROUND
|
||||
|
||||
@@ -1 +1 @@
|
||||
web: vendor/bin/heroku-php-nginx -C setup/nginx_heroku.conf
|
||||
web: vendor/bin/heroku-php-nginx -C setup/heroku/nginx.conf
|
||||
|
||||
@@ -33,8 +33,12 @@ 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
|
||||
* Add custom amount of videos per page
|
||||
* Discover does not work
|
||||
|
||||
## Credits
|
||||
[@TheFrenchGhosty](https://github.com/TheFrenchGhosty): Initial Dockerfile and fixes to a usable state. You can check his Docker image [here](https://github.com/PussTheCat-org/docker-proxitok-quay) on Github or [here](https://quay.io/repository/pussthecatorg/proxitok) on Quay
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "ProxiTok",
|
||||
"description": "Open source alternative frontend for TikTok",
|
||||
"keywords": [
|
||||
"php",
|
||||
"tiktok",
|
||||
"alternative-frontends"
|
||||
],
|
||||
"website": "https://github.com/pablouser1/ProxiTok",
|
||||
"repository": "https://github.com/pablouser1/ProxiTok",
|
||||
"env": {
|
||||
"APP_URL": {
|
||||
"description": "Your instance url (example: https://proxitok.herokuapp.com)"
|
||||
},
|
||||
"API_CACHE": {
|
||||
"description": "Cache system in use",
|
||||
"value": "redis"
|
||||
},
|
||||
"LATTE_CACHE": {
|
||||
"description": "Latte cache path",
|
||||
"value": "/tmp/latte"
|
||||
},
|
||||
"API_SIGNER_URL": {
|
||||
"description": "Remote signer url",
|
||||
"value": "https://signtok.vercel.app/api"
|
||||
}
|
||||
},
|
||||
"addons": [
|
||||
{
|
||||
"plan": "heroku-redis:hobby-dev",
|
||||
"as": "REDIS"
|
||||
}
|
||||
],
|
||||
"buildpacks": [
|
||||
{
|
||||
"url": "heroku/php"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
<?php
|
||||
namespace App\Cache;
|
||||
|
||||
class JSONCache {
|
||||
use TikScraper\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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<?php
|
||||
namespace App\Cache;
|
||||
|
||||
class RedisCache {
|
||||
use TikScraper\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 {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
namespace App\Constants;
|
||||
|
||||
class CacheMethods {
|
||||
const JSON = 'json';
|
||||
const REDIS = 'redis';
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
namespace App\Controllers;
|
||||
use App\Helpers\ErrorHandler;
|
||||
use App\Helpers\Misc;
|
||||
|
||||
/**
|
||||
@@ -11,6 +12,13 @@ class RedirectController {
|
||||
if (isset($_GET['type'], $_GET['term'])) {
|
||||
$term = trim($_GET['term']);
|
||||
switch ($_GET['type']) {
|
||||
case 'url':
|
||||
$endpoint = self::to_endpoint($term);
|
||||
if (!$endpoint) {
|
||||
echo 'Invalid or unknown TikTok URL format';
|
||||
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://vm\.tiktok\.com/([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 '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,6 @@ class SettingsController {
|
||||
$latte->render(Misc::getView('settings'), new BaseTemplate('Settings'));
|
||||
}
|
||||
|
||||
static private function redirect() {
|
||||
$url = Misc::url('/settings');
|
||||
header("Location: {$url}");
|
||||
}
|
||||
|
||||
static public function general() {
|
||||
if (isset($_POST['theme'])) {
|
||||
$theme = $_POST['theme'];
|
||||
@@ -25,10 +20,16 @@ class SettingsController {
|
||||
self::redirect();
|
||||
}
|
||||
static public function api() {
|
||||
if (isset($_POST['api-legacy'])) {
|
||||
$legacy = $_POST['api-legacy'];
|
||||
// TODO, ADD COUNT
|
||||
if (isset($_POST['api-test_endpoints'])) {
|
||||
$test_endpoints = $_POST['api-test_endpoints'];
|
||||
Cookies::set('api-test_endpoints', $test_endpoints);
|
||||
}
|
||||
Cookies::set('api-legacy', $legacy);
|
||||
self::redirect();
|
||||
}
|
||||
|
||||
static private function redirect() {
|
||||
$url = Misc::url('/settings');
|
||||
header("Location: {$url}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,8 @@ use App\Models\RSSTemplate;
|
||||
class TrendingController {
|
||||
static public function get() {
|
||||
$api = Wrappers::api();
|
||||
$cursor = Misc::getTtwid();
|
||||
|
||||
// Ttwid if standard, cursor if legacy
|
||||
if ($api->isLegacy()) {
|
||||
$cursor = Misc::getCursor();
|
||||
} else {
|
||||
$cursor = Misc::getTtwid();
|
||||
}
|
||||
$trending = $api->trending();
|
||||
$trending->feed($cursor);
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<?php
|
||||
namespace App\Controllers;
|
||||
|
||||
/**
|
||||
* @deprecated Please use UserController::video instead
|
||||
*/
|
||||
class VideoController {
|
||||
static public function get(string $video_id) {
|
||||
UserController::video('placeholder', $video_id);
|
||||
|
||||
@@ -23,6 +23,10 @@ class Cookies {
|
||||
return isset($_COOKIE[$name]);
|
||||
}
|
||||
|
||||
static public function check(string $name, string $value): bool {
|
||||
return self::exists($name) && $_COOKIE[$name] === $value;
|
||||
}
|
||||
|
||||
static public function set(string $name, string $value) {
|
||||
setcookie($name, $value, time()+60*60*24*30, '/', '', isset($_SERVER['HTTPS']), true);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ class Misc {
|
||||
}
|
||||
|
||||
static public function getTtwid(): string {
|
||||
return isset($_GET['cursor']) ? $_GET['cursor'] : '';
|
||||
return isset($_GET['cursor']) ? $_GET['cursor'] : '';
|
||||
}
|
||||
|
||||
static public function url(string $endpoint = ''): string {
|
||||
|
||||
+25
-10
@@ -3,6 +3,7 @@ namespace App\Helpers;
|
||||
|
||||
use App\Cache\JSONCache;
|
||||
use App\Cache\RedisCache;
|
||||
use App\Constants\CacheMethods;
|
||||
|
||||
class Wrappers {
|
||||
/**
|
||||
@@ -19,9 +20,12 @@ class Wrappers {
|
||||
return Misc::url($endpoint);
|
||||
});
|
||||
// Version being used
|
||||
$latte->addFunction('version', function (): string {
|
||||
$latte->addFunction('version_frontend', function (): string {
|
||||
return \Composer\InstalledVersions::getVersion('pablouser1/proxitok');
|
||||
});
|
||||
$latte->addFunction('version_scraper', function (): string {
|
||||
return \Composer\InstalledVersions::getVersion('pablouser1/tikscraper');
|
||||
});
|
||||
$latte->addFunction('theme', function(): string {
|
||||
return Cookies::theme();
|
||||
});
|
||||
@@ -46,22 +50,35 @@ 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),
|
||||
'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
|
||||
]
|
||||
];
|
||||
// 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!');
|
||||
}
|
||||
@@ -81,8 +98,6 @@ class Wrappers {
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy mode
|
||||
$legacy = Misc::env('API_FORCE_LEGACY', false) || isset($_COOKIE['api-legacy']) && $_COOKIE['api-legacy'] === 'on';
|
||||
return new \TikScraper\Api($options, $legacy, $cacheEngine);
|
||||
return new \TikScraper\Api($options, $cacheEngine);
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
@@ -2,9 +2,16 @@
|
||||
<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" />
|
||||
{if isset($has_rss)}
|
||||
<link rel="alternate" type="application/rss+xml" title="{$title}" href="{$_SERVER['REQUEST_URI'] . '/rss'}" />
|
||||
{/if}
|
||||
<link rel="stylesheet" href="{path('/styles/vendor/cssgg.min.css')}">
|
||||
<link rel="stylesheet" href="{path('/styles/vendor/bulma.min.css')}">
|
||||
<title>{$title} - ProxiTok</title>
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
{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">Legacy mode</label>
|
||||
<div class="select">
|
||||
<select name="api-legacy">
|
||||
<option hidden disabled selected value> -- Select an option -- </option>
|
||||
<option value="on">On</option>
|
||||
<option value="off">Off</option>
|
||||
</select>
|
||||
<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" />
|
||||
<span>Yes</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="api-test_endpoints" value="no" n:attr="checked => !$use_endpoints" />
|
||||
<span>No</span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="help">This <i>may</i> help bypass rate limits</p>
|
||||
</div>
|
||||
{/block}
|
||||
{/embed}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
data-video_download_nowatermark="{path('/download?id=' . $item->id . '&user=' . $item->author->uniqueId)}"
|
||||
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))}" />
|
||||
@@ -36,6 +37,7 @@
|
||||
</section>
|
||||
<footer class="modal-card-foot has-text-centered">
|
||||
<div class="container">
|
||||
<p id="item_date"></p>
|
||||
<div class="field has-addons has-addons-centered">
|
||||
<div class="control">
|
||||
<input id="share_input" class="input" readonly />
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<div n:ifset="$data->info" class="buttons">
|
||||
{* is_numeric is used to avoid having a back button with ttwid cursors *}
|
||||
{if isset($_GET['cursor']) && is_numeric($_GET['cursor']) && $_GET['cursor'] != 0 }
|
||||
{if isset($_GET['cursor']) && is_numeric($_GET['cursor']) && $_GET['cursor'] != 0}
|
||||
<a class="button is-danger" href="?cursor=0">First</a>
|
||||
<a class="button is-danger" href="?cursor={$data->feed->minCursor}">Back</a>
|
||||
{/if}
|
||||
<a n:attr="disabled => !$data->feed->hasMore" class="button is-success" href="?cursor={$data->feed->maxCursor}">Next</a>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
<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>
|
||||
<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>
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "pablouser1/proxitok",
|
||||
"description": "An alternative frontend for TikTok",
|
||||
"version": "2.3.0.0",
|
||||
"version": "2.4.0.0",
|
||||
"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.0"
|
||||
"pablouser1/tikscraper": "^2.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
Generated
+39
-33
@@ -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": "e0e24f4588d6e34423fa8931ae8ae9a3",
|
||||
"content-hash": "4e398680c8c683b157043558c21a25ad",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bramus/router",
|
||||
@@ -117,16 +117,16 @@
|
||||
},
|
||||
{
|
||||
"name": "latte/latte",
|
||||
"version": "v2.11.3",
|
||||
"version": "v2.11.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/latte.git",
|
||||
"reference": "f2e16d3ec6968854029740452c20c38a514e6842"
|
||||
"reference": "89e647e51213af8a270fe9903b8735a2f6c83ad1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/latte/zipball/f2e16d3ec6968854029740452c20c38a514e6842",
|
||||
"reference": "f2e16d3ec6968854029740452c20c38a514e6842",
|
||||
"url": "https://api.github.com/repos/nette/latte/zipball/89e647e51213af8a270fe9903b8735a2f6c83ad1",
|
||||
"reference": "89e647e51213af8a270fe9903b8735a2f6c83ad1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -195,9 +195,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nette/latte/issues",
|
||||
"source": "https://github.com/nette/latte/tree/v2.11.3"
|
||||
"source": "https://github.com/nette/latte/tree/v2.11.5"
|
||||
},
|
||||
"time": "2022-05-08T03:22:55+00:00"
|
||||
"time": "2022-06-26T10:12:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "m1/env",
|
||||
@@ -263,23 +263,29 @@
|
||||
},
|
||||
{
|
||||
"name": "pablouser1/tikscraper",
|
||||
"version": "v2.0.1.3",
|
||||
"version": "v2.2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pablouser1/TikScraperPHP.git",
|
||||
"reference": "45812af395b376dff6835af192827f34ba7a4cf9"
|
||||
"reference": "5561b82442caf4968f0c4f408ee5847a97cd8940"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pablouser1/TikScraperPHP/zipball/45812af395b376dff6835af192827f34ba7a4cf9",
|
||||
"reference": "45812af395b376dff6835af192827f34ba7a4cf9",
|
||||
"url": "https://api.github.com/repos/pablouser1/TikScraperPHP/zipball/5561b82442caf4968f0c4f408ee5847a97cd8940",
|
||||
"reference": "5561b82442caf4968f0c4f408ee5847a97cd8940",
|
||||
"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"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -298,9 +304,9 @@
|
||||
"description": "Get data from TikTok API",
|
||||
"support": {
|
||||
"issues": "https://github.com/pablouser1/TikScraperPHP/issues",
|
||||
"source": "https://github.com/pablouser1/TikScraperPHP/tree/v2.0.1.3"
|
||||
"source": "https://github.com/pablouser1/TikScraperPHP/tree/v2.2.0.0"
|
||||
},
|
||||
"time": "2022-05-24T12:08:22+00:00"
|
||||
"time": "2022-08-13T10:17:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-webdriver/webdriver",
|
||||
@@ -399,16 +405,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -423,7 +429,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -462,7 +468,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -478,20 +484,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-11-30T18:21:41+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -500,7 +506,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@@ -545,7 +551,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -561,20 +567,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-04T08:16:47+00:00"
|
||||
"time": "2022-05-10T07:21:04+00:00"
|
||||
},
|
||||
{
|
||||
"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": {
|
||||
@@ -607,7 +613,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": [
|
||||
{
|
||||
@@ -623,7 +629,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-08T05:07:18+00:00"
|
||||
"time": "2022-06-27T16:58:25+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
||||
@@ -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
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 626 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
+3
-3
@@ -34,10 +34,10 @@ $router->mount('/@([^/]+)', function () use ($router) {
|
||||
$router->get('/rss', 'UserController@rss');
|
||||
});
|
||||
|
||||
/**
|
||||
* @deprecated Please use /@username/video/id instead
|
||||
*/
|
||||
// Deprecated, please use /@USERNAME/video/VIDEO_ID instead
|
||||
$router->get('/video/(\w+)', 'VideoController@get');
|
||||
// Workaround that allows /t endpoints
|
||||
$router->get('/t/([^/]+)', 'VideoController@get');
|
||||
|
||||
$router->mount('/tag/([^/]+)', function () use ($router) {
|
||||
$router->get('/', 'TagController@get');
|
||||
|
||||
@@ -2,6 +2,7 @@ var opened_video_id = null
|
||||
|
||||
const video = document.getElementById('video')
|
||||
const item_title = document.getElementById('item_title')
|
||||
const item_date = document.getElementById('item_date')
|
||||
const audio = document.getElementById('audio')
|
||||
const audio_title = document.getElementById('audio_title')
|
||||
const modal = document.getElementById('modal')
|
||||
@@ -15,7 +16,7 @@ const getVideoDataById = id => {
|
||||
opened_video_id = id
|
||||
return el.dataset
|
||||
}
|
||||
return false
|
||||
return null
|
||||
}
|
||||
|
||||
const isModalActive = () => modal.classList.contains('is-active')
|
||||
@@ -23,9 +24,10 @@ const isModalActive = () => modal.classList.contains('is-active')
|
||||
const toggleButton = (id, force) => document.getElementById(id).toggleAttribute('disabled', force)
|
||||
|
||||
// -- MODAL -- //
|
||||
const swapData = ({ video_url, desc, video_download_watermark, video_download_nowatermark, video_share_url, music_title, music_url }) => {
|
||||
const swapData = ({ video_url, desc, createtime, video_download_watermark, video_download_nowatermark, video_share_url, music_title, music_url }) => {
|
||||
video.src = video_url
|
||||
item_title.innerText = desc
|
||||
item_date.innerText = new Date(createtime * 1000).toLocaleString()
|
||||
download_watermark.href = video_download_watermark
|
||||
download_nowatermark.href = video_download_nowatermark
|
||||
share_input.value = video_share_url
|
||||
|
||||
+3
-3
@@ -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.
|
||||
|
||||
+7
-7
@@ -72,9 +72,9 @@ glob-parent@~5.1.2:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
immutable@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23"
|
||||
integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef"
|
||||
integrity sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==
|
||||
|
||||
is-binary-path@~2.1.0:
|
||||
version "2.1.0"
|
||||
@@ -86,7 +86,7 @@ is-binary-path@~2.1.0:
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
|
||||
|
||||
is-glob@^4.0.1, is-glob@~4.0.1:
|
||||
version "4.0.3"
|
||||
@@ -118,9 +118,9 @@ readdirp@~3.6.0:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
sass@^1.46.0:
|
||||
version "1.52.1"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.52.1.tgz#554693da808543031f9423911d62c60a1acf7889"
|
||||
integrity sha512-fSzYTbr7z8oQnVJ3Acp9hV80dM1fkMN7mSD/25mpcct9F7FPBMOI8krEYALgU1aZoqGhQNhTPsuSmxjnIvAm4Q==
|
||||
version "1.53.0"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.53.0.tgz#eab73a7baac045cc57ddc1d1ff501ad2659952eb"
|
||||
integrity sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==
|
||||
dependencies:
|
||||
chokidar ">=3.0.0 <4.0.0"
|
||||
immutable "^4.0.0"
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
{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;">♥</span> in <a href="https://github.com/pablouser1/ProxiTok">Github</a>
|
||||
</p>
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
{block content}
|
||||
<p class="title">About this instance</p>
|
||||
<p>Version: {version()}</p>
|
||||
<p>Forcing Legacy mode: {isset($_ENV['API_FORCE_LEGACY']) ? 'yes' : 'no'}</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>
|
||||
@@ -29,7 +29,7 @@
|
||||
<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/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>
|
||||
|
||||
+3
-5
@@ -3,10 +3,8 @@
|
||||
{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>
|
||||
{/if}
|
||||
<p class="subtitle">API error code {$error->tiktok_code} ({$error->tiktok_msg})</p>
|
||||
{if $error->tiktok_code === 10000 || $error->tiktok_code === -1}
|
||||
<a href="{path('/verify')}">What does this mean?</a>
|
||||
{/if}
|
||||
{/block}
|
||||
|
||||
@@ -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
-3
@@ -1,7 +1,6 @@
|
||||
{contentType application/rss+xml}
|
||||
{do header('Content-Disposition: attachment; filename="' . $title . '.rss' . '"')}
|
||||
{do $full_link = path($link)}
|
||||
{var $download = new \TikScraper\Download}
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
@@ -12,11 +11,10 @@
|
||||
{foreach $items as $item}
|
||||
<item>
|
||||
<title>{$item->desc}</title>
|
||||
<description><![CDATA[{$item->desc}]]></description>
|
||||
<description><![CDATA[<p>{$item->desc}</p><video controls="controls" preload="auto" src="{path('/stream?url=' . urlencode($item->video->playAddr))}"></video>]]></description>
|
||||
<link>{path('/@' . $item->author->uniqueId . '/video/' . $item->id)}</link>
|
||||
<pubDate>{date('r', $item->createTime)}</pubDate>
|
||||
<guid isPermaLink="false">{$item->id}</guid>
|
||||
<enclosure length="{$download->file_size($item->video->playAddr)}" type="video/mp4" url="{path('/stream?url=' . urlencode($item->video->playAddr))}"></enclosure>
|
||||
</item>
|
||||
{/foreach}
|
||||
</channel>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{layout '../layouts/default.latte'}
|
||||
|
||||
{var $has_rss = true}
|
||||
|
||||
{block header}
|
||||
{if $data->info->detail->profileThumb !== ''}
|
||||
<figure class="figure is-96x96">
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{layout '../layouts/default.latte'}
|
||||
|
||||
{var $has_rss = true}
|
||||
|
||||
{block header}
|
||||
<p class="title">Trending</p>
|
||||
<p class="subtitle">{include '../components/rss.latte'}</p>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{layout '../layouts/default.latte'}
|
||||
|
||||
{var $has_rss = true}
|
||||
|
||||
{block header}
|
||||
<figure class="figure is-96x96">
|
||||
<img src="{path('/stream?url=' . urlencode($data->info->detail->avatarThumb))}" />
|
||||
|
||||
+1
-1
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user