Skip to content

Commit

Permalink
feat: hackernews
Browse files Browse the repository at this point in the history
  • Loading branch information
aldy505 committed Nov 12, 2023
1 parent 0970fd1 commit 40ad6b9
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { memoryUsage } from "process";
import { fork } from "child_process";
import { Telegraf } from "telegraf";
import dotenv from "dotenv";
import mongoose from "mongoose";
Expand Down Expand Up @@ -112,6 +113,8 @@ async function main() {
}
});

fork(pathTo("./hackernews.js"), { detached: false });

// For more information about what this is, please refer to:
// https://nodejs.org/api/process.html#process_process_memoryusage
terminal.log(
Expand Down
47 changes: 47 additions & 0 deletions src/hackernews.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Telegraf } from "telegraf";
import dotenv from "dotenv";
import { pathTo } from "#utils/path.js";
import { run } from "#services/hackernews.js";
import { sentry } from "#utils/logger.js";

dotenv.config({ path: pathTo(import.meta.url, "../.env") });

const bot = new Telegraf(process.env.BOT_TOKEN);

function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

for (;;) {
if (new Date().getUTCHours() === 0 || new Date().getUTCHours() === 11) {
let done = false;

// eslint-disable-next-line no-await-in-loop
await run(bot)
.catch((error) => {
sentry.captureException(error);
})
.finally(() => {
done = true;
});

while (!done) {
// wait
}
}

// How long until the next time we have to send message?
const now = new Date();
let nextTime;

if (now.getUTCHours() > 11) {
// The next time is 00:00 AM
nextTime = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDay() + 1, 0, 0, 0, 0);
} else if (now.getHours() < 11) {
// The next time is 11:00 AM
nextTime = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDay(), 11, 0, 0, 0);
}

// eslint-disable-next-line no-await-in-loop
await sleep(nextTime.getTime() - now.getTime());
}
81 changes: 81 additions & 0 deletions src/services/hackernews/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import got from "got";
import { sanitize } from "#utils/sanitize.js";

async function getStories() {
const response = await got.get("https://hacker-news.firebaseio.com/v0/topstories.json", {
headers: {
Accept: "application/json"
},
responseType: "json"
});

return response.body;
}

async function getItem(id) {
const response = await got.get(`https://hacker-news.firebaseio.com/v0/item/${id}.json`, {
headers: {
Accept: "application/json"
},
responseType: "json"
});

return response.body;
}

/**
*
* @param {import('telegraf').Telegraf<Context<Update>>} context
*/
export async function run(context) {
// Get all stories
const allStories = await getStories();

// Create an array for resulting stories
const resultingStories = [];

const last24Hours = new Date();
last24Hours.setHours(last24Hours.getHours() - 24);

// Iterate each story
for (const story of allStories) {
// If the resultingStories' length is 10, we'll stop.
if (resultingStories.length === 10) break;

// eslint-disable-next-line no-await-in-loop
const item = await getItem(story);
// We only want stories. Not job, comment, or poll
if (item?.type !== "story") continue;
// We only want stories that's high in rating
if (item?.score < 100) continue;
// It's useless if it's dead.
if (item?.dead) continue;
// We don't want old stories to come up. Limit this to last 24 hours.
if (item?.time && item.time < last24Hours.getTime()) continue;

resultingStories.push(item);
}

// Now we build the message
let message = "<b>Today's Hacker News</b>\n\n";
for (let i = 1; i <= resultingStories.length; i++) {
const story = resultingStories[i-1];

message += `${i}. <a href="${story.url}">${story.title}</a>\n`;
if (story?.text) {
message += sanitize(story.text, true);
message += "\n";
}

if (i !== resultingStories.length) {
message += "\n";
}
}

// Finally, send the message
await context.telegram.sen1dMessage(
process.env.HOME_GROUP_ID,
message,
{ parse_mode: "HTML", disable_web_page_preview: false }
);
}

0 comments on commit 40ad6b9

Please sign in to comment.