-
Notifications
You must be signed in to change notification settings - Fork 4
/
index.ts
136 lines (123 loc) · 4.01 KB
/
index.ts
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { BskyAgent, AtpSessionEvent, AtpSessionData, RichText } from '@atproto/api';
import cron from 'node-cron';
import boxen from 'boxen';
import { config } from 'dotenv';
import colors from 'colors';
import { heartIcon, shareIcon, replyIcon, wait } from './utils';
import { agent, login } from './auth';
import { db } from './db';
import { Notification } from '@atproto/api/dist/client/types/app/bsky/notification/listNotifications';
import { makeANiceThing } from './niceThingsToSay';
// import getTopUsers from './topUsers';
let savedSessionData: AtpSessionData;
config();
async function getTimeline() {
console.log(`Getting timeline...`);
const timeline = await agent.getTimeline({
limit: 25
});
if (!timeline.data?.feed) {
console.log('No timeline data');
return;
}
timeline.data.feed.forEach(function ({ post, reply }) {
const replyTo = reply ? colors.dim(`↩ @${reply?.parent.author.handle}`) : '';
const stats = `${replyIcon} ${post.replyCount} ${shareIcon} ${post.repostCount} ${heartIcon} ${post.likeCount}`;
const handle = colors.bgYellow(`@${post.author.handle}`);
const content = colors.white(post.record.text);
const sky = `${content}
${stats}
`;
const box = boxen(sky, {
title: `${handle} ${replyTo}`,
titleAlignment: 'center',
padding: 1,
borderStyle: 'double',
});
console.log(box);
});
}
async function post() {
const rt = new RichText({ text: 'Hello from the Bluesky API. Code written by @wesbos.bsky.social' })
await rt.detectFacets(agent) // automatically detects mentions and links
const postRecord = {
$type: 'app.bsky.feed.post',
text: rt.text,
facets: rt.facets,
createdAt: new Date().toISOString()
}
const res = await agent.app.bsky.feed.post.create({
repo: agent.session?.did,
}, postRecord);
console.log(res);
}
const dids = {
wesboscom: 'did:plc:etdjdgnly5tz5l5xdd4jq76d',
wesbsky: 'did:plc:aazhmzwhlizrj353fza2w6f2'
}
async function reply(notification: Notification) {
console.log(`🔥 Replying to @${notification.author.handle} because they ${notification.reason}`);
const text = makeANiceThing(notification.reason);
const rt = new RichText({ text })
await rt.detectFacets(agent);
const post = {
$type: 'app.bsky.feed.post',
createdAt: new Date().toISOString(),
text: rt.text,
facets: rt.facets,
reply: {
root: {
cid: notification.cid,
uri: notification.uri
},
parent: {
cid: notification.cid,
uri: notification.uri
},
}
};
// return;
const res = await agent.app.bsky.feed.post.create({
repo: agent.session?.did,
}, post);
return res;
}
async function checkForNewMentions() {
console.log('Running', new Date().toLocaleString());
const response = await agent.listNotifications();
const replies = response.data.notifications
// Filter for only replies
.filter((notification) => notification.reason === 'mention')
// Filter for replies that don't include my other handle @wesbos.com
.filter((notification) => {
const mentionsWes = notification.record.facets?.find(facet => facet.features.at(0).did === dids.wesboscom);
return !mentionsWes;
});
const follows = response.data.notifications.filter((notification) => notification.reason === 'follow');
for (const notification of [...follows, ...replies]) {
const { cid, reason, record, authot } = notification;
const key = `${reason}-${cid}`;
const existing = await db.get(key);
if (existing) {
// console.log(`👋 Already notified: ${reason} from ${notification.author.handle}`);
continue;
}
// Reply to them
await reply(notification);
// Save them as replies to
db.put(key, true);
// Wait 100ms
await wait(100);
};
// Loop over each notification and deal with the reason: 'mention' and 'follow'
}
async function go() {
await login();
cron.schedule('*/15 * * * * *', async () => {
await checkForNewMentions();
});
// await getTimeline();
// await post();
}
go();
export { }