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

plugins.niconicochannelplus: add support for "nicochannel.jp" #4923

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d641860
plugins.niconicochannelplus: add VoD support for "nicochannel.jp"
pzhlkj6612 Nov 6, 2022
d7e1629
plugins.niconicochannelplus: only latin1 characters in metadata
pzhlkj6612 Nov 6, 2022
4d132c8
plugins.niconicochannelplus: improve the code based on code review
pzhlkj6612 Nov 6, 2022
3d415c2
plugins.niconicochannelplus: only output title in debug level
pzhlkj6612 Nov 7, 2022
c9654cc
plugins.niconicochannelplus: remove unneeded metadata
pzhlkj6612 Nov 7, 2022
464eac5
plugins.niconicochannelplus: add live support for "nicochannel.jp"
pzhlkj6612 Nov 8, 2022
41125d0
plugins.niconicochannelplus: add type annotation
pzhlkj6612 Nov 8, 2022
16bc033
chore: merge "origin/master"
pzhlkj6612 Nov 8, 2022
31078e0
chore: merge "origin/master"
pzhlkj6612 Nov 8, 2022
711485b
plugins.niconicochannelplus: don't output the title
pzhlkj6612 Nov 8, 2022
55673f3
plugins.niconicochannelplus: use double quotes for strings
pzhlkj6612 Nov 8, 2022
e05e80c
plugins.niconicochannelplus: dots (.) are allowed in channel names
pzhlkj6612 Nov 30, 2022
51a9223
plugins.niconicochannelplus: add a test for channel name with dots
pzhlkj6612 Nov 30, 2022
f75580d
chore: merge "origin/master"
pzhlkj6612 Nov 30, 2022
263e29a
plugins.niconicochannelplus: DVR works if both "allow_dvr_flg" and "c…
pzhlkj6612 Dec 13, 2022
f85eedb
chore: merge "origin/master"
pzhlkj6612 Dec 13, 2022
9661f97
plugins.niconicochannelplus: fields in "video" are Null if it wasn't …
pzhlkj6612 Dec 20, 2022
c91c19e
plugins.niconicochannelplus: make URL matcher less strict
pzhlkj6612 Dec 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/streamlink/plugins/niconicochannelplus.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
$description NicoNico Channel Plus (nicochannel+) is a new feature of Niconico Channel.
$url nicochannel.jp
$type vod
$account Not required. Full-length videos are accessible.
$notes Downloading non-free content is not recommended.
bastimeyer marked this conversation as resolved.
Show resolved Hide resolved
"""

import json
import logging
import re

from streamlink.plugin import Plugin, pluginmatcher
from streamlink.plugin.api import HTTPSession
from streamlink.stream.hls import HLSStream

log = logging.getLogger(__name__)


@pluginmatcher(
re.compile(
r'^https?://nicochannel\.jp/(?P<channel>[a-z0-9_-]+)/video/(?P<id>sm[a-zA-Z0-9]+)$'
)
)
class NicoNicoChannelPlus(Plugin):
def get_video_page_info(self, http: HTTPSession, video_id: str) -> dict:
video_page_json = json.loads(
http.get(
url=f'https://nfc-api.nicochannel.jp/fc/video_pages/{video_id}',
).content
)['data']['video_page']

return video_page_json
bastimeyer marked this conversation as resolved.
Show resolved Hide resolved

def get_master_playlist_url(self, http: HTTPSession, video_id: str) -> str:
session_id = json.loads(
http.post(
url=f'https://nfc-api.nicochannel.jp/fc/video_pages/{video_id}/session_ids',
data=str({}).encode('ascii'),
headers={
'content-type': 'application/json',
}
).content
)['data']['session_id']

return f'https://hls-auth.cloud.stream.co.jp/auth/index.m3u8?session_id={session_id}'

def _get_streams(self):
self.id = self.match.group('id')
self.author = self.match.group('channel')

video_info = self.get_video_page_info(self.session.http, self.id)
playlist_url = self.get_master_playlist_url(self.session.http, self.id)

self.title = video_info['title']

log.info(f'ID: {self.id}')
log.info(f'Channel: {self.author}')
log.info(f'Title: {self.title}')
bastimeyer marked this conversation as resolved.
Show resolved Hide resolved

for name, stream in HLSStream.parse_variant_playlist(
self.session, playlist_url
).items():
yield name, stream
bastimeyer marked this conversation as resolved.
Show resolved Hide resolved


__plugin__ = NicoNicoChannelPlus
76 changes: 76 additions & 0 deletions tests/plugins/test_niconicochannelplus.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from streamlink.plugins.niconicochannelplus import NicoNicoChannelPlus
from tests.plugins import PluginCanHandleUrl


class TestPluginCanHandleUrlNicoNicoChannelPlus(PluginCanHandleUrl):
__plugin__ = NicoNicoChannelPlus

should_match = [
# normal channel name.
'https://nicochannel.jp/olchannel/video/smq9UriUQ9PU65jTjVxh2PVo',

# numbers in channel name.
'https://nicochannel.jp/dateno8noba/video/smVGqtKpdmva4Mcrw7rbeQ8Y',

# hyphens in channel name.
'https://nicochannel.jp/mimimoto-ayaka/video/smRS96YpmDJr24YpWFZziG4L',

# underscores in channel name.
'https://nicochannel.jp/sakaguchi_kugimiya/video/smnSFttxbkjZDBwZMMj8CgsJ',
]

should_match_groups = [
(
'https://nicochannel.jp/olchannel/video/smq9UriUQ9PU65jTjVxh2PVo',
{
'id': 'smq9UriUQ9PU65jTjVxh2PVo',
'channel': 'olchannel',
}
),
(
'https://nicochannel.jp/dateno8noba/video/smVGqtKpdmva4Mcrw7rbeQ8Y',
{
'id': 'smVGqtKpdmva4Mcrw7rbeQ8Y',
'channel': 'dateno8noba',
}
),
(
'https://nicochannel.jp/mimimoto-ayaka/video/smRS96YpmDJr24YpWFZziG4L',
{
'id': 'smRS96YpmDJr24YpWFZziG4L',
'channel': 'mimimoto-ayaka',
}
),
(
'https://nicochannel.jp/sakaguchi_kugimiya/video/smnSFttxbkjZDBwZMMj8CgsJ',
{
'id': 'smnSFttxbkjZDBwZMMj8CgsJ',
'channel': 'sakaguchi_kugimiya',
}
),
]

should_not_match = [
# Niconico Channel Plus
# portal
'https://portal.nicochannel.jp/',
# channel home pages
'https://nicochannel.jp/example',
# channel live list
'https://nicochannel.jp/example/lives',
# channel video list
'https://nicochannel.jp/example/videos',
# invalid urls
'https://nicochannel.jp/'
'https://nicochannel.jp/example/live',
'https://nicochannel.jp/example/video',
# live urls (move it to "should_match*" if the plugin supports live-streaming)
'https://nicochannel.jp/example/live/sm3Xample',

# Niconico Channel
# portal
'https://ch.nicovideo.jp/',
# channel home pages
'https://ch.nicovideo.jp/ch0000000',
'https://ch.nicovideo.jp/example',
]