Repository: streamlink/streamlink

Issue:
plugins.nicolive: Niconico login broken (404)
### Checklist

- [X] This is a plugin issue and not a different kind of issue
- [X] [I have read the contribution guidelines](https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink)
- [X] [I have checked the list of open and recently closed plugin issues](https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22plugin+issue%22)
- [ ] [I have checked the commit log of the master branch](https://github.com/streamlink/streamlink/commits/master)

### Streamlink version

Latest build from the master branch

### Description

The niconico function using login is broken. This error is shown:
404 Client Error: Not Found for url: https://account.nicovideo.jp/

The plugin seems to be pointing to https://account.nicovideo.jp/login/redirector which does not work anymore.
Pointing to https://account.nicovideo.jp/login instead should solve the issue.

### Debug log

```text
Used syntax:
streamlink -o "output.ts" https://live.nicovideo.jp/watch/[video-ID] best --niconico-email [mailaddress] --niconico-password [PW]
```



Discussion:
**Post the entire output when setting the `--loglevel=debug` parameter.**

The nicolive email logins were fixed recently in #4380. This looks like you're not using the latest version.
> **Post the entire output when setting the `--loglevel=debug` parameter.**
> 
> The nicolive email logins were fixed recently in #4380. This looks like you're not using the latest version.

Full log:

```
[cli][debug] OS:         Windows 10
[cli][debug] Python:     3.8.10
[cli][debug] Streamlink: 4.0.1
[cli][debug] Requests(2.27.1), Socks(1.7.1), Websocket(1.3.2)
[cli][debug] Arguments:
[cli][debug]  url=https://live.nicovideo.jp/watch/lv336832924
[cli][debug]  stream=['best']
[cli][debug]  --loglevel=debug
[cli][debug]  --output=output.ts
[cli][debug]  --ffmpeg-ffmpeg=C:\Users\xxx\AppData\Local\Streamlink\ffmpeg\ffmpeg.exe
[cli][debug]  --niconico-email=********
[cli][debug]  --niconico-password=********
[cli][info] Found matching plugin nicolive for URL https://live.nicovideo.jp/watch/lv336832924
[plugins.nicolive][info] Logging in via provided email and password
[plugins.nicolive][debug] unknown input: None
[plugins.nicolive][debug] unknown input: None
error: Unable to open URL: https://account.nicovideo.jp (404 Client Error: Not Found for url: https://account.nicovideo.jp/)
```

---

The video itself will only be available for a couple more hours, you might have to test with a different one on live.nicovideo.jp

I tested with both, latest stable, as well as latest nightly.
I can't reproduce this.

Invalid logins get caught, valid logins via email that require a confirmation code are working fine, and so are cached session cookies after a successful login.

Apart from that, the stream URL doesn't seem to require a login.

> [plugins.nicolive][info] Logging in via provided email and password
> [plugins.nicolive][debug] unknown input: None
> [plugins.nicolive][debug] unknown input: None
> error: Unable to open URL: https://account.nicovideo.jp/ (404 Client Error: Not Found for url: https://account.nicovideo.jp/)

This looks like you're seeing a different page after trying to logging in which the plugin can't handle. This might be caused by regional differences.
> I can't reproduce this.
> 
> Invalid logins get caught, valid logins via email that require a confirmation code are working fine, and so are cached session cookies after a successful login.
> 
> Apart from that, the stream URL doesn't seem to require a login.
> 
> > [plugins.nicolive][info] Logging in via provided email and password
> > [plugins.nicolive][debug] unknown input: None
> > [plugins.nicolive][debug] unknown input: None
> > error: Unable to open URL: https://account.nicovideo.jp/ (404 Client Error: Not Found for url: https://account.nicovideo.jp/)
> 
> This looks like you're seeing a different page after trying to logging in which the plugin can't handle. This might be caused by regional differences.

The video has a "members-only" part in the second half that is not shown if you are a guest/non-member user. This is a "timeshift" archive video of a live-stream.
Regional should not be an issue, since I am accessing from Japan.

Please see line 161 in this file:
https://github.com/streamlink/streamlink/blob/master/src/streamlink/plugins/nicolive.py
The link "https://account.nicovideo.jp/login/redirector" when accessed from browser is giving the error straight away. Like mentioned in OP, changing this to https://account.nicovideo.jp/login might solve the issue. (I cannot do commits, sorry)

https://account.nicovideo.jp/login/redirector is the target of the login form of https://account.nicovideo.jp/login, and it requires a POST request with the `mail_tel` and `password` parameters. The plugin is doing this correctly, as you can see here:
https://github.com/streamlink/streamlink/blob/473fda0a452745ea207dbcfec72bc83f7356bf99/src/streamlink/plugins/nicolive.py#L259-L263

As said, the issue is caused by the response of this request, which looks to be different in certain cases.
works with an IP from Europe,
does not work with an IP from Japan.

Plugin needs some changes.

Resolving patch:
diff --git a/src/streamlink/plugins/nicolive.py b/src/streamlink/plugins/nicolive.py
--- a/src/streamlink/plugins/nicolive.py
+++ b/src/streamlink/plugins/nicolive.py
@@ -260,10 +260,16 @@ def niconico_web_login(self):
                 self.LOGIN_URL,
                 data={"mail_tel": email, "password": password},
                 params=self.LOGIN_URL_PARAMS,
-                schema=validate.Schema(validate.parse_html()))
+                schema=validate.Schema(validate.parse_html()),
+            )
+
+            if self.session.http.cookies.get("user_session"):
+                log.info("Logged in.")
+                self.save_cookies()
+                return
 
             input_with_value = {}
-            for elem in root.xpath(".//input"):
+            for elem in root.xpath(".//form[@action]//input"):
                 if elem.attrib.get("value"):
                     input_with_value[elem.attrib.get("name")] = elem.attrib.get("value")
                 else:
@@ -283,7 +289,8 @@ def niconico_web_login(self):
             root = self.session.http.post(
                 urljoin("https://account.nicovideo.jp", root.xpath("string(.//form[@action]/@action)")),
                 data=input_with_value,
-                schema=validate.Schema(validate.parse_html()))
+                schema=validate.Schema(validate.parse_html()),
+            )
             log.debug(f"Cookies: {self.session.http.cookies.get_dict()}")
             if self.session.http.cookies.get("user_session") is None:
                 error = root.xpath("string(//div[@class='formError']/div/text())")


Test patch: