Runs every 4 hrs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { fetch } from "https://esm.town/v/std/fetch";
import { email, IAddress } from "https://esm.town/v/std/email";
import { DOMParser, Element } from "jsr:@b-fuze/deno-dom";
const WATCHED_HOSTS = new Set([
'alexanderpetros.com',
'unplannedobsolescence.com',
'thefloatingcontinent.com',
'wemakeinter.net',
])
export default async function (interval: Interval) {
const matchedStories = []
await checkHN(matchedStories)
await checkLobsters(matchedStories)
if (matchedStories.length < 1) {
return new Response("None found");
}
const html = `
<p>
One (or more) of your posts was spotted on the aggregators:
<ul>
${matchedStories.map(story => `<li>
<a href="${story.story_url}">${story.title}</a> - ${story.host}
(<a href="${story.agg_url}">${story.agg_name} comments</a>)`)}
</ul>
-
`
const from: IAddress = { email: 'alexpetros.bots@valtown.email', name: 'ValBot'}
await email({ subject: "Aggregator Sightings", from, html });
return new Response("Found");
}
async function checkHN(matchedStories) {
// Get the title of the top story on Hacker News
const res = await fetch("https://hacker-news.firebaseio.com/v0/topstories.json")
const topStories = await res.json()
const frontPage = topStories.slice(0, 50)
const promises = frontPage.map(async storyId => {
const res = await fetch(`https://hacker-news.firebaseio.com/v0/item/${storyId}.json`)
const story = await res.json()
try {
const host = (new URL(story.url)).host
const agg_url = `https://news.ycombinator.com/item?id=${story.id}`
const matchedStory = { story_url: story.url, title: story.title, host, agg_url, agg_name: 'HN' }
if (WATCHED_HOSTS.has(host)) matchedStories.push(matchedStory)
} catch {} // Ignore unparseable URLs
})
await Promise.all(promises)
}
async function checkLobsters(matchedStories) {
const res = await fetch(`https://lobste.rs`)
const text = await res.text()
const dom = new DOMParser().parseFromString(text, "text/html")
const stories = dom.querySelectorAll('li.story')
for (const story of stories) {
const link = story.querySelector('a.u-url')
try {
const url = new URL(link.getAttribute("href"))
const host = url.host
const title = link.innerText
const agg_local = story.querySelector('.comments_label a').getAttribute("href")
const agg_url = `https://lobste.rs` + agg_local
const matchedStory = { story_url: url.href, title, host, agg_url, agg_name: 'Lobsters' }
if (WATCHED_HOSTS.has(host)) matchedStories.push(matchedStory)
} catch {} // Ignore invalid URLs
}
}
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
August 21, 2024