# Парсер курсов

Here's the revised documentation with brief explanations of the properties, without the comments:

## Parser Integration Documentation

This document outlines the structure and key components required to integrate a parser into the system.

### File Structure

Your parser should be organized in the following directory structure:

```
pluginsExternal/parser/PARSER_NAME/
```

* **`configure.js`**: Configuration file to set up the parser.
* **`icon.png`**: An icon representing the parser.
* **`index.js`**: The main implementation of the parser.

### Configuration (`configure.js`)

The `configure.js` file is used to define the parser's setup. It should export an object with the following structure:

```javascript
module.exports = {
  title: "Parser Name",
  name: "parser_name",
  defaultInterval: 30000,
  isActiveDefault: false,
  extra: {
    // Additional configurations like API keys, currencies, etc.
  },
};
```

#### Properties:

* **`title`**: The display name of the parser.
* **`name`**: A unique identifier for the parser, typically in lowercase and snake\_case.
* **`defaultInterval`**: The default time interval (in milliseconds) at which the parser fetches data.
* **`isActiveDefault`**: A boolean indicating whether the parser is active by default when initialized.
* **`extra`**: An object for any additional settings such as API keys, currencies, or other specific parameters required by the parser.

### Icon (`icon.png`)

The `icon.png` file should be a PNG image with a minimum size of 150x150 pixels. This icon will represent your parser in the user interface.

### Implementation (`index.js`)

The `index.js` file contains the core logic of your parser. Below are the key methods that should be implemented:

#### Constructor

The constructor is responsible for initializing the parser with the necessary configurations and options.

**Parameters:**

* **`config`**: An object containing configuration details like the parser's name, title, default interval, and extra settings such as API keys.
* **`options`**: An object that may include an `emitter` for event-based data processing or a `callback` for direct function-based processing.

#### `updateRate` Method

The `updateRate` method fetches the latest data from an external API, processes it, and then either emits the data through an event emitter or returns it via a callback function.

**Key Responsibilities:**

* Fetch data from the API using the `apiRequest` method.
* Process the data, including calculations like exchange rates.
* Format the data into a consistent structure `({ from, to, buy })` and create data objects `rate1`
* Emit or return the processed data `rate1` using the `emitter` or `callback` provided in the options.
* Optional: Reverse the exchange rate if the API provides only one-way rates.
* Return an array of processed data objects.

#### `apiRequest` Method

The `apiRequest` method handles communication with the external API to retrieve the necessary data.

**Key Responsibilities:**

* Send an HTTP request to the API endpoint.
* Handle the response and format the data.
* Manage errors, ensuring that descriptive messages are provided if the request fails.

### Example Implementation

```javascript
const axios = require("axios");
const BigNumber = require("bignumber.js");

class ParserName {

  constructor(config, options) {
    this.id = __dirname.split("/").slice(-1)[0];
    this.exchangeRateUrl = "https://api.example.com/exchange_rate";

    if (config.extra && config.extra.apiKey) {
      this.apiKey = config.extra.apiKey;
    } else {
      throw new Error("API key is required");
    }

    if (options.emitter) {
      this.emitter = options.emitter;
    } else if (options.callback) {
      this.callback = options.callback;
    }
  }

  async updateRate() {
    const data = await this.apiRequest();
    const rate = new BigNumber(data.rate);

    const rate1 = { from: data.from, to: data.to, buy: rate };

    // Optional: Reverse the exchange rate if the API provides only one-way rates
    const rate2 = { from: data.to, to: data.from, buy: new BigNumber(1).div(rate) };

    if (this.emitter) {
      this.emitter.emit("updateRate", this.id_key, rate1);
      this.emitter.emit("updateRate", this.id_key, rate2);
    } else if (this.callback) {
      this.callback('updateRate', this.id_key, rate1);
      this.callback('updateRate', this.id_key, rate2);
    }

    return [rate1, rate2];
  }

  async apiRequest() {
    try {
      const response = await axios.get(this.exchangeRateUrl, {
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${this.apiKey}`,
        },
      });
      return response.data;
    } catch (error) {
      throw new Error(`API Request failed: ${error.message}`);
    }
  }
}

module.exports = ParserName;
```

### Testing

To test the parser, you can instantiate it and call the `updateRate` method:

```javascript
const parser = new ParserName(
  { extra: { apiKey: "your-api-key-here" } },
  { emitter: { emit: (event, data) => console.log(event, data) } }
);

parser.updateRate().then(data => console.log("Rates Updated:", data));
```

### Notes

* **Unique Directory Name**: Ensure that each parser has a unique directory name.
* **Default States**: Always define a default interval and active state (`isActiveDefault`) in the configuration.
* **Title and Name**: Both `title` and `name` fields in the configuration are mandatory and must be unique.
* **Icon**: Use a distinct icon for each parser to avoid confusion in the UI.
