1
1
import AwaitLock from "await-lock" ;
2
2
import chalk from "chalk" ;
3
- import { EventEmitter } from "events" ;
4
3
import { isLeft } from "fp-ts/lib/Either" ;
5
4
import { Type } from "io-ts" ;
6
5
import { PathReporter } from "io-ts/lib/PathReporter" ;
@@ -16,14 +15,22 @@ import {
16
15
Response ,
17
16
} from "puppeteer" ;
18
17
import * as winston from "winston" ;
19
- import { IPlugin , IPluginContext } from "../../plugins" ;
18
+ import {
19
+ AsyncPluginEvents ,
20
+ AsyncPluginEventsType ,
21
+ IPlugin ,
22
+ IPluginContext ,
23
+ PluginEventsType ,
24
+ SyncPluginEvents ,
25
+ SyncPluginEventsType ,
26
+ } from "../../plugins" ;
20
27
import { IOptions } from "./api" ;
21
28
import { PostIdSet } from "./postIdSet" ;
22
29
23
30
/**
24
31
* Instagram API wrapper
25
32
*/
26
- export class Instagram < PostType > extends EventEmitter {
33
+ export class Instagram < PostType > {
27
34
/**
28
35
* Apply defaults to undefined options
29
36
*/
@@ -153,6 +160,25 @@ export class Instagram<PostType> extends EventEmitter {
153
160
// Location of chromium / chrome binary executable
154
161
private readonly executablePath : string ;
155
162
163
+ // Plugins to be run
164
+ private pluginFunctions : {
165
+ [ key in keyof typeof AsyncPluginEvents ] : Array <
166
+ ( ...args : any [ ] ) => Promise < void >
167
+ > ;
168
+ } &
169
+ {
170
+ [ key in keyof typeof SyncPluginEvents ] : Array <
171
+ ( ...args : any [ ] ) => void
172
+ > ;
173
+ } = {
174
+ browser : [ ] ,
175
+ construction : [ ] ,
176
+ grafting : [ ] ,
177
+ postPage : [ ] ,
178
+ request : [ ] ,
179
+ response : [ ] ,
180
+ } ;
181
+
156
182
/**
157
183
* Create API wrapper instance
158
184
* @param endpoint the url for the type of resource to scrape
@@ -170,7 +196,6 @@ export class Instagram<PostType> extends EventEmitter {
170
196
options : IOptions = { } ,
171
197
validator : Type < unknown > ,
172
198
) {
173
- super ( ) ;
174
199
this . id = id ;
175
200
this . postIds = new PostIdSet ( ) ;
176
201
this . url = endpoint . replace ( "[id]" , id ) ;
@@ -192,7 +217,7 @@ export class Instagram<PostType> extends EventEmitter {
192
217
this . validator = options . validator || validator ;
193
218
194
219
this . addPlugins ( options [ "plugins" ] ) ;
195
- this . emit ( "construction" ) ;
220
+ this . executePlugins ( "construction" ) ;
196
221
}
197
222
198
223
/**
@@ -268,6 +293,7 @@ export class Instagram<PostType> extends EventEmitter {
268
293
public async start ( ) {
269
294
// Build page and visit url
270
295
await this . constructPage ( ) ;
296
+ await this . executePlugins ( "browser" ) ;
271
297
272
298
this . started = true ;
273
299
@@ -358,7 +384,7 @@ export class Instagram<PostType> extends EventEmitter {
358
384
headers : this . graftHeaders ,
359
385
url : this . graftURL ,
360
386
} ;
361
- this . emit ( "request" , req , overrides ) ;
387
+ await this . executePlugins ( "request" , req , overrides ) ;
362
388
await req . continue ( overrides ) ;
363
389
364
390
// Reset grafting data
@@ -372,7 +398,7 @@ export class Instagram<PostType> extends EventEmitter {
372
398
break ;
373
399
} else {
374
400
const overrides = { } ;
375
- this . emit ( "request" , req , overrides ) ;
401
+ this . executePlugins ( "request" , req , overrides ) ;
376
402
await req . continue ( overrides ) ;
377
403
}
378
404
}
@@ -410,7 +436,7 @@ export class Instagram<PostType> extends EventEmitter {
410
436
}
411
437
412
438
// Emit event
413
- this . emit ( "response" , res , data ) ;
439
+ this . executePlugins ( "response" , res , data ) ;
414
440
415
441
// Check for rate limiting
416
442
if ( data && "status" in data && data [ "status" ] === "fail" ) {
@@ -519,7 +545,7 @@ export class Instagram<PostType> extends EventEmitter {
519
545
if ( ! parsed ) {
520
546
return ;
521
547
}
522
- this . emit ( "postPage" , parsed ) ;
548
+ await this . executePlugins ( "postPage" , parsed ) ;
523
549
await this . addToPostBuffer ( parsed ) ;
524
550
}
525
551
@@ -841,7 +867,7 @@ export class Instagram<PostType> extends EventEmitter {
841
867
842
868
await this . progress ( Progress . GRAFTING ) ;
843
869
844
- this . emit ( "grafting" ) ;
870
+ this . executePlugins ( "grafting" ) ;
845
871
846
872
// Enable grafting
847
873
this . graft = true ;
@@ -886,28 +912,39 @@ export class Instagram<PostType> extends EventEmitter {
886
912
return ;
887
913
}
888
914
889
- const events = [
890
- "construction" ,
891
- "request" ,
892
- "response" ,
893
- "postPage" ,
894
- "grafting" ,
895
- ] ;
896
-
897
915
for ( const plugin of plugins ) {
898
- for ( const event of events ) {
916
+ for ( const event of Object . keys ( this . pluginFunctions ) ) {
899
917
const pluginEvent = plugin [ event + "Event" ] ;
900
918
if ( pluginEvent ) {
901
919
const context : IPluginContext < typeof plugin , PostType > = {
902
920
plugin,
903
921
state : this ,
904
922
} ;
905
923
906
- this . on ( event , pluginEvent . bind ( context ) ) ;
924
+ this . pluginFunctions [ event ] . push ( pluginEvent . bind ( context ) ) ;
907
925
}
908
926
}
909
927
}
910
928
}
929
+
930
+ private executePlugins ( event : SyncPluginEventsType , ...args ) : void ;
931
+ private executePlugins (
932
+ event : AsyncPluginEventsType ,
933
+ ...args
934
+ ) : Promise < unknown > ;
935
+ private executePlugins ( event : PluginEventsType , ...args ) {
936
+ if ( event in SyncPluginEvents ) {
937
+ for ( const pluginFunction of this . pluginFunctions [ "construction" ] ) {
938
+ pluginFunction ( ) ;
939
+ }
940
+ return ;
941
+ }
942
+
943
+ // @ts -ignore
944
+ return Promise . all (
945
+ this . pluginFunctions [ event ] . map ( ( cb ) => cb ( ...args ) ) ,
946
+ ) ;
947
+ }
911
948
}
912
949
913
950
/**
0 commit comments