iobroker.foobar2000 2.0.3 → 2.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +2 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- package/.github/auto-merge.yml +17 -0
- package/.github/dependabot.yml +18 -0
- package/.github/workflows/dependabot-auto-merge.yml +27 -0
- package/.github/workflows/test-and-release.yml +92 -0
- package/.prettierignore +2 -0
- package/.prettierrc.js +9 -0
- package/.releaseconfig.json +3 -0
- package/LICENSE +2 -1
- package/README.md +49 -19
- package/admin/background.png +0 -0
- package/admin/index_m.html +34 -0
- package/foobar2000.js +49 -44
- package/io-package.json +77 -21
- package/lib/adapter-config.d.ts +16 -0
- package/lib/tools.js +99 -0
- package/main.test.js +30 -0
- package/package.json +40 -24
- package/admin/tsconfig.json +0 -7
package/.eslintignore
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Something is not working as it should
|
|
4
|
+
title: ''
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
**Describe the bug**
|
|
10
|
+
A clear and concise description of what the bug is.
|
|
11
|
+
|
|
12
|
+
**To Reproduce**
|
|
13
|
+
Steps to reproduce the behavior:
|
|
14
|
+
1. Go to '...'
|
|
15
|
+
2. Click on '...'
|
|
16
|
+
3. Scroll down to '....'
|
|
17
|
+
4. See error
|
|
18
|
+
|
|
19
|
+
**Expected behavior**
|
|
20
|
+
A clear and concise description of what you expected to happen.
|
|
21
|
+
|
|
22
|
+
**Screenshots & Logfiles**
|
|
23
|
+
If applicable, add screenshots and logfiles to help explain your problem.
|
|
24
|
+
|
|
25
|
+
**Versions:**
|
|
26
|
+
- Adapter version: <adapter-version>
|
|
27
|
+
- JS-Controller version: <js-controller-version> <!-- determine this with `iobroker -v` on the console -->
|
|
28
|
+
- Node version: <node-version> <!-- determine this with `node -v` on the console -->
|
|
29
|
+
- Operating system: <os-name>
|
|
30
|
+
|
|
31
|
+
**Additional context**
|
|
32
|
+
Add any other context about the problem here.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Configure here which dependency updates should be merged automatically.
|
|
2
|
+
# The recommended configuration is the following:
|
|
3
|
+
- match:
|
|
4
|
+
# Only merge patches for production dependencies
|
|
5
|
+
dependency_type: production
|
|
6
|
+
update_type: "semver:patch"
|
|
7
|
+
- match:
|
|
8
|
+
# Except for security fixes, here we allow minor patches
|
|
9
|
+
dependency_type: production
|
|
10
|
+
update_type: "security:minor"
|
|
11
|
+
- match:
|
|
12
|
+
# and development dependencies can have a minor update, too
|
|
13
|
+
dependency_type: development
|
|
14
|
+
update_type: "semver:minor"
|
|
15
|
+
|
|
16
|
+
# The syntax is based on the legacy dependabot v1 automerged_updates syntax, see:
|
|
17
|
+
# https://dependabot.com/docs/config-file/#automerged_updates
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: npm
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
time: "04:00"
|
|
8
|
+
timezone: Europe/Berlin
|
|
9
|
+
open-pull-requests-limit: 15
|
|
10
|
+
versioning-strategy: increase
|
|
11
|
+
|
|
12
|
+
- package-ecosystem: github-actions
|
|
13
|
+
directory: "/"
|
|
14
|
+
schedule:
|
|
15
|
+
interval: weekly
|
|
16
|
+
time: "04:00"
|
|
17
|
+
timezone: Europe/Berlin
|
|
18
|
+
open-pull-requests-limit: 15
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Automatically merge Dependabot PRs when version comparison is within the range
|
|
2
|
+
# that is configured in .github/auto-merge.yml
|
|
3
|
+
|
|
4
|
+
name: Auto-Merge Dependabot PRs
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
# WARNING: This needs to be run in the PR base, DO NOT build untrusted code in this action
|
|
8
|
+
# details under https://github.blog/changelog/2021-02-19-github-actions-workflows-triggered-by-dependabot-prs-will-run-with-read-only-permissions/
|
|
9
|
+
pull_request_target:
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
auto-merge:
|
|
13
|
+
if: github.actor == 'dependabot[bot]'
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout code
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Check if PR should be auto-merged
|
|
20
|
+
uses: ahmadnassri/action-dependabot-auto-merge@v2
|
|
21
|
+
with:
|
|
22
|
+
# In order to use this, you need to go to https://github.com/settings/tokens and
|
|
23
|
+
# create a Personal Access Token with the permission "public_repo".
|
|
24
|
+
# Enter this token in your repository settings under "Secrets" and name it AUTO_MERGE_TOKEN
|
|
25
|
+
github-token: ${{ secrets.AUTO_MERGE_TOKEN }}
|
|
26
|
+
# By default, squash and merge, so Github chooses nice commit messages
|
|
27
|
+
command: squash and merge
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
name: Test and Release
|
|
2
|
+
|
|
3
|
+
# Run this job on all pushes and pull requests
|
|
4
|
+
# as well as tags with a semantic version
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches:
|
|
8
|
+
- 'master'
|
|
9
|
+
tags:
|
|
10
|
+
# normal versions
|
|
11
|
+
- 'v[0-9]+.[0-9]+.[0-9]+'
|
|
12
|
+
# pre-releases
|
|
13
|
+
- 'v[0-9]+.[0-9]+.[0-9]+-**'
|
|
14
|
+
pull_request: {}
|
|
15
|
+
|
|
16
|
+
# Cancel previous PR/branch runs when a new commit is pushed
|
|
17
|
+
concurrency:
|
|
18
|
+
group: ${{ github.ref }}
|
|
19
|
+
cancel-in-progress: true
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
# Performs quick checks before the expensive test runs
|
|
23
|
+
check-and-lint:
|
|
24
|
+
if: contains(github.event.head_commit.message, '[skip ci]') == false
|
|
25
|
+
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- uses: ioBroker/testing-action-check@v1
|
|
30
|
+
with:
|
|
31
|
+
node-version: '18.x'
|
|
32
|
+
# Uncomment the following line if your adapter cannot be installed using 'npm ci'
|
|
33
|
+
# install-command: 'npm install'
|
|
34
|
+
lint: true
|
|
35
|
+
|
|
36
|
+
# Runs adapter tests on all supported node versions and OSes
|
|
37
|
+
adapter-tests:
|
|
38
|
+
if: contains(github.event.head_commit.message, '[skip ci]') == false
|
|
39
|
+
|
|
40
|
+
runs-on: ${{ matrix.os }}
|
|
41
|
+
strategy:
|
|
42
|
+
matrix:
|
|
43
|
+
node-version: [16.x, 18.x, 20.x]
|
|
44
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
45
|
+
|
|
46
|
+
steps:
|
|
47
|
+
- uses: ioBroker/testing-action-adapter@v1
|
|
48
|
+
with:
|
|
49
|
+
node-version: ${{ matrix.node-version }}
|
|
50
|
+
os: ${{ matrix.os }}
|
|
51
|
+
# Uncomment the following line if your adapter cannot be installed using 'npm ci'
|
|
52
|
+
# install-command: 'npm install'
|
|
53
|
+
|
|
54
|
+
# TODO: To enable automatic npm releases, create a token on npmjs.org
|
|
55
|
+
# Enter this token as a GitHub secret (with name NPM_TOKEN) in the repository options
|
|
56
|
+
# Then uncomment the following block:
|
|
57
|
+
|
|
58
|
+
# Deploys the final package to NPM
|
|
59
|
+
deploy:
|
|
60
|
+
needs: [check-and-lint, adapter-tests]
|
|
61
|
+
|
|
62
|
+
# Trigger this step only when a commit on any branch is tagged with a version number
|
|
63
|
+
if: |
|
|
64
|
+
contains(github.event.head_commit.message, '[skip ci]') == false &&
|
|
65
|
+
github.event_name == 'push' &&
|
|
66
|
+
startsWith(github.ref, 'refs/tags/v')
|
|
67
|
+
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
|
|
70
|
+
# Write permissions are required to create Github releases
|
|
71
|
+
permissions:
|
|
72
|
+
contents: write
|
|
73
|
+
|
|
74
|
+
steps:
|
|
75
|
+
- uses: ioBroker/testing-action-deploy@v1
|
|
76
|
+
with:
|
|
77
|
+
node-version: '18.x'
|
|
78
|
+
# Uncomment the following line if your adapter cannot be installed using 'npm ci'
|
|
79
|
+
# install-command: 'npm install'
|
|
80
|
+
npm-token: ${{ secrets.NPM_TOKEN }}
|
|
81
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
82
|
+
|
|
83
|
+
# When using Sentry for error reporting, Sentry can be informed about new releases
|
|
84
|
+
# To enable create a API-Token in Sentry (User settings, API keys)
|
|
85
|
+
# Enter this token as a GitHub secret (with name SENTRY_AUTH_TOKEN) in the repository options
|
|
86
|
+
# Then uncomment and customize the following block:
|
|
87
|
+
# sentry: true
|
|
88
|
+
# sentry-token: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
89
|
+
# sentry-project: "iobroker-pid"
|
|
90
|
+
# sentry-version-prefix: "iobroker.pid"
|
|
91
|
+
# # If your sentry project is linked to a GitHub repository, you can enable the following option
|
|
92
|
+
# # sentry-github-integration: true
|
package/.prettierignore
ADDED
package/.prettierrc.js
ADDED
package/LICENSE
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
The MIT License (MIT)
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2023 iobroker-community-adapters <mcm57@gmx.at>
|
|
4
|
+
Copyright (c) 2021 instalator <vvvalt@mail.ru>
|
|
4
5
|
|
|
5
6
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
7
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -1,58 +1,88 @@
|
|
|
1
1
|

|
|
2
|
-
# Foobar2000 adapter for iobroker
|
|
3
|
-
  [](https://www.npmjs.com/package/iobroker.foobar2000)
|
|
4
|
-
[](https://www.npmjs.com/package/iobroker.foobar2000)
|
|
5
|
-
[](https://travis-ci.org/instalator/ioBroker.foobar2000)
|
|
6
2
|
|
|
7
|
-
|
|
3
|
+
# iobroker.foobar2000
|
|
8
4
|
|
|
9
|
-
[](https://github.com/iobroker-community-adapters/ioBroker.foobar2000/blob/master/LICENSE)
|
|
6
|
+
[](https://www.npmjs.com/package/iobroker.foobar2000)
|
|
7
|
+

|
|
8
|
+
[](https://weblate.iobroker.net/engage/adapters/?utm_source=widget)</br>
|
|
9
|
+

|
|
10
|
+

|
|
11
|
+

|
|
12
|
+

|
|
13
|
+
</br>
|
|
14
|
+
**Version:** </br>
|
|
15
|
+
[](https://www.npmjs.com/package/iobroker.foobar2000)
|
|
16
|
+

|
|
17
|
+

|
|
18
|
+
</br>
|
|
19
|
+
**Tests:** </br>
|
|
20
|
+
[](https://github.com/iobroker-community-adapters/ioBroker.foobar2000/actions/workflows/test-and-release.yml)
|
|
21
|
+
[](https://github.com/iobroker-community-adapters/ioBroker.foobar2000/actions/workflows/codeql.yml)
|
|
22
|
+
|
|
23
|
+
<!--
|
|
24
|
+
## Sentry
|
|
25
|
+
**This adapter uses Sentry libraries to automatically report exceptions and code errors to the developers.**
|
|
26
|
+
For more details and for information how to disable the error reporting see [Sentry-Plugin Documentation](https://github.com/ioBroker/plugin-sentry#plugin-sentry)! Sentry reporting is used starting with js-controller 3.0.
|
|
27
|
+
-->
|
|
28
|
+
|
|
29
|
+
## Foobar2000 adapter for iobroker
|
|
10
30
|
|
|
11
31
|

|
|
12
32
|
|
|
13
33
|
## Using
|
|
14
|
-
Описание [тут](http://blog.instalator.ru/archives/541).
|
|
15
|
-
Для управления проигрывателем необходимо установить плагин [foo_httpcontrol](https://bitbucket.org/oblikoamorale/foo_httpcontrol/downloads/).
|
|
16
|
-
Для отображения обложки как ссылка на файл, необходимо в файле ```c:\Users\{USER}\AppData\Roaming\foobar2000\foo_httpcontrol_data\foobar2000controller\config``` изменить параметр ```albumart_prefer_embedded=0```
|
|
17
34
|
|
|
18
35
|
To control the player, you must install the plugin [foo_httpcontrol](https://bitbucket.org/oblikoamorale/foo_httpcontrol/downloads/).
|
|
19
36
|
To display the cover as a link to a file, in the file ```c:\Users\{USER}\AppData\Roaming\foobar2000\foo_httpcontrol_data\foobar2000controller\config``` change the parameter ```albumart_prefer_embedded = 0```
|
|
20
37
|
|
|
21
38
|
## Changelog
|
|
22
39
|
|
|
23
|
-
|
|
40
|
+
<!--
|
|
41
|
+
Placeholder for the next version (at the beginning of the line):
|
|
42
|
+
### **WORK IN PROGRESS**
|
|
43
|
+
-->
|
|
44
|
+
### 2.1.0-alpha.0 (2023-11-07)
|
|
45
|
+
* (mcm1957) Adapter requires nodejs16 or newer now.
|
|
46
|
+
* (mcm1957) Adapter has been moved to iobroker-community-adapters organization.
|
|
47
|
+
* (mcm1957) Dependencies have been updated.
|
|
48
|
+
|
|
49
|
+
### 2.0.4
|
|
50
|
+
* (instalator) fixed error
|
|
51
|
+
|
|
52
|
+
### 2.0.3
|
|
24
53
|
* (instalator) fixed admin error
|
|
25
54
|
|
|
26
|
-
|
|
55
|
+
### 2.0.2
|
|
27
56
|
* (instalator) fixed error
|
|
28
57
|
|
|
29
|
-
|
|
58
|
+
### 2.0.0
|
|
30
59
|
* (instalator) Completely rewritten
|
|
31
60
|
|
|
32
|
-
|
|
61
|
+
### 1.0.0
|
|
33
62
|
* (instalator) Up to stable
|
|
34
63
|
|
|
35
|
-
|
|
64
|
+
### 0.2.0
|
|
36
65
|
* (instalator) Change for widgets vis-players
|
|
37
66
|
|
|
38
|
-
|
|
67
|
+
### 0.1.2
|
|
39
68
|
* (instalator) del widgets folders
|
|
40
69
|
* (instalator) change log level
|
|
41
70
|
* (instalator) add news object
|
|
42
71
|
|
|
43
|
-
|
|
72
|
+
### 0.1.1
|
|
44
73
|
* (instalator) fix start, exit for local
|
|
45
74
|
|
|
46
|
-
|
|
75
|
+
### 0.1.0
|
|
47
76
|
* (instalator) beta (20.10.2016)
|
|
48
77
|
|
|
49
|
-
|
|
78
|
+
### 0.0.1
|
|
50
79
|
* (instalator) initial (12.10.2016)
|
|
51
80
|
|
|
52
81
|
## License
|
|
53
82
|
The MIT License (MIT)
|
|
54
83
|
|
|
55
|
-
Copyright (c)
|
|
84
|
+
Copyright (c) 2023 iobroker-community-adapters <mcm57@gmx.at>
|
|
85
|
+
Copyright (c) 2021 instalator <vvvalt@mail.ru>
|
|
56
86
|
|
|
57
87
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
58
88
|
of this software and associated documentation files (the "Software"), to deal
|
|
Binary file
|
package/admin/index_m.html
CHANGED
|
@@ -72,7 +72,41 @@
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
</script>
|
|
75
|
+
<script>
|
|
76
|
+
$(function (){
|
|
77
|
+
$(".adapter-body").append("" +
|
|
78
|
+
"<div class=\"m row\" style='display:block;position:absolute;bottom:130px;right:0;'>" +
|
|
79
|
+
"<div class=\"col right\">" +
|
|
80
|
+
"<div class=\"col\" style=\"margin-top:10px;float:right;margin-right:20px;\">" +
|
|
81
|
+
"<a target=\"_blank\" href=\"https://sobe.ru/na/instalator\"><img style=\"float:right;\" src=\"https://img.shields.io/badge/Donate-YooMoney-green\" alt=\"\"></a>" +
|
|
82
|
+
"<a target=\"_blank\" href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PFUALWTR2CTPY\"><img style=\"float:right;padding-right:10px;\" src=\"https://img.shields.io/badge/Donate-PayPal-green.svg\" alt=\"\"></a>" +
|
|
83
|
+
"</div></div></div>");
|
|
84
|
+
});
|
|
85
|
+
</script>
|
|
86
|
+
<style>
|
|
87
|
+
.adapter-body {
|
|
88
|
+
display: block;
|
|
89
|
+
}
|
|
75
90
|
|
|
91
|
+
.m .input-field > label {
|
|
92
|
+
color: #5a5a5a;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.adapter-body::after {
|
|
96
|
+
top: 0;
|
|
97
|
+
left: 0;
|
|
98
|
+
bottom: 0;
|
|
99
|
+
right: 0;
|
|
100
|
+
content: "";
|
|
101
|
+
background: url(background.png);
|
|
102
|
+
background-position: top;
|
|
103
|
+
background-repeat: no-repeat;
|
|
104
|
+
background-size: cover;
|
|
105
|
+
opacity: 0.2;
|
|
106
|
+
position: absolute;
|
|
107
|
+
z-index: -1;
|
|
108
|
+
}
|
|
109
|
+
</style>
|
|
76
110
|
</head>
|
|
77
111
|
<body>
|
|
78
112
|
<div class="m adapter-container">
|
package/foobar2000.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
const utils = require('@iobroker/adapter-core');
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
let adapter
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
const http = require('http');
|
|
4
|
+
const exec = require('child_process').exec;
|
|
5
|
+
let adapter;
|
|
6
|
+
let foobarPath = null;
|
|
7
|
+
let timerPoll;
|
|
8
|
+
let timeout;
|
|
9
|
+
let muteVol = 100;
|
|
10
|
+
let request;
|
|
11
|
+
let old_states;
|
|
12
|
+
const states = {
|
|
13
|
+
playlist: []
|
|
14
|
+
};
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
const Commands = {
|
|
12
17
|
'play': 'Start',
|
|
13
18
|
'stop': 'Stop',
|
|
14
19
|
'next': 'StartNext',
|
|
@@ -41,7 +46,7 @@ function startAdapter(options){
|
|
|
41
46
|
timerPoll && clearInterval(timerPoll);
|
|
42
47
|
timeout && clearTimeout(timeout);
|
|
43
48
|
try {
|
|
44
|
-
debug('cleaned everything up...');
|
|
49
|
+
adapter.log.debug('cleaned everything up...');
|
|
45
50
|
callback();
|
|
46
51
|
} catch (e) {
|
|
47
52
|
callback();
|
|
@@ -51,7 +56,7 @@ function startAdapter(options){
|
|
|
51
56
|
if (id && state && !state.ack){
|
|
52
57
|
adapter.log.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
|
|
53
58
|
let param;
|
|
54
|
-
id = id.split(
|
|
59
|
+
id = id.split('.')[2].toString().toLowerCase();
|
|
55
60
|
if (id === 'start' || id === 'exit'){
|
|
56
61
|
launch(id);
|
|
57
62
|
return;
|
|
@@ -138,14 +143,14 @@ function startAdapter(options){
|
|
|
138
143
|
path: '/foobar2000controller/?cmd=Browse¶m1=' + param + '¶m2=EnqueueDirSubdirs' //¶m3=browser.json
|
|
139
144
|
};*/
|
|
140
145
|
timeout && clearTimeout(timeout);
|
|
141
|
-
httpGet('Browse', [param, 'EnqueueDirSubdirs'], (
|
|
146
|
+
httpGet('Browse', [param, 'EnqueueDirSubdirs'], (_data) => {
|
|
142
147
|
timeout = setTimeout(() => {
|
|
143
148
|
getPlaylist();
|
|
144
149
|
}, 1000);
|
|
145
150
|
});
|
|
146
151
|
}
|
|
147
152
|
} else {
|
|
148
|
-
|
|
153
|
+
const cmd = Commands[id];
|
|
149
154
|
if (cmd){
|
|
150
155
|
if (param !== undefined){
|
|
151
156
|
httpGet(cmd, [param]);
|
|
@@ -166,7 +171,7 @@ function httpGet(cmd, param, cb){
|
|
|
166
171
|
params += '¶m' + (i + 1) + '=' + key;
|
|
167
172
|
});
|
|
168
173
|
}
|
|
169
|
-
|
|
174
|
+
const options = {
|
|
170
175
|
host: adapter.config.ip || '127.0.0.1',
|
|
171
176
|
port: adapter.config.port || 8888,
|
|
172
177
|
path: '/foobar2000controller/?cmd=' + cmd + params
|
|
@@ -218,8 +223,8 @@ function getCurrentTrackInfo(cb){
|
|
|
218
223
|
if (res){
|
|
219
224
|
states.volume = res.volume;
|
|
220
225
|
states.state = statePlaying(res.isPlaying, res.playingItem);
|
|
221
|
-
states.album = res.playlist[0].album === '?' ? '':
|
|
222
|
-
states.artist = res.playlist[0].artist === '?' ? res.playlist[0].track:
|
|
226
|
+
states.album = res.playlist[0].album === '?' ? '' :res.playlist[0].album;
|
|
227
|
+
states.artist = res.playlist[0].artist === '?' ? res.playlist[0].track :res.playlist[0].artist;
|
|
223
228
|
states.title = res.playlist[0].track;
|
|
224
229
|
states.current_duration = res.playlist[0].len;
|
|
225
230
|
states.rating = res.playlist[0].rating !== '?' ? res.playlist[0].rating :'';
|
|
@@ -236,7 +241,7 @@ function getCurrentTrackInfo(cb){
|
|
|
236
241
|
states.volumeDB = parseInt(res.volumeDB, 10);
|
|
237
242
|
states.trackLength = parseInt(res.trackLength, 10);
|
|
238
243
|
states.elapsedTime = parseInt(res.trackPosition, 10);
|
|
239
|
-
states.seek = isNaN(parseFloat((res.trackPosition / res.trackLength) * 100).toFixed(4)) ? 0:parseFloat((res.trackPosition / res.trackLength) * 100).toFixed(4);
|
|
244
|
+
states.seek = isNaN(parseFloat((res.trackPosition / res.trackLength) * 100).toFixed(4)) ? 0 :parseFloat((res.trackPosition / res.trackLength) * 100).toFixed(4);
|
|
240
245
|
states.mute = res.volume === 0;
|
|
241
246
|
cb && cb();
|
|
242
247
|
}
|
|
@@ -356,41 +361,41 @@ function setInfoConnection(val){
|
|
|
356
361
|
function secToText(sec){
|
|
357
362
|
let res;
|
|
358
363
|
let m = Math.floor(sec / 60);
|
|
359
|
-
|
|
360
|
-
|
|
364
|
+
const s = sec % 60;
|
|
365
|
+
const h = Math.floor(m / 60);
|
|
361
366
|
m = m % 60;
|
|
362
367
|
if (h > 0){
|
|
363
|
-
res = pad2(h) +
|
|
368
|
+
res = pad2(h) + ':' + pad2(m) + ':' + pad2(s);
|
|
364
369
|
} else {
|
|
365
|
-
res = pad2(m) +
|
|
370
|
+
res = pad2(m) + ':' + pad2(s);
|
|
366
371
|
}
|
|
367
372
|
return res;
|
|
368
373
|
}
|
|
369
374
|
|
|
370
375
|
function pad2(num){
|
|
371
|
-
|
|
372
|
-
return (s.length < 2) ?
|
|
376
|
+
const s = num.toString();
|
|
377
|
+
return (s.length < 2) ? '0' + s :s;
|
|
373
378
|
}
|
|
374
379
|
|
|
375
380
|
function getPlaylist(){
|
|
376
381
|
httpGet('PlaylistItemsPerPage', [16384], (res) => {
|
|
377
382
|
if (res && res.playlist){
|
|
378
|
-
|
|
379
|
-
|
|
383
|
+
const playlist = [];
|
|
384
|
+
//const arr = res.songs;
|
|
380
385
|
res.playlist.forEach((key, i) => {
|
|
381
386
|
playlist[i] = {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
}
|
|
387
|
+
'id': i + 1,
|
|
388
|
+
'artist': key.artist,
|
|
389
|
+
'album': key.album,
|
|
390
|
+
'bitrate': 0,
|
|
391
|
+
'title': key.track,
|
|
392
|
+
'file': '',
|
|
393
|
+
'genre': '',
|
|
394
|
+
'year': 0,
|
|
395
|
+
'len': key.len,
|
|
396
|
+
'rating': key.rating,
|
|
397
|
+
'cover': ''
|
|
398
|
+
};
|
|
394
399
|
});
|
|
395
400
|
states.playlist = JSON.stringify(playlist);
|
|
396
401
|
states.playlists = JSON.stringify(res.playlists);
|
|
@@ -407,8 +412,8 @@ function launch(cmd){
|
|
|
407
412
|
sendShellCommand('exit');
|
|
408
413
|
}
|
|
409
414
|
} else if (adapter.config.cmdstart){
|
|
410
|
-
|
|
411
|
-
|
|
415
|
+
const parts = adapter.config.path.split(':');
|
|
416
|
+
const options = {
|
|
412
417
|
host: parts[0],
|
|
413
418
|
port: parts[1],
|
|
414
419
|
path: ''
|
|
@@ -456,18 +461,18 @@ function browser(cmd, param){
|
|
|
456
461
|
}
|
|
457
462
|
|
|
458
463
|
function filemanager(val, arr){
|
|
459
|
-
|
|
464
|
+
const browser = {}, files = [];
|
|
460
465
|
arr.forEach((item, i, arr) => {
|
|
461
|
-
|
|
462
|
-
|
|
466
|
+
const obj = {};
|
|
467
|
+
const size = parseFloat(arr[i].fs) * 1024;
|
|
463
468
|
if (!isNaN(size)){
|
|
464
469
|
obj.size = (parseFloat(arr[i].fs.replace(',', '.')) * 1024).toFixed(0);
|
|
465
470
|
} else {
|
|
466
471
|
obj.size = '';
|
|
467
472
|
}
|
|
468
473
|
if (arr[i].ft && ~arr[i].ft.indexOf(':')){
|
|
469
|
-
|
|
470
|
-
|
|
474
|
+
const mod = arr[i].ft.split(' '); //"27.05.2004 01:50" 2016-02-27 16:05:46
|
|
475
|
+
const d = mod[0].split('.').reverse().join('-');
|
|
471
476
|
arr[i].ft = d + ' ' + mod[1];
|
|
472
477
|
}
|
|
473
478
|
if (arr[i].fs){
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "foobar2000",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.1.0-alpha.0",
|
|
5
5
|
"news": {
|
|
6
|
+
"2.1.0-alpha.0": {
|
|
7
|
+
"en": "Adapter requires nodejs16 or newer now.\nAdapter has been moved to iobroker-community-adapters organization.\nDependencies have been updated.",
|
|
8
|
+
"de": "Adapter benötigt jetzt nodejs16 oder neuer.\nAdapter wurde auf iobroker-community-Adapter Organisation verschoben.\nAbhängigkeiten wurden aktualisiert.",
|
|
9
|
+
"ru": "Адаптер требует nodejs16 или новее теперь.\nАдаптер переехал в организацию iobroker-community-adapters.\nОбновлены зависимости.",
|
|
10
|
+
"pt": "Adaptador requer nodejs16 ou mais recente agora.\nAdapter foi movido para iobroker-community-adapters organização.\nAs dependências foram atualizadas.",
|
|
11
|
+
"nl": "Adapter vereist nodejs16 of Newer nu.\nAdapter is verplaatst naar iobroker-community-papters organisatie.\nAfhankelijkheid is geüpdateerd.",
|
|
12
|
+
"fr": "Adaptateur nécessite nodejs16 ou plus récent maintenant.\nL'adaptateur a été déplacé à l'organisation iobroker-community-adapters.\nLes dépendances ont été mises à jour.",
|
|
13
|
+
"it": "Adattatore richiede nodejs16 o più nuovo ora.\nL'adattatore è stato trasferito all'organizzazione iobroker-community-adapters.\nLe dipendenze sono state aggiornate.",
|
|
14
|
+
"es": "Adaptador requiere nodejs16 o nuevo ahora.\nEl adaptador ha sido trasladado a la organización de ibroker-community-adapters.\nSe han actualizado las dependencias.",
|
|
15
|
+
"pl": "Adapter wymaga węzłów 16 lub nowszych.\nAdapter przeniesiono do organizacji iobroker-community-adapter.\nW zależności zostały zaktualizowane.",
|
|
16
|
+
"uk": "Адаптер вимагає nodejs16 або новіший зараз.\nПереміщено перехід на організацію iobroker-community-adapters.\nОновлено залежність.",
|
|
17
|
+
"zh-cn": "道歉要求现在不再出现。.\n现已移到加勒比妓院。.\n情况已经更新。."
|
|
18
|
+
},
|
|
19
|
+
"2.0.4": {
|
|
20
|
+
"en": "fixed error",
|
|
21
|
+
"de": "fixed error",
|
|
22
|
+
"ru": "fixed error",
|
|
23
|
+
"pt": "fixed error",
|
|
24
|
+
"nl": "fixed error",
|
|
25
|
+
"fr": "fixed error",
|
|
26
|
+
"it": "fixed error",
|
|
27
|
+
"es": "fixed error",
|
|
28
|
+
"pl": "fixed error",
|
|
29
|
+
"zh-cn": "fixed error"
|
|
30
|
+
},
|
|
6
31
|
"2.0.3": {
|
|
7
32
|
"en": "fixed admin error",
|
|
8
33
|
"de": "fixed admin error",
|
|
@@ -28,37 +53,64 @@
|
|
|
28
53
|
"zh-cn": "Completely rewritten"
|
|
29
54
|
}
|
|
30
55
|
},
|
|
31
|
-
"
|
|
56
|
+
"titleLang": {
|
|
57
|
+
"en": "Control foobar2000 player",
|
|
58
|
+
"de": "Steuerung foobar2000 Player",
|
|
59
|
+
"ru": "Управление foobar2000 игроком",
|
|
60
|
+
"pt": "Control foobar2000 jogador",
|
|
61
|
+
"nl": "Controle:",
|
|
62
|
+
"fr": "Contrôle du joueur de foobar2000",
|
|
63
|
+
"it": "Controllo del lettore foobar2000",
|
|
64
|
+
"es": "Control foobar2000 jugador",
|
|
65
|
+
"pl": "Foobar2000 player",
|
|
66
|
+
"uk": "Контроль фобар2000",
|
|
67
|
+
"zh-cn": "控制软禁2000年"
|
|
68
|
+
},
|
|
32
69
|
"desc": {
|
|
33
70
|
"en": "Control your foobar2000 player",
|
|
34
|
-
"de": "Steuern Sie Ihren foobar2000
|
|
35
|
-
"ru": "
|
|
36
|
-
"pt": "Controle o seu foobar2000
|
|
37
|
-
"nl": "
|
|
71
|
+
"de": "Steuern Sie Ihren foobar2000 Player",
|
|
72
|
+
"ru": "Контролируйте своего игрока foobar2000",
|
|
73
|
+
"pt": "Controle o seu jogador foobar2000",
|
|
74
|
+
"nl": "Controleer je foobar2000 speler",
|
|
38
75
|
"fr": "Contrôlez votre lecteur foobar2000",
|
|
39
|
-
"it": "Controlla il tuo
|
|
40
|
-
"es": "
|
|
41
|
-
"pl": "
|
|
42
|
-
"
|
|
76
|
+
"it": "Controlla il tuo lettore foobar2000",
|
|
77
|
+
"es": "Controle su jugador foobar2000",
|
|
78
|
+
"pl": "Kontrola nad foobar2000",
|
|
79
|
+
"uk": "Керуйте фобар2000",
|
|
80
|
+
"zh-cn": "控制你的野蛮2000年事件"
|
|
43
81
|
},
|
|
44
|
-
"license": "MIT",
|
|
45
82
|
"authors": [
|
|
46
|
-
"instalator"
|
|
83
|
+
"instalator",
|
|
84
|
+
"iobroker-community-adapters <mcm57@gmx.at>"
|
|
85
|
+
],
|
|
86
|
+
"keywords": [
|
|
87
|
+
"foobar2000",
|
|
88
|
+
"player"
|
|
47
89
|
],
|
|
90
|
+
"license": "MIT",
|
|
48
91
|
"platform": "Javascript/Node.js",
|
|
49
|
-
"
|
|
92
|
+
"main": "foobar2000.js",
|
|
50
93
|
"icon": "foobar2000.png",
|
|
51
94
|
"enabled": false,
|
|
52
|
-
"
|
|
53
|
-
"
|
|
95
|
+
"extIcon": "https://raw.githubusercontent.com/iobroker-community-adapters/iobroker.foobar2000/master/admin/foobar2000.png",
|
|
96
|
+
"readme": "https://github.com/iobroker-community-adapters/iobroker.foobar2000/blob/master/README.md",
|
|
54
97
|
"loglevel": "info",
|
|
98
|
+
"mode": "daemon",
|
|
55
99
|
"type": "multimedia",
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
100
|
+
"compact": true,
|
|
101
|
+
"connectionType": "local",
|
|
102
|
+
"dataSource": "pull",
|
|
103
|
+
"materialize": true,
|
|
104
|
+
"dependencies": [
|
|
105
|
+
{
|
|
106
|
+
"js-controller": ">=4.0.24"
|
|
107
|
+
}
|
|
60
108
|
],
|
|
61
|
-
"
|
|
109
|
+
"globalDependencies": [
|
|
110
|
+
{
|
|
111
|
+
"admin": ">=5.1.13"
|
|
112
|
+
}
|
|
113
|
+
]
|
|
62
114
|
},
|
|
63
115
|
"native": {
|
|
64
116
|
"ip": "127.0.0.1",
|
|
@@ -392,7 +444,11 @@
|
|
|
392
444
|
"read": true,
|
|
393
445
|
"write": true,
|
|
394
446
|
"def": false,
|
|
395
|
-
"states": {
|
|
447
|
+
"states": {
|
|
448
|
+
"0": "Off",
|
|
449
|
+
"1": "All",
|
|
450
|
+
"2": "One"
|
|
451
|
+
}
|
|
396
452
|
},
|
|
397
453
|
"native": {}
|
|
398
454
|
},
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// This file extends the AdapterConfig type from "@types/iobroker"
|
|
2
|
+
// using the actual properties present in io-package.json
|
|
3
|
+
// in order to provide typings for adapter.config properties
|
|
4
|
+
|
|
5
|
+
import { native } from '../io-package.json';
|
|
6
|
+
|
|
7
|
+
type _AdapterConfig = typeof native;
|
|
8
|
+
|
|
9
|
+
// Augment the globally declared type ioBroker.AdapterConfig
|
|
10
|
+
declare global {
|
|
11
|
+
namespace ioBroker {
|
|
12
|
+
interface AdapterConfig extends _AdapterConfig {
|
|
13
|
+
// Do not enter anything here!
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
package/lib/tools.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tests whether the given variable is a real object and not an Array
|
|
5
|
+
* @param {any} it The variable to test
|
|
6
|
+
* @returns {it is Record<string, any>}
|
|
7
|
+
*/
|
|
8
|
+
function isObject(it) {
|
|
9
|
+
// This is necessary because:
|
|
10
|
+
// typeof null === 'object'
|
|
11
|
+
// typeof [] === 'object'
|
|
12
|
+
// [] instanceof Object === true
|
|
13
|
+
return Object.prototype.toString.call(it) === '[object Object]';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Tests whether the given variable is really an Array
|
|
18
|
+
* @param {any} it The variable to test
|
|
19
|
+
* @returns {it is any[]}
|
|
20
|
+
*/
|
|
21
|
+
function isArray(it) {
|
|
22
|
+
if (typeof Array.isArray === 'function') return Array.isArray(it);
|
|
23
|
+
return Object.prototype.toString.call(it) === '[object Array]';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Translates text to the target language. Automatically chooses the right translation API.
|
|
28
|
+
* @param {string} text The text to translate
|
|
29
|
+
* @param {string} targetLang The target languate
|
|
30
|
+
* @param {string} [yandexApiKey] The yandex API key. You can create one for free at https://translate.yandex.com/developers
|
|
31
|
+
* @returns {Promise<string>}
|
|
32
|
+
*/
|
|
33
|
+
async function translateText(text, targetLang, yandexApiKey) {
|
|
34
|
+
if (targetLang === 'en') {
|
|
35
|
+
return text;
|
|
36
|
+
} else if (!text) {
|
|
37
|
+
return '';
|
|
38
|
+
}
|
|
39
|
+
if (yandexApiKey) {
|
|
40
|
+
return translateYandex(text, targetLang, yandexApiKey);
|
|
41
|
+
} else {
|
|
42
|
+
return translateGoogle(text, targetLang);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Translates text with Yandex API
|
|
48
|
+
* @param {string} text The text to translate
|
|
49
|
+
* @param {string} targetLang The target languate
|
|
50
|
+
* @param {string} apiKey The yandex API key. You can create one for free at https://translate.yandex.com/developers
|
|
51
|
+
* @returns {Promise<string>}
|
|
52
|
+
*/
|
|
53
|
+
async function translateYandex(text, targetLang, apiKey) {
|
|
54
|
+
if (targetLang === 'zh-cn') {
|
|
55
|
+
targetLang = 'zh';
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const url = `https://translate.yandex.net/api/v1.5/tr.json/translate?key=${apiKey}&text=${encodeURIComponent(text)}&lang=en-${targetLang}`;
|
|
59
|
+
const response = await axios({url, timeout: 15000});
|
|
60
|
+
if (response.data && response.data.text && isArray(response.data.text)) {
|
|
61
|
+
return response.data.text[0];
|
|
62
|
+
}
|
|
63
|
+
throw new Error('Invalid response for translate request');
|
|
64
|
+
} catch (e) {
|
|
65
|
+
throw new Error(`Could not translate to "${targetLang}": ${e}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Translates text with Google API
|
|
71
|
+
* @param {string} text The text to translate
|
|
72
|
+
* @param {string} targetLang The target languate
|
|
73
|
+
* @returns {Promise<string>}
|
|
74
|
+
*/
|
|
75
|
+
async function translateGoogle(text, targetLang) {
|
|
76
|
+
try {
|
|
77
|
+
const url = `http://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}&ie=UTF-8&oe=UTF-8`;
|
|
78
|
+
const response = await axios({url, timeout: 15000});
|
|
79
|
+
if (isArray(response.data)) {
|
|
80
|
+
// we got a valid response
|
|
81
|
+
return response.data[0][0][0];
|
|
82
|
+
}
|
|
83
|
+
throw new Error('Invalid response for translate request');
|
|
84
|
+
} catch (e) {
|
|
85
|
+
if (e.response && e.response.status === 429) {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`Could not translate to "${targetLang}": Rate-limited by Google Translate`
|
|
88
|
+
);
|
|
89
|
+
} else {
|
|
90
|
+
throw new Error(`Could not translate to "${targetLang}": ${e}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = {
|
|
96
|
+
isArray,
|
|
97
|
+
isObject,
|
|
98
|
+
translateText
|
|
99
|
+
};
|
package/main.test.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This is a dummy TypeScript test file using chai and mocha
|
|
5
|
+
*
|
|
6
|
+
* It's automatically excluded from npm and its build output is excluded from both git and npm.
|
|
7
|
+
* It is advised to test all your modules with accompanying *.test.js-files
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// tslint:disable:no-unused-expression
|
|
11
|
+
|
|
12
|
+
const { expect } = require('chai');
|
|
13
|
+
// import { functionToTest } from "./moduleToTest";
|
|
14
|
+
|
|
15
|
+
describe('module to test => function to test', () => {
|
|
16
|
+
// initializing logic
|
|
17
|
+
const expected = 5;
|
|
18
|
+
|
|
19
|
+
it(`should return ${expected}`, () => {
|
|
20
|
+
const result = 5;
|
|
21
|
+
// assign result a value from functionToTest
|
|
22
|
+
expect(result).to.equal(expected);
|
|
23
|
+
// or using the should() syntax
|
|
24
|
+
result.should.equal(expected);
|
|
25
|
+
});
|
|
26
|
+
// ... more tests => it
|
|
27
|
+
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// ... more test suites => describe
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.foobar2000",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.1.0-alpha.0",
|
|
4
4
|
"description": "ioBroker Foobar2000 player adapter",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "instalator",
|
|
@@ -10,9 +10,13 @@
|
|
|
10
10
|
{
|
|
11
11
|
"name": "instalator",
|
|
12
12
|
"email": "vvvalt@mail.ru"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "iobroker-community-adapters",
|
|
16
|
+
"email": "mcm57@gmx.at"
|
|
13
17
|
}
|
|
14
18
|
],
|
|
15
|
-
"homepage": "https://github.com/
|
|
19
|
+
"homepage": "https://github.com/iobroker-community-adapters/iobroker.foobar2000",
|
|
16
20
|
"license": "MIT",
|
|
17
21
|
"keywords": [
|
|
18
22
|
"ioBroker",
|
|
@@ -22,42 +26,54 @@
|
|
|
22
26
|
],
|
|
23
27
|
"repository": {
|
|
24
28
|
"type": "git",
|
|
25
|
-
"url": "https://github.com/
|
|
29
|
+
"url": "https://github.com/iobroker-community-adapters/ioBroker.foobar2000.git"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=16"
|
|
26
33
|
},
|
|
27
34
|
"dependencies": {
|
|
28
|
-
"@iobroker/adapter-core": "^
|
|
35
|
+
"@iobroker/adapter-core": "^3.0.4"
|
|
29
36
|
},
|
|
30
37
|
"devDependencies": {
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"@
|
|
34
|
-
"@
|
|
35
|
-
"@
|
|
36
|
-
"@
|
|
37
|
-
"@
|
|
38
|
-
"@types/
|
|
39
|
-
"@types/
|
|
40
|
-
"
|
|
41
|
-
"
|
|
38
|
+
"@alcalzone/release-script": "^3.6.0",
|
|
39
|
+
"@alcalzone/release-script-plugin-iobroker": "^3.6.0",
|
|
40
|
+
"@alcalzone/release-script-plugin-license": "^3.5.9",
|
|
41
|
+
"@alcalzone/release-script-plugin-manual-review": "^3.5.9",
|
|
42
|
+
"@iobroker/adapter-dev": "^1.2.0",
|
|
43
|
+
"@iobroker/testing": "^4.1.0",
|
|
44
|
+
"@tsconfig/node14": "^14.1.0",
|
|
45
|
+
"@types/chai": "^4.3.8",
|
|
46
|
+
"@types/chai-as-promised": "^7.1.6",
|
|
47
|
+
"@types/mocha": "^10.0.2",
|
|
48
|
+
"@types/node": "^20.8.6",
|
|
49
|
+
"@types/proxyquire": "^1.3.29",
|
|
50
|
+
"@types/sinon": "^17.0.0",
|
|
51
|
+
"@types/sinon-chai": "^3.2.10",
|
|
52
|
+
"chai": "^4.3.10",
|
|
42
53
|
"chai-as-promised": "^7.1.1",
|
|
43
|
-
"eslint": "^
|
|
44
|
-
"
|
|
45
|
-
"
|
|
54
|
+
"eslint": "^8.51.0",
|
|
55
|
+
"eslint-config-prettier": "^8.9.0",
|
|
56
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
57
|
+
"mocha": "^10.2.0",
|
|
58
|
+
"prettier": "^3.0.3",
|
|
46
59
|
"proxyquire": "^2.1.3",
|
|
47
|
-
"sinon": "^
|
|
48
|
-
"sinon-chai": "^3.
|
|
60
|
+
"sinon": "^17.0.1",
|
|
61
|
+
"sinon-chai": "^3.7.0",
|
|
62
|
+
"typescript": "~5.2.2"
|
|
49
63
|
},
|
|
50
64
|
"main": "foobar2000.js",
|
|
51
65
|
"scripts": {
|
|
52
|
-
"test:js": "mocha --
|
|
66
|
+
"test:js": "mocha --config test/mocharc.custom.json \"{!(node_modules|test)/**/*.test.js,*.test.js,test/**/test!(PackageFiles|Startup).js}\"",
|
|
53
67
|
"test:package": "mocha test/package --exit",
|
|
54
|
-
"test:unit": "mocha test/unit --exit",
|
|
55
68
|
"test:integration": "mocha test/integration --exit",
|
|
56
69
|
"test": "npm run test:js && npm run test:package",
|
|
57
|
-
"
|
|
70
|
+
"check": "tsc --noEmit -p tsconfig.check.json",
|
|
71
|
+
"lint": "eslint .",
|
|
72
|
+
"translate": "translate-adapter",
|
|
73
|
+
"release": "release-script"
|
|
58
74
|
},
|
|
59
75
|
"bugs": {
|
|
60
|
-
"url": "https://github.com/
|
|
76
|
+
"url": "https://github.com/iobroker-community-adapters/iobroker.foobar2000/issues"
|
|
61
77
|
},
|
|
62
78
|
"readmeFilename": "README.md"
|
|
63
79
|
}
|