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

add epg.telemach.me #2630

Merged
merged 9 commits into from
Jan 20, 2025
Merged
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/epg.telemach.me/__data__/content.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions sites/epg.telemach.me/__data__/no_content.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"status":400,"error":"resource_not_found","errorMessage":"Resource not found","messageId":1674123545}
1 change: 1 addition & 0 deletions sites/epg.telemach.me/__data__/no_session.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"error":"unsupported_grant_type","error_description":"Unsupported grant type"}
1 change: 1 addition & 0 deletions sites/epg.telemach.me/__data__/session.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsidWMtaW5mby1zZXJ2aWNlIl0sInNjb3BlIjpbInJlYWQiXSwiZXhwIjoxNzM3Mzc3NDUxLCJhdXRob3JpdGllcyI6WyJST0xFX1BVQkxJQ19FUEciXSwianRpIjoiUVBubHdRSDczS1EwSnU0WDZwRTc2Zm5mUmRnIiwiY2xpZW50X2lkIjoiMjdlMTFmNWUtODhlMi00OGU0LWJkNDItOGUxNWFiYmM2NmY1In0.LqJAZUWEqIOcLrRSMpxZxnF-f1arKbHgfweLMXt-MBjCDbVJD39OQEsh_b68mtePAoa3n8LRbf3IFT40Ys5Vbe-k_Btm4a9gdEGr6cNi_4HGk4Bto6RUDvCp59VRfoRZhWe145Q2b5TS6szmC4Ws2YWIcZU5vrJcYs2GZiCk6U11MOcd1i52WmZj8cLPq0ZPDB_bzmTgYkvkVa7zOzUOPSl4M8T6fPUa__vVKUt0jOgtFoHeue2mQVgISC2puEGsBN0jJwvJ8PzM6IVxXrQno3MBv0VJy_qILiFPcxRePGRAmKLuEqagvikO7P_XQgFjZgg-j8u8wX2WwO0Yxft0Pg","token_type":"bearer","expires_in":86399,"scope":"read","jti":"QPnlwQH73KQ0Ju4X6pE76fnfRdg"}
219 changes: 219 additions & 0 deletions sites/epg.telemach.me/epg.telemach.me.channels.xml

Large diffs are not rendered by default.

101 changes: 101 additions & 0 deletions sites/epg.telemach.me/epg.telemach.me.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
const dayjs = require('dayjs')
const axios = require('axios')

const BASIC_TOKEN =
'MjdlMTFmNWUtODhlMi00OGU0LWJkNDItOGUxNWFiYmM2NmY1OjEyejJzMXJ3bXdhZmsxMGNkdzl0cjloOWFjYjZwdjJoZDhscXZ0aGc='

let session

module.exports = {
site: 'epg.telemach.me',
days: 3,
url({ channel, date }) {
return `https://api-web.ug-be.cdn.united.cloud/v1/public/events/epg?fromTime=${date.format(
'YYYY-MM-DDTHH:mm:ss-00:00'
)}&toTime=${date
.add(1, 'days')
.subtract(1, 's')
.format('YYYY-MM-DDTHH:mm:ss-00:00')}&communityId=5&languageId=10001&cid=${channel.site_id}`
},
request: {
async headers() {
if (!session) {
session = await loadSessionDetails()
if (!session || !session.access_token) return null
}

return {
Authorization: `Bearer ${session.access_token}`,
Referer: 'https://epg.telemach.me/'
}
}
},
parser({ content }) {
try {
const programs = []
const data = JSON.parse(content)
for (const channelId in data) {
if (Array.isArray(data[channelId])) {
data[channelId].forEach(item => {
programs.push({
title: item.title,
description: item.shortDescription,
image: parseImage(item),
season: item.seasonNumber,
episode: item.episodeNumber,
start: dayjs(item.startTime),
stop: dayjs(item.endTime)
})
})
}
}

return programs
} catch {
return []
}
},
async channels() {
const session = await loadSessionDetails()
if (!session || !session.access_token) return null

const data = await axios
.get(
'https://api-web.ug-be.cdn.united.cloud/v1/public/channels?channelType=TV&communityId=5&languageId=10001&imageSize=L',
{
headers: {
Authorization: `Bearer ${session.access_token}`
}
}
)
.then(r => r.data)
.catch(console.error)

return data.map(item => ({
lang: 'bs',
site_id: item.id,
name: item.name
}))
}
}

function parseImage(item) {
const baseURL = 'https://images-web.ug-be.cdn.united.cloud'

return Array.isArray(item?.images) && item.images[0] ? `${baseURL}${item.images[0].path}` : null
}

function loadSessionDetails() {
return axios
.post(
'https://api-web.ug-be.cdn.united.cloud/oauth/token?grant_type=client_credentials',
{},
{
headers: {
Authorization: `Basic ${BASIC_TOKEN}`
}
}
)
.then(r => r.data)
.catch(console.log)
}
96 changes: 96 additions & 0 deletions sites/epg.telemach.me/epg.telemach.me.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
const { parser, url, request } = require('./epg.telemach.me.config.js')
const fs = require('fs')
const axios = require('axios')
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)

jest.mock('axios')

axios.post.mockImplementation((url, data, opts) => {
if (
url === 'https://api-web.ug-be.cdn.united.cloud/oauth/token?grant_type=client_credentials' &&
JSON.stringify(opts.headers) ===
JSON.stringify({
Authorization:
'Basic MjdlMTFmNWUtODhlMi00OGU0LWJkNDItOGUxNWFiYmM2NmY1OjEyejJzMXJ3bXdhZmsxMGNkdzl0cjloOWFjYjZwdjJoZDhscXZ0aGc='
})
) {
return Promise.resolve({
data: JSON.parse(fs.readFileSync(path.resolve(__dirname, '__data__/session.json')))
})
} else {
return Promise.resolve({
data: JSON.parse(fs.readFileSync(path.resolve(__dirname, '__data__/no_session.json')))
})
}
})

const date = dayjs.utc('2025-01-20', 'YYYY-MM-DD').startOf('d')
const channel = {
site_id: '92',
xmltv_id: 'PinkKids.rs'
}

it('can generate valid url', async () => {
const result = url({ date, channel })

expect(result).toBe(
'https://api-web.ug-be.cdn.united.cloud/v1/public/events/epg?fromTime=2025-01-20T00:00:00-00:00&toTime=2025-01-20T23:59:59-00:00&communityId=5&languageId=10001&cid=92'
)
})

it('can generate valid request headers', async () => {
const result = await request.headers()

expect(result).toMatchObject({
Authorization:
'Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsidWMtaW5mby1zZXJ2aWNlIl0sInNjb3BlIjpbInJlYWQiXSwiZXhwIjoxNzM3Mzc3NDUxLCJhdXRob3JpdGllcyI6WyJST0xFX1BVQkxJQ19FUEciXSwianRpIjoiUVBubHdRSDczS1EwSnU0WDZwRTc2Zm5mUmRnIiwiY2xpZW50X2lkIjoiMjdlMTFmNWUtODhlMi00OGU0LWJkNDItOGUxNWFiYmM2NmY1In0.LqJAZUWEqIOcLrRSMpxZxnF-f1arKbHgfweLMXt-MBjCDbVJD39OQEsh_b68mtePAoa3n8LRbf3IFT40Ys5Vbe-k_Btm4a9gdEGr6cNi_4HGk4Bto6RUDvCp59VRfoRZhWe145Q2b5TS6szmC4Ws2YWIcZU5vrJcYs2GZiCk6U11MOcd1i52WmZj8cLPq0ZPDB_bzmTgYkvkVa7zOzUOPSl4M8T6fPUa__vVKUt0jOgtFoHeue2mQVgISC2puEGsBN0jJwvJ8PzM6IVxXrQno3MBv0VJy_qILiFPcxRePGRAmKLuEqagvikO7P_XQgFjZgg-j8u8wX2WwO0Yxft0Pg',
Referer: 'https://epg.telemach.me/'
})
})

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

expect(results.length).toBe(55)
expect(results[0]).toMatchObject({
start: '2025-01-19T23:20:00.000Z',
stop: '2025-01-20T00:10:00.000Z',
title: 'Pinkove Zvezdice',
description:
'Četvrta sezona najgledanijeg dečijeg muzičkog takmičenja, "Pinkove zvezdice" došlo do promena, pa će tako gledaoci imati priliku da najtalentovaniju decu gledaju na novoj, spektakularnoj sceni. Nova...',
image:
'https://images-web.ug-be.cdn.united.cloud/2023/06/22/11/19/19/stb_xl_115752ec1e05872b86ceda7726d347f533e17f43_340fc454bc73019d052cf936ebee5da3.jpg',
season: null,
episode: null
})
expect(results[54]).toMatchObject({
start: '2025-01-20T23:50:00.000Z',
stop: '2025-01-21T00:10:00.000Z',
title: 'Hajdi',
description:
'Život nekada nije jednostavan. To najbolje zna Hajdi. Nakon što je ostala siroče, njena tetka je odvodi visoko u Alpe kod njenog dede. Ona uz nove prijatelje i dedu uskoro zavoli svoj novi život. Ipak...',
image:
'https://images-web.ug-be.cdn.united.cloud/2024/05/10/14/49/09/stb_xl_7d1c73ee4df7de5c4157e9daccae098d50ee853d_99230e7f5bdc95451f37aa31f8425b4d.jpg',
season: null,
episode: null
})
})

it('can handle empty guide', () => {
const results = parser({
content: fs.readFileSync(path.resolve(__dirname, '__data__/no_content.json'), 'utf8')
})

expect(results).toMatchObject([])
})
21 changes: 21 additions & 0 deletions sites/epg.telemach.me/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# epg.telemach.me

https://epg.telemach.me/

### Download the guide

```sh
npm run grab --- --site=epg.telemach.me
```

### Update channel list

```sh
npm run channels:parse --- --config=./sites/epg.telemach.me/epg.telemach.me.config.js --output=./sites/epg.telemach.me/epg.telemach.me.channels.xml
```

### Test

```sh
npm test --- epg.telemach.me
```
Loading