3 pontos por GN⁺ 2024-08-30 | 1 comentários | Compartilhar no WhatsApp
  • Ao navegar pela internet, foi encontrado um componente interessante de arte ASCII. Parecia muito legal, mas era difícil entender como tinha sido implementado
  • Ao verificar o código-fonte, o código estava minificado

Exemplo de código minificado

  • Parte do código era a seguinte:
    const { floor: ra, abs: KE, min: QE } = Math,  
      O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"],  
      G7 = Date.now() % 3 ? O5[1] : O5[0],  
      V5 = G7.length,  
      JE = { fps: 60 };  
    

Pedido ao ChatGPT para explicar o código

  • Foi pedido ao ChatGPT: "explique o código"
  • Resposta do ChatGPT:

    O código fornecido é bastante complexo, mas vou explicar cada parte e sua função de forma clara.

Visão geral

  • Define várias funções e componentes usando JavaScript
  • Gera conteúdo de texto dinâmico em uma aplicação React
  • Cria um efeito visual usando arte ASCII ou um conjunto de caracteres predefinido

Principais componentes e funções

  1. Seleção do conjunto de caracteres:
const { floor: ra, abs: KE, min: QE } = Math;  
const O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"];  
const G7 = Date.now() % 3 ? O5[1] : O5[0];  
const V5 = G7.length;  
  • Importa funções de Math e define dois conjuntos de caracteres
  • Seleciona um conjunto de caracteres com base no horário atual
  • Armazena o comprimento do conjunto de caracteres selecionado
  1. Função de seleção dinâmica de caracteres:
function eT(e, t, n, r) {  
  const i = t.time * 8e-5;  
  const s = QE(t.cols, t.rows);  
  const o = t.metrics.aspect * 0.2;  
  const l = { x: ((4 * (e.x - t.cols / 6.25)) / s) * o, y: (5 * (e.y - t.rows / 4)) / s };  
  const u = ra(KE(YE(l) - i) * V5 + (ra(e.x / 1) % 2) * 2) % V5;  
  return G7[u];  
}  
  • A função eT gera caracteres com base na posição de entrada e no tempo atual
  • Ajusta a posição e seleciona um caractere do conjunto de caracteres
  1. Componente React (tT) que exibe conteúdo dinâmico:
const tT = () => {  
  const e = j.useRef(null);  
  const [t, n] = j.useState({ height: null, width: null });  
  j.useEffect(() => {  
    function r() {  
      n({ height: window.innerHeight, width: window.innerWidth });  
    }  
    if (typeof window < "u") {  
      n({ height: window.innerHeight, width: window.innerWidth });  
      window.addEventListener("resize", r);  
      return () => window.removeEventListener("resize", r);  
    }  
  }, []);  
  j.useEffect(() => {  
    const r = e.current;  
    if (!r) return;  
    const i = 12;  
    const s = ra(t.width / i) * 1.6;  
    const o = ra(t.height / i);  
    const l = { aspect: s / o };  
    const u = setInterval(() => {  
      let c = "";  
      for (let d = 0; d < o; d++) {  
        for (let f = 0; f < s; f++) c += eT({ x: f, y: d }, { cols: s, rows: o, metrics: l, time: Date.now() });  
        c += `  `;  
      }  
      r.textContent = c;  
    }, 1e3 / JE.fps);  
    return () => clearInterval(u);  
  }, [t]);  
  return a.jsx("div", { style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }, children: a.jsx("div", { ref: e, style: { width: "100%", height: "100%", whiteSpace: "pre", overflow: "hidden" } }) });  
};  
  • Este componente React atualiza periodicamente o conteúdo de um elemento div com caracteres gerados dinamicamente
  • Calcula o número de colunas e linhas de acordo com o tamanho da janela e preenche a div com caracteres

Código convertido para TypeScript

  • Foi pedido ao ChatGPT o código convertido para TypeScript
  • Resposta do ChatGPT:
    import React, { useEffect, useRef, useState } from 'react';  
    const selectedCharacterSet = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ";  
    const characterSetLength = selectedCharacterSet.length;  
    
    const calculateCharacter = (  
      x: number,  
      y: number,  
      cols: number,  
      rows: number,  
      aspect: number,  
      time: number,  
    ): string => {  
      const timeFactor = time * 0.000_08;  
      const size = Math.min(cols, rows);  
      const aspectRatio = aspect * 0.2;  
      const position = {  
        x: ((4 * (x - cols / 6.25)) / size) * aspectRatio,  
        y: (5 * (y - rows / 4)) / size,  
      };  
      const index = Math.floor(  
        Math.abs(  
          Math.cos(position.x * position.x - position.y * position.y) - timeFactor,  
        ) * characterSetLength + (Math.floor(x) % 2) * 2,  
      ) % characterSetLength;  
      return selectedCharacterSet[index];  
    };  
    
    type Size = {  
      height: null | number;  
      width: null | number;  
    };  
    
    const AsciiArtGenerator: React.FC = () => {  
      const textRef = useRef(null);  
      const [size, setSize] = useState({ height: null, width: null });  
    
      useEffect(() => {  
        const handleResize = () => {  
          setSize({ height: window.innerHeight, width: window.innerWidth });  
        };  
        handleResize();  
        window.addEventListener('resize', handleResize);  
        return () => {  
          window.removeEventListener('resize', handleResize);  
        };  
      }, []);  
    
      useEffect(() => {  
        const element = textRef.current;  
        if (!element || !size.width || !size.height) return undefined;  
    
        const cols = Math.floor(size.width / 12) * 1.6;  
        const rows = Math.floor(size.height / 12);  
        const aspectRatio = cols / rows;  
    
        const intervalId = setInterval(() => {  
          let content = '';  
          for (let y = 0; y < rows; y++) {  
            for (let x = 0; x < cols; x++) {  
              content += calculateCharacter(x, y, cols, rows, aspectRatio, Date.now());  
            }  
            content += '\n';  
          }  
          element.textContent = content;  
        }, 1_000 / 60);  
    
        return () => {  
          clearInterval(intervalId);  
        };  
      }, [size]);  
    
      return (  
    
      );  
    };  
    
    export default () => {  
      return ;  
    };  
    

Resumo do GN⁺

  • Este texto explica como entender e restaurar código minificado
  • Mostra o processo de usar o ChatGPT para explicar código complexo e convertê-lo para TypeScript
  • Apresenta uma forma de usar ferramentas de IA para ajudar na restauração e compreensão de código
  • Projetos com funcionalidade semelhante incluem Prettier e UglifyJS

1 comentários

 
GN⁺ 2024-08-30
Comentários do Hacker News
  • O autor do HumanifyJS desenvolveu uma ferramenta baseada em LLM. Ela usa LLM no nível de AST para garantir que o código continue funcionando após o unminification

  • A minificação de JS é mecânica e relativamente simples. É incômodo fazer isso manualmente, mas a transformação em si é limitada, então dá para ler acompanhando os identificadores com algumas anotações

  • Unminification ou unobfuscation em geral ainda é um problema não resolvido. No passado, alguém escreveu intencionalmente programas ofuscados, e o ChatGPT não conseguia entendê-los nem em nível superficial

    • Exemplo: o GPT-4 tentou explicar um interpretador Brainfuck de 160 bytes, mas o resultado não se parecia em nada com o código original
    • Link do código de exemplo
  • Alguns desenvolvedores podem ficar insatisfeitos porque usam minificação para ofuscação. Havia pessoas que usavam a ferramenta de "criptografia" de código oferecida em versões antigas do ColdFusion achando que era segura, apesar de o algoritmo ser fraco

  • Pode ser mais apropriado usar ChatGPT ou gpt-4 no título em vez de OpenAI

  • Este trabalho é um exemplo de desempenho intelectual superior ao humano. O LLM entende unminification e, neste tópico específico, é superior aos humanos

  • LLMs são excelentes em transformação de texto. Esse é o ponto forte central deles

  • Cerca de um ano atrás, alguém tentou usar GPT para desfazer a ofuscação de malware, mas analisar o código diretamente era melhor. Ao tentar de novo recentemente, já foi possível entendê-lo em certa medida

    • Exemplo: identificar a lógica que detecta o carregamento da página, faz cálculos e redireciona para um site malicioso
    • Link do relatório
  • Usar LLM para tornar códigos complexos mais legíveis é algo muito libertador. Às vezes ele deixa passar detalhes, mas isso pode ser verificado diretamente

    • Dá para entender o propósito do código, mas quando não se entende por que ele foi escrito de uma certa forma, é possível perguntar ao LLM e obter novos insights
    • Link de exemplo de uso
  • Se o código unminified não corresponder ao código minified, a utilidade cai bastante. Em muitos casos, não dá para verificar as diferenças depois de executar o código

  • Quando alguém quer saber o algoritmo de cálculo de um site, podia colocar o JS minificado no ChatGPT e entender facilmente. Dá para imaginar um futuro em que LLMs consigam clonar um app SaaS inteiro

    • Exemplo: para criar um clone do HubSpot, um LLM poderia interagir com o navegador, analisar a UI e sugerir a arquitetura de backend
    • A IA será um forte fator deflacionário no futuro