Removed Following (use RSS), allow unix for Redis

This commit is contained in:
Pablo Ferreiro 2022-02-06 14:22:23 +01:00
parent 84023905ff
commit 3772eabd99
No known key found for this signature in database
GPG key ID: 41FBCE65B779FA24
23 changed files with 144 additions and 205 deletions

View file

@ -4,8 +4,9 @@
# API_CACHE=redis # Cache engine for TikTok Api, (more info on README) # API_CACHE=redis # Cache engine for TikTok Api, (more info on README)
# Redis cache, used on Helpers\CacheEngines\RedisCache (CHOOSE ONE) # Redis cache, used on Helpers\CacheEngines\RedisCache (CHOOSE ONE)
# REDIS_URL=redis://:password@host:port # If using password # REDIS_HOST=localhost # Host or path to unix socket
# REDIS_URL=redis://host:port # If not using password # REDIS_PORT=6379 # Set to -1 to use unix socket
# REDIS_PASSWORD=example # Leave commented for no password
# JSON cache, used on Helpers\CacheEngines\JSONCache # JSON cache, used on Helpers\CacheEngines\JSONCache
# API_CACHE_JSON=/tmp/proxitok_api # Path for JSON API Cache, leave commented for ./cache/api # API_CACHE_JSON=/tmp/proxitok_api # Path for JSON API Cache, leave commented for ./cache/api

25
.github/workflows/tag.yaml vendored Normal file
View file

@ -0,0 +1,25 @@
name: Create Tag
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Get version
id: version
uses: notiz-dev/github-action-json-property@release
with:
path: 'composer.json'
prop_path: 'version'
- name: Create Release
uses: ncipollo/release-action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag: v${{steps.version.outputs.prop}}
allowUpdates: true

View file

@ -57,10 +57,11 @@ location /proxitok/.env {
* Add a NoJS version / Make the whole program without required JS * Add a NoJS version / Make the whole program without required JS
* Better error handling * Better error handling
* Make video on /video fit screen and don't overflow * Make video on /video fit screen and don't overflow
* Allow custom Region/Language * i18n
## Credits ## Credits
* [TikTok-API-PHP](https://github.com/ssovit/TikTok-API-PHP) (Currently using my personal fork) * [TikTok-API-PHP](https://github.com/ssovit/TikTok-API-PHP) (Currently using my personal fork)
* [Latte](https://github.com/nette/latte)
* [bramus/router](https://github.com/bramus/router) * [bramus/router](https://github.com/bramus/router)
* [PHP dotenv](https://github.com/vlucas/phpdotenv) * [PHP dotenv](https://github.com/vlucas/phpdotenv)
* [Bulma](https://github.com/jgthms/bulma) and [Bulmaswatch](https://github.com/jenil/bulmaswatch) * [Bulma](https://github.com/jgthms/bulma) and [Bulmaswatch](https://github.com/jenil/bulmaswatch)

View file

@ -27,7 +27,7 @@ class RedisCache {
return null; return null;
} }
public function set(string $cache_key, mixed $data, $timeout = 3600) { public function set(string $cache_key, array $data, $timeout = 3600) {
$this->client->set($cache_key, json_encode($data), $timeout); $this->client->set($cache_key, json_encode($data), $timeout);
} }
} }

View file

@ -1,15 +0,0 @@
<?php
namespace App\Controllers;
use App\Helpers\Following;
use App\Helpers\Misc;
use App\Models\FollowingTemplate;
class FollowingController {
static public function get() {
$users = Following::getUsers();
$feed = Following::getAll($users);
$latte = Misc::latte();
$latte->render(Misc::getView('following'), new FollowingTemplate($users, $feed));
}
}

View file

@ -3,7 +3,6 @@ namespace App\Controllers;
use App\Helpers\Misc; use App\Helpers\Misc;
use App\Helpers\Cookies; use App\Helpers\Cookies;
use App\Helpers\Following;
use App\Models\SettingsTemplate; use App\Models\SettingsTemplate;
class SettingsController { class SettingsController {
@ -21,34 +20,4 @@ class SettingsController {
$url = Misc::url('/settings'); $url = Misc::url('/settings');
header("Location: {$url}"); header("Location: {$url}");
} }
static public function following() {
$following = Following::getUsers();
if (!isset($_POST['mode']) || empty($_POST['mode'])) {
die('You need to send a mode');
}
switch ($_POST['mode']) {
case 'add':
// Add following
array_push($following, $_POST['account']);
break;
case 'remove':
// Remove following
$index = array_search($_POST['account'], $following);
if ($index !== false) {
unset($following[$index]);
}
break;
default:
// Invalid
die('Invalid mode');
}
// Build string
$following_string = implode(',', $following);
Cookies::set('following', $following_string);
$url = Misc::url('/settings');
header("Location: {$url}");
}
} }

View file

@ -1,37 +0,0 @@
<?php
namespace App\Helpers;
class Following {
static public function getUsers (): array {
$following_string = Cookies::get('following');
if ($following_string) {
return explode(',', $following_string);
}
return [];
}
static public function getAll (array $users): object {
$allowed_items_total = isset($_GET['max']) && is_numeric($_GET['max']) && $_GET['max'] <= 100 ? $_GET['max'] : 20;
$items = [];
if (count($users) !== 0) {
$api = Misc::api();
$max_items_per_user = $allowed_items_total / count($users);
foreach ($users as $user) {
$user_feed = $api->getUserFeed($user);
if ($user_feed) {
$max = count($user_feed->items) > $max_items_per_user ? $max_items_per_user : count($user_feed->items);
for ($i = 0; $i < $max; $i++) {
$item = $user_feed->items[$i];
array_push($items, $item);
}
}
}
}
$feed = (object) [
'items' => $items,
'hasMore' => false
];
return $feed;
}
};

View file

@ -43,14 +43,20 @@ class Misc {
$cacheEngine = new JSONCache(); $cacheEngine = new JSONCache();
break; break;
case 'redis': case 'redis':
if (!isset($_ENV['REDIS_URL'])) { if (!(isset($_ENV['REDIS_URL']) || isset($_ENV['REDIS_HOST'], $_ENV['REDIS_PORT']))) {
throw new \Exception('You need to set REDIS_URL to use Redis Cache!'); throw new \Exception('You need to set REDIS_URL or REDIS_HOST and REDIS_PORT to use Redis Cache!');
} }
$url = parse_url($_ENV['REDIS_URL']); if (isset($_ENV['REDIS_URL'])) {
$host = $url['host']; $url = parse_url($_ENV['REDIS_URL']);
$port = $url['port']; $host = $url['host'];
$password = $url['pass'] ?? null; $port = $url['port'];
$password = $url['pass'] ?? null;
} else {
$host = $_ENV['REDIS_HOST'];
$port = (int) $_ENV['REDIS_PORT'];
$password = isset($_ENV['REDIS_PASSWORD']) ? $_ENV['REDIS_PASSWORD'] : null;
}
$cacheEngine = new RedisCache($host, $port, $password); $cacheEngine = new RedisCache($host, $port, $password);
break; break;
} }
@ -77,7 +83,7 @@ class Misc {
return \Composer\InstalledVersions::getVersion('pablouser1/proxitok'); return \Composer\InstalledVersions::getVersion('pablouser1/proxitok');
}); });
// https://stackoverflow.com/a/36365553 // https://stackoverflow.com/a/36365553
$latte->addFunction('number', function (int $x) { $latte->addFunction('number', function (float $x) {
if($x > 1000) { if($x > 1000) {
$x_number_format = number_format($x); $x_number_format = number_format($x);
$x_array = explode(',', $x_number_format); $x_array = explode(',', $x_number_format);

View file

@ -1,14 +0,0 @@
<?php
namespace App\Models;
/**
* Exclusive for /following
*/
class FollowingTemplate extends FeedTemplate {
public array $following;
function __construct(array $following, object $feed) {
parent::__construct('Following', $feed);
$this->following = $following;
}
}

View file

@ -2,18 +2,15 @@
namespace App\Models; namespace App\Models;
use App\Helpers\Cookies; use App\Helpers\Cookies;
use App\Helpers\Following;
/** /**
* Exclusive for /settings * Exclusive for /settings
*/ */
class SettingsTemplate extends BaseTemplate { class SettingsTemplate extends BaseTemplate {
public array $proxy_elements = []; public array $proxy_elements = [];
public array $following = [];
function __construct() { function __construct() {
parent::__construct('Settings'); parent::__construct('Settings');
$this->proxy_elements = Cookies::PROXY; $this->proxy_elements = Cookies::PROXY;
$this->following = Following::getUsers();
} }
} }

11
components/card.latte Normal file
View 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>

View file

@ -17,13 +17,11 @@
{/foreach} {/foreach}
</div> </div>
<div n:ifset="$feed->info" class="buttons"> <div n:ifset="$feed->info" class="buttons">
<a n:ifset="$_GET['cursor']" class="button is-danger" href="?cursor=0">First</a> {if isset($_GET['cursor']) && $_GET['cursor'] != 0}
<a class="button is-danger" href="?cursor={$feed->minCursor}">Back</a> <a class="button is-danger" href="?cursor=0">First</a>
{if $feed->hasMore} <a class="button is-danger" href="?cursor={$feed->minCursor}">Back</a>
<a n-if="$feed->hasMore" class="button is-success" href="?cursor={$feed->maxCursor}">Next</a> {/if}
{else} <a n:attr="disabled => $feed->hasMore" class="button is-success" href="?cursor={$feed->maxCursor}">Next</a>
<a class="button is-success" disabled title="No more videos available">Next</a>
{/if}
</div> </div>
</section> </section>

View file

@ -2,6 +2,9 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta property="og:title" content="ProxiTok" />
<meta property="og:description" content="Alternative frontend for TikTok" />
<meta property="og:type" content="website" />
<link rel="stylesheet" href="{path('/styles/bulma.min.css')}"> <link rel="stylesheet" href="{path('/styles/bulma.min.css')}">
<title>{$title} - ProxiTok</title> <title>{$title} - ProxiTok</title>
</head> </head>

View file

@ -10,7 +10,6 @@
<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('/')}" class="navbar-item">Home</a> <a href="{path('/')}" class="navbar-item">Home</a>
<a href="{path('/following')}" class="navbar-item">Following</a>
<a href="{path('/settings')}" class="navbar-item">Settings</a> <a href="{path('/settings')}" class="navbar-item">Settings</a>
<a href="{path('/about')}" class="navbar-item">About</a> <a href="{path('/about')}" class="navbar-item">About</a>
</div> </div>

View file

@ -1,24 +0,0 @@
{include '../following_tags.latte'}
<form action="{path('/settings/following')}" method="POST">
<div class="field">
<label class="label">Add / Remove user</label>
<div class="control">
<input name="account" class="input" type="text" />
</div>
</div>
<div class="field">
<div class="control">
<label class="radio">
<input type="radio" name="mode" value="add">Add
</label>
<label class="radio">
<input type="radio" name="mode" value="remove">Remove
</label>
</div>
</div>
<div class="field">
<div class="control">
<button class="button is-primary" type="submit">Send</button>
</div>
</div>
</form>

View file

@ -1,7 +1,7 @@
{ {
"name": "pablouser1/proxitok", "name": "pablouser1/proxitok",
"description": "An alternative frontend for TikTok", "description": "An alternative frontend for TikTok",
"version": "1.4.0", "version": "1.4.1",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"type": "project", "type": "project",
"homepage": "https://github.com/pablouser1/ProxiTok", "homepage": "https://github.com/pablouser1/ProxiTok",

10
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "aef85efe0a29f3778e75eff24c3e8b67", "content-hash": "b40da817e3b81d14a1ed55aad52cf434",
"packages": [ "packages": [
{ {
"name": "bramus/router", "name": "bramus/router",
@ -381,12 +381,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/pablouser1/TikTok-API-PHP.git", "url": "https://github.com/pablouser1/TikTok-API-PHP.git",
"reference": "26e3c089bc409a324136cd4465d5489210cb73c3" "reference": "c6667d70757fd5405ee1b51eaa6602d8758d2abd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/pablouser1/TikTok-API-PHP/zipball/26e3c089bc409a324136cd4465d5489210cb73c3", "url": "https://api.github.com/repos/pablouser1/TikTok-API-PHP/zipball/c6667d70757fd5405ee1b51eaa6602d8758d2abd",
"reference": "26e3c089bc409a324136cd4465d5489210cb73c3", "reference": "c6667d70757fd5405ee1b51eaa6602d8758d2abd",
"shasum": "" "shasum": ""
}, },
"type": "library", "type": "library",
@ -425,7 +425,7 @@
"issues": "https://github.com/ssovit/TikTok-API-PHP/issues", "issues": "https://github.com/ssovit/TikTok-API-PHP/issues",
"email": "sovit.tamrakar@gmail.com" "email": "sovit.tamrakar@gmail.com"
}, },
"time": "2022-02-05T23:47:32+00:00" "time": "2022-02-06T13:17:16+00:00"
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",

View file

@ -39,8 +39,6 @@ $router->get('/music/([^/]+)', 'MusicController@get');
$router->mount('/settings', function () use ($router) { $router->mount('/settings', function () use ($router) {
$router->get('/', 'SettingsController@index'); $router->get('/', 'SettingsController@index');
$router->post('/proxy', 'SettingsController@proxy'); $router->post('/proxy', 'SettingsController@proxy');
$router->post('/following', 'SettingsController@following');
}); });
$router->get('/discover', 'DiscoverController@get'); $router->get('/discover', 'DiscoverController@get');
$router->get('/following', 'FollowingController@get');

View file

@ -1,9 +1,31 @@
{layout '../layouts/default.latte'} {layout '../layouts/default.latte'}
{block header} {block header}
<p class="title">About</p> <p class="title">Welcome to Proxitok!</p>
<p class="subtitle">An alternative frontend for TikTok</p>
{/block} {/block}
{block content} {block content}
<p>TODO</p> <p class="title">Why?</p>
<p>
There are already
<a rel="nofollow" href="https://penetrum.com/tiktok/Penetrum_TikTok_Security_Analysis_whitepaper.pdf">multiple</a>
<a rel="nofollow" href="https://rufposten.de/blog/2019/12/05/privacy-analysis-of-tiktoks-app-and-website">articles</a>
<a rel="nofollow" href="https://citizenlab.ca/2021/03/tiktok-vs-douyin-security-privacy-analysis">explaining</a>
Tiktok's privacy issues.
This program allows you to browse TikTok without having to worry about privacy concerns.
</p>
<hr />
<p class="title">Third party</p>
<p>
This project wouldn't be possible without the help of the following projects:
<ul>
<li><a rel="nofollow" href="https://github.com/ssovit/TikTok-API-PHP">TikTok-API-PHP</a></li>
<li><a rel="nofollow" href="https://github.com/nette/latte">Latte</a></li>
<li><a rel="nofollow" href="https://github.com/bramus/router">bramus/router</a></li>
<li><a rel="nofollow" href="https://github.com/vlucas/phpdotenv">PHP dotenv</a></li>
<li><a rel="nofollow" href="https://github.com/jgthms/bulma">Bulma</a> and <a href="https://github.com/jenil/bulmaswatch">Bulmaswatch</a></li>
<li><a rel="nofollow" href="https://github.com/mibe/FeedWriter">FeedWriter</a></li>
</ul>
</p>
{/block} {/block}

View file

@ -10,29 +10,30 @@
<div class="columns is-multiline is-vcentered"> <div class="columns is-multiline is-vcentered">
{foreach $items as $item} {foreach $items as $item}
<div class="column is-one-quarter"> <div class="column is-one-quarter">
<a href="{path($item->cardItem->link)}"> {embed '../components/card.latte'}
<div class="card"> {block content}
<div class="card-content"> <div class="media">
<div class="media"> <!-- Show image if exists -->
<!-- Show image if exists --> {if !empty($item->cardItem->cover)}
{if !empty($item->cardItem->cover)} <div class="media-left">
<div class="media-left"> <figure class="image is-96x96">
<figure class="image is-96x96"> <img width="96" height="96" src="{path('/stream?url=' . urlencode($item->cardItem->cover))}" />
<img width="96" height="96" src="{path('/stream?url=' . urlencode($item->cardItem->cover))}" /> </figure>
</figure>
</div>
{/if}
<div class="media-content">
<p class="title">{$item->cardItem->title}</p>
<p class="subtitle">{$item->cardItem->subTitle}</p>
</div> </div>
</div> {/if}
<div class="content"> <div class="media-content">
<p>{$item->cardItem->description}</p> <p class="title">{$item->cardItem->title}</p>
<p class="subtitle">{$item->cardItem->subTitle}</p>
</div> </div>
</div> </div>
</div> <div class="content">
</a> <p>{$item->cardItem->description}</p>
</div>
{/block}
{block footer}
<a href="{path($item->cardItem->link)}" class="card-footer-item">Go</a>
{/block}
{/embed}
</div> </div>
{/foreach} {/foreach}
</div> </div>

View file

@ -1,10 +0,0 @@
{layout '../layouts/default.latte'}
{block header}
<p class="title">Following</p>
{/block}
{block content}
<p>{include '../components/following_tags.latte'}</p>
{include '../components/feed.latte'}
{/block}

View file

@ -4,23 +4,35 @@
<p class="title">Welcome to ProxiTok!</p> <p class="title">Welcome to ProxiTok!</p>
<p class="subtitle">An alternative open source frontend for TikTok</p> <p class="subtitle">An alternative open source frontend for TikTok</p>
<!-- Create forms from App\Models\HomeTemplate --> <!-- Create forms from App\Models\HomeTemplate -->
{foreach $forms as $form} <div class="columns is-centered is-vcentered is-multiline">
<p>{$form['title']}</p> {foreach $forms as $form}
<form action="{path('/redirect')}"> <div class="column is-narrow">
<div class="field has-addons has-addons-centered"> {embed '../components/card.latte'}
<div class="control"> {block title}{$form['title']}{/block}
<input name="{$form['input']}" class="input" type="text" placeholder="{$form['placeholder']}" required /> {block content}
</div> <form action="{path('/redirect')}">
<div class="control"> <div class="field has-addons has-addons-centered">
<button class="button is-success" type="submit">Go</button> <div class="control">
</div> <input name="{$form['input']}" class="input" type="text" placeholder="{$form['placeholder']}" required />
</div>
<div class="control">
<button class="button is-success" type="submit">Search</button>
</div>
</div>
</form>
{/block}
{/embed}
</div> </div>
</form> {/foreach}
<hr /> </div>
{/foreach} <div class="columns is-centered is-mobile">
<p>Discover</p> <div class="column is-narrow">
<a class="button is-success" href="{path('/discover')}">Go</a> <p>Discover</p>
<hr /> <a class="button is-success" href="{path('/discover')}">Go</a>
<p>Trending</p> </div>
<a class="button is-success" href="{path('/trending')}">Go</a> <div class="column is-narrow">
<p>Trending</p>
<a class="button is-success" href="{path('/trending')}">Go</a>
</div>
</div>
{/block} {/block}

View file

@ -8,8 +8,4 @@
<!-- Proxy settings --> <!-- Proxy settings -->
<p class="title">Proxy</p> <p class="title">Proxy</p>
{include '../components/settings/proxy.latte'} {include '../components/settings/proxy.latte'}
<hr />
<!-- Following -->
<p class="title">Following</p>
{include '../components/settings/following.latte'}
{/block} {/block}