@@ -2,8 +2,8 @@ import https from 'https';
22import fs from 'fs' ;
33
44// GitHub API configuration
5- const REPO = ' session-foundation/session-desktop' ;
6- const API_URL = `https://api.github.com/repos/${ REPO } /releases` ;
5+ const DESKTOP_API_URL = `https://api.github.com/repos/ session-foundation/session-desktop/releases` ;
6+ const ANDROID_API_URL = `https://api.github.com/repos/session-foundation/session-android /releases` ;
77
88// Types
99interface Asset {
@@ -17,7 +17,7 @@ interface Release {
1717 assets : Asset [ ] ;
1818}
1919
20- interface ReleaseStats {
20+ interface DesktopReleaseStats {
2121 version : string ;
2222 snapshotDate : string ;
2323 dateCaptured : string ;
@@ -90,10 +90,10 @@ function getCurrentDate(): string {
9090}
9191
9292// Main function
93- async function generateReleaseStatsCSV ( ) : Promise < void > {
93+ async function generateDesktopReleaseStatsCSV ( ) : Promise < void > {
9494 try {
9595 console . log ( 'Fetching releases from GitHub...' ) ;
96- const releases = await fetchJSON ( API_URL ) ;
96+ const releases = await fetchJSON ( DESKTOP_API_URL ) ;
9797
9898 // Take only the last 10 releases
9999 const last10Releases = releases . slice ( 0 , 10 ) ;
@@ -113,7 +113,7 @@ async function generateReleaseStatsCSV(): Promise<void> {
113113
114114 // Data rows
115115 for ( const release of last10Releases ) {
116- const stats : ReleaseStats = {
116+ const stats : DesktopReleaseStats = {
117117 version : release . tag_name . replace ( / ^ v / , '' ) , // Remove 'v' prefix
118118 snapshotDate : snapshotDate ,
119119 dateCaptured : release . published_at . split ( 'T' ) [ 0 ] , // Get YYYY-MM-DD
@@ -174,5 +174,164 @@ async function generateReleaseStatsCSV(): Promise<void> {
174174 }
175175}
176176
177- // Run the script
178- generateReleaseStatsCSV ( ) ;
177+ // Android-specific types
178+ interface AndroidReleaseStats {
179+ version : string ;
180+ snapshotDate : string ;
181+ dateCaptured : string ;
182+ aabDownloads : number ;
183+ apkArm64Downloads : number ;
184+ apkArmv7aDownloads : number ;
185+ apkUniversalHuaweiDownloads : number ;
186+ apkUniversalPlayDownloads : number ;
187+ apkX86Downloads : number ;
188+ apkX86_64Downloads : number ;
189+ }
190+
191+ // Helper function to count downloads for Android APKs with specific architecture
192+ function countAndroidDownloadsByPattern (
193+ assets : any [ ] ,
194+ extension : string ,
195+ architecture : string ,
196+ buildType : string = 'play-release'
197+ ) : number {
198+ return assets
199+ . filter (
200+ ( asset ) =>
201+ asset . name . endsWith ( extension ) &&
202+ asset . name . includes ( architecture ) &&
203+ asset . name . includes ( buildType )
204+ )
205+ . reduce ( ( sum , asset ) => sum + asset . download_count , 0 ) ;
206+ }
207+
208+ // Helper function for AAB files
209+ function countAABDownloads ( assets : any [ ] ) : number {
210+ return assets
211+ . filter (
212+ ( asset ) =>
213+ asset . name . endsWith ( '.aab' ) && asset . name . includes ( 'play-release' )
214+ )
215+ . reduce ( ( sum , asset ) => sum + asset . download_count , 0 ) ;
216+ }
217+
218+ // Helper function for universal APKs
219+ function countUniversalAPKDownloads (
220+ assets : any [ ] ,
221+ storeType : 'play' | 'huawei'
222+ ) : number {
223+ return assets
224+ . filter (
225+ ( asset ) =>
226+ asset . name . endsWith ( '.apk' ) &&
227+ asset . name . includes ( 'universal' ) &&
228+ asset . name . includes ( `${ storeType } -release` )
229+ )
230+ . reduce ( ( sum , asset ) => sum + asset . download_count , 0 ) ;
231+ }
232+
233+ // Helper function to count downloads for x86 (excluding x86_64)
234+ function countX86Downloads ( assets : any [ ] ) : number {
235+ return assets
236+ . filter (
237+ ( asset ) =>
238+ asset . name . endsWith ( '.apk' ) &&
239+ asset . name . includes ( 'x86' ) &&
240+ ! asset . name . includes ( 'x86_64' ) && // Explicitly exclude x86_64
241+ asset . name . includes ( 'play-release' )
242+ )
243+ . reduce ( ( sum , asset ) => sum + asset . download_count , 0 ) ;
244+ }
245+
246+ // Main function for Android releases
247+ async function generateAndroidReleaseStatsCSV ( ) : Promise < void > {
248+ try {
249+ console . log ( 'Fetching releases from GitHub...' ) ;
250+ const releases = await fetchJSON ( ANDROID_API_URL ) ;
251+
252+ // Take only the last 10 releases
253+ const last10Releases = releases . slice ( 0 , 10 ) ;
254+
255+ console . log ( `Processing ${ last10Releases . length } releases...` ) ;
256+
257+ const snapshotDate = getCurrentDate ( ) ;
258+ console . log ( `Snapshot date: ${ snapshotDate } ` ) ;
259+
260+ // Build CSV data
261+ const csvRows : string [ ] = [ ] ;
262+
263+ // Header row
264+ csvRows . push (
265+ 'version,snapshot_date,release_date,.aab,.apk_arm64,.apk_armv7a,.apk_universal_huawei,.apk_universal_play,.apk_x86,.apk_x86_64'
266+ ) ;
267+
268+ // Data rows
269+ for ( const release of last10Releases ) {
270+ const stats : AndroidReleaseStats = {
271+ version : release . tag_name . replace ( / ^ v / , '' ) ,
272+ snapshotDate : snapshotDate ,
273+ dateCaptured : release . published_at . split ( 'T' ) [ 0 ] ,
274+ aabDownloads : countAABDownloads ( release . assets ) ,
275+ apkArm64Downloads : countAndroidDownloadsByPattern (
276+ release . assets ,
277+ '.apk' ,
278+ 'arm64-v8a'
279+ ) ,
280+ apkArmv7aDownloads : countAndroidDownloadsByPattern (
281+ release . assets ,
282+ '.apk' ,
283+ 'armeabi-v7a'
284+ ) ,
285+ apkUniversalHuaweiDownloads : countUniversalAPKDownloads (
286+ release . assets ,
287+ 'huawei'
288+ ) ,
289+ apkUniversalPlayDownloads : countUniversalAPKDownloads (
290+ release . assets ,
291+ 'play'
292+ ) ,
293+ apkX86Downloads : countX86Downloads ( release . assets ) , // Use the dedicated function
294+ apkX86_64Downloads : countAndroidDownloadsByPattern (
295+ release . assets ,
296+ '.apk' ,
297+ 'x86_64'
298+ ) ,
299+ } ;
300+
301+ csvRows . push (
302+ [
303+ stats . version ,
304+ stats . snapshotDate ,
305+ stats . dateCaptured ,
306+ stats . aabDownloads ,
307+ stats . apkArm64Downloads ,
308+ stats . apkArmv7aDownloads ,
309+ stats . apkUniversalHuaweiDownloads ,
310+ stats . apkUniversalPlayDownloads ,
311+ stats . apkX86Downloads ,
312+ stats . apkX86_64Downloads ,
313+ ] . join ( ',' )
314+ ) ;
315+ }
316+
317+ // Write to file
318+ const csvContent = csvRows . join ( '\n' ) ;
319+ const filename = 'session-android-release-stats.csv' ;
320+
321+ fs . writeFileSync ( filename , csvContent ) ;
322+
323+ console . log ( `\nCSV file generated: ${ filename } ` ) ;
324+ console . log ( `Total releases processed: ${ last10Releases . length } ` ) ;
325+ console . log ( '\nFull content:' ) ;
326+ console . log ( csvRows . join ( '\n' ) ) ;
327+ } catch ( error ) {
328+ console . error (
329+ 'Error:' ,
330+ error instanceof Error ? error . message : 'Unknown error'
331+ ) ;
332+ process . exit ( 1 ) ;
333+ }
334+ }
335+
336+ generateDesktopReleaseStatsCSV ( ) ;
337+ generateAndroidReleaseStatsCSV ( ) ;
0 commit comments