diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f7196aca..77dac552 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -10,24 +10,24 @@
### channels
-| Field | Description | Required | Example |
-| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------ |
-| id | Unique channel ID derived from the `name` and `country` separated by dot. May only contain Latin letters, numbers and dot. | Required | `AnhuiTV.cn` |
-| name | Official channel name in English or call sign. May include: `a-z`, `0-9`, `space`, `-`, `!`, `:`, `&`, `.`, `+`, `'`, `/`, `»`, `#`, `%`, `°`, `$`, `@`, `?`, \|
, `¡`, `–`. | Required | `Anhui TV` |
-| alt_names | List of alternative channel names separated by `;`. May contain any characters except `,` and `"`. | Optional | `安徽卫视;AHTV` |
-| network | Network of which this channel is a part. May contain any characters except `,` and `"`. | Optional | `Anhui` |
-| owners | List of channel owners separated by `;`. May contain any characters except `,` and `"`. | Optional | `China Central Television` |
-| country | Country code from which the channel is transmitted. A list of all supported countries and their codes can be found in [data/countries.csv](data/countries.csv) | Required | `CN` |
-| subdivision | Code of the subdivision (e.g., provinces or states) from which the broadcast is transmitted. A list of all supported subdivisions and their codes can be found in [data/subdivisions.csv](data/subdivisions.csv). | Optional | `CN-AH` |
-| city | The name of the city in English from which the channel is broadcast. May contain any characters except `,` and `"`. | Optional | `Hefei` |
-| broadcast_area | List of codes describing the broadcasting area of the channel separated by `;`. Any combination of `r/`, `c/`, `s/`. | Required | `c/CN;r/ASIA` |
-| languages | List of languages in which the channel is broadcast separated by `;`. A list of all supported languages and their codes can be found in [data/languages.csv](data/languages.csv). | Required | `zho;eng` |
-| categories | List of categories to which this channel belongs separated by `;`. A list of all supported categories can be found in [data/categories.csv](data/categories.csv). | Optional | `animation;kids` |
-| is_nsfw | Indicates whether the channel broadcasts adult content (`TRUE` or `FALSE`). | Required | `FALSE` |
-| launched | Launch date of the channel (`YYYY-MM-DD`). | Optional | `2016-07-28` |
-| closed | Date on which the channel closed (`YYYY-MM-DD`). | Optional | `2020-05-31` |
-| replaced_by | The ID of the channel that this channel was replaced by. | Optional | `CCTV1.cn` |
-| website | Official website URL. | Optional | `http://www.ahtv.cn/` |
+| Field | Description | Required | Example |
+| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------ |
+| id | Unique channel ID derived from the `name` and `country` separated by dot. May only contain Latin letters, numbers and dot. | Required | `AnhuiTV.cn` |
+| name | Official channel name in English or call sign. May include: `a-z`, `0-9`, `space`, `-`, `!`, `:`, `&`, `.`, `+`, `'`, `/`, `»`, `#`, `%`, `°`, `$`, `@`, `?`, \|
, `¡`. | Required | `Anhui TV` |
+| alt_names | List of alternative channel names separated by `;`. May contain any characters except `,` and `"`. | Optional | `安徽卫视;AHTV` |
+| network | Network of which this channel is a part. May contain any characters except `,` and `"`. | Optional | `Anhui` |
+| owners | List of channel owners separated by `;`. May contain any characters except `,` and `"`. | Optional | `China Central Television` |
+| country | Country code from which the channel is transmitted. A list of all supported countries and their codes can be found in [data/countries.csv](data/countries.csv) | Required | `CN` |
+| subdivision | Code of the subdivision (e.g., provinces or states) from which the broadcast is transmitted. A list of all supported subdivisions and their codes can be found in [data/subdivisions.csv](data/subdivisions.csv). | Optional | `CN-AH` |
+| city | The name of the city in English from which the channel is broadcast. May contain any characters except `,` and `"`. | Optional | `Hefei` |
+| broadcast_area | List of codes describing the broadcasting area of the channel separated by `;`. Any combination of `r/`, `c/`, `s/`. | Required | `c/CN;r/ASIA` |
+| languages | List of languages in which the channel is broadcast separated by `;`. A list of all supported languages and their codes can be found in [data/languages.csv](data/languages.csv). | Required | `zho;eng` |
+| categories | List of categories to which this channel belongs separated by `;`. A list of all supported categories can be found in [data/categories.csv](data/categories.csv). | Optional | `animation;kids` |
+| is_nsfw | Indicates whether the channel broadcasts adult content (`TRUE` or `FALSE`). | Required | `FALSE` |
+| launched | Launch date of the channel (`YYYY-MM-DD`). | Optional | `2016-07-28` |
+| closed | Date on which the channel closed (`YYYY-MM-DD`). | Optional | `2020-05-31` |
+| replaced_by | The ID of the channel that this channel was replaced by. | Optional | `CCTV1.cn` |
+| website | Official website URL. | Optional | `http://www.ahtv.cn/` |
| logo | Logo URL. Only URL with [HTTPS](https://ru.wikipedia.org/wiki/HTTPS) protocol are allowed. Supported image types: `PNG`, `JPEG`. Max size: 512x512 pixels. The link should not be [geo-blocked](https://en.wikipedia.org/wiki/Geo-blocking). May contain any characters except `,` and `"`. | Required | `https://example.com/logo.png` |
### categories
diff --git a/data/channels.csv b/data/channels.csv
index ebfdba1b..dee1cc1b 100644
--- a/data/channels.csv
+++ b/data/channels.csv
@@ -16543,7 +16543,7 @@ KSTVComedySeries.ua,KS TV | Comedy Series,КС ТБ | Комедійні сер
KSTVConcert.ua,KS TV | Concert,КС ТБ | Концерт,,Kyivstar,UA,,Kyiv,c/UA,ukr,music,FALSE,,,,https://tv.kyivstar.ua/en/live-channels/5fd36a935414fee0a809c916-ks-tv-concert-hd,https://i.imgur.com/TWhZf9c.png
KSTVCopWars.ua,KS TV | Cop Wars,КС ТБ | Ментівські війни,,Kyivstar,UA,,Kyiv,c/UA,ukr,,FALSE,,,,https://tv.kyivstar.ua/en/live-channels/6493029e8b94b9c41a08beda-ks-tv-cop-wars,https://i.imgur.com/U6xFbCa.png
KSTVCrime.ua,KS TV | Crime,КС ТБ | Кримінал,,Kyivstar,UA,,Kyiv,c/UA,ukr,,FALSE,,,,https://tv.kyivstar.ua/en/live-channels/633458df50347fd195aeeb37-ks-tv-crime-hd,https://i.imgur.com/14Y1dAm.png
-KSTVCrimeanbridgeitsover.ua,KS TV | Crimean bridge - it's over,КС ТБ | Кримський міст – всьо,,Kyivstar,UA,,Kyiv,c/UA,ukr,,FALSE,,,,https://tv.kyivstar.ua/en/live-channels/634155b445b4e86497aa384f-ks-tv-crimean-bridge-its-over,https://i.imgur.com/ipxyxZj.png
+KSTVCrimeanbridgeitsover.ua,KS TV | Crimean bridge it's over,KS TV | Crimean bridge - it's over;КС ТБ | Кримський міст – всьо,,Kyivstar,UA,,Kyiv,c/UA,ukr,,FALSE,,,,https://tv.kyivstar.ua/en/live-channels/634155b445b4e86497aa384f-ks-tv-crimean-bridge-its-over,https://i.imgur.com/ipxyxZj.png
KSTVCulinary.ua,KS TV | Culinary,КС ТБ | Кулінар,,Kyivstar,UA,,Kyiv,c/UA,ukr,cooking,FALSE,,,,https://tv.kyivstar.ua/en/live-channels/64f83591e4b0a1c5db131360-ks-tv-culinary,https://i.imgur.com/Sjsuhyr.png
KSTVDetective.ua,KS TV | Detective,КС ТБ | Детектив,,Kyivstar,UA,,Kyiv,c/UA,ukr,entertainment,FALSE,,,,https://tv.kyivstar.ua/en/live-channels/60f57a58d0348f888597bae9-ks-tv-detective-hd,https://i.imgur.com/yNrx31O.png
KSTVDoctorshearts.ua,KS TV | Doctors' hearts,КС ТБ | Лікарські серця,,Kyivstar,UA,,Kyiv,c/UA,ukr,,FALSE,,,,https://tv.kyivstar.ua/en/live-channels/646df4f5e4b0f13e55a40d2f-ks-tv-doctors-hearts,https://i.imgur.com/2lqkEeS.png
diff --git a/package-lock.json b/package-lock.json
index 1a2e9abf..5a03aa22 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,7 +21,7 @@
"chalk": "^4.1.2",
"commander": "^9.0.0",
"csvtojson": "^2.0.10",
- "eslint": "^9.18.0",
+ "eslint": "^9.19.0",
"eslint-config-prettier": "^9.0.0",
"fs-extra": "^11.2.0",
"globals": "^15.13.0",
@@ -1135,9 +1135,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.18.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz",
- "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==",
+ "version": "9.19.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz",
+ "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
@@ -3085,16 +3085,16 @@
}
},
"node_modules/eslint": {
- "version": "9.18.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz",
- "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==",
+ "version": "9.19.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz",
+ "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.19.0",
"@eslint/core": "^0.10.0",
"@eslint/eslintrc": "^3.2.0",
- "@eslint/js": "9.18.0",
+ "@eslint/js": "9.19.0",
"@eslint/plugin-kit": "^0.2.5",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
@@ -6831,9 +6831,9 @@
}
},
"@eslint/js": {
- "version": "9.18.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz",
- "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA=="
+ "version": "9.19.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz",
+ "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ=="
},
"@eslint/object-schema": {
"version": "2.1.5",
@@ -8265,16 +8265,16 @@
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"eslint": {
- "version": "9.18.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz",
- "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==",
+ "version": "9.19.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz",
+ "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==",
"requires": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.19.0",
"@eslint/core": "^0.10.0",
"@eslint/eslintrc": "^3.2.0",
- "@eslint/js": "9.18.0",
+ "@eslint/js": "9.19.0",
"@eslint/plugin-kit": "^0.2.5",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
diff --git a/package.json b/package.json
index 2e284597..593ea260 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,7 @@
"chalk": "^4.1.2",
"commander": "^9.0.0",
"csvtojson": "^2.0.10",
- "eslint": "^9.18.0",
+ "eslint": "^9.19.0",
"eslint-config-prettier": "^9.0.0",
"fs-extra": "^11.2.0",
"globals": "^15.13.0",
diff --git a/scripts/schemes/channels.ts b/scripts/schemes/channels.ts
index a4a5bb52..25481753 100644
--- a/scripts/schemes/channels.ts
+++ b/scripts/schemes/channels.ts
@@ -11,6 +11,7 @@ export default {
.required(),
name: Joi.string()
.regex(/^[a-z0-9-!:&.+'/»#%°$@?|¡–\s_—]+$/i)
+ .regex(/^((?!\s-\s).)*$/)
.required(),
alt_names: Joi.array().items(
Joi.string()
diff --git a/tests/__data__/expected/api/blocklist.json b/tests/__data__/expected/api/blocklist.json
index 8a66ad1a..a65c17ce 100644
--- a/tests/__data__/expected/api/blocklist.json
+++ b/tests/__data__/expected/api/blocklist.json
@@ -1 +1 @@
-[{"channel":"AnimalPlanetAfrica.za","ref":"https://github.com/iptv-org/iptv/issues/1831"}]
\ No newline at end of file
+[{"channel":"AnimalPlanetAfrica.za","ref":"https://github.com/iptv-org/iptv/issues/1831"},{"channel":"BeijingSatelliteTV.cn","ref":"https://github.com/iptv-org/iptv/issues/1831"}]
\ No newline at end of file
diff --git a/tests/__data__/expected/api/channels.json b/tests/__data__/expected/api/channels.json
index cfad2a47..0b513021 100644
--- a/tests/__data__/expected/api/channels.json
+++ b/tests/__data__/expected/api/channels.json
@@ -1 +1 @@
-[{"id":"002RadioTV.do","name":"002 Radio TV","alt_names":[],"network":null,"owners":[],"country":"DO","subdivision":null,"city":null,"broadcast_area":["c/DO"],"languages":["spa"],"categories":["general"],"is_nsfw":false,"launched":null,"closed":null,"replaced_by":null,"website":"https://www.002radio.com/","logo":"https://i.imgur.com/7oNe8xj.png"},{"id":"BeijingSatelliteTV.cn","name":"Beijing Satellite TV","alt_names":["北京卫视"],"network":null,"owners":[],"country":"CN","subdivision":null,"city":"Beijing","broadcast_area":["c/CN"],"languages":["zho"],"categories":["general"],"is_nsfw":false,"launched":"1979-05-16","closed":null,"replaced_by":null,"website":"https://www.brtn.cn/btv/","logo":"https://i.imgur.com/vsktAez.png"},{"id":"M5.hu","name":"M5","alt_names":[],"network":null,"owners":[],"country":"HU","subdivision":null,"city":null,"broadcast_area":["c/HU"],"languages":["hun"],"categories":["auto"],"is_nsfw":true,"launched":null,"closed":"2001-01-01","replaced_by":null,"website":"https://www.mediaklikk.hu/m5/","logo":"https://i.imgur.com/y21wFd0.png"}]
\ No newline at end of file
+[{"id":"002RadioTV.do","name":"002 Radio TV","alt_names":[],"network":null,"owners":[],"country":"DO","subdivision":null,"city":null,"broadcast_area":["c/DO"],"languages":["spa"],"categories":["general"],"is_nsfw":false,"launched":null,"closed":null,"replaced_by":null,"website":"https://www.002radio.com/","logo":"https://i.imgur.com/7oNe8xj.png"},{"id":"BeijingSatelliteTV.cn","name":"Beijing Satellite TV","alt_names":["北京卫视"],"network":null,"owners":[],"country":"CN","subdivision":null,"city":"Beijing","broadcast_area":["c/CN"],"languages":["zho"],"categories":["general"],"is_nsfw":false,"launched":"1979-05-16","closed":null,"replaced_by":null,"website":"https://www.brtn.cn/btv/","logo":"https://i.imgur.com/vsktAez.png"},{"id":"M5.hu","name":"M5","alt_names":[],"network":null,"owners":[],"country":"HU","subdivision":null,"city":null,"broadcast_area":["c/HU"],"languages":["hun"],"categories":["auto"],"is_nsfw":true,"launched":null,"closed":"2001-01-01","replaced_by":"BeijingSatelliteTV.cn","website":"https://www.mediaklikk.hu/m5/","logo":"https://i.imgur.com/y21wFd0.png"}]
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index b05cc960..4d2c1598 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -357,10 +357,10 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
-"@eslint/js@^9.16.0", "@eslint/js@9.18.0":
- version "9.18.0"
- resolved "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz"
- integrity sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==
+"@eslint/js@^9.16.0", "@eslint/js@9.19.0":
+ version "9.19.0"
+ resolved "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz"
+ integrity sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==
"@eslint/object-schema@^2.1.5":
version "2.1.5"
@@ -1649,17 +1649,17 @@ eslint-visitor-keys@^4.2.0:
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz"
integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
-"eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^8.57.0 || ^9.0.0", eslint@^9.18.0, eslint@>=7.0.0:
- version "9.18.0"
- resolved "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz"
- integrity sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==
+"eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^8.57.0 || ^9.0.0", eslint@^9.19.0, eslint@>=7.0.0:
+ version "9.19.0"
+ resolved "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz"
+ integrity sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==
dependencies:
"@eslint-community/eslint-utils" "^4.2.0"
"@eslint-community/regexpp" "^4.12.1"
"@eslint/config-array" "^0.19.0"
"@eslint/core" "^0.10.0"
"@eslint/eslintrc" "^3.2.0"
- "@eslint/js" "9.18.0"
+ "@eslint/js" "9.19.0"
"@eslint/plugin-kit" "^0.2.5"
"@humanfs/node" "^0.16.6"
"@humanwhocodes/module-importer" "^1.0.1"