17
17
18
18
'use strict' ;
19
19
20
- const { writeFile, mkdir} = require ( 'fs' ) . promises ;
20
+ const { loadImage} = require ( 'canvas' ) ;
21
+ const { writeFile, mkdir, rmdir} = require ( 'fs' ) . promises ;
21
22
const { resolve} = require ( 'path' ) ;
22
23
const debug = require ( 'debug' ) ( 'mocha:docs:data:supporters' ) ;
23
24
const needle = require ( 'needle' ) ;
24
- const imageSize = require ( 'image-size' ) ;
25
25
const blocklist = new Set ( require ( './blocklist.json' ) ) ;
26
26
27
27
/**
@@ -36,7 +36,12 @@ const BLOCKED_STRINGS = /(?:vpn|[ck]a[sz]ino|seo|slots|gambl(?:e|ing)|crypto)/i;
36
36
*/
37
37
const API_ENDPOINT = 'https://api.opencollective.com/graphql/v2' ;
38
38
39
- const query = `query account($limit: Int, $offset: Int, $slug: String) {
39
+ const SPONSOR_TIER = 'sponsor' ;
40
+ const BACKER_TIER = 'backer' ;
41
+
42
+ const SUPPORTER_IMAGE_PATH = resolve ( __dirname , '../images/supporters' ) ;
43
+
44
+ const SUPPORTER_QUERY = `query account($limit: Int, $offset: Int, $slug: String) {
40
45
account(slug: $slug) {
41
46
orders(limit: $limit, offset: $offset) {
42
47
limit
@@ -61,7 +66,9 @@ const query = `query account($limit: Int, $offset: Int, $slug: String) {
61
66
}
62
67
}` ;
63
68
64
- const graphqlPageSize = 1000 ;
69
+ const GRAPHQL_PAGE_SIZE = 1000 ;
70
+
71
+ const invalidSupporters = [ ] ;
65
72
66
73
const nodeToSupporter = node => ( {
67
74
id : node . fromAccount . id ,
@@ -75,6 +82,30 @@ const nodeToSupporter = node => ({
75
82
type : node . fromAccount . type
76
83
} ) ;
77
84
85
+ const fetchImage = async supporter => {
86
+ try {
87
+ const { avatar : url } = supporter ;
88
+ const { body : imageBuf } = await needle ( 'get' , url ) ;
89
+ debug ( 'fetched %s' , url ) ;
90
+ const canvasImage = await loadImage ( imageBuf ) ;
91
+ debug ( 'ok %s' , url ) ;
92
+ supporter . dimensions = {
93
+ width : canvasImage . width ,
94
+ height : canvasImage . height
95
+ } ;
96
+ debug ( 'dimensions %s %dw %dh' , url , canvasImage . width , canvasImage . height ) ;
97
+ const filePath = resolve ( SUPPORTER_IMAGE_PATH , supporter . id + '.png' ) ;
98
+ await writeFile ( filePath , imageBuf ) ;
99
+ debug ( 'wrote %s' , filePath ) ;
100
+ } catch ( err ) {
101
+ console . error (
102
+ `failed to load ${ supporter . avatar } ; will discard ${ supporter . tier } "${ supporter . name } (${ supporter . slug } ). reason:\n` ,
103
+ err
104
+ ) ;
105
+ invalidSupporters . push ( supporter ) ;
106
+ }
107
+ } ;
108
+
78
109
/**
79
110
* Retrieves donation data from OC
80
111
*
@@ -84,26 +115,26 @@ const nodeToSupporter = node => ({
84
115
*/
85
116
const getAllOrders = async ( slug = 'mochajs' ) => {
86
117
let allOrders = [ ] ;
87
- const variables = { limit : graphqlPageSize , offset : 0 , slug} ;
118
+ const variables = { limit : GRAPHQL_PAGE_SIZE , offset : 0 , slug} ;
88
119
89
120
// Handling pagination if necessary (2 pages for ~1400 results in May 2019)
90
121
while ( true ) {
91
122
const result = await needle (
92
123
'post' ,
93
124
API_ENDPOINT ,
94
- { query, variables} ,
125
+ { query : SUPPORTER_QUERY , variables} ,
95
126
{ json : true }
96
127
) ;
97
128
const orders = result . body . data . account . orders . nodes ;
98
129
allOrders = [ ...allOrders , ...orders ] ;
99
- variables . offset += graphqlPageSize ;
100
- if ( orders . length < graphqlPageSize ) {
130
+ variables . offset += GRAPHQL_PAGE_SIZE ;
131
+ if ( orders . length < GRAPHQL_PAGE_SIZE ) {
101
132
debug ( 'retrieved %d orders' , allOrders . length ) ;
102
133
return allOrders ;
103
134
} else {
104
135
debug (
105
136
'loading page %d of orders...' ,
106
- Math . floor ( variables . offset / graphqlPageSize )
137
+ Math . floor ( variables . offset / GRAPHQL_PAGE_SIZE )
107
138
) ;
108
139
}
109
140
}
@@ -143,7 +174,8 @@ const getSupporters = async () => {
143
174
...supporters . backers ,
144
175
{
145
176
...supporter ,
146
- avatar : encodeURI ( supporter . imgUrlSmall )
177
+ avatar : encodeURI ( supporter . imgUrlSmall ) ,
178
+ tier : BACKER_TIER
147
179
}
148
180
] ;
149
181
}
@@ -152,7 +184,8 @@ const getSupporters = async () => {
152
184
...supporters . sponsors ,
153
185
{
154
186
...supporter ,
155
- avatar : encodeURI ( supporter . imgUrlMed )
187
+ avatar : encodeURI ( supporter . imgUrlMed ) ,
188
+ tier : SPONSOR_TIER
156
189
}
157
190
] ;
158
191
}
@@ -164,38 +197,34 @@ const getSupporters = async () => {
164
197
}
165
198
) ;
166
199
167
- const supporterImagePath = resolve ( __dirname , '../images/supporters' ) ;
168
-
169
- await mkdir ( supporterImagePath , { recursive : true } ) ;
200
+ await rmdir ( SUPPORTER_IMAGE_PATH , { recursive : true } ) ;
201
+ debug ( 'blasted %s' , SUPPORTER_IMAGE_PATH ) ;
202
+ await mkdir ( SUPPORTER_IMAGE_PATH , { recursive : true } ) ;
203
+ debug ( 'created %s' , SUPPORTER_IMAGE_PATH ) ;
170
204
171
205
// Fetch images for sponsors and save their image dimensions
172
- await Promise . all (
173
- supporters . sponsors . map ( async sponsor => {
174
- const filePath = resolve ( supporterImagePath , `${ sponsor . id } .png` ) ;
175
- const { body} = await needle ( 'get' , sponsor . avatar ) ;
176
- sponsor . dimensions = imageSize ( body ) ;
177
- await writeFile ( filePath , body ) ;
178
- } )
179
- ) ;
180
-
181
- // Fetch images for backers and save their image dimensions
182
- await Promise . all (
183
- supporters . backers . map ( async backer => {
184
- const filePath = resolve ( supporterImagePath , `${ backer . id } .png` ) ;
185
- const { body} = await needle ( 'get' , backer . avatar ) ;
186
- await writeFile ( filePath , body ) ;
187
- } )
188
- ) ;
206
+ await Promise . all ( [
207
+ ...supporters . sponsors . map ( fetchImage ) ,
208
+ ...supporters . backers . map ( fetchImage )
209
+ ] ) ;
210
+
211
+ invalidSupporters . forEach ( supporter => {
212
+ supporters [ supporter . tier ] . splice (
213
+ supporters [ supporter . tier ] . indexOf ( supporter ) ,
214
+ 1
215
+ ) ;
216
+ } ) ;
189
217
190
218
const backerCount = supporters . backers . length ;
191
219
const sponsorCount = supporters . sponsors . length ;
192
220
const totalValidSupportersCount = backerCount + sponsorCount ;
193
221
194
222
debug (
195
- 'found %d valid backers and %d valid sponsors (of %d total; %d blocked)' ,
223
+ 'found %d valid backers and %d valid sponsors (%d total; %d invalid ; %d blocked)' ,
196
224
backerCount ,
197
225
sponsorCount ,
198
226
totalValidSupportersCount ,
227
+ invalidSupporters . length ,
199
228
uniqueSupporters . size - totalValidSupportersCount
200
229
) ;
201
230
return supporters ;
0 commit comments