33 * From: https://github.com/kaicataldo/discord-transcript-generator (npm package: discord-transcript-generator)
44 * Licensed under MIT
55 */
6- ' use strict' ;
6+ " use strict" ;
77
88/** @import { Message, Channel } from "discord.js" */
99
10- const fs = require ( ' node:fs' ) . promises ;
11- const path = require ( ' node:path' ) ;
12- const { Client, GatewayIntentBits, Partials } = require ( ' discord.js' ) ;
10+ const fs = require ( " node:fs" ) . promises ;
11+ const path = require ( " node:path" ) ;
12+ const { Client, GatewayIntentBits, Partials } = require ( " discord.js" ) ;
1313
1414/**
1515 * Converts a date string representation to an UTC date offset.
1616 * @param {string } dateString String representation of the string
1717 * @returns {number } UTC date offset
1818 */
1919function getUTCDate ( dateString ) {
20- const dateInstance = new Date ( dateString ) ;
20+ const dateInstance = new Date ( dateString ) ;
2121
22- return Date . UTC (
23- dateInstance . getYear ( ) ,
24- dateInstance . getMonth ( ) ,
25- dateInstance . getDate ( ) ,
26- ) ;
22+ return Date . UTC (
23+ dateInstance . getYear ( ) ,
24+ dateInstance . getMonth ( ) ,
25+ dateInstance . getDate ( ) ,
26+ ) ;
2727}
2828
2929/**
@@ -33,8 +33,8 @@ function getUTCDate(dateString) {
3333 * @returns {boolean } True iff message created on date
3434 */
3535function messageMatchesDate ( message , date ) {
36- // Ensure that comparisons are done using UTC.
37- return getUTCDate ( date ) === getUTCDate ( message . createdTimestamp ) ;
36+ // Ensure that comparisons are done using UTC.
37+ return getUTCDate ( date ) === getUTCDate ( message . createdTimestamp ) ;
3838}
3939
4040/**
@@ -45,36 +45,38 @@ function messageMatchesDate(message, date) {
4545 * @returns {Promise<string> } Generated transcript
4646 */
4747async function generateContent ( messages , date , name ) {
48- const generatedMessages = (
49- await Promise . all (
50- messages . map ( async message => {
51- let content = `**${ message . author . username } :** ${ message . content } ` ;
52-
53- if ( message . reactions . cache . size ) {
54- const reactions = (
55- await Promise . all (
56- Array . from ( message . reactions . cache . entries ( ) ) . map (
57- async ( [ emoji , { users } ] ) => {
58- const reaction = await users . fetch ( ) ;
59- return ` * ${ emoji } ${ Array . from ( reaction . values ( ) )
60- . map ( ( { username } ) => `@${ username } ` )
61- . join ( ', ' ) } `;
62- } ,
63- ) ,
64- )
65- ) . join ( '\n' ) ;
66-
67- content += `\n${ reactions } ` ;
68- }
69-
70- return content ;
71- } ) ,
72- )
73- ) . join ( '\n\n' ) ;
74-
75- return `# ${ date } ${
76- name ? `${ name } ` : ''
77- } Transcript\n\n${ generatedMessages } \n`;
48+ const generatedMessages = (
49+ await Promise . all (
50+ messages . map ( async message => {
51+ let content = `**${ message . author . username } :** ${ message . content } ` ;
52+
53+ if ( message . reactions . cache . size ) {
54+ const reactions = (
55+ await Promise . all (
56+ Array . from ( message . reactions . cache . entries ( ) ) . map (
57+ async ( [ emoji , { users } ] ) => {
58+ const reaction = await users . fetch ( ) ;
59+ return ` * ${ emoji } ${ Array . from (
60+ reaction . values ( ) ,
61+ )
62+ . map ( ( { username } ) => `@${ username } ` )
63+ . join ( ", " ) } `;
64+ } ,
65+ ) ,
66+ )
67+ ) . join ( "\n" ) ;
68+
69+ content += `\n${ reactions } ` ;
70+ }
71+
72+ return content ;
73+ } ) ,
74+ )
75+ ) . join ( "\n\n" ) ;
76+
77+ return `# ${ date } ${
78+ name ? `${ name } ` : ""
79+ } Transcript\n\n${ generatedMessages } \n`;
7880}
7981
8082/**
@@ -84,9 +86,9 @@ async function generateContent(messages, date, name) {
8486 * @returns {Message[] } Sorted by created timestamp
8587 */
8688function getTranscriptMessages ( messages , date ) {
87- return messages
88- . filter ( message => messageMatchesDate ( message , date ) )
89- . sort ( ( a , b ) => a . createdTimestamp - b . createdTimestamp ) ;
89+ return messages
90+ . filter ( message => messageMatchesDate ( message , date ) )
91+ . sort ( ( a , b ) => a . createdTimestamp - b . createdTimestamp ) ;
9092}
9193
9294/**
@@ -96,35 +98,35 @@ function getTranscriptMessages(messages, date) {
9698 * @returns {Promise<Message[]> } Fetched messages
9799 */
98100async function fetchMessages ( channel , date ) {
99- let messages = [ ] ;
100-
101- // Discord's API limits fetching messages to 50 at a time. Continue requesting batches
102- // until we either have no messages or find a message from a previous date.
103- while ( true ) {
104- const batch = Array . from (
105- await channel . messages . fetch (
106- messages . length ? { before : messages [ 0 ] . id } : void 0 ,
107- )
108- ) ;
109-
110- if ( ! batch . length ) {
111- break ;
112- }
113-
114- messages = [ ...getTranscriptMessages ( batch , date ) , ...messages ] ;
115-
116- if ( ! messageMatchesDate ( batch . at ( - 1 ) , date ) ) {
117- break ;
118- }
119- }
120-
121- return messages . map ( message => {
122- message . content = message . content . replace (
123- / < @ ! ? ( \d + ) > / gu,
124- ( match , p1 ) => `@${ channel . client . users . cache . get ( p1 ) . username } ` ,
125- ) ;
126- return message ;
127- } ) ;
101+ let messages = [ ] ;
102+
103+ // Discord's API limits fetching messages to 50 at a time. Continue requesting batches
104+ // until we either have no messages or find a message from a previous date.
105+ while ( true ) {
106+ const batch = Array . from (
107+ await channel . messages . fetch (
108+ messages . length ? { before : messages [ 0 ] . id } : void 0 ,
109+ ) ,
110+ ) ;
111+
112+ if ( ! batch . length ) {
113+ break ;
114+ }
115+
116+ messages = [ ...getTranscriptMessages ( batch , date ) , ...messages ] ;
117+
118+ if ( ! messageMatchesDate ( batch . at ( - 1 ) , date ) ) {
119+ break ;
120+ }
121+ }
122+
123+ return messages . map ( message => {
124+ message . content = message . content . replace (
125+ / < @ ! ? ( \d + ) > / gu,
126+ ( match , p1 ) => `@${ channel . client . users . cache . get ( p1 ) . username } ` ,
127+ ) ;
128+ return message ;
129+ } ) ;
128130}
129131
130132/**
@@ -139,42 +141,45 @@ async function fetchMessages(channel, date) {
139141 * @returns {Promise<void> }
140142 */
141143module . exports = async function generateTranscript ( {
142- token,
143- id,
144- date,
145- output,
146- name = null ,
144+ token,
145+ id,
146+ date,
147+ output,
148+ name = null ,
147149} ) {
148- const client = new Client ( { intents : [ GatewayIntentBits . MessageContent ] , partials : [ Partials . Channel ] } ) ;
149- const transcriptPath = path . resolve ( process . cwd ( ) , output ) ;
150-
151- try {
152- // discord.js provides an events-based API. Promise.all() allows
153- // us to wrap the entire login/message fetching flow in a Promise by registering
154- // the event handler, kicking off the client login, and awaiting both promises.
155- await Promise . all ( [
156- new Promise ( ( resolve , reject ) => {
157- client . on ( 'clientReady' , async ( ) => {
158- try {
159- const channel = await client . channels . fetch ( id ) ;
160- const messages = await fetchMessages ( channel , date ) ;
161-
162- await fs . writeFile (
163- transcriptPath ,
164- await generateContent ( messages , date , name ) ,
165- ) ;
166- resolve ( ) ;
167- } catch ( e ) {
168- reject ( e ) ;
169- }
170- } ) ;
171- } ) ,
172- client . login ( token ) ,
173- ] ) ;
174- console . log (
175- `\nTranscript for channel ${ id } on ${ date } successfully written to ${ transcriptPath } .` ,
176- ) ;
177- } finally {
178- client . destroy ( ) ;
179- }
150+ const client = new Client ( {
151+ intents : [ GatewayIntentBits . MessageContent ] ,
152+ partials : [ Partials . Channel ] ,
153+ } ) ;
154+ const transcriptPath = path . resolve ( process . cwd ( ) , output ) ;
155+
156+ try {
157+ // discord.js provides an events-based API. Promise.all() allows
158+ // us to wrap the entire login/message fetching flow in a Promise by registering
159+ // the event handler, kicking off the client login, and awaiting both promises.
160+ await Promise . all ( [
161+ new Promise ( ( resolve , reject ) => {
162+ client . on ( "clientReady" , async ( ) => {
163+ try {
164+ const channel = await client . channels . fetch ( id ) ;
165+ const messages = await fetchMessages ( channel , date ) ;
166+
167+ await fs . writeFile (
168+ transcriptPath ,
169+ await generateContent ( messages , date , name ) ,
170+ ) ;
171+ resolve ( ) ;
172+ } catch ( e ) {
173+ reject ( e ) ;
174+ }
175+ } ) ;
176+ } ) ,
177+ client . login ( token ) ,
178+ ] ) ;
179+ console . log (
180+ `\nTranscript for channel ${ id } on ${ date } successfully written to ${ transcriptPath } .` ,
181+ ) ;
182+ } finally {
183+ client . destroy ( ) ;
184+ }
180185} ;
0 commit comments