Coverage for otaku_info/external/entities/RedditLnRelease.py: 65%

Shortcuts on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

61 statements  

1"""LICENSE 

2Copyright 2020 Hermann Krumrey <hermann@krumreyh.com> 

3 

4This file is part of otaku-info. 

5 

6otaku-info is free software: you can redistribute it and/or modify 

7it under the terms of the GNU General Public License as published by 

8the Free Software Foundation, either version 3 of the License, or 

9(at your option) any later version. 

10 

11otaku-info is distributed in the hope that it will be useful, 

12but WITHOUT ANY WARRANTY; without even the implied warranty of 

13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

14GNU General Public License for more details. 

15 

16You should have received a copy of the GNU General Public License 

17along with otaku-info. If not, see <http://www.gnu.org/licenses/>. 

18LICENSE""" 

19 

20from datetime import datetime 

21from typing import Optional, List 

22from bs4.element import Tag 

23from otaku_info.utils.dates import map_month_name_to_month_number 

24from otaku_info.external.anilist import load_anilist_info 

25from otaku_info.enums import ListService, MediaType 

26 

27 

28class RedditLnRelease: 

29 """ 

30 Object that acts as a wrapper around a light novel release on reddit.com 

31 """ 

32 

33 def __init__( 

34 self, 

35 series_name: str, 

36 year: int, 

37 release_date_string: str, 

38 volume: str, 

39 publisher: Optional[str], 

40 purchase_link: Optional[str], 

41 info_link: Optional[str], 

42 digital: bool, 

43 physical: bool 

44 ): 

45 """ 

46 Initializes the object 

47 :param series_name: The name of the series 

48 :param year: The year of release 

49 :param release_date_string: The month and day of release 

50 :param volume: The volume number 

51 :param publisher: The publisher of the release 

52 :param purchase_link: A purchase link for the release 

53 :param info_link: Link to information for the release 

54 :param digital: Whether or not the release is digital 

55 :param physical: Whether or not the release is physical 

56 """ 

57 self.series_name = series_name 

58 self.volume = volume 

59 self.publisher = publisher 

60 self.purchase_link = purchase_link 

61 self.info_link = info_link 

62 self.digital = digital 

63 self.physical = physical 

64 self.year = year 

65 self._release_date_string = release_date_string 

66 

67 @property 

68 def release_date(self) -> datetime: 

69 """ 

70 :return: The release date as a datetime object 

71 """ 

72 month_name, day_string = self._release_date_string.split(" ") 

73 month = map_month_name_to_month_number(month_name) 

74 if month is None: 74 ↛ 75line 74 didn't jump to line 75, because the condition on line 74 was never true

75 month = 1 

76 try: 

77 day = int(day_string) 

78 except ValueError: 

79 day = 1 

80 return datetime(year=self.year, month=month, day=day) 

81 

82 @property 

83 def release_date_string(self) -> str: 

84 """ 

85 :return: The release date as a string (ISO 8601) 

86 """ 

87 return self.release_date.strftime("%Y-%m-%d") 

88 

89 @property 

90 def myanimelist_id(self) -> Optional[int]: 

91 """ 

92 :return: The myanimelist ID, if available 

93 """ 

94 if self.info_link is None or "myanimelist.net" not in self.info_link: 

95 return None 

96 

97 url_parts = self.info_link.split("/") 

98 index = -1 

99 while not url_parts[index].isdigit(): 

100 index -= 1 

101 return int(url_parts[index]) 

102 

103 @property 

104 def anilist_id(self) -> Optional[int]: 

105 """ 

106 :return: The anilist ID, if available 

107 """ 

108 if self.myanimelist_id is None: 

109 return None 

110 anilist_info = load_anilist_info( 

111 self.myanimelist_id, MediaType.MANGA, ListService.MYANIMELIST 

112 ) 

113 if anilist_info is not None: 

114 return anilist_info.id 

115 else: 

116 return None 

117 

118 @classmethod 

119 def from_parts(cls, year: int, parts: List[Tag]) -> "RedditLnRelease": 

120 """ 

121 Generates a reddit LN release from BeautifulSoup td tags 

122 :param year: The year of the release 

123 :param parts: The td tags 

124 :return: The reddit ln release 

125 """ 

126 purchase_link_item = parts[3].find("a") 

127 purchase_link = None 

128 if purchase_link_item is not None: 128 ↛ 131line 128 didn't jump to line 131, because the condition on line 128 was never false

129 purchase_link = purchase_link_item["href"] 

130 

131 info_link_item = parts[1].find("a") 

132 info_link: Optional[str] = None 

133 if info_link_item is not None: 

134 info_link = info_link_item["href"] 

135 

136 digital = "digital" in parts[4].text.lower() 

137 physical = "physical" in parts[4].text.lower() 

138 

139 return cls( 

140 series_name=parts[1].text, 

141 year=year, 

142 release_date_string=parts[0].text, 

143 volume=parts[2].text, 

144 publisher=parts[3].text, 

145 purchase_link=purchase_link, 

146 info_link=info_link, 

147 digital=digital, 

148 physical=physical 

149 )