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

Some episodes of a tv show are unavailable for download #26

Open
laovvai opened this issue Jan 19, 2025 · 7 comments
Open

Some episodes of a tv show are unavailable for download #26

laovvai opened this issue Jan 19, 2025 · 7 comments

Comments

@laovvai
Copy link

laovvai commented Jan 19, 2025

Hello, thank you so much for creating this script, it is very useful for downloading subs from kisskh!

However, with some dramas I run into an issue where I can only download the first couple of episodes and after that, the script stops working properly.
For example, I managed to download only first 8 episodes of this cdrama : https://kisskh.co/Drama/Under-the-Moonlight?id=10123

But when I try to run the script with the link for the 9th episode, I get this error:

2025-01-19 19:19:16,275 - INFO - Getting details for Episode 9...
urllib3.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:1122)

The above exception was the direct cause of the following exception:

urllib3.exceptions.ProxyError: ('Unable to connect to proxy', SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:1122)')))

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\requests\adapters.py", line 486, in send
    resp = conn.urlopen(
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\urllib3\connectionpool.py", line 845, in urlopen
    retries = retries.increment(
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\urllib3\util\retry.py", line 515, in increment
    raise MaxRetryError(_pool, url, reason) from reason  # type: ignore[arg-type]
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='kisskh.co', port=443): Max retries exceeded with url: /api/DramaList/Episode/173169.png?err=false&ts=&time= (Caused by ProxyError('Unable to connect to proxy', SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:1122)'))))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\Lenovo\AppData\Local\Programs\Python\Python39\Scripts\kisskh.exe\__main__.py", line 7, in <module>
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\click\core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\click\core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\click\core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\click\core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\click\core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\kisskh_downloader\cli.py", line 123, in dl
    video_stream_url = kisskh_api.get_stream_url(episode_id)  # type: ignore
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\kisskh_downloader\kisskh_api.py", line 120, in get_stream_url
    response = self._request(stream_api_url)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\kisskh_downloader\kisskh_api.py", line 66, in _request
    response = session.get(url)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\requests\sessions.py", line 602, in get
    return self.request("GET", url, **kwargs)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\requests\sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\requests\sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\requests\adapters.py", line 513, in send
    raise ProxyError(e, request=request)
requests.exceptions.ProxyError: HTTPSConnectionPool(host='kisskh.co', port=443): Max retries exceeded with url: /api/DramaList/Episode/173169.png?err=false&ts=&time= (Caused by ProxyError('Unable to connect to proxy', SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:1122)'))))

Or sometimes I get errors like these:

kisskh dl "https://kisskh.co/Drama/Under-the-Moonlight/Episode-10?id=10123&ep=173170&page=0&pageSize=100"  -o 
2025-01-19 20:55:42,563 - INFO - Getting details for Episode 10...
Traceback (most recent call last):
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\Lenovo\AppData\Local\Programs\Python\Python39\Scripts\kisskh.exe\__main__.py", line 7, in <module>
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\click\core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\click\core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\click\core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\click\core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\click\core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\kisskh_downloader\cli.py", line 123, in dl
    video_stream_url = kisskh_api.get_stream_url(episode_id)  # type: ignore
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\kisskh_downloader\kisskh_api.py", line 120, in get_stream_url
    response = self._request(stream_api_url)
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\kisskh_downloader\kisskh_api.py", line 67, in _request
    response.raise_for_status()
  File "c:\users\lenovo\appdata\local\programs\python\python39\lib\site-packages\requests\models.py", line 1021, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://kisskh.co/api/DramaList/Episode/173170.png?err=false&ts=&time=

At first, I thought kisshkh might have implemented webscraping prevention and blocked my IP but the script still works with older episodes and other tv shows.

Could you please look into it? I don't understand what this error really means, is there any workaround for this problem?

Thank you in advance!

@worlon-code
Copy link

worlon-code commented Jan 27, 2025

Hello, kisskh has added a key for every video url api and sub url api
Eg: https://kisskh.co/api/DramaList/Episode/171699.png?err=false&ts=&time= previous api for getting video url

New video url looks like this
https://kisskh.co/api/DramaList/Episode/171699.png?err=false&ts=null&time=null&kkey=56697480CCBF13FF11E371C19696FBA7601E1C569630FF4001DBEBAB511F65357C5D712E4AD39F6E859770F5A0763B06E95ECB5142C0FE2DF561F722DB89E5F38D05E72CAA2FB6700380C17689688661D2D0631EDF1D579DF3127B9D313427CBD092C9B4D546EB6F69E2CA9760E02535750C1496D08C7C8937ACC42EE4B5334A

They have added a new url parameter kkey , and this kkey is unique for each episode.they are doing this for both video and subtitle

If we can get the kkey for each episode and append to existing api call for subtitle and video ,then every thing works fine. But I am not sure how to get the kkey for each episode.i hope the admin/other pick this issue.
Thank you in advance

@RaphMendoza
Copy link

kkey generation eventually leads to common.js, but it is heavily obfuscated.

The main function that we need is:

return function(_0x3be93d, _0x3e48ea, _0xbf2c16, _0x576527, _0x454b79, _0x361753, _0x3cdffa, _0x2fa7de, _0xdaf7bd, _0x59e242, _0x5674ce) {
        const _0x5acc2f = _0x3a8d;
        if (typeof _0x361753 === _0x5acc2f(0x122))
            _0x361753 = window[_0x5acc2f(0x11f)]['URL'];
        if (typeof _0x3cdffa === _0x5acc2f(0x122))
            _0x3cdffa = window[_0x5acc2f(0x119)][_0x5acc2f(0x11c)];
        if (typeof _0x2fa7de === _0x5acc2f(0x122))
            _0x2fa7de = window[_0x5acc2f(0x11f)][_0x5acc2f(0x115)];
        if (typeof _0xdaf7bd === _0x5acc2f(0x122))
            _0xdaf7bd = window[_0x5acc2f(0x119)][_0x5acc2f(0x118)];
        if (typeof _0x59e242 === _0x5acc2f(0x122))
            _0x59e242 = window[_0x5acc2f(0x119)]['appName'];
        if (typeof _0x5674ce === _0x5acc2f(0x122))
            _0x5674ce = window[_0x5acc2f(0x119)][_0x5acc2f(0x117)];
        const _0x5989e7 = ['', _0x3be93d, _0x3e48ea, _0x5acc2f(0x111), _0xbf2c16, _0x576527, _0x454b79, _0x12af79(_0x361753), _0x12af79(_0x3cdffa[_0x5acc2f(0x11e)]()), _0x12af79(_0x2fa7de), _0xdaf7bd, _0x59e242, _0x5674ce, '00', ''];
        _0x5989e7[_0x5acc2f(0x110)](0x1, 0x0, _0x70dbf4(_0x5989e7[_0x5acc2f(0x124)]('|')));
        const _0x278f64 = _0x29e11d(_0x5989e7[_0x5acc2f(0x124)]('|'))
          , [_0x3db385,_0x2f9d88] = _0x1b25b9(_0x278f64);
        return _0xaf4f42(_0x3db385),
        _0x1c779c(_0x3db385, _0x2f9d88)[_0x5acc2f(0x10b)]();
    }
    ;

@rensac
Copy link

rensac commented Jan 31, 2025

kkey generation eventually leads to common.js, but it is heavily obfuscated.

The main function that we need is:

return function(_0x3be93d, _0x3e48ea, _0xbf2c16, _0x576527, _0x454b79, _0x361753, _0x3cdffa, _0x2fa7de, _0xdaf7bd, _0x59e242, _0x5674ce) {
        const _0x5acc2f = _0x3a8d;
        if (typeof _0x361753 === _0x5acc2f(0x122))
            _0x361753 = window[_0x5acc2f(0x11f)]['URL'];
        if (typeof _0x3cdffa === _0x5acc2f(0x122))
            _0x3cdffa = window[_0x5acc2f(0x119)][_0x5acc2f(0x11c)];
        if (typeof _0x2fa7de === _0x5acc2f(0x122))
            _0x2fa7de = window[_0x5acc2f(0x11f)][_0x5acc2f(0x115)];
        if (typeof _0xdaf7bd === _0x5acc2f(0x122))
            _0xdaf7bd = window[_0x5acc2f(0x119)][_0x5acc2f(0x118)];
        if (typeof _0x59e242 === _0x5acc2f(0x122))
            _0x59e242 = window[_0x5acc2f(0x119)]['appName'];
        if (typeof _0x5674ce === _0x5acc2f(0x122))
            _0x5674ce = window[_0x5acc2f(0x119)][_0x5acc2f(0x117)];
        const _0x5989e7 = ['', _0x3be93d, _0x3e48ea, _0x5acc2f(0x111), _0xbf2c16, _0x576527, _0x454b79, _0x12af79(_0x361753), _0x12af79(_0x3cdffa[_0x5acc2f(0x11e)]()), _0x12af79(_0x2fa7de), _0xdaf7bd, _0x59e242, _0x5674ce, '00', ''];
        _0x5989e7[_0x5acc2f(0x110)](0x1, 0x0, _0x70dbf4(_0x5989e7[_0x5acc2f(0x124)]('|')));
        const _0x278f64 = _0x29e11d(_0x5989e7[_0x5acc2f(0x124)]('|'))
          , [_0x3db385,_0x2f9d88] = _0x1b25b9(_0x278f64);
        return _0xaf4f42(_0x3db385),
        _0x1c779c(_0x3db385, _0x2f9d88)[_0x5acc2f(0x10b)]();
    }
    ;

How to use the kkey

@RaphMendoza
Copy link

kkey generation eventually leads to common.js, but it is heavily obfuscated.
The main function that we need is:

return function(_0x3be93d, _0x3e48ea, _0xbf2c16, _0x576527, _0x454b79, _0x361753, _0x3cdffa, _0x2fa7de, _0xdaf7bd, _0x59e242, _0x5674ce) {
        const _0x5acc2f = _0x3a8d;
        if (typeof _0x361753 === _0x5acc2f(0x122))
            _0x361753 = window[_0x5acc2f(0x11f)]['URL'];
        if (typeof _0x3cdffa === _0x5acc2f(0x122))
            _0x3cdffa = window[_0x5acc2f(0x119)][_0x5acc2f(0x11c)];
        if (typeof _0x2fa7de === _0x5acc2f(0x122))
            _0x2fa7de = window[_0x5acc2f(0x11f)][_0x5acc2f(0x115)];
        if (typeof _0xdaf7bd === _0x5acc2f(0x122))
            _0xdaf7bd = window[_0x5acc2f(0x119)][_0x5acc2f(0x118)];
        if (typeof _0x59e242 === _0x5acc2f(0x122))
            _0x59e242 = window[_0x5acc2f(0x119)]['appName'];
        if (typeof _0x5674ce === _0x5acc2f(0x122))
            _0x5674ce = window[_0x5acc2f(0x119)][_0x5acc2f(0x117)];
        const _0x5989e7 = ['', _0x3be93d, _0x3e48ea, _0x5acc2f(0x111), _0xbf2c16, _0x576527, _0x454b79, _0x12af79(_0x361753), _0x12af79(_0x3cdffa[_0x5acc2f(0x11e)]()), _0x12af79(_0x2fa7de), _0xdaf7bd, _0x59e242, _0x5674ce, '00', ''];
        _0x5989e7[_0x5acc2f(0x110)](0x1, 0x0, _0x70dbf4(_0x5989e7[_0x5acc2f(0x124)]('|')));
        const _0x278f64 = _0x29e11d(_0x5989e7[_0x5acc2f(0x124)]('|'))
          , [_0x3db385,_0x2f9d88] = _0x1b25b9(_0x278f64);
        return _0xaf4f42(_0x3db385),
        _0x1c779c(_0x3db385, _0x2f9d88)[_0x5acc2f(0x10b)]();
    }
    ;

How to use the kkey

Kkey is appended to the url, as @worlon-code described. This url is used to get a json object containing a download link for the video or subtitle.

@laovvai
Copy link
Author

laovvai commented Feb 3, 2025

So for now, there isn't any way to generate this kkey for new episodes? I don't understand where I can find this new url with kkey and how to get use it to obtain json object after that :(

The admin hasn't been updating this project for almost two years.. it seems unlikely any changes will be done to the script to solve this problem unless someone else picks it up

@juanchoarg87
Copy link

Hello, i use IDM. When i go to de page of the episode, it captures the video with the monitor and i can download it. In the idm configuration for the monitor you can also add the extension "txt1" and it will capture the subtitle file with the extension txt1. You have to change the extension to txt or srt later.
The only problem is that the subtitles are encrypted and the key and iv change. You need to figure it out the new encryptions.
Salu2

@Prudhvi-pln
Copy link

I figured this out. Since the commons.js is heavily obfuscated, you can execute the js code and get the kkey.
On that note, you can check out my repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants