Coverage for mindsdb / integrations / handlers / hackernews_handler / hn_handler.py: 0%

69 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-21 00:36 +0000

1import requests 

2import pandas as pd 

3from mindsdb.utilities import log 

4from mindsdb.integrations.libs.api_handler import APIHandler 

5from mindsdb.integrations.libs.response import HandlerStatusResponse as StatusResponse, HandlerResponse as Response, RESPONSE_TYPE 

6from .hn_table import StoriesTable, CommentsTable, HNStoriesTable, JobStoriesTable, ShowStoriesTable 

7 

8logger = log.getLogger(__name__) 

9 

10 

11class HackerNewsHandler(APIHandler): 

12 """ 

13 A class for handling connections and interactions with the Hacker News API. 

14 """ 

15 

16 def __init__(self, name=None, **kwargs): 

17 super().__init__(name) 

18 

19 self.base_url = 'https://hacker-news.firebaseio.com/v0' 

20 

21 stories = StoriesTable(self) 

22 self._register_table('stories', stories) 

23 

24 hnstories = HNStoriesTable(self) 

25 self._register_table('hnstories', hnstories) 

26 

27 jobstories = JobStoriesTable(self) 

28 self._register_table('jobstories', jobstories) 

29 

30 showstories = ShowStoriesTable(self) 

31 self._register_table('showstories', showstories) 

32 

33 comments = CommentsTable(self) 

34 self._register_table('comments', comments) 

35 

36 def connect(self): 

37 return 

38 

39 def check_connection(self) -> StatusResponse: 

40 try: 

41 response = requests.get(f'{self.base_url}/maxitem.json') 

42 response.raise_for_status() 

43 return StatusResponse(True) 

44 except Exception as e: 

45 logger.error(f'Error checking connection: {e}') 

46 return StatusResponse(False, str(e)) 

47 

48 def native_query(self, query_string: str = None): 

49 method_name, params = self.parse_native_query(query_string) 

50 

51 df = self.call_hackernews_api(method_name, params) 

52 

53 return Response( 

54 RESPONSE_TYPE.TABLE, 

55 data_frame=df 

56 ) 

57 

58 def get_df_from_class(self, table: StoriesTable = None, limit: int = None): 

59 url = f'{self.base_url}/{table.json_endpoint}' 

60 response = requests.get(url) 

61 data = response.json() 

62 stories_data = [] 

63 if limit is None: 

64 limit = len(data) 

65 for story_id in data[:limit]: 

66 url = f'{self.base_url}/item/{story_id}.json' 

67 response = requests.get(url) 

68 story_data = response.json() 

69 stories_data.append(story_data) 

70 return pd.DataFrame(stories_data, columns=table.columns) 

71 

72 def call_hackernews_api(self, method_name: str = None, params: dict = None): 

73 story_method_handlers = { 

74 'get_top_stories': StoriesTable, 

75 'ask_hn_stories': HNStoriesTable, 

76 'get_job_stories': JobStoriesTable, 

77 'show_hn_stories': ShowStoriesTable, 

78 } 

79 if method_name in story_method_handlers: 

80 table = story_method_handlers[method_name] 

81 df = self.get_df_from_class(table) 

82 elif method_name == 'get_comments': 

83 item_id = params.get('item_id') 

84 url = f'{self.base_url}/item/{item_id}.json' 

85 response = requests.get(url) 

86 item_data = response.json() 

87 if 'kids' in item_data: 

88 comments_data = [] 

89 for comment_id in item_data['kids']: 

90 url = f'{self.base_url}/item/{comment_id}.json' 

91 response = requests.get(url) 

92 comment_data = response.json() 

93 comments_data.append(comment_data) 

94 df = pd.DataFrame(comments_data) 

95 else: 

96 df = pd.DataFrame() 

97 else: 

98 raise ValueError(f'Unknown method_name: {method_name}') 

99 

100 return df