mirror of
https://github.com/iptv-org/epg
synced 2026-09-12 06:46:50 -04:00
[add] adding s.mxtv.jp
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
# s.mxtv.jp
|
||||||
|
|
||||||
|
<https://s.mxtv.jp>
|
||||||
|
|
||||||
|
## Index
|
||||||
|
|
||||||
|
- [Index](#index)
|
||||||
|
- [Download the guide](#download-the-guide)
|
||||||
|
- [Update channel list](#update-channel-list)
|
||||||
|
- [Test](#test)
|
||||||
|
|
||||||
|
## Download the guide
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run grab -- --site=s.mxtv.jp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update channel list
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run channels:parse -- --config=./sites/s.mxtv.jp/s.mxtv.jp.config.js --output=./sites/s.mxtv.jp/s.mxtv.jp.channels.xml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm test -- s.mxtv.jp
|
||||||
|
```
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<channels>
|
||||||
|
<channel site="s.mxtv.jp" lang="ja" xmltv_id="TokyoMX1.jp" site_id="1">Tokyo MX1</channel>
|
||||||
|
<channel site="s.mxtv.jp" lang="ja" xmltv_id="TokyoMX2.jp" site_id="2">Tokyo MX2</channel>
|
||||||
|
</channels>
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
const axios = require('axios')
|
||||||
|
const dayjs = require('dayjs')
|
||||||
|
const duration = require("dayjs/plugin/duration")
|
||||||
|
const utc = require('dayjs/plugin/utc')
|
||||||
|
const timezone = require('dayjs/plugin/timezone')
|
||||||
|
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||||
|
|
||||||
|
dayjs.extend(utc)
|
||||||
|
dayjs.extend(timezone)
|
||||||
|
dayjs.extend(customParseFormat)
|
||||||
|
dayjs.extend(duration)
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
site: 's.mxtv.jp',
|
||||||
|
days: 1,
|
||||||
|
url: function ({ date, channel }) {
|
||||||
|
const id = `SV${channel.site_id}EPG${date.format('YYYYMMDD')}`
|
||||||
|
return `https://s.mxtv.jp/bangumi_file/json01/${id}.json`
|
||||||
|
},
|
||||||
|
parser: function ({ content, channel, date }) {
|
||||||
|
let programs = []
|
||||||
|
const items = parseItems(content, channel, date)
|
||||||
|
items.forEach(item => {
|
||||||
|
programs.push({
|
||||||
|
title: item.Event_name,
|
||||||
|
description: item.Event_text,
|
||||||
|
category: parseCategory(item),
|
||||||
|
image: parseImage(item),
|
||||||
|
start: parseStart(item),
|
||||||
|
stop: parseStop(item)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return programs
|
||||||
|
},
|
||||||
|
async channels() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
lang: 'ja',
|
||||||
|
site_id: '1',
|
||||||
|
name: 'Tokyo MX1',
|
||||||
|
xmltv_id: 'TokyoMX1.jp'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
lang: 'ja',
|
||||||
|
site_id: '2',
|
||||||
|
name: 'Tokyo MX2',
|
||||||
|
xmltv_id: 'TokyoMX2.jp'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseImage(item) {
|
||||||
|
// Should return a string if we can output an image URL
|
||||||
|
// Might be done with `https://s.mxtv.jp/bangumi/link/weblinkU.csv?1722421896752` ?
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCategory(item) {
|
||||||
|
// Should return a string if we can determine the category
|
||||||
|
// Might be done with `https://s.mxtv.jp/index_set/csv/ranking_bangumi_allU.csv` ?
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseStart(item) {
|
||||||
|
return dayjs.tz(item.Start_time.toString(), 'YYYY年MM月DD日HH時mm分ss秒', 'Asia/Tokyo')
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseStop(item) {
|
||||||
|
// Add the duration to the start time
|
||||||
|
const durationDate = dayjs(item.Duration, 'HH:mm:ss');
|
||||||
|
return parseStart(item).add(dayjs.duration({
|
||||||
|
hours: durationDate.hour(),
|
||||||
|
minutes: durationDate.minute(),
|
||||||
|
seconds: durationDate.second()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseItems(content) {
|
||||||
|
return JSON.parse(content) || []
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
const { parser, url } = require('./s.mxtv.jp.config.js')
|
||||||
|
const dayjs = require('dayjs')
|
||||||
|
const utc = require('dayjs/plugin/utc')
|
||||||
|
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||||
|
dayjs.extend(customParseFormat)
|
||||||
|
dayjs.extend(utc)
|
||||||
|
|
||||||
|
const date = dayjs.utc('2024-08-01', 'YYYY-MM-DD').startOf('d')
|
||||||
|
const channel = {
|
||||||
|
site_id: '2',
|
||||||
|
name: 'Tokyo MX2',
|
||||||
|
xmltv_id: 'TokyoMX2.jp'
|
||||||
|
}
|
||||||
|
const content = `[{ "Event_id": "0x6a57", "Start_time": "2024年07月27日05時00分00秒", "Duration": "01:00:00", "Event_name": "ヒーリングタイム&ヘッドラインニュース", "Event_text": "ねこの足跡", "Component": "480i 16:9 パンベクトルなし", "Sound": "ステレオ", "Event_detail": ""}]`
|
||||||
|
|
||||||
|
it('can generate valid url', () => {
|
||||||
|
const result = url({ date, channel })
|
||||||
|
expect(result).toBe('https://s.mxtv.jp/bangumi_file/json01/SV2EPG20240801.json')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can parse response', () => {
|
||||||
|
const result = parser({ date, channel, content }).map(p => {
|
||||||
|
p.start = p.start.toJSON()
|
||||||
|
p.stop = p.stop.toJSON()
|
||||||
|
return p
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result).toMatchObject([
|
||||||
|
{
|
||||||
|
start: '2024-07-26T20:00:00.000Z', // UTC time
|
||||||
|
stop: '2024-07-26T21:00:00.000Z', // UTC
|
||||||
|
title: 'ヒーリングタイム&ヘッドラインニュース',
|
||||||
|
description: 'ねこの足跡',
|
||||||
|
image: null,
|
||||||
|
category: null
|
||||||
|
}
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can handle empty guide', () => {
|
||||||
|
const result = parser({
|
||||||
|
date,
|
||||||
|
channel,
|
||||||
|
content: '[]'
|
||||||
|
})
|
||||||
|
expect(result).toMatchObject([])
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user