mirror of
				https://github.com/taigrr/wtf
				synced 2025-01-18 04:03:14 -08:00 
			
		
		
		
	Add google analytics module
This commit is contained in:
		
							parent
							
								
									4f8a4c9dc2
								
							
						
					
					
						commit
						ae61d2f7ad
					
				
							
								
								
									
										93
									
								
								modules/googleanalytics/client.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								modules/googleanalytics/client.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,93 @@
 | 
				
			|||||||
 | 
					package googleanalytics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/wtfutil/wtf/utils"
 | 
				
			||||||
 | 
						"golang.org/x/oauth2"
 | 
				
			||||||
 | 
						"golang.org/x/oauth2/google"
 | 
				
			||||||
 | 
						ga "google.golang.org/api/analyticsreporting/v4"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type websiteReport struct {
 | 
				
			||||||
 | 
					    Name string
 | 
				
			||||||
 | 
					    Report *ga.GetReportsResponse
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (widget *Widget) Fetch() ([]websiteReport) {
 | 
				
			||||||
 | 
						secretPath, err := utils.ExpandHomeDir(widget.settings.secretFile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("Unable to parse secretFile path")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						service, err := makeReportService(secretPath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("Unable to create Google Analytics Reporting Service")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						visitorsDataArray := getReports(service, widget.settings.viewIds, widget.settings.months)
 | 
				
			||||||
 | 
						return visitorsDataArray
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func makeReportService(secretPath string) (*ga.Service, error) {
 | 
				
			||||||
 | 
						clientSecret, err := ioutil.ReadFile(secretPath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("Unable to read secretPath. %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						jwtConfig, err := google.JWTConfigFromJSON(clientSecret, ga.AnalyticsReadonlyScope)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("Unable to get config from JSON. %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var netClient *http.Client
 | 
				
			||||||
 | 
						netClient = jwtConfig.Client(oauth2.NoContext)
 | 
				
			||||||
 | 
						svc, err := ga.New(netClient)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("Failed to create Google Analytics Reporting Service")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return svc, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getReports(service *ga.Service, viewIds map[string]interface{}, displayedMonths int) ([]websiteReport) {
 | 
				
			||||||
 | 
						startDate := fmt.Sprintf("%s-01", time.Now().AddDate(0, -displayedMonths+1, 0).Format("2006-01"))
 | 
				
			||||||
 | 
						var websiteReports []websiteReport = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for website, viewId := range viewIds {
 | 
				
			||||||
 | 
							// For custom queries: https://ga-dev-tools.appspot.com/dimensions-metrics-explorer/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							req := &ga.GetReportsRequest{
 | 
				
			||||||
 | 
								ReportRequests: []*ga.ReportRequest{
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										ViewId: viewId.(string),
 | 
				
			||||||
 | 
										DateRanges: []*ga.DateRange{
 | 
				
			||||||
 | 
											{StartDate: startDate, EndDate: "today"},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Metrics: []*ga.Metric{
 | 
				
			||||||
 | 
											{Expression: "ga:sessions"},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Dimensions: []*ga.Dimension{
 | 
				
			||||||
 | 
											{Name: "ga:month"},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							response, err := service.Reports.BatchGet(req).Do()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Fatalf("GET request to analyticsreporting/v4 returned error with viewID: %s", viewId)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if response.HTTPStatusCode != 200 {
 | 
				
			||||||
 | 
								log.Fatalf("Did not get expected HTTP response code")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							report := websiteReport{Name: website, Report: response,}
 | 
				
			||||||
 | 
							websiteReports = append(websiteReports, report)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return websiteReports
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										54
									
								
								modules/googleanalytics/display.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								modules/googleanalytics/display.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					package googleanalytics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (widget *Widget) createTable(websiteReports []websiteReport) (string) {
 | 
				
			||||||
 | 
					  content := widget.createHeader()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, websiteReport := range websiteReports {
 | 
				
			||||||
 | 
							websiteRow := ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, report := range websiteReport.Report.Reports {
 | 
				
			||||||
 | 
								websiteRow += fmt.Sprintf(" %-20s", websiteReport.Name)
 | 
				
			||||||
 | 
								reportRows := report.Data.Rows
 | 
				
			||||||
 | 
								noDataMonth := widget.settings.months - len(reportRows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Fill in requested months with no data from query
 | 
				
			||||||
 | 
								if noDataMonth > 0 {
 | 
				
			||||||
 | 
										websiteRow += strings.Repeat("-         ", noDataMonth)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if reportRows == nil {
 | 
				
			||||||
 | 
									websiteRow += fmt.Sprintf("No data found for given ViewId.")
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									for _, row := range reportRows {
 | 
				
			||||||
 | 
										metrics := row.Metrics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										for _, metric := range metrics {
 | 
				
			||||||
 | 
											websiteRow += fmt.Sprintf("%-10s", metric.Values[0])
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								content += websiteRow + "\n"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return content
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (widget *Widget) createHeader() (string) {
 | 
				
			||||||
 | 
					  // Creates the table header of consisting of Months
 | 
				
			||||||
 | 
						currentMonth := int(time.Now().Month())
 | 
				
			||||||
 | 
						widgetStartMonth := currentMonth-widget.settings.months+1
 | 
				
			||||||
 | 
					  header := "                     "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for i := widgetStartMonth; i < currentMonth+1; i++ {
 | 
				
			||||||
 | 
					  	header += fmt.Sprintf("%-10s", time.Month(i))
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  header += "\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return header
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										29
									
								
								modules/googleanalytics/settings.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								modules/googleanalytics/settings.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					package googleanalytics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/olebedev/config"
 | 
				
			||||||
 | 
						"github.com/wtfutil/wtf/cfg"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const defaultTitle = "Google Analytics"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Settings struct {
 | 
				
			||||||
 | 
						common *cfg.Common
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						months				int
 | 
				
			||||||
 | 
						secretFile    string `help:"Your Google client secret JSON file." values:"A string representing a file path to the JSON secret file."`
 | 
				
			||||||
 | 
						viewIds				map[string]interface{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						settings := Settings{
 | 
				
			||||||
 | 
							common: cfg.NewCommonSettingsFromModule(name, defaultTitle, ymlConfig, globalConfig),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							months:			ymlConfig.UInt("months"),
 | 
				
			||||||
 | 
							secretFile: ymlConfig.UString("secretFile"),
 | 
				
			||||||
 | 
							viewIds:  ymlConfig.UMap("viewIds"),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &settings
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										29
									
								
								modules/googleanalytics/widget.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								modules/googleanalytics/widget.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					package googleanalytics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/rivo/tview"
 | 
				
			||||||
 | 
						"github.com/wtfutil/wtf/wtf"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Widget struct {
 | 
				
			||||||
 | 
						wtf.TextWidget
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						settings *Settings
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewWidget(app *tview.Application, settings *Settings) *Widget {
 | 
				
			||||||
 | 
						widget := Widget{
 | 
				
			||||||
 | 
							TextWidget: wtf.NewTextWidget(app, settings.common, false),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							settings: settings,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &widget
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (widget *Widget) Refresh() {
 | 
				
			||||||
 | 
						websiteReports := widget.Fetch()
 | 
				
			||||||
 | 
						contentTable := widget.createTable(websiteReports)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						widget.Redraw(widget.CommonSettings().Title, contentTable, false)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user