Skip to content

Commit

Permalink
feat: add hackernews project in kittehub (#123)
Browse files Browse the repository at this point in the history
This PR addresses ENG-1025. Project tracks articles from Hacker News
based on user-provided topic and sends updates to a designated Slack
channel. The main functionality includes:
• Slash Command Integration: Users can specify a topic to monitor
directly from Slack.
• Real-Time Updates: The bot fetches new articles every two minutes and
posts any updates to Slack.
• Hacker News API Integration: Uses the Algolia-powered Hacker News API
to search for articles by keyword.
• Slack Integration: Sends article details (title and URL) to the
specified Slack channel.

Since we’re updating the README to focus on cloud deployment, I did not
place significant emphasis on the README file

---------

Co-authored-by: Daniel Abraham <[email protected]>
Co-authored-by: Pasha Fateev <[email protected]>
  • Loading branch information
3 people authored Dec 8, 2024
1 parent fb34bd6 commit 4968949
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 0 deletions.
63 changes: 63 additions & 0 deletions hackernews/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
title: Hacker News Alerts in Slack
description: Track Hacker News articles by topic and send updates to Slack
integrations: ["slack"]
categories: ["Office Automation"]
---

# Hacker News Alerts in Slack

This project monitors Hacker News for new articles matching a specific topic, fetching their details in real-time. It compares the latest results with previously fetched articles to identify new ones and sends their title and URL as notifications to a Slack channel.

## How It Works

1. Extract the topic from the Slack app mention.
2. Add the topic to the Hacker News search query (check out [Algolia's REST API](https://www.algolia.com/doc/api-reference/rest-api) for more details).
3. Return all the new articles related to the topic that were published since the last check.

## Deployment & Configuration

#### Cloud Usage (Recommended)

- Initialize your connection with Slack through the UI

#### Prerequisites

- [Install AutoKitteh](https://docs.autokitteh.com/get_started/install)
- Set up required integrations:
- [Slack](https://docs.autokitteh.com/integrations/slack)

#### Installation Steps

1. Clone the repository:
```shell
git clone https://github.com/autokitteh/kittehub.git
cd kittehub/hackernews
```

2. Start the AutoKitteh server:
```shell
ak up --mode dev
```

3. Deploy the project:
```shell
ak deploy --manifest autokitteh.yaml
```

The output will show your connection IDs, which you'll need for the next step. Look for lines like:
```shell
[exec] create_connection "hackernews_alert/slack_connection": con_01je39d6frfdtshstfg5qpk8sz created
```

In this example, `con_01je39d6frfdtshstfg5qpk8sz` is the connection ID.

4. Initialize your connections using the CLI:
```shell
ak connection init slack_connection <connection ID>
```

## Trigger Workflow

- Type `@your-slack-app topic` in the Slack channel you set in the environment variable, replacing `topic` with what you want to search for, to start tracking articles
- The workflow runs automatically every two minutes after deployment
18 changes: 18 additions & 0 deletions hackernews/autokitteh.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This YAML file is a declarative manifest that describes the setup of an
# AutoKitteh project that monitors Hacker News for a specific topic.

version: v1

project:
name: hackernews_alert
vars:
- name: POLLING_INTERVAL_SECS
value: 120
connections:
- name: slack_connection
integration: slack
triggers:
- name: slack_slash_command
connection: slack_connection
event_type: app_mention
call: program.py:on_slack_command
56 changes: 56 additions & 0 deletions hackernews/program.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""Monitor Hacker News for new articles on a specific topic, and post updates to a Slack channel."""

import os
import requests
import time
import urllib.parse

from autokitteh.slack import slack_client


API_URL = "http://hn.algolia.com/api/v1/search_by_date?tags=story&page=0&query="
POLLING_INTERVAL_SECS = int(os.getenv("POLLING_INTERVAL_SECS"))

slack = slack_client("slack_connection")


def on_slack_command(event):
"""Workflow's entry-point.
Extracts a topic from a Slack command, monitors for new articles,
and posts updates to `SLACK_CHANNEL`.
"""
topic = event.data.text.split(" ", 1)[-1].strip()
slack.chat_postMessage(
channel=event.data.channel,
text=f"Waiting for new articles on the topic: `{topic}`.",
)
current_articles = set()
fetch_articles(topic, current_articles)

# NOTE: For low-traffic topics, it might take a while for new articles to be published,
# so users may experience delays in receiving notifications.
while True:
all_articles = set(current_articles)
fetch_articles(topic, all_articles)
new_articles = all_articles - current_articles

for article in new_articles:
_, title, url = article
slack_message = f"Title: {title}, URL: {url if url else 'No URL'}"
slack.chat_postMessage(channel=event.data.channel, text=slack_message)
current_articles.update(new_articles)

time.sleep(POLLING_INTERVAL_SECS)


def fetch_articles(topic, all_articles):
encoded_query = urllib.parse.quote(topic)
full_url = f"{API_URL}{encoded_query}"
hits = requests.get(full_url).json().get("hits", [])

# Extract some of the article fields from the API response.
for article in hits:
object_id = article["objectID"]
title = article["title"]
url = article.get("url")
all_articles.add((object_id, title, url))

0 comments on commit 4968949

Please sign in to comment.