-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.ts
118 lines (98 loc) · 3.05 KB
/
main.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
import { load as loadEnv } from '@std/dotenv';
import type { ConversationsHistoryResponse } from 'npm:@slack/web-api';
import {
uniqueNamesGenerator,
adjectives,
colors,
animals,
} from 'npm:unique-names-generator';
import redis from './lib/redis.ts';
import { TwitterClient } from './lib/twitter.ts';
import { NostrClient } from './lib/nostr.ts';
import { channelId, slackClient } from './lib/slack.ts';
try {
await loadEnv({ export: true });
} catch (error) {
console.warn('Unable to load .env file:', error);
}
const socialClients = [new TwitterClient(), new NostrClient()];
for (const socialClient of socialClients) {
await socialClient.init();
}
async function resolveUserTags(text: string): Promise<string> {
const userTagRegex = /<@([A-Z0-9]+)>/g;
const userTags = text.match(userTagRegex) || [];
for (const tag of userTags) {
const userId = tag.match(/<@([A-Z0-9]+)>/)?.[1];
if (!userId) continue;
let userAlias = await redis.get(`user_alias:${userId}`);
if (!userAlias) {
userAlias = uniqueNamesGenerator({
dictionaries: [adjectives, colors, animals],
style: 'capital',
separator: ' ',
});
await redis.set(`user_alias:${userId}`, userAlias);
}
text = text.replace(tag, userAlias);
}
return text.replace(/\(at\)/g, '@');
}
async function pollAndPost() {
const lastTimestamp = (await redis.get('last_timestamp')) || '0';
const result = (await slackClient.conversations.history({
channel: channelId,
oldest: lastTimestamp,
limit: 1,
})) as ConversationsHistoryResponse;
if (!result.messages?.length) return;
const message = result.messages[0];
if (!message.ts) {
await redis.set('last_timestamp', parseFloat(lastTimestamp) + 1);
return;
}
if (
message.type !== 'message' ||
message.subtype !== undefined ||
!message.text
) {
await redis.set('last_timestamp', message.ts);
return;
}
const resolvedText = await resolveUserTags(message.text);
const results = await Promise.allSettled(
socialClients.map((client) => client.post(resolvedText))
);
const resultsText = results
.map((result, index) => {
if (result.status === 'rejected')
return `Failed posting to ${socialClients[index].name}: Redacted Error (see logs)`;
if (!result.value.success)
return `Failed posting to ${socialClients[index].name}: ${result.value.message}`;
return `Successfully posted to ${socialClients[index].name}: ${result.value.message}`;
})
.join('\n');
console.info(resultsText);
try {
await slackClient.chat.postMessage({
channel: channelId!,
thread_ts: message.ts,
text: resultsText,
});
} catch (error) {
console.error('Error reporting post status on Slack:', error);
}
await redis.set('last_timestamp', message.ts);
}
async function main() {
while (true) {
try {
await pollAndPost();
} catch (error) {
console.error('Error while polling:', error);
} finally {
await new Promise((resolve) => setTimeout(resolve, 5000));
}
}
}
main();