Ma Suhyeon

Implement two more APIs

......@@ -33,6 +33,11 @@ func NewApp(config Config) *App {
app.router.HandleFunc("/users", app.PostUsers).Methods("POST")
app.router.HandleFunc("/users/tokens", app.PostTokens).Methods("POST")
app.router.Handle("/extractions", app.WithAuth(app.PostExtractions)).Methods("Post")
app.router.HandleFunc("/extractions/{file}/calls", app.GetCalls).Methods("GET")
app.router.HandleFunc("/extractions/{file}/messages", app.GetMessages).Methods("GET")
app.router.HandleFunc("/extractions/{file}/calls/analyses", app.GetCallsAnalyses).Methods("GET")
app.router.HandleFunc("/extractions/{file}/apps/analyses", app.GetAppsAnalyses).Methods("GET")
app.router.HandleFunc("/extractions/{file}/messages/analyses", app.GetMessagesAnalyses).Methods("GET")
return app
}
......
package main
import (
"fmt"
"net/http"
"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 int `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
ORDER BY totaltimeforeground DESC`
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:"number" db:"number"`
Receive int `json:"incoming" db:"incoming"`
Send int `json:"outgoing" db:"outgoing"`
}
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)
}
......@@ -8,5 +8,6 @@ require (
github.com/google/uuid v1.1.2
github.com/gorilla/mux v1.8.0
github.com/jmoiron/sqlx v1.2.0
github.com/mattn/go-sqlite3 v1.9.0
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
)
......
......@@ -11,6 +11,7 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
......
package main
import (
"time"
)
type Time time.Time
func (t *Time) Scan(v interface{}) error {
p, err := time.Parse("2006-01-02 15:04:05", string(v.([]byte)))
*t = Time(p)
return err
}
func (t *Time) MarshalJSON() ([]byte, error) {
return time.Time(*t).MarshalJSON()
}