Дроп: jscpd v4.1.0 🎩
🚨Що нового:
→ AI Reporter (--reporters ai) - компактний вивід для feeding у LLM
→ MCP Server та Agent Skill для AI-агентів - підключайте через те, що любите
→ Підтримка Apex, CFML, GDScript
🫢Якщо ваш агент задихається на copy-paste у згенерованому коді - спробуйте AI reporter.
🏁Швидкий старт зі скілом:
✔️Скіл працює з Claude, Cursor, Copilot, Gemini та іншими.
До речі, якщо ще не знали - skills.sh це реєстр з купою корисних скілів, не тільки наш.
npm: npmjs.com/package/jscpd
https://github.com/kucherenko/jscpd
#CopyPasteDetector #jscpd #TokenEconomics #LLM
🚨Що нового:
→ AI Reporter (--reporters ai) - компактний вивід для feeding у LLM
→ MCP Server та Agent Skill для AI-агентів - підключайте через те, що любите
→ Підтримка Apex, CFML, GDScript
🫢Якщо ваш агент задихається на copy-paste у згенерованому коді - спробуйте AI reporter.
🏁Швидкий старт зі скілом:
npx skills add kucherenko/jscpd✔️Скіл працює з Claude, Cursor, Copilot, Gemini та іншими.
До речі, якщо ще не знали - skills.sh це реєстр з купою корисних скілів, не тільки наш.
npm: npmjs.com/package/jscpd
https://github.com/kucherenko/jscpd
#CopyPasteDetector #jscpd #TokenEconomics #LLM
❤3👍2🔥2😁1
🎩 Дроп: jscpd v4.2.0
🧩Cross-format detection - головна фіча. Тепер блок коду в одному форматі матчиться з блоком в іншому
🚀 Скрипт у .vue файлі - з
.ts файлом. Code block у Markdown - з .py файлом. Цього не вміє жоден з конкурентів
🔎223 підтримуваних формати - додали 71
новий в одному релізі. Apex, CFML, GDScript,
Svelte, Astro та ще 70+. Найбільший приріст
мов за всю історію проєкту📈
⚡️+11.5% швидше - замінив prismjs на
власний reprism-based engine.
Виміряно на реальному проєкті: 1126ms → 997ms на скані 548 файлів
🔍 Shebang detection - скрипти без розширень (з #!/usr/bin/env python3) тепер автоматично визначаються
🏎️Швидкий старт для AI agents:
Працює з Claude, Cursor, Copilot, Gemini 🤖
🏁Швидкий старт для людей:
У npm: npmjs.com/package/jscpd
changelog: github.com/kucherenko/jscpd/blob/master/CHANGELOG.md
P.S. Якщо jscpd колись зекономив вам час, прошу
підтримати на opencollective.com/jscpd
#CopyPasteDetector #jscpd #TokenEconomics #LLM
🧩Cross-format detection - головна фіча. Тепер блок коду в одному форматі матчиться з блоком в іншому
🚀 Скрипт у .vue файлі - з
.ts файлом. Code block у Markdown - з .py файлом. Цього не вміє жоден з конкурентів
🔎223 підтримуваних формати - додали 71
новий в одному релізі. Apex, CFML, GDScript,
Svelte, Astro та ще 70+. Найбільший приріст
мов за всю історію проєкту📈
⚡️+11.5% швидше - замінив prismjs на
власний reprism-based engine.
Виміряно на реальному проєкті: 1126ms → 997ms на скані 548 файлів
🔍 Shebang detection - скрипти без розширень (з #!/usr/bin/env python3) тепер автоматично визначаються
🏎️Швидкий старт для AI agents:
npx skills add kucherenko/jscpd
Працює з Claude, Cursor, Copilot, Gemini 🤖
🏁Швидкий старт для людей:
npx jscpd ./path
У npm: npmjs.com/package/jscpd
changelog: github.com/kucherenko/jscpd/blob/master/CHANGELOG.md
P.S. Якщо jscpd колись зекономив вам час, прошу
підтримати на opencollective.com/jscpd
#CopyPasteDetector #jscpd #TokenEconomics #LLM
❤5🔥3👏3
Поки тиша на каналі - я писав статтю на HackerNoon.
Запустив jscpd на 49 проектах з GitHub, які створені AI-агентами. Хотів виміряти скільки коду вони копіпастять.
Знайшов інше🤯
Перший проект у рейтингу за дуплікацією виявився не AI-додатком, а бібліотекою скілів для AI-агентів.
Другий - теж
бібліотека скілів.
Третій - фреймворк
для агентів.
‼️Тобто інфраструктура, яка вчить AI писати чистий код, сама на 30-40% складається з повторів.
Стаття пройде editorial review - кину посилання. А поки що почитайте сирі дані:
🔗 kucherenko.github.io/cpd-vibe-coding-report
Цікаво подивитись на свій проект jscpd-ом?
#CopyPasteDetector #jscpd #TokenEconomics #LLM #SDD #VibeCoding #SpecDrivenDevelopment
Запустив jscpd на 49 проектах з GitHub, які створені AI-агентами. Хотів виміряти скільки коду вони копіпастять.
Знайшов інше🤯
Перший проект у рейтингу за дуплікацією виявився не AI-додатком, а бібліотекою скілів для AI-агентів.
Другий - теж
бібліотека скілів.
Третій - фреймворк
для агентів.
‼️Тобто інфраструктура, яка вчить AI писати чистий код, сама на 30-40% складається з повторів.
Стаття пройде editorial review - кину посилання. А поки що почитайте сирі дані:
🔗 kucherenko.github.io/cpd-vibe-coding-report
Цікаво подивитись на свій проект jscpd-ом?
#CopyPasteDetector #jscpd #TokenEconomics #LLM #SDD #VibeCoding #SpecDrivenDevelopment
❤8🔥4👏3
42% дублів. Не в коді від AI - у файлах, що вчать AI не дублювати‼️
Я просканував 49 AI-згенерованих проектів на GitHub
🍋У 7.24 млн рядків коду:
🔁 25 612 дубльованих блоків
📊 7,98% середнє дублювання
⚠️ 45 із 49 проектів - з дублями
Думав, найгірші — «vibe-coded» застосунки, зліплені за вихідні з AI. Виявилось - ні. 6–9%. Вище норми, але не критично.
А далі - головний парадокс.
Skill-бібліотеки - markdown-інструкції, що вчать Claude, Cursor, Gemini й Codex поводитись правильно - дали 30–42% дублів
Я підтримую jscpd 13 років. Бачив багато дублів. Але це нова форма: шар, що вчить машини дисципліни, - найменш дисциплінований у стеку
Повна методологія, топ-10 і застереження 👇
🔗https://hackernoon.com/what-49-vibe-coded-github-projects-revealed-about-ai-code-duplication
#CopyPasteDetector #jscpd #LLM #SDD #VibeCoding #SpecDrivenDevelopment
Я просканував 49 AI-згенерованих проектів на GitHub
🍋У 7.24 млн рядків коду:
🔁 25 612 дубльованих блоків
📊 7,98% середнє дублювання
⚠️ 45 із 49 проектів - з дублями
Думав, найгірші — «vibe-coded» застосунки, зліплені за вихідні з AI. Виявилось - ні. 6–9%. Вище норми, але не критично.
А далі - головний парадокс.
Найвищий рівень дублювання спостерігався в інфраструктурі, створеній для того, щоб AI-агенти генерували чистий кодSkill-бібліотеки - markdown-інструкції, що вчать Claude, Cursor, Gemini й Codex поводитись правильно - дали 30–42% дублів
Я підтримую jscpd 13 років. Бачив багато дублів. Але це нова форма: шар, що вчить машини дисципліни, - найменш дисциплінований у стеку
Повна методологія, топ-10 і застереження 👇
🔗https://hackernoon.com/what-49-vibe-coded-github-projects-revealed-about-ai-code-duplication
#CopyPasteDetector #jscpd #LLM #SDD #VibeCoding #SpecDrivenDevelopment
❤6👍5🔥3👏1
jscpd v5: 83 секунди → 3.4 секунди
Copy-paste detector для коду тепер у 24–37 разів швидший - повне переписування engine на Rust.
Реальні цифри (10 прогонів, Apple Silicon, v4 Node.js проти v5):
→ 548 файлів: 1.03с → 0.03с (34x)
→ 9K файлів, 164 MB: 15.8с → 0.43с (37x)
→ 17K файлів, 902 MB: 83с → 3.4с (24x)
Чому різниця така велика:
Зник startup overhead - на малому репозиторії майже весь 1.03с був запуском Node.js, ще до
сканування. Нативний бінарник стартує миттєво.
Тепер усі ядра - старий engine був однопотоковий, новий спалює 7.3с CPU за 3.4с реального часу.
І головне: drop-in заміна. Ті самі прапорці, конфіг, 223 формати.
Встановлення те саме -
Запустіть на своєму найбільшому репозиторії і напишіть результат у коментарях)
github.com/kucherenko/jscpd
#CopyPasteDetector #jscpd #TokenEconomics #LLM
Copy-paste detector для коду тепер у 24–37 разів швидший - повне переписування engine на Rust.
Реальні цифри (10 прогонів, Apple Silicon, v4 Node.js проти v5):
→ 548 файлів: 1.03с → 0.03с (34x)
→ 9K файлів, 164 MB: 15.8с → 0.43с (37x)
→ 17K файлів, 902 MB: 83с → 3.4с (24x)
Чому різниця така велика:
Зник startup overhead - на малому репозиторії майже весь 1.03с був запуском Node.js, ще до
сканування. Нативний бінарник стартує миттєво.
Тепер усі ядра - старий engine був однопотоковий, новий спалює 7.3с CPU за 3.4с реального часу.
І головне: drop-in заміна. Ті самі прапорці, конфіг, 223 формати.
Встановлення те саме -
npm install -g jscpd.Запустіть на своєму найбільшому репозиторії і напишіть результат у коментарях)
github.com/kucherenko/jscpd
#CopyPasteDetector #jscpd #TokenEconomics #LLM
🔥9👍8❤2👏2
А ви знали, що більше знайдених дублікатів не означає кращий пошук? Іноді це лише більше… помилок.
Я постійно вдосконалюю свій jscpd, тож вирішив перевірити, як справляються інші. Зібрав сім інструментів і прогнав на одній базі: 547 файлів, 150+ форматів, для всіх однакові умови.
І ось що показали цифри.
Багато клонів, мало сенсу:
⚠️ Duplo - 162 мс, 518 клонів, найбільше з усіх. Зіставляє сирий текст без токенізації, реагує на відмінності у форматуванні - тому більшість збігів false positives.
Майже нічого не бачить:
⚠️ Fallow dupes - 164 мс, 10 клонів. Аналізує лише JS/TS, решту 513 файлів із 547 не опрацьовує - непридатний для багатомовних баз.
Повільні й обмежені в покритті:
⚠️ Simian - 964 мс, 424 клони. Звітує агрегованими блоками, без поділу на мови - не зрозуміти, у якій секції коду дублікат.
⚠️ PMD CPD - 36 с, 56 клонів. Ретельний у межах однієї мови, але повільний: опрацював лише 71 файл із 547.
Один клон різниці - і 32 рази у швидкості. Переписування на Rust дало приріст, зберігши якість виявлення:
✅ jscpd v5 (Rust) - 84 мс, 212 клонів.
✅ jscpd v4 (JavaScript) - 2.7 с, 211 клонів.
Суть у тому, що велике число знайдених клонів нічого не гарантує. Текстові інструменти швидкі, але завищують кількість збігами, яких насправді немає. Точні працюють повільно або бачать лише кілька форматів. Токенізація дозволяє не вибирати: тримає і швидкість, і точність водночас.
Це перший із трьох розборів цього бенчмарку. Далі - як інструменти розпізнають дублікати між різними форматами файлів, і скільки токенів з'їдає звіт кожного з них під час роботи з LLM (частина 2)
🔗 Повний бенчмарк: jscpd.dev/benchmarks/detection-speed
💻 GitHub: github.com/kucherenko/jscpd
☕ Підтримати: opencollective.com/jscpd
#CopyPasteDetector #jscpd #TokenEconomics #LLM
Я постійно вдосконалюю свій jscpd, тож вирішив перевірити, як справляються інші. Зібрав сім інструментів і прогнав на одній базі: 547 файлів, 150+ форматів, для всіх однакові умови.
І ось що показали цифри.
Багато клонів, мало сенсу:
⚠️ Duplo - 162 мс, 518 клонів, найбільше з усіх. Зіставляє сирий текст без токенізації, реагує на відмінності у форматуванні - тому більшість збігів false positives.
Майже нічого не бачить:
⚠️ Fallow dupes - 164 мс, 10 клонів. Аналізує лише JS/TS, решту 513 файлів із 547 не опрацьовує - непридатний для багатомовних баз.
Повільні й обмежені в покритті:
⚠️ Simian - 964 мс, 424 клони. Звітує агрегованими блоками, без поділу на мови - не зрозуміти, у якій секції коду дублікат.
⚠️ PMD CPD - 36 с, 56 клонів. Ретельний у межах однієї мови, але повільний: опрацював лише 71 файл із 547.
Один клон різниці - і 32 рази у швидкості. Переписування на Rust дало приріст, зберігши якість виявлення:
✅ jscpd v5 (Rust) - 84 мс, 212 клонів.
✅ jscpd v4 (JavaScript) - 2.7 с, 211 клонів.
Суть у тому, що велике число знайдених клонів нічого не гарантує. Текстові інструменти швидкі, але завищують кількість збігами, яких насправді немає. Точні працюють повільно або бачать лише кілька форматів. Токенізація дозволяє не вибирати: тримає і швидкість, і точність водночас.
Це перший із трьох розборів цього бенчмарку. Далі - як інструменти розпізнають дублікати між різними форматами файлів, і скільки токенів з'їдає звіт кожного з них під час роботи з LLM (частина 2)
🔗 Повний бенчмарк: jscpd.dev/benchmarks/detection-speed
💻 GitHub: github.com/kucherenko/jscpd
☕ Підтримати: opencollective.com/jscpd
#CopyPasteDetector #jscpd #TokenEconomics #LLM
👍6🔥4❤1👏1
Дуже легко. Показую.
Той самий код, ті самі 212 дублікатів. Один інструмент пошуку копіпасту віддає AI звіт на 2 800 токенів, інший — на 158 000.
Різниця — це ваші гроші, спалені на токенах.
Проблема:
Більшість інструментів видають «важкі» звіти, не оптимізовані для LLM — величезні JSON або неструктуровані дані. Вони забивають контекстне вікно, сповільнюють відповідь і роздувають вартість кожного запиту.
А тепер наочно. Ефективність на 212 клонах:
🔴 Гроші на вітер — не для LLM:
• Duplo — 158 000 токенів, величезний JSON із купою false positives
• PMD CPD — 21 000 токенів, розкидані по 34 файлах
🟡 Частково придатні:
• Simian — 15 000 токенів, без структурованих метаданих
• Fallow — 400 токенів, та це не економія: він просто бачить мізерну частину коду
🟢 Готові до роботи з AI — економно:
• jscpd@5 — 2 800 токенів
• jscpd@4 — 2 700 токенів
• jscpd-rs — 3 000 токенів
У jscpd є окремий флаг --reporters ai — компактний звіт без зайвого шуму, створений саме для AI-пайплайнів.
⚠️ Важлива ремарка:
Токени на клон не можна порівнювати між інструментами напряму — кожен визначає «клон» по-своєму. Порівнюйте лише всередині однієї групи.
Висновок:
Коли звіт іде в LLM, його розмір — це прямі витрати вашого часу й бюджету. Той самий результат можна віддати економно або спалити на ньому гроші. Обирайте інструменти, які поважають ваш токен-ліміт.
Це друга з трьох частин про порівняння Copy-Paste Detector (CPD) інструментів. Частина 1 — про швидкість. Далі — як інструменти бачать дублікати між різними форматами файлів.
🔗 Бенчмарк токенів: jscpd.dev/benchmarks/ai-token-efficiency
💻 GitHub: github.com/kucherenko/jscpd
☕ Підтримати: opencollective.com/jscpd
#TokenEconomics #LLM #CopyPasteDetector #jscpd
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11👏2❤1🔥1
🍋jscpd має 1,5 млн завантажень на тиждень. І я не вгадую, що в ньому покращити. Я це вимірюю.
⁉ Як зрозуміти, чого вартий твій продукт порівняно з іншими?
‼️ Запустити бенчмарк 🚀
Я взяв 7 copy-paste детекторів і прогнав усі на одній базі: 547 файлів, 223 формати, однакові умови для всіх.
Результати показав тут:
⚡️ Швидкість
🪙 Токени
🧩 Формати - сьогодні, фінальна 👇
👀 Дуже часто Copy-Paste Detector каже, що «дублікатів немає». Але він просто не зазирнув всередину ваших Vue- та Svelte-файлів. Сучасний файл - це не суцільний текст: один .vue, .svelte чи .astro містить кілька мов одразу - скрипт, стилі, шаблон. У markdown - YAML і блоки коду. І те, як інструмент це читає, вирішує все.
Існує 2 види інструментів:
🔴 Flat-text - порівнюють усе з усім: CSS зі скриптом, шаблон зі стилями. Або шум, або сліпота: звіт каже «чисто», а копіпаст лишається в коді.
🟢 Section-aware - спершу парсить файл, ділить на мови, і лише потім порівнює CSS із CSS, скрипт зі скриптом. Це вміє лише движок jscpd.
👨🏻💻Окремо про markdown: код усередині .md jscpd дістає з блоку й порівнює як код, а не як текст документації. Дубль, схований у прикладі коду, більше не проходить повз.
Результат: знайти дублікати між різними форматами (наприклад, однаковий CSS у .svelte та .astro) здатні лише три інструменти. І всі - на jscpd.
💡 Висновок.
У сучасних проектах дублікати ховаються не в тексті, а в структурі. Інструмент, який бачить лише текст, у найгіршому випадку звітує «чисто» - і ви вірите цьому звіту. Якщо інструмент не розуміє секцій усередині файлу - він не розуміє frontend.
🔗 Бенчмарк форматів: jscpd.dev/benchmarks/cross-format
💻 GitHub:github.com/kucherenko/jscpd
☕ Підтримати:opencollective.com/jscpd
А ваш CPD точно бачить дублікати у .vue і .svelte - чи просто каже «чисто»?
👍 Бачить, я перевіряв
👀 Не знаю - піду перевірю
😱 Тепер боюся дивитися
#jscpd #CopyPasteDetector
Сьогодні - про внутрішню кухню роботи над open-source проектом.
⁉ Як зрозуміти, чого вартий твій продукт порівняно з іншими?
‼️ Запустити бенчмарк 🚀
Я взяв 7 copy-paste детекторів і прогнав усі на одній базі: 547 файлів, 223 формати, однакові умови для всіх.
Результати показав тут:
⚡️ Швидкість
🪙 Токени
🧩 Формати - сьогодні, фінальна 👇
👀 Дуже часто Copy-Paste Detector каже, що «дублікатів немає». Але він просто не зазирнув всередину ваших Vue- та Svelte-файлів. Сучасний файл - це не суцільний текст: один .vue, .svelte чи .astro містить кілька мов одразу - скрипт, стилі, шаблон. У markdown - YAML і блоки коду. І те, як інструмент це читає, вирішує все.
Існує 2 види інструментів:
🔴 Flat-text - порівнюють усе з усім: CSS зі скриптом, шаблон зі стилями. Або шум, або сліпота: звіт каже «чисто», а копіпаст лишається в коді.
🟢 Section-aware - спершу парсить файл, ділить на мови, і лише потім порівнює CSS із CSS, скрипт зі скриптом. Це вміє лише движок jscpd.
👨🏻💻Окремо про markdown: код усередині .md jscpd дістає з блоку й порівнює як код, а не як текст документації. Дубль, схований у прикладі коду, більше не проходить повз.
Результат: знайти дублікати між різними форматами (наприклад, однаковий CSS у .svelte та .astro) здатні лише три інструменти. І всі - на jscpd.
💡 Висновок.
У сучасних проектах дублікати ховаються не в тексті, а в структурі. Інструмент, який бачить лише текст, у найгіршому випадку звітує «чисто» - і ви вірите цьому звіту. Якщо інструмент не розуміє секцій усередині файлу - він не розуміє frontend.
💻 GitHub:
☕ Підтримати:
А ваш CPD точно бачить дублікати у .vue і .svelte - чи просто каже «чисто»?
👍 Бачить, я перевіряв
👀 Не знаю - піду перевірю
😱 Тепер боюся дивитися
#jscpd #CopyPasteDetector
👍8❤3😱3👀2
This media is not supported in your browser
VIEW IN TELEGRAM
97% вашого коду - «унікальні». Так каже інструмент, який не бачить дубль, якщо змінну просто назвали інакше.
👀 jscpd 5.2.0 бачить.
Три класи копій, які раніше не потрапляли у звіт: перейменовані, зі вставленим рядком і переписані по всій функції.
Половину цього коду написав агент, а він не робить Ctrl+C: генерує заново і рідко тими самими іменами. Тому дірка у звіті - не крайній випадок, а норма.
1. Перейменовані копії
--ignore-identifiers, --ignore-literals, --ignore-annotations
Нормалізують класи токенів перед хешуванням: усі ідентифікатори стають одним класом, ключові слова зберігають своє значення, рядки і числа лишаються різними класами, анотації @Name(...) відкидаються. Java, Kotlin, Scala, Groovy, Python, Dart, Swift, JS, TS. Копія з іншими іменами тепер має kind: renamed.
2. Копії з розривом
--max-gap-lines N
Копія, куди вставили рядок посередині, раніше показувалась як два коротких клони. Тепер фрагменти однієї пари файлів, між якими не більше N незіставлених рядків, зливаються в один клон kind: similar зі значенням similarity. Схожість нижче 0.5 - злиття не відбувається.
3. Схожість функцій, JS/TS
--similarity RATIO
Правки, розмазані по всій функції, не ловить жодне вікно токенів. jscpd порівнює кожну функцію, метод і стрілкову функцію за набором 4-грам по типах вузлів AST та індексує через MinHash. Імена і літерали участі не беруть: перейменована копія дає 1.0, один вставлений рядок - близько 0.9, дві вставлені інструкції плюс перейменування - близько 0.75.
Кожен клон тепер несе kind: exact, renamed або similar - у консолі, JSON, XML і HTML. У SARIF і Code Climate додались правила jscpd/renamed-code та jscpd/similar-code.
На npm зараз 5 156 441 М завантаження за тиждень. Саме тому все нове - opt-in: жоден з цих пайплайнів не змінить поведінку після оновлення. Без прапорців результат той самий, плюс поле "kind": "exact".
Реліз v5.2.0
Яка у вас цифра дублювання у CI і скільки їй років?
👀 - зараз перевірю
🔥 - вже перевірив
#jscpd #CopyPasteDetector
Три класи копій, які раніше не потрапляли у звіт: перейменовані, зі вставленим рядком і переписані по всій функції.
Половину цього коду написав агент, а він не робить Ctrl+C: генерує заново і рідко тими самими іменами. Тому дірка у звіті - не крайній випадок, а норма.
1. Перейменовані копії
--ignore-identifiers, --ignore-literals, --ignore-annotations
Нормалізують класи токенів перед хешуванням: усі ідентифікатори стають одним класом, ключові слова зберігають своє значення, рядки і числа лишаються різними класами, анотації @Name(...) відкидаються. Java, Kotlin, Scala, Groovy, Python, Dart, Swift, JS, TS. Копія з іншими іменами тепер має kind: renamed.
2. Копії з розривом
--max-gap-lines N
Копія, куди вставили рядок посередині, раніше показувалась як два коротких клони. Тепер фрагменти однієї пари файлів, між якими не більше N незіставлених рядків, зливаються в один клон kind: similar зі значенням similarity. Схожість нижче 0.5 - злиття не відбувається.
3. Схожість функцій, JS/TS
--similarity RATIO
Правки, розмазані по всій функції, не ловить жодне вікно токенів. jscpd порівнює кожну функцію, метод і стрілкову функцію за набором 4-грам по типах вузлів AST та індексує через MinHash. Імена і літерали участі не беруть: перейменована копія дає 1.0, один вставлений рядок - близько 0.9, дві вставлені інструкції плюс перейменування - близько 0.75.
Кожен клон тепер несе kind: exact, renamed або similar - у консолі, JSON, XML і HTML. У SARIF і Code Climate додались правила jscpd/renamed-code та jscpd/similar-code.
На npm зараз 5 156 441 М завантаження за тиждень. Саме тому все нове - opt-in: жоден з цих пайплайнів не змінить поведінку після оновлення. Без прапорців результат той самий, плюс поле "kind": "exact".
Реліз v5.2.0
Яка у вас цифра дублювання у CI і скільки їй років?
👀 - зараз перевірю
🔥 - вже перевірив
#jscpd #CopyPasteDetector
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥5👀3👏2