macros-garb 0.2.6

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.
@@ -0,0 +1,38 @@
1
+ module Garb
2
+ class DataRequest
3
+
4
+ def initialize(base_url, parameters={})
5
+ @base_url = base_url
6
+ @parameters = parameters
7
+ end
8
+
9
+ def query_string
10
+ parameter_list = @parameters.map {|k,v| "#{k}=#{v}" }
11
+ parameter_list.empty? ? '' : "?#{parameter_list.join('&')}"
12
+ end
13
+
14
+ def uri
15
+ URI.parse(@base_url)
16
+ end
17
+
18
+ def send_request
19
+ http_retries = 5
20
+ begin
21
+ http = Net::HTTP.new(uri.host, uri.port)
22
+ http.use_ssl = true
23
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
24
+ http.read_timeout = 60
25
+ response = http.get("#{uri.path}#{query_string}", 'Authorization' => "GoogleLogin auth=#{Session.auth_token}")
26
+ raise response.body.inspect unless response.is_a?(Net::HTTPOK)
27
+ response
28
+ rescue Timeout::Error
29
+ sleep(2)
30
+ retry if (http_retries -= 1 > 0)
31
+ raise Timeout::Error, "Timeout connecting to google analytics, giving up"
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+
38
+
@@ -0,0 +1,21 @@
1
+ module Garb
2
+ class OAuthSession
3
+ attr_accessor :access_token
4
+
5
+ OAuthGetRequestToken = "https://www.google.com/accounts/OAuthGetRequestToken"
6
+ OAuthAuthorizeToken = "https://www.google.com/accounts/OAuthAuthorizeToken"
7
+ OAuthGetAccessToken = "https://www.google.com/accounts/OAuthGetAccessToken"
8
+
9
+ def get_request_token
10
+
11
+ end
12
+
13
+ def authorization_request
14
+
15
+ end
16
+
17
+ def get_access_token
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,50 @@
1
+ module Garb
2
+ class Profile
3
+
4
+ attr_reader :table_id, :title, :account_name, :account_id
5
+
6
+ class Property
7
+ include HappyMapper
8
+
9
+ tag 'property'
10
+ namespace 'dxp'
11
+
12
+ attribute :name, String
13
+ attribute :value, String
14
+
15
+ def instance_name
16
+ name.from_ga.underscored
17
+ end
18
+ end
19
+
20
+ class Entry
21
+ include HappyMapper
22
+
23
+ tag 'entry'
24
+
25
+ element :title, String
26
+ element :tableId, String, :namespace => 'dxp'
27
+
28
+ has_many :properties, Property
29
+ end
30
+
31
+ def initialize(entry)
32
+ @title = entry.title
33
+ @table_id = entry.tableId
34
+
35
+ entry.properties.each do |p|
36
+ instance_variable_set :"@#{p.instance_name}", p.value
37
+ end
38
+ end
39
+
40
+ def id
41
+ @table_id.from_ga
42
+ end
43
+
44
+ def self.all
45
+ url = "https://www.google.com/analytics/feeds/accounts/default"
46
+ response = DataRequest.new(url).send_request
47
+ Entry.parse(response.body).map {|entry| new(entry)}
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,31 @@
1
+ module Garb
2
+ class Report
3
+ include Resource::ResourceMethods
4
+
5
+ MONTH = 2592000
6
+ URL = "https://www.google.com/analytics/feeds/data"
7
+
8
+ def initialize(profile, opts={})
9
+ @profile = profile
10
+
11
+ @start_date = opts.fetch(:start_date, Time.now - MONTH)
12
+ @end_date = opts.fetch(:end_date, Time.now)
13
+ @limit = opts.fetch(:limit, nil)
14
+ @offset = opts.fetch(:offset, nil)
15
+
16
+ # clear filters and sort
17
+ @filters = ReportParameter.new(:filters)
18
+ @sorts = ReportParameter.new(:sort)
19
+
20
+ metrics opts.fetch(:metrics, [])
21
+ dimensions opts.fetch(:dimensions, [])
22
+ filter opts.fetch(:filter, [])
23
+ sort opts.fetch(:sort, [])
24
+ end
25
+
26
+ def results
27
+ ReportResponse.new(send_request_for_body).results
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,36 @@
1
+ module Garb
2
+ class ReportParameter
3
+
4
+ attr_reader :elements
5
+
6
+ def initialize(name)
7
+ @name = name
8
+ @elements = []
9
+ end
10
+
11
+ def name
12
+ @name.to_s
13
+ end
14
+
15
+ def <<(element)
16
+ (@elements += [element].flatten).compact!
17
+ self
18
+ end
19
+
20
+ def to_params
21
+ params = self.elements.map do |elem|
22
+ case elem
23
+ when Hash
24
+ elem.collect do |k,v|
25
+ next unless k.is_a?(Operator)
26
+ "#{k.target}#{URI.encode(k.operator.to_s, /[=<>]/)}#{CGI::escape(v.to_s)}"
27
+ end.join(';')
28
+ else
29
+ elem.to_ga
30
+ end
31
+ end.join(',')
32
+
33
+ params.empty? ? {} : {self.name => params}
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,62 @@
1
+ module Garb
2
+ class ReportResponse
3
+ # include Enumerable
4
+
5
+ def initialize(response_body)
6
+ @xml = response_body
7
+ end
8
+
9
+ def parse
10
+ entries = Entry.parse(@xml)
11
+
12
+ @results = entries.collect do |entry|
13
+ hash = {}
14
+
15
+ entry.metrics.each do |m|
16
+ name = m.name.sub(/^ga\:/,'').underscored
17
+ hash.merge!({name => m.value})
18
+ end
19
+
20
+ entry.dimensions.each do |d|
21
+ name = d.name.sub(/^ga\:/,'').underscored
22
+ hash.merge!({name => d.value})
23
+ end
24
+
25
+ OpenStruct.new(hash)
26
+ end
27
+ end
28
+
29
+ def results
30
+ @results || parse
31
+ end
32
+
33
+ class Metric
34
+ include HappyMapper
35
+
36
+ tag 'metric'
37
+ namespace 'dxp'
38
+
39
+ attribute :name, String
40
+ attribute :value, String
41
+ end
42
+
43
+ class Dimension
44
+ include HappyMapper
45
+
46
+ tag 'dimension'
47
+ namespace 'dxp'
48
+
49
+ attribute :name, String
50
+ attribute :value, String
51
+ end
52
+
53
+ class Entry
54
+ include HappyMapper
55
+
56
+ tag 'entry'
57
+
58
+ has_many :metrics, Metric
59
+ has_many :dimensions, Dimension
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,89 @@
1
+ module Garb
2
+ module Resource
3
+ MONTH = 2592000
4
+ URL = "https://www.google.com/analytics/feeds/data"
5
+
6
+ def self.included(report)
7
+ report.extend(ResourceMethods)
8
+ end
9
+
10
+ module ResourceMethods
11
+
12
+ def metrics(*fields)
13
+ @metrics ||= ReportParameter.new(:metrics)
14
+ @metrics << fields
15
+ end
16
+
17
+ def dimensions(*fields)
18
+ @dimensions ||= ReportParameter.new(:dimensions)
19
+ @dimensions << fields
20
+ end
21
+
22
+ def filter(*hash)
23
+ @filters << hash
24
+ end
25
+
26
+ def filters
27
+ @filters ||= ReportParameter.new(:filters)
28
+ end
29
+
30
+ def sort(*fields)
31
+ @sorts << fields
32
+ end
33
+
34
+ def sorts
35
+ @sorts ||= ReportParameter.new(:sort)
36
+ end
37
+
38
+ def results(profile, opts = {}, &block)
39
+ @profile = profile
40
+
41
+ # clear filters and sort
42
+ @filters = ReportParameter.new(:filters)
43
+ @sorts = ReportParameter.new(:sort)
44
+
45
+ @start_date = opts.fetch(:start_date, Time.now - MONTH)
46
+ @end_date = opts.fetch(:end_date, Time.now)
47
+ @limit = opts.fetch(:limit, nil)
48
+ @offset = opts.fetch(:offset, nil)
49
+
50
+ instance_eval(&block) if block_given?
51
+
52
+ ReportResponse.new(send_request_for_body).results
53
+ end
54
+
55
+ def page_params
56
+ {'max-results' => @limit, 'start-index' => @offset}.reject{|k,v| v.nil?}
57
+ end
58
+
59
+ def default_params
60
+ {'ids' => @profile.table_id,
61
+ 'start-date' => format_time(@start_date),
62
+ 'end-date' => format_time(@end_date)}
63
+ end
64
+
65
+ def params
66
+ [
67
+ metrics.to_params,
68
+ dimensions.to_params,
69
+ sorts.to_params,
70
+ filters.to_params,
71
+ page_params
72
+ ].inject(default_params) do |p, i|
73
+ p.merge(i)
74
+ end
75
+ end
76
+
77
+ def format_time(t)
78
+ t.strftime('%Y-%m-%d')
79
+ end
80
+
81
+ def send_request_for_body
82
+ request = DataRequest.new(URL, params)
83
+ response = request.send_request
84
+ response.body
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,19 @@
1
+ module Garb
2
+ class Session
3
+
4
+ def self.login(email, password, opts={})
5
+ @email = email
6
+ auth_request = AuthenticationRequest.new(email, password)
7
+ @auth_token = auth_request.auth_token(opts)
8
+ end
9
+
10
+ def self.auth_token
11
+ @auth_token
12
+ end
13
+
14
+ def self.email
15
+ @email
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module Garb
2
+ module Version
3
+
4
+ MAJOR = 0
5
+ MINOR = 2
6
+ TINY = 6
7
+
8
+ def self.to_s # :nodoc:
9
+ [MAJOR, MINOR, TINY].join('.')
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,67 @@
1
+ ##
2
+ ## cacert.pem-foo -- Bundle of CA Root Certificates
3
+ ##
4
+ ## Converted at: Thu Mar 26 21:23:06 2009 UTC
5
+ ##
6
+ ## This is a bundle of X.509 certificates of public Certificate Authorities
7
+ ## (CA). These were automatically extracted from Mozilla's root certificates
8
+ ## file (certdata.txt). This file can be found in the mozilla source tree:
9
+ ## '/mozilla/security/nss/lib/ckfw/builtins/certdata.txt'
10
+ ##
11
+ ## It contains the certificates in PEM format and therefore
12
+ ## can be directly used with curl / libcurl / php_curl, or with
13
+ ## an Apache+mod_ssl webserver for SSL client authentication.
14
+ ## Just configure this file as the SSLCACertificateFile.
15
+ ##
16
+
17
+ # ***** BEGIN LICENSE BLOCK *****
18
+ # Version: MPL 1.1/GPL 2.0/LGPL 2.1
19
+ #
20
+ # The contents of this file are subject to the Mozilla Public License Version
21
+ # 1.1 (the "License"); you may not use this file except in compliance with
22
+ # the License. You may obtain a copy of the License at
23
+ # http://www.mozilla.org/MPL/
24
+ #
25
+ # Software distributed under the License is distributed on an "AS IS" basis,
26
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
27
+ # for the specific language governing rights and limitations under the
28
+ # License.
29
+ #
30
+ # The Original Code is the Netscape security libraries.
31
+ #
32
+ # The Initial Developer of the Original Code is
33
+ # Netscape Communications Corporation.
34
+ # Portions created by the Initial Developer are Copyright (C) 1994-2000
35
+ # the Initial Developer. All Rights Reserved.
36
+ #
37
+ # Contributor(s):
38
+ #
39
+ # Alternatively, the contents of this file may be used under the terms of
40
+ # either the GNU General Public License Version 2 or later (the "GPL"), or
41
+ # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
42
+ # in which case the provisions of the GPL or the LGPL are applicable instead
43
+ # of those above. If you wish to allow use of your version of this file only
44
+ # under the terms of either the GPL or the LGPL, and not to allow others to
45
+ # use your version of this file under the terms of the MPL, indicate your
46
+ # decision by deleting the provisions above and replace them with the notice
47
+ # and other provisions required by the GPL or the LGPL. If you do not delete
48
+ # the provisions above, a recipient may use your version of this file under
49
+ # the terms of any one of the MPL, the GPL or the LGPL.
50
+ #
51
+ # ***** END LICENSE BLOCK *****
52
+ # @(#) $RCSfile: certdata.txt,v $ $Revision: 1.51 $ $Date: 2009/01/15 22:35:15 $
53
+
54
+ Verisign/RSA Secure Server CA
55
+ =============================
56
+ -----BEGIN CERTIFICATE-----
57
+ MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx
58
+ IDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy
59
+ IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVow
60
+ XzELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQL
61
+ EyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUA
62
+ A4GJADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII0haGN1Xp
63
+ sSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphIuR2nKRoTLkoRWZweFdVJ
64
+ VCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZIhvcNAQECBQADfgBl3X7hsuyw4jrg7HFG
65
+ mhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2
66
+ qUtN8iD3zV9/ZHuO3ABc1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA==
67
+ -----END CERTIFICATE-----
@@ -0,0 +1,33 @@
1
+ <?xml version='1.0' encoding='UTF-8'?>
2
+ <feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:dxp='http://schemas.google.com/analytics/2009'>
3
+ <id>http://www.google.com/analytics/feeds/accounts/email@example.com</id>
4
+ <updated>2009-03-27T08:14:28.000-07:00</updated>
5
+ <title type='text'>Profile list for email@example.com</title>
6
+ <link rel='self' type='application/atom+xml' href='http://www.google.com/analytics/feeds/accounts/email@example.com'/>
7
+ <author><name>Google Analytics</name></author>
8
+ <generator version='1.0'>Google Analytics</generator>
9
+ <openSearch:totalResults>2</openSearch:totalResults>
10
+ <openSearch:startIndex>1</openSearch:startIndex>
11
+ <openSearch:itemsPerPage>2</openSearch:itemsPerPage>
12
+ <entry>
13
+ <id>http://www.google.com/analytics/feeds/accounts/ga:12345</id>
14
+ <updated>2008-07-21T14:05:57.000-07:00</updated>
15
+ <title type='text'>Historical</title>
16
+ <dxp:tableId>ga:12345</dxp:tableId>
17
+ <dxp:property name='ga:accountId' value='1111'/>
18
+ <dxp:property name='ga:accountName' value='Blog Beta'/>
19
+ <dxp:property name='ga:profileId' value='1212'/>
20
+ <dxp:property name='ga:webPropertyId' value='UA-1111-1'/>
21
+ </entry>
22
+ <entry>
23
+ <id>http://www.google.com/analytics/feeds/accounts/ga:12346</id>
24
+ <updated>2008-11-24T11:51:07.000-08:00</updated>
25
+ <title type='text'>Presently</title>
26
+ <dxp:tableId>ga:12346</dxp:tableId>
27
+ <dxp:property name='ga:accountId' value='1111'/>
28
+ <dxp:property name='ga:accountName' value='Blog Beta'/>
29
+ <dxp:property name='ga:profileId' value='1213'/>
30
+ <dxp:property name='ga:webPropertyId' value='UA-1111-2'/>
31
+ </entry>
32
+ </feed>
33
+