Split HTML head, PHP, added searching tags

This commit is contained in:
Pablo Ferreiro 2022-01-03 16:11:24 +01:00
parent 477efe8486
commit 340f500206
No known key found for this signature in database
GPG key ID: 41FBCE65B779FA24
17 changed files with 262 additions and 216 deletions

View file

@ -1 +1 @@
APP_SUBDIR=/ # Subpath your app is running, defaults to / APP_SUBDIR=/ # Subpath your app is running, LEAVE EMPTY IF RUNNING FROM /

View file

@ -20,10 +20,10 @@ Move the .env.example file to .env and modify it.
If you are using Apache you don't have to do anything more If you are using Apache you don't have to do anything more
### Nginx ### Nginx
Add the following to your config (you can modify the tiktok-viewer part if you have or not a subdir): Add the following to your config (you can modify the tiktok-viewer part if you have or not a subdir):
``` ```
location /tiktok-viewer { location /tiktok-viewer {
return 302 $scheme://$host/tiktok-viewer/; return 302 $scheme://$host/tiktok-viewer/;
} }
location /tiktok-viewer/ { location /tiktok-viewer/ {

152
index.php
View file

@ -1,162 +1,16 @@
<?php <?php
require __DIR__ . "/vendor/autoload.php"; require __DIR__ . "/vendor/autoload.php";
require __DIR__ . "/helpers/domains.php";
require __DIR__ . "/helpers/settings_elements.php";
use Steampixel\Route; use Steampixel\Route;
// LOAD DOTENV // LOAD DOTENV
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__); $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load(); $dotenv->load();
// -- HELPERS -- //
function getSubdir(): string { function getSubdir(): string {
return $_ENV['APP_SUBDIR'] ? $_ENV['APP_SUBDIR'] : ''; return isset($_ENV['APP_SUBDIR']) && !empty($_ENV['APP_SUBDIR']) ? $_ENV['APP_SUBDIR'] : '';
} }
function getApi(array $proxy_elements): \Sovit\TikTok\Api { require __DIR__ . '/routes/index.php';
$options = [];
// Proxy config
if (in_array($proxy_elements, $_COOKIE)) {
foreach ($proxy_elements as $proxy_element) {
$options[$proxy_element] = $_COOKIE[$proxy_element];
}
}
$api = new \Sovit\TikTok\Api($options);
return $api;
}
function getLatte(): \Latte\Engine {
$subdir = getSubdir();
$latte = new Latte\Engine;
$latte->setTempDirectory('./cache/views');
$latte->addFunction('assets', function (string $name, string $type) use ($subdir) {
$path = "{$subdir}/{$type}/{$name}";
return $path;
});
$latte->addFunction('path', function (string $name) use ($subdir) {
$path = "{$subdir}/{$name}";
return $path;
});
return $latte;
}
function getView(string $template): string {
return "./views/{$template}.latte";
}
Route::add('/', function () {
http_response_code(302);
header('Location: ./home');
});
Route::add('/home', function () {
$latte = getLatte();
$latte->render('./views/home.latte');
});
Route::add('/images', function () use ($domains) {
if (!isset($_GET['url'])) {
die('You need to send a url!');
}
$url = $_GET['url'];
$host = parse_url($url, PHP_URL_HOST);
if (!filter_var($url, FILTER_VALIDATE_URL) || !in_array($host, $domains['image'])) {
die('Not a valid URL');
}
$img = file_get_contents($url, false, stream_context_create(['http' => ['ignore_errors' => true]]));
if ($img) {
header('Content-Type: image/jpeg');
return $img;
} else {
return 'Error while getting image!';
}
});
Route::add('/audios', function () use ($domains) {
if (!isset($_GET['url'])) {
die('You need to send a url!');
}
$url = $_GET['url'];
$host = parse_url($url, PHP_URL_HOST);
if (!filter_var($url, FILTER_VALIDATE_URL) || !in_array($host, $domains['audio'])) {
die('Not a valid URL');
}
$audio = file_get_contents($url, false, stream_context_create(['http' => ['ignore_errors' => true]]));
if ($audio) {
header('Content-Type: audio/mp3');
return $audio;
} else {
return 'Error while getting audio!';
}
});
Route::add('/stream', function () use ($domains) {
if (!isset($_GET['url'])) {
die('You need to send a url!');
}
$url = $_GET['url'];
$host = parse_url($url, PHP_URL_HOST);
if (!filter_var($url, FILTER_VALIDATE_URL) || !in_array($host, $domains['video'])) {
die('Not a valid URL');
}
if (isset($_GET['download'])) {
header('Content-Disposition: attachment; filename="tiktok.mp4"');
}
$streamer = new \Sovit\TikTok\Stream();
$streamer->stream($url);
});
Route::add("/trending", function () use ($proxy_elements) {
$cursor = 0;
if (isset($_GET['cursor']) && is_numeric($_GET['cursor'])) {
$cursor = (int) $_GET['cursor'];
}
$latte = getLatte();
$api = getApi($proxy_elements);
$feed = $api->getTrendingFeed($cursor);
if ($feed) {
$latte->render(getView('trending'), ['feed' => $feed]);
} else {
return 'ERROR!';
}
});
Route::add("/@([^/]+)", function (string $username) use ($proxy_elements) {
$cursor = 0;
if (isset($_GET['cursor']) && is_numeric($_GET['cursor'])) {
$cursor = (int) $_GET['cursor'];
}
$latte = getLatte();
$api = getApi($proxy_elements);
$feed = $api->getUserFeed($username, $cursor);
if ($feed) {
if ($feed->info->detail->user->privateAccount) {
http_response_code(400);
return 'Private account detected! Not supported';
}
$latte->render(getView('user'), ['feed' => $feed]);
} else {
return 'ERROR!';
}
});
Route::add("/settings", function () use ($proxy_elements) {
$latte = getLatte();
$latte->render(getView('settings'), ["proxy_elements" => $proxy_elements]);
});
Route::add("/settings", function () use ($proxy_elements) {
if (in_array($proxy_elements, $_POST)) {
foreach ($proxy_elements as $proxy_element) {
setcookie($proxy_element, $_POST[$proxy_element], time()+60*60*24*30, '/', '', true, true);
}
}
http_response_code(302);
header('Location: ./home');
}, 'POST');
Route::run(getSubdir()); Route::run(getSubdir());

60
routes/assets.php Normal file
View file

@ -0,0 +1,60 @@
<?php
require __DIR__ . "/../helpers/domains.php";
use Steampixel\Route;
Route::add('/images', function () use ($domains) {
if (!isset($_GET['url'])) {
die('You need to send a url!');
}
$url = $_GET['url'];
$host = parse_url($url, PHP_URL_HOST);
if (!filter_var($url, FILTER_VALIDATE_URL) || !in_array($host, $domains['image'])) {
die('Not a valid URL');
}
$img = file_get_contents($url, false, stream_context_create(['http' => ['ignore_errors' => true]]));
if ($img) {
header('Content-Type: image/jpeg');
return $img;
} else {
return 'Error while getting image!';
}
});
Route::add('/audios', function () use ($domains) {
if (!isset($_GET['url'])) {
die('You need to send a url!');
}
$url = $_GET['url'];
$host = parse_url($url, PHP_URL_HOST);
if (!filter_var($url, FILTER_VALIDATE_URL) || !in_array($host, $domains['audio'])) {
die('Not a valid URL');
}
$audio = file_get_contents($url, false, stream_context_create(['http' => ['ignore_errors' => true]]));
if ($audio) {
header('Content-Type: audio/mp3');
return $audio;
} else {
return 'Error while getting audio!';
}
});
Route::add('/stream', function () use ($domains) {
if (!isset($_GET['url'])) {
die('You need to send a url!');
}
$url = $_GET['url'];
$host = parse_url($url, PHP_URL_HOST);
if (!filter_var($url, FILTER_VALIDATE_URL) || !in_array($host, $domains['video'])) {
die('Not a valid URL');
}
if (isset($_GET['download'])) {
header('Content-Disposition: attachment; filename="tiktok.mp4"');
}
$streamer = new \Sovit\TikTok\Stream();
$streamer->stream($url);
});

91
routes/index.php Normal file
View file

@ -0,0 +1,91 @@
<?php
require __DIR__ . '/assets.php';
require __DIR__ . '/settings.php';
require __DIR__ . "/../helpers/settings_elements.php";
use Steampixel\Route;
// - ROUTING HELPERS - //
function getApi(array $proxy_elements): \Sovit\TikTok\Api {
$options = [];
// Proxy config
if (in_array($proxy_elements, $_COOKIE)) {
foreach ($proxy_elements as $proxy_element) {
$options[$proxy_element] = $_COOKIE[$proxy_element];
}
}
$api = new \Sovit\TikTok\Api($options);
return $api;
}
function getLatte(): \Latte\Engine {
$subdir = getSubdir();
$latte = new Latte\Engine;
$latte->setTempDirectory('./cache/views');
$latte->addFunction('assets', function (string $name, string $type) use ($subdir) {
$path = "{$subdir}/{$type}/{$name}";
return $path;
});
$latte->addFunction('path', function (string $name) use ($subdir) {
$path = "{$subdir}/{$name}";
return $path;
});
return $latte;
}
function getView(string $template): string {
return "./views/{$template}.latte";
}
Route::add('/', function () {
$latte = getLatte();
$latte->render(getView('home'));
});
Route::add("/trending", function () use ($proxy_elements) {
$cursor = 0;
if (isset($_GET['cursor']) && is_numeric($_GET['cursor'])) {
$cursor = (int) $_GET['cursor'];
}
$latte = getLatte();
$api = getApi($proxy_elements);
$feed = $api->getTrendingFeed($cursor);
if ($feed) {
$latte->render(getView('trending'), ['feed' => $feed]);
} else {
return 'ERROR!';
}
});
Route::add("/@([^/]+)", function (string $username) use ($proxy_elements) {
$cursor = 0;
if (isset($_GET['cursor']) && is_numeric($_GET['cursor'])) {
$cursor = (int) $_GET['cursor'];
}
$latte = getLatte();
$api = getApi($proxy_elements);
$feed = $api->getUserFeed($username, $cursor);
if ($feed) {
if ($feed->info->detail->user->privateAccount) {
http_response_code(400);
return 'Private account detected! Not supported';
}
$latte->render(getView('user'), ['feed' => $feed]);
} else {
return 'ERROR!';
}
});
Route::add('/tag/(\w+)', function (string $name) use ($proxy_elements) {
$cursor = 0;
if (isset($_GET['cursor']) && is_numeric($_GET['cursor'])) {
$cursor = (int) $_GET['cursor'];
}
$latte = getLatte();
$api = getApi($proxy_elements);
$feed = $api->getChallengeFeed($name, $cursor);
if ($feed) {
$latte->render(getView('tag'), ['feed' => $feed]);
} else {
return 'ERROR!';
}
});

18
routes/settings.php Normal file
View file

@ -0,0 +1,18 @@
<?php
require __DIR__ . "/../helpers/settings_elements.php";
use Steampixel\Route;
Route::add("/settings", function () use ($proxy_elements) {
$latte = getLatte();
$latte->render(getView('settings'), ["proxy_elements" => $proxy_elements]);
});
Route::add("/settings", function () use ($proxy_elements) {
if (in_array($proxy_elements, $_POST)) {
foreach ($proxy_elements as $proxy_element) {
setcookie($proxy_element, $_POST[$proxy_element], time()+60*60*24*30, '/', '', true, true);
}
}
http_response_code(302);
header('Location: ./home');
}, 'POST');

16
scripts/home.js Normal file
View file

@ -0,0 +1,16 @@
const goToUser = (e) => {
e.preventDefault()
const formData = new FormData(e.target)
const username = formData.get('username')
window.location.href = `./@${username}`
}
const goToTag = (e) => {
e.preventDefault()
const formData = new FormData(e.target)
const tag = formData.get('tag')
window.location.href = `./tag/${tag}`
}
document.getElementById('username_form').addEventListener('submit', goToUser, false)
document.getElementById('tag_form').addEventListener('submit', goToTag, false)

View file

@ -1,14 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<meta charset="UTF-8"> {include 'components/head.latte', title: 'About'}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>About - TikTok</title>
<link rel="stylesheet" href="https://unpkg.com/bulmaswatch/superhero/bulmaswatch.min.css">
</head>
<body> <body>
{include 'navbar.latte'} {include 'components/navbar.latte'}
<section class="hero is-primary"> <section class="hero is-primary">
<div class="hero-body"> <div class="hero-body">
<div class="container"> <div class="container">
@ -19,6 +15,6 @@
<section class="section"> <section class="section">
<p>TODO</p> <p>TODO</p>
</section> </section>
{include 'footer.latte'} {include 'components/footer.latte'}
</body> </body>
</html> </html>

View file

@ -1,16 +1,17 @@
<link rel="stylesheet" href="{assets('feed.css', 'styles')}">
<section class="section"> <section class="section">
<div class="columns is-multiline is-vcentered"> <div class="columns is-multiline is-vcentered">
{foreach $feed->items as $item} {foreach $feed->items as $item}
<div class="column is-one-quarter"> <div class="column is-one-quarter">
<a id="{$item->id}" href="#{$item->id}" class="clickable-img" <a id="{$item->id}" href="#{$item->id}" class="clickable-img"
data-video_url="./stream?url={$item->video->playAddr}" data-video_url="{path('stream?url=' . urlencode($item->video->playAddr))}"
data-video_download="./stream?url={urlencode($item->video->downloadAddr)}&download=1" data-video_download="{path('stream?url=' . urlencode($item->video->playAddr) . '&download=1')}"
data-desc="{$item->desc}" data-desc="{$item->desc}"
data-video_width="{$item->video->width}" data-video_width="{$item->video->width}"
data-video_height="{$item->video->height}" data-video_height="{$item->video->height}"
data-music_title="{$item->music->title}" data-music_title="{$item->music->title}"
data-music_url="./audios?url={urlencode($item->music->playUrl)}"> data-music_url="{path('audios?url=' . urlencode($item->music->playUrl))}">
<img loading="lazy" src="./images?url={urlencode($item->video->originCover)}"/> <img loading="lazy" src="{path('images?url=' . urlencode($item->video->originCover))}"/>
</a> </a>
</div> </div>
{/foreach} {/foreach}

View file

@ -0,0 +1,7 @@
<head>
<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="stylesheet" href="https://unpkg.com/bulmaswatch/superhero/bulmaswatch.min.css">
<title>{$title} - Tiktok Viewer</title>
</head>

View file

@ -9,7 +9,7 @@
<div id="navbar-menu" class="navbar-menu"> <div id="navbar-menu" class="navbar-menu">
<div class="navbar-start"> <div class="navbar-start">
<a href="{path('home')}" class="navbar-item">Home</a> <a href="{path('')}" class="navbar-item">Home</a>
<a href="{path('settings')}" class="navbar-item">Settings</a> <a href="{path('settings')}" class="navbar-item">Settings</a>
</div> </div>
</div> </div>

View file

@ -1,16 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> {include 'components/head.latte', title: 'Home'}
<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="stylesheet" href="https://unpkg.com/bulmaswatch/superhero/bulmaswatch.min.css">
<title>Tiktok Viewer</title>
</head>
<body> <body>
{include 'navbar.latte'} {include 'components/navbar.latte'}
<section class="hero is-fullheight-with-navbar"> <section class="hero is-fullheight-with-navbar">
<div class="hero-body"> <div class="hero-body">
<div class="container has-text-centered"> <div class="container has-text-centered">
@ -20,7 +14,19 @@
<form id="username_form"> <form id="username_form">
<div class="field has-addons has-addons-centered"> <div class="field has-addons has-addons-centered">
<div class="control"> <div class="control">
<input name="username" class="input" placeholder="Type username" required /> <input name="username" class="input" type="text" placeholder="Type username" required />
</div>
<div class="control">
<button class="button is-success" type="submit">Go</button>
</div>
</div>
</form>
<hr />
<p>Search tag:</p>
<form id="tag_form">
<div class="field has-addons has-addons-centered">
<div class="control">
<input name="tag" class="input" type="text" placeholder="Type tag" required />
</div> </div>
<div class="control"> <div class="control">
<button class="button is-success" type="submit">Go</button> <button class="button is-success" type="submit">Go</button>
@ -33,18 +39,10 @@
</div> </div>
</div> </div>
<div class="hero-foot"> <div class="hero-foot">
{include 'footer.latte'} {include 'components/footer.latte'}
</div> </div>
</section> </section>
<script n:syntax=off> <script src="{assets('home.js', 'scripts')}"></script>
const goToUser = (e) => {
e.preventDefault()
const formData = new FormData(e.target)
const username = formData.get('username')
window.location.href = `./@${username}`
}
document.getElementById('username_form').addEventListener('submit', goToUser, false)
</script>
</body> </body>
</html> </html>

View file

@ -1,14 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<meta charset="UTF-8"> {include 'components/head.latte', title: 'Settings'}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Settings - TikTok</title>
<link rel="stylesheet" href="https://unpkg.com/bulmaswatch/superhero/bulmaswatch.min.css">
</head>
<body> <body>
{include 'navbar.latte'} {include 'components/navbar.latte'}
<section class="hero is-primary"> <section class="hero is-primary">
<div class="hero-body"> <div class="hero-body">
<div class="container"> <div class="container">
@ -35,6 +31,6 @@
</div> </div>
</form> </form>
</section> </section>
{include 'footer.latte'} {include 'components/footer.latte'}
</body> </body>
</html> </html>

19
views/tag.latte Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
{include 'components/head.latte', title: 'Challenge'}
<body>
{include 'components/navbar.latte'}
<section class="hero is-primary">
<div class="hero-body">
<div class="container">
<p class="title">{$feed->info->detail->challenge->title}</p>
<p class="subtitle">{$feed->info->detail->challenge->desc}</p>
</div>
</div>
</section>
{include 'components/feed.latte'}
{include 'components/footer.latte'}
</body>
</html>

View file

@ -1,15 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<meta charset="UTF-8"> {include 'components/head.latte', title: 'Trending'}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Trending - TikTok</title>
<link rel="stylesheet" href="https://unpkg.com/bulmaswatch/superhero/bulmaswatch.min.css">
<link rel="stylesheet" href="{assets('feed.css', 'styles')}">
</head>
<body> <body>
{include 'navbar.latte'} {include 'components/navbar.latte'}
<section class="hero is-primary"> <section class="hero is-primary">
<div class="hero-body"> <div class="hero-body">
<div class="container"> <div class="container">
@ -17,7 +12,7 @@
</div> </div>
</div> </div>
</section> </section>
{include 'feed.latte'} {include 'components/feed.latte'}
{include 'footer.latte'} {include 'components/footer.latte'}
</body> </body>
</html> </html>

View file

@ -1,15 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<meta charset="UTF-8"> {include 'components/head.latte', title: $feed->info->detail->user->nickname}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{$feed->info->detail->user->nickname} - TikTok</title>
<link rel="stylesheet" href="https://unpkg.com/bulmaswatch/superhero/bulmaswatch.min.css">
<link rel="stylesheet" href="{assets('feed.css', 'styles')}">
</head>
<body> <body>
{include 'navbar.latte'} {include 'components/navbar.latte'}
<section class="hero is-primary"> <section class="hero is-primary">
<div class="hero-body"> <div class="hero-body">
<div class="container"> <div class="container">
@ -18,7 +13,7 @@
</div> </div>
</div> </div>
</section> </section>
{include 'feed.latte'} {include 'components/feed.latte'}
{include 'footer.latte'} {include 'components/footer.latte'}
</body> </body>
</html> </html>