data.go 6.42 KB
package main

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/gorilla/mux"
	"github.com/jmoiron/sqlx"

	_ "github.com/mattn/go-sqlite3"
)

type Call struct {
	ID       int     `json:"id" db:"id"`
	Type     int     `json:"type" db:"type"`
	Name     *string `json:"name" db:"name"`
	Number   int     `json:"number" db:"number"`
	Duration int     `json:"duration" db:"duration"`
	Date     Time    `json:"date" db:"date"`
}

func (app *App) GetCalls(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	calls := []Call{}

	db, err := sqlx.Connect("sqlite3", fmt.Sprintf("data/1/%s", vars["file"]))
	if err != nil {
		WriteError(w, http.StatusInternalServerError, "Could not open db file")
		return
	}
	defer db.Close()

	query := `SELECT * FROM calllog`
	fmt.Println(db.Select(&calls, query))

	WriteJson(w, calls)
}

type CallStats struct {
	Number   string  `json:"number" db:"number"`
	Name     *string `json:"name" db:"name"`
	Incoming int     `json:"incoming" db:"incoming"`
	Outgoing int     `json:"outgoing" db:"outgoing"`
	Duration int     `json:"duration" db:"duration"`
}

func (app *App) GetCallsAnalyses(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	calls := []CallStats{}

	db, err := sqlx.Connect("sqlite3", fmt.Sprintf("data/1/%s", vars["file"]))
	if err != nil {
		WriteError(w, http.StatusInternalServerError, "Could not open db file")
		return
	}
	defer db.Close()

	query := `SELECT number, name,
		(SELECT COUNT(1) FROM calllog s WHERE s.number=c.number AND s.type=1) incoming,
		(SELECT COUNT(1) FROM calllog s WHERE s.number=c.number AND s.type=2) outgoing,
		SUM(duration) duration
	FROM calllog c GROUP BY number ORDER BY duration DESC`
	db.Select(&calls, query)

	WriteJson(w, calls)
}

type AppInfo struct {
	PackageName    string    `json:"package_name" db:"packagename"`
	Name           string    `json:"name" db:"name"`
	Version        string    `json:"version" db:"version"`
	WifiUsage      int       `json:"wifi_usage" db:"wifiusage"`
	CellularUsage  int       `json:"cellular_usage" db:"cellularusage"`
	LastUsed       time.Time `json:"last_used" db:"lasttimeused"`
	ForegroundTime int64     `json:"foreground_time" db:"totaltimeforeground"`
}

func (app *App) GetAppsAnalyses(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	apps := []AppInfo{}
	db, err := sqlx.Connect("sqlite3", fmt.Sprintf("data/1/%s", vars["file"]))
	if err != nil {
		WriteError(w, http.StatusInternalServerError, "Could not open db file")
		return
	}
	defer db.Close()

	query := `SELECT
		a.packagename, a.name, a.version, a.wifiusage, a.cellularusage,
		u.lasttimeused, u.totaltimeforeground
	FROM AppInfo a JOIN AppUsageYear u ON a.packagename=u.packagename
	ORDER BY u.totaltimeforeground DESC LIMIT 0, 100`
	db.Select(&apps, query)

	WriteJson(w, apps)
}

type Message struct {
	ID      int    `json:"id" db:"mid"`
	Type    int    `json:"type" db:"type"`
	Address string `json:"address"`
	Body    string `json:"body"`
	Date    Time   `json:"date" db:"date"`
}

func (app *App) GetMessages(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	messages := []Message{}
	db, err := sqlx.Connect("sqlite3", fmt.Sprintf("data/1/%s", vars["file"]))
	if err != nil {
		WriteError(w, http.StatusInternalServerError, "Could not open db file")
		return
	}
	defer db.Close()

	query := `SELECT mid, type, address, body, date FROM sms`
	db.Select(&messages, query)

	WriteJson(w, messages)
}

type MessageStats struct {
	Address string `json:"address" db:"address"`
	Receive int    `json:"receive" db:"receive"`
	Send    int    `json:"send" db:"send"`
}

func (app *App) GetMessagesAnalyses(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	messages := []MessageStats{}
	db, err := sqlx.Connect("sqlite3", fmt.Sprintf("data/1/%s", vars["file"]))
	if err != nil {
		WriteError(w, http.StatusInternalServerError, "Could not open db file")
		return
	}
	defer db.Close()

	query := `SELECT address,
		(SELECT COUNT(1) FROM sms m WHERE m.address=s.address AND m.type=1) receive,
		(SELECT COUNT(1) FROM sms m WHERE m.address=s.address AND m.type=2) send
	FROM sms s GROUP BY address ORDER BY receive + send DESC`
	db.Select(&messages, query)

	WriteJson(w, messages)
}

type Process struct {
	UID   string `json:"uid" db:"UID"`
	PID   int    `json:"pid" db:"PID"`
	PPID  int    `json:"ppid" db:"PPID"`
	STIME string `json:"stime" db:"STIME"`
	TIME  string `json:"time" db:"TIME"`
	CMD   string `json:"cmd" db:"CMD"`
}

func (app *App) GetProcesses(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	processes := []Process{}
	db, err := sqlx.Connect("sqlite3", fmt.Sprintf("data/1/%s", vars["file"]))
	if err != nil {
		WriteError(w, http.StatusInternalServerError, "Could not open db file")
		return
	}
	defer db.Close()

	query := `SELECT UID, CAST(PID AS INTEGER) PID, CAST(PPID AS INTEGER) PPID, STIME, TIME, CMD FROM process WHERE UID LIKE 'u%' ORDER BY TIME DESC`
	db.Select(&processes, query)

	WriteJson(w, processes)
}

type Alarm struct {
	ID      string         `json:"id"`
	When    time.Time      `json:"when"`
	History []AlarmHistory `json:"history"`
}

type AlarmHistory struct {
	Type string    `json:"type"`
	When time.Time `json:"when"`
}

func (app *App) GetAlarms(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	db, err := sqlx.Connect("sqlite3", fmt.Sprintf("data/1/%s", vars["file"]))
	if err != nil {
		WriteError(w, http.StatusInternalServerError, "Could not open db file")
		return
	}
	defer db.Close()

	alarms := map[string]Alarm{}
	rows, _ := db.Queryx("SELECT * FROM alarm ORDER BY TIME")

	for rows.Next() {
		var tm string
		var typ string
		var detail string

		rows.Scan(&tm, &typ, &detail)

		detail = detail[strings.Index(detail, "{")+1 : strings.Index(detail, "}")]
		s := strings.Split(detail, " ")
		timestamp, _ := strconv.ParseInt(s[4], 10, 64)
		timestamp /= 1000

		if _, ok := alarms[s[0]]; !ok {
			alarms[s[0]] = Alarm{ID: s[0], When: time.Unix(timestamp, 0)}
		}

		when, _ := time.Parse("2006-01-02 15:04:05", tm)
		alarm := alarms[s[0]]
		alarm.History = append(alarms[s[0]].History, AlarmHistory{
			Type: typ,
			When: when,
		})
		alarms[s[0]] = alarm
	}

	results := []Alarm{}
	for _, v := range alarms {
		results = append(results, v)
	}

	WriteJson(w, results)
}