Skip to content

Commit

Permalink
Feat: save cache to disk
Browse files Browse the repository at this point in the history
  • Loading branch information
xtrime-ru committed Aug 14, 2021
1 parent 48aebbc commit bf28e0c
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 52 deletions.
3 changes: 2 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.*
!.env.docker.example
log/
log/*
cache/*
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ vendor
*.madeline
*.madeline.lock
composer.phar
log
log/*
cache/*
36 changes: 36 additions & 0 deletions app/AccessControl/AccessControl.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ class AccessControl
/** @var User[] */
private array $mediaUsers = [];

private const FILES = [
ROOT_DIR . '/cache/users.cache' => 'users',
ROOT_DIR . '/cache/media-users.cache' => 'mediaUsers',
];

/** @var int Interval to remove old clients: 60 seconds */
private const CLEANUP_INTERVAL_MS = 60*1000;
private int $rpmLimit;
Expand All @@ -33,8 +38,11 @@ public function __construct()

$this->clientsSettings = (array) Config::getInstance()->get('access.clients_settings');

$this->loadUsers();

Timer::tick(static::CLEANUP_INTERVAL_MS, function () {
$this->removeOldUsers();
$this->saveUsers();
});
}

Expand All @@ -53,6 +61,34 @@ private function removeOldUsers(): void
}
}

private function saveUsers(): void {
foreach (self::FILES as $path => $object) {
file_put_contents($path, '');
foreach ($this->{$object} as $key => $value) {
file_put_contents($path, serialize([$key=>$value]) . PHP_EOL,FILE_APPEND);
}

}
}

private function loadUsers(): void {
foreach (self::FILES as $path => $object) {
if(file_exists($path)) {
$file = fopen($path, 'rb');
while(!feof($file)) {
$line = fgets($file);
if ($line) {
$line = trim($line);
$item = unserialize($line, ['allowed_classes'=>[User::class]]);
$this->{$object}[array_key_first($item)] = reset($item);
}
}
} else {
$this->{$object} = [];
}
}
}

public function getOrCreateUser(string $ip, string $type = 'default'): User
{
if ($type === 'media') {
Expand Down
55 changes: 42 additions & 13 deletions app/AccessControl/ForbiddenPeers.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,36 @@

namespace TelegramRSS\AccessControl;

use TelegramRSS\Client;
use TelegramRSS\Config;

final class ForbiddenPeers
{
private static ?string $regex = null;

private static $errorTypes = [
'USERNAME_INVALID',
'CHANNEL_PRIVATE',
'This peer is not present in the internal peer database',
];
private static ?string $regex = null;

/** @var array<string, string> */
private static array $peers = [];
private static ?array $peers = null;

private const FILE = ROOT_DIR . '/cache/forbidden-peers.csv';
/** @var resource|null */
private static $filePointer = null;

public static function add(string $peer, string $error): void {
if (
$error === Client::MESSAGE_CLIENT_UNAVAILABLE ||
$error === 'Empty message' ||
$error === 'Connection closed unexpectedly' ||
stripos($error, Client::MESSAGE_FLOOD_WAIT) !== false ||
stripos($error, 'Media') !== false
) {
return;
}

$peer = mb_strtolower($peer);

foreach (self::$errorTypes as $errorType) {
if ($errorType === $error) {
self::$peers[$peer] = $error;
break;
}
}
self::$peers[$peer] = $error;
fputcsv(self::getFilePointer(), [$peer, $error]);
}

/**
Expand All @@ -42,11 +48,34 @@ public static function check(string $peer): ?string {
self::$regex = (string)Config::getInstance()->get('access.forbidden_peer_regex');
}

if (self::$peers === null) {
if (file_exists(self::FILE)) {
$file = self::getFilePointer();
while(!feof($file)){
[$oldPeer, $error] = fgetcsv($file);
if ($oldPeer && $error) {
self::$peers[$oldPeer] = $error;
}
}
}
}

$regex = self::$regex;
if ($regex && preg_match("/{$regex}/i", $peer)) {
return "PEER NOT ALLOWED";
}

return self::$peers[$peer] ?? null;
}

/**
* @return false|resource|null
*/
private static function getFilePointer() {
if (self::$filePointer === null) {
self::$filePointer = fopen(self::FILE, 'cb+');
}

return self::$filePointer;
}
}
7 changes: 4 additions & 3 deletions app/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class Client
private const RETRY = 5;
private const RETRY_INTERVAL = 3;
private const TIMEOUT = 1;
public const CLIENT_UNAVAILABLE_MESSAGE = 'Telegram client connection error';
public const MESSAGE_CLIENT_UNAVAILABLE = 'Telegram client connection error';
public const MESSAGE_FLOOD_WAIT = 'FLOOD_WAIT';

/**
* Client constructor.
Expand Down Expand Up @@ -177,11 +178,11 @@ private function get(string $method, $parameters = [], array $headers = [], stri
if ($errorMessage) {
throw new \UnexpectedValueException($errorMessage, $body->errors[0]->code ?? 400);
}
throw new \UnexpectedValueException(static::CLIENT_UNAVAILABLE_MESSAGE, $curl->statusCode);
throw new \UnexpectedValueException(static::MESSAGE_CLIENT_UNAVAILABLE, $curl->statusCode);
}

if (!$result = $body->response ?? null) {
throw new \UnexpectedValueException(static::CLIENT_UNAVAILABLE_MESSAGE, $curl->statusCode);
throw new \UnexpectedValueException(static::MESSAGE_CLIENT_UNAVAILABLE, $curl->statusCode);
}
return $result;

Expand Down
7 changes: 1 addition & 6 deletions app/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@ private function validate(): self
*/
private function generateResponse(Client $client, Request $request): self
{

if ($this->response['errors']) {
return $this;
}
Expand Down Expand Up @@ -278,14 +277,10 @@ private function generateResponse(Client $client, Request $request): self
);
}
}




} catch (Exception $e) {
$this->response['code'] = $e->getCode() ?: 400;
$this->response['errors'][] = $e->getMessage();
if ($e->getMessage() !== Client::CLIENT_UNAVAILABLE_MESSAGE) {
if ($e->getMessage() !== Client::MESSAGE_CLIENT_UNAVAILABLE) {
$this->user->addError($e->getMessage(), $this->request['url']);
}
ForbiddenPeers::add($this->request['peer'], $e->getMessage());
Expand Down
17 changes: 0 additions & 17 deletions app/Log.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ private function __construct() {
if ($this->file) {
$this->echoLog = false;
}
$this->createDirIfNotExists();
}


Expand Down Expand Up @@ -75,22 +74,6 @@ private function send(string $text): self
return $this;
}

/**
* @return Log
*/
private function createDirIfNotExists(): self
{
if ($this->echoLog) {
return $this;
}
if (!is_dir($this->dir)) {
if (!mkdir($this->dir, 0755, true) && !is_dir($this->dir)) {
throw new \RuntimeException("Directory {$this->dir} was not created");
}
}
return $this;
}

/**
* @return string
*/
Expand Down
Empty file added cache/.gitkeep
Empty file.
18 changes: 7 additions & 11 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file added log/.gitkeep
Empty file.

0 comments on commit bf28e0c

Please sign in to comment.