documentação e padronização

This commit is contained in:
Renan Bernordi 2024-11-26 13:46:20 -03:00
parent 10a8aa43ec
commit f9cefd9328
6 changed files with 85 additions and 61 deletions

View file

@ -91,9 +91,13 @@ A opção de `DEBUG` quando `true` não irá gerar cache!
## ⚙️ Personalizando
No `Rules.php` você pode configurar regras diferentes pra cada site e regras globais
As configurações estão organizadas em `data/`:
Em `config.php` você tem a lista os sites que não quer permitir ou não permitem extrair dados e configurações de User Agents
- `domain_rules.php`: Regras específicas para cada site
- `global_rules.php`: Regras que se aplicam a todos os sites
- `blocked_domains.php`: Lista de sites bloqueados
- `user_agents.php`: Configurações de User Agents
- `messages.php`: Mensagens do sistema
## 🛠️ Manutenção

View file

@ -1,4 +1,5 @@
<?php
/**
* API para análise de URLs
*
@ -28,25 +29,26 @@ $prefix = '/api/';
if (strpos($path, $prefix) === 0) {
$url = urldecode(substr($path, strlen($prefix)));
/**
* Função para enviar resposta JSON padronizada
*
* @param array $data Dados a serem enviados na resposta
* @param int $statusCode Código de status HTTP
*/
function sendResponse($data, $statusCode = 200) {
function sendResponse($data, $statusCode = 200)
{
http_response_code($statusCode);
$response = [
'status' => $statusCode
];
if (isset($data['error'])) {
$response['error'] = $data['error'];
} else if (isset($data['url'])) {
$response['url'] = $data['url'];
}
echo json_encode($response);
exit;
}
@ -64,21 +66,20 @@ if (strpos($path, $prefix) === 0) {
try {
// Instancia o analisador de URLs
$analyzer = new URLAnalyzer();
// Tenta analisar a URL fornecida
$analyzer->analyze($url);
// Se a análise for bem-sucedida, retorna a URL processada
sendResponse([
'url' => SITE_URL . '/p/' . $url
], 200);
} catch (Exception $e) {
// Tratamento de erros com mapeamento para códigos HTTP apropriados
$message = $e->getMessage();
$statusCode = 400;
$errorCode = 'GENERIC_ERROR';
// Mapeia a mensagem de erro para o código e status apropriados
foreach (MESSAGES as $key => $value) {
if (strpos($message, $value['message']) !== false) {
@ -87,10 +88,10 @@ if (strpos($path, $prefix) === 0) {
break;
}
}
// Adiciona header de erro para melhor tratamento no cliente
header('X-Error-Message: ' . $message);
sendResponse([
'error' => [
'code' => $errorCode,

View file

@ -1,4 +1,5 @@
<?php
/**
* Classe responsável pelo gerenciamento de cache do sistema
*
@ -9,7 +10,8 @@
*
* Quando o modo DEBUG está ativo, todas as operações de cache são desativadas.
*/
class Cache {
class Cache
{
/**
* @var string Diretório onde os arquivos de cache serão armazenados
*/
@ -20,7 +22,8 @@ class Cache {
*
* Inicializa o diretório de cache e cria-o se não existir
*/
public function __construct() {
public function __construct()
{
$this->cacheDir = CACHE_DIR;
if (!file_exists($this->cacheDir)) {
mkdir($this->cacheDir, 0777, true);
@ -33,7 +36,8 @@ class Cache {
* @param string $url URL para qual será gerado o ID
* @return string Hash SHA-256 da URL normalizada
*/
public function generateId($url) {
public function generateId($url)
{
// Remove protocolo e www
$url = preg_replace('#^https?://(www\.)?#', '', $url);
// Gera ID único usando SHA-256
@ -46,7 +50,8 @@ class Cache {
* @param string $url URL a ser verificada
* @return bool True se existir cache, False caso contrário
*/
public function exists($url) {
public function exists($url)
{
// Se DEBUG está ativo, sempre retorna false
if (DEBUG) {
return false;
@ -63,7 +68,8 @@ class Cache {
* @param string $url URL do conteúdo a ser recuperado
* @return string|null Conteúdo em cache ou null se não existir
*/
public function get($url) {
public function get($url)
{
// Se DEBUG está ativo, sempre retorna null
if (DEBUG) {
return null;
@ -74,13 +80,13 @@ class Cache {
}
$id = $this->generateId($url);
$cachePath = $this->cacheDir . '/' . $id . '.gz';
// Lê e descomprime o conteúdo
$compressedContent = file_get_contents($cachePath);
if ($compressedContent === false) {
return null;
}
return gzdecode($compressedContent);
}
@ -91,7 +97,8 @@ class Cache {
* @param string $content Conteúdo a ser armazenado em cache
* @return bool True se o cache foi salvo com sucesso, False caso contrário
*/
public function set($url, $content) {
public function set($url, $content)
{
// Se DEBUG está ativo, não gera cache
if (DEBUG) {
return true;
@ -99,13 +106,13 @@ class Cache {
$id = $this->generateId($url);
$cachePath = $this->cacheDir . '/' . $id . '.gz';
// Comprime o conteúdo usando gzip
$compressedContent = gzencode($content, 3);
if ($compressedContent === false) {
return false;
}
return file_put_contents($cachePath, $compressedContent) !== false;
}
}

View file

@ -1,4 +1,5 @@
<?php
/**
* Classe responsável pelo gerenciamento de regras de manipulação de conteúdo
*
@ -7,7 +8,8 @@
* Inclui funcionalidades para remoção de paywalls, elementos específicos,
* manipulação de cookies e execução de códigos customizados.
*/
class Rules {
class Rules
{
/**
* Array associativo contendo regras específicas para cada domínio
*
@ -37,7 +39,8 @@ class Rules {
* @param string $domain Domínio completo
* @return string Domínio base sem www
*/
private function getBaseDomain($domain) {
private function getBaseDomain($domain)
{
return preg_replace('/^www\./', '', $domain);
}
@ -47,19 +50,20 @@ class Rules {
* @param string $domain Domínio a ser dividido
* @return array Array com todas as combinações possíveis do domínio
*/
private function getDomainParts($domain) {
private function getDomainParts($domain)
{
$domain = $this->getBaseDomain($domain);
$parts = explode('.', $domain);
$combinations = [];
for ($i = 0; $i < count($parts) - 1; $i++) {
$combinations[] = implode('.', array_slice($parts, $i));
}
usort($combinations, function($a, $b) {
usort($combinations, function ($a, $b) {
return strlen($b) - strlen($a);
});
return $combinations;
}
@ -69,15 +73,16 @@ class Rules {
* @param string $domain Domínio para buscar regras
* @return array|null Array com regras mescladas ou null se não encontrar
*/
public function getDomainRules($domain) {
public function getDomainRules($domain)
{
$domainParts = $this->getDomainParts($domain);
foreach ($this->domainRules as $pattern => $rules) {
if ($this->getBaseDomain($domain) === $this->getBaseDomain($pattern)) {
return $this->mergeWithGlobalRules($rules);
}
}
foreach ($domainParts as $part) {
foreach ($this->domainRules as $pattern => $rules) {
if ($part === $this->getBaseDomain($pattern)) {
@ -85,7 +90,7 @@ class Rules {
}
}
}
return null;
}
@ -95,7 +100,8 @@ class Rules {
* @param array $rules Regras específicas do domínio
* @return array Regras mescladas
*/
private function mergeWithGlobalRules($rules) {
private function mergeWithGlobalRules($rules)
{
$globalRules = $this->getGlobalRules();
if (isset($rules['excludeGlobalRules']) && is_array($rules['excludeGlobalRules'])) {
@ -130,7 +136,8 @@ class Rules {
*
* @return array Array com todas as regras globais
*/
public function getGlobalRules() {
public function getGlobalRules()
{
return $this->globalRules;
}
}

View file

@ -1,4 +1,5 @@
<?php
/**
* Página principal do sistema
*
@ -38,6 +39,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['url'])) {
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -50,6 +52,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['url'])) {
<meta property="og:image" content="<?php echo SITE_URL; ?>/assets/opengraph.png" />
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-4xl">
<!-- Cabeçalho da página -->
@ -75,18 +78,18 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['url'])) {
<span class="inline-flex items-center px-5 rounded-l-lg border border-r-0 border-gray-300 bg-gray-50 text-gray-500">
<img src="assets/svg/link.svg" class="w-6 h-6" alt="Link">
</span>
<input type="url"
name="url"
id="url"
class="flex-1 block w-full rounded-none rounded-r-lg text-lg py-4 border border-l-0 border-gray-300 bg-gray-50 focus:border-blue-500 focus:ring-blue-500 shadow-sm bg-gray-50"
placeholder="Digite a URL (ex: https://exemplo.com)"
value="<?php echo htmlspecialchars($url); ?>"
required
pattern="https?://.+"
title="Por favor, insira uma URL válida começando com http:// ou https://">
<input type="url"
name="url"
id="url"
class="flex-1 block w-full rounded-none rounded-r-lg text-lg py-4 border border-l-0 border-gray-300 bg-gray-50 focus:border-blue-500 focus:ring-blue-500 shadow-sm bg-gray-50"
placeholder="Digite a URL (ex: https://exemplo.com)"
value="<?php echo htmlspecialchars($url); ?>"
required
pattern="https?://.+"
title="Por favor, insira uma URL válida começando com http:// ou https://">
</div>
<button type="submit"
class="mt-4 w-full inline-flex justify-center items-center px-6 py-4 border border-transparent text-lg font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
<button type="submit"
class="mt-4 w-full inline-flex justify-center items-center px-6 py-4 border border-transparent text-lg font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
<img src="assets/svg/search.svg" class="w-6 h-6 mr-3" alt="Search">
Analisar
</button>
@ -113,13 +116,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['url'])) {
</div>
<?php endif; ?>
</div>
<!-- Exemplo de uso direto -->
<div class="mt-8 text-center text-base text-gray-500">
<p>
<img src="assets/svg/code.svg" class="inline-block w-5 h-5 mr-2" alt="Acesso direito">
Acesso direto:
<pre class="bg-gray-100 p-3 rounded-lg text-sm overflow-x-auto"><?php echo SITE_URL; ?>/p/https://exemplo.com</pre>
Acesso direto:
<pre class="bg-gray-100 p-3 rounded-lg text-sm overflow-x-auto"><?php echo SITE_URL; ?>/p/https://exemplo.com</pre>
</p>
</div>
@ -134,9 +137,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['url'])) {
Arraste o botão abaixo para sua barra de favoritos para acessar o <?php echo SITE_NAME; ?> rapidamente em qualquer página:
</p>
<div class="flex justify-center">
<a href="javascript:(function(){let currentUrl=window.location.href;window.location.href='<?php echo SITE_URL; ?>/p/'+encodeURIComponent(currentUrl);})()"
class="inline-flex items-center px-6 py-3 border-2 border-blue-500 font-medium rounded-lg text-blue-600 bg-white hover:bg-blue-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200 cursor-move"
onclick="return false;">
<a href="javascript:(function(){let currentUrl=window.location.href;window.location.href='<?php echo SITE_URL; ?>/p/'+encodeURIComponent(currentUrl);})()"
class="inline-flex items-center px-6 py-3 border-2 border-blue-500 font-medium rounded-lg text-blue-600 bg-white hover:bg-blue-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200 cursor-move"
onclick="return false;">
<img src="assets/svg/marreta.svg" class="w-5 h-5 mr-2" alt="Marreta">
Abrir no <?php echo SITE_NAME; ?>
</a>
@ -151,15 +154,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['url'])) {
Serviços alternativos
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<a href="https://archive.today" target="_blank"
class="flex items-center p-4 rounded-lg border-2 border-gray-200 hover:border-blue-500 hover:bg-blue-50 transition-all duration-200">
<a href="https://archive.today" target="_blank"
class="flex items-center p-4 rounded-lg border-2 border-gray-200 hover:border-blue-500 hover:bg-blue-50 transition-all duration-200">
<img src="assets/svg/archive.svg" class="w-8 h-8 mr-4" alt="Archive.today">
<div>
<div class="font-medium text-lg text-gray-800">archive.today</div>
</div>
</a>
<a href="https://12ft.io" target="_blank"
class="flex items-center p-4 rounded-lg border-2 border-gray-200 hover:border-green-500 hover:bg-green-50 transition-all duration-200">
class="flex items-center p-4 rounded-lg border-2 border-gray-200 hover:border-green-500 hover:bg-green-50 transition-all duration-200">
<img src="assets/svg/bypass.svg" class="w-8 h-8 mr-4" alt="12ft.io">
<div>
<div class="font-medium text-lg text-gray-800">12ft.io</div>
@ -204,11 +207,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['url'])) {
</div>
<h2 class="text-xl font-semibold text-gray-800 mt-6 mb-6 flex items-center">
<img src="assets/svg/code.svg" class="w-6 h-6 mr-3" alt="Open Source">
Projeto Open Source
Projeto Open Source
</h2>
<div>
<p class="text-gray-600">
Este é um projeto de <a href="https://github.com/manualdousuario/marreta/" class="underline" target="_blank">código aberto</a> feito com ❤️!<br/>
Este é um projeto de <a href="https://github.com/manualdousuario/marreta/" class="underline" target="_blank">código aberto</a> feito com ❤️!<br />
Você pode contribuir, reportar problemas ou fazer sugestões através do <a href="https://github.com/manualdousuario/marreta/" class="underline" target="_blank">GitHub</a>.
</p>
</div>
@ -218,4 +221,5 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['url'])) {
<!-- Scripts JavaScript -->
<script src="assets/js/scripts.js"></script>
</body>
</html>
</html>

View file

@ -1,4 +1,5 @@
<?php
/**
* Processador de URLs
*
@ -22,7 +23,7 @@ $prefix = '/p/';
if (strpos($path, $prefix) === 0) {
// Remove o prefixo e decodifica a URL
$url = urldecode(substr($path, strlen($prefix)));
// Valida o formato da URL
if (filter_var($url, FILTER_VALIDATE_URL)) {
$analyzer = new URLAnalyzer();
@ -35,7 +36,7 @@ if (strpos($path, $prefix) === 0) {
} catch (Exception $e) {
$errorMessage = $e->getMessage();
$errorType = 'GENERIC_ERROR'; // Tipo padrão de erro
// Mapeia a mensagem de erro para um tipo específico
if (strpos($errorMessage, 'bloqueado') !== false) {
$errorType = 'BLOCKED_DOMAIN';
@ -48,7 +49,7 @@ if (strpos($path, $prefix) === 0) {
} elseif (strpos($errorMessage, 'obter conteúdo') !== false) {
$errorType = 'CONTENT_ERROR';
}
// Redireciona para a página inicial com mensagem de erro
header('Location: /?message=' . $errorType);
exit;