Skip to content

Commit c5ada12

Browse files
authored
feat: summarize cool links youtube videos (#40)
1 parent f341bec commit c5ada12

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

src/cool-links-management.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { type Message, ThreadAutoArchiveDuration } from 'discord.js';
22
import ogs from 'open-graph-scraper';
3+
import { getVideoSummary } from './summarize-cool-videos';
34

45
const getThreadNameFromOpenGraph = async (url: string): Promise<string | null> => {
56
try {
@@ -24,6 +25,8 @@ const getThreadNameFromOpenGraph = async (url: string): Promise<string | null> =
2425
return null;
2526
};
2627

28+
const youtubeUrlRegex = new RegExp('^(https?)?(://)?(www.)?(m.)?((youtube.com)|(youtu.be))');
29+
2730
export const coolLinksManagement = async (message: Message) => {
2831
const urlRegex = /(((https?:\/\/)|(www\.))[^\s]+)/g;
2932
const detectedURLs = message.content.match(urlRegex);
@@ -36,9 +39,18 @@ export const coolLinksManagement = async (message: Message) => {
3639
await message.react('✅');
3740
await message.react('❌');
3841

39-
const threadName = await getThreadNameFromOpenGraph(detectedURLs[0]);
40-
await message.startThread({
42+
const url = detectedURLs[0];
43+
const threadName = await getThreadNameFromOpenGraph(url);
44+
const thread = await message.startThread({
4145
name: threadName ?? message.content,
4246
autoArchiveDuration: ThreadAutoArchiveDuration.ThreeDays,
4347
});
48+
if (thread.joinable) await thread.join();
49+
50+
if (youtubeUrlRegex.test(url)) {
51+
const summary = await getVideoSummary(url);
52+
if (!summary) return;
53+
54+
await thread.send(summary);
55+
}
4456
};

src/summarize-cool-videos.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
const baseUrl = 'https://www.summarize.tech/api/summary';
2+
3+
export const getVideoSummary = async (videoUrl: string) => {
4+
const summary = await fetch(baseUrl, {
5+
method: 'POST',
6+
body: JSON.stringify({ url: videoUrl, deviceId: makeId(21) }),
7+
headers: { 'content-type': 'application/json' },
8+
})
9+
.then((res) => res.json())
10+
.then((res) =>
11+
(Object.values((res as SummaryResponse).rollups) ?? [])
12+
.map((chunk) => chunk.summary)
13+
.join(' '),
14+
);
15+
16+
return summary;
17+
};
18+
19+
const makeId = (length: number) => {
20+
let result = '';
21+
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_';
22+
const charactersLength = characters.length;
23+
24+
for (let i = 0; i < length; i++)
25+
result += characters.charAt(Math.floor(Math.random() * charactersLength));
26+
27+
return result;
28+
};
29+
30+
// Example usage:
31+
// const videoUrl = 'https://www.youtube.com/watch?v=ruUlK6zRwS8';
32+
// const summary = await getVideoSummary(videoUrl);
33+
// console.log({ summary });
34+
35+
type SummaryResponse = {
36+
rollups: Record<number, SummaryChunk>;
37+
title: string;
38+
};
39+
40+
type SummaryChunk = {
41+
children: Record<number, string>;
42+
summary: string;
43+
};

0 commit comments

Comments
 (0)