Интеграция с NocoDB для вывода списка рефералов по USER_ID. Реализовано на PuzzleBot

СПИСОК РЕФЕРАЛОВ
СПИСОК РЕФЕРАЛОВ

В этой статье мы рассмотрим, как в Puzzle можно интегрировать NocoDB с вашими мини-приложениями для вывода списка рефералов, приглашенных пользователями. Мы используем JavaScript для создания простого интерфейса, который позволяет пользователям вводить идентификатор (ID) и получать соответствующий список рефералов.

Основные элементы кода

const token = 'заIT43zdIy2vXNEXmLV*********'; const tableUrl = 'https://nocodb.puzzlebot.top/api/v2/tables/m0o0ba8********/records';

Что такое token и tableUrl?

- token: это токен аутентификации, который используется при обращении к API NocoDB. Он позволяет вашему приложению делать запросы к вашему табличному хранилищу.

- tableUrl: это URL-адрес API, который ссылается на таблицу в NocoDB, содержащую записи рефералов.

Функция searchUsers

async function searchUsers() { const userId = document.getElementById('userIdInput').value.trim(); const resultsContainer = document.getElementById('results'); const loadingIndicator = document.getElementById('loading'); if (!userId) { showError('Рефералы не найдены'); return; } ... }
Эта функция выполняется по нажатию кнопки "Поиск" после ввода ID пользователя. Она берет значение userId из текстового поля и проверяет, что оно не пустое. Если это не так, отображается сообщение об ошибке.
@verifure

- loadingIndicator: элемент, который показывает состояние загрузки во время выполнения запроса. 
- resultsContainer: область, куда будут выводиться найденные рефералы.

Формирование и отправка запроса

const params = new URLSearchParams({ where: USER_ID_TEXT,eq,${userId}, fields: 'username' }); const response = await fetch(${tableUrl}?${params}, { headers: { 'xc-token': token, 'Content-Type': 'application/json' } });
Здесь мы формируем параметры запроса, чтобы найти записи, соответствующие введенному ID пользователя. Мы используем метод fetch для отправки HTTP-запроса к API NocoDB.
@verifure

- where: здесь мы указываем условие для фильтрации записей по идентификатору пользователя. - fields: вы можете указать, какие поля таблицы вы хотите получить. В нашем случае мы хотим получить только поле username.

Обработка ответа

if (!response.ok) throw new Error(HTTP error! status: ${response.status}); const data = await response.json(); if (data.list.length === 0) { showError('Рефералы не найдены'); return; }
После отправки запроса мы проверяем, успешно ли он выполнен, и извлекаем данные в формате JSON. Если рефералы не найдены, выводится сообщение об ошибке.
@verifure

Отображение результатов

data.list.forEach(user => { const div = document.createElement('div'); div.className = 'user-container'; div.textContent = user.username; resultsContainer.appendChild(div); });
Если данные были успешно получены, мы проходим по каждому пользователю из ответа и создаем новый элемент div, который добавляется в контейнер результатов.

Функция showError

function showError(message) { const resultsContainer = document.getElementById('results'); resultsContainer.innerHTML = <div class="error">${message}</div>; }
Эта функция используется для отображения сообщений об ошибках. Принимает текст ошибки в качестве аргумента и обновляет содержимое контейнера результатов.

Заключение и сам код

Таким образом, с помощью этого небольшого скрипта вы можете интегрировать ваше веб-приложение с NocoDB, позволяя пользователям вводить идентификаторы и получать список их приглашенных рефералов. Это простое решение можно адаптировать под ваши конкретные нужды и расширить для дополнительных задач.

Код

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>User Search</title> <style> body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background-color: #f5f5f7; color: #1d1d1f; display: flex; justify-content: center; align-items: center; height: 100vh; } .container { width: 100%; max-width: 800px; padding: 20px; background-color: #ffffff; border-radius: 12px; } .search-box { display: flex; justify-content: space-between; margin-bottom: 20px; } #userIdInput { flex: 1; padding: 12px; font-size: 16px; border: 1px solid #d1d1d6; border-radius: 8px; margin-right: 10px; outline: none; transition: border-color 0.3s ease; } #userIdInput:focus { border-color: #007AFF; } button { padding: 12px 20px; background-color: #007AFF; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 16px; transition: background-color 0.3s ease; } button:hover { background-color: #007bfd; } .header-text { display: flex; height: 13px; flex-direction: column; justify-content: center; flex-shrink: 0; color: #7e7d83; font-size: 13px; font-weight: 380; line-height: 90px; letter-spacing: 0px; } .header { display: flex; width: 335px; padding: 0 10px; align-items: flex-start; gap: 10px; border-radius: 12px; } .user-container { padding: 15px; margin: 10px 0; border: 1px solid #e0e0e0; border-radius: 8px; background-color: #fafafa; font-size: 16px; color: #1d1d1f; transition: background-color 0.3s ease; } .user-container:hover { background-color: #007bfd; } .error { color: #ff3b30; padding: 10px; font-size: 16px; text-align: center; } .loading { display: none; color: #666; padding: 10px; font-size: 16px; text-align: center; } </style> </head> <body> <div class="header"> <div class="header-text">СПИСОК РЕФЕРАЛОВ</div> </div> <br> <div class="content"> <div class="container"> <div class="search-box"> <input type="text" id="userIdInput" placeholder="ID юзера"> <button onclick="searchUsers()">Поиск</button> <div class="loading" id="loading">🔍</div> </div> <div id="results"></div> </div> <script> const token = 'Ваш токен'; const tableUrl = 'https://nocodb.puzzlebot.top/api/v2/tables/Токен вашей таблицы/records'; async function searchUsers() { const userId = document.getElementById('userIdInput').value.trim(); const resultsContainer = document.getElementById('results'); const loadingIndicator = document.getElementById('loading'); if (!userId) { showError('Рефералы не найдены'); return; } try { // Показываем загрузку loadingIndicator.style.display = 'block'; resultsContainer.innerHTML = ''; // Формируем запрос const params = new URLSearchParams({ where: `(USER_ID_TEXT,eq,${userId})`, fields: 'username' }); const response = await fetch(`${tableUrl}?${params}`, { headers: { 'xc-token': token, 'Content-Type': 'application/json' } }); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const data = await response.json(); if (data.list.length === 0) { showError('Транзакций по этой дате не найдено'); return; } // Создаем элементы data.list.forEach(user => { const div = document.createElement('div'); div.className = 'user-container'; div.textContent = user.username; resultsContainer.appendChild(div); }); } catch (error) { showError(`Error: ${error.message}`); } finally { loadingIndicator.style.display = 'none'; } } function showError(message) { const resultsContainer = document.getElementById('results'); resultsContainer.innerHTML = `<div class="error">${message}</div>`; } </script> </body> </html>

Мой канал

Мой ТГ

3
1
6 комментариев
\n\n","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Мой канал

"}},{"type":"link","cover":false,"hidden":false,"anchor":"","data":{"link":{"type":"link","data":{"url":"https://api.vc.ru/v2.8/redirect?to=https%3A%2F%2Ft.me%2FPuzzleHTML&postId=1880232","title":"Puzzle Html • Шаблоны","description":"@PuzzleHtmlBot: Мы предлагаем широкий спектр готовых шаблонов, которые помогут пригодиться в Mini-App","image":{"type":"image","data":{"uuid":"0c5ec522-6456-5837-a7a9-efa6a12645d2","width":180,"height":180,"size":4016,"type":"png","color":"26a5e4","hash":"","external_service":[]}},"v":1,"hostname":"t.me"}}}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Мой ТГ

"}},{"type":"link","cover":false,"hidden":false,"anchor":"","data":{"link":{"type":"link","data":{"url":"https://api.vc.ru/v2.8/redirect?to=https%3A%2F%2Ft.me%2FVerifure&postId=1880232","title":"Hacker Verifure","description":"The service of the best bots Verifure","image":{"type":"image","data":{"uuid":"0c5ec522-6456-5837-a7a9-efa6a12645d2","width":180,"height":180,"size":4016,"type":"png","color":"26a5e4","hash":"","external_service":[]}},"v":1,"hostname":"t.me"}}}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":6,"favorites":0,"reposts":0,"views":761,"hits":542,"reads":null,"online":0},"dateFavorite":0,"hitsCount":542,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":false,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/telegram/1880232-integraciya-s-nocodb-dlya-vyvoda-spiska-referalov-po-user-id-realizovano-na-puzzlebot","author":{"id":755936,"name":"Hacker Verifure","nickname":null,"description":"Шаблоны HTML виджетов: Мы предлагаем широкий спектр готовых шаблонов, которые помогут пригодиться в Mini-App","uri":"","avatar":{"type":"image","data":{"uuid":"f536a51a-90ad-53e6-9996-52506cd70148","width":828,"height":828,"size":59583,"type":"jpg","color":"e7d4c5","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5Ojf/2wBDAQoKCg0MDRoPDxo3JR8lNzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzf/wAARCAAKAAoDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIFB//EACYQAAECBAMJAAAAAAAAAAAAAAECAwAEESEFBjESExUiMkFRYXH/xAAUAQEAAAAAAAAAAAAAAAAAAAAF/8QAHREAAQQCAwAAAAAAAAAAAAAAAQACBBEDMVFhof/aAAwDAQACEQMRAD8AotzRmcTCEzZC0sgol20jmNb1tXT55hjO3NiPR7QZHSnj2KKoNre60v1LjQCw0TUtIJOpKRCEebT322we9IyTBvGwB1EDjfq//9k="}},"cover":{"cover":{"type":"image","data":{"uuid":"03bffb95-befa-548d-9188-a0dff1180e28","width":800,"height":800,"size":44565,"type":"jpg","color":"32a9f6","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAQDAwQDAwQEAwQFBAQFBgoHBgYGBg0JCggKDw0QEA8NDw4RExgUERIXEg4PFRwVFxkZGxsbEBQdHx0aHxgaGxr/2wBDAQQFBQYFBgwHBwwaEQ8RGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhr/wAARCAAKAAoDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABgAD/8QAIhABAAEDAwQDAAAAAAAAAAAAAQIAAxIFE1EEETGRQVKh/8QAFQEBAQAAAAAAAAAAAAAAAAAABwj/xAAcEQEAAQQDAAAAAAAAAAAAAAABAgADBREhcaH/2gAMAwEAAhEDEQA/AF17X4FvpdgtXBlhed1jKPzl2RH6/tZT12MZyI3BBQR80HyeX3Vk8vunyGMtwXau/KneeQnIAA13zX//2Q=="}},"cover_y":50},"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4680765,"userId":755936,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4680765"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1056678,"userId":755936,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1056678"}],"lastModificationDate":1764963384,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":true,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":3680492,"name":"Телеграм","description":"Все о мессенджере Телеграм: новые фичи, каналы, новости, Павел Дуров, TON","uri":"/telegram","avatar":{"type":"image","data":{"uuid":"a6bd3ea3-1a25-5402-8c27-d063a43ad500","width":500,"height":500,"size":6665,"type":"jpg","color":"28a7e8","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAKAAoDASEAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABgME/8QAIRAAAQIGAgMAAAAAAAAAAAAAAQMEAAIFERIxBiETFEH/xAAVAQEBAAAAAAAAAAAAAAAAAAAEB//EABkRAAIDAQAAAAAAAAAAAAAAAAIDAAERYf/aAAwDAQACEQMRAD8AZcWpFGqLJ24fVgJKt2yi3ryjGY4g2F5tkn4AeoNBQ21FOS5hsMSHKrM7I69C1qAgLbLd5yTVA8uo0AdQmoSf/9k="}},"cover":{"type":"image","data":{"uuid":"ebe1c612-381b-52c8-897c-ac8a8002770f","width":1920,"height":1080,"size":636123,"type":"jpg","color":"def2f4","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAKAAoDASEAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAwEI/8QAHxAAAQMEAwEAAAAAAAAAAAAAAQACERIiQVEhMTKS/8QAFwEAAwEAAAAAAAAAAAAAAAAAAAEDBP/EABURAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIRAxEAPwDSQjeNKtIgXD5V2EVToNx8jKRrnUjk9bQUf//Z"}},"lastModificationDate":1721721308,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":false,"isDisabledAd":false,"nickname":"telegram","isUnsubscribable":true,"badge":null,"badgeId":null,"isDonationsEnabled":false,"isOnline":false,"isPlus":false,"isUnverifiedBlogForCompanyWithoutPro":false,"isVerified":false,"isRemovedByUserRequest":false,"isFrozen":false,"isPro":false,"type":2,"subtype":"community"},"reactions":{"counters":[{"id":1,"count":3},{"id":2,"count":1}],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null,"keywords":[],"media":{"type":"image","data":{"uuid":"292f9435-a522-51c7-82dc-ea3c6da5816e","width":3312,"height":1860,"size":151801,"type":"jpg","color":"49b0f4","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAKAAoDASEAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAgQFCP/EACQQAAEEAQEJAQAAAAAAAAAAAAECAwQRAAYFEiEkMWGBk8LR/8QAFAEBAAAAAAAAAAAAAAAAAAAABP/EAB0RAQABBAMBAAAAAAAAAAAAAAEDAAIEUREhsZH/2gAMAwEAAhEDEQA/ANcN7PhyIbzDsZG64CgkCjRFcD1HjIqdC6eQkIDUykihc10/WMx86aASzjvYPtEmw4pkbj4p5SaJkxKQBKfA7OHAM2ZZ5uR7D+4gjs1RWS/df//Z"}},"customCover":null,"robotsTag":"noindex","categories":[3],"isAnonymized":true}};