Avatar

@akkartik

2 likes14 public vals
Joined September 17, 2022
Building programs that are useful, easy to install, easy to run, easy to modify, easy to share.
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
export let hnAuthors = [
"alankay",
"worrydream",
"stevewoz",
"norvig",
"willbyrd",
"hwayne",
"jackrusher",
"spiralganglion",
"kragen",
"khinsen",
"atularora",
// "btilly", // volume
"cwan",
"edw519",
"fogus",
"gruseom",
"haberman",
"icey",
// "jerf", // volume
// "jrockway", // volume
"nostrademons",
"ojbyrne",
"palish",
"pchristensen",
"raganwald",
"swombat",
"tokenadult",
"vaksel",
"yummyfajitas",
"zedshaw",
"aadillpickle",
"johnfn",
// "YeGoblynQueenne", // Prolog stuff is fun, anti-AI rants not fun
// "DonHopkins", // too little Forth
// "cxr", // too damn confrontational
"saurik",
"Zak",
// "bioemerl", // one-track railing against China these days
"alecco",
// "eternalban", // too few comments on islamic history
"carapace",
"kkfx",
"raphlinus",
"Avshalom",
"dragontamer",
"torgoguys", // via kragen
"jonjacky", // flattery will get you anywhere: https://news.ycombinator.com/context?id=38987209&submission=38858012
"Pamar", // via kragen; https://news.ycombinator.com/item?id=39403344
];
1
2
3
4
5
export let hnContextLink = (comment_id, submission_id) =>
// My preferred permalink format. HN context links will skip to the appropriate page
// when a large thread gets paginated.
// I like to include the story (submission) even though they aren't required.
`https://news.ycombinator.com/context?id=${comment_id}&submission=${submission_id}`;
1
2
3
4
5
6
7
8
9
export let oldHNFollowNotebook = [
"@akkartik.hnInterval",
"@akkartik.testHNEmail",
"@akkartik.hnAlert",
"@akkartik.testHNAlert",
"@akkartik.getNewHNPosts",
"@akkartik.postprocessHNitem",
"@stevekrouse.hnSearch",
];
1
2
3
4
5
6
7
8
9
export let hnPostsByUserOldNotebook = [
"@akkartik.testHNpostsWithStoryTitles",
"@akkartik.hnPostsWithStoriesNoBylineCached",
"@akkartik.hnPostsBy",
"@akkartik.hnPostIdsBy",
"@akkartik.hnPostsCached",
"@akkartik.HNcache",
"@akkartik.hnPost",
];
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
import { hnStoryPure } from "https://esm.town/v/akkartik/hnStoryPure";
import { hnPostsCached } from "https://esm.town/v/akkartik/hnPostsCached";
export let hnPostsWithStoriesNoBylineCached = async (posts) => {
// crawl parents of each post up to stories
var remaining = posts
.map((post) => post.parent)
.filter((x) => x !== undefined);
while (remaining.length > 0) {
var remainingPosts = await hnPostsCached(remaining);
remaining = remainingPosts
.map((post) => post.parent)
.filter((x) => x !== undefined);
}
// now traverse each post to story
for (i = 0; i < posts.length; i++) {
var post = posts[i];
post.story = (await hnStoryPure(post)).title;
delete post.kids;
delete post.parent;
delete post.time;
delete post.type;
delete post.parent;
delete post.by;
delete post.id;
}
return posts;
};
1
2
3
4
5
6
7
8
9
10
import { HNcache } from "https://esm.town/v/akkartik/HNcache";
// traverse parent links up to story, but don't make any API requests
export let hnStoryPure = async (post) => {
while (post.parent) {
post = HNcache[post.parent];
// console.assert(post);
}
return post;
};
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
import { hnStoryPure } from "https://esm.town/v/akkartik/hnStoryPure";
import { hnPostsCached } from "https://esm.town/v/akkartik/hnPostsCached";
export let hnPostsWithStoriesCached = async (posts) => {
// crawl parents of each post up to stories
var remaining = posts
.map((post) => post.parent)
.filter((x) => x !== undefined);
while (remaining.length > 0) {
var remainingPosts = await hnPostsCached(remaining);
remaining = remainingPosts
.map((post) => post.parent)
.filter((x) => x !== undefined);
}
// now traverse each post to story
for (i = 0; i < posts.length; i++) {
var post = posts[i];
post.story = (await hnStoryPure(post)).title;
delete post.kids;
delete post.parent;
delete post.time;
delete post.type;
delete post.parent;
}
return posts;
};
1
2
3
4
5
6
7
8
import { hnPostsCached } from "https://esm.town/v/akkartik/hnPostsCached";
export let hnPostParentsCached = async (posts) => {
var postParentIds = posts
.map((post) => post.parent)
.filter((x) => x !== undefined);
return await hnPostsCached(postParentIds);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { hnPost } from "https://esm.town/v/akkartik/hnPost";
let { HNcache } = await import("https://esm.town/v/akkartik/HNcache");
export let hnPostsCached = async (postIds) => {
// request needed ids
var newPosts = {};
for (const postId of postIds) {
if (HNcache[postId] == undefined)
newPosts[postId] = await hnPost(postId);
}
// update cache all at once
HNcache = {
...HNcache,
...newPosts,
};
// construct results
return postIds.map((postId) => HNcache[postId]);
};
1
2
// https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep
export let sleep = async (ms) => (r) => setTimeout(r, ms);