-
Notifications
You must be signed in to change notification settings - Fork 0
/
digest.js
119 lines (92 loc) · 3.28 KB
/
digest.js
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
export default {
async fetch(request, env) {
let maxId = null;
let timeline = [];
const { startOfDay, endOfDay } = this.today();
try {
while (true) {
const statuses = await this.fetchStatuses(env.MASTODON_TOKEN, maxId);
if (statuses.length === 0) {
break;
}
timeline.push(...statuses.filter(
status => new Date(status.created_at) >= startOfDay && new Date(status.created_at) <= endOfDay
));
const lastId = Math.min(...statuses.map(status => status.id));
const reachedDayBefore = new Date(statuses.pop().created_at) < startOfDay;
if (reachedDayBefore || maxId == lastId) {
break;
}
maxId = lastId;
}
} catch(err) {
return new Response(err.stack, { status: 500 })
}
const scoredTimeline = this.scoreTimeline(timeline)
.filter(status => status._score > 2) // remove junk
.slice(0, 5); // limit to 5 posts
const { pathname } = new URL(request.url);
if (pathname.endsWith('.json')) {
return new Response(JSON.stringify(scoredTimeline, null, 2), {
headers: { 'content-type': 'application/json;charset=UTF-8' },
});
}
const iframes = scoredTimeline.map(status => {
return `<iframe src="${status.url}/embed" class="mastodon-embed" width="400" style="border: 0; max-width: 100%; margin-bottom: 2rem;"></iframe>`
});
const html = `<!DOCTYPE html>
<body style="text-align: center;">
<h1>Daily Digest</h1>
<h3>${startOfDay.toLocaleString('en-GB', {timeZone: 'America/Vancouver'})} — ${endOfDay.toLocaleString('en-GB', {timeZone: 'America/Vancouver'})}</h3>
${iframes.join('<br>')}
<script src="https://nelson.social/embed.js" async="async"></script>
</body>`;
return new Response(html, {
headers: { 'content-type': 'text/html;charset=UTF-8' },
});
},
async fetchStatuses(token, maxId) {
let params = 'local=1&limit=5';
if (maxId) {
params += `&max_id=${maxId}`;
}
const response = await fetch(`https://nelson.social/api/v1/timelines/public?${params}`, {
headers: {
'authorization': `Bearer ${token}`,
},
});
return await response.json();
},
scoreTimeline(timeline) {
const scored = timeline.map(status => {
status._score = [
status.replies_count * 2,
status.reblogs_count * 2,
status.favourites_count,
status.in_reply_to_id ? 0 : 2, // score replies lower
].reduce((a, b) => a + b, 0);
return status;
});
return scored.sort(function(a, b) {
return ((a._score > b._score) ? -1 : ((a._score < b._score) ? 1 : 0));
});
},
today() {
const now = new Date().toLocaleString('en-GB', {
timeZone: 'America/Vancouver',
hour12: false,
dateStyle: 'short',
});
const year = now.slice(6, 10);
const month = now.slice(3, 5);
const day = now.slice(0, 2);
const tzOffset = new Date().toLocaleString('en-US', {
timeZone: 'America/Vancouver',
timeZoneName: 'longOffset',
}).slice(-6);
return {
startOfDay: new Date(`${year}-${month}-${day}T00:00:00${tzOffset}`),
endOfDay: new Date(`${year}-${month}-${day}T23:59:59${tzOffset}`),
};
}
};