Repository: yt-dlp/yt-dlp

Issue:
Falling back to generic extractor for twitcasting archives page and failing
### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

- [X] I understand that I will be **blocked** if I *intentionally* remove or skip any mandatory\* field

### Checklist

- [X] I'm reporting that yt-dlp is broken on a **supported** site
- [X] I've verified that I'm running yt-dlp version **2023.07.06** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#video-url-contains-an-ampersand--and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [X] I've searched [known issues](https://github.com/yt-dlp/yt-dlp/issues/3766) and the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
- [ ] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required

### Region

Australia

### Provide a description that is worded well enough to be understood

yt-dlp is falling back onto the generic extractor for the twitcasting channel archive page and is unable to extract the URLs for the archived videos to download. However, yt-dlp is able to download the archived videos when given its URL individually.

The command used is 
yt-dlp -vU "https://twitcasting.tv/natsuiromatsuri/archive/"

### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [ ] If using API, add `'verbose': True` to `YoutubeDL` params instead
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
[debug] Command-line config: ['-vU', 'https://twitcasting.tv/natsuiromatsuri/archive/']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.07.06 [b532a3481] (zip)
[debug] Python 3.11.2 (CPython x86_64 64bit) - Linux-6.2.0-25-generic-x86_64-with-glibc2.37 (OpenSSL 3.0.8 7 Feb 2023, g
libc 2.37)
[debug] exe versions: ffmpeg 5.1.2 (setts), ffprobe 5.1.2, phantomjs broken
[debug] Optional libraries: certifi-2022.09.24, mutagen-1.46.0, secretstorage-3.3.3, sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Loaded 1855 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Available version: stable@2023.07.06, Current version: stable@2023.07.06
Current Build Hash: cedf44a9cf3c241520a692c1006d276e6f434d4d945727c47cb1a70d32953f4a
yt-dlp is up to date (stable@2023.07.06)
[generic] Extracting URL: https://twitcasting.tv/natsuiromatsuri/archive/
[generic] archive: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] archive: Extracting information
[debug] Looking for embeds
ERROR: Unsupported URL: https://twitcasting.tv/natsuiromatsuri/archive/
Traceback (most recent call last):
  File "/usr/local/bin/yt-dlp/yt_dlp/YoutubeDL.py", line 1560, in wrapper
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/bin/yt-dlp/yt_dlp/YoutubeDL.py", line 1688, in __extract_info
    ie_result = ie.extract(url)
                ^^^^^^^^^^^^^^^
  File "/usr/local/bin/yt-dlp/yt_dlp/extractor/common.py", line 710, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/bin/yt-dlp/yt_dlp/extractor/generic.py", line 2568, in _real_extract
    raise UnsupportedError(url)
yt_dlp.utils.UnsupportedError: Unsupported URL: https://twitcasting.tv/natsuiromatsuri/archive/
```



Discussion:
Seems `TwitCastingUserIE` works just fine for this. I assume all we need is to let it match "archive" urls as well.
https://github.com/yt-dlp/yt-dlp/blob/613dbce177d34ffc31053e8e01acf4bb107bcd1e/yt_dlp/extractor/twitcasting.py#L267-L268



```diff
 class TwitCastingUserIE(InfoExtractor):
-    _VALID_URL = r'https?://(?:[^/]+\.)?twitcasting\.tv/(?P<id>[^/]+)/show/?(?:[#?]|$)'
+    _VALID_URL = r'https?://(?:[^/]+\.)?twitcasting\.tv/(?P<id>[^/]+)/(:?show|archive)/?(?:[#?]|$)'
```
I can confirm the above change works using the 2023.07.06 release, compiled via the standalone pyinstaller on Debian sid using Python 3.11.5.
```
./yt-dlp_linux -vU "https://twitcasting.tv/natsuiromatsuri/archive"
[debug] Command-line config: ['-vU', 'https://twitcasting.tv/natsuiromatsuri/archive']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.07.06 [b532a3481] (linux_exe)
[debug] Python 3.11.5 (CPython x86_64 64bit) - Linux-6.4.0-4-amd64-x86_64-with-glibc2.37 (OpenSSL 3.0.10 1 Aug 2023, glibc 2.37)
[debug] exe versions: ffmpeg 6.0-6 (setts), ffprobe 6.0-6
[debug] Optional libraries: Cryptodome-3.18.0, brotli-1.1.0, certifi-2023.07.22, mutagen-1.47.0, sqlite3-2.6.0, websockets-11.0.3
[debug] Proxy map: {}
[debug] Loaded 1855 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Available version: stable@2023.07.06, Current version: stable@2023.07.06
Current Build Hash: 6e75372b3d6f59ba8398d9d4ed0de881aabe2b95fcd8c2b2a06f03fe5ed4bd07
yt-dlp is up to date (stable@2023.07.06)
[TwitCastingUser] Extracting URL: https://twitcasting.tv/natsuiromatsuri/archive
[download] Downloading playlist: natsuiromatsuri - Live History
[TwitCastingUser] natsuiromatsuri: Downloading page 1
[TwitCastingUser] natsuiromatsuri: Downloading page 2
[TwitCastingUser] natsuiromatsuri: Downloading page 3
[TwitCastingUser] natsuiromatsuri: Downloading page 4
[TwitCastingUser] natsuiromatsuri: Downloading page 5
[TwitCastingUser] natsuiromatsuri: Downloading page 6
[TwitCastingUser] natsuiromatsuri: Downloading page 7
[TwitCastingUser] natsuiromatsuri: Downloading page 8
[TwitCastingUser] natsuiromatsuri: Downloading page 9
[TwitCastingUser] natsuiromatsuri: Downloading page 10
[TwitCastingUser] natsuiromatsuri: Downloading page 11
[TwitCastingUser] natsuiromatsuri: Downloading page 12
[TwitCastingUser] natsuiromatsuri: Downloading page 13
[TwitCastingUser] natsuiromatsuri: Downloading page 14
[TwitCastingUser] natsuiromatsuri: Downloading page 15
[TwitCastingUser] Playlist natsuiromatsuri - Live History: Downloading 235 items of 235
[download] Downloading item 1 of 235
[TwitCasting] Extracting URL: https://twitcasting.tv/natsuiromatsuri/movie/772472807
[TwitCasting] 772472807: Downloading webpage
[TwitCasting] 772472807: Downloading live info
[TwitCasting] 772472807: Downloading m3u8 information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, size, br, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 772472807: Downloading 1 format(s): 269
[debug] Invoking hlsnative downloader on "https://dl193248.twitcasting.tv/tc.vod.v2/v1/streams/772472807.0.2.1.1689927066/hls/v0/media.m3u8"
[hlsnative] Downloading m3u8 manifest
[hlsnative] Total fragments: 443
[download] Destination: 君と暇電🫶 ⧸ 夏まつch [772472807].mp4
[download] 100% of   91.95MiB in 00:07:53 at 198.92KiB/s
[debug] ffprobe command line: ffprobe -hide_banner -show_format -show_streams -print_format json 'file:君と暇電🫶 ⧸ 夏まつch [772472807].mp4'
[download] Downloading item 2 of 235
[TwitCasting] Extracting URL: https://twitcasting.tv/natsuiromatsuri/movie/772375097
[TwitCasting] 772375097: Downloading webpage
[TwitCasting] 772375097: Downloading live info
[TwitCasting] 772375097: Downloading m3u8 information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, size, br, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 772375097: Downloading 1 format(s): 270
[debug] Invoking hlsnative downloader on "https://dl193235.twitcasting.tv/tc.vod.v2/v1/streams/772375097.0.2.1.1689811970/hls/v0/media.m3u8"
[hlsnative] Downloading m3u8 manifest
[hlsnative] Total fragments: 728
[download] Destination: おはよ ⧸ 夏まつch [772375097].mp4
[download]   0.3% of ~  72.76MiB at  215.50KiB/s ETA 05:44 (frag 2/728)^C
ERROR: Interrupted by user
```

Resolving patch:
diff --git a/yt_dlp/extractor/twitcasting.py b/yt_dlp/extractor/twitcasting.py
--- a/yt_dlp/extractor/twitcasting.py
+++ b/yt_dlp/extractor/twitcasting.py
@@ -22,7 +22,7 @@
 
 
 class TwitCastingIE(InfoExtractor):
-    _VALID_URL = r'https?://(?:[^/]+\.)?twitcasting\.tv/(?P<uploader_id>[^/]+)/(?:movie|twplayer)/(?P<id>\d+)'
+    _VALID_URL = r'https?://(?:[^/?#]+\.)?twitcasting\.tv/(?P<uploader_id>[^/?#]+)/(?:movie|twplayer)/(?P<id>\d+)'
     _M3U8_HEADERS = {
         'Origin': 'https://twitcasting.tv',
         'Referer': 'https://twitcasting.tv/',
@@ -231,7 +231,7 @@ def find_dmu(x):
 
 
 class TwitCastingLiveIE(InfoExtractor):
-    _VALID_URL = r'https?://(?:[^/]+\.)?twitcasting\.tv/(?P<id>[^/]+)/?(?:[#?]|$)'
+    _VALID_URL = r'https?://(?:[^/?#]+\.)?twitcasting\.tv/(?P<id>[^/?#]+)/?(?:[#?]|$)'
     _TESTS = [{
         'url': 'https://twitcasting.tv/ivetesangalo',
         'only_matching': True,
@@ -265,8 +265,15 @@ def _real_extract(self, url):
 
 
 class TwitCastingUserIE(InfoExtractor):
-    _VALID_URL = r'https?://(?:[^/]+\.)?twitcasting\.tv/(?P<id>[^/]+)/show/?(?:[#?]|$)'
+    _VALID_URL = r'https?://(?:[^/?#]+\.)?twitcasting\.tv/(?P<id>[^/?#]+)/(:?show|archive)/?(?:[#?]|$)'
     _TESTS = [{
+        'url': 'https://twitcasting.tv/natsuiromatsuri/archive/',
+        'info_dict': {
+            'id': 'natsuiromatsuri',
+            'title': 'natsuiromatsuri - Live History',
+        },
+        'playlist_mincount': 235,
+    }, {
         'url': 'https://twitcasting.tv/noriyukicas/show',
         'only_matching': True,
     }]


Test patch: