# Индикатори за настроение

> GET /3/movie/{movie_id}/moods и GET /3/tv/{tv_id}/moods връщат source и списък results. Всеки резултат има име на настроение, например fear или humor, avg по скала от 0 до 10 и стойностите зад него. Добавете append_to_response=moods към извикване за детайли, за да включите индикаторите без втора заявка.

## Ендпойнт

`GET /3/movie/{movie_id}/moods`

```bash
curl "https://api.amodb.dev/3/movie/155/moods" \
  -H "Authorization: Bearer $AMODB_KEY"
```

Отговор:

```json
{
  "id": 155,
  "source": "measured",
  "results": [
    {
      "name": "action",
      "avg": 3.9,
      "values": [
        3.6,
        3.4,
        4.2
      ]
    },
    {
      "name": "fear",
      "avg": 5.2,
      "values": [
        3.6,
        6,
        4.8
      ]
    },
    {
      "name": "humor",
      "avg": 0.9,
      "values": [
        2.4,
        1.8,
        0.4
      ]
    }
  ]
}
```

## Индикатори за настроение на филм

`GET /3/movie/{movie_id}/moods` връща индикаторите за настроение на един филм. Индикаторът за настроение е име и средна стойност по скала от 0 до 10. Отговорът носи `id` на филма, `source` и масив `results`. Всеки резултат съдържа `name`, `avg` и `values`.

Примерът зарежда индикаторите за The Dark Knight (id 155) и ги отпечатва от най-силния към най-слабия.

```bash
curl -sf "https://api.amodb.dev/3/movie/155/moods" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```js
const res = await fetch('https://api.amodb.dev/3/movie/155/moods', {
  headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` },
});
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { source, results } = await res.json();
console.log('source:', source);
for (const m of [...results].sort((a, b) => b.avg - a.avg)) {
  console.log(m.name.padEnd(10), m.avg);
}
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/155/moods",
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
data = r.json()
print("source:", data.get("source"))
for m in sorted(data["results"], key=lambda m: m["avg"], reverse=True):
    print(f"{m['name']:<10} {m['avg']}")
```

```php
<?php
$ch = curl_init('https://api.amodb.dev/3/movie/155/moods');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 10,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AMODB_KEY')],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
    throw new RuntimeException("amodb returned $status");
}
$data = json_decode($body, true);
echo 'source: ', $data['source'] ?? 'none', PHP_EOL;
$results = $data['results'];
usort($results, fn ($a, $b) => $b['avg'] <=> $a['avg']);
foreach ($results as $m) {
    printf("%-10s %.1f\n", $m['name'], $m['avg']);
}
```

```go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"sort"
	"time"
)

type Mood struct {
	Name   string    `json:"name"`
	Avg    float64   `json:"avg"`
	Values []float64 `json:"values"`
}

func main() {
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/movie/155/moods", nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
	client := &http.Client{Timeout: 10 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		panic(res.Status)
	}
	var body struct {
		Source  string `json:"source"`
		Results []Mood `json:"results"`
	}
	if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
		panic(err)
	}
	fmt.Println("source:", body.Source)
	sort.Slice(body.Results, func(i, j int) bool { return body.Results[i].Avg > body.Results[j].Avg })
	for _, m := range body.Results {
		fmt.Printf("%-10s %.1f\n", m.Name, m.Avg)
	}
}
```

### Параметри

| Параметър  | Къде   | Задължителен  | Описание                                                            |
| ---------- | ------ | ------------- | ------------------------------------------------------------------- |
| `movie_id` | път    | да            | Числов id на филма, например `155`.                                 |
| `api_key`  | заявка | един от двата | Вашият ключ. Ползвайте него или заглавката `Authorization: Bearer`. |

### Полета на отговора

| Поле               | Тип            | Бележки                                                                                                             |
| ------------------ | -------------- | ------------------------------------------------------------------------------------------------------------------- |
| `id`               | цяло число     | Id на филма.                                                                                                        |
| `source`           | низ или null   | `measured` за данни от зрители, `estimated` когато е изведено от жанровете, `null` когато заглавието няма данни.    |
| `results`          | масив          | Индикатори за настроение, подредени по `name`. Празен, когато нищо не е известно.                                   |
| `results[].name`   | низ            | Кратка дума с малки букви, например `fear`.                                                                         |
| `results[].avg`    | число          | Средна стойност по скала от 0 до 10. Един десетичен знак за измерените заглавия, цяло число за приблизителните.     |
| `results[].values` | масив от числа | До 24 стойности по същата скала от 0 до 10. Измерените заглавия, които сме виждали, имат 6, приблизителните имат 5. |

Днес се срещат имената `action`, `fear`, `humor`, `pace`, `profanity`, `romance`, `sadness`, `sex` и `violence`. Не всяко заглавие има и деветте, затова показвайте имената от данните, а не от фиксиран списък.

### Примерен отговор

```json
{
  "id": 155,
  "source": "measured",
  "results": [
    { "name": "action", "avg": 3.9, "values": [3.6, 3.4, 4.2, 4.2, 4.8, 3] },
    { "name": "fear", "avg": 5.2, "values": [3.6, 6, 4.8, 6.4, 6.4, 3.8] },
    { "name": "humor", "avg": 0.9, "values": [2.4, 1.8, 0.4, 0.4, 0, 0.5] }
  ]
}
```

Списъкът е съкратен до 3 от 9-те резултата.

### Измерени и приблизителни заглавия

Fight Club (id 550) още няма данни от зрители, затова индикаторите му са изведени от жанровете. Всяко `avg` е цяло число, а `values` има 5 записа.

```json
{
  "id": 550,
  "source": "estimated",
  "results": [
    { "name": "action", "avg": 4, "values": [3, 4, 5, 4, 3] },
    { "name": "fear", "avg": 7, "values": [6, 7, 8, 7, 6] }
  ]
}
```

Проверявайте `source`, ако искате да третирате приблизителните индикатори различно от измерените.

## Индикатори за настроение на сериал

`GET /3/tv/{tv_id}/moods` има същата форма на отговора, с id на сериала в `id`. За Breaking Bad ползвайте `1396`.

| Метод и път                   | Какво връща                      | Параметри                                  |
| ----------------------------- | -------------------------------- | ------------------------------------------ |
| `GET /movie/{movie_id}/moods` | `id`, `source` и `results`       | `movie_id`                                 |
| `GET /tv/{tv_id}/moods`       | `id`, `source` и `results`       | `tv_id`                                    |
| `append_to_response=moods`    | `source` и `results` под `moods` | Добавя се към детайлите на филм или сериал |

```bash
curl -sf "https://api.amodb.dev/3/tv/1396?append_to_response=moods" -H "Authorization: Bearer $AMODB_KEY"
```

Когато добавите `moods` към извикване за детайли, ключът `moods` стои на най-горно ниво в записа до `title` или `name`. Съдържа `source` и `results` и няма собствен `id`. Това струва една заявка, докато две отделни извиквания струват две.

## Как да четете скалата

Полето `avg` е интензитет от 0 до 10. По-голямо число означава по-силно настроение в заглавието.

| Диапазон    | Прочит                            |
| ----------- | --------------------------------- |
| от 0 до 2.9 | Настроението е слабо или липсва.  |
| от 3 до 5.9 | Настроението присъства.           |
| от 6 до 7.9 | Настроението е ясно изразено.     |
| от 8 до 10  | Настроението определя заглавието. |

Диапазоните са предложение за вашия интерфейс, а не поле в отговора. Масивът `values` съдържа стойностите зад средната, по същата скала.

## Значки и филтри

Настроенията пасват на три чести шаблона в интерфейса. Изберете прагове, които подхождат на вашия каталог, и ги донастройте.

| Шаблон     | Правило                                                              | Бележки                                                            |
| ---------- | -------------------------------------------------------------------- | ------------------------------------------------------------------ |
| Значка     | Показвайте до 3 настроения с `avg` 6 или повече                      | Първо сортирайте по `avg`.                                         |
| Лента      | Задайте ширина на лентата `avg` по 10 като процент                   | Скалата е от 0 до 10.                                              |
| Филтър чип | Съпоставяйте заглавия, при които избраното настроение е 7 или повече | Вземете индикаторите за всяко заглавие, после филтрирайте локално. |

```js
function topMoods(results, min = 6, limit = 3) {
  return results
    .filter((m) => m.avg >= min)
    .sort((a, b) => b.avg - a.avg)
    .slice(0, limit)
    .map((m) => m.name);
}

function matchesMood(results, name, min = 7) {
  return results.some((m) => m.name === name && m.avg >= min);
}
```

Празен масив `results` трябва да се показва като липса на значки, а не като грешка.

## Грешки

Тялото на грешката има `success`, `status_code` и `status_message`, същите полета като при TMDB.

| HTTP | status_code | Кога                                                                      |
| ---- | ----------- | ------------------------------------------------------------------------- |
| 401  | 7           | Ключът липсва или е грешен.                                               |
| 402  | 36          | Периодът на плана е изтекъл.                                              |
| 429  | 25          | Надхвърлен е лимитът на заявки в минута. Изчакайте `Retry-After` секунди. |

Ендпойнтът moods не отговаря с 404 за непознат id. Отговаря със 200 и празен масив `results`, а `source` е `null` или липсва. Когато се добавя към детайлите, непознат id дава 404 от извикването за детайли. Пълният списък е на страницата [грешки](https://amodb.dev/bg/errors/), а лимитите са на страницата [лимити на заявките](https://amodb.dev/bg/rate-limits/).

## Практически бележки

- Както другите данни за детайли, индикаторите за настроение се кешират на edge за 6 часа. По-честото им теглене връща същото тяло.
- Списък от 20 заглавия изисква 20 заявки за настроение. Ако вече извиквате детайли за всяко заглавие, добавете `moods` и спестете второто извикване.
- Проверявайте `source`, преди да сравнявате заглавия. Измерените и приблизителните индикатори ползват една скала, но не една и съща точност.
- Ако филтрирате често, пазете `name` и `avg` заедно с id на заглавието в собствената си база данни. Локалният филтър е по-добър от заявка за всяко заглавие.
- Комбинирайте индикаторите с [рейтинги](https://amodb.dev/bg/ratings/) за оценка и със [саундтраци](https://amodb.dev/bg/soundtracks/) за музиката в същото заглавие.

## Въпроси и отговори

### Какво означава стойността на настроението?

Полето avg е интензитет по скала от 0 до 10, с един знак след десетичната запетая за измерените заглавия. Стойност avg 7 за fear означава, че заглавието е страшно, а 0 означава, че настроението липсва. Не е процент и не е оценка от ревю.

### Фиксиран ли е списъкът с имена на настроения?

Не приемайте, че е. Днес се срещат action, fear, humor, pace, profanity, romance, sadness, sex и violence, а едно заглавие може да има по-малко от девет. Показвайте получените низове с имена, за да се появи и ново настроение.

### Какво означават measured и estimated в source?

Measured означава, че индикаторите идват от данни на зрители и имат десетични знаци. Estimated означава, че са изведени от жанровете на заглавието, затова avg е цяло число. Заглавие без данни има празен масив results и source със стойност null.

### Как да филтрирам списък със заглавия по настроение?

Вземете индикаторите за всяко заглавие от списъка, или през ендпойнта moods, или с append_to_response към детайлите, и оставете заглавията, чието избрано настроение надхвърля вашия праг. Филтърът работи във вашия код.

### Имат ли сериалите настроения?

Да. Ползвайте GET /3/tv/{tv_id}/moods, например с id на сериал 1396. Отговорът има същата форма като ендпойнта за филми.

## Свързани страници

- [API за детайли на филм](https://amodb.dev/bg/movies/): API за детайли на филм със същите пътища и JSON като TMDB v3. Един филм по id, а актьори, рейтинги и настроения през append_to_response, на 14 езика.
- [API за сериали](https://amodb.dev/bg/tv-series/): API за сериали със същите пътища и JSON като TMDB v3. Сериал по id със сезони, мрежи и следващ епизод, плюс възрастови рейтинги и доставчици за гледане.
- [Рейтинги на филми и сериали](https://amodb.dev/bg/ratings/): API за рейтинги на филми връща оценки от IMDb, Kinopoisk, Metacritic, Rotten Tomatoes и TMDB за заглавие с едно извикване, с null за неизвестен източник.
- [Саундтраци](https://amodb.dev/bg/soundtracks/): API за саундтраци връща албума със саундтрака на филм или сериал със списък на песните. Извикайте ендпойнта или добавете append_to_response=soundtracks.
- [Discover API](https://amodb.dev/bg/discover/): Discover API със същите филтри като TMDB v3. Списък с филми и сериали по жанр, актьори, компания, ключова дума, година, рейтинг и продължителност със сортиране.
- [Бърз старт](https://amodb.dev/bg/quickstart/): Първата ви заявка към amodb: вземете ключ, поискайте детайли за филм с curl, JavaScript, Python, PHP или Go и заредете постера от img.amodb.dev. До 2 минути.

Обновено: 2026-10-18. Source: https://amodb.dev/bg/moods/
