@@ -96,13 +96,21 @@ def __init__(self, webtoon_id: str | tuple[str, str], /, *, bearer: str | None =
9696
9797 self ._shuffled_directory = None
9898 self ._unshuffled_directory = None
99+
100+ self .is_library = language_code .endswith ("-library" )
101+ language_code = language_code .removesuffix ("-library" )
102+
99103 self .language_code = language_code
100104 self .base_url = self .BASE_URLS [language_code ]
101- referrer = f"{ self .base_url } /{ self .language_code } /comic/{ webtoon_id } "
105+ if self .is_library :
106+ referrer = f"{ self .base_url } /{ self .language_code } /library/comic/{ self .LOCALES [self .language_code ]} /{ webtoon_id } "
107+ else :
108+ referrer = f"{ self .base_url } /{ self .language_code } /comic/{ webtoon_id } "
102109
103110 super ().__init__ (webtoon_id )
104111 extra_headers = {
105112 "Referer" : referrer ,
113+ # NOTE: 나중에 작동 안 할지도 모르니 잘 확인하기
106114 "X-Lz-Adult" : "0" ,
107115 "X-Lz-Allowadult" : "false" ,
108116 "X-Lz-Country" : "kr" ,
@@ -168,8 +176,12 @@ async def fetch_webtoon_information(self, *, reload: bool = False) -> None:
168176 @async_reload_manager
169177 async def fetch_episode_information (self , * , reload : bool = False ) -> None :
170178 with WebtoonIdError .redirect_error (self ):
179+ if self .is_library :
180+ url = f"{ self .base_url } /{ self .language_code } /library/comic/{ self .LOCALES [self .language_code ]} /{ self .webtoon_id } "
181+ else :
182+ url = f"{ self .base_url } /{ self .language_code } /comic/{ self .webtoon_id } "
171183 try :
172- res = await self .client .get (f" { self . base_url } / { self . language_code } /comic/ { self . webtoon_id } " )
184+ res = await self .client .get (url )
173185 except HTTPStatusError as exc :
174186 if not exc .response .status_code == 307 :
175187 raise # InvalidWebtoonIdError이거나 기타 위로 전파해야 할 오류들
@@ -219,19 +231,24 @@ async def fetch_episode_information(self, *, reload: bool = False) -> None:
219231 else :
220232 raise WebtoonIdError .from_webtoon_id (self .webtoon_id , LezhinComicsScraper )
221233
222- selector = "body > div.lzCntnr > div > div > ul > li > a" # cspell: ignore Cntnr
223- episode_dates : list [str ] = []
224- episode_states : list [str ] = []
225- for episode in res .match (selector ):
226- # *_: 'N시간 후 무료' 요소의 경우 개수가 3개임
227- date_element , state_element , * _ = episode .css ("a > div > div > div > div" )
228- episode_dates .append (date_element .text ())
229- episode_states .append (state_element .text ())
234+ if self .is_library :
235+ self .episode_dates = None
236+ self .episode_states = None
237+ else :
238+ selector = "body > div.lzCntnr > div > div > ul > li > a" # cspell: ignore Cntnr
239+ episode_dates : list [str ] = []
240+ episode_states : list [str ] = []
241+ for episode in res .match (selector ):
242+ # *_: 'N시간 후 무료' 요소의 경우 개수가 3개임
243+ date_element , state_element , * _ = episode .css ("a > div > div > div > div" )
244+ episode_dates .append (date_element .text ())
245+ episode_states .append (state_element .text ())
246+
247+ self .episode_dates : list [str ] | None = episode_dates
248+ self .episode_states : list [str ] | None = episode_states
230249
231- self .episode_dates : list [str ] = episode_dates
232- self .episode_states : list [str ] = episode_states
233- if self .open_free_episode is None :
234- self .open_free_episode = False
250+ if self .open_free_episode is None :
251+ self .open_free_episode = False
235252
236253 # webtoon 정보를 받아옴.
237254 title = data ["meta" ]["content" ]["display" ]["title" ]
@@ -267,6 +284,9 @@ def _parse_user_information(self, data) -> None:
267284 default = {"isCollected" : False , "isViewed" : False }
268285 self .purchased_episodes = [episode_data_dict .get (episode_id , default )["isCollected" ] for episode_id in self .episode_int_ids ]
269286 self .viewed_episodes = [episode_data_dict .get (episode_id , default )["isViewed" ] for episode_id in self .episode_int_ids ]
287+ # 라이브러리인 경우 어차피 구매한 회차만 다운로드할 수 있기 때문에 나머지를 skip_download에 저장함
288+ if self .is_library and not self .skip_download :
289+ self .skip_download = [i for i , purchased in enumerate (self .purchased_episodes ) if not purchased ]
270290 if self .is_fhd_downloaded is None :
271291 self .is_fhd_downloaded = any (self .purchased_episodes )
272292
@@ -296,7 +316,7 @@ async def get_episode_image_urls(self, episode_no: int, retry: int = 3) -> list[
296316 episode_id_str = urllib .parse .quote (self .episode_ids [episode_no ])
297317 episode_id_int = self .episode_int_ids [episode_no ]
298318
299- if self .open_free_episode and self .episode_states [episode_no ] == "무료 공개" :
319+ if self .open_free_episode and self .episode_states and self . episode_states [episode_no ] == "무료 공개" :
300320 await self ._open_free_episode (episode_id_str )
301321
302322 keygen_url = (
@@ -402,6 +422,8 @@ def _extract_webtoon_id(cls, url) -> str | tuple[str, str] | None:
402422 match url .host , url .parts :
403423 case "www.lezhin.com" | "www.lezhinus.com" | "www.lezhin.jp" , ("/" , language_code , "comic" , webtoon_id ):
404424 return language_code , webtoon_id
425+ case "www.lezhin.com" | "www.lezhinus.com" | "www.lezhin.jp" , ("/" , language_code , "library" , "comic" , locale , webtoon_id ):
426+ return f"{ language_code } -library" , webtoon_id
405427
406428 async def _download_image (
407429 self ,
0 commit comments