mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
fix: include machine names when importing wakatime data
This commit is contained in:
parent
66b01c2797
commit
e4c413a33c
@ -39,6 +39,7 @@ const (
|
|||||||
WakatimeApiHeartbeatsUrl = "/users/current/heartbeats"
|
WakatimeApiHeartbeatsUrl = "/users/current/heartbeats"
|
||||||
WakatimeApiHeartbeatsBulkUrl = "/users/current/heartbeats.bulk"
|
WakatimeApiHeartbeatsBulkUrl = "/users/current/heartbeats.bulk"
|
||||||
WakatimeApiUserAgentsUrl = "/users/current/user_agents"
|
WakatimeApiUserAgentsUrl = "/users/current/user_agents"
|
||||||
|
WakatimeApiMachineNamesUrl = "/users/current/machine_names"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cfg *Config
|
var cfg *Config
|
||||||
|
@ -16,6 +16,15 @@ type AllTimeData struct {
|
|||||||
TotalSeconds float32 `json:"total_seconds"` // total number of seconds logged since account created
|
TotalSeconds float32 `json:"total_seconds"` // total number of seconds logged since account created
|
||||||
Text string `json:"text"` // total time logged since account created as human readable string>
|
Text string `json:"text"` // total time logged since account created as human readable string>
|
||||||
IsUpToDate bool `json:"is_up_to_date"` // true if the stats are up to date; when false, a 202 response code is returned and stats will be refreshed soon>
|
IsUpToDate bool `json:"is_up_to_date"` // true if the stats are up to date; when false, a 202 response code is returned and stats will be refreshed soon>
|
||||||
|
Range *AllTimeRange `json:"range"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AllTimeRange struct {
|
||||||
|
End string `json:"end"`
|
||||||
|
EndDate string `json:"end_date"`
|
||||||
|
Start string `json:"start"`
|
||||||
|
StartDate string `json:"start_date"`
|
||||||
|
Timezone string `json:"timezone"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAllTimeFrom(summary *models.Summary, filters *models.Filters) *AllTimeViewModel {
|
func NewAllTimeFrom(summary *models.Summary, filters *models.Filters) *AllTimeViewModel {
|
||||||
|
12
models/compat/wakatime/v1/machine.go
Normal file
12
models/compat/wakatime/v1/machine.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
// https://wakatime.com/api/v1/users/current/machine_names
|
||||||
|
|
||||||
|
type MachineViewModel struct {
|
||||||
|
Data []*MachineEntry `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MachineEntry struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/emvi/logbuch"
|
"github.com/emvi/logbuch"
|
||||||
"github.com/muety/wakapi/config"
|
"github.com/muety/wakapi/config"
|
||||||
@ -53,6 +52,12 @@ func (w *WakatimeHeartbeatImporter) Import(user *models.User, minFrom time.Time,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
machinesNames, err := w.fetchMachineNames()
|
||||||
|
if err != nil {
|
||||||
|
logbuch.Error("failed to fetch machine names while importing wakatime heartbeats for user '%s' – %v", user.ID, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
days := generateDays(startDate, endDate)
|
days := generateDays(startDate, endDate)
|
||||||
|
|
||||||
c := atomic.NewUint32(uint32(len(days)))
|
c := atomic.NewUint32(uint32(len(days)))
|
||||||
@ -75,7 +80,7 @@ func (w *WakatimeHeartbeatImporter) Import(user *models.User, minFrom time.Time,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, h := range heartbeats {
|
for _, h := range heartbeats {
|
||||||
out <- mapHeartbeat(h, userAgents, user)
|
out <- mapHeartbeat(h, userAgents, machinesNames, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Dec() == 0 {
|
if c.Dec() == 0 {
|
||||||
@ -134,27 +139,17 @@ func (w *WakatimeHeartbeatImporter) fetchRange() (time.Time, time.Time, error) {
|
|||||||
return notime, notime, err
|
return notime, notime, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var allTimeData map[string]interface{}
|
var allTimeData wakatime.AllTimeViewModel
|
||||||
if err := json.NewDecoder(res.Body).Decode(&allTimeData); err != nil {
|
if err := json.NewDecoder(res.Body).Decode(&allTimeData); err != nil {
|
||||||
return notime, notime, err
|
return notime, notime, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := allTimeData["data"].(map[string]interface{})
|
startDate, err := time.Parse("2006-01-02", allTimeData.Data.Range.StartDate)
|
||||||
if data == nil {
|
|
||||||
return notime, notime, errors.New("invalid response")
|
|
||||||
}
|
|
||||||
|
|
||||||
dataRange := data["range"].(map[string]interface{})
|
|
||||||
if dataRange == nil {
|
|
||||||
return notime, notime, errors.New("invalid response")
|
|
||||||
}
|
|
||||||
|
|
||||||
startDate, err := time.Parse("2006-01-02", dataRange["start_date"].(string))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return notime, notime, err
|
return notime, notime, err
|
||||||
}
|
}
|
||||||
|
|
||||||
endDate, err := time.Parse("2006-01-02", dataRange["end_date"].(string))
|
endDate, err := time.Parse("2006-01-02", allTimeData.Data.Range.EndDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return notime, notime, err
|
return notime, notime, err
|
||||||
}
|
}
|
||||||
@ -189,6 +184,33 @@ func (w *WakatimeHeartbeatImporter) fetchUserAgents() (map[string]*wakatime.User
|
|||||||
return userAgents, nil
|
return userAgents, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://wakatime.com/api/v1/users/current/machine_names
|
||||||
|
func (w *WakatimeHeartbeatImporter) fetchMachineNames() (map[string]*wakatime.MachineEntry, error) {
|
||||||
|
httpClient := &http.Client{Timeout: 10 * time.Second}
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, config.WakatimeApiUrl+config.WakatimeApiMachineNamesUrl, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := httpClient.Do(w.withHeaders(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var machineData wakatime.MachineViewModel
|
||||||
|
if err := json.NewDecoder(res.Body).Decode(&machineData); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
machines := make(map[string]*wakatime.MachineEntry)
|
||||||
|
for _, ma := range machineData.Data {
|
||||||
|
machines[ma.Id] = ma
|
||||||
|
}
|
||||||
|
|
||||||
|
return machines, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (w *WakatimeHeartbeatImporter) withHeaders(req *http.Request) *http.Request {
|
func (w *WakatimeHeartbeatImporter) withHeaders(req *http.Request) *http.Request {
|
||||||
req.Header.Set("Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(w.ApiKey))))
|
req.Header.Set("Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(w.ApiKey))))
|
||||||
return req
|
return req
|
||||||
@ -197,6 +219,7 @@ func (w *WakatimeHeartbeatImporter) withHeaders(req *http.Request) *http.Request
|
|||||||
func mapHeartbeat(
|
func mapHeartbeat(
|
||||||
entry *wakatime.HeartbeatEntry,
|
entry *wakatime.HeartbeatEntry,
|
||||||
userAgents map[string]*wakatime.UserAgentEntry,
|
userAgents map[string]*wakatime.UserAgentEntry,
|
||||||
|
machineNames map[string]*wakatime.MachineEntry,
|
||||||
user *models.User,
|
user *models.User,
|
||||||
) *models.Heartbeat {
|
) *models.Heartbeat {
|
||||||
ua := userAgents[entry.UserAgentId]
|
ua := userAgents[entry.UserAgentId]
|
||||||
@ -207,6 +230,14 @@ func mapHeartbeat(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ma := machineNames[entry.MachineNameId]
|
||||||
|
if ma == nil {
|
||||||
|
ma = &wakatime.MachineEntry{
|
||||||
|
Id: entry.MachineNameId,
|
||||||
|
Value: entry.MachineNameId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (&models.Heartbeat{
|
return (&models.Heartbeat{
|
||||||
User: user,
|
User: user,
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
@ -219,7 +250,7 @@ func mapHeartbeat(
|
|||||||
IsWrite: entry.IsWrite,
|
IsWrite: entry.IsWrite,
|
||||||
Editor: ua.Editor,
|
Editor: ua.Editor,
|
||||||
OperatingSystem: ua.Os,
|
OperatingSystem: ua.Os,
|
||||||
Machine: entry.MachineNameId, // TODO
|
Machine: ma.Value,
|
||||||
Time: entry.Time,
|
Time: entry.Time,
|
||||||
Origin: OriginWakatime,
|
Origin: OriginWakatime,
|
||||||
OriginId: entry.Id,
|
OriginId: entry.Id,
|
||||||
|
@ -1 +1 @@
|
|||||||
1.23.4
|
1.23.5
|
Loading…
Reference in New Issue
Block a user