Editor API

Вводная

Использовать 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;

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *