web manifest tweaks and .latte structure
This commit is contained in:
parent
4bfc4c9434
commit
1176bc35fe
34 changed files with 3 additions and 3 deletions
11
templates/components/card.latte
Normal file
11
templates/components/card.latte
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<div class="card">
|
||||
<header class="card-header" n:ifcontent>
|
||||
<p class="card-header-title" n:ifcontent>{block title}{/block}</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
{block content}{/block}
|
||||
</div>
|
||||
<footer class="card-footer" n:ifcontent>
|
||||
{block footer}{/block}
|
||||
</footer>
|
||||
</div>
|
||||
1
templates/components/feed.latte
Normal file
1
templates/components/feed.latte
Normal file
|
|
@ -0,0 +1 @@
|
|||
{include './themes/' . theme() . '.latte'}
|
||||
10
templates/components/form.latte
Normal file
10
templates/components/form.latte
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<form action="{path($path)}" method="{$method}">
|
||||
{block fields}{/block}
|
||||
{ifset $submit}
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<button class="button is-success" type="submit">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
{/ifset}
|
||||
</form>
|
||||
19
templates/components/head.latte
Normal file
19
templates/components/head.latte
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<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="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:site_name" content="ProxiTok" />
|
||||
<meta property="og:title" content="{$title}" />
|
||||
<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>
|
||||
</head>
|
||||
14
templates/components/icon.latte
Normal file
14
templates/components/icon.latte
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{define icon_common, $icon}
|
||||
<span class="icon">
|
||||
<i class="gg-{$icon}"></i>
|
||||
</span>
|
||||
{/define}
|
||||
|
||||
{if isset($text)}
|
||||
<span class="icon-text">
|
||||
{include icon_common, icon: $icon}
|
||||
<span>{$text}</span>
|
||||
</span>
|
||||
{else}
|
||||
{include icon_common, icon: $icon}
|
||||
{/if}
|
||||
29
templates/components/navbar.latte
Normal file
29
templates/components/navbar.latte
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<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>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navbar-menu" class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
<a href="{path('/settings')}" class="navbar-item">
|
||||
{include './icon.latte', icon: 'options', text: '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>
|
||||
3
templates/components/rss.latte
Normal file
3
templates/components/rss.latte
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<a href="{$_SERVER['REQUEST_URI'] . '/rss'}">
|
||||
{include './icon.latte', icon: 'feed', text: 'RSS Feed'}
|
||||
</a>
|
||||
31
templates/components/settings/api.latte
Normal file
31
templates/components/settings/api.latte
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{embed '../form.latte', path: '/settings/api', method: 'POST', submit: true}
|
||||
{block fields}
|
||||
<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 => $isTestEndpoints" />
|
||||
<span>Yes</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<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}
|
||||
16
templates/components/settings/general.latte
Normal file
16
templates/components/settings/general.latte
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{embed '../form.latte', path: '/settings/general', method: 'POST', submit: true}
|
||||
{block fields}
|
||||
<div class="field">
|
||||
<label class="label">Theme</label>
|
||||
<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>
|
||||
{/block}
|
||||
{/embed}
|
||||
18
templates/components/settings/misc.latte
Normal file
18
templates/components/settings/misc.latte
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{embed '../form.latte', path: '/settings/misc', method: 'POST', submit: true}
|
||||
{block fields}
|
||||
<div class="field">
|
||||
<label class="label">Enable service worker</label>
|
||||
<div class="control">
|
||||
<label class="radio">
|
||||
<input type="radio" name="misc-sw" value="yes" n:attr="checked => $isServiceWorker" />
|
||||
<span>Yes</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="misc-sw" value="no" n:attr="checked => !$isServiceWorker" />
|
||||
<span>No</span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="help">This can be used to install the PWA version of ProxiTok</p>
|
||||
</div>
|
||||
{/block}
|
||||
{/embed}
|
||||
70
templates/components/themes/card.latte
Normal file
70
templates/components/themes/card.latte
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<link rel="stylesheet" href="{path('/styles/themes/card.css')}">
|
||||
<noscript>JavaScript is required for this section to work!</noscript>
|
||||
<section class="section">
|
||||
<div class="columns is-multiline is-vcentered">
|
||||
{foreach $data->feed->items as $item}
|
||||
{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="{url_stream($item->video->playAddr)}"
|
||||
data-video_download_watermark="{url_download($item->video->playAddr, $item->author->uniqueId, $item->id, true)}"
|
||||
data-video_download_nowatermark="{url_download(url_video_external($item->author->uniqueId, $item->id), $item->author->uniqueId, $item->id, false)}"
|
||||
data-video_share_url="{$share_url}"
|
||||
data-desc="{$item->desc}"
|
||||
data-createtime="{$item->createTime}"
|
||||
data-music_title="{$item->music->title}"
|
||||
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)}
|
||||
<p class="title">No items sent by TikTok!</p>
|
||||
{/if}
|
||||
</div>
|
||||
{include './common/controls.latte'}
|
||||
</section>
|
||||
|
||||
<!-- MODAL -->
|
||||
<div id="modal" class="modal">
|
||||
<div id="modal-background" class="modal-background"></div>
|
||||
<div class="modal-card">
|
||||
<header class="modal-card-head">
|
||||
<button id="modal-close" class="delete" aria-label="close"></button>
|
||||
<p class="modal-card-title" id="item_title"></p>
|
||||
</header>
|
||||
<section class="modal-card-body has-text-centered" style="overflow: hidden;">
|
||||
<video id="video" autoplay controls></video>
|
||||
</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 />
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-primary" onclick="copyShare()">Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="download_dropdown" class="dropdown is-hoverable">
|
||||
<div class="dropdown-trigger">
|
||||
<button id="download_button" class="button" aria-haspopup="true" aria-controls="dropdown-menu">Download</button>
|
||||
</div>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<div class="dropdown-content">
|
||||
<a id="download_watermark" target="_blank" class="dropdown-item">With watermark</a>
|
||||
<a id="download_nowatermark" target="_blank" class="dropdown-item">Without watermark</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p id="audio_title"></p>
|
||||
<audio id="audio" controls preload="none"></audio>
|
||||
<div class="buttons is-centered">
|
||||
<button id="back-button" class="button is-danger">Back</button>
|
||||
<button id="next-button" class="button is-success">Next</button>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{path('/scripts/themes/card.js')}"></script>
|
||||
7
templates/components/themes/common/controls.latte
Normal file
7
templates/components/themes/common/controls.latte
Normal file
|
|
@ -0,0 +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}
|
||||
<a class="button is-danger" href="?cursor=0">First</a>
|
||||
{/if}
|
||||
<a n:attr="disabled => !$data->feed->hasMore" class="button is-success" href="?cursor={$data->feed->maxCursor}">Next</a>
|
||||
</div>
|
||||
13
templates/components/themes/common/download.latte
Normal file
13
templates/components/themes/common/download.latte
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<div class="dropdown is-hoverable">
|
||||
<div class="dropdown-trigger">
|
||||
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu">
|
||||
{include '../../icon.latte', icon: 'software-download', text: 'Download'}
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<div class="dropdown-content">
|
||||
<a target="_blank" href="{url_download($playAddr, $uniqueId, $id, true)}" class="dropdown-item">Watermark</a>
|
||||
<a target="_blank" href="{url_download(url_video_external($uniqueId, $id), $uniqueId, $id, false)}" class="dropdown-item">No watermark</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
5
templates/components/themes/common/share.latte
Normal file
5
templates/components/themes/common/share.latte
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{do $endpoint = '/@' . $uniqueId . '/video/' . $id}
|
||||
<div class="buttons is-centered">
|
||||
<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>
|
||||
6
templates/components/themes/common/stats.latte
Normal file
6
templates/components/themes/common/stats.latte
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<p>
|
||||
{include '../../icon.latte', icon: 'eye', text: number($playCount)}
|
||||
{include '../../icon.latte', icon: 'heart', text: number($diggCount)}
|
||||
{include '../../icon.latte', icon: 'comment', text: number($commentCount)}
|
||||
{include '../../icon.latte', icon: 'share', text: number($shareCount)}
|
||||
</p>
|
||||
5
templates/components/themes/common/tags.latte
Normal file
5
templates/components/themes/common/tags.latte
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<div class="tags">
|
||||
{foreach $challenges as $challenge}
|
||||
<a class="tag is-rounded is-info" href="{path('/tag/' . $challenge->title)}">{$challenge->title}</a>
|
||||
{/foreach}
|
||||
</div>
|
||||
38
templates/components/themes/default.latte
Normal file
38
templates/components/themes/default.latte
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<div class="container">
|
||||
{foreach $data->feed->items as $item}
|
||||
<article class="media">
|
||||
<figure class="media-left">
|
||||
<p class="image is-64x64">
|
||||
<img src="{url_stream($item->author->avatarThumb)}" />
|
||||
</p>
|
||||
</figure>
|
||||
<div class="media-content">
|
||||
<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="{url_stream($item->video->originCover)}">
|
||||
<source src="{url_stream($item->video->playAddr)}" type="video/mp4" />
|
||||
</video>
|
||||
</div>
|
||||
<div class="has-text-centered">
|
||||
{include './common/share.latte', uniqueId: $item->author->uniqueId, id: $item->id}
|
||||
{include './common/download.latte', playAddr: $item->video->playAddr, id: $item->id, uniqueId: $item->author->uniqueId}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
{/foreach}
|
||||
{if empty($data->feed->items)}
|
||||
<p class="title">No items sent by TikTok!</p>
|
||||
{/if}
|
||||
</div>
|
||||
{include './common/controls.latte'}
|
||||
20
templates/layouts/default.latte
Normal file
20
templates/layouts/default.latte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
{include '../components/head.latte'}
|
||||
|
||||
<body>
|
||||
{include '../components/navbar.latte'}
|
||||
<section class="hero is-primary">
|
||||
<div class="hero-body">
|
||||
<div class="container has-text-centered">
|
||||
{block header}{/block}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="section">
|
||||
{block content}{/block}
|
||||
</section>
|
||||
{block extra}{/block}
|
||||
</body>
|
||||
</html>
|
||||
10
templates/layouts/embed.latte
Normal file
10
templates/layouts/embed.latte
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
{include '../components/head.latte'}
|
||||
|
||||
<body>
|
||||
{block content}{/block}
|
||||
{block extra}{/block}
|
||||
</body>
|
||||
</html>
|
||||
20
templates/layouts/hero.latte
Normal file
20
templates/layouts/hero.latte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
{include '../components/head.latte'}
|
||||
|
||||
<body>
|
||||
<section class="hero is-fullheight">
|
||||
<div class="hero-head">
|
||||
{include '../components/navbar.latte'}
|
||||
</div>
|
||||
<div class="hero-body">
|
||||
<div class="container has-text-centered">
|
||||
{block content}{/block}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{block extra}{/block}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
40
templates/views/about.latte
Normal file
40
templates/views/about.latte
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
{layout '../layouts/default.latte'}
|
||||
|
||||
{block header}
|
||||
<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>
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
<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}
|
||||
44
templates/views/discover.latte
Normal file
44
templates/views/discover.latte
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
{layout '../layouts/default.latte'}
|
||||
|
||||
{block header}
|
||||
<p class="title">Discover</p>
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
{foreach $data->feed->items as $type => $items}
|
||||
<p class="title">{$type|firstUpper}</p>
|
||||
<div class="columns is-multiline is-vcentered">
|
||||
{foreach $items as $item}
|
||||
<div class="column is-one-quarter">
|
||||
{embed '../components/card.latte'}
|
||||
{block content}
|
||||
<div class="media">
|
||||
<!-- Show image if exists -->
|
||||
{if !empty($item->cardItem->cover)}
|
||||
<div class="media-left">
|
||||
<figure class="image is-96x96">
|
||||
<img loading="lazy" width="96" height="96" src="{path('/stream?url=' . urlencode($item->cardItem->cover))}" />
|
||||
</figure>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="media-content">
|
||||
<p class="title">{$item->cardItem->title}</p>
|
||||
<p class="subtitle">{$item->cardItem->subTitle}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{$item->cardItem->description}</p>
|
||||
</div>
|
||||
{/block}
|
||||
{block footer}
|
||||
<a href="{path($item->cardItem->link)}" class="card-footer-item">Go</a>
|
||||
{/block}
|
||||
{/embed}
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
{if !$iterator->last}
|
||||
<hr />
|
||||
{/if}
|
||||
{/foreach}
|
||||
{/block}
|
||||
18
templates/views/error.latte
Normal file
18
templates/views/error.latte
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{layout '../layouts/hero.latte'}
|
||||
|
||||
{block content}
|
||||
<p class="title">There was an error processing your request!</p>
|
||||
<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}
|
||||
</div>
|
||||
{/block}
|
||||
41
templates/views/home.latte
Normal file
41
templates/views/home.latte
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{layout '../layouts/hero.latte'}
|
||||
|
||||
{block content}
|
||||
<p class="title">Welcome to ProxiTok!</p>
|
||||
<p class="subtitle">An alternative open source frontend for TikTok</p>
|
||||
{embed '../components/form.latte', path: '/redirect', method: 'GET'}
|
||||
{block fields}
|
||||
<div class="field has-addons has-addons-centered">
|
||||
<div class="control">
|
||||
<input class="input" name="term" placeholder="Search" required>
|
||||
</div>
|
||||
<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>
|
||||
<option value="video">Video ID</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button type="submit" class="button is-success">
|
||||
{include '../components/icon.latte', icon: 'search', text: 'Search'}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
{/embed}
|
||||
<div class="columns is-centered is-mobile">
|
||||
<div class="column is-narrow">
|
||||
<p>Discover</p>
|
||||
<a class="button is-success" href="{path('/discover')}">Go</a>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<p>Trending</p>
|
||||
<a class="button is-success" href="{path('/trending')}">Go</a>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
11
templates/views/music.latte
Normal file
11
templates/views/music.latte
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{layout '../layouts/default.latte'}
|
||||
|
||||
{block header}
|
||||
<p class="title">{$data->info->detail->title}</p>
|
||||
<p class="subtitle">{$data->info->detail->desc}</p>
|
||||
<p>Videos: {number($data->info->stats->videoCount)}</p>
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
{include '../components/feed.latte'}
|
||||
{/block}
|
||||
21
templates/views/rss.latte
Normal file
21
templates/views/rss.latte
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{contentType application/rss+xml}
|
||||
{do header('Content-Disposition: attachment; filename="' . $title . '.rss' . '"')}
|
||||
{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>
|
||||
<title>{$title}</title>
|
||||
<description><![CDATA[{$desc}]]></description>
|
||||
<link>{$full_link}</link>
|
||||
<atom:link href="{$full_link . '/rss'}" rel="self" type="application/rss+xml"></atom:link>
|
||||
{foreach $items as $item}
|
||||
<item>
|
||||
<title>{$item->desc}</title>
|
||||
<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>
|
||||
</item>
|
||||
{/foreach}
|
||||
</channel>
|
||||
</rss>
|
||||
17
templates/views/settings.latte
Normal file
17
templates/views/settings.latte
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{layout '../layouts/default.latte'}
|
||||
|
||||
{block header}
|
||||
<p class="title">Settings</p>
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
<div class="content">
|
||||
<p class="title">General</p>
|
||||
{include '../components/settings/general.latte'}
|
||||
</div>
|
||||
<hr />
|
||||
<div class="content">
|
||||
<p class="title">Api</p>
|
||||
{include '../components/settings/api.latte'}
|
||||
</div>
|
||||
{/block}
|
||||
18
templates/views/tag.latte
Normal file
18
templates/views/tag.latte
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{layout '../layouts/default.latte'}
|
||||
|
||||
{var $has_rss = true}
|
||||
|
||||
{block header}
|
||||
{if $data->info->detail->profileThumb !== ''}
|
||||
<figure class="figure is-96x96">
|
||||
<img src="{path('/stream?url=' . urlencode($data->info->detail->profileThumb))}" />
|
||||
</figure>
|
||||
{/if}
|
||||
<p class="title">{$data->info->detail->title}</p>
|
||||
<p class="subtitle">{include '../components/rss.latte'}</p>
|
||||
<p>Videos: {number($data->info->stats->videoCount)} / Views: {number($data->info->stats->viewCount)}</p>
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
{include '../components/feed.latte'}
|
||||
{/block}
|
||||
12
templates/views/trending.latte
Normal file
12
templates/views/trending.latte
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{layout '../layouts/default.latte'}
|
||||
|
||||
{var $has_rss = true}
|
||||
|
||||
{block header}
|
||||
<p class="title">Trending</p>
|
||||
<p class="subtitle">{include '../components/rss.latte'}</p>
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
{include '../components/feed.latte'}
|
||||
{/block}
|
||||
18
templates/views/user.latte
Normal file
18
templates/views/user.latte
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{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))}" />
|
||||
</figure>
|
||||
<p class="title">{$data->info->detail->uniqueId}</p>
|
||||
<p class="subtitle">{include '../components/rss.latte'}</p>
|
||||
<p>{$data->info->detail->signature}</p>
|
||||
<p>Following: {number($data->info->stats->followingCount)} / Followers: {number($data->info->stats->followerCount)}</p>
|
||||
<p>Hearts: {number($data->info->stats->heartCount)} / Videos: {$data->info->stats->videoCount}</p>
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
{include '../components/feed.latte'}
|
||||
{/block}
|
||||
38
templates/views/verify.latte
Normal file
38
templates/views/verify.latte
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{layout '../layouts/default.latte'}
|
||||
|
||||
{block header}
|
||||
<p class="title">VERIFY_CODE</p>
|
||||
<p class="subtitle">What can I do?</p>
|
||||
{/block}
|
||||
|
||||
{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 api:</p>
|
||||
<hr />
|
||||
<div class="block">
|
||||
<p class="is-size-4">Rate limits</p>
|
||||
<p>
|
||||
This is pretty standard stuff,
|
||||
it blocks ips temporarly if you send too many requests to an endpoint and unbans you after some hours.
|
||||
</p>
|
||||
</div>
|
||||
<div class="block">
|
||||
<p class="is-size-4">IP Blacklist</p>
|
||||
<p>
|
||||
It is a list with IPs from popular Hosters (AWS, Heroku...). This IPs are banned <i>(I think) permanently</i> and
|
||||
can barely make requests.
|
||||
</p>
|
||||
<p>
|
||||
This makes hosting a public instance really hard. Even if you use a hosting platform that is not banned by TikTok, it is only a matter of time
|
||||
that it inevitably gets banned.
|
||||
</p>
|
||||
<p class="is-size-5">(For webmasters) How can I know if my server is not blacklisted?</p>
|
||||
<p>Run this command on your instance:</p>
|
||||
<code>
|
||||
curl \
|
||||
--url 'https://www.tiktok.com/@tiktok/?lang=en' \
|
||||
--header 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36'
|
||||
</code>
|
||||
<p>If you don't get an empty response or a captcha, you are good to go</p>
|
||||
</div>
|
||||
{/block}
|
||||
25
templates/views/video.latte
Normal file
25
templates/views/video.latte
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{layout "../layouts/{$layout}.latte"}
|
||||
|
||||
{block content}
|
||||
<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">
|
||||
<div class="box">
|
||||
<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}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
Loading…
Add table
Add a link
Reference in a new issue