StatsCollect 0.1.0.20101220 → 0.1.1.20101220

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.
data/Credits CHANGED
@@ -5,6 +5,11 @@
5
5
  * http://www.ruby-lang.org/
6
6
  * Thanks a lot Matz for this truly wonderful language !
7
7
 
8
+ == rUtilAnts
9
+ * Muriel Salvan (http://murielsalvan.users.sourceforge.net)
10
+ * http://rutilants.sourceforge.net
11
+ * Used for plugins and logging handling.
12
+
8
13
  = Projects used by StatsCollect plugins
9
14
 
10
15
  == Plugin Backends/MySQL
data/ReleaseInfo CHANGED
@@ -2,7 +2,7 @@
2
2
  # This file has been generated by RubyPackager during a delivery.
3
3
  # More info about RubyPackager: http://rubypackager.sourceforge.net
4
4
  {
5
- :Version => '0.1.0.20101220',
5
+ :Version => '0.1.1.20101220',
6
6
  :Tags => [ 'Beta' ],
7
7
  :DevStatus => 'Beta'
8
8
  }
data/TODO CHANGED
@@ -1 +1,2 @@
1
- * MySpace: Get the user ID by parsing the Profile URL and remove :MySpaceName configuration option.
1
+ * MySpace: Get the user ID by parsing the Profile URL and remove :MySpaceName configuration option.
2
+ * Get all the orders at once, and merge them to call Locations just once per execution.
data/bin/StatsCollect.rb CHANGED
@@ -4,11 +4,6 @@
4
4
  # Licensed under the terms specified in LICENSE file. No warranty is provided.
5
5
  #++
6
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
7
  require 'rUtilAnts/Logging'
13
8
  RUtilAnts::Logging::initializeLogging('','')
14
9
  require 'tmpdir'
@@ -36,7 +36,10 @@ module StatsCollect
36
36
  rStatus = nil
37
37
 
38
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')
39
+ @LstStatsOrders = []
40
+ @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').each do |iRow|
41
+ @LstStatsOrders << iRow.clone
42
+ end
40
43
  end
41
44
  if (!@LstStatsOrders.empty?)
42
45
  lID, rTimeStamp, lStrLocations, lStrObjects, lStrCategories, rStatus = @LstStatsOrders.pop
@@ -115,7 +118,7 @@ module StatsCollect
115
118
  # Return:
116
119
  # * _Integer_: Its resulting ID
117
120
  def addCategory(iCategory, iValueType)
118
- @MySQLConnection.query("INSERT INTO stats_categories (name, value_type) VALUES ('#{@MySQLConnection.escape_string(iLocation)}', #{iValueType})")
121
+ @MySQLConnection.query("INSERT INTO stats_categories (name, value_type) VALUES ('#{@MySQLConnection.escape_string(iCategory)}', #{iValueType})")
119
122
 
120
123
  return @MySQLConnection.insert_id
121
124
  end
@@ -42,7 +42,9 @@ module StatsCollect
42
42
  lProfilePage = iMechanizeAgent.get('http://www.facebook.com/profile.php')
43
43
  lNbrFriends = nil
44
44
  lProfilePage.root.css('script').each do |iScriptNode|
45
- lMatch = iScriptNode.content.match(/>(\d*) friends<\\\/a><\\\/span>/)
45
+ lMatch = iScriptNode.content.match(/>Friends \((\d*)\)<\\\/a><\\\/span>/)
46
+ # The following line is valid for old profiles only
47
+ #lMatch = iScriptNode.content.match(/>(\d*) friends<\\\/a><\\\/span>/)
46
48
  if (lMatch != nil)
47
49
  lNbrFriends = Integer(lMatch[1])
48
50
  break
@@ -23,8 +23,8 @@ module StatsCollect
23
23
  require 'mechanize'
24
24
  lMechanizeAgent = Mechanize.new
25
25
  lLoginForm = lMechanizeAgent.get('http://www.youtube.com').link_with(:text => 'Sign In').click.forms[1]
26
- lLoginForm.Email = 'Muriel.Esteban@GMail.com'
27
- lLoginForm.Passwd = 'M[K2LBVu0}xT|b<[<Q")'
26
+ lLoginForm.Email = iConf[:LoginEMail]
27
+ lLoginForm.Passwd = iConf[:LoginPassword]
28
28
  lMechanizeAgent.submit(lLoginForm, lLoginForm.buttons.first).meta.first.click
29
29
  if ((oStatsProxy.isCategoryIncluded?('Video plays')) or
30
30
  (oStatsProxy.isCategoryIncluded?('Video likes')) or
@@ -33,6 +33,19 @@ module StatsCollect
33
33
  (oStatsProxy.isCategoryIncluded?('Video responses')))
34
34
  getVideos(oStatsProxy, lMechanizeAgent)
35
35
  end
36
+ if ((oStatsProxy.isObjectIncluded?('Global')) and
37
+ ((oStatsProxy.isCategoryIncluded?('Visits')) or
38
+ (oStatsProxy.isCategoryIncluded?('Followers'))))
39
+ getOverview(oStatsProxy, lMechanizeAgent)
40
+ end
41
+ if ((oStatsProxy.isObjectIncluded?('Global')) and
42
+ (oStatsProxy.isCategoryIncluded?('Friends')))
43
+ getFriends(oStatsProxy, lMechanizeAgent)
44
+ end
45
+ if ((oStatsProxy.isObjectIncluded?('Global')) and
46
+ (oStatsProxy.isCategoryIncluded?('Following')))
47
+ getSubscriptions(oStatsProxy, lMechanizeAgent)
48
+ end
36
49
  end
37
50
 
38
51
  # Get the videos statistics
@@ -62,6 +75,61 @@ module StatsCollect
62
75
  logDebug "#{lLstVideosRead.size} videos read: #{lLstVideosRead.join(', ')}"
63
76
  end
64
77
 
78
+ # Get the overview statistics
79
+ #
80
+ # Parameters:
81
+ # * *oStatsProxy* (_StatsProxy_): The stats proxy to be used to populate stats
82
+ # * *iMechanizeAgent* (_Mechanize_): The agent reading pages
83
+ def getOverview(oStatsProxy, iMechanizeAgent)
84
+ lOverviewPage = iMechanizeAgent.get('http://www.youtube.com/account_overview')
85
+ lNbrVisits = nil
86
+ lNbrFollowers = nil
87
+ lOverviewPage.root.css('div.statBlock').each do |iStatsSectionNode|
88
+ lChildrenNodes = iStatsSectionNode.children
89
+ lChildrenNodes.each_with_index do |iNode, iIdx|
90
+ if (iNode.content == 'Channel Views:')
91
+ lNbrVisits = Integer(lChildrenNodes[iIdx+1].content.strip)
92
+ elsif (iNode.content == 'Subscribers:')
93
+ lNbrFollowers = Integer(lChildrenNodes[iIdx+1].content.strip)
94
+ end
95
+ end
96
+ if ((lNbrVisits != nil) and
97
+ (lNbrFollowers != nil))
98
+ break
99
+ end
100
+ end
101
+ if (lNbrVisits == nil)
102
+ logErr "Unable to get number of visits: #{lOverviewPage}"
103
+ elsif (lNbrFollowers == nil)
104
+ logErr "Unable to get number of followers: #{lOverviewPage}"
105
+ else
106
+ oStatsProxy.addStat('Global', 'Visits', lNbrVisits)
107
+ oStatsProxy.addStat('Global', 'Followers', lNbrFollowers)
108
+ end
109
+ end
110
+
111
+ # Get the friends statistics
112
+ #
113
+ # Parameters:
114
+ # * *oStatsProxy* (_StatsProxy_): The stats proxy to be used to populate stats
115
+ # * *iMechanizeAgent* (_Mechanize_): The agent reading pages
116
+ def getFriends(oStatsProxy, iMechanizeAgent)
117
+ lOverviewPage = iMechanizeAgent.get('http://www.youtube.com/profile?view=friends')
118
+ lNbrFriends = Integer(lOverviewPage.root.xpath('//span[@name="channel-box-item-count"]').first.content)
119
+ oStatsProxy.addStat('Global', 'Friends', lNbrFriends)
120
+ end
121
+
122
+ # Get the friends statistics
123
+ #
124
+ # Parameters:
125
+ # * *oStatsProxy* (_StatsProxy_): The stats proxy to be used to populate stats
126
+ # * *iMechanizeAgent* (_Mechanize_): The agent reading pages
127
+ def getSubscriptions(oStatsProxy, iMechanizeAgent)
128
+ lOverviewPage = iMechanizeAgent.get('http://www.youtube.com/profile?view=subscriptions')
129
+ lNbrFollowing = Integer(lOverviewPage.root.xpath('//span[@name="channel-box-item-count"]').first.content)
130
+ oStatsProxy.addStat('Global', 'Following', lNbrFollowing)
131
+ end
132
+
65
133
  end
66
134
 
67
135
  end
@@ -10,12 +10,10 @@ require 'StatsCollect/StatsProxy'
10
10
  module StatsCollect
11
11
 
12
12
  # Stats orders statuses
13
- # !!! Those constants are also defined in the RoR website.
14
13
  STATS_ORDER_STATUS_TOBEPROCESSED = 0
15
14
  STATS_ORDER_STATUS_RECOVERABLE_ERROR = 1
16
15
  STATS_ORDER_STATUS_UNRECOVERABLE_ERROR = 2
17
16
  # Value types
18
- # !!! Those constants are also defined in the RoR website.
19
17
  STATS_VALUE_TYPE_INTEGER = 0
20
18
  STATS_VALUE_TYPE_FLOAT = 1
21
19
  STATS_VALUE_TYPE_PERCENTAGE = 2
@@ -33,6 +31,7 @@ module StatsCollect
33
31
  parsePluginsFromDir('Notifiers', "#{File.expand_path(File.dirname(__FILE__))}/Notifiers", 'StatsCollect::Notifiers')
34
32
 
35
33
  @Backend = nil
34
+ @BackendInit = false
36
35
  @Notifier = nil
37
36
  @ConfigFile = nil
38
37
  @DisplayHelp = false
@@ -183,7 +182,10 @@ module StatsCollect
183
182
  begin
184
183
  # Collect statistics
185
184
  logInfo "[#{DateTime.now.strftime('%Y-%m-%d %H:%M:%S')}] - Begin collecting stats..."
186
- @BackendInstance.initSession(@Conf[:Backends][@Backend])
185
+ if (!@BackendInit)
186
+ @BackendInstance.initSession(@Conf[:Backends][@Backend])
187
+ @BackendInit = true
188
+ end
187
189
  # Get the stats orders to process
188
190
  lFoundOrder = false
189
191
  lTimeStamp, lLstLocations, lLstObjects, lLstCategories, lStatus = @BackendInstance.getNextStatsOrder
@@ -245,6 +247,20 @@ module StatsCollect
245
247
  end
246
248
  end
247
249
 
250
+ # Enqueue a new stats order
251
+ #
252
+ # Parameters:
253
+ # * *iLstLocations* (<em>list<String></em>): Locations list (can be empty for all locations)
254
+ # * *iLstObjects* (<em>list<String></em>): Objects list (can be empty for all objects)
255
+ # * *iLstCategories* (<em>list<String></em>): Categories list (can be empty for all categories)
256
+ def pushStatsOrder(iLstLocations, iLstObjects, iLstCategories)
257
+ if (!@BackendInit)
258
+ @BackendInstance.initSession(@Conf[:Backends][@Backend])
259
+ @BackendInit = true
260
+ end
261
+ @BackendInstance.putNewStatsOrder(DateTime.now, iLstLocations, iLstObjects, iLstCategories, STATS_ORDER_STATUS_TOBEPROCESSED)
262
+ end
263
+
248
264
  private
249
265
 
250
266
  # Process an order
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
8
+ - 1
9
9
  - 20101220
10
- version: 0.1.0.20101220
10
+ version: 0.1.1.20101220
11
11
  platform: ruby
12
12
  authors:
13
13
  - Muriel Salvan