StatsCollect 0.1.0.20101220
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +2 -0
- data/ChangeLog +5 -0
- data/Credits +31 -0
- data/LICENSE +31 -0
- data/README +18 -0
- data/ReleaseInfo +8 -0
- data/StatsCollect.conf.rb.example +91 -0
- data/TODO +1 -0
- data/bin/StatsCollect.rb +30 -0
- data/lib/StatsCollect/Backends/MySQL.rb +190 -0
- data/lib/StatsCollect/Backends/Terminal.rb +157 -0
- data/lib/StatsCollect/Locations/AddThis.rb +65 -0
- data/lib/StatsCollect/Locations/Facebook.rb +62 -0
- data/lib/StatsCollect/Locations/FacebookArtist.rb +63 -0
- data/lib/StatsCollect/Locations/FacebookLike.rb +51 -0
- data/lib/StatsCollect/Locations/GoogleSearch.rb +39 -0
- data/lib/StatsCollect/Locations/MySpace.rb +224 -0
- data/lib/StatsCollect/Locations/ReverbNation.rb +143 -0
- data/lib/StatsCollect/Locations/Tweets.rb +51 -0
- data/lib/StatsCollect/Locations/Twitter.rb +46 -0
- data/lib/StatsCollect/Locations/Youtube.rb +69 -0
- data/lib/StatsCollect/Notifiers/None.rb +24 -0
- data/lib/StatsCollect/Notifiers/SendMail.rb +34 -0
- data/lib/StatsCollect/Stats.rb +447 -0
- data/lib/StatsCollect/StatsProxy.rb +106 -0
- metadata +89 -0
data/AUTHORS
ADDED
data/ChangeLog
ADDED
data/Credits
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
= Projects used by StatsCollect
|
2
|
+
|
3
|
+
== Ruby
|
4
|
+
* Yukihiro « matz » Matsumoto (http://www.rubyist.net/~matz/)
|
5
|
+
* http://www.ruby-lang.org/
|
6
|
+
* Thanks a lot Matz for this truly wonderful language !
|
7
|
+
|
8
|
+
= Projects used by StatsCollect plugins
|
9
|
+
|
10
|
+
== Plugin Backends/MySQL
|
11
|
+
|
12
|
+
=== ruby-mysql
|
13
|
+
* TOMITA Masahiro (http://www.tmtm.org/)
|
14
|
+
* http://www.tmtm.org/en/ruby/mysql/
|
15
|
+
* Used to access MySQL databases.
|
16
|
+
|
17
|
+
== Plugin Notifiers/SendMail
|
18
|
+
|
19
|
+
=== Mail
|
20
|
+
* Mikel Lindsaar (http://lindsaar.net/)
|
21
|
+
* http://github.com/mikel/mail
|
22
|
+
* Used to send notification mails.
|
23
|
+
|
24
|
+
== Most Locations plugins
|
25
|
+
|
26
|
+
=== Mechanize
|
27
|
+
* Mike Dalessio (http://github.com/flavorjones)
|
28
|
+
* http://mechanize.rubyforge.org
|
29
|
+
* Used to scrap web pages to get statistics.
|
30
|
+
|
31
|
+
= People that helped a lot in developing StatsCollect
|
data/LICENSE
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
The license stated herein is a copy of the BSD License (modified on July 1999).
|
3
|
+
The AUTHOR mentionned below refers to the list of people involved in the
|
4
|
+
creation and modification of any file included in the delivered package.
|
5
|
+
This list is found in the file named AUTHORS.
|
6
|
+
The AUTHORS and LICENSE files have to be included in any release of software
|
7
|
+
embedding source code of this package, or using it as a derivative software.
|
8
|
+
|
9
|
+
Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
10
|
+
|
11
|
+
Redistribution and use in source and binary forms, with or without
|
12
|
+
modification, are permitted provided that the following conditions are met:
|
13
|
+
|
14
|
+
1. Redistributions of source code must retain the above copyright notice,
|
15
|
+
this list of conditions and the following disclaimer.
|
16
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
17
|
+
this list of conditions and the following disclaimer in the documentation
|
18
|
+
and/or other materials provided with the distribution.
|
19
|
+
3. The name of the author may not be used to endorse or promote products
|
20
|
+
derived from this software without specific prior written permission.
|
21
|
+
|
22
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
23
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
24
|
+
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
25
|
+
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
26
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
27
|
+
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
28
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
29
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
30
|
+
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
31
|
+
OF SUCH DAMAGE.
|
data/README
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
-- This file is best viewed when processed by rdoc.
|
2
|
+
++
|
3
|
+
|
4
|
+
= StatsCollect
|
5
|
+
|
6
|
+
StatsCollect is a little framework gathering statistics from external sources (social networks, web sites...), stored in pluggable backends. It can be very easily extended thanks to its plugins (currently include Facebook, Myspace, Youtube, Google).
|
7
|
+
|
8
|
+
== Where is the documentation ?
|
9
|
+
|
10
|
+
Check the website at http://statscollect.sourceforge.net
|
11
|
+
|
12
|
+
== Who wrote it ?
|
13
|
+
|
14
|
+
Check the AUTHORS[link:files/AUTHORS.html] file.
|
15
|
+
|
16
|
+
== What is the license ?
|
17
|
+
|
18
|
+
You can find out in the LICENSE[link:files/LICENSE.html] file.
|
data/ReleaseInfo
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
{
|
2
|
+
# Configuration for Backends
|
3
|
+
:Backends => {
|
4
|
+
'MySQL' => {
|
5
|
+
:DBHost => 'localhost',
|
6
|
+
:DBUser => 'mydbuser',
|
7
|
+
:DBPassword => '*****',
|
8
|
+
:DBName => 'mydb',
|
9
|
+
},
|
10
|
+
'Terminal' => {}
|
11
|
+
},
|
12
|
+
|
13
|
+
# Configuration for Notifiers
|
14
|
+
:Notifiers => {
|
15
|
+
'SendMail' => {
|
16
|
+
:SMTP => {
|
17
|
+
:address => "mail.myhost.com",
|
18
|
+
:port => 25,
|
19
|
+
:domain => 'mail.myhost.com',
|
20
|
+
:user_name => 'smtpuser',
|
21
|
+
:password => '*****',
|
22
|
+
:authentication => nil,
|
23
|
+
:enable_starttls_auto => false
|
24
|
+
},
|
25
|
+
# The From field
|
26
|
+
:From => 'MailOriginator@myhost.com',
|
27
|
+
# To who the notifications are sent
|
28
|
+
:To => 'mail@host.com'
|
29
|
+
},
|
30
|
+
'None' => {}
|
31
|
+
},
|
32
|
+
|
33
|
+
# Configuration for Locations
|
34
|
+
:Locations => {
|
35
|
+
'MySpace' => {
|
36
|
+
:LoginEMail => 'MySpaceLogin',
|
37
|
+
:LoginPassword => '****',
|
38
|
+
# This is the last part of profile URL
|
39
|
+
:MySpaceName => 'myspace_user',
|
40
|
+
# List the blogs IDs. They can be taken from their respective URL.
|
41
|
+
:BlogsID => [
|
42
|
+
123456789,
|
43
|
+
234567891,
|
44
|
+
345678912
|
45
|
+
]
|
46
|
+
},
|
47
|
+
'Facebook' => {
|
48
|
+
:LoginEMail => 'FacebookLogin',
|
49
|
+
:LoginPassword => '*****'
|
50
|
+
},
|
51
|
+
'FacebookArtist' => {
|
52
|
+
:LoginEMail => 'FacebookLogin',
|
53
|
+
:LoginPassword => '*****',
|
54
|
+
# URL of the page (after the /pages sub-directory) to fetch stats from
|
55
|
+
:PageID => 'ArtistName/123456789012345'
|
56
|
+
},
|
57
|
+
'ReverbNation' => {
|
58
|
+
:LoginEMail => 'ReverbNationLogin',
|
59
|
+
:LoginPassword => '*****'
|
60
|
+
},
|
61
|
+
'AddThis' => {
|
62
|
+
:Login => 'AddThisLogin',
|
63
|
+
:Password => '*****',
|
64
|
+
# List of objects for which we retrieve the AddThis stats
|
65
|
+
:Objects => [
|
66
|
+
'www.myhost.com'
|
67
|
+
]
|
68
|
+
},
|
69
|
+
'FacebookLike' => {
|
70
|
+
# List of objects for which we retrieve the Facebook likes
|
71
|
+
:Objects => [
|
72
|
+
'www.myhost.com'
|
73
|
+
]
|
74
|
+
},
|
75
|
+
'Tweets' => {
|
76
|
+
# List of objects for which we retrieve the tweets
|
77
|
+
:Objects => [
|
78
|
+
'www.myhost.com'
|
79
|
+
]
|
80
|
+
},
|
81
|
+
'Twitter' => {
|
82
|
+
:Name => 'TwitterID'
|
83
|
+
},
|
84
|
+
'GoogleSearch' => {
|
85
|
+
# List of objects for which we will query Google search
|
86
|
+
:Objects => [
|
87
|
+
'GoogleSearchString'
|
88
|
+
]
|
89
|
+
},
|
90
|
+
}
|
91
|
+
}
|
data/TODO
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* MySpace: Get the user ID by parsing the Profile URL and remove :MySpaceName configuration option.
|
data/bin/StatsCollect.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
4
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
5
|
+
#++
|
6
|
+
|
7
|
+
# Uncomment for PlanetHoster
|
8
|
+
#require 'rubygems'
|
9
|
+
#ENV['GEM_PATH'] = "/home/murieles/ruby/gems:/home/murieles/.gem/ruby/1.8:/usr/lib/ruby/gems/1.8"
|
10
|
+
#Gem.clear_paths
|
11
|
+
|
12
|
+
require 'rUtilAnts/Logging'
|
13
|
+
RUtilAnts::Logging::initializeLogging('','')
|
14
|
+
require 'tmpdir'
|
15
|
+
lLogFile = "#{Dir.tmpdir}/StatsCollect_#{Process.pid}.log"
|
16
|
+
setLogFile(lLogFile)
|
17
|
+
require 'StatsCollect/Stats'
|
18
|
+
|
19
|
+
rErrorCode = 0
|
20
|
+
|
21
|
+
lStatsCollect = StatsCollect::Stats.new
|
22
|
+
rErrorCode = lStatsCollect.setup(ARGV)
|
23
|
+
if (rErrorCode == 0)
|
24
|
+
rErrorCode = lStatsCollect.collect
|
25
|
+
lStatsCollect.notify(lLogFile)
|
26
|
+
end
|
27
|
+
|
28
|
+
File.unlink(lLogFile)
|
29
|
+
|
30
|
+
exit rErrorCode
|
@@ -0,0 +1,190 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module StatsCollect
|
7
|
+
|
8
|
+
module Backends
|
9
|
+
|
10
|
+
class MySQL
|
11
|
+
|
12
|
+
# Initialize a session of this backend
|
13
|
+
#
|
14
|
+
# Parameters:
|
15
|
+
# * *iConf* (<em>map<Symbol,Object></em>): Configuration of this backend
|
16
|
+
def initSession(iConf)
|
17
|
+
require 'mysql'
|
18
|
+
@MySQLConnection = Mysql.new(iConf[:DBHost], iConf[:DBUser], iConf[:DBPassword], iConf[:DBName])
|
19
|
+
# TODO: Use bound variables everywhere !
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get the next stats order.
|
23
|
+
# Code to begin a new transaction can be set in this method too.
|
24
|
+
#
|
25
|
+
# Return:
|
26
|
+
# * _DateTime_: The time stamp, or nil if no new stats order
|
27
|
+
# * <em>list<String></em>: List of locations
|
28
|
+
# * <em>list<String></em>: List of objects
|
29
|
+
# * <em>list<String></em>: List of categories
|
30
|
+
# * _Integer_: The order status
|
31
|
+
def getNextStatsOrder
|
32
|
+
rTimeStamp = nil
|
33
|
+
rLstLocations = nil
|
34
|
+
rLstObjects = nil
|
35
|
+
rLstCategories = nil
|
36
|
+
rStatus = nil
|
37
|
+
|
38
|
+
if (defined?(@LstStatsOrders) == nil)
|
39
|
+
@LstStatsOrders = @MySQLConnection.query('SELECT id, timestamp, objects_list, categories_list, locations_list, status FROM stats_orders WHERE status=0 OR status=1 ORDER BY timestamp DESC')
|
40
|
+
end
|
41
|
+
if (!@LstStatsOrders.empty?)
|
42
|
+
lID, rTimeStamp, lStrLocations, lStrObjects, lStrCategories, rStatus = @LstStatsOrders.pop
|
43
|
+
rLstLocations = lStrLocations.split('|')
|
44
|
+
rLstObjects = lStrObjects.split('|')
|
45
|
+
rLstCategories = lStrCategories.split('|')
|
46
|
+
@MySQLConnection.query('start transaction')
|
47
|
+
@MySQLConnection.query("DELETE FROM stats_orders WHERE id=#{lID}")
|
48
|
+
end
|
49
|
+
|
50
|
+
return rTimeStamp, rLstLocations, rLstObjects, rLstCategories, rStatus
|
51
|
+
end
|
52
|
+
|
53
|
+
# Get the list of known locations
|
54
|
+
#
|
55
|
+
# Return:
|
56
|
+
# * <em>map<String,Integer></em>: Each location with its associated ID
|
57
|
+
def getKnownLocations
|
58
|
+
rKnownLocations = {}
|
59
|
+
|
60
|
+
@MySQLConnection.query('SELECT name, id FROM stats_locations').each do |iRow|
|
61
|
+
iLocationName, iLocationID = iRow
|
62
|
+
rKnownLocations[iLocationName] = iLocationID.to_i
|
63
|
+
end
|
64
|
+
|
65
|
+
return rKnownLocations
|
66
|
+
end
|
67
|
+
|
68
|
+
# Get the list of known categories
|
69
|
+
#
|
70
|
+
# Return:
|
71
|
+
# * <em>map<String,[Integer,Integer]></em>: Each category with its associated ID and value type
|
72
|
+
def getKnownCategories
|
73
|
+
rKnownCategories = {}
|
74
|
+
|
75
|
+
@MySQLConnection.query('SELECT name, id, value_type FROM stats_categories').each do |iRow|
|
76
|
+
iCategoryName, iCategoryID, iValueType = iRow
|
77
|
+
rKnownCategories[iCategoryName] = [ iCategoryID.to_i, iValueType.to_i ]
|
78
|
+
end
|
79
|
+
|
80
|
+
return rKnownCategories
|
81
|
+
end
|
82
|
+
|
83
|
+
# Get the list of known objects
|
84
|
+
#
|
85
|
+
# Return:
|
86
|
+
# * <em>map<String,Integer></em>: Each object with its associated ID
|
87
|
+
def getKnownObjects
|
88
|
+
rKnownObjects = {}
|
89
|
+
|
90
|
+
@MySQLConnection.query('SELECT name, id FROM stats_objects').each do |iRow|
|
91
|
+
iObjectName, iObjectID = iRow
|
92
|
+
rKnownObjects[iObjectName] = iObjectID.to_i
|
93
|
+
end
|
94
|
+
|
95
|
+
return rKnownObjects
|
96
|
+
end
|
97
|
+
|
98
|
+
# Add a new location
|
99
|
+
#
|
100
|
+
# Parameters:
|
101
|
+
# * *iLocation* (_String_): The location
|
102
|
+
# Return:
|
103
|
+
# * _Integer_: Its resulting ID
|
104
|
+
def addLocation(iLocation)
|
105
|
+
@MySQLConnection.query("INSERT INTO stats_locations (name) VALUES ('#{@MySQLConnection.escape_string(iLocation)}')")
|
106
|
+
|
107
|
+
return @MySQLConnection.insert_id
|
108
|
+
end
|
109
|
+
|
110
|
+
# Add a new category
|
111
|
+
#
|
112
|
+
# Parameters:
|
113
|
+
# * *iCategory* (_String_): The category
|
114
|
+
# * *iValueType* (_Integer_): Its value type
|
115
|
+
# Return:
|
116
|
+
# * _Integer_: Its resulting ID
|
117
|
+
def addCategory(iCategory, iValueType)
|
118
|
+
@MySQLConnection.query("INSERT INTO stats_categories (name, value_type) VALUES ('#{@MySQLConnection.escape_string(iLocation)}', #{iValueType})")
|
119
|
+
|
120
|
+
return @MySQLConnection.insert_id
|
121
|
+
end
|
122
|
+
|
123
|
+
# Add a new object
|
124
|
+
#
|
125
|
+
# Parameters:
|
126
|
+
# * *iObject* (_String_): The object
|
127
|
+
# Return:
|
128
|
+
# * _Integer_: Its resulting ID
|
129
|
+
def addObject(iObject)
|
130
|
+
@MySQLConnection.query("INSERT INTO stats_objects (name) VALUES ('#{@MySQLConnection.escape_string(iObject)}')")
|
131
|
+
|
132
|
+
return @MySQLConnection.insert_id
|
133
|
+
end
|
134
|
+
|
135
|
+
# Add a new stat
|
136
|
+
#
|
137
|
+
# Parameters:
|
138
|
+
# * *iTimeStamp* (_DateTime_): The time stamp
|
139
|
+
# * *iLocationID* (_Integer_): Location ID
|
140
|
+
# * *iObjectID* (_Integer_): Object ID
|
141
|
+
# * *iCategoryID* (_Integer_): Category ID
|
142
|
+
# * *iValue* (_Object_): The value to store
|
143
|
+
# * *iValueType* (_Integer_): The value type
|
144
|
+
def addStat(iTimeStamp, iLocationID, iObjectID, iCategoryID, iValue, iValueType)
|
145
|
+
# Convert the value to its internal representation
|
146
|
+
lStrValue = nil
|
147
|
+
case iValueType
|
148
|
+
when STATS_VALUE_TYPE_INTEGER
|
149
|
+
lStrValue = iValue.to_s
|
150
|
+
when STATS_VALUE_TYPE_FLOAT
|
151
|
+
lStrValue = iValue.to_s
|
152
|
+
when STATS_VALUE_TYPE_PERCENTAGE
|
153
|
+
lStrValue = iValue.to_s
|
154
|
+
when STATS_VALUE_TYPE_UNKNOWN
|
155
|
+
lStrValue = iValue.to_s
|
156
|
+
else
|
157
|
+
logErr "Unknown category value type: #{iValueType}. It will be treated as Unknown."
|
158
|
+
lStrValue = iValue.to_s
|
159
|
+
end
|
160
|
+
# Add the new stat in the DB for real
|
161
|
+
@MySQLConnection.query("INSERT INTO stats_values (timestamp, stats_object_id, stats_category_id, stats_location_id, value) VALUES ('#{iTimeStamp.strftime('%Y-%m-%d %H:%M:%S')}', #{iObjectID}, #{iCategoryID}, #{iLocationID}, '#{lStrValue}')")
|
162
|
+
end
|
163
|
+
|
164
|
+
# Add a new stats order
|
165
|
+
#
|
166
|
+
# Parameters:
|
167
|
+
# * *iTimeStamp* (_DateTime_): The time stamp
|
168
|
+
# * *iLstLocations* (<em>list<String></em>): List of locations
|
169
|
+
# * *iLstObjects* (<em>list<String></em>): List of objects
|
170
|
+
# * *iLstCategories* (<em>list<String></em>): List of categories
|
171
|
+
# * *iStatus* (_Integer_): The order status
|
172
|
+
def putNewStatsOrder(iTimeStamp, iLstLocations, iLstObjects, iLstCategories, iStatus)
|
173
|
+
@MySQLConnection.query("INSERT INTO stats_orders (timestamp, locations_list, objects_list, categories_list, status) VALUES ('#{iTimeStamp.strftime('%Y-%m-%d %H:%M:%S')}', '#{@MySQLConnection.escape_string(iLstLocations.join('|'))}', '#{@MySQLConnection.escape_string(iLstObjects.join('|'))}', '#{@MySQLConnection.escape_string(iLstCategories.join('|'))}', #{iStatus})")
|
174
|
+
end
|
175
|
+
|
176
|
+
# Commit the current stats order transaction
|
177
|
+
def commit
|
178
|
+
@MySQLConnection.query('commit')
|
179
|
+
end
|
180
|
+
|
181
|
+
# Rollback the current stats order transaction
|
182
|
+
def rollback
|
183
|
+
@MySQLConnection.query('rollback')
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module StatsCollect
|
7
|
+
|
8
|
+
module Backends
|
9
|
+
|
10
|
+
class Terminal
|
11
|
+
|
12
|
+
# Initialize a session of this backend
|
13
|
+
#
|
14
|
+
# Parameters:
|
15
|
+
# * *iConf* (<em>map<Symbol,Object></em>): Configuration of this backend
|
16
|
+
def initSession(iConf)
|
17
|
+
@IdxID = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get the next stats order.
|
21
|
+
# Code to begin a new transaction can be set in this method too.
|
22
|
+
#
|
23
|
+
# Return:
|
24
|
+
# * _DateTime_: The time stamp, or nil if no new stats order
|
25
|
+
# * <em>list<String></em>: List of locations
|
26
|
+
# * <em>list<String></em>: List of objects
|
27
|
+
# * <em>list<String></em>: List of categories
|
28
|
+
# * _Integer_: The order status
|
29
|
+
def getNextStatsOrder
|
30
|
+
rTimeStamp = nil
|
31
|
+
rLstLocations = nil
|
32
|
+
rLstObjects = nil
|
33
|
+
rLstCategories = nil
|
34
|
+
rStatus = nil
|
35
|
+
|
36
|
+
if (defined?(@LstStatsOrders) == nil)
|
37
|
+
@LstStatsOrders = [
|
38
|
+
[ DateTime.now, [], [], [], STATS_ORDER_STATUS_TOBEPROCESSED ]
|
39
|
+
]
|
40
|
+
end
|
41
|
+
if (!@LstStatsOrders.empty?)
|
42
|
+
rTimeStamp, rLstLocations, rLstObjects, rLstCategories, rStatus = @LstStatsOrders.pop
|
43
|
+
end
|
44
|
+
|
45
|
+
return rTimeStamp, rLstLocations, rLstObjects, rLstCategories, rStatus
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get the list of known locations
|
49
|
+
#
|
50
|
+
# Return:
|
51
|
+
# * <em>map<String,Integer></em>: Each location with its associated ID
|
52
|
+
def getKnownLocations
|
53
|
+
rKnownLocations = {}
|
54
|
+
|
55
|
+
return rKnownLocations
|
56
|
+
end
|
57
|
+
|
58
|
+
# Get the list of known categories
|
59
|
+
#
|
60
|
+
# Return:
|
61
|
+
# * <em>map<String,[Integer,Integer]></em>: Each category with its associated ID and value type
|
62
|
+
def getKnownCategories
|
63
|
+
rKnownCategories = {}
|
64
|
+
|
65
|
+
return rKnownCategories
|
66
|
+
end
|
67
|
+
|
68
|
+
# Get the list of known objects
|
69
|
+
#
|
70
|
+
# Return:
|
71
|
+
# * <em>map<String,Integer></em>: Each object with its associated ID
|
72
|
+
def getKnownObjects
|
73
|
+
rKnownObjects = {}
|
74
|
+
|
75
|
+
return rKnownObjects
|
76
|
+
end
|
77
|
+
|
78
|
+
# Add a new location
|
79
|
+
#
|
80
|
+
# Parameters:
|
81
|
+
# * *iLocation* (_String_): The location
|
82
|
+
# Return:
|
83
|
+
# * _Integer_: Its resulting ID
|
84
|
+
def addLocation(iLocation)
|
85
|
+
logMsg "Added location: #{iLocation} (#{@IdxID})"
|
86
|
+
@IdxID += 1
|
87
|
+
|
88
|
+
return @IdxID-1
|
89
|
+
end
|
90
|
+
|
91
|
+
# Add a new category
|
92
|
+
#
|
93
|
+
# Parameters:
|
94
|
+
# * *iCategory* (_String_): The category
|
95
|
+
# * *iValueType* (_Integer_): Its value type
|
96
|
+
# Return:
|
97
|
+
# * _Integer_: Its resulting ID
|
98
|
+
def addCategory(iCategory, iValueType)
|
99
|
+
logMsg "Added category: #{iCategory}, #{iValueType} (#{@IdxID})"
|
100
|
+
@IdxID += 1
|
101
|
+
|
102
|
+
return @IdxID-1
|
103
|
+
end
|
104
|
+
|
105
|
+
# Add a new object
|
106
|
+
#
|
107
|
+
# Parameters:
|
108
|
+
# * *iObject* (_String_): The object
|
109
|
+
# Return:
|
110
|
+
# * _Integer_: Its resulting ID
|
111
|
+
def addObject(iObject)
|
112
|
+
logMsg "Added object: #{iObject} (#{@IdxID})"
|
113
|
+
@IdxID += 1
|
114
|
+
|
115
|
+
return @IdxID-1
|
116
|
+
end
|
117
|
+
|
118
|
+
# Add a new stat
|
119
|
+
#
|
120
|
+
# Parameters:
|
121
|
+
# * *iTimeStamp* (_DateTime_): The time stamp
|
122
|
+
# * *iLocationID* (_Integer_): Location ID
|
123
|
+
# * *iObjectID* (_Integer_): Object ID
|
124
|
+
# * *iCategoryID* (_Integer_): Category ID
|
125
|
+
# * *iValue* (_Object_): The value to store
|
126
|
+
# * *iValueType* (_Integer_): The value type
|
127
|
+
def addStat(iTimeStamp, iLocationID, iObjectID, iCategoryID, iValue, iValueType)
|
128
|
+
logMsg "Added stat: #{iTimeStamp} | Location: #{iLocationID} | Object: #{iObjectID} | Category: #{iCategoryID} | Value: #{iValue}"
|
129
|
+
end
|
130
|
+
|
131
|
+
# Add a new stats order
|
132
|
+
#
|
133
|
+
# Parameters:
|
134
|
+
# * *iTimeStamp* (_DateTime_): The time stamp
|
135
|
+
# * *iLstLocations* (<em>list<String></em>): List of locations
|
136
|
+
# * *iLstObjects* (<em>list<String></em>): List of objects
|
137
|
+
# * *iLstCategories* (<em>list<String></em>): List of categories
|
138
|
+
# * *iStatus* (_Integer_): The order status
|
139
|
+
def putNewStatsOrder(iTimeStamp, iLstLocations, iLstObjects, iLstCategories, iStatus)
|
140
|
+
logMsg "Added new stats order: #{iTimeStamp} | Locations: #{iLstLocations.join(', ')} | Objects: #{iLstObjects.join(', ')} | Categories: #{iLstCategories.join(', ')} | Status: #{iStatus}"
|
141
|
+
end
|
142
|
+
|
143
|
+
# Commit the current stats order transaction
|
144
|
+
def commit
|
145
|
+
logMsg 'Transaction committed'
|
146
|
+
end
|
147
|
+
|
148
|
+
# Rollback the current stats order transaction
|
149
|
+
def rollback
|
150
|
+
logMsg 'Transaction rollbacked'
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module StatsCollect
|
7
|
+
|
8
|
+
module Locations
|
9
|
+
|
10
|
+
class AddThis
|
11
|
+
|
12
|
+
# Execute the plugin.
|
13
|
+
# This method has to add the stats and errors to the proxy.
|
14
|
+
# It can filter only objects and categories given.
|
15
|
+
# It has access to its configuration.
|
16
|
+
#
|
17
|
+
# Parameters:
|
18
|
+
# * *oStatsProxy* (_StatsProxy_): The stats proxy to be used to populate stats
|
19
|
+
# * *iConf* (<em>map<Symbol,Object></em>): The configuration associated to this plugin
|
20
|
+
# * *iLstObjects* (<em>list<String></em>): List of objects to filter (can be empty for all)
|
21
|
+
# * *iLstCategories* (<em>list<String></em>): List of categories to filter (can be empty for all)
|
22
|
+
def execute(oStatsProxy, iConf, iLstObjects, iLstCategories)
|
23
|
+
require 'mechanize'
|
24
|
+
lMechanizeAgent = Mechanize.new
|
25
|
+
# Get the number of likes from Facebook
|
26
|
+
if (oStatsProxy.isCategoryIncluded?('Monthly shares'))
|
27
|
+
getDomains(oStatsProxy, lMechanizeAgent, iConf, 'month', 'Monthly shares')
|
28
|
+
end
|
29
|
+
if (oStatsProxy.isCategoryIncluded?('Weekly shares'))
|
30
|
+
getDomains(oStatsProxy, lMechanizeAgent, iConf, 'week', 'Weekly shares')
|
31
|
+
end
|
32
|
+
if (oStatsProxy.isCategoryIncluded?('Daily shares'))
|
33
|
+
getDomains(oStatsProxy, lMechanizeAgent, iConf, 'day', 'Daily shares')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# Get domains stats for a given period
|
40
|
+
#
|
41
|
+
# Parameters:
|
42
|
+
# * *oStatsProxy* (_StatsProxy_): The stats proxy to be used to populate stats
|
43
|
+
# * *iMechanizeAgent* (_Mechanize_): The mechanize agent
|
44
|
+
# * *iConf* (<em>map<Symbol,Object></em>): The configuration associated to this plugin
|
45
|
+
# * *iAddThisPeriod* (_String_): The period given to AddThis API
|
46
|
+
# * *iCategory* (_String_): Corresponding category
|
47
|
+
def getDomains(oStatsProxy, iMechanizeAgent, iConf, iAddThisPeriod, iCategory)
|
48
|
+
iMechanizeAgent.auth(iConf[:Login], iConf[:Password])
|
49
|
+
lData = eval(iMechanizeAgent.get_file("http://api.addthis.com/analytics/1.0/pub/shares/domain.json?period=#{iAddThisPeriod}").gsub(/:/,'=>'))
|
50
|
+
iConf[:Objects].each do |iObject|
|
51
|
+
lNbrShares = 0
|
52
|
+
lData.each do |iDataInfo|
|
53
|
+
if (iDataInfo['domain'] == iObject)
|
54
|
+
lNbrShares = iDataInfo['shares']
|
55
|
+
end
|
56
|
+
end
|
57
|
+
oStatsProxy.addStat(iObject, iCategory, lNbrShares)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|