From 15397257dfd59f79833297705ed85b59006a95ba Mon Sep 17 00:00:00 2001 From: Yoshiki Obinata Date: Mon, 19 Dec 2022 15:51:49 +0900 Subject: [PATCH] [newsapi_ros] Add newsapi package --- newsapi_ros/CMakeLists.txt | 47 ++++++++++++++ newsapi_ros/action/GetTopHeadlines.action | 11 ++++ newsapi_ros/launch/newsapi_ros.launch | 15 +++++ newsapi_ros/msg/News.msg | 8 +++ newsapi_ros/node_scripts/newsapi_node.py | 74 +++++++++++++++++++++++ newsapi_ros/package.xml | 26 ++++++++ newsapi_ros/requirements.txt | 1 + 7 files changed, 182 insertions(+) create mode 100644 newsapi_ros/CMakeLists.txt create mode 100644 newsapi_ros/action/GetTopHeadlines.action create mode 100644 newsapi_ros/launch/newsapi_ros.launch create mode 100644 newsapi_ros/msg/News.msg create mode 100644 newsapi_ros/node_scripts/newsapi_node.py create mode 100644 newsapi_ros/package.xml create mode 100644 newsapi_ros/requirements.txt diff --git a/newsapi_ros/CMakeLists.txt b/newsapi_ros/CMakeLists.txt new file mode 100644 index 000000000..a1bddb74d --- /dev/null +++ b/newsapi_ros/CMakeLists.txt @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 2.8.3) +project(newsapi_ros) + +find_package( + catkin REQUIRED COMPONENTS + catkin_virtualenv REQUIRED + rospy + actionlib_msgs + std_msgs + message_generation + ) + +add_message_files( + FILES + News.msg +) + +add_action_files( + FILES + GetTopHeadlines.action +) + +generate_messages( + DEPENDENCIES + std_msgs + actionlib_msgs +) + +catkin_package() + +catkin_generate_virtualenv( + PYTHON_INTERPRETER python3 + ) + +file(GLOB PYTHON_NODES node_scripts/*.py) +catkin_install_python( + PROGRAMS ${PYTHON_NODES} + DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} + ) + +install(FILES requirements.txt + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} + ) + +install(DIRECTORY launch + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} + ) diff --git a/newsapi_ros/action/GetTopHeadlines.action b/newsapi_ros/action/GetTopHeadlines.action new file mode 100644 index 000000000..8c9416c37 --- /dev/null +++ b/newsapi_ros/action/GetTopHeadlines.action @@ -0,0 +1,11 @@ +# Define the goal +string keyword # Keywords or a phrase to search for in the article title and body +string[] sources # A string list of identifiers for the news sources or blogs you want headlines from +string category # Find sources that display news of this category. Choose from business entertainment general health science sports technology +--- +# Define the result +newsapi_ros/News[] news_list +bool done +--- +# Define the feedback message +string status diff --git a/newsapi_ros/launch/newsapi_ros.launch b/newsapi_ros/launch/newsapi_ros.launch new file mode 100644 index 000000000..9340a44e1 --- /dev/null +++ b/newsapi_ros/launch/newsapi_ros.launch @@ -0,0 +1,15 @@ + + + + + + + + + api_key: $(arg api_key) + country: $(arg country) + + + + diff --git a/newsapi_ros/msg/News.msg b/newsapi_ros/msg/News.msg new file mode 100644 index 000000000..3421fdadb --- /dev/null +++ b/newsapi_ros/msg/News.msg @@ -0,0 +1,8 @@ +string source +string author +string title +string description +string url +string url_to_image +string published_at +string content diff --git a/newsapi_ros/node_scripts/newsapi_node.py b/newsapi_ros/node_scripts/newsapi_node.py new file mode 100644 index 000000000..c0e995716 --- /dev/null +++ b/newsapi_ros/node_scripts/newsapi_node.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +import actionlib +from newsapi import NewsApiClient +from newsapi.newsapi_client import NewsAPIException +from newsapi_ros.msg import GetTopHeadlinesAction, GetTopHeadlinesFeedback, GetTopHeadlinesResult, News +import rospy + +class NewsApiNode(object): + + CATEGORIES = ["business", "entertainment", "general", "health", "science", "sports", "technology"] + + def __init__(self): + self.language = rospy.get_param("~language", None) + self.country = rospy.get_param("~country", "jp") + _api_key = rospy.get_param("~api_key") + self._newsapi = NewsApiClient(api_key=_api_key) + self._top_headlines_as = actionlib.SimpleActionServer("~get_top_headlines", + GetTopHeadlinesAction, + execute_cb=self._top_headlines_cb, + auto_start=False) + # TODO add EVERYTHING. c.f. https://newsapi.org/docs/endpoints/everything + self._top_headlines_as.start() + + + def _top_headlines_cb(self, goal): + feedback = GetTopHeadlinesFeedback() + result = GetTopHeadlinesResult() + success = False + # Request + keyword = goal.keyword if goal.keyword else None + sources = ",".join(goal.sources) if ",".join(goal.sources) else None + if sources: + rospy.logwarn("Sources param was set. Category and country are ignored") + # sources param cannot be mixed with the ``country`` or ``category`` params + if not goal.category in self.CATEGORIES: + raise KeyError("Invalid categories. Choose from {}".format(",".join(self.CATEGORIES))) + category = goal.category if (goal.category and not sources) else None + country = self.country if (not sources) else None + try: + res = self._newsapi.get_top_headlines(q=keyword, + sources=sources, + category=category, + language=self.language, + country=country) + news_infos = [] + for article in res['articles']: + news = News() + news.source = str(article.get("source").get("name")) + news.author = str(article.get("author")) + news.title = str(article.get("title")) + news_infos.append(news.title) + news.description = str(article.get("description")) + news.url = str(article.get("url")) + news.url_to_image = str(article.get("urlToImage")) + news.published_at = str(article.get("published_at")) + news.content = str(article.get("content")) + result.news_list.append(news) + success = True + rospy.loginfo("Got Top Headlines news. {}".format(", ".join(news_infos))) + except (NewsAPIException, SyntaxError, ValueError) as e: + rospy.logerr(e) + feedback.status = str(e) + success = False + finally: + self._top_headlines_as.publish_feedback(feedback) + result.done = success + self._top_headlines_as.set_succeeded(result) + + +if __name__ == "__main__": + rospy.init_node("newsapi_ros") + node = NewsApiNode() + rospy.spin() diff --git a/newsapi_ros/package.xml b/newsapi_ros/package.xml new file mode 100644 index 000000000..985653069 --- /dev/null +++ b/newsapi_ros/package.xml @@ -0,0 +1,26 @@ + + + newsapi_ros + 0.0.0 + The ROS package for news API + + Yoshiki Obinata + Kei Okada + + Yoshiki Obinata + + BSD + + catkin + + message_generation + catkin_virtualenv + + message_runtime + rospy + std_msgs + + + requirements.txt + + diff --git a/newsapi_ros/requirements.txt b/newsapi_ros/requirements.txt new file mode 100644 index 000000000..0375285d7 --- /dev/null +++ b/newsapi_ros/requirements.txt @@ -0,0 +1 @@ +newsapi-python