diff --git a/conf.py b/conf.py index e06aa5b..330196b 100644 --- a/conf.py +++ b/conf.py @@ -10,8 +10,8 @@ display_visitor_ip = True # Hooks used pre_analysis_hooks = ['page_to_hit', 'robots'] -post_analysis_hooks = ['referers', 'top_pages', 'top_downloads', 'operating_systems', 'browsers', 'feeds', 'hours_stats', 'reverse_dns'] -display_hooks = ['track_users', 'top_visitors', 'all_visits', 'referers', 'top_pages', 'top_downloads', 'referers_diff', 'operating_systems', 'browsers', 'feeds', 'hours_stats', 'top_downloads_diff'] +post_analysis_hooks = ['referers', 'top_pages', 'top_downloads', 'operating_systems', 'browsers', 'feeds', 'hours_stats', 'reverse_dns', 'ip_to_geo'] +display_hooks = ['track_users', 'top_visitors', 'all_visits', 'referers', 'top_pages', 'top_downloads', 'referers_diff', 'ip_to_geo', 'operating_systems', 'browsers', 'feeds', 'hours_stats', 'top_downloads_diff'] # Reverse DNS timeout reverse_dns_timeout = 0.2 diff --git a/display.py b/display.py index 6be75df..b5a5bc0 100644 --- a/display.py +++ b/display.py @@ -48,10 +48,18 @@ class DisplayHTMLRaw(object): def _build(self, f, html): if html: f.write(html) - def build(self, f): + def build(self, f, filters=None): + if filters: self.filter(filters) self._buildHTML() self._build(f, self.html) + def _filter(self, function, **kwargs): + pass + + def filter(self, filters): + for (args, function) in filters: + self._filter(function, **args) + def getTitle(self): return '' @@ -189,6 +197,18 @@ class DisplayHTMLBlockTable(DisplayHTMLBlock): val = r[column] and int(r[column]) or 0 self.setCellValue(index, column_insertion, '%.1f%%' % (float(val*100)/float(total))) + def _filter(self, function, column, args): + target_col = None + for col in range(0, len(self.cols)): + if self.cols[col] == column: + target_col = col + break + if target_col is None: return + for row in self.rows: + res = function(row[target_col], **args) + if res: + row[target_col] = res + def _buildHTML(self): style = u'' if self.table_css: style = u' class="%s"' % (self.table_css) @@ -315,11 +335,14 @@ class DisplayHTMLPage(object): if title == b.getTitle(): return b return None - + + def getAllBlocks(self): + return self.blocks + def appendBlock(self, block): self.blocks.append(block) - def build(self, root, displayVersion=True): + def build(self, root, displayVersion=True, filters=None): filename = os.path.join(root, self.filename) base = os.path.dirname(filename) @@ -339,7 +362,7 @@ class DisplayHTMLPage(object): f.write(u'
' % (self.icon_path, cc)
+ return '%s %s' % (icon ,host)
+
+ def hook(self):
+ display = self.iwla.getDisplay()
+ geo = self.iwla.getMonthStats()['geo']
+ geo = sorted(geo.items(), key=lambda t: t[1], reverse=True)
+ self.valid_visitors = self.iwla.getValidVisitors()
+
+ # All in a page
+ if self.create_geo_page:
+ title = createCurTitle(self.iwla, u'All Coutries')
+ filename = 'geo.html'
+ path = self.iwla.getCurDisplayPath(filename)
+
+ page = display.createPage(title, path, self.iwla.getConfValue('css_path', []))
+ table = display.createBlock(DisplayHTMLBlockTable, self.iwla._(u'Countries'), ['', self.iwla._(u'Country'), self.iwla._(u'Visitors')])
+ table.setColsCSSClass(['', '', 'iwla_hit'])
+ for (cc, visitors) in geo:
+ icon = '
' % (self.icon_path, cc)
+ table.appendRow([icon, cc, visitors])
+ table.computeRatio(2)
+ page.appendBlock(table)
+
+ display.addPage(page)
+
+ # Countries in index
+ title = self.iwla._(u'Countries')
+ if self.create_geo_page:
+ link = '%s' % (filename, self.iwla._(u'Details'))
+ title = '%s - %s' % (title, link)
+
+ index = self.iwla.getDisplayIndex()
+
+ table = display.createBlock(DisplayHTMLBlockTable, title, ['', self.iwla._(u'Countries'), self.iwla._(u'Visitors')])
+ table.setColsCSSClass(['', '', 'iwla_hit'])
+ for (cc, visitors) in geo[:10]:
+ icon = '
' % (self.icon_path, cc)
+ table.appendRow([icon, cc, visitors])
+ table.computeRatio(2)
+ index.appendBlock(table)
diff --git a/plugins/display/track_users.py b/plugins/display/track_users.py
index 53b7b9d..c653e4a 100644
--- a/plugins/display/track_users.py
+++ b/plugins/display/track_users.py
@@ -64,7 +64,7 @@ class IWLADisplayTrackUsers(IPlugin):
def hook(self):
display = self.iwla.getDisplay()
- hits = self.iwla.getCurrentVisists()
+ hits = self.iwla.getCurrentVisits()
stats = {}
# All in a page
@@ -110,7 +110,7 @@ class IWLADisplayTrackUsers(IPlugin):
index = self.iwla.getDisplayIndex()
- table = display.createBlock(DisplayHTMLBlockTable, title, [self.iwla._(u'IP'), self.iwla._(u'Last Access'), self.iwla._(u'Pages'), self.iwla._(u'Hits')])
+ table = display.createBlock(DisplayHTMLBlockTable, title, [self.iwla._(u'Host'), self.iwla._(u'Last Access'), self.iwla._(u'Pages'), self.iwla._(u'Hits')])
table.setColsCSSClass(['', '', 'iwla_page', 'iwla_hit'])
for ip in self.tracked_ip:
if not ip in hits.keys(): continue
diff --git a/plugins/post_analysis/feeds.py b/plugins/post_analysis/feeds.py
index 8476881..570649f 100644
--- a/plugins/post_analysis/feeds.py
+++ b/plugins/post_analysis/feeds.py
@@ -85,7 +85,7 @@ class IWLAPostAnalysisFeeds(IPlugin):
hit['feed_parser'] = isFeedParser
def hook(self):
- hits = self.iwla.getCurrentVisists()
+ hits = self.iwla.getCurrentVisits()
one_hit_only = {}
for hit in hits.values():
isFeedParser = hit.get('feed_parser', None)
diff --git a/plugins/post_analysis/hours_stats.py b/plugins/post_analysis/hours_stats.py
index a45dbdd..4ec9014 100644
--- a/plugins/post_analysis/hours_stats.py
+++ b/plugins/post_analysis/hours_stats.py
@@ -62,7 +62,7 @@ class IWLAPostAnalysisHoursStats(IPlugin):
self.API_VERSION = 1
def hook(self):
- stats = self.iwla.getCurrentVisists()
+ stats = self.iwla.getCurrentVisits()
month_stats = self.iwla.getMonthStats()
hours_stats = month_stats.get('hours_stats', {})
diff --git a/plugins/post_analysis/ip_to_geo.py b/plugins/post_analysis/ip_to_geo.py
new file mode 100644
index 0000000..a15e016
--- /dev/null
+++ b/plugins/post_analysis/ip_to_geo.py
@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright Grégory Soutadé 2016
+
+# This file is part of iwla
+
+# iwla is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# iwla is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with iwla. If not, see