apdm 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +4 -0
  5. data/README.md +223 -0
  6. data/Rakefile +1 -0
  7. data/apdm.gemspec +34 -0
  8. data/bin/apdm +6 -0
  9. data/features/ad_tech.feature +11 -0
  10. data/features/step_definitions/ad_tech_steps.rb +19 -0
  11. data/features/support/env.rb +5 -0
  12. data/fixtures/approvals/ad_tech_loader_scripts.approved.txt +42 -0
  13. data/fixtures/approvals/ad_tech_placeholders.approved.txt +6 -0
  14. data/lib/apdm.rb +24 -0
  15. data/lib/apdm/ad_tech.rb +96 -0
  16. data/lib/apdm/ad_tech/ad_loader.rb +67 -0
  17. data/lib/apdm/ad_tech/ads.csv +475 -0
  18. data/lib/apdm/ad_tech/data.rb +47 -0
  19. data/lib/apdm/channel.rb +87 -0
  20. data/lib/apdm/channels.rb +569 -0
  21. data/lib/apdm/credentials.rb +26 -0
  22. data/lib/apdm/design_elements.rb +60 -0
  23. data/lib/apdm/design_elements/api.rb +75 -0
  24. data/lib/apdm/feed.rb +65 -0
  25. data/lib/apdm/issues.rb +14 -0
  26. data/lib/apdm/issues/aasavis.rb +51 -0
  27. data/lib/apdm/issues/amta.rb +253 -0
  28. data/lib/apdm/issues/an.rb +302 -0
  29. data/lib/apdm/issues/auraavis.rb +154 -0
  30. data/lib/apdm/issues/austagderblad.rb +154 -0
  31. data/lib/apdm/issues/avisa-hordaland.rb +154 -0
  32. data/lib/apdm/issues/avisa-valdres.rb +177 -0
  33. data/lib/apdm/issues/ba.rb +352 -0
  34. data/lib/apdm/issues/bladet.rb +154 -0
  35. data/lib/apdm/issues/blv.rb +254 -0
  36. data/lib/apdm/issues/bygdeposten.rb +154 -0
  37. data/lib/apdm/issues/demokraten.rb +154 -0
  38. data/lib/apdm/issues/eikerbladet.rb +409 -0
  39. data/lib/apdm/issues/enebakkavis.rb +51 -0
  40. data/lib/apdm/issues/etl.rb +79 -0
  41. data/lib/apdm/issues/eub.rb +254 -0
  42. data/lib/apdm/issues/finnmarkdagblad.rb +302 -0
  43. data/lib/apdm/issues/finnmarken.rb +302 -0
  44. data/lib/apdm/issues/firda.rb +302 -0
  45. data/lib/apdm/issues/firdaposten.rb +153 -0
  46. data/lib/apdm/issues/fremover.rb +304 -0
  47. data/lib/apdm/issues/gd.rb +304 -0
  48. data/lib/apdm/issues/glomdalen.rb +302 -0
  49. data/lib/apdm/issues/ha-halden.rb +302 -0
  50. data/lib/apdm/issues/hadeland.rb +251 -0
  51. data/lib/apdm/issues/hardanger-folkeblad.rb +151 -0
  52. data/lib/apdm/issues/helgeland-arbeiderblad.rb +304 -0
  53. data/lib/apdm/issues/import.csv +12821 -0
  54. data/lib/apdm/issues/indre.rb +151 -0
  55. data/lib/apdm/issues/jarlsbergavis.rb +154 -0
  56. data/lib/apdm/issues/kvinnheringen.rb +202 -0
  57. data/lib/apdm/issues/lofot-tidende.rb +102 -0
  58. data/lib/apdm/issues/lofotposten.rb +304 -0
  59. data/lib/apdm/issues/mb.rb +103 -0
  60. data/lib/apdm/issues/namdalsavisa.rb +302 -0
  61. data/lib/apdm/issues/nordhordland.rb +103 -0
  62. data/lib/apdm/issues/nordlys.rb +304 -0
  63. data/lib/apdm/issues/oa.rb +302 -0
  64. data/lib/apdm/issues/op.rb +304 -0
  65. data/lib/apdm/issues/opdalingen.rb +150 -0
  66. data/lib/apdm/issues/oyene.rb +51 -0
  67. data/lib/apdm/issues/pd.rb +254 -0
  68. data/lib/apdm/issues/r-a.rb +152 -0
  69. data/lib/apdm/issues/ranablad.rb +304 -0
  70. data/lib/apdm/issues/rb.rb +302 -0
  71. data/lib/apdm/issues/retten.rb +151 -0
  72. data/lib/apdm/issues/ringblad.rb +304 -0
  73. data/lib/apdm/issues/rogalandsavis.rb +302 -0
  74. data/lib/apdm/issues/sa.rb +304 -0
  75. data/lib/apdm/issues/smaalenene.rb +304 -0
  76. data/lib/apdm/issues/sognavis.rb +254 -0
  77. data/lib/apdm/issues/ta.rb +304 -0
  78. data/lib/apdm/issues/tk.rb +304 -0
  79. data/lib/apdm/issues/tvedestrandsposten.rb +150 -0
  80. data/lib/apdm/issues/vestbyavis.rb +51 -0
  81. data/lib/apdm/local_paper_area.rb +21 -0
  82. data/lib/apdm/network.rb +49 -0
  83. data/lib/apdm/null_cache.rb +15 -0
  84. data/lib/apdm/origo.rb +46 -0
  85. data/lib/apdm/saxo.rb +58 -0
  86. data/lib/apdm/saxo/iptc.rb +69 -0
  87. data/lib/apdm/saxo/metadata.rb +36 -0
  88. data/lib/apdm/saxo/remote.rb +67 -0
  89. data/lib/apdm/sinatra.rb +85 -0
  90. data/lib/apdm/version.rb +3 -0
  91. data/lib/cli.rb +12 -0
  92. data/spec/ad_tech/ad_loader_spec.rb +27 -0
  93. data/spec/ad_tech/data_spec.rb +14 -0
  94. data/spec/ad_tech_spec.rb +70 -0
  95. data/spec/approvals_helper.rb +6 -0
  96. data/spec/channel_spec.rb +91 -0
  97. data/spec/channels_spec.rb +9 -0
  98. data/spec/credentials_integration_spec.rb +13 -0
  99. data/spec/credentials_spec.rb +34 -0
  100. data/spec/design_elements_spec.rb +132 -0
  101. data/spec/feed_spec.rb +49 -0
  102. data/spec/fixtures/ad_tech.csv +6 -0
  103. data/spec/fixtures/approvals/adtech/ad_loader.approved.txt +9 -0
  104. data/spec/fixtures/approvals/apdm_adtech/data/handles_artikkelboard.approved.txt +10 -0
  105. data/spec/fixtures/approvals/apdm_adtech/data/handles_bunnbanner.approved.txt +10 -0
  106. data/spec/fixtures/approvals/apdm_adtech/data/handles_skyskraper_1.approved.txt +10 -0
  107. data/spec/fixtures/approvals/apdm_adtech/data/handles_toppbanner.approved.txt +10 -0
  108. data/spec/fixtures/approvals/apdm_adtech/data/is_ok_with_new_bandwagon_data.approved.txt +10 -0
  109. data/spec/fixtures/approvals/apdm_adtech/data/loads_default_data.approved.txt +10 -0
  110. data/spec/fixtures/approvals/apdm_designelements/css/via_api.approved.txt +23 -0
  111. data/spec/fixtures/approvals/apdm_designelements/footer_html/via_api.approved.html +85 -0
  112. data/spec/fixtures/approvals/apdm_designelements/header_html/via_api.approved.html +40 -0
  113. data/spec/fixtures/approvals/apdm_designelements/tracking_scripts/api/keyword.approved.txt +54 -0
  114. data/spec/fixtures/approvals/apdm_designelements/tracking_scripts/api/placeholder.approved.txt +54 -0
  115. data/spec/fixtures/issues.csv +3 -0
  116. data/spec/fixtures/test.jpg +0 -0
  117. data/spec/fixtures/vcr_cassettes/apdm_credentials.yml +44 -0
  118. data/spec/fixtures/vcr_cassettes/css.yml +5588 -0
  119. data/spec/fixtures/vcr_cassettes/footer-html.yml +178 -0
  120. data/spec/fixtures/vcr_cassettes/header-html.yml +132 -0
  121. data/spec/fixtures/vcr_cassettes/origo_someone_credentials.yml +43 -0
  122. data/spec/fixtures/vcr_cassettes/origo_westerdal_credentials.yml +56 -0
  123. data/spec/fixtures/vcr_cassettes/site_stat.yml +172 -0
  124. data/spec/fixtures/vcr_cassettes/site_stat_custom_category.yml +172 -0
  125. data/spec/geo_spec.rb +10 -0
  126. data/spec/issues_etl_spec.rb +41 -0
  127. data/spec/mockcached.rb +36 -0
  128. data/spec/network_spec.rb +43 -0
  129. data/spec/null_cache_spec.rb +29 -0
  130. data/spec/origo_spec.rb +24 -0
  131. data/spec/saxo/iptc_spec.rb +105 -0
  132. data/spec/saxo/metadata_spec.rb +79 -0
  133. data/spec/saxo/remote_spec.rb +71 -0
  134. data/spec/saxo/saxo_spec.rb +82 -0
  135. data/spec/spec_helper.rb +22 -0
  136. data/spec/vcr_helper.rb +6 -0
  137. data/test/fixtures/config-example.yml +6 -0
  138. data/test/saxo/acceptance_spec.rb +109 -0
  139. metadata +427 -0
@@ -0,0 +1,51 @@
1
+ APDM::ISSUES['vestbyavis'] = [
2
+ Date.parse('2013-01-03'),
3
+ Date.parse('2013-01-10'),
4
+ Date.parse('2013-01-17'),
5
+ Date.parse('2013-01-24'),
6
+ Date.parse('2013-01-31'),
7
+ Date.parse('2013-02-07'),
8
+ Date.parse('2013-02-14'),
9
+ Date.parse('2013-02-21'),
10
+ Date.parse('2013-02-28'),
11
+ Date.parse('2013-03-07'),
12
+ Date.parse('2013-03-14'),
13
+ Date.parse('2013-03-21'),
14
+ Date.parse('2013-04-04'),
15
+ Date.parse('2013-04-11'),
16
+ Date.parse('2013-04-18'),
17
+ Date.parse('2013-04-25'),
18
+ Date.parse('2013-05-02'),
19
+ Date.parse('2013-05-16'),
20
+ Date.parse('2013-05-23'),
21
+ Date.parse('2013-05-30'),
22
+ Date.parse('2013-06-06'),
23
+ Date.parse('2013-06-13'),
24
+ Date.parse('2013-06-20'),
25
+ Date.parse('2013-06-27'),
26
+ Date.parse('2013-07-04'),
27
+ Date.parse('2013-07-11'),
28
+ Date.parse('2013-07-18'),
29
+ Date.parse('2013-07-25'),
30
+ Date.parse('2013-08-01'),
31
+ Date.parse('2013-08-08'),
32
+ Date.parse('2013-08-15'),
33
+ Date.parse('2013-08-22'),
34
+ Date.parse('2013-08-29'),
35
+ Date.parse('2013-09-05'),
36
+ Date.parse('2013-09-12'),
37
+ Date.parse('2013-09-19'),
38
+ Date.parse('2013-09-26'),
39
+ Date.parse('2013-10-03'),
40
+ Date.parse('2013-10-10'),
41
+ Date.parse('2013-10-17'),
42
+ Date.parse('2013-10-24'),
43
+ Date.parse('2013-10-31'),
44
+ Date.parse('2013-11-07'),
45
+ Date.parse('2013-11-14'),
46
+ Date.parse('2013-11-21'),
47
+ Date.parse('2013-11-28'),
48
+ Date.parse('2013-12-05'),
49
+ Date.parse('2013-12-12'),
50
+ Date.parse('2013-12-19')
51
+ ]
@@ -0,0 +1,21 @@
1
+ require 'rgeo'
2
+ require 'rgeo-geojson'
3
+
4
+ module APDM
5
+ class LocalPaperArea
6
+
7
+ attr_reader :feature, :factory
8
+ def initialize(geojson)
9
+ @factory = RGeo::Geographic.spherical_factory
10
+ @feature = RGeo::GeoJSON.decode(geojson, :json_parser => :json)
11
+ end
12
+
13
+ def contains?(lon, lat)
14
+ feature.contains? factory.point(lon, lat)
15
+ end
16
+ end
17
+
18
+ EmptyGeoHash = "{\"type\":\"MultiPolygon\",\"coordinates\":[[[]]]}"
19
+
20
+ end
21
+
@@ -0,0 +1,49 @@
1
+ require 'enumerator'
2
+
3
+ module APDM
4
+
5
+ class Network
6
+ include Enumerable
7
+
8
+ attr_reader :channels
9
+ def initialize
10
+ @channels = []
11
+ end
12
+
13
+ def each
14
+ @channels.each {|c| yield c}
15
+ end
16
+
17
+ def <<(channel)
18
+ @channels << channel
19
+ end
20
+
21
+ def find_by_label(label)
22
+ find do |channel|
23
+ channel.label == label
24
+ end
25
+ end
26
+
27
+ def find_by_ad_tech_id(id)
28
+ find do |channel|
29
+ channel.ad_tech_id == id.to_i
30
+ end
31
+ end
32
+
33
+ def find_by_url(url)
34
+ return nil unless (url && url[/\./])
35
+ label = url.gsub(/https?:\/\//, '')[/([^\.]+\.[^\.]+)$/, 1].gsub(/\.\w+$/, '')
36
+ find_by_label(label)
37
+ end
38
+
39
+ def random_production_channel
40
+ # used to display ads from a random channel
41
+ @channels.reject{|c| c.ad_tech_id.nil? || c.label == 'avisnavn' || c.label == 'moss-dagblad' }.sample
42
+ end
43
+
44
+ # DEPRECATED
45
+ def find_by_domain(url)
46
+ find_by_url(url)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ module APDM
2
+ class NullCache
3
+ def set(*args)
4
+ # Elegantly does exactly nothing.
5
+ end
6
+
7
+ def get(*args)
8
+ # Nothing is cached; nothing to get.
9
+ end
10
+
11
+ def delete(*args)
12
+ # It's already gone.
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,46 @@
1
+ require 'curb'
2
+ require 'json'
3
+
4
+ # Hackish origo knowledge
5
+ module APDM
6
+ class Origo
7
+
8
+ # Found in the Origo console with
9
+ # Organization.find_by_title('A-pressen').children.map(&:id)
10
+ APRESSEN = [29, 34, 35, 39, 40, 42, 44, 47, 56, 64, 67, 69, 82, 94, 95, 99, 134, 139, 154, 155, 162, 232, 242, 264, 287, 317, 386, 401, 420, 433, 456, 462, 597, 12455, 12617, 12733, 12735, 12737, 12802, 12886, 13036, 13038, 13041, 13042]
11
+
12
+ BENGLER = [22]
13
+
14
+ ORGANIZATIONS = APRESSEN + BENGLER
15
+
16
+ def self.organization?(id)
17
+ ORGANIZATIONS.include?(id)
18
+ end
19
+
20
+ def self.fetch_credentials(id)
21
+ api.fetch_credentials(id)
22
+ end
23
+
24
+ def self.api
25
+ @api ||= API.new
26
+ end
27
+
28
+ class API
29
+ # Credentials in Origo relate a person to an organization via a role.
30
+ # An 'authorized' role means that a human has actually
31
+ # eyeballed the credential and said: "Yeah, this is true."
32
+ # A 'privileged' role, gives the person god-like powers in the
33
+ # organization, but only works if actually authorized.
34
+ def fetch_credentials(id)
35
+ credentials = JSON.parse(Curl::Easy.http_get("#{url}#{id}").body_str)
36
+ credentials.select {|credential| Origo.organization?(credential["organization"]["id"]) }
37
+ end
38
+
39
+ private
40
+ def url
41
+ "http://origo.no/-/api/v2/credential/find?api_key=49rgnfu9tdtovs1bn2k9xbdq141thogpjbll3bn460d559gk0o&include_organization=true&user_id="
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,58 @@
1
+ require 'net/ftp'
2
+ require 'open3'
3
+ require 'open-uri'
4
+ require 'logger'
5
+
6
+ require "apdm/saxo/metadata"
7
+ require "apdm/saxo/iptc"
8
+ require "apdm/saxo/remote"
9
+
10
+ module APDM
11
+ class Saxo
12
+ class InvalidConfig < Exception; end
13
+
14
+ class << self
15
+ attr_writer :logger
16
+ def logger
17
+ unless @logger
18
+ FileUtils.mkdir('log') unless File.exists?('log')
19
+ @logger = Logger.new('log/saxo.log')
20
+ end
21
+ @logger
22
+ end
23
+ end
24
+
25
+ attr_accessor :server, :username, :password, :remote_dir
26
+ def initialize(options = {})
27
+ options.each {|k,v| validate(k, v)}
28
+
29
+ self.server = options[:server] || options['server']
30
+ self.username = options[:username] || options['username']
31
+ self.password = options[:password] || options['password']
32
+ self.remote_dir = (options[:remote_dir] || options['remote_dir']).upcase
33
+ end
34
+
35
+ def write(metadata)
36
+ Metadata.new(metadata)
37
+ end
38
+
39
+ def transfer(photo)
40
+ Remote.new(self, photo).transfer
41
+ end
42
+
43
+ private
44
+ def validate(key, value)
45
+ if required?(key) && !valid?(value)
46
+ raise InvalidConfig.new("#{key} is required!")
47
+ end
48
+ end
49
+
50
+ def required?(key)
51
+ [:server, :username, :password, :remote_dir].include? key.to_sym
52
+ end
53
+
54
+ def valid?(value)
55
+ !value.nil? && value != ""
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,69 @@
1
+ module APDM
2
+ class Saxo
3
+ class IPTC
4
+
5
+ attr_accessor :name, :path, :file, :source
6
+ def initialize(name, path, options = {})
7
+ self.source = options[:source]
8
+ self.name = name
9
+ self.path = path
10
+ self.file = "#{path.chomp('/')}/#{name}"
11
+ duplicate options[:file] if options[:file]
12
+ end
13
+
14
+ def duplicate(original)
15
+ FileUtils.cp(original, file)
16
+ end
17
+
18
+ def logger
19
+ APDM::Saxo.logger
20
+ end
21
+
22
+ def write(data = {})
23
+ download if source
24
+ delete_metadata
25
+ write_metadata(data)
26
+ end
27
+
28
+ def download
29
+ logger.info "Downloading #{source}."
30
+ begin
31
+ File.open(file, "wb") do |f|
32
+ o = open(source)
33
+ r = o.read
34
+ f.write r
35
+ end
36
+ rescue
37
+ raise $!, "Problem downloading image with file: #{file} and source: #{source}. #{$!}"
38
+ end
39
+ end
40
+
41
+ def delete_metadata
42
+ logger.info "Deleting metadata on #{file}."
43
+ command = "exiv2 -d a delete #{file}"
44
+ Open3.popen3(command) do |stdin, stdout, stderr|
45
+ if stderr.gets
46
+ logger.warn "Could not delete metadata: #{stderr.gets}"
47
+ end
48
+ end
49
+ end
50
+
51
+ def write_metadata(data = {})
52
+ logger.info "Writing metadata to #{file}."
53
+ write_value('ObjectName', name)
54
+ data.each do |key, value|
55
+ write_value(key.to_s.capitalize, value)
56
+ end
57
+ end
58
+
59
+ def write_value(key, value)
60
+ command = "exiv2 -M \"set Iptc.Application2.#{key} String #{value}\" #{file}"
61
+ Open3.popen3(command) do |stdin, stdout, stderr|
62
+ if stderr.gets
63
+ logger.warn "Failed to write #{value} to #{key}: #{stderr.gets}"
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ module APDM
3
+ class Saxo
4
+ class Metadata
5
+
6
+ class << self
7
+ def sanitize(s)
8
+ s.gsub(/`/, "'").gsub(/´/, '\'').gsub(/"/, '\"').gsub('<3', ':heart:').gsub(/[<>]/, '').squeeze(' ')
9
+ end
10
+
11
+ def to_iso88591(utf8_string)
12
+ utf8_string.encode(Encoding::ISO_8859_1, Encoding::UTF_8, :undef => :replace)
13
+ end
14
+ end
15
+
16
+ attr_accessor :metadata
17
+
18
+ def initialize(data = {})
19
+ data = data.dup
20
+ self.metadata = data.each {|k,v| data[k] = convert(Metadata.sanitize(v))}
21
+ end
22
+
23
+ def to(name, path, options = {})
24
+ iptc = IPTC.new(name, path, options)
25
+ iptc.write(metadata)
26
+ iptc
27
+ end
28
+
29
+ private
30
+
31
+ def convert(value)
32
+ Metadata.to_iso88591(value)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,67 @@
1
+ module APDM
2
+
3
+ class SaxoTransferError < StandardError; end
4
+
5
+ class Saxo
6
+ class Remote
7
+
8
+ attr_accessor :saxo, :photo, :local_size, :remote_size
9
+ def initialize(saxo, photo)
10
+ self.saxo = saxo
11
+ self.photo = photo
12
+ end
13
+
14
+ def logger
15
+ APDM::Saxo.logger
16
+ end
17
+
18
+ def source
19
+ @source ||= photo.file
20
+ end
21
+
22
+ def destination
23
+ @destination ||= "#{saxo.remote_dir}/#{photo.name}"
24
+ end
25
+
26
+ def transfer
27
+ logger.info("Begin transfer of #{source} to #{destination}")
28
+ Timeout.timeout(30) do
29
+ Net::FTP.open(saxo.server, saxo.username, saxo.password) do |ftp|
30
+ Timeout.timeout(20) do
31
+ upload(ftp)
32
+ end
33
+ Timeout.timeout(10) do
34
+ cleanup(ftp)
35
+ end
36
+ end
37
+ end
38
+ return true if transfer_succeeded?
39
+
40
+ raise SaxoTransferError("Upload failed [#{local_size}/#{remote_size}]. Source: #{source} -- destination: #{destination}")
41
+ end
42
+
43
+ def upload(ftp)
44
+ ftp.passive = true
45
+ ftp.putbinaryfile(source, destination)
46
+ self.remote_size = ftp.size(destination)
47
+ end
48
+
49
+ def cleanup(ftp)
50
+ if transfer_succeeded?
51
+ File.delete(source)
52
+ else
53
+ ftp.delete(destination)
54
+ end
55
+ end
56
+
57
+ def transfer_succeeded?
58
+ local_size == remote_size
59
+ end
60
+
61
+ def local_size
62
+ @local_size ||= File.size(source)
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,85 @@
1
+ require "apdm"
2
+
3
+ module Sinatra
4
+ module APDM
5
+ module Helpers
6
+
7
+ def current_channel
8
+ host = request.env['HTTP_X_FORWARDED_HOST'] || request.host
9
+ ::APDM::Channel.find_by_domain(host) || ::APDM::Channel.find_by_domain("avisnavn.no")
10
+ end
11
+
12
+ def design_elements
13
+ @design_elements ||= ::APDM::DesignElements.new(current_channel.label, :api_key => self.settings.design_elements_api_key)
14
+ end
15
+
16
+ def ad_tech
17
+ ad_tech_for(::APDM::CHANNELS.random_production_channel)
18
+ end
19
+
20
+ def ad_tech_for(channel)
21
+ @ad_tech_for ||= {}
22
+ @ad_tech_for[channel.label] ||= ::APDM::AdTech.new(channel, :context_key => self.settings.ad_tech_context_prefix)
23
+ end
24
+
25
+ def ad_tech_api_js
26
+ # This snippet is needed by the ad_tech scripts and should be included in the head tag of pages displaying ad_tech ads
27
+ # Note: its an extract of code found in apdm JavaScript as per august 2012 and may be cause future breakage
28
+ # It hurts but it works
29
+ <<-js
30
+ window.api = {"cookie": {
31
+ "del": function (name,path,domain){var cookie=name+"="+((path)?";path="+path:"");cookie+=((domain)?";domain="+domain:"");cookie+=";expires=Thu, 01-Jan-1970 00:00:01 GMT";if(this.get(name)){document.cookie=cookie;}},
32
+ "get": function (name){var dc=document.cookie;if(dc===""){return false;}},
33
+ "isOn": function (){this.set("apiCookiesOnCheck","true",365);return(this.get("apiCookiesOnCheck")=="true");},
34
+ "set": function (name,value,expires,path,domain,secure){var fDate=new Date();var exDate=fDate.getTime();exDate+=1000*3600*24*expires;fDate.setTime(exDate);name+="="+escape(value)+((expires)?"; expires="+fDate.toGMTString():"");name+=((path)?"; path="+path:"");name+=((domain)?"; domain="+domain:"");name+=((secure)?"; secure":"");document.cookie=name;}
35
+ }};
36
+ js
37
+ end
38
+
39
+ def design_elements_css_path
40
+ "#{request.script_name}/apdm-design-elements.css"
41
+ end
42
+ end
43
+
44
+ def self.registered(app)
45
+ app.get '/apdm-design-elements.css' do
46
+ headers('Content-Type' => 'text/css', 'X-Content-Type-Options' => 'nosniff')
47
+ design_elements.css
48
+ end
49
+
50
+ app.helpers(Sinatra::APDM::Helpers)
51
+ end
52
+
53
+ def apdm_configure(&blk)
54
+ self.instance_exec(&blk)
55
+ end
56
+
57
+ def set_design_elements_api_key(api_key)
58
+ set :design_elements_api_key, api_key
59
+ end
60
+
61
+ def set_ad_tech_context_prefix(context_prefix)
62
+ set :ad_tech_context_prefix, context_prefix
63
+ end
64
+
65
+ # Here be workarounds for the diabolical evil apdm proxy
66
+ def enable_apdm_proxy_workarounds
67
+ before do
68
+ # Enforce a trailing slash for root requests.
69
+ # i.e. /vis/bandwagon ==redirects to==> /vis/bandwagon/
70
+ # The evil apdm proxy sets cookies on path with trailing slash (e.g. /vis/bandwagon/)
71
+ # so a user entering /vis/bandwagon (without trailing slash) will loose its credentials. This is the workaround.
72
+ if request.path_info == '/' and not request.env['REQUEST_PATH'].match(/\/$/)
73
+ redirect request.env['REQUEST_PATH']+"/"
74
+ end
75
+ end
76
+ end
77
+
78
+ # Cache headers required/recommended by the apdm proxy
79
+ def enable_apdm_cache_headers
80
+ before do
81
+ cache_control :private, :no_cache, :no_store, :must_revalidate
82
+ end
83
+ end
84
+ end
85
+ end