Skip to content

Instantly share code, notes, and snippets.

@velut
Last active July 8, 2021 16:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save velut/6d0335c3ede885e11ce7c5768107d103 to your computer and use it in GitHub Desktop.
Save velut/6d0335c3ede885e11ce7c5768107d103 to your computer and use it in GitHub Desktop.
🦕 Running your first Deno script (From: https://www.edoardoscibona.com/running-your-first-deno-script)
//
// Follow along with the article at:
// https://www.edoardoscibona.com/running-your-first-deno-script
//
// This script is licensed under the MIT license (https://opensource.org/licenses/MIT).
//
// Import the `sleep` function from a remote module
import { sleep } from "https://deno.land/x/sleep/mod.ts";
/** Base URL for all calls to the Hacker News API */
const baseURL = "https://hacker-news.firebaseio.com/v0";
/** Item represents an item fetched from the HN API */
interface Item {
/** Unique item ID; the only required property */
readonly id: number;
/** Item type (`job`, `story`, `comment`, `poll`, or `pollopt`) */
readonly type?: string;
/** Username of the user who submitted the item */
readonly by?: string;
/** Title text for a story, poll or job */
readonly title?: string;
/** URL for a story or job */
readonly url?: string;
/** Text for a story, comment, poll, poll option or job */
readonly text?: string;
/** Unix timestamp for when the item was created */
readonly time?: number;
/** Score for a story, job or poll; votes for a poll option */
readonly score?: number;
/** Number of total comments for a story or poll */
readonly descendants?: number;
/** Set to `true` if the item is deleted */
readonly deleted?: boolean;
/** Set to `true` if the item is dead */
readonly dead?: boolean;
/** ID of the parent item of a comment (a story or another comment) */
readonly parent?: number;
/** List of IDs of the item's comments, in display order */
readonly kids?: number[];
/** ID of the poll associated to a poll option */
readonly poll?: number;
/** List of IDs of related poll options, in display order */
readonly parts?: number[];
}
/** getMaxItemID returns the ID of the most recent item published on HN */
async function getMaxItemID(): Promise<number> {
const endpoint = `${baseURL}/maxitem.json`;
const res = await fetch(endpoint);
const id = await res.json();
return id;
}
/** getItemByID fetches an item from the HN API given its ID */
async function getItemByID(id: number): Promise<Item | undefined> {
const endpoint = `${baseURL}/item/${id}.json`;
const res = await fetch(endpoint);
const item = await res.json();
return item ?? undefined;
}
/** streamComments continuously fetches and displays the most recent comments published on HN */
async function streamComments() {
// Get the ID of the most recent item
let id = await getMaxItemID();
// Keep running forever
while (true) {
// Get the item
const item = await getItemByID(id);
// If the item does not exist, wait 5 seconds and try again
if (!item) {
await sleep(5);
continue;
}
// Print only items that are visible comments
const { type, deleted, dead } = item;
const removed = deleted || dead || false;
if (type === "comment" && !removed) {
// Get the comment's author, if any
const author = item.by ?? "unknown author";
// Get the comment's URL on HN website
const hnURL = `https://news.ycombinator.com/item?id=${id}`;
// Print the comment
console.log(`\nRead new comment by ${author} on ${hnURL}`);
console.log(item);
}
// Increment the ID for the next item
id += 1;
}
}
await streamComments();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment