11"""ForumTopic and ForumPost classes"""
22from __future__ import annotations
33
4+ from dataclasses import dataclass , field
5+ from typing import Optional
6+ from urllib .parse import urlparse , parse_qs
7+ import xml .etree .ElementTree as ET
8+
9+ from bs4 import BeautifulSoup
10+
411from . import user
12+ from . import session
513from ..utils .commons import headers
614from ..utils import exceptions , commons
715from ._base import BaseSiteComponent
8- import xml .etree .ElementTree as ET
9- from bs4 import BeautifulSoup
10- from urllib .parse import urlparse , parse_qs
11-
12- from ..utils .requests import Requests as requests
16+ from ..utils .requests import requests
1317
18+ @dataclass
1419class ForumTopic (BaseSiteComponent ):
1520 '''
1621 Represents a Scratch forum topic.
@@ -33,20 +38,18 @@ class ForumTopic(BaseSiteComponent):
3338
3439 :.update(): Updates the attributes
3540 '''
36-
37- def __init__ (self , ** entries ):
41+ id : int
42+ title : str
43+ category_name : str
44+ last_updated : str
45+ _session : Optional [session .Session ] = field (default = None )
46+ reply_count : Optional [int ] = field (default = None )
47+ view_count : Optional [int ] = field (default = None )
48+
49+ def __post_init__ (self ):
3850 # Info on how the .update method has to fetch the data:
3951 self .update_function = requests .get
40- self .update_API = f"https://scratch.mit.edu/discuss/feeds/topic/{ entries ['id' ]} /"
41-
42- # Set attributes every Project object needs to have:
43- self ._session = None
44- self .id = 0
45- self .reply_count = None
46- self .view_count = None
47-
48- # Update attributes from entries dict:
49- self .__dict__ .update (entries )
52+ self .update_api = f"https://scratch.mit.edu/discuss/feeds/topic/{ self .id } /"
5053
5154 # Headers and cookies:
5255 if self ._session is None :
@@ -65,7 +68,7 @@ def update(self):
6568 # As there is no JSON API for getting forum topics anymore,
6669 # the data has to be retrieved from the XML feed.
6770 response = self .update_function (
68- self .update_API ,
71+ self .update_api ,
6972 headers = self ._headers ,
7073 cookies = self ._cookies , timeout = 20 # fetching forums can take very long
7174 )
@@ -87,15 +90,20 @@ def update(self):
8790 raise exceptions .ScrapeError (str (e ))
8891 else :
8992 raise exceptions .ForumContentNotFound
90-
91- return self ._update_from_dict (dict (
92- title = title , category_name = category_name , last_updated = last_updated
93- ))
94-
95-
96- def _update_from_dict (self , data ):
97- self .__dict__ .update (data )
93+ self .title = title
94+ self .category_name = category_name
95+ self .last_updated = last_updated
9896 return True
97+
98+ @classmethod
99+ def from_id (cls , id : int , session : session .Session , update : bool = False ):
100+ new = cls (id = id , _session = session , title = "" , last_updated = "" , category_name = "" )
101+ if update :
102+ new .update ()
103+ return new
104+
105+ def _update_from_dict (self , data ):
106+ raise NotImplementedError ()
99107
100108 def posts (self , * , page = 1 , order = "oldest" ):
101109 """
@@ -157,7 +165,6 @@ def first_post(self):
157165 if len (posts ) > 0 :
158166 return posts [0 ]
159167
160-
161168class ForumPost (BaseSiteComponent ):
162169 '''
163170 Represents a Scratch forum post.
@@ -195,7 +202,7 @@ def __init__(self, **entries):
195202
196203 # A forum post can't be updated the usual way as there is no API anymore
197204 self .update_function = None
198- self .update_API = None
205+ self .update_api = None
199206
200207 # Set attributes every Project object needs to have:
201208 self ._session = None
@@ -225,14 +232,14 @@ def update(self):
225232 As there is no API for retrieving a single post anymore, this requires reloading the forum page.
226233 """
227234 page = 1
228- posts = ForumTopic (id = self .topic_id , _session = self ._session ).posts (page = 1 )
235+ posts = ForumTopic . from_id (id = self .topic_id , session = self ._session ).posts (page = 1 )
229236 while posts != []:
230237 matching = list (filter (lambda x : int (x .id ) == int (self .id ), posts ))
231238 if len (matching ) > 0 :
232239 this = matching [0 ]
233240 break
234241 page += 1
235- posts = ForumTopic (id = self .topic_id , _session = self ._session ).posts (page = page )
242+ posts = ForumTopic . from_id (id = self .topic_id , session = self ._session ).posts (page = page )
236243 else :
237244 return False
238245
0 commit comments