amplitude.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. const crypto = require('crypto');
  2. const fetch = require('node-fetch');
  3. const config = require('./config');
  4. const pkg = require('../package.json');
  5. const geoip = config.ip_db
  6. ? require('fxa-geodb')({ dbPath: config.ip_db })
  7. : () => ({});
  8. const HOUR = 1000 * 60 * 60;
  9. function truncateToHour(timestamp) {
  10. return Math.floor(timestamp / HOUR) * HOUR;
  11. }
  12. function orderOfMagnitude(n) {
  13. return Math.floor(Math.log10(n));
  14. }
  15. function userId(fileId, ownerId) {
  16. const hash = crypto.createHash('sha256');
  17. hash.update(fileId);
  18. hash.update(ownerId);
  19. return hash.digest('hex').substring(32);
  20. }
  21. function location(ip) {
  22. try {
  23. return geoip(ip);
  24. } catch (e) {
  25. return {};
  26. }
  27. }
  28. function statUploadEvent(data) {
  29. const loc = location(data.ip);
  30. const event = {
  31. session_id: -1,
  32. country: loc.country,
  33. region: loc.state,
  34. user_id: userId(data.id, data.owner),
  35. app_version: pkg.version,
  36. time: truncateToHour(Date.now()),
  37. event_type: 'server_upload',
  38. user_properties: {
  39. download_limit: data.dlimit,
  40. time_limit: data.timeLimit,
  41. size: orderOfMagnitude(data.size),
  42. anonymous: data.anonymous
  43. },
  44. event_properties: {
  45. agent: data.agent
  46. },
  47. event_id: 0
  48. };
  49. return sendBatch([event]);
  50. }
  51. function statDownloadEvent(data) {
  52. const loc = location(data.ip);
  53. const event = {
  54. session_id: -1,
  55. country: loc.country,
  56. region: loc.state,
  57. user_id: userId(data.id, data.owner),
  58. app_version: pkg.version,
  59. time: truncateToHour(Date.now()),
  60. event_type: 'server_download',
  61. event_properties: {
  62. agent: data.agent,
  63. download_count: data.download_count,
  64. ttl: data.ttl
  65. },
  66. event_id: data.download_count
  67. };
  68. return sendBatch([event]);
  69. }
  70. function statDeleteEvent(data) {
  71. const loc = location(data.ip);
  72. const event = {
  73. session_id: -1,
  74. country: loc.country,
  75. region: loc.state,
  76. user_id: userId(data.id, data.owner),
  77. app_version: pkg.version,
  78. time: truncateToHour(Date.now()),
  79. event_type: 'server_delete',
  80. event_properties: {
  81. agent: data.agent,
  82. download_count: data.download_count,
  83. ttl: data.ttl
  84. },
  85. event_id: data.download_count + 1
  86. };
  87. return sendBatch([event]);
  88. }
  89. function clientEvent(event, ua, language, session_id, deltaT, platform, ip) {
  90. const loc = location(ip);
  91. const ep = event.event_properties || {};
  92. const up = event.user_properties || {};
  93. const event_properties = {
  94. browser: ua.browser.name,
  95. browser_version: ua.browser.version,
  96. status: ep.status,
  97. age: ep.age,
  98. downloaded: ep.downloaded,
  99. download_limit: ep.download_limit,
  100. duration: ep.duration,
  101. entrypoint: ep.entrypoint,
  102. file_count: ep.file_count,
  103. password_protected: ep.password_protected,
  104. referrer: ep.referrer,
  105. size: ep.size,
  106. time_limit: ep.time_limit,
  107. trigger: ep.trigger,
  108. ttl: ep.ttl,
  109. utm_campaign: ep.utm_campaign,
  110. utm_content: ep.utm_content,
  111. utm_medium: ep.utm_medium,
  112. utm_source: ep.utm_source,
  113. utm_term: ep.utm_term,
  114. experiment: ep.experiment,
  115. variant: ep.variant
  116. };
  117. const user_properties = {
  118. active_count: up.active_count,
  119. anonymous: up.anonymous,
  120. experiments: up.experiments,
  121. first_action: up.first_action
  122. };
  123. return {
  124. app_version: pkg.version,
  125. country: loc.country,
  126. device_id: event.device_id,
  127. event_properties,
  128. event_type: event.event_type,
  129. language,
  130. os_name: ua.os.name,
  131. os_version: ua.os.version,
  132. platform,
  133. region: loc.state,
  134. session_id,
  135. time: event.time + deltaT,
  136. user_id: event.user_id,
  137. user_properties
  138. };
  139. }
  140. async function sendBatch(events, timeout = 1000) {
  141. if (!config.amplitude_id) {
  142. return 200;
  143. }
  144. try {
  145. const result = await fetch('https://api.amplitude.com/batch', {
  146. method: 'POST',
  147. headers: { 'Content-Type': 'application/json' },
  148. body: JSON.stringify({
  149. api_key: config.amplitude_id,
  150. events
  151. }),
  152. timeout
  153. });
  154. return result.status;
  155. } catch (e) {
  156. return 500;
  157. }
  158. }
  159. module.exports = {
  160. statUploadEvent,
  161. statDownloadEvent,
  162. statDeleteEvent,
  163. clientEvent,
  164. sendBatch
  165. };