adtekio_adnetworks 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +24 -0
  5. data/README.md +333 -0
  6. data/Rakefile +56 -0
  7. data/VERSION +1 -0
  8. data/adtekio_adnetworks.gemspec +297 -0
  9. data/lib/adtekio_adnetworks.rb +6 -0
  10. data/lib/adtekio_adnetworks/api_key_scrapers.rb +59 -0
  11. data/lib/adtekio_adnetworks/api_key_scrapers/adcolony.rb +20 -0
  12. data/lib/adtekio_adnetworks/api_key_scrapers/applift.rb +13 -0
  13. data/lib/adtekio_adnetworks/api_key_scrapers/applovin.rb +13 -0
  14. data/lib/adtekio_adnetworks/api_key_scrapers/chartboost.rb +18 -0
  15. data/lib/adtekio_adnetworks/api_key_scrapers/crossinstall.rb +13 -0
  16. data/lib/adtekio_adnetworks/api_key_scrapers/leadbolt.rb +18 -0
  17. data/lib/adtekio_adnetworks/api_key_scrapers/loopme.rb +12 -0
  18. data/lib/adtekio_adnetworks/api_key_scrapers/mdotm.rb +22 -0
  19. data/lib/adtekio_adnetworks/api_key_scrapers/revmob.rb +22 -0
  20. data/lib/adtekio_adnetworks/api_key_scrapers/tapjoy.rb +19 -0
  21. data/lib/adtekio_adnetworks/api_key_scrapers/unilead.rb +13 -0
  22. data/lib/adtekio_adnetworks/api_key_scrapers/vungle.rb +23 -0
  23. data/lib/adtekio_adnetworks/importers.rb +58 -0
  24. data/lib/adtekio_adnetworks/importers/cost/adcolony.rb +43 -0
  25. data/lib/adtekio_adnetworks/importers/cost/adquant.rb +68 -0
  26. data/lib/adtekio_adnetworks/importers/cost/appia.rb +47 -0
  27. data/lib/adtekio_adnetworks/importers/cost/applifier.rb +64 -0
  28. data/lib/adtekio_adnetworks/importers/cost/applift.rb +41 -0
  29. data/lib/adtekio_adnetworks/importers/cost/applovin.rb +52 -0
  30. data/lib/adtekio_adnetworks/importers/cost/bidmotion.rb +82 -0
  31. data/lib/adtekio_adnetworks/importers/cost/chartboost.rb +40 -0
  32. data/lib/adtekio_adnetworks/importers/cost/crossinstall.rb +34 -0
  33. data/lib/adtekio_adnetworks/importers/cost/facebook.rb +39 -0
  34. data/lib/adtekio_adnetworks/importers/cost/fractionalmedia.rb +104 -0
  35. data/lib/adtekio_adnetworks/importers/cost/fyber.rb +54 -0
  36. data/lib/adtekio_adnetworks/importers/cost/gamegenetics.rb +44 -0
  37. data/lib/adtekio_adnetworks/importers/cost/glispa.rb +59 -0
  38. data/lib/adtekio_adnetworks/importers/cost/googleadwords.rb +99 -0
  39. data/lib/adtekio_adnetworks/importers/cost/jampp.rb +57 -0
  40. data/lib/adtekio_adnetworks/importers/cost/leadbolt.rb +43 -0
  41. data/lib/adtekio_adnetworks/importers/cost/lifestreet.rb +49 -0
  42. data/lib/adtekio_adnetworks/importers/cost/loopme.rb +63 -0
  43. data/lib/adtekio_adnetworks/importers/cost/matomy.rb +65 -0
  44. data/lib/adtekio_adnetworks/importers/cost/mdotm.rb +69 -0
  45. data/lib/adtekio_adnetworks/importers/cost/mmg.rb +67 -0
  46. data/lib/adtekio_adnetworks/importers/cost/mnectar.rb +45 -0
  47. data/lib/adtekio_adnetworks/importers/cost/moboqo.rb +33 -0
  48. data/lib/adtekio_adnetworks/importers/cost/mobpartner.rb +46 -0
  49. data/lib/adtekio_adnetworks/importers/cost/nanigans.rb +114 -0
  50. data/lib/adtekio_adnetworks/importers/cost/revmob.rb +44 -0
  51. data/lib/adtekio_adnetworks/importers/cost/rtbmob.rb +48 -0
  52. data/lib/adtekio_adnetworks/importers/cost/startapp.rb +47 -0
  53. data/lib/adtekio_adnetworks/importers/cost/supersonic.rb +77 -0
  54. data/lib/adtekio_adnetworks/importers/cost/tapjoy.rb +42 -0
  55. data/lib/adtekio_adnetworks/importers/cost/tokenads.rb +46 -0
  56. data/lib/adtekio_adnetworks/importers/cost/unilead.rb +39 -0
  57. data/lib/adtekio_adnetworks/importers/cost/vungle.rb +58 -0
  58. data/lib/adtekio_adnetworks/importers/cost_import.rb +13 -0
  59. data/lib/adtekio_adnetworks/importers/revenue/adcolony.rb +67 -0
  60. data/lib/adtekio_adnetworks/importers/revenue/applifier.rb +55 -0
  61. data/lib/adtekio_adnetworks/importers/revenue/applovin.rb +58 -0
  62. data/lib/adtekio_adnetworks/importers/revenue/chartboost.rb +43 -0
  63. data/lib/adtekio_adnetworks/importers/revenue/flurry.rb +85 -0
  64. data/lib/adtekio_adnetworks/importers/revenue/fyber.rb +61 -0
  65. data/lib/adtekio_adnetworks/importers/revenue/hypr_mx.rb +69 -0
  66. data/lib/adtekio_adnetworks/importers/revenue/lifestreet.rb +59 -0
  67. data/lib/adtekio_adnetworks/importers/revenue/mdotm.rb +38 -0
  68. data/lib/adtekio_adnetworks/importers/revenue/mopub.rb +54 -0
  69. data/lib/adtekio_adnetworks/importers/revenue/nexage.rb +71 -0
  70. data/lib/adtekio_adnetworks/importers/revenue/supersonic.rb +73 -0
  71. data/lib/adtekio_adnetworks/importers/revenue/tapsense.rb +38 -0
  72. data/lib/adtekio_adnetworks/importers/revenue/trialpay.rb +41 -0
  73. data/lib/adtekio_adnetworks/importers/revenue/vungle.rb +75 -0
  74. data/lib/adtekio_adnetworks/importers/revenue_import.rb +27 -0
  75. data/lib/adtekio_adnetworks/postbacks.rb +193 -0
  76. data/lib/adtekio_adnetworks/postbacks/aarki.rb +17 -0
  77. data/lib/adtekio_adnetworks/postbacks/adaction.rb +18 -0
  78. data/lib/adtekio_adnetworks/postbacks/adcash.rb +19 -0
  79. data/lib/adtekio_adnetworks/postbacks/adcolony.rb +90 -0
  80. data/lib/adtekio_adnetworks/postbacks/adgorithms.rb +74 -0
  81. data/lib/adtekio_adnetworks/postbacks/adjapon_nend.rb +39 -0
  82. data/lib/adtekio_adnetworks/postbacks/adknowledge.rb +18 -0
  83. data/lib/adtekio_adnetworks/postbacks/admob.rb +17 -0
  84. data/lib/adtekio_adnetworks/postbacks/adp.rb +18 -0
  85. data/lib/adtekio_adnetworks/postbacks/adperio.rb +19 -0
  86. data/lib/adtekio_adnetworks/postbacks/adquant.rb +39 -0
  87. data/lib/adtekio_adnetworks/postbacks/adstract.rb +15 -0
  88. data/lib/adtekio_adnetworks/postbacks/adxperience.rb +16 -0
  89. data/lib/adtekio_adnetworks/postbacks/airpush.rb +17 -0
  90. data/lib/adtekio_adnetworks/postbacks/app_chocolate.rb +17 -0
  91. data/lib/adtekio_adnetworks/postbacks/appfload.rb +17 -0
  92. data/lib/adtekio_adnetworks/postbacks/appia.rb +18 -0
  93. data/lib/adtekio_adnetworks/postbacks/appintheair.rb +17 -0
  94. data/lib/adtekio_adnetworks/postbacks/applifier.rb +49 -0
  95. data/lib/adtekio_adnetworks/postbacks/applift.rb +88 -0
  96. data/lib/adtekio_adnetworks/postbacks/applovin.rb +127 -0
  97. data/lib/adtekio_adnetworks/postbacks/appnext.rb +17 -0
  98. data/lib/adtekio_adnetworks/postbacks/appredeem.rb +33 -0
  99. data/lib/adtekio_adnetworks/postbacks/appsfire.rb +19 -0
  100. data/lib/adtekio_adnetworks/postbacks/appturbo.rb +18 -0
  101. data/lib/adtekio_adnetworks/postbacks/apsalar.rb +21 -0
  102. data/lib/adtekio_adnetworks/postbacks/bee7.rb +17 -0
  103. data/lib/adtekio_adnetworks/postbacks/bidmotion.rb +80 -0
  104. data/lib/adtekio_adnetworks/postbacks/blindferretmedia.rb +17 -0
  105. data/lib/adtekio_adnetworks/postbacks/chartboost.rb +116 -0
  106. data/lib/adtekio_adnetworks/postbacks/cheetah.rb +32 -0
  107. data/lib/adtekio_adnetworks/postbacks/clickky.rb +30 -0
  108. data/lib/adtekio_adnetworks/postbacks/covus.rb +17 -0
  109. data/lib/adtekio_adnetworks/postbacks/crossinstall.rb +26 -0
  110. data/lib/adtekio_adnetworks/postbacks/cyberagent_ameba.rb +17 -0
  111. data/lib/adtekio_adnetworks/postbacks/cyberagent_amoad.rb +17 -0
  112. data/lib/adtekio_adnetworks/postbacks/cyberagent_imobile.rb +43 -0
  113. data/lib/adtekio_adnetworks/postbacks/cyberagent_kjnw.rb +17 -0
  114. data/lib/adtekio_adnetworks/postbacks/cyberagent_maio.rb +18 -0
  115. data/lib/adtekio_adnetworks/postbacks/cyberagent_nend.rb +40 -0
  116. data/lib/adtekio_adnetworks/postbacks/cyberagent_smartc.rb +17 -0
  117. data/lib/adtekio_adnetworks/postbacks/cyberagent_smartnews.rb +17 -0
  118. data/lib/adtekio_adnetworks/postbacks/cyberz_asta.rb +26 -0
  119. data/lib/adtekio_adnetworks/postbacks/cyberz_bead.rb +26 -0
  120. data/lib/adtekio_adnetworks/postbacks/cyberz_imobile.rb +28 -0
  121. data/lib/adtekio_adnetworks/postbacks/cyberz_nend.rb +30 -0
  122. data/lib/adtekio_adnetworks/postbacks/datalead.rb +17 -0
  123. data/lib/adtekio_adnetworks/postbacks/eccrine.rb +80 -0
  124. data/lib/adtekio_adnetworks/postbacks/eeline.rb +50 -0
  125. data/lib/adtekio_adnetworks/postbacks/f5.rb +30 -0
  126. data/lib/adtekio_adnetworks/postbacks/fiksu.rb +43 -0
  127. data/lib/adtekio_adnetworks/postbacks/fiksu_applift.rb +31 -0
  128. data/lib/adtekio_adnetworks/postbacks/fractionalmedia.rb +78 -0
  129. data/lib/adtekio_adnetworks/postbacks/fyber.rb +36 -0
  130. data/lib/adtekio_adnetworks/postbacks/gamegenetics.rb +17 -0
  131. data/lib/adtekio_adnetworks/postbacks/ginga.rb +26 -0
  132. data/lib/adtekio_adnetworks/postbacks/glispa.rb +96 -0
  133. data/lib/adtekio_adnetworks/postbacks/googleadwords.rb +19 -0
  134. data/lib/adtekio_adnetworks/postbacks/growmobile.rb +36 -0
  135. data/lib/adtekio_adnetworks/postbacks/heyzap.rb +51 -0
  136. data/lib/adtekio_adnetworks/postbacks/inmobi.rb +50 -0
  137. data/lib/adtekio_adnetworks/postbacks/inneractive.rb +17 -0
  138. data/lib/adtekio_adnetworks/postbacks/instal.rb +18 -0
  139. data/lib/adtekio_adnetworks/postbacks/iqu.rb +19 -0
  140. data/lib/adtekio_adnetworks/postbacks/ironsource.rb +19 -0
  141. data/lib/adtekio_adnetworks/postbacks/jampp.rb +48 -0
  142. data/lib/adtekio_adnetworks/postbacks/jestadigital.rb +18 -0
  143. data/lib/adtekio_adnetworks/postbacks/jumpramp.rb +17 -0
  144. data/lib/adtekio_adnetworks/postbacks/jumptap.rb +23 -0
  145. data/lib/adtekio_adnetworks/postbacks/leadbolt.rb +29 -0
  146. data/lib/adtekio_adnetworks/postbacks/lifestreet.rb +97 -0
  147. data/lib/adtekio_adnetworks/postbacks/liftoff.rb +66 -0
  148. data/lib/adtekio_adnetworks/postbacks/loopme.rb +17 -0
  149. data/lib/adtekio_adnetworks/postbacks/magic_solver.rb +18 -0
  150. data/lib/adtekio_adnetworks/postbacks/marimedia.rb +20 -0
  151. data/lib/adtekio_adnetworks/postbacks/matomy.rb +59 -0
  152. data/lib/adtekio_adnetworks/postbacks/mdotm.rb +116 -0
  153. data/lib/adtekio_adnetworks/postbacks/misterbell.rb +18 -0
  154. data/lib/adtekio_adnetworks/postbacks/mmg.rb +20 -0
  155. data/lib/adtekio_adnetworks/postbacks/mnectar.rb +22 -0
  156. data/lib/adtekio_adnetworks/postbacks/moblin.rb +17 -0
  157. data/lib/adtekio_adnetworks/postbacks/moboqo.rb +17 -0
  158. data/lib/adtekio_adnetworks/postbacks/mobpartner.rb +19 -0
  159. data/lib/adtekio_adnetworks/postbacks/mopub.rb +30 -0
  160. data/lib/adtekio_adnetworks/postbacks/motive_interactive.rb +32 -0
  161. data/lib/adtekio_adnetworks/postbacks/mundo.rb +17 -0
  162. data/lib/adtekio_adnetworks/postbacks/nanigans.rb +38 -0
  163. data/lib/adtekio_adnetworks/postbacks/nativex.rb +30 -0
  164. data/lib/adtekio_adnetworks/postbacks/neodau.rb +19 -0
  165. data/lib/adtekio_adnetworks/postbacks/neverblue.rb +19 -0
  166. data/lib/adtekio_adnetworks/postbacks/operamedia.rb +39 -0
  167. data/lib/adtekio_adnetworks/postbacks/pandora.rb +17 -0
  168. data/lib/adtekio_adnetworks/postbacks/phunware.rb +18 -0
  169. data/lib/adtekio_adnetworks/postbacks/pirasin.rb +16 -0
  170. data/lib/adtekio_adnetworks/postbacks/playhaven.rb +31 -0
  171. data/lib/adtekio_adnetworks/postbacks/pocketmath.rb +17 -0
  172. data/lib/adtekio_adnetworks/postbacks/propeller.rb +18 -0
  173. data/lib/adtekio_adnetworks/postbacks/quixey.rb +17 -0
  174. data/lib/adtekio_adnetworks/postbacks/realzeit.rb +60 -0
  175. data/lib/adtekio_adnetworks/postbacks/remerge.rb +66 -0
  176. data/lib/adtekio_adnetworks/postbacks/revmob.rb +17 -0
  177. data/lib/adtekio_adnetworks/postbacks/ripple.rb +18 -0
  178. data/lib/adtekio_adnetworks/postbacks/roostr.rb +17 -0
  179. data/lib/adtekio_adnetworks/postbacks/rtbcom.rb +28 -0
  180. data/lib/adtekio_adnetworks/postbacks/septeni.rb +17 -0
  181. data/lib/adtekio_adnetworks/postbacks/seven_games.rb +51 -0
  182. data/lib/adtekio_adnetworks/postbacks/startapp.rb +48 -0
  183. data/lib/adtekio_adnetworks/postbacks/supersonic.rb +19 -0
  184. data/lib/adtekio_adnetworks/postbacks/tapjoy.rb +36 -0
  185. data/lib/adtekio_adnetworks/postbacks/taptica.rb +21 -0
  186. data/lib/adtekio_adnetworks/postbacks/targetcircle.rb +41 -0
  187. data/lib/adtekio_adnetworks/postbacks/todacell.rb +18 -0
  188. data/lib/adtekio_adnetworks/postbacks/tokenads.rb +18 -0
  189. data/lib/adtekio_adnetworks/postbacks/trademob.rb +48 -0
  190. data/lib/adtekio_adnetworks/postbacks/trademob_magic_solver.rb +22 -0
  191. data/lib/adtekio_adnetworks/postbacks/trialpay.rb +18 -0
  192. data/lib/adtekio_adnetworks/postbacks/unilead.rb +78 -0
  193. data/lib/adtekio_adnetworks/postbacks/uppsmobi.rb +19 -0
  194. data/lib/adtekio_adnetworks/postbacks/vungle.rb +33 -0
  195. data/lib/adtekio_adnetworks/postbacks/w4.rb +17 -0
  196. data/lib/adtekio_adnetworks/postbacks/webmedia.rb +17 -0
  197. data/lib/adtekio_adnetworks/postbacks/yahoo.rb +20 -0
  198. data/lib/adtekio_adnetworks/postbacks/youappi.rb +116 -0
  199. data/lib/adtekio_adnetworks/postbacks/zemail.rb +19 -0
  200. data/test/helper.rb +78 -0
  201. data/test/unit/postbacks/test_chartboost.rb +105 -0
  202. data/test/unit/postbacks/test_mdotm.rb +35 -0
  203. data/test/unit/postbacks/test_playhaven.rb +76 -0
  204. data/test/unit/postbacks/test_trademob_magic_solver.rb +24 -0
  205. data/test/unit/postbacks/test_unilead.rb +67 -0
  206. data/test/unit/test_api_key_scrapers.rb +302 -0
  207. data/test/unit/test_base_postback_class.rb +82 -0
  208. data/test/unit/test_cost_importers.rb +12 -0
  209. data/test/unit/test_postbacks.rb +33 -0
  210. data/test/unit/test_postbacks_definition.rb +111 -0
  211. data/test/unit/test_revenue_importers.rb +12 -0
  212. metadata +500 -0
@@ -0,0 +1,54 @@
1
+ class AdtekioAdnetworks::Revenue::Mopub
2
+ include AdtekioAdnetworks::RevenueImport
3
+
4
+ define_required_credentials do
5
+ [:account, :key]
6
+ end
7
+
8
+ def revenues(from, to)
9
+ # index meanings can be taken from exp_cols
10
+ report(from,to).map do |row|
11
+ {
12
+ :appname => row[1],
13
+ :date => Date.strptime(row[0], "%Y-%m-%d"),
14
+ :impressions => row[3],
15
+ :requests => row[4].to_i,
16
+ :clicks => row[5],
17
+ :amount => row[6]
18
+ }
19
+ end
20
+ end
21
+
22
+ def report(from,to)
23
+ d = data(from,to)
24
+ raise "Columns mismatch: #{d['columns']}" if d['columns'] != exp_cols
25
+ d["rows"]
26
+ end
27
+
28
+ def exp_cols
29
+ ["date", "app", "conversions", "impressions", "attempts",
30
+ "clicks", "revenue"]
31
+ end
32
+
33
+ def http_client
34
+ Net::HTTP::Persistent.new('chartboost').tap do |h|
35
+ h.verify_mode = OpenSSL::SSL::VERIFY_NONE
36
+ end
37
+ end
38
+
39
+ def data(from,to)
40
+ params = {
41
+ :group_by => "date,app",
42
+ :start_date => from.strftime("%Y-%m-%d"),
43
+ :end_date => to.strftime("%Y-%m-%d"),
44
+ :account => credentials.account,
45
+ :key => credentials.key,
46
+ }
47
+
48
+ uri = Addressable::URI.new
49
+ uri.query_values = params
50
+ url = URI.parse("%s?%s" % ["https://data-service.mopub.com/mpx",
51
+ uri.query])
52
+ JSON(http_client.request(url).body)
53
+ end
54
+ end
@@ -0,0 +1,71 @@
1
+ class AdtekioAdnetworks::Revenue::Nexage
2
+ include AdtekioAdnetworks::RevenueImport
3
+
4
+ define_required_credentials do
5
+ [:company_id, :access_key, :secret_key]
6
+ end
7
+
8
+ def revenues(from, to)
9
+ []
10
+ end
11
+
12
+ def report(from,to)
13
+ []
14
+ end
15
+
16
+ def seller_revenue_by_app(from,to)
17
+ Hash[site_ids(from,to)["detail"].map do |site_data|
18
+ uri = Addressable::URI.new
19
+ uri.query_values = {
20
+ :start => from.strftime("%Y-%m-%d"),
21
+ :stop => to.strftime("%Y-%m-%d"),
22
+ :dim => "day",
23
+ :site => site_data["siteId"]
24
+ }
25
+ url = ("https://reports.nexage.com/access/"+
26
+ "#{credentials.company_id}"+
27
+ "/reports/sellerrevenue")
28
+
29
+ [site_data["site"],
30
+ do_request("%s?%s" % [url, uri.query])["detail"]]
31
+ end]
32
+ end
33
+
34
+ def site_ids(from,to)
35
+ uri = Addressable::URI.new
36
+ uri.query_values = {
37
+ :start => from.strftime("%Y-%m-%d"),
38
+ :stop => to.strftime("%Y-%m-%d"),
39
+ :dim => "site"
40
+ }
41
+ url = ("https://reports.nexage.com/access/#{credentials.company_id}"+
42
+ "/reports/sellerrevenue")
43
+ do_request("%s?%s" % [url, uri.query])
44
+ end
45
+
46
+ def do_request(urlstring)
47
+ digest_auth = Net::HTTP::DigestAuth.new
48
+
49
+ uri = URI.parse(urlstring)
50
+ uri.user = credentials.access_key
51
+ uri.password = credentials.secret_key
52
+
53
+ h = Net::HTTP::Persistent.new('whatever')
54
+ h.verify_mode = OpenSSL::SSL::VERIFY_NONE
55
+
56
+ req = Net::HTTP::Get.new uri.request_uri
57
+
58
+ res = h.request uri, req
59
+
60
+ auth = digest_auth.auth_header uri, res['www-authenticate'], 'GET'
61
+
62
+ req = Net::HTTP::Get.new uri.request_uri
63
+ req.add_field 'Authorization', auth
64
+
65
+ res = h.request uri,req
66
+
67
+ raise "No data available" if res.code.to_i == 204
68
+ raise "Unable to authenticate" if res.code.to_i != 200
69
+ JSON(res.body)
70
+ end
71
+ end
@@ -0,0 +1,73 @@
1
+ class AdtekioAdnetworks::Revenue::Supersonic
2
+ include AdtekioAdnetworks::RevenueImport
3
+
4
+ BASE_URL = "https://api.supersonicads.com/api/rest/v1/ultra/statistics"
5
+
6
+ define_required_credentials do
7
+ [:access_key, :secret_key]
8
+ end
9
+
10
+ def revenues(from, to)
11
+ report(from,to).map do |(appname, appid, providerName, date), values|
12
+ values.map do |dpt|
13
+ # we assume: impressions == clicks, strange but true!
14
+ if dpt.impressions != dpt.clicks
15
+ raise "impressions didn't match clicks: "+
16
+ "#{dpt.impressions}/#{dpt.clicks}"
17
+ end
18
+
19
+ nmstuff = {
20
+ :provider => providerName,
21
+ :appid => appid,
22
+ :uniqUser => dpt.uniqueUsers.remove(',').to_i,
23
+ :uniqPayingUsers => dpt.uniquePayingUsers.remove(',').to_i,
24
+ :rewards => dpt.rewards.remove(',').to_i,
25
+ }
26
+
27
+ {
28
+ :date => Date.strptime(date, "%Y-%m-%d"),
29
+ :appname => appname,
30
+ :amount => dpt.revenue.remove('$').to_f,
31
+ :requests => dpt.hits.remove(',').to_i,
32
+ :impressions => dpt.fulfillments.remove(',').to_i,
33
+ :clicks => dpt.clicks.remove(',').to_i,
34
+ :completions => dpt.completions.remove(',').to_i,
35
+ :not_matched => not_matched(nmstuff)
36
+ }
37
+ end
38
+ end.flatten
39
+ end
40
+
41
+ def report(from,to)
42
+ CSV(ultra_data(from,to), :col_sep => ",", :headers => true ).map do |a|
43
+ OpenStruct.new(a.to_h)
44
+ end[0..-2].group_by do |a| ## last line is a summary row, ignore it.
45
+ [a.applicationName, a.applicationId, a.providerName, a.theDate]
46
+ end
47
+ end
48
+
49
+ def http_client
50
+ @http_client ||= Net::HTTP::Persistent.new('supersonic').tap do |client|
51
+ client.verify_mode = OpenSSL::SSL::VERIFY_NONE
52
+ end
53
+ end
54
+
55
+ def ultra_data(from_date, to_date)
56
+ http_client.request(ultra_url(from_date, to_date)).body
57
+ end
58
+
59
+ def ultra_url(from_date, to_date)
60
+ uri = Addressable::URI.new
61
+ uri.query_values = {
62
+ :accessKey => credentials.access_key,
63
+ :secretKey => credentials.secret_key,
64
+ :onlyRevenue => 0,
65
+ :fromDate => from_date.strftime("%Y-%m-%d"),
66
+ :toDate => to_date.strftime("%Y-%m-%d"),
67
+ :format => "csv",
68
+ "breakdowns[]" => ["date", "application", "provider"]
69
+ }
70
+
71
+ URI.parse("%s?%s" % [BASE_URL, uri.query])
72
+ end
73
+ end
@@ -0,0 +1,38 @@
1
+ class AdtekioAdnetworks::Revenue::Tapsense
2
+ include AdtekioAdnetworks::RevenueImport
3
+ ## More info on the API:
4
+ ## https://github.com/TapSense/tapsense-adapters/wiki/TapSense-Reporting-API-for-Publishers
5
+
6
+ define_required_credentials do
7
+ [:username, :password]
8
+ end
9
+
10
+ def revenues(from, to)
11
+ end
12
+
13
+ def report(from,to)
14
+ end
15
+
16
+ def data(from, to)
17
+ require 'mechanize'
18
+ agent = Mechanize.new
19
+ agent.user_agent_alias = 'Mac Safari'
20
+
21
+ agent.post("https://dashboard.tapsense.com/console/login", {
22
+ :username => credentials.username,
23
+ :password => credentials.password}.to_json,
24
+ {"Content-Type" => "application/json",
25
+ "Accept" => "application/json" })
26
+
27
+ uri = Addressable::URI.new
28
+ uri.query_values = {
29
+ :start_date => from.strftime("%Y-%m-%d"),
30
+ :end_date => to.strftime("%Y-%m-%d"),
31
+ :format => :json,
32
+ :rollup => "date,country",
33
+ :action_type => "report"
34
+ }
35
+ url = "https://dashboard.tapsense.com/console/publisher/report"
36
+ agent.get("%s?%s" % [url, uri.query]).body
37
+ end
38
+ end
@@ -0,0 +1,41 @@
1
+ class AdtekioAdnetworks::Revenue::Trialpay
2
+ include AdtekioAdnetworks::RevenueImport
3
+
4
+ define_required_credentials do
5
+ [:username, :password]
6
+ end
7
+
8
+ def revenues(from, to)
9
+ end
10
+
11
+ def report(from,to)
12
+ end
13
+
14
+ def dailysummary
15
+ require 'mechanize'
16
+ agent = Mechanize.new
17
+ agent.user_agent_alias = 'Mac Safari'
18
+
19
+ agent.post("https://merchant.trialpay.com/login/", {
20
+ :action => "del",
21
+ :email => credentials.username,
22
+ :password => credentials.password})
23
+
24
+ uri = Addressable::URI.new
25
+ uri.query_values = {
26
+ :app_id => "",
27
+ :context => "",
28
+ :group_by => "group_by_app_id_context_and_date",
29
+ :date_group => "day",
30
+ :date_type => 1,
31
+ :date_interval => 6, # 30 days back
32
+ :csv => "Export to CSV",
33
+ "[sort_by]" => "date",
34
+ "[sort_order]" => "asc",
35
+ "report_table[sort_by]" => "date",
36
+ "report_table[sort_order]" => "asc",
37
+ }
38
+ url = "https://merchant.trialpay.com/reports/dailysummary/"
39
+ agent.get("%s?%s" % [url, uri.query]).body
40
+ end
41
+ end
@@ -0,0 +1,75 @@
1
+ class AdtekioAdnetworks::Revenue::Vungle
2
+ include AdtekioAdnetworks::RevenueImport
3
+
4
+ BASE_URL = "https://ssl.vungle.com"
5
+
6
+ define_required_credentials do
7
+ [:api_key]
8
+ end
9
+
10
+ def revenues(from, to)
11
+ report(from,to).map do |dpt|
12
+ nmstuff = {
13
+ :appId => dpt['appId'],
14
+ :installs => dpt['installs'],
15
+ :platform => dpt['platform'],
16
+ :status => dpt['status'],
17
+ :connection => dpt['connection']
18
+ }
19
+
20
+ {
21
+ :appname => dpt['name'],
22
+ :date => dpt['datestamp'],
23
+ :amount => dpt['revenue'].to_f,
24
+ :impressions => dpt['impressions'].to_i,
25
+ :clicks => dpt['views'].to_i,
26
+ :completions => dpt['completes'].to_i,
27
+ :not_matched => not_matched(nmstuff)
28
+ }
29
+ end
30
+ end
31
+
32
+ def report(from,to)
33
+ # Because we have a api rate limit of 2 per 10 seconds:
34
+ # ApiError: Rate limit hit. Maximum 2 requests every 10 seconds
35
+ # batch the dates together and sleep 5 seconds between requests.
36
+ applications.map do |app|
37
+ sleep 5
38
+ retrieve_data(app["id"], from, to).map do |data|
39
+ data.merge(app).
40
+ merge("datestamp" => Date.strptime(data["date"], "%Y-%m-%d"))
41
+ end
42
+ end.flatten
43
+ end
44
+
45
+ def applications
46
+ uri = Addressable::URI.new
47
+ uri.query_values = { :key => credentials.api_key }
48
+ datauri = URI.
49
+ parse("%s/api/applications?%s" % [BASE_URL, uri.query])
50
+
51
+ JSON(Net::HTTP::Persistent.new('vungle').request(datauri).body)
52
+ end
53
+
54
+ def retrieve_data(app, startdate, enddate)
55
+ uri = Addressable::URI.new
56
+ uri.query_values = {
57
+ :key => credentials.api_key,
58
+ :start => startdate.strftime("%Y-%m-%d"),
59
+ :end => enddate.strftime("%Y-%m-%d")
60
+ }
61
+ datauri = URI.
62
+ parse("%s/api/applications/%s?%s" % [BASE_URL, app, uri.query])
63
+
64
+ json_data_string =
65
+ Net::HTTP::Persistent.new('vungle').request(datauri).body
66
+
67
+ begin
68
+ JSON(json_data_string)
69
+ rescue Exception => e
70
+ $stderr.puts("vungle data failure: #{e}")
71
+ $stderr.puts("json data string: #{json_data_string}")
72
+ []
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,27 @@
1
+ module AdtekioAdnetworks
2
+ module Revenue
3
+ # placeholder
4
+ end
5
+
6
+ module RevenueImport
7
+ include BaseImporter
8
+
9
+ def check_version!(version, expected_version)
10
+ raise "Unsupported version: #{version}" if version != expected_version
11
+ end
12
+
13
+ def check_currency!(currency, expected_currency)
14
+ raise "Unsupported currency: #{currency}" if currency != expected_currency
15
+ end
16
+
17
+ def not_matched(hsh)
18
+ uri = Addressable::URI.new
19
+ uri.query_values = hsh
20
+ uri.query
21
+ end
22
+ end
23
+ end
24
+
25
+ Dir[File.join(File.dirname(__FILE__), 'revenue', '*.rb')].each do |f|
26
+ require f
27
+ end
@@ -0,0 +1,193 @@
1
+ require 'uuidtools'
2
+ require 'json'
3
+ require 'digest/sha2'
4
+ require 'digest/md5'
5
+ require 'erubis'
6
+ require 'active_support'
7
+ require 'active_support/core_ext'
8
+
9
+ module AdtekioAdnetworks
10
+ module Postbacks
11
+ extend self
12
+
13
+ PossibleEvents = {
14
+ :mac => "Attribution",
15
+ :ist => "Application Install",
16
+ :apo => "Application Open",
17
+ :fun => "Tutorial",
18
+ :pay => "Payment",
19
+ :eor => "End of Round",
20
+ :scs => "Scene Start",
21
+ :scc => "Scene Complete",
22
+ }
23
+
24
+ def networks
25
+ @networks ||= {}
26
+ end
27
+
28
+ def register(postback_klz)
29
+ networks[postback_klz.network] = postback_klz
30
+ end
31
+ end
32
+
33
+ class BasePostbackClass
34
+ attr_reader :event, :params, :user, :netcfg
35
+
36
+ class CGIEruby < Erubis::PI::Eruby
37
+ REGEXP = Regexp.new("[^#{URI::PATTERN::UNRESERVED}]").freeze
38
+
39
+ def escaped_expr(code)
40
+ "URI.encode((#{code.strip}).to_s, CGIEruby::REGEXP)"
41
+ end
42
+ end
43
+
44
+ class MD5 < Digest::MD5
45
+ class << self
46
+ alias orig_new new
47
+ def new(str = nil)
48
+ str ? orig_new.update(str) : orig_new
49
+ end
50
+
51
+ def md5(*args)
52
+ new(*args)
53
+ end
54
+ end
55
+ end
56
+
57
+ def initialize(event, user, netcfg, params = nil)
58
+ @event = event
59
+ @params = params || (event && event.params)
60
+ @user = user
61
+ @netcfg = netcfg
62
+ end
63
+
64
+ def sha1(value)
65
+ Digest::SHA1.hexdigest(value || "")
66
+ end
67
+
68
+ def muidify(val)
69
+ Base64.encode64(MD5.md5(val).digest).tr("+/=", "-_\n").strip
70
+ end
71
+
72
+ def contains_eruby?(val)
73
+ val && !!(val =~ /@\{.*\}@/ || val =~ /<%.*%>/m)
74
+ end
75
+
76
+ def parse_string(str)
77
+ contains_eruby?(str) ? CGIEruby.new(str).result(binding) : str
78
+ end
79
+
80
+ def should_handle?(cfg)
81
+ cfg.check.nil? ||
82
+ !!(cfg.check.is_a?(Symbol) ? send(cfg.check) : eval(cfg.check))
83
+ end
84
+
85
+ def either_hash_or_symbol_to_string(val)
86
+ if val.is_a?(Hash)
87
+ uri = Addressable::URI.new
88
+ uri.query_values = val
89
+ CGI.unescape(uri.to_s).gsub(/^[?]/,'')
90
+ elsif val.is_a?(Symbol)
91
+ send(val)
92
+ else
93
+ val.to_s
94
+ end
95
+ end
96
+
97
+ def cfg_to_url(cfg)
98
+ return unless should_handle?(cfg)
99
+
100
+ header = either_hash_or_symbol_to_string(cfg.header)
101
+ body = either_hash_or_symbol_to_string(cfg.post)
102
+
103
+ urlparams = ( (cfg.params.is_a?(Hash) && cfg.params) ||
104
+ cfg.params.is_a?(Symbol) && send(cfg.params) ) || {}
105
+
106
+ uri = Addressable::URI.parse(cfg.url)
107
+ uri.query_values = urlparams unless urlparams.empty?
108
+ url = CGI.unescape(uri.to_s)
109
+
110
+ parsed_header = CGI::parse(parse_string(header) || "")
111
+ parsed_header.each { |key, value| parsed_header[key] = value.first }
112
+
113
+ { :url => parse_string(url),
114
+ :body => parse_string(body),
115
+ :header => parsed_header}
116
+ end
117
+ end
118
+
119
+ module BasePostbacks
120
+ def self.included(klz)
121
+ klz.class_eval do
122
+ def self.postbacks
123
+ @postbacks ||= Hash.new{ |k,v| k[v] = [] }
124
+ end
125
+
126
+ def self.pbcfg
127
+ @pbcfg ||= Hash.new{ |k,v| k[v] = Hash.new{ |k,v| k[v] = [] }}
128
+ end
129
+
130
+ def self.define_network_config(&block)
131
+ @network_config = yield
132
+ self.class_eval do
133
+ def self.netcfg
134
+ @network_config
135
+ end
136
+ end
137
+ end
138
+
139
+ def self.define_postback_for(platform, type, &block)
140
+ cfg = OpenStruct.new(yield)
141
+
142
+ postbacks[platform] << type.to_sym
143
+ pbcfg[platform][type.to_sym] << cfg
144
+
145
+ self.send(:define_method, type, Proc.new do |platform|
146
+ pbc = self.class.instance_variable_get("@pbcfg")
147
+ pbc[platform.to_sym][type.to_sym].map do |cfg|
148
+ cfg_to_url(cfg)
149
+ end.compact
150
+ end)
151
+
152
+ self.class.send(:define_method, type, Proc.new do |platform|
153
+ @pbcfg[platform.to_sym][type.to_sym].map do |cfg|
154
+ cfg_to_description(cfg)
155
+ end
156
+ end)
157
+ end
158
+
159
+ def self.cfg_to_description(cfg)
160
+ url = if cfg.params.is_a?(Hash)
161
+ uri = Addressable::URI.parse(cfg.url)
162
+ uri.query_values = cfg.params unless cfg.params.empty?
163
+ CGI.unescape(uri.to_s)
164
+ else
165
+ "%s?%s" % [cfg.url, cfg.params.to_s]
166
+ end
167
+
168
+ { :url => url,
169
+ :user_required => cfg.user_required || false,
170
+ :store_user => cfg.store_user || false }
171
+ end
172
+
173
+ def self.user_required?(event, platform)
174
+ self.send(event, platform).any? { |desc| desc[:user_required] }
175
+ end
176
+
177
+ def self.store_user?(event, platform)
178
+ self.send(event, platform).any? { |desc| desc[:store_user] }
179
+ end
180
+
181
+ def self.network
182
+ name.to_s.sub(/^.+::([^:]+)$/,'\1').snakecase.to_sym
183
+ end
184
+ end
185
+
186
+ Postbacks.register(klz)
187
+ end
188
+ end
189
+ end
190
+
191
+ Dir[File.join(File.dirname(__FILE__), 'postbacks', '*.rb')].each do |f|
192
+ require f
193
+ end