Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: nhl.com site #2467

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions SITES.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
| [mytvsuper.com](sites/mytvsuper.com) | 🟢 | |
| [nhk.or.jp](sites/nhk.or.jp) | 🟢 | |
| [nhkworldpremium.com](sites/nhkworldpremium.com) | 🟢 | |
| [nhl.com](sites/nhl.com) | 🟢 | |
| [nostv.pt](sites/nostv.pt) | 🟢 | |
| [novacyprus.com](sites/novacyprus.com) | 🟢 | |
| [novasports.gr](sites/novasports.gr) | 🟢 | |
Expand Down
1 change: 1 addition & 0 deletions sites/nhl.com/__data__/content.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"date":"2024-11-22","startDate":"2024-11-08","endDate":"2024-12-05","broadcasts":[{"startTime":"2024-11-22T00:00:00","endTime":"2024-11-22T01:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124SOR","broadcastType":"HD","broadcastStatus":"LIVE","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T01:00:00","endTime":"2024-11-22T02:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T02:00:00","endTime":"2024-11-22T03:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T03:00:00","endTime":"2024-11-22T04:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T04:00:00","endTime":"2024-11-22T05:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T05:00:00","endTime":"2024-11-22T06:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T06:00:00","endTime":"2024-11-22T07:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T07:00:00","endTime":"2024-11-22T08:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T08:00:00","endTime":"2024-11-22T09:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T09:00:00","endTime":"2024-11-22T10:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T10:00:00","endTime":"2024-11-22T11:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T11:00:00","endTime":"2024-11-22T12:00:00","durationSeconds":3600,"title":"On The Fly","description":"On The Fly","houseNumber":"HOTF25R112124CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"onthefly.png"},{"startTime":"2024-11-22T12:00:00","endTime":"2024-11-22T14:00:00","durationSeconds":7200,"title":"NHL Game","description":"New York Rangers at Calgary Flames on 11/21/2024 From Scotiabank Saddledome","houseNumber":"H120NYRCGY11212024","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"nhl.png"},{"startTime":"2024-11-22T14:00:00","endTime":"2024-11-22T16:00:00","durationSeconds":7200,"title":"NHL Game","description":"Carolina Hurricanes at New Jersey Devils on 11/21/2024 From Prudential Center","houseNumber":"H120CARNJD11212024","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"nhl.png"},{"startTime":"2024-11-22T16:00:00","endTime":"2024-11-22T17:00:00","durationSeconds":3600,"title":"NHL Tonight: First Shift","description":"NHL Tonight: First Shift","houseNumber":"HNHLTFS25112224LV","broadcastType":"HD","broadcastStatus":"LIVE","broadcastImageUrl":""},{"startTime":"2024-11-22T17:00:00","endTime":"2024-11-22T19:00:00","durationSeconds":7200,"title":"NHL Now","description":"NHL Now","houseNumber":"HNOW25R112224LV","broadcastType":"HD","broadcastStatus":"LIVE","broadcastImageUrl":"nhlnow.png"},{"startTime":"2024-11-22T19:00:00","endTime":"2024-11-22T22:00:00","durationSeconds":10800,"title":"Regular Season Hockey on NHL Network","description":"Winnipeg Jets at Pittsburgh Penguins on 11/22/2024 From PPG Paints Arena","houseNumber":"H180WPGPIT11222024","broadcastType":"HD","broadcastStatus":"LIVE","broadcastImageUrl":"nhl.png"},{"startTime":"2024-11-22T22:00:00","endTime":"2024-11-22T22:30:00","durationSeconds":1800,"title":"NHL Tonight","description":"NHL Tonight","houseNumber":"HNHLT25RS112224LV","broadcastType":"HD","broadcastStatus":"LIVE","broadcastImageUrl":"nhltonight.png"},{"startTime":"2024-11-22T22:30:00","endTime":"2024-11-22T23:00:00","durationSeconds":1800,"title":"NHL Tonight","description":"NHL Tonight","houseNumber":"HNHLT25RS112224CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"nhltonight.png"},{"startTime":"2024-11-22T23:00:00","endTime":"2024-11-22T23:30:00","durationSeconds":1800,"title":"NHL Tonight","description":"NHL Tonight","houseNumber":"HNHLT25RS112224CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"nhltonight.png"},{"startTime":"2024-11-22T23:30:00","endTime":"2024-11-23T00:00:00","durationSeconds":1800,"title":"NHL Tonight","description":"NHL Tonight","houseNumber":"HNHLT25RS112224CC","broadcastType":"HD","broadcastStatus":"","broadcastImageUrl":"nhltonight.png"}]}
10 changes: 10 additions & 0 deletions sites/nhl.com/nhl.com.channels.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<!--
`site_id` is not relevant for this configuration as nhl.com only has a guide for one channel.
nonetheless I elected to use "network" here because:
1) a blank value causes the record to be skipped
2) "network" is a keyword in the API endpoint
-->
<channel site="nhl.com" lang="en" xmltv_id="NHLNetwork.us" site_id="network">NHL Network</channel>
</channels>
45 changes: 45 additions & 0 deletions sites/nhl.com/nhl.com.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const dayjs = require('dayjs')

module.exports = {
site: 'nhl.com',
// I'm not sure what `endDate` represents but they only return 1 day of
// results, with `endTime`s ocassionally in the following day.
days: 1,
url: ({ date }) => `https://api-web.nhle.com/v1/network/tv-schedule/${date.toJSON().split("T")[0]}`,
parser({ content }) {
const programs = []
const items = parseItems(content)
for (const item of items) {
programs.push({
title: item.title,
description: item.description === item.title ? undefined : item.description,
category: "Sports",
// image: parseImage(item),
start: parseStart(item),
stop: parseStop(item)
})
}

return programs
}
}

// Unfortunately I couldn't determine how these are
// supposed to be formatted. Pointers appreciated!
// function parseImage(item) {
// const uri = item.broadcastImageUrl

// return uri ? `https://???/${uri}` : null
// }

function parseStart(item) {
return dayjs(item.startTime)
}

function parseStop(item) {
return dayjs(item.endTime)
}

function parseItems(content) {
return JSON.parse(content).broadcasts
}
44 changes: 44 additions & 0 deletions sites/nhl.com/nhl.com.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const { parser, url } = require('./nhl.com.config.js')
const fs = require('fs')
const path = require('path')
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-11-21', 'YYYY-MM-DD').startOf('d')

it('can generate valid url', () => {
expect(url({ date })).toBe(
'https://api-web.nhle.com/v1/network/tv-schedule/2024-11-21'
)
})

it('can parse response', () => {
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'))
let results = parser({ content, date })
results = results.map(p => {
p.start = p.start.toJSON()
p.stop = p.stop.toJSON()
return p
})

expect(results[0]).toMatchObject({
start: '2024-11-21T12:00:00.000Z',
stop: '2024-11-21T13:00:00.000Z',
title: 'On The Fly',
category: 'Sports',
})
})

it('can handle empty guide', () => {
const results = parser({ content: JSON.stringify({
// extra props not necessary but they form a valid response
date: "2024-11-21",
startDate: "2024-11-07",
endDate: "2024-12-05",
broadcasts: [],
}) })
expect(results).toMatchObject([])
})
15 changes: 15 additions & 0 deletions sites/nhl.com/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# nhl.com

https://www.nhl.com/nhl-network/programming-schedule

### Download the guide

```sh
npm run grab -- --site=nhl.com
```

### Test

```sh
npm test -- nhl.com
```