Compare commits

...

18 Commits

Author SHA1 Message Date
Pablo Ferreiro e5d416f696 pictures using carousel 2023-04-01 17:09:12 +02:00
Pablo Ferreiro 98a9ec2b65 hotfix 2023-04-01 16:35:17 +02:00
Pablo Ferreiro 33c723d786 Pictures support 2023-04-01 15:48:27 +02:00
Pablo Ferreiro faee8d58f2 bump 2023-03-29 11:23:14 +02:00
Pablo Ferreiro 75e13bc7d2 Merge pull request #140 from NoPlagiarism/www_shortened
Fix https:// + www in redirections (fixes #139)
2023-03-29 09:05:36 +00:00
Pablo Ferreiro 08145ee90b Merge pull request #135 from kuanhulio/master
harden docker-compose
2023-03-29 09:04:10 +00:00
NoPlagiarism 6194324452 Fix https:// + www in redirections (#139) 2023-03-29 07:39:36 +05:00
Nullnet Services Administrator 48eccbc5ec harden docker-compose 2023-03-18 21:10:24 -05:00
Pablo Ferreiro cac97ff05e Initial comments support 2023-03-06 21:20:14 +01:00
Pablo Ferreiro eeaa8cdf1c Random User Agent generator 2023-03-05 13:18:34 +01:00
Pablo Ferreiro ecba96eaf4 Merge pull request #131 from chrisnovakovic/video-title
Set page title to video description in video view
2023-02-28 11:40:30 +00:00
Chris Novakovic 013feeb679 Set page title to video description in video view
If the upstream video has a description set, use it as the page title in
place of "Video" in the video view. This helps to disambiguate video
pages in the browser history.
2023-02-27 23:11:36 +00:00
Pablo Ferreiro bf86e0d36a Merge pull request #125 from samip5/configureable_user_agent
Ability to pass custom user agent to the scraper and ignore .git on Docker
2023-02-19 11:08:22 +00:00
Skyler Mäntysaari 72ea5d43fd Addressing PR comments about not using hardcoded string. 2023-02-17 22:32:36 +02:00
Skyler Mäntysaari 288f87504c Add .git to dockerignore
Otherwise bad things end up in container.
2023-02-16 02:26:25 +02:00
Skyler Mäntysaari 3d5890d821 Ability to pass own user agent to the scraper. 2023-02-08 12:59:17 +02:00
Pablo Ferreiro 5dea2468f8 Better handling of private accounts 2023-02-01 15:22:53 +01:00
Pablo Ferreiro e8ec0ab293 bump 2023-01-28 17:32:07 +01:00
16 changed files with 253 additions and 40 deletions
+1
View File
@@ -1,5 +1,6 @@
node_modules
/.env
/.git
/.vscode
/vendor
/cache/latte/*
+2
View File
@@ -20,3 +20,5 @@
# PROXY_PORT=8080
# PROXY_USERNAME=username
# PROXY_PASSWORD=password
# USER_AGENT="Mozilla/5.0 (Android 12; Mobile; rv:109.0) Gecko/109.0 Firefox/109.0"
+2 -1
View File
@@ -40,7 +40,8 @@ Apply to: Main window (address bar)
* Add custom amount of videos per page
## Credits
[TheFrenchGhosty](https://thefrenchghosty.me) ([Github](https://github.com/TheFrenchGhosty)): Initial Dockerfile and fixes to a usable state.
* [TheFrenchGhosty](https://thefrenchghosty.me) ([Github](https://github.com/TheFrenchGhosty)): Initial Dockerfile and fixes to a usable state.
* [Jennifer Wjertzoch](https://wjertzochjennifer.medium.com): Carousel CSS Implementation
### External libraries
* [TikScraperPHP](https://github.com/pablouser1/TikScraperPHP)
+4 -1
View File
@@ -2,6 +2,8 @@
namespace App\Controllers;
use App\Helpers\Cookies;
use App\Helpers\Misc;
use TikScraper\Constants\UserAgents as TikScraperUserAgents;
class ProxyController {
const VALID_TIKTOK_DOMAINS = [
@@ -11,7 +13,8 @@ class ProxyController {
static public function stream() {
self::checkUrl();
$url = $_GET['url'];
$streamer = new \TikScraper\Stream();
$config['user_agent'] = Misc::env("USER_AGENT", TikScraperUserAgents::DEFAULT);
$streamer = new \TikScraper\Stream($config);
$streamer->url($url);
}
+1 -1
View File
@@ -71,7 +71,7 @@ class RedirectController {
* 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)) {
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)) {
-4
View File
@@ -18,10 +18,6 @@ class UserController {
if ($user->ok()) {
$info = $user->getInfo();
$feed = $user->getFeed();
if ($info->detail->privateAccount) {
ErrorHandler::showText(401, "Private account detected! Not supported");
return;
}
Wrappers::latte('user', new FullTemplate($info->detail->nickname, $info, $feed));
} else {
ErrorHandler::showMeta($user->error());
+8
View File
@@ -7,6 +7,8 @@ use App\Cache\RedisCache;
use App\Constants\CacheMethods;
use App\Models\BaseTemplate;
use TikScraper\Constants\UserAgents as TikScraperUserAgents;
class Wrappers {
/**
* Setup of Latte template engine
@@ -162,6 +164,12 @@ class Wrappers {
}
}
$customUa = Misc::env("USER_AGENT", '');
if ($customUa) {
$options['user_agent'] = $customUa;
}
return new \TikScraper\Api($options, $cacheEngine);
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "pablouser1/proxitok",
"description": "An alternative frontend for TikTok",
"version": "2.4.5.0",
"version": "2.4.8.1",
"license": "AGPL-3.0-or-later",
"type": "project",
"authors": [
Generated
+67 -25
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": "818a3e623705c076822f3d895a0d99ca",
"content-hash": "15a71acabddd2588be9800ae1bb37c92",
"packages": [
{
"name": "bramus/router",
@@ -57,6 +57,46 @@
},
"time": "2021-11-18T19:24:07+00:00"
},
{
"name": "deemon47/user-agent-generator",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/Deemon47/user-agent-generator.git",
"reference": "5af13fd2e905c5441eb4d61aad3a71bd1e801709"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Deemon47/user-agent-generator/zipball/5af13fd2e905c5441eb4d61aad3a71bd1e801709",
"reference": "5af13fd2e905c5441eb4d61aad3a71bd1e801709",
"shasum": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Deemon47\\": "./"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-3.0-only"
],
"authors": [
{
"name": "phpfail",
"email": "phpfail@gihub.com"
},
{
"name": "Dee",
"email": "deemon47@gmail.com"
}
],
"description": "Generate random User-Agent http header with parameters",
"support": {
"source": "https://github.com/Deemon47/user-agent-generator/tree/v1.0.1"
},
"time": "2020-04-11T12:05:34+00:00"
},
{
"name": "josegonzalez/dotenv",
"version": "dev-master",
@@ -263,19 +303,20 @@
},
{
"name": "pablouser1/tikscraper",
"version": "v2.3.4.0",
"version": "v2.3.6.2",
"source": {
"type": "git",
"url": "https://github.com/pablouser1/TikScraperPHP.git",
"reference": "8ee7efd58892d0a6e536b7cc29de200202916394"
"reference": "10394fb5fb5213d05fe0eb29f7582423fc15d08a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pablouser1/TikScraperPHP/zipball/8ee7efd58892d0a6e536b7cc29de200202916394",
"reference": "8ee7efd58892d0a6e536b7cc29de200202916394",
"url": "https://api.github.com/repos/pablouser1/TikScraperPHP/zipball/10394fb5fb5213d05fe0eb29f7582423fc15d08a",
"reference": "10394fb5fb5213d05fe0eb29f7582423fc15d08a",
"shasum": ""
},
"require": {
"deemon47/user-agent-generator": "^1.0",
"ext-curl": "*",
"ext-json": "*",
"ext-xml": "*",
@@ -305,43 +346,44 @@
"description": "Get data from TikTok API",
"support": {
"issues": "https://github.com/pablouser1/TikScraperPHP/issues",
"source": "https://github.com/pablouser1/TikScraperPHP/tree/v2.3.4.0"
"source": "https://github.com/pablouser1/TikScraperPHP/tree/v2.3.6.2"
},
"time": "2023-01-26T18:18:34+00:00"
"time": "2023-04-01T13:46:50+00:00"
},
{
"name": "php-webdriver/webdriver",
"version": "1.13.1",
"version": "1.14.0",
"source": {
"type": "git",
"url": "https://github.com/php-webdriver/php-webdriver.git",
"reference": "6dfe5f814b796c1b5748850aa19f781b9274c36c"
"reference": "3ea4f924afb43056bf9c630509e657d951608563"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/6dfe5f814b796c1b5748850aa19f781b9274c36c",
"reference": "6dfe5f814b796c1b5748850aa19f781b9274c36c",
"url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/3ea4f924afb43056bf9c630509e657d951608563",
"reference": "3ea4f924afb43056bf9c630509e657d951608563",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-json": "*",
"ext-zip": "*",
"php": "^5.6 || ~7.0 || ^8.0",
"php": "^7.3 || ^8.0",
"symfony/polyfill-mbstring": "^1.12",
"symfony/process": "^2.8 || ^3.1 || ^4.0 || ^5.0 || ^6.0"
"symfony/process": "^5.0 || ^6.0"
},
"replace": {
"facebook/webdriver": "*"
},
"require-dev": {
"ondram/ci-detector": "^2.1 || ^3.5 || ^4.0",
"ergebnis/composer-normalize": "^2.20.0",
"ondram/ci-detector": "^4.0",
"php-coveralls/php-coveralls": "^2.4",
"php-mock/php-mock-phpunit": "^1.1 || ^2.0",
"php-mock/php-mock-phpunit": "^2.0",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpunit/phpunit": "^5.7 || ^7 || ^8 || ^9",
"phpunit/phpunit": "^9.3",
"squizlabs/php_codesniffer": "^3.5",
"symfony/var-dumper": "^3.3 || ^4.0 || ^5.0 || ^6.0"
"symfony/var-dumper": "^5.0 || ^6.0"
},
"suggest": {
"ext-SimpleXML": "For Firefox profile creation"
@@ -370,9 +412,9 @@
],
"support": {
"issues": "https://github.com/php-webdriver/php-webdriver/issues",
"source": "https://github.com/php-webdriver/php-webdriver/tree/1.13.1"
"source": "https://github.com/php-webdriver/php-webdriver/tree/1.14.0"
},
"time": "2022-10-11T11:49:44+00:00"
"time": "2023-02-09T12:12:19+00:00"
},
{
"name": "sapistudio/seleniumstealth",
@@ -572,16 +614,16 @@
},
{
"name": "symfony/process",
"version": "v5.4.19",
"version": "v5.4.22",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "c5ba874c9b636dbccf761e22ce750e88ec3f55e1"
"reference": "4b850da0cc3a2a9181c1ed407adbca4733dc839b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/c5ba874c9b636dbccf761e22ce750e88ec3f55e1",
"reference": "c5ba874c9b636dbccf761e22ce750e88ec3f55e1",
"url": "https://api.github.com/repos/symfony/process/zipball/4b850da0cc3a2a9181c1ed407adbca4733dc839b",
"reference": "4b850da0cc3a2a9181c1ed407adbca4733dc839b",
"shasum": ""
},
"require": {
@@ -614,7 +656,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v5.4.19"
"source": "https://github.com/symfony/process/tree/v5.4.22"
},
"funding": [
{
@@ -630,7 +672,7 @@
"type": "tidelift"
}
],
"time": "2023-01-01T08:32:19+00:00"
"time": "2023-03-06T21:29:33+00:00"
}
],
"packages-dev": [],
+34
View File
@@ -18,13 +18,47 @@ services:
depends_on:
- redis
- signer
networks:
- proxitok
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
redis:
container_name: proxitok-redis
image: redis:7-alpine
command: redis-server --save 60 1 --loglevel warning
restart: unless-stopped
networks:
- proxitok
user: nobody
read_only: true
security_opt:
- no-new-privileges:true
tmpfs:
- /data:size=10M,mode=0770,uid=65534,gid=65534,noexec,nosuid,nodev
cap_drop:
- ALL
signer:
container_name: proxitok-signer
image: ghcr.io/pablouser1/signtok:master
networks:
- proxitok
user: nobody
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
volumes:
proxitok-cache:
networks:
proxitok:
+68
View File
@@ -0,0 +1,68 @@
/*
CREDITS:
CSS Taken from: https://levelup.gitconnected.com/how-to-make-a-fully-accessible-css-only-carousel-40e8bd62032b
Author: Jennifer Wjertzoch (https://wjertzochjennifer.medium.com)
CodePen: https://codepen.io/jwjertzoch/pen/JjyGeRy
*/
.carousel {
margin: 0 auto;
overflow: hidden;
text-align: center;
}
.slides {
width: 100%;
display: flex;
overflow-x: scroll;
scrollbar-width: none;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
}
.slides::-webkit-scrollbar {
display: none;
}
.slides-item {
max-height: 75vh;
align-items: center;
display: flex;
flex-shrink: 0;
justify-content: center;
margin: 0 1rem;
position: relative;
scroll-snap-align: start;
transform: scale(1);
transform-origin: center center;
transition: transform .5s;
width: 100%;
}
.slides-item img {
max-height: 75vh;
}
.carousel__nav {
padding: 1.25rem .5rem;
}
.slider-nav {
align-items: center;
background-color: #ddd;
border-radius: 50%;
color: #000;
display: inline-flex;
height: 1.5rem;
justify-content: center;
padding: .5rem;
position: relative;
text-decoration: none;
width: 1.5rem;
}
.slider-nav:hover,
.slider-nav:active {
background-color: #000;
color: #fff;
}
+1
View File
@@ -31,5 +31,6 @@
{/if}
<link rel="stylesheet" href="{static('css', 'cssgg.min.css', true)}">
<link rel="stylesheet" href="{static('css', 'bulma.min.css', true)}">
<link rel="stylesheet" href="{static('css', 'carousel.css')}">
<title>{$title} - ProxiTok</title>
</head>
@@ -0,0 +1,21 @@
{if !isset($item->imagePost)}
<video controls n:attr="autoplay => $isAutoplay" poster="{url_stream($item->video->originCover)}" preload="none">
<source src="{url_stream($item->video->playAddr)}" type="video/mp4" />
</video>
{else}
<section class="carousel" aria-label="carousel" Tabindex="0">
<div class="slides">
{foreach $item->imagePost->images as $i => $image}
<div class="slides-item" id="image-{$i + 1}" tabindex="0">
<img src="{url_stream($image->imageURL->urlList[0])}" />
</div>
{/foreach}
</div>
<div class="carousel__nav">
{for $i = 0; $i < count($item->imagePost->images); $i++}
<a class="slider-nav" href="#image-{$i + 1}">{$i + 1}</a>
{/for}
</div>
<div class="carousel__skip-message" id="skip-link" tabindex="0"></div>
</section>
{/if}
+3 -3
View File
@@ -18,11 +18,11 @@
<p>{include './common/tags.latte', challenges: $item->challenges}</p>
{/if}
<p n:ifcontent>{$item->desc}</p>
<p>Song: {$item->music->title}</p>
<audio controls preload="none" src="{$item->music->playUrl}"></audio>
{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="{url_stream($item->video->originCover)}">
<source src="{url_stream($item->video->playAddr)}" type="video/mp4" />
</video>
{include './common/content.latte', item: $item, isAutoplay: false, isBig: false}
</div>
<p class="has-text-centered"><b>Download video</b></p>
{include './common/download.latte', playAddr: $item->video->playAddr, id: $item->id, uniqueId: $item->author->uniqueId}
+4
View File
@@ -12,6 +12,10 @@
</figure>
<p class="title">{$info->detail->uniqueId}</p>
<p class="subtitle">{include '../components/rss.latte'}</p>
{if $info->detail->privateAccount}
<p><strong>Private account</strong></p>
{/if}
<p></p>
<p>{$info->detail->signature}</p>
<p>Following: {number($info->stats->followingCount)} / Followers: {number($info->stats->followerCount)}</p>
<p>Hearts: {number($info->stats->heartCount)} / Videos: {$info->stats->videoCount}</p>
+36 -4
View File
@@ -4,12 +4,14 @@
{var $og_content = $item->video->originCover}
{var $og_url = url_video_internal($info->detail->uniqueId, $item->id)}
{if !empty($item->desc)}
{var $title = trim($item->desc)}
{/if}
{block content}
<div class="columns is-centered is-vcentered is-gapless">
<div class="columns is-centered is-vcentered">
<div class="column has-text-centered">
<video controls autoplay poster="{url_stream($item->video->originCover)}">
<source src="{url_stream($item->video->playAddr)}" type="video/mp4" />
</video>
{include '../components/themes/common/content.latte', item: $item, isAutoplay: true, isBig: true}
</div>
<div class="column">
<div class="box">
@@ -32,6 +34,8 @@
{/if}
<div class="content">
<p n:ifcontent>{$item->desc}</p>
<p>Song: {$item->music->title}</p>
<audio controls preload="none" src="{$item->music->playUrl}"></audio>
{include '../components/themes/common/stats.latte', playCount: $item->stats->playCount, diggCount: $item->stats->diggCount, commentCount: $item->stats->commentCount, shareCount: $item->stats->shareCount}
<div class="has-text-centered">
{include '../components/themes/common/share.latte', uniqueId: $info->detail->uniqueId, id: $item->id}
@@ -41,6 +45,34 @@
</div>
</article>
</div>
{if !empty($item->comments)}
<div class="box">
<p class="is-size-5 has-text-centered">Comments</p>
{foreach $item->comments as $comment}
<article class="media">
<figure class="media-left">
<p class="image is-64x64">
<img src="{url_stream($comment->user->avatar_thumb->url_list[0])}" />
</p>
</figure>
<div class="media-content">
<div class="content">
<p>
<strong>{$comment->user->unique_id}</strong>
<small>
<a href="{url_user($comment->user->unique_id)}">@{$comment->user->nickname}</a>
</small>
<small title="{date('M d, Y H:i:s e', $comment->create_time)}">{date('M d, Y', $comment->create_time)}</small>
<br>
{$comment->text}
</p>
</div>
<p>{include '../components/icon.latte', icon: 'heart', text: number($comment->digg_count)}</p>
</div>
</article>
{/foreach}
</div>
{/if}
</div>
</div>
{/block}