Giter VIP home page Giter VIP logo

amo's People

Contributors

belyaev-dev avatar github-actions[bot] avatar monsterdeveloper avatar shevernitskiy avatar yatolstoy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

amo's Issues

Add support of long-term tokens

New update added long-term access tokens for private integrations. They are the same as the access token, but has longer expire period.

Do we need to update readme? Basically we can use new token as an access_token, but specify expired_at as 5 years or less (depends on real token lifetime)

The file deletion method throws an error after deleting files.

This is a issue about fix error.

I expect that if the files are successfully deleted, my script should execute next.
Currently, the method await amo.file(amoAccount.drive_url).deleteFiles(fileIds) throws an Error: 204 No Content on successful execution.

Based on AmoCRM documentation
you can see that code 204 comes when files are successfully deleted.
I checked, the files are indeed deleted from amoCRM.

As I found out the error occurs because the checkError method of the RestClient object specifies that if the response code is 204, the code throws an error throw new NoContentError(`${res.status} ${res.statusText}, ${res.statusText}, ${res.url}`); (line 75).

Because of this collision I do not get further script execution.

To be honest, I haven't found a more elegant solution yet except to check the method and URL directly } else if (res.status === 204 && !(res.url.includes('v1.0/files') && res.method === 'DELETE'))) {

Any ideas?

Add Chat API support

We need to update requests module so we can add Chats API support. Currently it's not possible even using raw amoCRM API requests.

Docs: amoCRM and Kommo

Required methods:

  • Connect channel
  • Disconnect channel
  • Create chat
  • Link chat to contact (update contact entity)
  • Send message (incoming/outgoing)
  • Get chat history
  • Update delivery status
  • Typing infomation
  • Send reaction
  • Withdraw reaction

Required webhooks:

  • Outgoing message webhook

Required integration tokens, received from amoCRM when registering new Chats API integration:

  1. AMOJO_UUID
  2. AMOJO_BOT_UUID
  3. AMOJO_SECRET

Required account data:

  1. ACCOUNT_AMOJO_ID (received by /api/v4/account?with=amojo_id req)
  2. SCOPE_ID (consists of ${AMOJO_UUID}_${ACCOUNT_AMOJO_ID})

We also need to constuct complex headers using request body to work with chats API, example:

import { createHash } from "https://deno.land/[email protected]/hash/mod.ts";
import { hmac } from "https://deno.land/x/[email protected]/mod.ts";

private getHeaders(body: object): Headers {
    const contentType = "application/json";
    const date = new Date().toUTCString().replace(
      /(\w+), (\d+) (\w+) (\d+) (\d+):(\d+):(\d+) GMT/,
      "$1, $2 $3 $4 $5:$6:$7 +0000",
    );
    const requestBody = JSON.stringify(body);
    const checkSum = createHash("md5").update(requestBody).toString("hex");

    const signature = hmac("sha1", AMOJO_SECRET, requestBody, "utf8", "hex").toString();

    const headers = new Headers();
    headers.append("Date", date);
    headers.append("Content-Type", contentType);
    headers.append("Content-MD5", checkSum);
    headers.append("X-Signature", signature);

    return headers;
  }

Any help is appreciated

amo.custom_fields.getCustomFieldById возвращает undefined

При попытке запросить

const field = await amo.custom_fields.getCustomFieldById(707045, 'leads');
console.log(`found field 707045 leads`, field);

возвращается

found field 707045 leads undefined

this.rest.get('/api/v4/leads/custom_fields/707045') при отладке возвращает тело ответа:

{
  id: 707045,
  name: 'Врач',
  type: 'select',
  account_id: 30091462,
  code: null,
  sort: 510,
  is_api_only: false,
  enums: [
    { id: 630339, value: 'Фомин Игорь Викторович', sort: 500 },
    { id: 630341, value: 'Кизарьянц Анна Альбертовна', sort: 1 },
    { id: 630343, value: 'Тупатилов Кирилл Валерьевич', sort: 2 },
    { id: 630345, value: 'Бриштен Виктория Леонидовна', sort: 3 },
    { id: 630347, value: 'Фроловичев Кирилл Андреевич', sort: 4 },
    { id: 630349, value: 'Фроловичева Марина Владимировна', sort: 5 },
    { id: 630351, value: 'Колотиков Павел Александрович', sort: 6 },
    { id: 630353, value: 'Родивилова Наталия Александровна', sort: 7 },
    { id: 630355, value: 'Фомина Ольга Леонтьевна', sort: 8 },
    { id: 630357, value: 'Мартынова Мария Игоревна', sort: 9 },
    { id: 630359, value: 'Байтокова Амина Джашарбековна', sort: 10 },
    { id: 630361, value: 'Чаниева Зара Ахмедовна', sort: 11 },
    { id: 630363, value: 'Еварницкая Наталья Ростиславовна', sort: 12 },
    { id: 630365, value: 'Сапрыкина Юлия Александровна', sort: 13 },
    { id: 630367, value: 'Липунова Валерия Константиновна', sort: 14 },
    { id: 630369, value: 'Петракова Алтына Юрьевна', sort: 15 },
    { id: 630371, value: 'Савченко Кристина Сергеевна', sort: 16 },
    { id: 631039, value: 'Рентген Рентген', sort: 17 }
  ],
  group_id: null,
  required_statuses: [],
  is_deletable: true,
  is_predefined: false,
  entity_type: 'leads',
  tracking_callback: null,
  remind: null,
  triggers: [],
  currency: null,
  hidden_statuses: [],
  chained_lists: null,
  _links: {
    self: {
      href: 'https://kprodent.amocrm.ru/api/v4/leads/custom_fields/707045'
    }
  }
}

По непонятной причине оно возвращается в вызывающую функцию как undefined

NodeJs version >=18

Hi, please add to the readme that at least nodejs >=18 is required.

As of only Node.js version 18, the fetch API is natively available.

getCustomFields doesn't support query params (pagination)

Query for method GET /api/v4/${entity}/custom_fields supports params limit (до 50) и page for receiving all entity fields
Currently method getCustomFields doesn't support query params, so we can get only up to 50 fields

Example:

https://example.amocrm.ru/api/v4/leads/custom_fields?limit=2&page=2

Docs

Migrate from AsyncQueue to Bottleneck

I'd like to recommend switching to Bottleneck as way more stable and flexible approach to request queue, just adding a delay for request is way too unpredictable when using on production

export class RestClient {
  private url_base: string;
  private _token?: OAuth;
  private limiter: Bottleneck;

  constructor(
    private base_url: string,
    private auth: OAuthCode | OAuth & Pick<OAuthRefresh, "client_id" | "client_secret" | "redirect_uri">,
    private options?: Options,
  ) {
    this.url_base = `https://${this.base_url}`; 
    if (this.isOAuth(this.auth)) {
      this._token = {
        token_type: this.auth.token_type,
        expires_in: this.auth.expires_in,
        access_token: this.auth.access_token,
        refresh_token: this.auth.refresh_token,
        expires_at: this.auth.expires_at ?? 0,
      };
    }
    this.limiter = new Bottleneck(this.limiterOptions);
  }

  private get limiterOptions(): BottleneckTypes.ConstructorOptions {
    return this.options?.limiterOptions ?? {
      reservoir: 7,
      reservoirRefreshAmount: 7,
      reservoirRefreshInterval: 1000,
      maxConcurrent: 5,
      minTime: 300
    };
  }

  ...
}

and then using it as

const res = await this.limiter.schedule(() => fetch(target, {
  method: method,
  headers: init.headers ?? {
    "Authorization": `${this._token?.token_type} ${this._token?.access_token}`,
    "Content-Type": "application/json",
  },
  body: init.payload ? JSON.stringify(init.payload) : undefined,
}));

Just a small problem before I prepare a pull request to review.
Bottleneck is external depedency, and this project is currently loading all external depedencies using CDNs without use of package.json
How to correctly load it then?

RequestAddCustomField не соответствует реальному интерфейсу amoCRM

Для создания нового поля используется другой набор полей, а именно:

  1. Отсутствует ID
  2. Все поля с припиской field_ указываются без нее (code, name, sort, type)
interface CustomFieldsValue = Partial<{
    /** Тип поля. Список доступных полей */
    type: CustomFieldsValueTypes;
    /** Название поля */
    name: string;
    /** Код поля, по-которому можно обновлять значение в сущности, без передачи ID поля */
    code: string;
    /** Сортировка поля */
    sort: number;
    /** ID группы полей, в которой состоит данное поле. Данный ключ возвращается только при получении списка полей контактов, сделок, покупателей и компаний */
    group_id: string;
    /** Доступно ли поле для редактирования только через API. Данный ключ возвращается только при получении списка полей контактов, сделок и компаний */
    is_api_only: boolean;
    required_statuses: {
          /** ID статуса, для перехода в который данное поле обязательно к заполнению. Данный ключ возвращается только при получении списка полей контактов, сделок и компаний */
          status_id: number;
          /** ID воронки, для перехода в который данное поле обязательно к заполнению. Данный ключ возвращается только при получении списка полей контактов, сделок и компаний */
          pipeline_id: number;
      }[] | null;
    /** Настройки поля. Данный ключ возвращается только при получении списка полей списков (каталогов) */
    settings: any[] | null;
    /** Отображается ли поле в интерфейсе списка. Данный ключ возвращается только при получении списка полей списков (каталогов) */
    is_visible: boolean;
    /** Обязательно ли поле для заполнения при создании элемента списка. Данный ключ возвращается только при получении списка полей списков (каталогов) */
    is_required: boolean;
    /** Когда напоминать о дне рождения (never – никогда, day – за день, week – за неделю, month – за месяц). Значение данного поля доступно только для поля типа birthday. Данный ключ возвращается только при получении списка полей контактов, сделок и компаний */
    remind: string;
    /** Доступные значения для поля. Значение данного поля доступно только для полей с поддержкой enum */
    enums: Partial<{
          /** Значение */
          value: string;
          /** Сортировка значения */
          sort: number;
          /** Символьный код значения */
          code: string | null;
      }>[] | null;
    nested: {
          /** ID вложенного значения. Данные ключ возвращается только при получении списка полей каталогов и значение доступно только для поля category */
          id: number;
          /** ID родительского вложенного значения. Данные ключ возвращается только при получении списка полей каталогов и значение доступно только для поля category */
          parent_id: number;
          /** Значение вложенного значения. Данные ключ возвращается только при получении списка полей каталогов и значение доступно только для поля category */
          value: string;
          /** Сортировка вложенного значения. Данные ключ возвращается только при получении списка полей каталогов и значение доступно только для поля category */
          sort: number;
      }[] | null;
      /** Сallback js-функция, которая будет выполнена на странице с CRM Plugin и формой amoCRM при отправке данных. Данное значение возвращается для полей типа tracking_data */
    tracking_callback: string;
    /** Настройка скрытия полей. Поля скрываются в интерфейсе в зависимости от статуса. Данный ключ возвращается только при получении списка полей сделок. */
    hidden_statuses: {
          /** ID статуса, в котором поле скрыто */
          status_id: number;
          /** ID воронки, в котором поле скрыто */
          pipeline_id: number;
      }[];
    /** Настройка поля типа chained_list. Данный ключ возвращается только при получении списка полей сделок и покупателей. */
    chained_lists: {
          /** Модель настройки связанного списка. */
          /** Название связанного списка, которое отображается в карточке */
          title: string | null;
          /** ID каталога */
          catalog_id: number;
          /** ID родительского каталога */
          parent_catalog_id: number;
      }[] | null;
    /** ID списка или символьный код (contacts, companies, contacts_and_companies) для поля типа Связь с другим элементов (linked_entity). */
    search_in: string | null;
    /** Код валюты поля. Применимо только для типа поля – monetary. Для других типов полей – null. */
    currency: string | null;
  }>;

https://www.amocrm.ru/developers/content/crm_platform/custom-fields#%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B4%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D1%85-%D0%BF%D0%BE%D0%BB%D0%B5%D0%B9-%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D0%B8

Expand the _embedded property of the RequestAddLead

The _embedded property now supports the same entities as the CreateLeadComplex

export type RequestAddComplex = Partial<Pick<Lead, "name" | "price" | "status_id" | "pipeline_id" | "created_by" | "updated_by" | "closed_at" | "created_at" | "updated_at" | "loss_reason_id" | "responsible_user_id" | "custom_fields_values">> & {
    _embedded?: {
        tags?: {
            id?: number;
            name?: string;
        }[];
        contacts?: Partial<Contact>[];
        companies?: Partial<Company>[];
        metadata?: Partial<UnsrotedMetadataForm> | Partial<UnsrotedMetadataSip>;
        source?: {
            external_id?: number;
            type?: string;
        };
    };
};

see Leads API

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.