Вводная
Использовать API Connector в DataLens можно для множества вещей, на этой странице разберем основные подходы, как делать базовые запросы через API и разберем интересные примеры использования.
Основные шаги подключения API
Простое видео, как сделать запрос к API внутри DataLens
То есть, основные шаги
- Создать API или получить информацию по адресу и формату работы с некоторым API
- Создать подключение к API
- Создать чарт Editor
- Написать и настроить код на Sources для интерактивной работы с API
- Обработать результат на Prepare
Пример: простой чат внутри DataLens
Python Код для API
import psycopg2
import os
import csv
import io
def handler(event, context):
params = event.get('multiValueQueryStringParameters', {})
chat_id = params.get('chat_id', [None])[0]
message = params.get('message', [None])[0]
author = params.get('author', [None])[0]
message_key = params.get('message_key', [None])[0]
if not chat_id:
return {
'statusCode': 400,
'body': "Ошибка: параметр 'chat_id' является обязательным.",
'headers': {'Content-Type': 'text/csv; charset=UTF-8'},
}
pg_pass = os.environ.get('PG_PASS')
try:
conn = psycopg2.connect(
user="user1",
password=pg_pass,
host="rc1a-***.mdb.yandexcloud.net",
port="6432",
database="db1"
)
cur = conn.cursor()
# 1. Обработка message_key: проверка и вставка
if message_key is not None:
cur.execute(
"SELECT 1 FROM chat_messages WHERE chat_id = %s AND message_key = %s",
(chat_id, message_key)
)
if not cur.fetchone():
# ключ не найден — вставляем полную строку
cur.execute(
"INSERT INTO chat_messages (chat_id, author, message, message_key, dttm) "
"VALUES (%s, %s, %s, %s, NOW())",
(chat_id, author, message, message_key)
)
conn.commit()
# 2. Обычная логика добавления сообщения (если нет message_key)
elif message and author:
stop_words = ['политика', 'религия', 'другие чувствительные темы']
if not any(w in message.lower() for w in stop_words):
cur.execute(
"SELECT 1 FROM chat_messages "
"WHERE author = %s AND message = %s AND chat_id = %s "
"AND dttm > NOW() - INTERVAL '1 minute'",
(author, message, chat_id)
)
if not cur.fetchone():
cur.execute(
"INSERT INTO chat_messages (chat_id, author, message, dttm) "
"VALUES (%s, %s, %s, NOW())",
(chat_id, author, message)
)
conn.commit()
# 3. Получение последних 30 сообщений
cur.execute("""
SELECT author, message, dttm
FROM (
SELECT author, message, dttm
FROM chat_messages
WHERE chat_id = %s
ORDER BY dttm DESC
LIMIT 30
) AS last_30
ORDER BY dttm ASC;
""", (chat_id,))
rows = cur.fetchall()
output = io.StringIO()
w = csv.writer(output)
w.writerow(['author', 'message', 'dttm'])
if not rows:
w.writerow(['-', '-', '-'])
else:
for r in rows:
w.writerow([r[0], r[1], r[2].isoformat()])
return {
'statusCode': 200,
'body': output.getvalue(),
'headers': {'Content-Type': 'text/csv; charset=UTF-8'},
}
except psycopg2.Error as e:
return {
'statusCode': 500,
'body': f"Ошибка базы данных: {e}",
'headers': {'Content-Type': 'text/csv; charset=UTF-8'},
}
finally:
if 'cur' in locals():
cur.close()
if 'conn' in locals():
conn.close()
API Editor Chart
var params = Editor.getParams();
var author = params.user[0] != '' ? params.user[0]:Editor.getUserLogin();
var message = params.message_to_send[0];
var chat_id = params.chat_id[0];
var message_key = author + params.send_dttm[0];
if (message != '') {
module.exports = {
'myApiDataSource': {
apiConnectionId: 'mu751arjzpn88',
path: encodeURI(`?chat_id=${chat_id}&author=${author}&message=${message}&message_key=${message_key}`),
method: 'GET'
}
}
}
else {
module.exports = {
'myApiDataSource': {
apiConnectionId: 'mu751arjzpn88',
path: `?chat_id=${chat_id}`,
method: 'GET'
}
}
}Editor.updateParams({"send_it":[""]});
function print(mess) {
console.log(mess);
}
function parseCsvToObjects(csvString) {
const lines = csvString.trim().split('\n');
// Функция, которая разбивает строку на значения с учётом кавычек
function parseCsvLine(line) {
const result = [];
let current = '';
let inQuotes = false;
for (let i = 0; i < line.length; i++) {
const char = line[i];
if (char === '"') {
// Если текущий символ кавычка, проверяем следующий чтобы определить если это экранирование
if (inQuotes && line[i + 1] === '"') {
// Экранированная кавычка двойным двойным
current += '"';
i++; // пропускаем следующий символ
} else {
inQuotes = !inQuotes; // переключаем состояние в/из кавычек
}
} else if (char === ',' && !inQuotes) {
// Разделитель поля только если не внутри кавычек
result.push(current);
current = '';
} else {
current += char;
}
}
result.push(current);
return result;
}
const headers = parseCsvLine(lines[0]).map(h => h.trim());
return lines.slice(1).map(line => {
const values = parseCsvLine(line);
const obj = {};
headers.forEach((header, index) => {
obj[header] = values[index] ? values[index].trim() : '';
});
return obj;
});
}
var params = Editor.getParams();
var current_user = params.user[0] != '' ? params.user[0]:Editor.getUserLogin();
function csvToMarkdownChat(csvString) {
const data = parseCsvToObjects(csvString);
return data.map(({ author, message, dttm }) => {
const isCurrentUser = author === current_user;
const time = new Date(dttm).toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit',
hour12: false // 24-часовой формат
});
// Иконка пользователя
const userIcon = isCurrentUser ? '👤' : '👥';
// Строка автора и времени
const authorTimeLine = isCurrentUser
? `> **${userIcon} Вы (${time})**`
: `**${userIcon} ${author} (${time})**`;
// Сообщение с правильным выравниванием
const messageLine = isCurrentUser
? `{blue}(${message.replace(/\n/g, '\n> ')})` // Сохраняем переносы строк в цитате
: message.replace(/\n/g, '\n'); // Обычное сообщение
return `${authorTimeLine}\n${messageLine}`;
}).join('\n\n');
}
const response = Editor.getLoadedData();
print(response['myApiDataSource'].data.body.result);
print(parseCsvToObjects(response['myApiDataSource'].data.body.result));
const markdown = csvToMarkdownChat(response['myApiDataSource'].data.body.result);
module.exports = {
markdown
};JS SELECTOR for message
// Controls Tab
var controls = [];
var params = Editor.getParams();
var message = params.message[0];
var key = new Date().getTime() / 1000;
if (message != '') {
controls.push(
{
type: 'input',
param: 'message',
width:'85%',
postUpdateOnChange: true
})
controls.push(
{
type: 'input',
param: 'message_to_send',
hidden:true
})
controls.push(
{
type: 'button',
label: '💬',
theme: 'action',
updateOnChange: true,
onClick: {
action: 'setParams',
args: {
message_to_send:message,
message: '',
send_dttm:key
}
}
}
)
}
else {
controls.push(
{
type: 'input',
param: 'message',
width:'85%',
updateOnChange: true
})
controls.push(
{
type: 'input',
param: 'message_to_send',
hidden:true
})
}
module.exports = controls;
Добавить комментарий