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

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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://manual.boxexchanger.net/dlya-razrabotchikov/razrabotka-modulei/parser-kursov.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
