Added referrer analytics. You can now see what site a visitor has come from.
Added the viewchunks_referrers table.
This commit is contained in:
parent
e56e7cd467
commit
1ac47bfdfd
@ -96,13 +96,17 @@ var PreRenderHooks = map[string][]func(http.ResponseWriter, *http.Request, *User
|
|||||||
"pre_render_panel_forums": nil,
|
"pre_render_panel_forums": nil,
|
||||||
"pre_render_panel_delete_forum": nil,
|
"pre_render_panel_delete_forum": nil,
|
||||||
"pre_render_panel_edit_forum": nil,
|
"pre_render_panel_edit_forum": nil,
|
||||||
|
|
||||||
"pre_render_panel_analytics_views": nil,
|
"pre_render_panel_analytics_views": nil,
|
||||||
"pre_render_panel_analytics_routes": nil,
|
"pre_render_panel_analytics_routes": nil,
|
||||||
"pre_render_panel_analytics_agents": nil,
|
"pre_render_panel_analytics_agents": nil,
|
||||||
"pre_render_panel_analytics_systems": nil,
|
"pre_render_panel_analytics_systems": nil,
|
||||||
|
"pre_render_panel_analytics_referrers": nil,
|
||||||
"pre_render_panel_analytics_route_views": nil,
|
"pre_render_panel_analytics_route_views": nil,
|
||||||
"pre_render_panel_analytics_agent_views": nil,
|
"pre_render_panel_analytics_agent_views": nil,
|
||||||
"pre_render_panel_analytics_system_views": nil,
|
"pre_render_panel_analytics_system_views": nil,
|
||||||
|
"pre_render_panel_analytics_referrer_views": nil,
|
||||||
|
|
||||||
"pre_render_panel_settings": nil,
|
"pre_render_panel_settings": nil,
|
||||||
"pre_render_panel_setting": nil,
|
"pre_render_panel_setting": nil,
|
||||||
"pre_render_panel_word_filters": nil,
|
"pre_render_panel_word_filters": nil,
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"../query_gen/lib"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add ReferrerItems here after they've had zero views for a while
|
var ReferrerTracker *DefaultReferrerTracker
|
||||||
var referrersToDelete = make(map[string]ReferrerDeletable)
|
|
||||||
|
|
||||||
type ReferrerDeletable struct {
|
// Add ReferrerItems here after they've had zero views for a while
|
||||||
item *ReferrerItem
|
var referrersToDelete = make(map[string]*ReferrerItem)
|
||||||
scheduledAt int64 //unixtime
|
|
||||||
}
|
|
||||||
|
|
||||||
type ReferrerItem struct {
|
type ReferrerItem struct {
|
||||||
Counter int64
|
Count int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// ? We'll track referrer domains here rather than the exact URL they arrived from for now, we'll think about expanding later
|
// ? We'll track referrer domains here rather than the exact URL they arrived from for now, we'll think about expanding later
|
||||||
@ -24,24 +24,79 @@ type DefaultReferrerTracker struct {
|
|||||||
even map[string]*ReferrerItem
|
even map[string]*ReferrerItem
|
||||||
oddLock sync.RWMutex
|
oddLock sync.RWMutex
|
||||||
evenLock sync.RWMutex
|
evenLock sync.RWMutex
|
||||||
|
|
||||||
|
insert *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultReferrerTracker() *DefaultReferrerTracker {
|
func NewDefaultReferrerTracker() (*DefaultReferrerTracker, error) {
|
||||||
return &DefaultReferrerTracker{
|
acc := qgen.Builder.Accumulator()
|
||||||
|
refTracker := &DefaultReferrerTracker{
|
||||||
odd: make(map[string]*ReferrerItem),
|
odd: make(map[string]*ReferrerItem),
|
||||||
even: make(map[string]*ReferrerItem),
|
even: make(map[string]*ReferrerItem),
|
||||||
|
insert: acc.Insert("viewchunks_referrers").Columns("count, createdAt, domain").Fields("?,UTC_TIMESTAMP(),?").Prepare(), // TODO: Do something more efficient than doing a query for each referrer
|
||||||
|
}
|
||||||
|
//AddScheduledFifteenMinuteTask(refTracker.Tick)
|
||||||
|
AddScheduledSecondTask(refTracker.Tick)
|
||||||
|
AddShutdownTask(refTracker.Tick)
|
||||||
|
return refTracker, acc.FirstError()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move this and the other view tickers out of the main task loop to avoid blocking other tasks?
|
||||||
|
func (ref *DefaultReferrerTracker) Tick() (err error) {
|
||||||
|
for referrer, counter := range referrersToDelete {
|
||||||
|
// Handle views which squeezed through the gaps at the last moment
|
||||||
|
count := counter.Count
|
||||||
|
if count != 0 {
|
||||||
|
err := ref.insertChunk(referrer, count) // TODO: Bulk insert for speed?
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ref *DefaultReferrerTracker) Tick() (err error) {
|
delete(referrersToDelete, referrer)
|
||||||
for _, del := range referrersToDelete {
|
|
||||||
_ = del
|
|
||||||
// TODO: Calculate the gap between now and the times they were scheduled
|
|
||||||
}
|
}
|
||||||
// TODO: Run the queries and schedule zero view refs for deletion from memory
|
|
||||||
|
// Run the queries and schedule zero view refs for deletion from memory
|
||||||
|
ref.oddLock.Lock()
|
||||||
|
for referrer, counter := range ref.odd {
|
||||||
|
if counter.Count == 0 {
|
||||||
|
referrersToDelete[referrer] = counter
|
||||||
|
delete(ref.odd, referrer)
|
||||||
|
}
|
||||||
|
count := atomic.SwapInt64(&counter.Count, 0)
|
||||||
|
err := ref.insertChunk(referrer, count) // TODO: Bulk insert for speed?
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ref.oddLock.Unlock()
|
||||||
|
|
||||||
|
ref.evenLock.Lock()
|
||||||
|
for referrer, counter := range ref.even {
|
||||||
|
if counter.Count == 0 {
|
||||||
|
referrersToDelete[referrer] = counter
|
||||||
|
delete(ref.even, referrer)
|
||||||
|
}
|
||||||
|
count := atomic.SwapInt64(&counter.Count, 0)
|
||||||
|
err := ref.insertChunk(referrer, count) // TODO: Bulk insert for speed?
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ref.evenLock.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ref *DefaultReferrerTracker) insertChunk(referrer string, count int64) error {
|
||||||
|
if count == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
debugDetailf("Inserting a viewchunk with a count of %d for referrer %s", count, referrer)
|
||||||
|
_, err := ref.insert.Exec(count, referrer)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (ref *DefaultReferrerTracker) Bump(referrer string) {
|
func (ref *DefaultReferrerTracker) Bump(referrer string) {
|
||||||
if referrer == "" {
|
if referrer == "" {
|
||||||
return
|
return
|
||||||
@ -53,22 +108,22 @@ func (ref *DefaultReferrerTracker) Bump(referrer string) {
|
|||||||
ref.evenLock.RLock()
|
ref.evenLock.RLock()
|
||||||
refItem = ref.even[referrer]
|
refItem = ref.even[referrer]
|
||||||
ref.evenLock.RUnlock()
|
ref.evenLock.RUnlock()
|
||||||
if ref != nil {
|
if refItem != nil {
|
||||||
atomic.AddInt64(&refItem.Counter, 1)
|
atomic.AddInt64(&refItem.Count, 1)
|
||||||
} else {
|
} else {
|
||||||
ref.evenLock.Lock()
|
ref.evenLock.Lock()
|
||||||
ref.even[referrer] = &ReferrerItem{Counter: 1}
|
ref.even[referrer] = &ReferrerItem{Count: 1}
|
||||||
ref.evenLock.Unlock()
|
ref.evenLock.Unlock()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ref.oddLock.RLock()
|
ref.oddLock.RLock()
|
||||||
refItem = ref.odd[referrer]
|
refItem = ref.odd[referrer]
|
||||||
ref.oddLock.RUnlock()
|
ref.oddLock.RUnlock()
|
||||||
if ref != nil {
|
if refItem != nil {
|
||||||
atomic.AddInt64(&refItem.Counter, 1)
|
atomic.AddInt64(&refItem.Count, 1)
|
||||||
} else {
|
} else {
|
||||||
ref.oddLock.Lock()
|
ref.oddLock.Lock()
|
||||||
ref.odd[referrer] = &ReferrerItem{Counter: 1}
|
ref.odd[referrer] = &ReferrerItem{Count: 1}
|
||||||
ref.oddLock.Unlock()
|
ref.oddLock.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
359
gen_router.go
359
gen_router.go
@ -57,9 +57,11 @@ var RouteMap = map[string]interface{}{
|
|||||||
"routePanelAnalyticsRoutes": routePanelAnalyticsRoutes,
|
"routePanelAnalyticsRoutes": routePanelAnalyticsRoutes,
|
||||||
"routePanelAnalyticsAgents": routePanelAnalyticsAgents,
|
"routePanelAnalyticsAgents": routePanelAnalyticsAgents,
|
||||||
"routePanelAnalyticsSystems": routePanelAnalyticsSystems,
|
"routePanelAnalyticsSystems": routePanelAnalyticsSystems,
|
||||||
|
"routePanelAnalyticsReferrers": routePanelAnalyticsReferrers,
|
||||||
"routePanelAnalyticsRouteViews": routePanelAnalyticsRouteViews,
|
"routePanelAnalyticsRouteViews": routePanelAnalyticsRouteViews,
|
||||||
"routePanelAnalyticsAgentViews": routePanelAnalyticsAgentViews,
|
"routePanelAnalyticsAgentViews": routePanelAnalyticsAgentViews,
|
||||||
"routePanelAnalyticsSystemViews": routePanelAnalyticsSystemViews,
|
"routePanelAnalyticsSystemViews": routePanelAnalyticsSystemViews,
|
||||||
|
"routePanelAnalyticsReferrerViews": routePanelAnalyticsReferrerViews,
|
||||||
"routePanelAnalyticsPosts": routePanelAnalyticsPosts,
|
"routePanelAnalyticsPosts": routePanelAnalyticsPosts,
|
||||||
"routePanelAnalyticsTopics": routePanelAnalyticsTopics,
|
"routePanelAnalyticsTopics": routePanelAnalyticsTopics,
|
||||||
"routePanelGroups": routePanelGroups,
|
"routePanelGroups": routePanelGroups,
|
||||||
@ -157,61 +159,63 @@ var routeMapEnum = map[string]int{
|
|||||||
"routePanelAnalyticsRoutes": 38,
|
"routePanelAnalyticsRoutes": 38,
|
||||||
"routePanelAnalyticsAgents": 39,
|
"routePanelAnalyticsAgents": 39,
|
||||||
"routePanelAnalyticsSystems": 40,
|
"routePanelAnalyticsSystems": 40,
|
||||||
"routePanelAnalyticsRouteViews": 41,
|
"routePanelAnalyticsReferrers": 41,
|
||||||
"routePanelAnalyticsAgentViews": 42,
|
"routePanelAnalyticsRouteViews": 42,
|
||||||
"routePanelAnalyticsSystemViews": 43,
|
"routePanelAnalyticsAgentViews": 43,
|
||||||
"routePanelAnalyticsPosts": 44,
|
"routePanelAnalyticsSystemViews": 44,
|
||||||
"routePanelAnalyticsTopics": 45,
|
"routePanelAnalyticsReferrerViews": 45,
|
||||||
"routePanelGroups": 46,
|
"routePanelAnalyticsPosts": 46,
|
||||||
"routePanelGroupsEdit": 47,
|
"routePanelAnalyticsTopics": 47,
|
||||||
"routePanelGroupsEditPerms": 48,
|
"routePanelGroups": 48,
|
||||||
"routePanelGroupsEditSubmit": 49,
|
"routePanelGroupsEdit": 49,
|
||||||
"routePanelGroupsEditPermsSubmit": 50,
|
"routePanelGroupsEditPerms": 50,
|
||||||
"routePanelGroupsCreateSubmit": 51,
|
"routePanelGroupsEditSubmit": 51,
|
||||||
"routePanelBackups": 52,
|
"routePanelGroupsEditPermsSubmit": 52,
|
||||||
"routePanelLogsMod": 53,
|
"routePanelGroupsCreateSubmit": 53,
|
||||||
"routePanelDebug": 54,
|
"routePanelBackups": 54,
|
||||||
"routePanelDashboard": 55,
|
"routePanelLogsMod": 55,
|
||||||
"routes.AccountEditCritical": 56,
|
"routePanelDebug": 56,
|
||||||
"routeAccountEditCriticalSubmit": 57,
|
"routePanelDashboard": 57,
|
||||||
"routeAccountEditAvatar": 58,
|
"routes.AccountEditCritical": 58,
|
||||||
"routeAccountEditAvatarSubmit": 59,
|
"routeAccountEditCriticalSubmit": 59,
|
||||||
"routeAccountEditUsername": 60,
|
"routeAccountEditAvatar": 60,
|
||||||
"routeAccountEditUsernameSubmit": 61,
|
"routeAccountEditAvatarSubmit": 61,
|
||||||
"routeAccountEditEmail": 62,
|
"routeAccountEditUsername": 62,
|
||||||
"routeAccountEditEmailTokenSubmit": 63,
|
"routeAccountEditUsernameSubmit": 63,
|
||||||
"routeProfile": 64,
|
"routeAccountEditEmail": 64,
|
||||||
"routes.BanUserSubmit": 65,
|
"routeAccountEditEmailTokenSubmit": 65,
|
||||||
"routes.UnbanUser": 66,
|
"routeProfile": 66,
|
||||||
"routes.ActivateUser": 67,
|
"routes.BanUserSubmit": 67,
|
||||||
"routes.IPSearch": 68,
|
"routes.UnbanUser": 68,
|
||||||
"routes.CreateTopicSubmit": 69,
|
"routes.ActivateUser": 69,
|
||||||
"routes.EditTopicSubmit": 70,
|
"routes.IPSearch": 70,
|
||||||
"routes.DeleteTopicSubmit": 71,
|
"routes.CreateTopicSubmit": 71,
|
||||||
"routes.StickTopicSubmit": 72,
|
"routes.EditTopicSubmit": 72,
|
||||||
"routes.UnstickTopicSubmit": 73,
|
"routes.DeleteTopicSubmit": 73,
|
||||||
"routes.LockTopicSubmit": 74,
|
"routes.StickTopicSubmit": 74,
|
||||||
"routes.UnlockTopicSubmit": 75,
|
"routes.UnstickTopicSubmit": 75,
|
||||||
"routes.MoveTopicSubmit": 76,
|
"routes.LockTopicSubmit": 76,
|
||||||
"routeLikeTopicSubmit": 77,
|
"routes.UnlockTopicSubmit": 77,
|
||||||
"routes.ViewTopic": 78,
|
"routes.MoveTopicSubmit": 78,
|
||||||
"routeCreateReplySubmit": 79,
|
"routeLikeTopicSubmit": 79,
|
||||||
"routes.ReplyEditSubmit": 80,
|
"routes.ViewTopic": 80,
|
||||||
"routes.ReplyDeleteSubmit": 81,
|
"routeCreateReplySubmit": 81,
|
||||||
"routeReplyLikeSubmit": 82,
|
"routes.ReplyEditSubmit": 82,
|
||||||
"routeProfileReplyCreateSubmit": 83,
|
"routes.ReplyDeleteSubmit": 83,
|
||||||
"routes.ProfileReplyEditSubmit": 84,
|
"routeReplyLikeSubmit": 84,
|
||||||
"routes.ProfileReplyDeleteSubmit": 85,
|
"routeProfileReplyCreateSubmit": 85,
|
||||||
"routes.PollVote": 86,
|
"routes.ProfileReplyEditSubmit": 86,
|
||||||
"routes.PollResults": 87,
|
"routes.ProfileReplyDeleteSubmit": 87,
|
||||||
"routes.AccountLogin": 88,
|
"routes.PollVote": 88,
|
||||||
"routes.AccountRegister": 89,
|
"routes.PollResults": 89,
|
||||||
"routeLogout": 90,
|
"routes.AccountLogin": 90,
|
||||||
"routes.AccountLoginSubmit": 91,
|
"routes.AccountRegister": 91,
|
||||||
"routes.AccountRegisterSubmit": 92,
|
"routeLogout": 92,
|
||||||
"routeDynamic": 93,
|
"routes.AccountLoginSubmit": 93,
|
||||||
"routeUploads": 94,
|
"routes.AccountRegisterSubmit": 94,
|
||||||
"BadRoute": 95,
|
"routeDynamic": 95,
|
||||||
|
"routeUploads": 96,
|
||||||
|
"BadRoute": 97,
|
||||||
}
|
}
|
||||||
var reverseRouteMapEnum = map[int]string{
|
var reverseRouteMapEnum = map[int]string{
|
||||||
0: "routeAPI",
|
0: "routeAPI",
|
||||||
@ -255,61 +259,63 @@ var reverseRouteMapEnum = map[int]string{
|
|||||||
38: "routePanelAnalyticsRoutes",
|
38: "routePanelAnalyticsRoutes",
|
||||||
39: "routePanelAnalyticsAgents",
|
39: "routePanelAnalyticsAgents",
|
||||||
40: "routePanelAnalyticsSystems",
|
40: "routePanelAnalyticsSystems",
|
||||||
41: "routePanelAnalyticsRouteViews",
|
41: "routePanelAnalyticsReferrers",
|
||||||
42: "routePanelAnalyticsAgentViews",
|
42: "routePanelAnalyticsRouteViews",
|
||||||
43: "routePanelAnalyticsSystemViews",
|
43: "routePanelAnalyticsAgentViews",
|
||||||
44: "routePanelAnalyticsPosts",
|
44: "routePanelAnalyticsSystemViews",
|
||||||
45: "routePanelAnalyticsTopics",
|
45: "routePanelAnalyticsReferrerViews",
|
||||||
46: "routePanelGroups",
|
46: "routePanelAnalyticsPosts",
|
||||||
47: "routePanelGroupsEdit",
|
47: "routePanelAnalyticsTopics",
|
||||||
48: "routePanelGroupsEditPerms",
|
48: "routePanelGroups",
|
||||||
49: "routePanelGroupsEditSubmit",
|
49: "routePanelGroupsEdit",
|
||||||
50: "routePanelGroupsEditPermsSubmit",
|
50: "routePanelGroupsEditPerms",
|
||||||
51: "routePanelGroupsCreateSubmit",
|
51: "routePanelGroupsEditSubmit",
|
||||||
52: "routePanelBackups",
|
52: "routePanelGroupsEditPermsSubmit",
|
||||||
53: "routePanelLogsMod",
|
53: "routePanelGroupsCreateSubmit",
|
||||||
54: "routePanelDebug",
|
54: "routePanelBackups",
|
||||||
55: "routePanelDashboard",
|
55: "routePanelLogsMod",
|
||||||
56: "routes.AccountEditCritical",
|
56: "routePanelDebug",
|
||||||
57: "routeAccountEditCriticalSubmit",
|
57: "routePanelDashboard",
|
||||||
58: "routeAccountEditAvatar",
|
58: "routes.AccountEditCritical",
|
||||||
59: "routeAccountEditAvatarSubmit",
|
59: "routeAccountEditCriticalSubmit",
|
||||||
60: "routeAccountEditUsername",
|
60: "routeAccountEditAvatar",
|
||||||
61: "routeAccountEditUsernameSubmit",
|
61: "routeAccountEditAvatarSubmit",
|
||||||
62: "routeAccountEditEmail",
|
62: "routeAccountEditUsername",
|
||||||
63: "routeAccountEditEmailTokenSubmit",
|
63: "routeAccountEditUsernameSubmit",
|
||||||
64: "routeProfile",
|
64: "routeAccountEditEmail",
|
||||||
65: "routes.BanUserSubmit",
|
65: "routeAccountEditEmailTokenSubmit",
|
||||||
66: "routes.UnbanUser",
|
66: "routeProfile",
|
||||||
67: "routes.ActivateUser",
|
67: "routes.BanUserSubmit",
|
||||||
68: "routes.IPSearch",
|
68: "routes.UnbanUser",
|
||||||
69: "routes.CreateTopicSubmit",
|
69: "routes.ActivateUser",
|
||||||
70: "routes.EditTopicSubmit",
|
70: "routes.IPSearch",
|
||||||
71: "routes.DeleteTopicSubmit",
|
71: "routes.CreateTopicSubmit",
|
||||||
72: "routes.StickTopicSubmit",
|
72: "routes.EditTopicSubmit",
|
||||||
73: "routes.UnstickTopicSubmit",
|
73: "routes.DeleteTopicSubmit",
|
||||||
74: "routes.LockTopicSubmit",
|
74: "routes.StickTopicSubmit",
|
||||||
75: "routes.UnlockTopicSubmit",
|
75: "routes.UnstickTopicSubmit",
|
||||||
76: "routes.MoveTopicSubmit",
|
76: "routes.LockTopicSubmit",
|
||||||
77: "routeLikeTopicSubmit",
|
77: "routes.UnlockTopicSubmit",
|
||||||
78: "routes.ViewTopic",
|
78: "routes.MoveTopicSubmit",
|
||||||
79: "routeCreateReplySubmit",
|
79: "routeLikeTopicSubmit",
|
||||||
80: "routes.ReplyEditSubmit",
|
80: "routes.ViewTopic",
|
||||||
81: "routes.ReplyDeleteSubmit",
|
81: "routeCreateReplySubmit",
|
||||||
82: "routeReplyLikeSubmit",
|
82: "routes.ReplyEditSubmit",
|
||||||
83: "routeProfileReplyCreateSubmit",
|
83: "routes.ReplyDeleteSubmit",
|
||||||
84: "routes.ProfileReplyEditSubmit",
|
84: "routeReplyLikeSubmit",
|
||||||
85: "routes.ProfileReplyDeleteSubmit",
|
85: "routeProfileReplyCreateSubmit",
|
||||||
86: "routes.PollVote",
|
86: "routes.ProfileReplyEditSubmit",
|
||||||
87: "routes.PollResults",
|
87: "routes.ProfileReplyDeleteSubmit",
|
||||||
88: "routes.AccountLogin",
|
88: "routes.PollVote",
|
||||||
89: "routes.AccountRegister",
|
89: "routes.PollResults",
|
||||||
90: "routeLogout",
|
90: "routes.AccountLogin",
|
||||||
91: "routes.AccountLoginSubmit",
|
91: "routes.AccountRegister",
|
||||||
92: "routes.AccountRegisterSubmit",
|
92: "routeLogout",
|
||||||
93: "routeDynamic",
|
93: "routes.AccountLoginSubmit",
|
||||||
94: "routeUploads",
|
94: "routes.AccountRegisterSubmit",
|
||||||
95: "BadRoute",
|
95: "routeDynamic",
|
||||||
|
96: "routeUploads",
|
||||||
|
97: "BadRoute",
|
||||||
}
|
}
|
||||||
var osMapEnum = map[string]int{
|
var osMapEnum = map[string]int{
|
||||||
"unknown": 0,
|
"unknown": 0,
|
||||||
@ -681,6 +687,17 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
common.OSViewCounter.Bump(osMapEnum[os])
|
common.OSViewCounter.Bump(osMapEnum[os])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
referrer := req.Header.Get("Referer") // Check the referrer header too? :P
|
||||||
|
if referrer != "" {
|
||||||
|
// ? Optimise this a little?
|
||||||
|
referrer = strings.TrimPrefix(strings.TrimPrefix(referrer,"http://"),"https://")
|
||||||
|
referrer = strings.Split(referrer,"/")[0]
|
||||||
|
portless := strings.Split(referrer,":")[0]
|
||||||
|
if portless != "localhost" && portless != "127.0.0.1" && portless == common.Site.Host {
|
||||||
|
common.ReferrerTracker.Bump(referrer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Deal with the session stuff, etc.
|
// Deal with the session stuff, etc.
|
||||||
user, ok := common.PreRoute(w, req)
|
user, ok := common.PreRoute(w, req)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -1011,15 +1028,27 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
common.RouteViewCounter.Bump(40)
|
common.RouteViewCounter.Bump(40)
|
||||||
err = routePanelAnalyticsSystems(w,req,user)
|
err = routePanelAnalyticsSystems(w,req,user)
|
||||||
case "/panel/analytics/route/":
|
case "/panel/analytics/referrers/":
|
||||||
|
err = common.ParseForm(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
router.handleError(err,w,req,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(41)
|
common.RouteViewCounter.Bump(41)
|
||||||
|
err = routePanelAnalyticsReferrers(w,req,user)
|
||||||
|
case "/panel/analytics/route/":
|
||||||
|
common.RouteViewCounter.Bump(42)
|
||||||
err = routePanelAnalyticsRouteViews(w,req,user,extraData)
|
err = routePanelAnalyticsRouteViews(w,req,user,extraData)
|
||||||
case "/panel/analytics/agent/":
|
case "/panel/analytics/agent/":
|
||||||
common.RouteViewCounter.Bump(42)
|
common.RouteViewCounter.Bump(43)
|
||||||
err = routePanelAnalyticsAgentViews(w,req,user,extraData)
|
err = routePanelAnalyticsAgentViews(w,req,user,extraData)
|
||||||
case "/panel/analytics/system/":
|
case "/panel/analytics/system/":
|
||||||
common.RouteViewCounter.Bump(43)
|
common.RouteViewCounter.Bump(44)
|
||||||
err = routePanelAnalyticsSystemViews(w,req,user,extraData)
|
err = routePanelAnalyticsSystemViews(w,req,user,extraData)
|
||||||
|
case "/panel/analytics/referrer/":
|
||||||
|
common.RouteViewCounter.Bump(45)
|
||||||
|
err = routePanelAnalyticsReferrerViews(w,req,user,extraData)
|
||||||
case "/panel/analytics/posts/":
|
case "/panel/analytics/posts/":
|
||||||
err = common.ParseForm(w,req,user)
|
err = common.ParseForm(w,req,user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1027,7 +1056,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(44)
|
common.RouteViewCounter.Bump(46)
|
||||||
err = routePanelAnalyticsPosts(w,req,user)
|
err = routePanelAnalyticsPosts(w,req,user)
|
||||||
case "/panel/analytics/topics/":
|
case "/panel/analytics/topics/":
|
||||||
err = common.ParseForm(w,req,user)
|
err = common.ParseForm(w,req,user)
|
||||||
@ -1036,16 +1065,16 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(45)
|
common.RouteViewCounter.Bump(47)
|
||||||
err = routePanelAnalyticsTopics(w,req,user)
|
err = routePanelAnalyticsTopics(w,req,user)
|
||||||
case "/panel/groups/":
|
case "/panel/groups/":
|
||||||
common.RouteViewCounter.Bump(46)
|
common.RouteViewCounter.Bump(48)
|
||||||
err = routePanelGroups(w,req,user)
|
err = routePanelGroups(w,req,user)
|
||||||
case "/panel/groups/edit/":
|
case "/panel/groups/edit/":
|
||||||
common.RouteViewCounter.Bump(47)
|
common.RouteViewCounter.Bump(49)
|
||||||
err = routePanelGroupsEdit(w,req,user,extraData)
|
err = routePanelGroupsEdit(w,req,user,extraData)
|
||||||
case "/panel/groups/edit/perms/":
|
case "/panel/groups/edit/perms/":
|
||||||
common.RouteViewCounter.Bump(48)
|
common.RouteViewCounter.Bump(50)
|
||||||
err = routePanelGroupsEditPerms(w,req,user,extraData)
|
err = routePanelGroupsEditPerms(w,req,user,extraData)
|
||||||
case "/panel/groups/edit/submit/":
|
case "/panel/groups/edit/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1054,7 +1083,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(49)
|
common.RouteViewCounter.Bump(51)
|
||||||
err = routePanelGroupsEditSubmit(w,req,user,extraData)
|
err = routePanelGroupsEditSubmit(w,req,user,extraData)
|
||||||
case "/panel/groups/edit/perms/submit/":
|
case "/panel/groups/edit/perms/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1063,7 +1092,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(50)
|
common.RouteViewCounter.Bump(52)
|
||||||
err = routePanelGroupsEditPermsSubmit(w,req,user,extraData)
|
err = routePanelGroupsEditPermsSubmit(w,req,user,extraData)
|
||||||
case "/panel/groups/create/":
|
case "/panel/groups/create/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1072,7 +1101,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(51)
|
common.RouteViewCounter.Bump(53)
|
||||||
err = routePanelGroupsCreateSubmit(w,req,user)
|
err = routePanelGroupsCreateSubmit(w,req,user)
|
||||||
case "/panel/backups/":
|
case "/panel/backups/":
|
||||||
err = common.SuperAdminOnly(w,req,user)
|
err = common.SuperAdminOnly(w,req,user)
|
||||||
@ -1081,10 +1110,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(52)
|
common.RouteViewCounter.Bump(54)
|
||||||
err = routePanelBackups(w,req,user,extraData)
|
err = routePanelBackups(w,req,user,extraData)
|
||||||
case "/panel/logs/mod/":
|
case "/panel/logs/mod/":
|
||||||
common.RouteViewCounter.Bump(53)
|
common.RouteViewCounter.Bump(55)
|
||||||
err = routePanelLogsMod(w,req,user)
|
err = routePanelLogsMod(w,req,user)
|
||||||
case "/panel/debug/":
|
case "/panel/debug/":
|
||||||
err = common.AdminOnly(w,req,user)
|
err = common.AdminOnly(w,req,user)
|
||||||
@ -1093,10 +1122,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(54)
|
common.RouteViewCounter.Bump(56)
|
||||||
err = routePanelDebug(w,req,user)
|
err = routePanelDebug(w,req,user)
|
||||||
default:
|
default:
|
||||||
common.RouteViewCounter.Bump(55)
|
common.RouteViewCounter.Bump(57)
|
||||||
err = routePanelDashboard(w,req,user)
|
err = routePanelDashboard(w,req,user)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1111,7 +1140,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(56)
|
common.RouteViewCounter.Bump(58)
|
||||||
err = routes.AccountEditCritical(w,req,user)
|
err = routes.AccountEditCritical(w,req,user)
|
||||||
case "/user/edit/critical/submit/":
|
case "/user/edit/critical/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1126,7 +1155,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(57)
|
common.RouteViewCounter.Bump(59)
|
||||||
err = routeAccountEditCriticalSubmit(w,req,user)
|
err = routeAccountEditCriticalSubmit(w,req,user)
|
||||||
case "/user/edit/avatar/":
|
case "/user/edit/avatar/":
|
||||||
err = common.MemberOnly(w,req,user)
|
err = common.MemberOnly(w,req,user)
|
||||||
@ -1135,7 +1164,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(58)
|
common.RouteViewCounter.Bump(60)
|
||||||
err = routeAccountEditAvatar(w,req,user)
|
err = routeAccountEditAvatar(w,req,user)
|
||||||
case "/user/edit/avatar/submit/":
|
case "/user/edit/avatar/submit/":
|
||||||
err = common.MemberOnly(w,req,user)
|
err = common.MemberOnly(w,req,user)
|
||||||
@ -1155,7 +1184,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(59)
|
common.RouteViewCounter.Bump(61)
|
||||||
err = routeAccountEditAvatarSubmit(w,req,user)
|
err = routeAccountEditAvatarSubmit(w,req,user)
|
||||||
case "/user/edit/username/":
|
case "/user/edit/username/":
|
||||||
err = common.MemberOnly(w,req,user)
|
err = common.MemberOnly(w,req,user)
|
||||||
@ -1164,7 +1193,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(60)
|
common.RouteViewCounter.Bump(62)
|
||||||
err = routeAccountEditUsername(w,req,user)
|
err = routeAccountEditUsername(w,req,user)
|
||||||
case "/user/edit/username/submit/":
|
case "/user/edit/username/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1179,7 +1208,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(61)
|
common.RouteViewCounter.Bump(63)
|
||||||
err = routeAccountEditUsernameSubmit(w,req,user)
|
err = routeAccountEditUsernameSubmit(w,req,user)
|
||||||
case "/user/edit/email/":
|
case "/user/edit/email/":
|
||||||
err = common.MemberOnly(w,req,user)
|
err = common.MemberOnly(w,req,user)
|
||||||
@ -1188,7 +1217,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(62)
|
common.RouteViewCounter.Bump(64)
|
||||||
err = routeAccountEditEmail(w,req,user)
|
err = routeAccountEditEmail(w,req,user)
|
||||||
case "/user/edit/token/":
|
case "/user/edit/token/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1203,11 +1232,11 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(63)
|
common.RouteViewCounter.Bump(65)
|
||||||
err = routeAccountEditEmailTokenSubmit(w,req,user,extraData)
|
err = routeAccountEditEmailTokenSubmit(w,req,user,extraData)
|
||||||
default:
|
default:
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
common.RouteViewCounter.Bump(64)
|
common.RouteViewCounter.Bump(66)
|
||||||
err = routeProfile(w,req,user)
|
err = routeProfile(w,req,user)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1228,7 +1257,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(65)
|
common.RouteViewCounter.Bump(67)
|
||||||
err = routes.BanUserSubmit(w,req,user,extraData)
|
err = routes.BanUserSubmit(w,req,user,extraData)
|
||||||
case "/users/unban/":
|
case "/users/unban/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1243,7 +1272,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(66)
|
common.RouteViewCounter.Bump(68)
|
||||||
err = routes.UnbanUser(w,req,user,extraData)
|
err = routes.UnbanUser(w,req,user,extraData)
|
||||||
case "/users/activate/":
|
case "/users/activate/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1258,7 +1287,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(67)
|
common.RouteViewCounter.Bump(69)
|
||||||
err = routes.ActivateUser(w,req,user,extraData)
|
err = routes.ActivateUser(w,req,user,extraData)
|
||||||
case "/users/ips/":
|
case "/users/ips/":
|
||||||
err = common.MemberOnly(w,req,user)
|
err = common.MemberOnly(w,req,user)
|
||||||
@ -1267,7 +1296,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(68)
|
common.RouteViewCounter.Bump(70)
|
||||||
err = routes.IPSearch(w,req,user)
|
err = routes.IPSearch(w,req,user)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1293,7 +1322,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(69)
|
common.RouteViewCounter.Bump(71)
|
||||||
err = routes.CreateTopicSubmit(w,req,user)
|
err = routes.CreateTopicSubmit(w,req,user)
|
||||||
case "/topic/edit/submit/":
|
case "/topic/edit/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1308,7 +1337,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(70)
|
common.RouteViewCounter.Bump(72)
|
||||||
err = routes.EditTopicSubmit(w,req,user,extraData)
|
err = routes.EditTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/delete/submit/":
|
case "/topic/delete/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1324,7 +1353,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
common.RouteViewCounter.Bump(71)
|
common.RouteViewCounter.Bump(73)
|
||||||
err = routes.DeleteTopicSubmit(w,req,user)
|
err = routes.DeleteTopicSubmit(w,req,user)
|
||||||
case "/topic/stick/submit/":
|
case "/topic/stick/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1339,7 +1368,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(72)
|
common.RouteViewCounter.Bump(74)
|
||||||
err = routes.StickTopicSubmit(w,req,user,extraData)
|
err = routes.StickTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/unstick/submit/":
|
case "/topic/unstick/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1354,7 +1383,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(73)
|
common.RouteViewCounter.Bump(75)
|
||||||
err = routes.UnstickTopicSubmit(w,req,user,extraData)
|
err = routes.UnstickTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/lock/submit/":
|
case "/topic/lock/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1370,7 +1399,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
common.RouteViewCounter.Bump(74)
|
common.RouteViewCounter.Bump(76)
|
||||||
err = routes.LockTopicSubmit(w,req,user)
|
err = routes.LockTopicSubmit(w,req,user)
|
||||||
case "/topic/unlock/submit/":
|
case "/topic/unlock/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1385,7 +1414,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(75)
|
common.RouteViewCounter.Bump(77)
|
||||||
err = routes.UnlockTopicSubmit(w,req,user,extraData)
|
err = routes.UnlockTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/move/submit/":
|
case "/topic/move/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1400,7 +1429,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(76)
|
common.RouteViewCounter.Bump(78)
|
||||||
err = routes.MoveTopicSubmit(w,req,user,extraData)
|
err = routes.MoveTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/like/submit/":
|
case "/topic/like/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1415,10 +1444,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(77)
|
common.RouteViewCounter.Bump(79)
|
||||||
err = routeLikeTopicSubmit(w,req,user,extraData)
|
err = routeLikeTopicSubmit(w,req,user,extraData)
|
||||||
default:
|
default:
|
||||||
common.RouteViewCounter.Bump(78)
|
common.RouteViewCounter.Bump(80)
|
||||||
err = routes.ViewTopic(w,req,user, extraData)
|
err = routes.ViewTopic(w,req,user, extraData)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1444,7 +1473,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(79)
|
common.RouteViewCounter.Bump(81)
|
||||||
err = routeCreateReplySubmit(w,req,user)
|
err = routeCreateReplySubmit(w,req,user)
|
||||||
case "/reply/edit/submit/":
|
case "/reply/edit/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1459,7 +1488,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(80)
|
common.RouteViewCounter.Bump(82)
|
||||||
err = routes.ReplyEditSubmit(w,req,user,extraData)
|
err = routes.ReplyEditSubmit(w,req,user,extraData)
|
||||||
case "/reply/delete/submit/":
|
case "/reply/delete/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1474,7 +1503,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(81)
|
common.RouteViewCounter.Bump(83)
|
||||||
err = routes.ReplyDeleteSubmit(w,req,user,extraData)
|
err = routes.ReplyDeleteSubmit(w,req,user,extraData)
|
||||||
case "/reply/like/submit/":
|
case "/reply/like/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1489,7 +1518,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(82)
|
common.RouteViewCounter.Bump(84)
|
||||||
err = routeReplyLikeSubmit(w,req,user,extraData)
|
err = routeReplyLikeSubmit(w,req,user,extraData)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1510,7 +1539,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(83)
|
common.RouteViewCounter.Bump(85)
|
||||||
err = routeProfileReplyCreateSubmit(w,req,user)
|
err = routeProfileReplyCreateSubmit(w,req,user)
|
||||||
case "/profile/reply/edit/submit/":
|
case "/profile/reply/edit/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1525,7 +1554,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(84)
|
common.RouteViewCounter.Bump(86)
|
||||||
err = routes.ProfileReplyEditSubmit(w,req,user,extraData)
|
err = routes.ProfileReplyEditSubmit(w,req,user,extraData)
|
||||||
case "/profile/reply/delete/submit/":
|
case "/profile/reply/delete/submit/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1540,7 +1569,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(85)
|
common.RouteViewCounter.Bump(87)
|
||||||
err = routes.ProfileReplyDeleteSubmit(w,req,user,extraData)
|
err = routes.ProfileReplyDeleteSubmit(w,req,user,extraData)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1561,10 +1590,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(86)
|
common.RouteViewCounter.Bump(88)
|
||||||
err = routes.PollVote(w,req,user,extraData)
|
err = routes.PollVote(w,req,user,extraData)
|
||||||
case "/poll/results/":
|
case "/poll/results/":
|
||||||
common.RouteViewCounter.Bump(87)
|
common.RouteViewCounter.Bump(89)
|
||||||
err = routes.PollResults(w,req,user,extraData)
|
err = routes.PollResults(w,req,user,extraData)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1573,10 +1602,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
case "/accounts":
|
case "/accounts":
|
||||||
switch(req.URL.Path) {
|
switch(req.URL.Path) {
|
||||||
case "/accounts/login/":
|
case "/accounts/login/":
|
||||||
common.RouteViewCounter.Bump(88)
|
common.RouteViewCounter.Bump(90)
|
||||||
err = routes.AccountLogin(w,req,user)
|
err = routes.AccountLogin(w,req,user)
|
||||||
case "/accounts/create/":
|
case "/accounts/create/":
|
||||||
common.RouteViewCounter.Bump(89)
|
common.RouteViewCounter.Bump(91)
|
||||||
err = routes.AccountRegister(w,req,user)
|
err = routes.AccountRegister(w,req,user)
|
||||||
case "/accounts/logout/":
|
case "/accounts/logout/":
|
||||||
err = common.NoSessionMismatch(w,req,user)
|
err = common.NoSessionMismatch(w,req,user)
|
||||||
@ -1591,7 +1620,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(90)
|
common.RouteViewCounter.Bump(92)
|
||||||
err = routeLogout(w,req,user)
|
err = routeLogout(w,req,user)
|
||||||
case "/accounts/login/submit/":
|
case "/accounts/login/submit/":
|
||||||
err = common.ParseForm(w,req,user)
|
err = common.ParseForm(w,req,user)
|
||||||
@ -1600,7 +1629,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(91)
|
common.RouteViewCounter.Bump(93)
|
||||||
err = routes.AccountLoginSubmit(w,req,user)
|
err = routes.AccountLoginSubmit(w,req,user)
|
||||||
case "/accounts/create/submit/":
|
case "/accounts/create/submit/":
|
||||||
err = common.ParseForm(w,req,user)
|
err = common.ParseForm(w,req,user)
|
||||||
@ -1609,7 +1638,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteViewCounter.Bump(92)
|
common.RouteViewCounter.Bump(94)
|
||||||
err = routes.AccountRegisterSubmit(w,req,user)
|
err = routes.AccountRegisterSubmit(w,req,user)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1626,7 +1655,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
common.NotFound(w,req)
|
common.NotFound(w,req)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
common.RouteViewCounter.Bump(94)
|
common.RouteViewCounter.Bump(96)
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
// TODO: Find a way to propagate errors up from this?
|
// TODO: Find a way to propagate errors up from this?
|
||||||
router.UploadHandler(w,req) // TODO: Count these views
|
router.UploadHandler(w,req) // TODO: Count these views
|
||||||
@ -1669,7 +1698,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
router.RUnlock()
|
router.RUnlock()
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
common.RouteViewCounter.Bump(93) // TODO: Be more specific about *which* dynamic route it is
|
common.RouteViewCounter.Bump(95) // TODO: Be more specific about *which* dynamic route it is
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
err = handle(w,req,user)
|
err = handle(w,req,user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1683,7 +1712,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
if strings.Contains(lowerPath,"admin") || strings.Contains(lowerPath,"sql") || strings.Contains(lowerPath,"manage") || strings.Contains(lowerPath,"//") || strings.Contains(lowerPath,"\\\\") || strings.Contains(lowerPath,"wp") || strings.Contains(lowerPath,"wordpress") || strings.Contains(lowerPath,"config") || strings.Contains(lowerPath,"setup") || strings.Contains(lowerPath,"install") || strings.Contains(lowerPath,"update") || strings.Contains(lowerPath,"php") {
|
if strings.Contains(lowerPath,"admin") || strings.Contains(lowerPath,"sql") || strings.Contains(lowerPath,"manage") || strings.Contains(lowerPath,"//") || strings.Contains(lowerPath,"\\\\") || strings.Contains(lowerPath,"wp") || strings.Contains(lowerPath,"wordpress") || strings.Contains(lowerPath,"config") || strings.Contains(lowerPath,"setup") || strings.Contains(lowerPath,"install") || strings.Contains(lowerPath,"update") || strings.Contains(lowerPath,"php") {
|
||||||
router.SuspiciousRequest(req)
|
router.SuspiciousRequest(req)
|
||||||
}
|
}
|
||||||
common.RouteViewCounter.Bump(95)
|
common.RouteViewCounter.Bump(97)
|
||||||
common.NotFound(w,req)
|
common.NotFound(w,req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
main.go
4
main.go
@ -125,6 +125,10 @@ func afterDBInit() (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
common.ReferrerTracker, err = common.NewDefaultReferrerTracker()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
126
panel_routes.go
126
panel_routes.go
@ -917,6 +917,81 @@ func routePanelAnalyticsSystemViews(w http.ResponseWriter, r *http.Request, user
|
|||||||
return panelRenderTemplate("panel_analytics_system_views", w, r, user, &pi)
|
return panelRenderTemplate("panel_analytics_system_views", w, r, user, &pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func routePanelAnalyticsReferrerViews(w http.ResponseWriter, r *http.Request, user common.User, domain string) common.RouteError {
|
||||||
|
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||||
|
if ferr != nil {
|
||||||
|
return ferr
|
||||||
|
}
|
||||||
|
headerVars.Stylesheets = append(headerVars.Stylesheets, "chartist/chartist.min.css")
|
||||||
|
headerVars.Scripts = append(headerVars.Scripts, "chartist/chartist.min.js")
|
||||||
|
|
||||||
|
timeRange, err := panelAnalyticsTimeRange(r.FormValue("timeRange"))
|
||||||
|
if err != nil {
|
||||||
|
return common.LocalError(err.Error(), w, r, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
var revLabelList []int64
|
||||||
|
var labelList []int64
|
||||||
|
var viewMap = make(map[int64]int64)
|
||||||
|
var currentTime = time.Now().Unix()
|
||||||
|
|
||||||
|
for i := 1; i <= timeRange.Slices; i++ {
|
||||||
|
var label = currentTime - int64(i*timeRange.SliceWidth)
|
||||||
|
revLabelList = append(revLabelList, label)
|
||||||
|
viewMap[label] = 0
|
||||||
|
}
|
||||||
|
for _, value := range revLabelList {
|
||||||
|
labelList = append(labelList, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
var viewList []int64
|
||||||
|
log.Print("in routePanelAnalyticsReferrerViews")
|
||||||
|
|
||||||
|
acc := qgen.Builder.Accumulator()
|
||||||
|
// TODO: Verify the agent is valid
|
||||||
|
rows, err := acc.Select("viewchunks_referrers").Columns("count, createdAt").Where("domain = ?").DateCutoff("createdAt", timeRange.Quantity, timeRange.Unit).Query(domain)
|
||||||
|
if err != nil && err != ErrNoRows {
|
||||||
|
return common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var count int64
|
||||||
|
var createdAt time.Time
|
||||||
|
err := rows.Scan(&count, &createdAt)
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
var unixCreatedAt = createdAt.Unix()
|
||||||
|
if common.Dev.SuperDebug {
|
||||||
|
log.Print("count: ", count)
|
||||||
|
log.Print("createdAt: ", createdAt)
|
||||||
|
log.Print("unixCreatedAt: ", unixCreatedAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, value := range labelList {
|
||||||
|
if unixCreatedAt > value {
|
||||||
|
viewMap[value] += count
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = rows.Err()
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, value := range revLabelList {
|
||||||
|
viewList = append(viewList, viewMap[value])
|
||||||
|
}
|
||||||
|
graph := common.PanelTimeGraph{Series: viewList, Labels: labelList}
|
||||||
|
log.Printf("graph: %+v\n", graph)
|
||||||
|
|
||||||
|
pi := common.PanelAnalyticsAgentPage{common.GetTitlePhrase("panel_analytics"), user, headerVars, stats, "analytics", html.EscapeString(domain), "", graph, timeRange.Range}
|
||||||
|
return panelRenderTemplate("panel_analytics_referrer_views", w, r, user, &pi)
|
||||||
|
}
|
||||||
|
|
||||||
func routePanelAnalyticsTopics(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
func routePanelAnalyticsTopics(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||||
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
@ -1232,6 +1307,57 @@ func routePanelAnalyticsSystems(w http.ResponseWriter, r *http.Request, user com
|
|||||||
return panelRenderTemplate("panel_analytics_systems", w, r, user, &pi)
|
return panelRenderTemplate("panel_analytics_systems", w, r, user, &pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func routePanelAnalyticsReferrers(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||||
|
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||||
|
if ferr != nil {
|
||||||
|
return ferr
|
||||||
|
}
|
||||||
|
var refMap = make(map[string]int)
|
||||||
|
|
||||||
|
timeRange, err := panelAnalyticsTimeRange(r.FormValue("timeRange"))
|
||||||
|
if err != nil {
|
||||||
|
return common.LocalError(err.Error(), w, r, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
acc := qgen.Builder.Accumulator()
|
||||||
|
rows, err := acc.Select("viewchunks_referrers").Columns("count, domain").DateCutoff("createdAt", timeRange.Quantity, timeRange.Unit).Query()
|
||||||
|
if err != nil && err != ErrNoRows {
|
||||||
|
return common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var count int
|
||||||
|
var domain string
|
||||||
|
err := rows.Scan(&count, &domain)
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
if common.Dev.SuperDebug {
|
||||||
|
log.Print("count: ", count)
|
||||||
|
log.Print("domain: ", domain)
|
||||||
|
}
|
||||||
|
refMap[domain] += count
|
||||||
|
}
|
||||||
|
err = rows.Err()
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Sort this slice
|
||||||
|
var refItems []common.PanelAnalyticsAgentsItem
|
||||||
|
for domain, count := range refMap {
|
||||||
|
refItems = append(refItems, common.PanelAnalyticsAgentsItem{
|
||||||
|
Agent: html.EscapeString(domain),
|
||||||
|
Count: count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pi := common.PanelAnalyticsAgentsPage{common.GetTitlePhrase("panel_analytics"), user, headerVars, stats, "analytics", refItems, timeRange.Range}
|
||||||
|
return panelRenderTemplate("panel_analytics_referrers", w, r, user, &pi)
|
||||||
|
}
|
||||||
|
|
||||||
func routePanelSettings(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
func routePanelSettings(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||||
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
|
@ -411,11 +411,11 @@ $(document).ready(function(){
|
|||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
})
|
})
|
||||||
|
|
||||||
$(".create_topic_link").click(function(event){
|
$(".create_topic_link").click((event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
$(".topic_create_form").show();
|
$(".topic_create_form").show();
|
||||||
});
|
});
|
||||||
$(".topic_create_form .close_form").click(function(){
|
$(".topic_create_form .close_form").click((event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
$(".topic_create_form").hide();
|
$(".topic_create_form").hide();
|
||||||
});
|
});
|
||||||
@ -504,7 +504,7 @@ $(document).ready(function(){
|
|||||||
data: JSON.stringify(selectedTopics),
|
data: JSON.stringify(selectedTopics),
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
error: ajaxError,
|
error: ajaxError,
|
||||||
success: function() {
|
success: () => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -598,7 +598,7 @@ $(document).ready(function(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
var pollInputIndex = 1;
|
var pollInputIndex = 1;
|
||||||
$("#add_poll_button").click(function(event){
|
$("#add_poll_button").click((event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
$(".poll_content_row").removeClass("auto_hide");
|
$(".poll_content_row").removeClass("auto_hide");
|
||||||
$("#has_poll_input").val("1");
|
$("#has_poll_input").val("1");
|
||||||
|
@ -416,7 +416,16 @@ func createTables(adapter qgen.Adapter) error {
|
|||||||
[]qgen.DBTableColumn{
|
[]qgen.DBTableColumn{
|
||||||
qgen.DBTableColumn{"count", "int", 0, false, false, "0"},
|
qgen.DBTableColumn{"count", "int", 0, false, false, "0"},
|
||||||
qgen.DBTableColumn{"createdAt", "datetime", 0, false, false, ""},
|
qgen.DBTableColumn{"createdAt", "datetime", 0, false, false, ""},
|
||||||
qgen.DBTableColumn{"system", "varchar", 200, false, false, ""}, // windows, android, bot, etc.
|
qgen.DBTableColumn{"system", "varchar", 200, false, false, ""}, // windows, android, unknown, etc.
|
||||||
|
},
|
||||||
|
[]qgen.DBTableKey{},
|
||||||
|
)
|
||||||
|
|
||||||
|
qgen.Install.CreateTable("viewchunks_referrers", "", "",
|
||||||
|
[]qgen.DBTableColumn{
|
||||||
|
qgen.DBTableColumn{"count", "int", 0, false, false, "0"},
|
||||||
|
qgen.DBTableColumn{"createdAt", "datetime", 0, false, false, ""},
|
||||||
|
qgen.DBTableColumn{"domain", "varchar", 200, false, false, ""},
|
||||||
},
|
},
|
||||||
[]qgen.DBTableKey{},
|
[]qgen.DBTableKey{},
|
||||||
)
|
)
|
||||||
|
@ -546,6 +546,17 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
common.OSViewCounter.Bump(osMapEnum[os])
|
common.OSViewCounter.Bump(osMapEnum[os])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P
|
||||||
|
if referrer != "" {
|
||||||
|
// ? Optimise this a little?
|
||||||
|
referrer = strings.TrimPrefix(strings.TrimPrefix(referrer,"http://"),"https://")
|
||||||
|
referrer = strings.Split(referrer,"/")[0]
|
||||||
|
portless := strings.Split(referrer,":")[0]
|
||||||
|
if portless != "localhost" && portless != "127.0.0.1" && portless != common.Site.Host {
|
||||||
|
common.ReferrerTracker.Bump(referrer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Deal with the session stuff, etc.
|
// Deal with the session stuff, etc.
|
||||||
user, ok := common.PreRoute(w, req)
|
user, ok := common.PreRoute(w, req)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -167,9 +167,11 @@ func buildPanelRoutes() {
|
|||||||
View("routePanelAnalyticsRoutes", "/panel/analytics/routes/").Before("ParseForm"),
|
View("routePanelAnalyticsRoutes", "/panel/analytics/routes/").Before("ParseForm"),
|
||||||
View("routePanelAnalyticsAgents", "/panel/analytics/agents/").Before("ParseForm"),
|
View("routePanelAnalyticsAgents", "/panel/analytics/agents/").Before("ParseForm"),
|
||||||
View("routePanelAnalyticsSystems", "/panel/analytics/systems/").Before("ParseForm"),
|
View("routePanelAnalyticsSystems", "/panel/analytics/systems/").Before("ParseForm"),
|
||||||
|
View("routePanelAnalyticsReferrers", "/panel/analytics/referrers/").Before("ParseForm"),
|
||||||
View("routePanelAnalyticsRouteViews", "/panel/analytics/route/", "extraData"),
|
View("routePanelAnalyticsRouteViews", "/panel/analytics/route/", "extraData"),
|
||||||
View("routePanelAnalyticsAgentViews", "/panel/analytics/agent/", "extraData"),
|
View("routePanelAnalyticsAgentViews", "/panel/analytics/agent/", "extraData"),
|
||||||
View("routePanelAnalyticsSystemViews", "/panel/analytics/system/", "extraData"),
|
View("routePanelAnalyticsSystemViews", "/panel/analytics/system/", "extraData"),
|
||||||
|
View("routePanelAnalyticsReferrerViews", "/panel/analytics/referrer/", "extraData"),
|
||||||
View("routePanelAnalyticsPosts", "/panel/analytics/posts/").Before("ParseForm"),
|
View("routePanelAnalyticsPosts", "/panel/analytics/posts/").Before("ParseForm"),
|
||||||
View("routePanelAnalyticsTopics", "/panel/analytics/topics/").Before("ParseForm"),
|
View("routePanelAnalyticsTopics", "/panel/analytics/topics/").Before("ParseForm"),
|
||||||
|
|
||||||
|
5
schema/mssql/query_viewchunks_referrers.sql
Normal file
5
schema/mssql/query_viewchunks_referrers.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE [viewchunks_referrers] (
|
||||||
|
[count] int DEFAULT 0 not null,
|
||||||
|
[createdAt] datetime not null,
|
||||||
|
[domain] nvarchar (200) not null
|
||||||
|
);
|
5
schema/mysql/query_viewchunks_referrers.sql
Normal file
5
schema/mysql/query_viewchunks_referrers.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE `viewchunks_referrers` (
|
||||||
|
`count` int DEFAULT 0 not null,
|
||||||
|
`createdAt` datetime not null,
|
||||||
|
`domain` varchar(200) not null
|
||||||
|
);
|
5
schema/pgsql/query_viewchunks_referrers.sql
Normal file
5
schema/pgsql/query_viewchunks_referrers.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE `viewchunks_referrers` (
|
||||||
|
`count` int DEFAULT 0 not null,
|
||||||
|
`createdAt` timestamp not null,
|
||||||
|
`domain` varchar (200) not null
|
||||||
|
);
|
@ -41,11 +41,14 @@
|
|||||||
<div class="rowitem passive submenu">
|
<div class="rowitem passive submenu">
|
||||||
<a href="/panel/analytics/agents/">Agents</a>
|
<a href="/panel/analytics/agents/">Agents</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="rowitem passive submenu">
|
||||||
|
<a href="/panel/analytics/crawlers/">Crawlers</a>
|
||||||
|
</div>
|
||||||
<div class="rowitem passive submenu">
|
<div class="rowitem passive submenu">
|
||||||
<a href="/panel/analytics/systems/">Systems</a>
|
<a href="/panel/analytics/systems/">Systems</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowitem passive submenu">
|
<div class="rowitem passive submenu">
|
||||||
<a href="/panel/analytics/crawlers/">Crawlers</a>
|
<a href="/panel/analytics/referrers/">Referrers</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="rowitem passive">
|
<div class="rowitem passive">
|
||||||
|
51
templates/panel_analytics_referrer_views.html
Normal file
51
templates/panel_analytics_referrer_views.html
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{{template "header.html" . }}
|
||||||
|
<div class="colstack panel_stack">
|
||||||
|
{{template "panel-menu.html" . }}
|
||||||
|
<main id="panel_dashboard_right" class="colstack_right">
|
||||||
|
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/referrer/{{.Agent}}" method="get">
|
||||||
|
<div class="colstack_item colstack_head">
|
||||||
|
<div class="rowitem">
|
||||||
|
<a>{{.Agent}} Views</a>
|
||||||
|
<select class="timeRangeSelector to_right" name="timeRange">
|
||||||
|
<option val="one-month"{{if eq .TimeRange "one-month"}} selected{{end}}>1 month</option>
|
||||||
|
<option val="two-days"{{if eq .TimeRange "two-days"}} selected{{end}}>2 days</option>
|
||||||
|
<option val="one-day"{{if eq .TimeRange "one-day"}} selected{{end}}>1 day</option>
|
||||||
|
<option val="twelve-hours"{{if eq .TimeRange "twelve-hours"}} selected{{end}}>12 hours</option>
|
||||||
|
<option val="six-hours"{{if eq .TimeRange "six-hours"}} selected{{end}}>6 hours</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div id="panel_analytics_referrers" class="colstack_graph_holder">
|
||||||
|
<div class="ct-chart"></div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
let labels = [];
|
||||||
|
let rawLabels = [{{range .PrimaryGraph.Labels}}
|
||||||
|
{{.}},{{end}}
|
||||||
|
];
|
||||||
|
for(const i in rawLabels) {
|
||||||
|
let date = new Date(rawLabels[i]*1000);
|
||||||
|
console.log("date: ", date);
|
||||||
|
let minutes = "0" + date.getMinutes();
|
||||||
|
let label = date.getHours() + ":" + minutes.substr(-2);
|
||||||
|
console.log("label:", label);
|
||||||
|
labels.push(label);
|
||||||
|
}
|
||||||
|
labels = labels.reverse()
|
||||||
|
|
||||||
|
let seriesData = [{{range .PrimaryGraph.Series}}
|
||||||
|
{{.}},{{end}}
|
||||||
|
];
|
||||||
|
seriesData = seriesData.reverse();
|
||||||
|
|
||||||
|
Chartist.Line('.ct-chart', {
|
||||||
|
labels: labels,
|
||||||
|
series: [seriesData],
|
||||||
|
}, {
|
||||||
|
height: '250px',
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{{template "footer.html" . }}
|
29
templates/panel_analytics_referrers.html
Normal file
29
templates/panel_analytics_referrers.html
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{{template "header.html" . }}
|
||||||
|
<div class="colstack panel_stack">
|
||||||
|
{{template "panel-menu.html" . }}
|
||||||
|
<main id="panel_dashboard_right" class="colstack_right">
|
||||||
|
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/referrers/" method="get">
|
||||||
|
<div class="colstack_item colstack_head">
|
||||||
|
<div class="rowitem">
|
||||||
|
<a>Referrers</a>
|
||||||
|
<select class="timeRangeSelector to_right" name="timeRange">
|
||||||
|
<option val="one-month"{{if eq .TimeRange "one-month"}} selected{{end}}>1 month</option>
|
||||||
|
<option val="two-days"{{if eq .TimeRange "two-days"}} selected{{end}}>2 days</option>
|
||||||
|
<option val="one-day"{{if eq .TimeRange "one-day"}} selected{{end}}>1 day</option>
|
||||||
|
<option val="twelve-hours"{{if eq .TimeRange "twelve-hours"}} selected{{end}}>12 hours</option>
|
||||||
|
<option val="six-hours"{{if eq .TimeRange "six-hours"}} selected{{end}}>6 hours</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div id="panel_analytics_referrers" class="colstack_item rowlist">
|
||||||
|
{{range .ItemList}}
|
||||||
|
<div class="rowitem panel_compactrow editable_parent">
|
||||||
|
<a href="/panel/analytics/referrer/{{.Agent}}" class="panel_upshift">{{.Agent}}</a>
|
||||||
|
<span class="panel_compacttext to_right">{{.Count}} views</span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
{{template "footer.html" . }}
|
Loading…
Reference in New Issue
Block a user