diff --git a/config/config.go b/config/config.go index b912a37..4d2da45 100644 --- a/config/config.go +++ b/config/config.go @@ -51,6 +51,7 @@ const ( WakatimeApiHeartbeatsBulkUrl = "/users/current/heartbeats.bulk" WakatimeApiUserAgentsUrl = "/users/current/user_agents" WakatimeApiMachineNamesUrl = "/users/current/machine_names" + WakatimeApiDataDumpUrl = "/users/current/data_dumps" ) const ( diff --git a/coverage/coverage.out b/coverage/coverage.out index 0e1f093..02d8edd 100644 --- a/coverage/coverage.out +++ b/coverage/coverage.out @@ -1,4 +1,94 @@ mode: set +github.com/muety/wakapi/utils/auth.go:15.79,17.54 2 0 +github.com/muety/wakapi/utils/auth.go:21.2,23.16 3 0 +github.com/muety/wakapi/utils/auth.go:27.2,29.45 3 0 +github.com/muety/wakapi/utils/auth.go:32.2,33.32 2 0 +github.com/muety/wakapi/utils/auth.go:17.54,19.3 1 0 +github.com/muety/wakapi/utils/auth.go:23.16,25.3 1 0 +github.com/muety/wakapi/utils/auth.go:29.45,31.3 1 0 +github.com/muety/wakapi/utils/auth.go:36.65,38.85 2 0 +github.com/muety/wakapi/utils/auth.go:42.2,43.30 2 0 +github.com/muety/wakapi/utils/auth.go:38.85,40.3 1 0 +github.com/muety/wakapi/utils/auth.go:48.57,49.34 1 0 +github.com/muety/wakapi/utils/auth.go:52.2,52.45 1 0 +github.com/muety/wakapi/utils/auth.go:49.34,51.3 1 0 +github.com/muety/wakapi/utils/auth.go:55.57,57.2 1 0 +github.com/muety/wakapi/utils/auth.go:59.55,63.2 3 0 +github.com/muety/wakapi/utils/auth.go:65.55,68.16 3 0 +github.com/muety/wakapi/utils/auth.go:71.2,71.16 1 0 +github.com/muety/wakapi/utils/auth.go:68.16,70.3 1 0 +github.com/muety/wakapi/utils/auth.go:74.57,78.2 3 0 +github.com/muety/wakapi/utils/auth.go:80.57,83.16 3 0 +github.com/muety/wakapi/utils/auth.go:86.2,86.16 1 0 +github.com/muety/wakapi/utils/auth.go:83.16,85.3 1 0 +github.com/muety/wakapi/utils/collection.go:5.52,6.26 1 0 +github.com/muety/wakapi/utils/collection.go:9.2,9.28 1 0 +github.com/muety/wakapi/utils/collection.go:6.26,8.3 1 0 +github.com/muety/wakapi/utils/collection.go:12.78,14.22 2 0 +github.com/muety/wakapi/utils/collection.go:20.2,20.11 1 0 +github.com/muety/wakapi/utils/collection.go:14.22,15.18 1 0 +github.com/muety/wakapi/utils/collection.go:18.3,18.12 1 0 +github.com/muety/wakapi/utils/collection.go:15.18,17.4 1 0 +github.com/muety/wakapi/utils/db.go:10.34,11.37 1 0 +github.com/muety/wakapi/utils/db.go:19.2,20.14 2 0 +github.com/muety/wakapi/utils/db.go:11.37,13.110 2 0 +github.com/muety/wakapi/utils/db.go:17.3,17.20 1 0 +github.com/muety/wakapi/utils/db.go:13.110,16.4 2 0 +github.com/muety/wakapi/utils/db.go:23.39,24.37 1 0 +github.com/muety/wakapi/utils/db.go:32.2,33.14 2 0 +github.com/muety/wakapi/utils/db.go:24.37,26.119 2 0 +github.com/muety/wakapi/utils/db.go:30.3,30.20 1 0 +github.com/muety/wakapi/utils/db.go:26.119,29.4 2 0 +github.com/muety/wakapi/utils/db.go:36.66,37.48 1 0 +github.com/muety/wakapi/utils/db.go:40.2,40.53 1 0 +github.com/muety/wakapi/utils/db.go:37.48,39.3 1 0 +github.com/muety/wakapi/utils/db.go:43.59,44.16 1 0 +github.com/muety/wakapi/utils/db.go:47.2,47.15 1 0 +github.com/muety/wakapi/utils/db.go:50.2,50.14 1 0 +github.com/muety/wakapi/utils/db.go:44.16,46.3 1 0 +github.com/muety/wakapi/utils/db.go:47.15,49.3 1 0 +github.com/muety/wakapi/utils/dns.go:9.38,11.21 2 0 +github.com/muety/wakapi/utils/dns.go:14.2,15.39 2 0 +github.com/muety/wakapi/utils/dns.go:11.21,13.3 1 0 +github.com/muety/wakapi/utils/strings.go:7.58,8.49 1 0 +github.com/muety/wakapi/utils/strings.go:8.49,9.32 1 0 +github.com/muety/wakapi/utils/strings.go:14.3,14.15 1 0 +github.com/muety/wakapi/utils/strings.go:9.32,10.22 1 0 +github.com/muety/wakapi/utils/strings.go:10.22,12.5 1 0 +github.com/muety/wakapi/utils/strings.go:18.77,19.29 1 0 +github.com/muety/wakapi/utils/strings.go:24.2,24.19 1 0 +github.com/muety/wakapi/utils/strings.go:19.29,20.18 1 0 +github.com/muety/wakapi/utils/strings.go:20.18,22.4 1 0 +github.com/muety/wakapi/utils/sync.go:11.66,13.12 2 0 +github.com/muety/wakapi/utils/sync.go:17.2,17.9 1 0 +github.com/muety/wakapi/utils/sync.go:13.12,16.3 2 0 +github.com/muety/wakapi/utils/sync.go:18.11,19.15 1 0 +github.com/muety/wakapi/utils/sync.go:20.29,21.14 1 0 +github.com/muety/wakapi/utils/cron.go:5.44,7.21 2 0 +github.com/muety/wakapi/utils/cron.go:10.2,10.20 1 0 +github.com/muety/wakapi/utils/cron.go:7.21,9.3 1 0 +github.com/muety/wakapi/utils/date.go:9.48,11.2 1 0 +github.com/muety/wakapi/utils/date.go:13.51,15.2 1 0 +github.com/muety/wakapi/utils/date.go:17.52,19.2 1 0 +github.com/muety/wakapi/utils/date.go:21.51,23.2 1 0 +github.com/muety/wakapi/utils/date.go:26.41,28.21 2 0 +github.com/muety/wakapi/utils/date.go:31.2,31.33 1 0 +github.com/muety/wakapi/utils/date.go:28.21,30.3 1 0 +github.com/muety/wakapi/utils/date.go:35.67,38.33 2 1 +github.com/muety/wakapi/utils/date.go:47.2,47.18 1 1 +github.com/muety/wakapi/utils/date.go:38.33,40.19 2 1 +github.com/muety/wakapi/utils/date.go:43.3,44.10 2 1 +github.com/muety/wakapi/utils/date.go:40.19,42.4 1 1 +github.com/muety/wakapi/utils/date.go:51.36,54.2 2 0 +github.com/muety/wakapi/utils/date.go:56.42,57.28 1 0 +github.com/muety/wakapi/utils/date.go:73.2,73.20 1 0 +github.com/muety/wakapi/utils/date.go:58.52,59.21 1 0 +github.com/muety/wakapi/utils/date.go:60.53,61.22 1 0 +github.com/muety/wakapi/utils/date.go:62.55,63.24 1 0 +github.com/muety/wakapi/utils/date.go:64.54,65.23 1 0 +github.com/muety/wakapi/utils/date.go:66.52,67.21 1 0 +github.com/muety/wakapi/utils/date.go:68.54,69.23 1 0 +github.com/muety/wakapi/utils/date.go:70.52,71.21 1 0 github.com/muety/wakapi/utils/http.go:20.13,22.2 1 1 github.com/muety/wakapi/utils/http.go:29.34,30.20 1 0 github.com/muety/wakapi/utils/http.go:33.2,33.19 1 0 @@ -25,97 +115,6 @@ github.com/muety/wakapi/utils/http.go:74.30,76.3 1 0 github.com/muety/wakapi/utils/http.go:80.56,83.45 3 1 github.com/muety/wakapi/utils/http.go:86.2,86.40 1 1 github.com/muety/wakapi/utils/http.go:83.45,85.3 1 1 -github.com/muety/wakapi/utils/strings.go:8.34,10.2 1 0 -github.com/muety/wakapi/utils/strings.go:12.58,13.49 1 0 -github.com/muety/wakapi/utils/strings.go:13.49,14.32 1 0 -github.com/muety/wakapi/utils/strings.go:19.3,19.15 1 0 -github.com/muety/wakapi/utils/strings.go:14.32,15.22 1 0 -github.com/muety/wakapi/utils/strings.go:15.22,17.5 1 0 -github.com/muety/wakapi/utils/strings.go:23.77,24.29 1 0 -github.com/muety/wakapi/utils/strings.go:29.2,29.19 1 0 -github.com/muety/wakapi/utils/strings.go:24.29,25.18 1 0 -github.com/muety/wakapi/utils/strings.go:25.18,27.4 1 0 -github.com/muety/wakapi/utils/sync.go:11.66,13.12 2 0 -github.com/muety/wakapi/utils/sync.go:17.2,17.9 1 0 -github.com/muety/wakapi/utils/sync.go:13.12,16.3 2 0 -github.com/muety/wakapi/utils/sync.go:18.11,19.15 1 0 -github.com/muety/wakapi/utils/sync.go:20.29,21.14 1 0 -github.com/muety/wakapi/utils/collection.go:5.52,6.26 1 0 -github.com/muety/wakapi/utils/collection.go:9.2,9.28 1 0 -github.com/muety/wakapi/utils/collection.go:6.26,8.3 1 0 -github.com/muety/wakapi/utils/collection.go:12.78,14.22 2 0 -github.com/muety/wakapi/utils/collection.go:20.2,20.11 1 0 -github.com/muety/wakapi/utils/collection.go:14.22,15.18 1 0 -github.com/muety/wakapi/utils/collection.go:18.3,18.12 1 0 -github.com/muety/wakapi/utils/collection.go:15.18,17.4 1 0 -github.com/muety/wakapi/utils/date.go:9.48,11.2 1 0 -github.com/muety/wakapi/utils/date.go:13.51,15.2 1 0 -github.com/muety/wakapi/utils/date.go:17.52,19.2 1 0 -github.com/muety/wakapi/utils/date.go:21.51,23.2 1 0 -github.com/muety/wakapi/utils/date.go:26.41,28.21 2 0 -github.com/muety/wakapi/utils/date.go:31.2,31.33 1 0 -github.com/muety/wakapi/utils/date.go:28.21,30.3 1 0 -github.com/muety/wakapi/utils/date.go:35.67,38.33 2 1 -github.com/muety/wakapi/utils/date.go:47.2,47.18 1 1 -github.com/muety/wakapi/utils/date.go:38.33,40.19 2 1 -github.com/muety/wakapi/utils/date.go:43.3,44.10 2 1 -github.com/muety/wakapi/utils/date.go:40.19,42.4 1 1 -github.com/muety/wakapi/utils/date.go:51.36,54.2 2 0 -github.com/muety/wakapi/utils/date.go:56.42,57.28 1 0 -github.com/muety/wakapi/utils/date.go:73.2,73.20 1 0 -github.com/muety/wakapi/utils/date.go:58.52,59.21 1 0 -github.com/muety/wakapi/utils/date.go:60.53,61.22 1 0 -github.com/muety/wakapi/utils/date.go:62.55,63.24 1 0 -github.com/muety/wakapi/utils/date.go:64.54,65.23 1 0 -github.com/muety/wakapi/utils/date.go:66.52,67.21 1 0 -github.com/muety/wakapi/utils/date.go:68.54,69.23 1 0 -github.com/muety/wakapi/utils/date.go:70.52,71.21 1 0 -github.com/muety/wakapi/utils/db.go:10.34,11.37 1 0 -github.com/muety/wakapi/utils/db.go:19.2,20.14 2 0 -github.com/muety/wakapi/utils/db.go:11.37,13.110 2 0 -github.com/muety/wakapi/utils/db.go:17.3,17.20 1 0 -github.com/muety/wakapi/utils/db.go:13.110,16.4 2 0 -github.com/muety/wakapi/utils/db.go:23.39,24.37 1 0 -github.com/muety/wakapi/utils/db.go:32.2,33.14 2 0 -github.com/muety/wakapi/utils/db.go:24.37,26.119 2 0 -github.com/muety/wakapi/utils/db.go:30.3,30.20 1 0 -github.com/muety/wakapi/utils/db.go:26.119,29.4 2 0 -github.com/muety/wakapi/utils/db.go:36.66,37.48 1 0 -github.com/muety/wakapi/utils/db.go:40.2,40.53 1 0 -github.com/muety/wakapi/utils/db.go:37.48,39.3 1 0 -github.com/muety/wakapi/utils/db.go:43.59,44.16 1 0 -github.com/muety/wakapi/utils/db.go:47.2,47.15 1 0 -github.com/muety/wakapi/utils/db.go:50.2,50.14 1 0 -github.com/muety/wakapi/utils/db.go:44.16,46.3 1 0 -github.com/muety/wakapi/utils/db.go:47.15,49.3 1 0 -github.com/muety/wakapi/utils/dns.go:9.38,11.21 2 0 -github.com/muety/wakapi/utils/dns.go:14.2,15.39 2 0 -github.com/muety/wakapi/utils/dns.go:11.21,13.3 1 0 -github.com/muety/wakapi/utils/auth.go:15.79,17.54 2 0 -github.com/muety/wakapi/utils/auth.go:21.2,23.16 3 0 -github.com/muety/wakapi/utils/auth.go:27.2,29.45 3 0 -github.com/muety/wakapi/utils/auth.go:32.2,33.32 2 0 -github.com/muety/wakapi/utils/auth.go:17.54,19.3 1 0 -github.com/muety/wakapi/utils/auth.go:23.16,25.3 1 0 -github.com/muety/wakapi/utils/auth.go:29.45,31.3 1 0 -github.com/muety/wakapi/utils/auth.go:36.65,38.85 2 0 -github.com/muety/wakapi/utils/auth.go:42.2,43.30 2 0 -github.com/muety/wakapi/utils/auth.go:38.85,40.3 1 0 -github.com/muety/wakapi/utils/auth.go:48.57,49.34 1 0 -github.com/muety/wakapi/utils/auth.go:52.2,52.45 1 0 -github.com/muety/wakapi/utils/auth.go:49.34,51.3 1 0 -github.com/muety/wakapi/utils/auth.go:55.57,57.2 1 0 -github.com/muety/wakapi/utils/auth.go:59.55,63.2 3 0 -github.com/muety/wakapi/utils/auth.go:65.55,68.16 3 0 -github.com/muety/wakapi/utils/auth.go:71.2,71.16 1 0 -github.com/muety/wakapi/utils/auth.go:68.16,70.3 1 0 -github.com/muety/wakapi/utils/auth.go:74.57,78.2 3 0 -github.com/muety/wakapi/utils/auth.go:80.57,83.16 3 0 -github.com/muety/wakapi/utils/auth.go:86.2,86.16 1 0 -github.com/muety/wakapi/utils/auth.go:83.16,85.3 1 0 -github.com/muety/wakapi/utils/cron.go:5.44,7.21 2 0 -github.com/muety/wakapi/utils/cron.go:10.2,10.20 1 0 -github.com/muety/wakapi/utils/cron.go:7.21,9.3 1 0 github.com/muety/wakapi/utils/json.go:12.75,18.62 2 0 github.com/muety/wakapi/utils/json.go:22.2,22.29 1 0 github.com/muety/wakapi/utils/json.go:26.2,26.72 1 0 @@ -144,8 +143,141 @@ github.com/muety/wakapi/utils/template.go:39.51,40.12 1 0 github.com/muety/wakapi/utils/template.go:44.17,46.4 1 0 github.com/muety/wakapi/utils/template.go:48.17,50.4 1 0 github.com/muety/wakapi/utils/template.go:55.17,57.4 1 0 -github.com/muety/wakapi/config/eventbus.go:27.13,29.2 1 1 -github.com/muety/wakapi/config/eventbus.go:31.26,33.2 1 0 +github.com/muety/wakapi/config/config.go:184.64,186.2 1 0 +github.com/muety/wakapi/config/config.go:188.59,190.2 1 0 +github.com/muety/wakapi/config/config.go:192.82,202.2 1 0 +github.com/muety/wakapi/config/config.go:204.31,206.2 1 0 +github.com/muety/wakapi/config/config.go:208.32,210.2 1 0 +github.com/muety/wakapi/config/config.go:212.60,214.2 1 0 +github.com/muety/wakapi/config/config.go:216.59,218.2 1 0 +github.com/muety/wakapi/config/config.go:220.57,222.2 1 0 +github.com/muety/wakapi/config/config.go:224.53,226.2 1 0 +github.com/muety/wakapi/config/config.go:228.53,229.46 1 0 +github.com/muety/wakapi/config/config.go:245.2,245.51 1 0 +github.com/muety/wakapi/config/config.go:229.46,233.17 3 0 +github.com/muety/wakapi/config/config.go:237.3,238.17 2 0 +github.com/muety/wakapi/config/config.go:242.3,242.44 1 0 +github.com/muety/wakapi/config/config.go:233.17,235.4 1 0 +github.com/muety/wakapi/config/config.go:238.17,240.4 1 0 +github.com/muety/wakapi/config/config.go:248.50,249.47 1 0 +github.com/muety/wakapi/config/config.go:268.2,268.52 1 0 +github.com/muety/wakapi/config/config.go:249.47,256.17 5 0 +github.com/muety/wakapi/config/config.go:260.3,261.17 2 0 +github.com/muety/wakapi/config/config.go:265.3,265.54 1 0 +github.com/muety/wakapi/config/config.go:256.17,258.4 1 0 +github.com/muety/wakapi/config/config.go:261.17,263.4 1 0 +github.com/muety/wakapi/config/config.go:271.65,276.56 3 0 +github.com/muety/wakapi/config/config.go:298.2,298.76 1 0 +github.com/muety/wakapi/config/config.go:302.2,302.14 1 0 +github.com/muety/wakapi/config/config.go:276.56,278.33 1 0 +github.com/muety/wakapi/config/config.go:278.33,281.18 3 0 +github.com/muety/wakapi/config/config.go:285.4,286.18 2 0 +github.com/muety/wakapi/config/config.go:290.4,290.45 1 0 +github.com/muety/wakapi/config/config.go:281.18,283.5 1 0 +github.com/muety/wakapi/config/config.go:286.18,288.5 1 0 +github.com/muety/wakapi/config/config.go:292.8,293.33 1 0 +github.com/muety/wakapi/config/config.go:293.33,295.4 1 0 +github.com/muety/wakapi/config/config.go:298.76,300.3 1 0 +github.com/muety/wakapi/config/config.go:305.54,308.2 2 0 +github.com/muety/wakapi/config/config.go:310.36,312.2 1 0 +github.com/muety/wakapi/config/config.go:314.35,316.2 1 0 +github.com/muety/wakapi/config/config.go:318.38,320.2 1 0 +github.com/muety/wakapi/config/config.go:322.46,324.2 1 0 +github.com/muety/wakapi/config/config.go:326.43,328.2 1 0 +github.com/muety/wakapi/config/config.go:330.29,332.2 1 1 +github.com/muety/wakapi/config/config.go:334.48,345.16 2 0 +github.com/muety/wakapi/config/config.go:349.2,350.53 2 0 +github.com/muety/wakapi/config/config.go:354.2,354.15 1 0 +github.com/muety/wakapi/config/config.go:345.16,347.3 1 0 +github.com/muety/wakapi/config/config.go:350.53,352.3 1 0 +github.com/muety/wakapi/config/config.go:357.45,358.27 1 0 +github.com/muety/wakapi/config/config.go:361.2,361.24 1 0 +github.com/muety/wakapi/config/config.go:364.2,364.25 1 0 +github.com/muety/wakapi/config/config.go:367.2,367.15 1 0 +github.com/muety/wakapi/config/config.go:358.27,360.3 1 0 +github.com/muety/wakapi/config/config.go:361.24,363.3 1 0 +github.com/muety/wakapi/config/config.go:364.25,366.3 1 0 +github.com/muety/wakapi/config/config.go:370.26,372.2 1 0 +github.com/muety/wakapi/config/config.go:374.20,376.2 1 0 +github.com/muety/wakapi/config/config.go:378.54,381.82 2 0 +github.com/muety/wakapi/config/config.go:385.2,389.21 4 0 +github.com/muety/wakapi/config/config.go:393.2,401.16 7 0 +github.com/muety/wakapi/config/config.go:407.2,412.47 4 0 +github.com/muety/wakapi/config/config.go:418.2,418.29 1 0 +github.com/muety/wakapi/config/config.go:423.2,423.41 1 0 +github.com/muety/wakapi/config/config.go:434.2,434.108 1 0 +github.com/muety/wakapi/config/config.go:437.2,437.28 1 0 +github.com/muety/wakapi/config/config.go:440.2,440.51 1 0 +github.com/muety/wakapi/config/config.go:444.2,444.100 1 0 +github.com/muety/wakapi/config/config.go:447.2,447.74 1 0 +github.com/muety/wakapi/config/config.go:451.2,453.78 2 0 +github.com/muety/wakapi/config/config.go:456.2,456.81 1 0 +github.com/muety/wakapi/config/config.go:459.2,459.66 1 0 +github.com/muety/wakapi/config/config.go:466.2,466.55 1 0 +github.com/muety/wakapi/config/config.go:469.2,469.56 1 0 +github.com/muety/wakapi/config/config.go:472.2,472.65 1 0 +github.com/muety/wakapi/config/config.go:476.2,477.14 2 0 +github.com/muety/wakapi/config/config.go:381.82,383.3 1 0 +github.com/muety/wakapi/config/config.go:389.21,391.3 1 0 +github.com/muety/wakapi/config/config.go:401.16,405.3 3 0 +github.com/muety/wakapi/config/config.go:412.47,413.14 1 0 +github.com/muety/wakapi/config/config.go:413.14,415.4 1 0 +github.com/muety/wakapi/config/config.go:418.29,421.3 2 0 +github.com/muety/wakapi/config/config.go:423.41,425.3 1 0 +github.com/muety/wakapi/config/config.go:425.8,427.35 2 0 +github.com/muety/wakapi/config/config.go:430.3,430.37 1 0 +github.com/muety/wakapi/config/config.go:427.35,429.4 1 0 +github.com/muety/wakapi/config/config.go:434.108,436.3 1 0 +github.com/muety/wakapi/config/config.go:437.28,439.3 1 0 +github.com/muety/wakapi/config/config.go:440.51,443.3 2 0 +github.com/muety/wakapi/config/config.go:444.100,446.3 1 0 +github.com/muety/wakapi/config/config.go:447.74,449.3 1 0 +github.com/muety/wakapi/config/config.go:453.78,455.3 1 0 +github.com/muety/wakapi/config/config.go:456.81,458.3 1 0 +github.com/muety/wakapi/config/config.go:459.66,460.48 1 0 +github.com/muety/wakapi/config/config.go:460.48,462.4 1 0 +github.com/muety/wakapi/config/config.go:466.55,468.3 1 0 +github.com/muety/wakapi/config/config.go:469.56,471.3 1 0 +github.com/muety/wakapi/config/config.go:472.65,474.3 1 0 +github.com/muety/wakapi/config/db.go:40.50,41.19 1 0 +github.com/muety/wakapi/config/db.go:54.2,54.12 1 0 +github.com/muety/wakapi/config/db.go:42.23,46.5 1 0 +github.com/muety/wakapi/config/db.go:47.26,50.5 1 0 +github.com/muety/wakapi/config/db.go:51.24,52.48 1 0 +github.com/muety/wakapi/config/db.go:57.53,60.25 2 1 +github.com/muety/wakapi/config/db.go:64.2,71.3 1 1 +github.com/muety/wakapi/config/db.go:60.25,62.3 1 1 +github.com/muety/wakapi/config/db.go:74.56,75.25 1 1 +github.com/muety/wakapi/config/db.go:79.2,80.16 2 1 +github.com/muety/wakapi/config/db.go:84.2,91.3 1 1 +github.com/muety/wakapi/config/db.go:75.25,77.3 1 0 +github.com/muety/wakapi/config/db.go:80.16,82.3 1 0 +github.com/muety/wakapi/config/db.go:94.54,96.2 1 1 +github.com/muety/wakapi/config/db_opts.go:11.56,13.2 1 0 +github.com/muety/wakapi/config/db_opts.go:15.59,17.2 1 0 +github.com/muety/wakapi/config/db_opts.go:19.61,21.39 1 0 +github.com/muety/wakapi/config/db_opts.go:28.2,28.30 1 0 +github.com/muety/wakapi/config/db_opts.go:34.2,34.12 1 0 +github.com/muety/wakapi/config/db_opts.go:21.39,23.100 1 0 +github.com/muety/wakapi/config/db_opts.go:23.100,25.4 1 0 +github.com/muety/wakapi/config/db_opts.go:28.30,29.68 1 0 +github.com/muety/wakapi/config/db_opts.go:29.68,31.4 1 0 +github.com/muety/wakapi/config/jobqueue.go:30.13,32.2 1 1 +github.com/muety/wakapi/config/jobqueue.go:34.18,41.2 6 0 +github.com/muety/wakapi/config/jobqueue.go:43.48,44.34 1 0 +github.com/muety/wakapi/config/jobqueue.go:47.2,50.12 4 0 +github.com/muety/wakapi/config/jobqueue.go:44.34,46.3 1 0 +github.com/muety/wakapi/config/jobqueue.go:53.44,55.2 1 0 +github.com/muety/wakapi/config/jobqueue.go:57.48,58.35 1 0 +github.com/muety/wakapi/config/jobqueue.go:61.2,61.24 1 0 +github.com/muety/wakapi/config/jobqueue.go:58.35,60.3 1 0 +github.com/muety/wakapi/config/jobqueue.go:64.43,66.37 2 0 +github.com/muety/wakapi/config/jobqueue.go:73.2,73.16 1 0 +github.com/muety/wakapi/config/jobqueue.go:66.37,72.3 1 0 +github.com/muety/wakapi/config/jobqueue.go:76.20,77.30 1 0 +github.com/muety/wakapi/config/jobqueue.go:77.30,79.3 1 0 +github.com/muety/wakapi/config/jobqueue.go:82.20,84.2 1 0 +github.com/muety/wakapi/config/jobqueue.go:86.21,88.2 1 0 github.com/muety/wakapi/config/key_utils.go:11.58,15.44 2 0 github.com/muety/wakapi/config/key_utils.go:30.2,31.16 2 0 github.com/muety/wakapi/config/key_utils.go:34.2,37.51 3 0 @@ -157,6 +289,11 @@ github.com/muety/wakapi/config/key_utils.go:17.17,19.4 1 0 github.com/muety/wakapi/config/key_utils.go:23.17,25.4 1 0 github.com/muety/wakapi/config/key_utils.go:31.16,33.3 1 0 github.com/muety/wakapi/config/key_utils.go:37.51,39.3 1 0 +github.com/muety/wakapi/config/eventbus.go:27.13,29.2 1 1 +github.com/muety/wakapi/config/eventbus.go:31.26,33.2 1 0 +github.com/muety/wakapi/config/fs.go:9.56,10.19 1 0 +github.com/muety/wakapi/config/fs.go:13.2,13.19 1 0 +github.com/muety/wakapi/config/fs.go:10.19,12.3 1 0 github.com/muety/wakapi/config/sentry.go:21.35,23.2 1 0 github.com/muety/wakapi/config/sentry.go:25.62,28.2 2 0 github.com/muety/wakapi/config/sentry.go:38.33,45.2 2 0 @@ -191,144 +328,6 @@ github.com/muety/wakapi/config/sentry.go:148.51,150.3 1 0 github.com/muety/wakapi/config/session.go:9.46,10.25 1 0 github.com/muety/wakapi/config/session.go:13.2,13.21 1 0 github.com/muety/wakapi/config/session.go:10.25,12.3 1 0 -github.com/muety/wakapi/config/jobqueue.go:30.13,32.2 1 1 -github.com/muety/wakapi/config/jobqueue.go:34.18,41.2 6 0 -github.com/muety/wakapi/config/jobqueue.go:43.48,44.34 1 0 -github.com/muety/wakapi/config/jobqueue.go:47.2,50.12 4 0 -github.com/muety/wakapi/config/jobqueue.go:44.34,46.3 1 0 -github.com/muety/wakapi/config/jobqueue.go:53.44,55.2 1 0 -github.com/muety/wakapi/config/jobqueue.go:57.48,58.35 1 0 -github.com/muety/wakapi/config/jobqueue.go:61.2,61.24 1 0 -github.com/muety/wakapi/config/jobqueue.go:58.35,60.3 1 0 -github.com/muety/wakapi/config/jobqueue.go:64.43,66.37 2 0 -github.com/muety/wakapi/config/jobqueue.go:73.2,73.16 1 0 -github.com/muety/wakapi/config/jobqueue.go:66.37,72.3 1 0 -github.com/muety/wakapi/config/jobqueue.go:76.20,77.30 1 0 -github.com/muety/wakapi/config/jobqueue.go:77.30,79.3 1 0 -github.com/muety/wakapi/config/jobqueue.go:82.20,84.2 1 0 -github.com/muety/wakapi/config/jobqueue.go:86.21,88.2 1 0 -github.com/muety/wakapi/config/config.go:183.64,185.2 1 0 -github.com/muety/wakapi/config/config.go:187.59,189.2 1 0 -github.com/muety/wakapi/config/config.go:191.82,201.2 1 0 -github.com/muety/wakapi/config/config.go:203.31,205.2 1 0 -github.com/muety/wakapi/config/config.go:207.32,209.2 1 0 -github.com/muety/wakapi/config/config.go:211.60,213.2 1 0 -github.com/muety/wakapi/config/config.go:215.59,217.2 1 0 -github.com/muety/wakapi/config/config.go:219.57,221.2 1 0 -github.com/muety/wakapi/config/config.go:223.53,225.2 1 0 -github.com/muety/wakapi/config/config.go:227.53,228.46 1 0 -github.com/muety/wakapi/config/config.go:244.2,244.51 1 0 -github.com/muety/wakapi/config/config.go:228.46,232.17 3 0 -github.com/muety/wakapi/config/config.go:236.3,237.17 2 0 -github.com/muety/wakapi/config/config.go:241.3,241.44 1 0 -github.com/muety/wakapi/config/config.go:232.17,234.4 1 0 -github.com/muety/wakapi/config/config.go:237.17,239.4 1 0 -github.com/muety/wakapi/config/config.go:247.50,248.47 1 0 -github.com/muety/wakapi/config/config.go:267.2,267.52 1 0 -github.com/muety/wakapi/config/config.go:248.47,255.17 5 0 -github.com/muety/wakapi/config/config.go:259.3,260.17 2 0 -github.com/muety/wakapi/config/config.go:264.3,264.54 1 0 -github.com/muety/wakapi/config/config.go:255.17,257.4 1 0 -github.com/muety/wakapi/config/config.go:260.17,262.4 1 0 -github.com/muety/wakapi/config/config.go:270.65,275.56 3 0 -github.com/muety/wakapi/config/config.go:297.2,297.76 1 0 -github.com/muety/wakapi/config/config.go:301.2,301.14 1 0 -github.com/muety/wakapi/config/config.go:275.56,277.33 1 0 -github.com/muety/wakapi/config/config.go:277.33,280.18 3 0 -github.com/muety/wakapi/config/config.go:284.4,285.18 2 0 -github.com/muety/wakapi/config/config.go:289.4,289.45 1 0 -github.com/muety/wakapi/config/config.go:280.18,282.5 1 0 -github.com/muety/wakapi/config/config.go:285.18,287.5 1 0 -github.com/muety/wakapi/config/config.go:291.8,292.33 1 0 -github.com/muety/wakapi/config/config.go:292.33,294.4 1 0 -github.com/muety/wakapi/config/config.go:297.76,299.3 1 0 -github.com/muety/wakapi/config/config.go:304.54,307.2 2 0 -github.com/muety/wakapi/config/config.go:309.36,311.2 1 0 -github.com/muety/wakapi/config/config.go:313.35,315.2 1 0 -github.com/muety/wakapi/config/config.go:317.38,319.2 1 0 -github.com/muety/wakapi/config/config.go:321.46,323.2 1 0 -github.com/muety/wakapi/config/config.go:325.43,327.2 1 0 -github.com/muety/wakapi/config/config.go:329.29,331.2 1 1 -github.com/muety/wakapi/config/config.go:333.48,344.16 2 0 -github.com/muety/wakapi/config/config.go:348.2,349.53 2 0 -github.com/muety/wakapi/config/config.go:353.2,353.15 1 0 -github.com/muety/wakapi/config/config.go:344.16,346.3 1 0 -github.com/muety/wakapi/config/config.go:349.53,351.3 1 0 -github.com/muety/wakapi/config/config.go:356.45,357.27 1 0 -github.com/muety/wakapi/config/config.go:360.2,360.24 1 0 -github.com/muety/wakapi/config/config.go:363.2,363.25 1 0 -github.com/muety/wakapi/config/config.go:366.2,366.15 1 0 -github.com/muety/wakapi/config/config.go:357.27,359.3 1 0 -github.com/muety/wakapi/config/config.go:360.24,362.3 1 0 -github.com/muety/wakapi/config/config.go:363.25,365.3 1 0 -github.com/muety/wakapi/config/config.go:369.26,371.2 1 0 -github.com/muety/wakapi/config/config.go:373.20,375.2 1 0 -github.com/muety/wakapi/config/config.go:377.54,380.82 2 0 -github.com/muety/wakapi/config/config.go:384.2,388.21 4 0 -github.com/muety/wakapi/config/config.go:392.2,400.16 7 0 -github.com/muety/wakapi/config/config.go:406.2,411.47 4 0 -github.com/muety/wakapi/config/config.go:417.2,417.29 1 0 -github.com/muety/wakapi/config/config.go:422.2,422.41 1 0 -github.com/muety/wakapi/config/config.go:433.2,433.108 1 0 -github.com/muety/wakapi/config/config.go:436.2,436.28 1 0 -github.com/muety/wakapi/config/config.go:439.2,439.51 1 0 -github.com/muety/wakapi/config/config.go:443.2,443.100 1 0 -github.com/muety/wakapi/config/config.go:446.2,446.74 1 0 -github.com/muety/wakapi/config/config.go:450.2,452.78 2 0 -github.com/muety/wakapi/config/config.go:455.2,455.81 1 0 -github.com/muety/wakapi/config/config.go:458.2,458.66 1 0 -github.com/muety/wakapi/config/config.go:465.2,465.55 1 0 -github.com/muety/wakapi/config/config.go:468.2,468.56 1 0 -github.com/muety/wakapi/config/config.go:471.2,471.65 1 0 -github.com/muety/wakapi/config/config.go:475.2,476.14 2 0 -github.com/muety/wakapi/config/config.go:380.82,382.3 1 0 -github.com/muety/wakapi/config/config.go:388.21,390.3 1 0 -github.com/muety/wakapi/config/config.go:400.16,404.3 3 0 -github.com/muety/wakapi/config/config.go:411.47,412.14 1 0 -github.com/muety/wakapi/config/config.go:412.14,414.4 1 0 -github.com/muety/wakapi/config/config.go:417.29,420.3 2 0 -github.com/muety/wakapi/config/config.go:422.41,424.3 1 0 -github.com/muety/wakapi/config/config.go:424.8,426.35 2 0 -github.com/muety/wakapi/config/config.go:429.3,429.37 1 0 -github.com/muety/wakapi/config/config.go:426.35,428.4 1 0 -github.com/muety/wakapi/config/config.go:433.108,435.3 1 0 -github.com/muety/wakapi/config/config.go:436.28,438.3 1 0 -github.com/muety/wakapi/config/config.go:439.51,442.3 2 0 -github.com/muety/wakapi/config/config.go:443.100,445.3 1 0 -github.com/muety/wakapi/config/config.go:446.74,448.3 1 0 -github.com/muety/wakapi/config/config.go:452.78,454.3 1 0 -github.com/muety/wakapi/config/config.go:455.81,457.3 1 0 -github.com/muety/wakapi/config/config.go:458.66,459.48 1 0 -github.com/muety/wakapi/config/config.go:459.48,461.4 1 0 -github.com/muety/wakapi/config/config.go:465.55,467.3 1 0 -github.com/muety/wakapi/config/config.go:468.56,470.3 1 0 -github.com/muety/wakapi/config/config.go:471.65,473.3 1 0 -github.com/muety/wakapi/config/db.go:40.50,41.19 1 0 -github.com/muety/wakapi/config/db.go:54.2,54.12 1 0 -github.com/muety/wakapi/config/db.go:42.23,46.5 1 0 -github.com/muety/wakapi/config/db.go:47.26,50.5 1 0 -github.com/muety/wakapi/config/db.go:51.24,52.48 1 0 -github.com/muety/wakapi/config/db.go:57.53,60.25 2 1 -github.com/muety/wakapi/config/db.go:64.2,71.3 1 1 -github.com/muety/wakapi/config/db.go:60.25,62.3 1 1 -github.com/muety/wakapi/config/db.go:74.56,75.25 1 1 -github.com/muety/wakapi/config/db.go:79.2,80.16 2 1 -github.com/muety/wakapi/config/db.go:84.2,91.3 1 1 -github.com/muety/wakapi/config/db.go:75.25,77.3 1 0 -github.com/muety/wakapi/config/db.go:80.16,82.3 1 0 -github.com/muety/wakapi/config/db.go:94.54,96.2 1 1 -github.com/muety/wakapi/config/db_opts.go:11.56,13.2 1 0 -github.com/muety/wakapi/config/db_opts.go:15.59,17.2 1 0 -github.com/muety/wakapi/config/db_opts.go:19.61,21.39 1 0 -github.com/muety/wakapi/config/db_opts.go:28.2,28.30 1 0 -github.com/muety/wakapi/config/db_opts.go:34.2,34.12 1 0 -github.com/muety/wakapi/config/db_opts.go:21.39,23.100 1 0 -github.com/muety/wakapi/config/db_opts.go:23.100,25.4 1 0 -github.com/muety/wakapi/config/db_opts.go:28.30,29.68 1 0 -github.com/muety/wakapi/config/db_opts.go:29.68,31.4 1 0 -github.com/muety/wakapi/config/fs.go:9.56,10.19 1 0 -github.com/muety/wakapi/config/fs.go:13.2,13.19 1 0 -github.com/muety/wakapi/config/fs.go:10.19,12.3 1 0 github.com/muety/wakapi/middlewares/logging.go:20.102,21.43 1 0 github.com/muety/wakapi/middlewares/logging.go:21.43,27.3 1 0 github.com/muety/wakapi/middlewares/logging.go:30.80,39.44 7 0 @@ -425,31 +424,6 @@ github.com/muety/wakapi/middlewares/filetype.go:22.84,24.34 2 0 github.com/muety/wakapi/middlewares/filetype.go:31.2,31.27 1 0 github.com/muety/wakapi/middlewares/filetype.go:24.34,25.50 1 0 github.com/muety/wakapi/middlewares/filetype.go:25.50,29.4 3 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:12.98,14.16 2 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:17.2,17.51 1 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:14.16,16.3 1 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:20.119,22.22 2 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:26.2,34.16 2 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:38.2,41.36 3 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:22.22,24.3 1 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:34.16,36.3 1 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:44.90,46.32 2 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:51.2,51.15 1 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:46.32,47.50 1 0 -github.com/muety/wakapi/routes/utils/summary_utils.go:47.50,49.4 1 0 -github.com/muety/wakapi/routes/utils/user_utils.go:15.139,16.68 1 1 -github.com/muety/wakapi/routes/utils/user_utils.go:23.2,24.21 2 1 -github.com/muety/wakapi/routes/utils/user_utils.go:28.2,29.27 2 1 -github.com/muety/wakapi/routes/utils/user_utils.go:35.2,35.63 1 1 -github.com/muety/wakapi/routes/utils/user_utils.go:39.2,40.16 2 1 -github.com/muety/wakapi/routes/utils/user_utils.go:44.2,44.27 1 1 -github.com/muety/wakapi/routes/utils/user_utils.go:16.68,21.3 4 1 -github.com/muety/wakapi/routes/utils/user_utils.go:24.21,26.3 1 1 -github.com/muety/wakapi/routes/utils/user_utils.go:29.27,31.3 1 1 -github.com/muety/wakapi/routes/utils/user_utils.go:31.8,31.35 1 1 -github.com/muety/wakapi/routes/utils/user_utils.go:31.35,33.3 1 1 -github.com/muety/wakapi/routes/utils/user_utils.go:35.63,37.3 1 1 -github.com/muety/wakapi/routes/utils/user_utils.go:40.16,42.3 1 0 github.com/muety/wakapi/routes/utils/badge_utils.go:21.13,24.2 2 1 github.com/muety/wakapi/routes/utils/badge_utils.go:26.114,28.79 2 0 github.com/muety/wakapi/routes/utils/badge_utils.go:32.2,33.75 2 0 @@ -495,6 +469,65 @@ github.com/muety/wakapi/routes/utils/project_utils.go:37.2,39.20 3 0 github.com/muety/wakapi/routes/utils/project_utils.go:18.16,20.3 1 0 github.com/muety/wakapi/routes/utils/project_utils.go:24.16,26.3 1 0 github.com/muety/wakapi/routes/utils/project_utils.go:32.35,35.3 2 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:12.98,14.16 2 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:17.2,17.51 1 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:14.16,16.3 1 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:20.119,22.22 2 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:26.2,34.16 2 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:38.2,41.36 3 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:22.22,24.3 1 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:34.16,36.3 1 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:44.90,46.32 2 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:51.2,51.15 1 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:46.32,47.50 1 0 +github.com/muety/wakapi/routes/utils/summary_utils.go:47.50,49.4 1 0 +github.com/muety/wakapi/routes/utils/user_utils.go:15.139,16.68 1 1 +github.com/muety/wakapi/routes/utils/user_utils.go:23.2,24.21 2 1 +github.com/muety/wakapi/routes/utils/user_utils.go:28.2,29.27 2 1 +github.com/muety/wakapi/routes/utils/user_utils.go:35.2,35.63 1 1 +github.com/muety/wakapi/routes/utils/user_utils.go:39.2,40.16 2 1 +github.com/muety/wakapi/routes/utils/user_utils.go:44.2,44.27 1 1 +github.com/muety/wakapi/routes/utils/user_utils.go:16.68,21.3 4 1 +github.com/muety/wakapi/routes/utils/user_utils.go:24.21,26.3 1 1 +github.com/muety/wakapi/routes/utils/user_utils.go:29.27,31.3 1 1 +github.com/muety/wakapi/routes/utils/user_utils.go:31.8,31.35 1 1 +github.com/muety/wakapi/routes/utils/user_utils.go:31.35,33.3 1 1 +github.com/muety/wakapi/routes/utils/user_utils.go:35.63,37.3 1 1 +github.com/muety/wakapi/routes/utils/user_utils.go:40.16,42.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:23.116,29.2 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:31.60,32.34 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:32.34,35.3 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:47.70,49.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:53.2,54.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:60.2,61.46 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:49.16,51.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:54.16,58.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:64.116,73.29 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:77.2,85.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:89.2,89.36 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:73.29,75.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:85.16,87.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:29.124,34.2 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:36.62,37.34 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:37.34,40.3 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:52.72,54.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:58.2,61.16 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:67.2,71.16 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:78.2,84.47 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:54.16,56.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:61.16,65.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:71.16,76.3 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:23.123,29.2 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:31.61,32.34 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:32.34,35.3 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:48.71,50.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:54.2,55.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:62.2,65.28 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:71.2,72.46 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:50.16,52.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:55.16,60.3 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:65.28,66.30 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:66.30,68.4 1 0 github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:22.112,28.2 1 0 github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:30.58,31.34 1 0 github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:31.34,41.3 5 0 @@ -576,423 +609,40 @@ github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:58.2,58.72 1 1 github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:47.16,49.3 1 1 github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:52.72,54.3 1 1 github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:54.8,56.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:23.116,29.2 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:31.60,32.34 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:32.34,35.3 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:47.70,49.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:53.2,54.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:60.2,61.46 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:49.16,51.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:54.16,58.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:64.116,73.29 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:77.2,85.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:89.2,89.36 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:73.29,75.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:85.16,87.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:29.124,34.2 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:36.62,37.34 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:37.34,40.3 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:52.72,54.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:58.2,61.16 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:67.2,71.16 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:78.2,84.47 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:54.16,56.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:61.16,65.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:71.16,76.3 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:23.123,29.2 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:31.61,32.34 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:32.34,35.3 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:48.71,50.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:54.2,55.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:62.2,65.28 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:71.2,72.46 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:50.16,52.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:55.16,60.3 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:65.28,66.30 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:66.30,68.4 1 0 -github.com/muety/wakapi/models/alias.go:18.32,20.2 1 0 -github.com/muety/wakapi/models/alias.go:22.37,23.35 1 0 -github.com/muety/wakapi/models/alias.go:28.2,28.14 1 0 -github.com/muety/wakapi/models/alias.go:23.35,24.18 1 0 -github.com/muety/wakapi/models/alias.go:24.18,26.4 1 0 -github.com/muety/wakapi/models/interval.go:41.47,42.23 1 0 -github.com/muety/wakapi/models/interval.go:47.2,47.14 1 0 -github.com/muety/wakapi/models/interval.go:42.23,43.13 1 0 -github.com/muety/wakapi/models/interval.go:43.13,45.4 1 0 -github.com/muety/wakapi/models/leaderboard.go:28.73,30.2 1 0 -github.com/muety/wakapi/models/leaderboard.go:34.56,35.103 1 0 -github.com/muety/wakapi/models/leaderboard.go:35.103,37.3 1 0 -github.com/muety/wakapi/models/leaderboard.go:37.13,39.3 1 0 -github.com/muety/wakapi/models/leaderboard.go:42.63,43.29 1 0 -github.com/muety/wakapi/models/leaderboard.go:43.29,45.3 1 0 -github.com/muety/wakapi/models/leaderboard.go:48.41,49.123 1 0 -github.com/muety/wakapi/models/leaderboard.go:49.123,51.3 1 0 -github.com/muety/wakapi/models/leaderboard.go:54.50,56.2 1 0 -github.com/muety/wakapi/models/leaderboard.go:58.65,59.95 1 0 -github.com/muety/wakapi/models/leaderboard.go:59.95,61.3 1 0 -github.com/muety/wakapi/models/leaderboard.go:64.49,72.25 3 0 -github.com/muety/wakapi/models/leaderboard.go:83.2,83.129 1 0 -github.com/muety/wakapi/models/leaderboard.go:86.2,86.67 1 0 -github.com/muety/wakapi/models/leaderboard.go:90.2,90.79 1 0 -github.com/muety/wakapi/models/leaderboard.go:72.25,73.58 1 0 -github.com/muety/wakapi/models/leaderboard.go:76.3,77.38 2 0 -github.com/muety/wakapi/models/leaderboard.go:80.3,80.40 1 0 -github.com/muety/wakapi/models/leaderboard.go:73.58,74.12 1 0 -github.com/muety/wakapi/models/leaderboard.go:77.38,79.4 1 0 -github.com/muety/wakapi/models/leaderboard.go:83.129,85.3 1 0 -github.com/muety/wakapi/models/leaderboard.go:86.67,88.3 1 0 -github.com/muety/wakapi/models/leaderboard.go:90.79,92.3 1 0 -github.com/muety/wakapi/models/leaderboard.go:95.70,96.107 1 0 -github.com/muety/wakapi/models/leaderboard.go:96.107,98.3 1 0 -github.com/muety/wakapi/models/leaderboard.go:101.45,103.25 2 0 -github.com/muety/wakapi/models/leaderboard.go:108.2,108.19 1 0 -github.com/muety/wakapi/models/leaderboard.go:103.25,104.43 1 0 -github.com/muety/wakapi/models/leaderboard.go:104.43,106.4 1 0 -github.com/muety/wakapi/models/mail_address.go:18.13,21.2 2 1 -github.com/muety/wakapi/models/mail_address.go:27.38,29.2 1 0 -github.com/muety/wakapi/models/mail_address.go:31.35,33.21 2 1 -github.com/muety/wakapi/models/mail_address.go:39.2,39.11 1 1 -github.com/muety/wakapi/models/mail_address.go:33.21,34.21 1 1 -github.com/muety/wakapi/models/mail_address.go:37.3,37.18 1 1 -github.com/muety/wakapi/models/mail_address.go:34.21,36.4 1 1 -github.com/muety/wakapi/models/mail_address.go:42.38,44.21 2 0 -github.com/muety/wakapi/models/mail_address.go:47.2,47.17 1 0 -github.com/muety/wakapi/models/mail_address.go:44.21,46.3 1 0 -github.com/muety/wakapi/models/mail_address.go:50.35,52.2 1 1 -github.com/muety/wakapi/models/mail_address.go:54.43,56.22 2 0 -github.com/muety/wakapi/models/mail_address.go:59.2,59.12 1 0 -github.com/muety/wakapi/models/mail_address.go:56.22,58.3 1 0 -github.com/muety/wakapi/models/mail_address.go:62.46,64.22 2 1 -github.com/muety/wakapi/models/mail_address.go:67.2,67.12 1 1 -github.com/muety/wakapi/models/mail_address.go:64.22,66.3 1 1 -github.com/muety/wakapi/models/mail_address.go:70.40,71.22 1 1 -github.com/muety/wakapi/models/mail_address.go:76.2,76.13 1 1 -github.com/muety/wakapi/models/mail_address.go:71.22,72.17 1 1 -github.com/muety/wakapi/models/mail_address.go:72.17,74.4 1 1 -github.com/muety/wakapi/models/user.go:13.13,15.2 1 1 -github.com/muety/wakapi/models/user.go:90.34,92.2 1 0 -github.com/muety/wakapi/models/user.go:94.36,95.22 1 1 -github.com/muety/wakapi/models/user.go:98.2,99.16 2 1 -github.com/muety/wakapi/models/user.go:102.2,102.11 1 1 -github.com/muety/wakapi/models/user.go:95.22,97.3 1 1 -github.com/muety/wakapi/models/user.go:99.16,101.3 1 0 -github.com/muety/wakapi/models/user.go:107.41,110.2 2 1 -github.com/muety/wakapi/models/user.go:112.53,115.54 3 0 -github.com/muety/wakapi/models/user.go:118.2,118.51 1 0 -github.com/muety/wakapi/models/user.go:121.2,121.20 1 0 -github.com/muety/wakapi/models/user.go:115.54,117.3 1 0 -github.com/muety/wakapi/models/user.go:118.51,120.3 1 0 -github.com/muety/wakapi/models/user.go:125.52,126.28 1 0 -github.com/muety/wakapi/models/user.go:129.2,129.17 1 0 -github.com/muety/wakapi/models/user.go:126.28,128.3 1 0 -github.com/muety/wakapi/models/user.go:133.45,135.2 1 1 -github.com/muety/wakapi/models/user.go:137.51,139.2 1 1 -github.com/muety/wakapi/models/user.go:145.65,147.32 2 0 -github.com/muety/wakapi/models/user.go:150.2,150.30 1 0 -github.com/muety/wakapi/models/user.go:153.2,154.24 2 0 -github.com/muety/wakapi/models/user.go:147.32,149.3 1 0 -github.com/muety/wakapi/models/user.go:150.30,152.3 1 0 -github.com/muety/wakapi/models/user.go:157.39,159.55 2 1 -github.com/muety/wakapi/models/user.go:163.2,163.51 1 1 -github.com/muety/wakapi/models/user.go:159.55,161.3 1 1 -github.com/muety/wakapi/models/user.go:166.43,169.2 1 0 -github.com/muety/wakapi/models/user.go:171.45,174.2 1 0 -github.com/muety/wakapi/models/user.go:176.33,181.2 1 0 -github.com/muety/wakapi/models/user.go:183.41,185.2 1 0 -github.com/muety/wakapi/models/user.go:187.45,189.2 1 0 -github.com/muety/wakapi/models/user.go:191.45,193.2 1 0 -github.com/muety/wakapi/models/user.go:196.39,198.2 1 0 -github.com/muety/wakapi/models/user.go:200.39,203.2 2 0 -github.com/muety/wakapi/models/duration.go:27.75,28.23 1 0 -github.com/muety/wakapi/models/duration.go:31.2,35.35 1 0 -github.com/muety/wakapi/models/duration.go:38.2,38.18 1 0 -github.com/muety/wakapi/models/duration.go:28.23,30.3 1 0 -github.com/muety/wakapi/models/duration.go:35.35,37.3 1 0 -github.com/muety/wakapi/models/duration.go:41.55,56.2 2 0 -github.com/muety/wakapi/models/duration.go:58.50,61.2 2 0 -github.com/muety/wakapi/models/duration.go:63.39,65.16 2 0 -github.com/muety/wakapi/models/duration.go:68.2,69.10 2 0 -github.com/muety/wakapi/models/duration.go:65.16,67.3 1 0 -github.com/muety/wakapi/models/duration.go:72.49,73.11 1 0 -github.com/muety/wakapi/models/duration.go:90.2,90.15 1 0 -github.com/muety/wakapi/models/duration.go:94.2,94.12 1 0 -github.com/muety/wakapi/models/duration.go:74.22,75.18 1 0 -github.com/muety/wakapi/models/duration.go:76.21,77.17 1 0 -github.com/muety/wakapi/models/duration.go:78.23,79.19 1 0 -github.com/muety/wakapi/models/duration.go:80.17,81.26 1 0 -github.com/muety/wakapi/models/duration.go:82.22,83.18 1 0 -github.com/muety/wakapi/models/duration.go:84.21,85.17 1 0 -github.com/muety/wakapi/models/duration.go:86.21,87.17 1 0 -github.com/muety/wakapi/models/duration.go:90.15,92.3 1 0 -github.com/muety/wakapi/models/filters.go:22.33,24.2 1 1 -github.com/muety/wakapi/models/filters.go:26.48,27.22 1 1 -github.com/muety/wakapi/models/filters.go:32.2,32.14 1 1 -github.com/muety/wakapi/models/filters.go:27.22,28.48 1 1 -github.com/muety/wakapi/models/filters.go:28.48,30.4 1 1 -github.com/muety/wakapi/models/filters.go:40.56,42.2 1 1 -github.com/muety/wakapi/models/filters.go:44.66,47.2 2 1 -github.com/muety/wakapi/models/filters.go:49.59,51.2 1 1 -github.com/muety/wakapi/models/filters.go:53.70,54.16 1 1 -github.com/muety/wakapi/models/filters.go:72.2,72.10 1 1 -github.com/muety/wakapi/models/filters.go:55.22,56.41 1 1 -github.com/muety/wakapi/models/filters.go:57.17,58.31 1 0 -github.com/muety/wakapi/models/filters.go:59.23,60.43 1 1 -github.com/muety/wakapi/models/filters.go:61.21,62.39 1 0 -github.com/muety/wakapi/models/filters.go:63.22,64.41 1 0 -github.com/muety/wakapi/models/filters.go:65.20,66.37 1 1 -github.com/muety/wakapi/models/filters.go:67.21,68.39 1 0 -github.com/muety/wakapi/models/filters.go:69.21,70.39 1 0 -github.com/muety/wakapi/models/filters.go:75.49,76.44 1 1 -github.com/muety/wakapi/models/filters.go:93.2,93.29 1 1 -github.com/muety/wakapi/models/filters.go:76.44,78.3 1 1 -github.com/muety/wakapi/models/filters.go:78.8,78.41 1 1 -github.com/muety/wakapi/models/filters.go:78.41,80.3 1 0 -github.com/muety/wakapi/models/filters.go:80.8,80.53 1 1 -github.com/muety/wakapi/models/filters.go:80.53,82.3 1 1 -github.com/muety/wakapi/models/filters.go:82.8,82.49 1 1 -github.com/muety/wakapi/models/filters.go:82.49,84.3 1 0 -github.com/muety/wakapi/models/filters.go:84.8,84.51 1 1 -github.com/muety/wakapi/models/filters.go:84.51,86.3 1 0 -github.com/muety/wakapi/models/filters.go:86.8,86.47 1 1 -github.com/muety/wakapi/models/filters.go:86.47,88.3 1 0 -github.com/muety/wakapi/models/filters.go:88.8,88.49 1 1 -github.com/muety/wakapi/models/filters.go:88.49,90.3 1 0 -github.com/muety/wakapi/models/filters.go:90.8,90.49 1 1 -github.com/muety/wakapi/models/filters.go:90.49,92.3 1 0 -github.com/muety/wakapi/models/filters.go:96.46,97.30 1 1 -github.com/muety/wakapi/models/filters.go:100.2,100.66 1 0 -github.com/muety/wakapi/models/filters.go:97.30,99.3 1 1 -github.com/muety/wakapi/models/filters.go:103.34,106.2 2 1 -github.com/muety/wakapi/models/filters.go:108.31,110.51 2 0 -github.com/muety/wakapi/models/filters.go:113.2,113.14 1 0 -github.com/muety/wakapi/models/filters.go:110.51,112.3 1 0 -github.com/muety/wakapi/models/filters.go:116.51,118.2 1 0 -github.com/muety/wakapi/models/filters.go:120.37,122.51 2 0 -github.com/muety/wakapi/models/filters.go:127.2,127.14 1 0 -github.com/muety/wakapi/models/filters.go:122.51,123.37 1 0 -github.com/muety/wakapi/models/filters.go:123.37,125.4 1 0 -github.com/muety/wakapi/models/filters.go:130.59,131.18 1 0 -github.com/muety/wakapi/models/filters.go:132.22,133.20 1 0 -github.com/muety/wakapi/models/filters.go:134.23,135.21 1 0 -github.com/muety/wakapi/models/filters.go:136.21,137.19 1 0 -github.com/muety/wakapi/models/filters.go:138.17,139.15 1 0 -github.com/muety/wakapi/models/filters.go:140.22,141.20 1 0 -github.com/muety/wakapi/models/filters.go:142.20,143.18 1 0 -github.com/muety/wakapi/models/filters.go:144.21,145.19 1 0 -github.com/muety/wakapi/models/filters.go:146.21,147.19 1 0 -github.com/muety/wakapi/models/filters.go:148.10,149.21 1 0 -github.com/muety/wakapi/models/filters.go:153.33,155.16 2 0 -github.com/muety/wakapi/models/filters.go:158.2,158.32 1 0 -github.com/muety/wakapi/models/filters.go:155.16,157.3 1 0 -github.com/muety/wakapi/models/filters.go:161.44,167.2 1 1 -github.com/muety/wakapi/models/filters.go:170.70,171.22 1 1 -github.com/muety/wakapi/models/filters.go:179.2,179.17 1 1 -github.com/muety/wakapi/models/filters.go:187.2,187.23 1 1 -github.com/muety/wakapi/models/filters.go:195.2,195.21 1 1 -github.com/muety/wakapi/models/filters.go:203.2,203.22 1 1 -github.com/muety/wakapi/models/filters.go:211.2,211.21 1 1 -github.com/muety/wakapi/models/filters.go:220.2,220.10 1 1 -github.com/muety/wakapi/models/filters.go:171.22,173.31 2 1 -github.com/muety/wakapi/models/filters.go:177.3,177.22 1 1 -github.com/muety/wakapi/models/filters.go:173.31,176.4 2 1 -github.com/muety/wakapi/models/filters.go:179.17,181.26 2 0 -github.com/muety/wakapi/models/filters.go:185.3,185.17 1 0 -github.com/muety/wakapi/models/filters.go:181.26,184.4 2 0 -github.com/muety/wakapi/models/filters.go:187.23,189.32 2 1 -github.com/muety/wakapi/models/filters.go:193.3,193.23 1 1 -github.com/muety/wakapi/models/filters.go:189.32,192.4 2 1 -github.com/muety/wakapi/models/filters.go:195.21,197.30 2 0 -github.com/muety/wakapi/models/filters.go:201.3,201.21 1 0 -github.com/muety/wakapi/models/filters.go:197.30,200.4 2 0 -github.com/muety/wakapi/models/filters.go:203.22,205.31 2 0 -github.com/muety/wakapi/models/filters.go:209.3,209.22 1 0 -github.com/muety/wakapi/models/filters.go:205.31,208.4 2 0 -github.com/muety/wakapi/models/filters.go:211.21,213.30 2 0 -github.com/muety/wakapi/models/filters.go:217.3,217.21 1 0 -github.com/muety/wakapi/models/filters.go:213.30,216.4 2 0 -github.com/muety/wakapi/models/filters.go:223.83,224.41 1 1 -github.com/muety/wakapi/models/filters.go:227.2,227.28 1 1 -github.com/muety/wakapi/models/filters.go:230.2,230.10 1 1 -github.com/muety/wakapi/models/filters.go:224.41,226.3 1 0 -github.com/muety/wakapi/models/filters.go:227.28,229.3 1 1 -github.com/muety/wakapi/models/filters.go:233.43,235.2 1 0 -github.com/muety/wakapi/models/heartbeat.go:34.34,36.2 1 1 -github.com/muety/wakapi/models/heartbeat.go:38.55,41.2 2 0 -github.com/muety/wakapi/models/heartbeat.go:43.43,49.80 1 0 -github.com/muety/wakapi/models/heartbeat.go:53.2,56.10 3 0 -github.com/muety/wakapi/models/heartbeat.go:49.80,51.3 1 0 -github.com/muety/wakapi/models/heartbeat.go:59.65,61.46 2 1 -github.com/muety/wakapi/models/heartbeat.go:61.46,62.108 1 1 -github.com/muety/wakapi/models/heartbeat.go:62.108,65.4 2 1 -github.com/muety/wakapi/models/heartbeat.go:69.50,70.11 1 1 -github.com/muety/wakapi/models/heartbeat.go:87.2,87.15 1 1 -github.com/muety/wakapi/models/heartbeat.go:91.2,91.12 1 1 -github.com/muety/wakapi/models/heartbeat.go:71.22,72.18 1 1 -github.com/muety/wakapi/models/heartbeat.go:73.21,74.17 1 1 -github.com/muety/wakapi/models/heartbeat.go:75.23,76.19 1 1 -github.com/muety/wakapi/models/heartbeat.go:77.17,78.26 1 1 -github.com/muety/wakapi/models/heartbeat.go:79.22,80.18 1 1 -github.com/muety/wakapi/models/heartbeat.go:81.21,82.17 1 0 -github.com/muety/wakapi/models/heartbeat.go:83.21,84.17 1 0 -github.com/muety/wakapi/models/heartbeat.go:87.15,89.3 1 1 -github.com/muety/wakapi/models/heartbeat.go:94.37,110.2 1 0 -github.com/muety/wakapi/models/heartbeat.go:118.41,120.16 2 1 -github.com/muety/wakapi/models/heartbeat.go:123.2,124.10 2 1 -github.com/muety/wakapi/models/heartbeat.go:120.16,122.3 1 0 -github.com/muety/wakapi/models/heartbeat.go:127.38,137.2 1 0 -github.com/muety/wakapi/models/models.go:3.14,5.2 0 1 -github.com/muety/wakapi/models/summary.go:66.29,68.2 1 1 -github.com/muety/wakapi/models/summary.go:70.35,72.2 1 0 -github.com/muety/wakapi/models/summary.go:74.38,76.2 1 0 -github.com/muety/wakapi/models/summary.go:78.37,88.2 9 1 -github.com/muety/wakapi/models/summary.go:90.35,92.2 1 1 -github.com/muety/wakapi/models/summary.go:94.57,105.2 1 1 -github.com/muety/wakapi/models/summary.go:107.64,108.21 1 1 -github.com/muety/wakapi/models/summary.go:126.2,126.12 1 0 -github.com/muety/wakapi/models/summary.go:109.22,110.21 1 1 -github.com/muety/wakapi/models/summary.go:111.23,112.22 1 1 -github.com/muety/wakapi/models/summary.go:113.21,114.20 1 1 -github.com/muety/wakapi/models/summary.go:115.17,116.29 1 1 -github.com/muety/wakapi/models/summary.go:117.22,118.21 1 1 -github.com/muety/wakapi/models/summary.go:119.20,120.19 1 1 -github.com/muety/wakapi/models/summary.go:121.21,122.21 1 1 -github.com/muety/wakapi/models/summary.go:123.21,124.21 1 1 -github.com/muety/wakapi/models/summary.go:129.59,130.21 1 1 -github.com/muety/wakapi/models/summary.go:134.2,134.35 1 1 -github.com/muety/wakapi/models/summary.go:140.2,140.10 1 1 -github.com/muety/wakapi/models/summary.go:130.21,132.3 1 1 -github.com/muety/wakapi/models/summary.go:134.35,135.41 1 1 -github.com/muety/wakapi/models/summary.go:135.41,137.4 1 1 -github.com/muety/wakapi/models/summary.go:156.33,161.26 4 1 -github.com/muety/wakapi/models/summary.go:168.2,168.37 1 1 -github.com/muety/wakapi/models/summary.go:173.2,174.16 2 1 -github.com/muety/wakapi/models/summary.go:177.2,177.33 1 1 -github.com/muety/wakapi/models/summary.go:161.26,162.30 1 1 -github.com/muety/wakapi/models/summary.go:162.30,164.4 1 1 -github.com/muety/wakapi/models/summary.go:168.37,170.3 1 0 -github.com/muety/wakapi/models/summary.go:174.16,176.3 1 0 -github.com/muety/wakapi/models/summary.go:177.33,179.3 1 1 -github.com/muety/wakapi/models/summary.go:183.56,189.28 5 1 -github.com/muety/wakapi/models/summary.go:193.2,194.42 2 1 -github.com/muety/wakapi/models/summary.go:201.2,202.15 2 1 -github.com/muety/wakapi/models/summary.go:189.28,191.3 1 1 -github.com/muety/wakapi/models/summary.go:194.42,195.22 1 0 -github.com/muety/wakapi/models/summary.go:195.22,197.9 2 0 -github.com/muety/wakapi/models/summary.go:202.15,203.28 1 1 -github.com/muety/wakapi/models/summary.go:203.28,205.4 1 0 -github.com/muety/wakapi/models/summary.go:205.9,211.4 1 1 -github.com/muety/wakapi/models/summary.go:215.45,220.16 4 1 -github.com/muety/wakapi/models/summary.go:223.2,223.39 1 1 -github.com/muety/wakapi/models/summary.go:227.2,227.30 1 1 -github.com/muety/wakapi/models/summary.go:220.16,222.3 1 0 -github.com/muety/wakapi/models/summary.go:223.39,225.3 1 1 -github.com/muety/wakapi/models/summary.go:230.73,232.55 2 1 -github.com/muety/wakapi/models/summary.go:237.2,237.16 1 1 -github.com/muety/wakapi/models/summary.go:232.55,233.31 1 1 -github.com/muety/wakapi/models/summary.go:233.31,235.4 1 1 -github.com/muety/wakapi/models/summary.go:240.88,242.55 2 1 -github.com/muety/wakapi/models/summary.go:250.2,250.16 1 1 -github.com/muety/wakapi/models/summary.go:242.55,243.31 1 1 -github.com/muety/wakapi/models/summary.go:243.31,244.23 1 1 -github.com/muety/wakapi/models/summary.go:247.4,247.46 1 1 -github.com/muety/wakapi/models/summary.go:244.23,245.13 1 1 -github.com/muety/wakapi/models/summary.go:253.73,255.34 2 1 -github.com/muety/wakapi/models/summary.go:258.2,258.14 1 1 -github.com/muety/wakapi/models/summary.go:255.34,257.3 1 1 -github.com/muety/wakapi/models/summary.go:261.56,264.55 3 0 -github.com/muety/wakapi/models/summary.go:271.2,271.12 1 0 -github.com/muety/wakapi/models/summary.go:264.55,265.31 1 0 -github.com/muety/wakapi/models/summary.go:265.31,266.44 1 0 -github.com/muety/wakapi/models/summary.go:266.44,268.5 1 0 -github.com/muety/wakapi/models/summary.go:274.58,276.16 2 0 -github.com/muety/wakapi/models/summary.go:279.2,279.16 1 0 -github.com/muety/wakapi/models/summary.go:276.16,278.3 1 0 -github.com/muety/wakapi/models/summary.go:282.71,283.63 1 1 -github.com/muety/wakapi/models/summary.go:327.2,336.10 8 1 -github.com/muety/wakapi/models/summary.go:283.63,284.20 1 1 -github.com/muety/wakapi/models/summary.go:288.3,290.45 2 1 -github.com/muety/wakapi/models/summary.go:299.3,299.31 1 1 -github.com/muety/wakapi/models/summary.go:306.3,306.31 1 1 -github.com/muety/wakapi/models/summary.go:323.3,323.16 1 1 -github.com/muety/wakapi/models/summary.go:284.20,286.4 1 1 -github.com/muety/wakapi/models/summary.go:290.45,291.32 1 1 -github.com/muety/wakapi/models/summary.go:296.4,296.14 1 1 -github.com/muety/wakapi/models/summary.go:291.32,292.24 1 1 -github.com/muety/wakapi/models/summary.go:292.24,294.6 1 1 -github.com/muety/wakapi/models/summary.go:299.31,301.60 1 1 -github.com/muety/wakapi/models/summary.go:301.60,303.5 1 1 -github.com/muety/wakapi/models/summary.go:306.31,308.60 1 1 -github.com/muety/wakapi/models/summary.go:308.60,309.55 1 1 -github.com/muety/wakapi/models/summary.go:309.55,311.6 1 1 -github.com/muety/wakapi/models/summary.go:311.11,319.6 1 1 -github.com/muety/wakapi/models/summary.go:339.57,340.30 1 1 -github.com/muety/wakapi/models/summary.go:345.2,345.43 1 0 -github.com/muety/wakapi/models/summary.go:340.30,341.28 1 1 -github.com/muety/wakapi/models/summary.go:341.28,343.4 1 1 -github.com/muety/wakapi/models/summary.go:348.43,350.2 1 0 -github.com/muety/wakapi/models/summary.go:352.49,353.21 1 0 -github.com/muety/wakapi/models/summary.go:356.2,357.54 2 0 -github.com/muety/wakapi/models/summary.go:353.21,355.3 1 0 -github.com/muety/wakapi/models/summary.go:360.51,361.27 1 0 -github.com/muety/wakapi/models/summary.go:364.2,365.19 2 0 -github.com/muety/wakapi/models/summary.go:361.27,363.3 1 0 -github.com/muety/wakapi/models/summary.go:368.50,372.2 1 1 -github.com/muety/wakapi/models/summary.go:374.33,376.2 1 1 -github.com/muety/wakapi/models/summary.go:378.43,380.2 1 1 -github.com/muety/wakapi/models/summary.go:382.38,384.2 1 1 -github.com/muety/wakapi/models/heartbeats.go:7.31,9.2 1 0 -github.com/muety/wakapi/models/heartbeats.go:11.41,13.2 1 0 -github.com/muety/wakapi/models/heartbeats.go:15.36,17.2 1 0 -github.com/muety/wakapi/models/heartbeats.go:19.43,22.2 2 0 -github.com/muety/wakapi/models/heartbeats.go:24.41,26.18 1 0 -github.com/muety/wakapi/models/heartbeats.go:29.2,29.16 1 0 -github.com/muety/wakapi/models/heartbeats.go:26.18,28.3 1 0 -github.com/muety/wakapi/models/heartbeats.go:32.40,34.18 1 0 -github.com/muety/wakapi/models/heartbeats.go:37.2,37.24 1 0 -github.com/muety/wakapi/models/heartbeats.go:34.18,36.3 1 0 -github.com/muety/wakapi/models/language_mapping.go:11.42,13.2 1 0 -github.com/muety/wakapi/models/language_mapping.go:15.51,17.2 1 0 -github.com/muety/wakapi/models/language_mapping.go:19.52,21.2 1 0 -github.com/muety/wakapi/models/shared.go:38.52,40.2 1 0 -github.com/muety/wakapi/models/shared.go:42.52,45.16 3 0 -github.com/muety/wakapi/models/shared.go:48.2,50.12 3 0 -github.com/muety/wakapi/models/shared.go:45.16,47.3 1 0 -github.com/muety/wakapi/models/shared.go:53.52,59.22 2 0 -github.com/muety/wakapi/models/shared.go:74.2,77.12 3 0 -github.com/muety/wakapi/models/shared.go:60.14,64.17 2 0 -github.com/muety/wakapi/models/shared.go:67.17,69.8 2 0 -github.com/muety/wakapi/models/shared.go:70.10,71.64 1 0 -github.com/muety/wakapi/models/shared.go:64.17,66.4 1 0 -github.com/muety/wakapi/models/shared.go:80.51,83.2 2 0 -github.com/muety/wakapi/models/shared.go:85.45,87.2 1 1 -github.com/muety/wakapi/models/shared.go:89.37,91.2 1 0 -github.com/muety/wakapi/models/shared.go:93.35,95.2 1 1 -github.com/muety/wakapi/models/shared.go:97.34,99.2 1 0 -github.com/muety/wakapi/models/durations.go:7.30,9.2 1 0 -github.com/muety/wakapi/models/durations.go:11.40,13.2 1 0 -github.com/muety/wakapi/models/durations.go:15.35,17.2 1 0 -github.com/muety/wakapi/models/durations.go:19.45,21.22 2 0 -github.com/muety/wakapi/models/durations.go:24.2,24.14 1 0 -github.com/muety/wakapi/models/durations.go:21.22,23.3 1 0 -github.com/muety/wakapi/models/durations.go:27.39,30.2 2 0 -github.com/muety/wakapi/models/durations.go:32.39,34.18 1 0 -github.com/muety/wakapi/models/durations.go:37.2,37.16 1 0 -github.com/muety/wakapi/models/durations.go:34.18,36.3 1 0 -github.com/muety/wakapi/models/durations.go:40.38,42.18 1 0 -github.com/muety/wakapi/models/durations.go:45.2,45.24 1 0 -github.com/muety/wakapi/models/durations.go:42.18,44.3 1 0 -github.com/muety/wakapi/models/mail.go:23.44,27.2 3 0 -github.com/muety/wakapi/models/mail.go:29.44,33.2 3 0 -github.com/muety/wakapi/models/mail.go:35.34,36.18 1 0 -github.com/muety/wakapi/models/mail.go:39.2,39.21 1 0 -github.com/muety/wakapi/models/mail.go:42.2,42.23 1 0 -github.com/muety/wakapi/models/mail.go:45.2,45.10 1 0 -github.com/muety/wakapi/models/mail.go:36.18,38.3 1 0 -github.com/muety/wakapi/models/mail.go:39.21,41.3 1 0 -github.com/muety/wakapi/models/mail.go:42.23,44.3 1 0 -github.com/muety/wakapi/models/mail.go:48.32,67.2 1 0 -github.com/muety/wakapi/models/mail.go:69.41,71.2 1 0 -github.com/muety/wakapi/models/project_label.go:14.39,16.2 1 0 +github.com/muety/wakapi/routes/api/avatar.go:18.40,20.16 2 0 +github.com/muety/wakapi/routes/api/avatar.go:24.2,27.3 1 0 +github.com/muety/wakapi/routes/api/avatar.go:20.16,21.13 1 0 +github.com/muety/wakapi/routes/api/avatar.go:30.59,32.2 1 0 +github.com/muety/wakapi/routes/api/avatar.go:34.69,37.37 2 0 +github.com/muety/wakapi/routes/api/avatar.go:41.2,41.29 1 0 +github.com/muety/wakapi/routes/api/avatar.go:44.2,49.32 5 0 +github.com/muety/wakapi/routes/api/avatar.go:37.37,39.3 1 0 +github.com/muety/wakapi/routes/api/avatar.go:41.29,43.3 1 0 +github.com/muety/wakapi/routes/api/badge.go:27.112,34.2 1 1 +github.com/muety/wakapi/routes/api/badge.go:36.58,38.2 1 1 +github.com/muety/wakapi/routes/api/badge.go:40.68,42.16 2 1 +github.com/muety/wakapi/routes/api/badge.go:47.2,48.16 2 1 +github.com/muety/wakapi/routes/api/badge.go:54.2,56.62 3 1 +github.com/muety/wakapi/routes/api/badge.go:61.2,69.16 3 1 +github.com/muety/wakapi/routes/api/badge.go:75.2,76.66 2 1 +github.com/muety/wakapi/routes/api/badge.go:79.2,79.66 1 1 +github.com/muety/wakapi/routes/api/badge.go:83.2,83.101 1 1 +github.com/muety/wakapi/routes/api/badge.go:87.2,89.25 3 1 +github.com/muety/wakapi/routes/api/badge.go:42.16,45.3 2 0 +github.com/muety/wakapi/routes/api/badge.go:48.16,52.3 3 1 +github.com/muety/wakapi/routes/api/badge.go:56.62,59.3 2 0 +github.com/muety/wakapi/routes/api/badge.go:69.16,73.3 3 0 +github.com/muety/wakapi/routes/api/badge.go:76.66,78.3 1 0 +github.com/muety/wakapi/routes/api/badge.go:79.66,81.3 1 0 +github.com/muety/wakapi/routes/api/badge.go:83.101,85.3 1 1 +github.com/muety/wakapi/routes/api/badge.go:92.53,97.2 4 1 +github.com/muety/wakapi/routes/api/diagnostics.go:20.138,26.2 1 0 +github.com/muety/wakapi/routes/api/diagnostics.go:28.67,30.2 1 0 +github.com/muety/wakapi/routes/api/diagnostics.go:39.78,42.69 2 0 +github.com/muety/wakapi/routes/api/diagnostics.go:49.2,49.66 1 0 +github.com/muety/wakapi/routes/api/diagnostics.go:56.2,56.59 1 0 +github.com/muety/wakapi/routes/api/diagnostics.go:42.69,47.3 4 0 +github.com/muety/wakapi/routes/api/diagnostics.go:49.66,54.3 4 0 github.com/muety/wakapi/routes/api/health.go:15.57,17.2 1 0 github.com/muety/wakapi/routes/api/health.go:19.62,21.2 1 0 github.com/muety/wakapi/routes/api/health.go:29.72,31.41 2 0 @@ -1090,63 +740,25 @@ github.com/muety/wakapi/routes/api/summary.go:28.63,34.2 4 0 github.com/muety/wakapi/routes/api/summary.go:53.73,55.16 2 0 github.com/muety/wakapi/routes/api/summary.go:61.2,61.51 1 0 github.com/muety/wakapi/routes/api/summary.go:55.16,59.3 3 0 -github.com/muety/wakapi/routes/api/avatar.go:18.40,20.16 2 0 -github.com/muety/wakapi/routes/api/avatar.go:24.2,27.3 1 0 -github.com/muety/wakapi/routes/api/avatar.go:20.16,21.13 1 0 -github.com/muety/wakapi/routes/api/avatar.go:30.59,32.2 1 0 -github.com/muety/wakapi/routes/api/avatar.go:34.69,37.37 2 0 -github.com/muety/wakapi/routes/api/avatar.go:41.2,41.29 1 0 -github.com/muety/wakapi/routes/api/avatar.go:44.2,49.32 5 0 -github.com/muety/wakapi/routes/api/avatar.go:37.37,39.3 1 0 -github.com/muety/wakapi/routes/api/avatar.go:41.29,43.3 1 0 -github.com/muety/wakapi/routes/api/badge.go:27.112,34.2 1 1 -github.com/muety/wakapi/routes/api/badge.go:36.58,38.2 1 1 -github.com/muety/wakapi/routes/api/badge.go:40.68,42.16 2 1 -github.com/muety/wakapi/routes/api/badge.go:47.2,48.16 2 1 -github.com/muety/wakapi/routes/api/badge.go:54.2,56.62 3 1 -github.com/muety/wakapi/routes/api/badge.go:61.2,69.16 3 1 -github.com/muety/wakapi/routes/api/badge.go:75.2,76.66 2 1 -github.com/muety/wakapi/routes/api/badge.go:79.2,79.66 1 1 -github.com/muety/wakapi/routes/api/badge.go:83.2,83.101 1 1 -github.com/muety/wakapi/routes/api/badge.go:87.2,89.25 3 1 -github.com/muety/wakapi/routes/api/badge.go:42.16,45.3 2 0 -github.com/muety/wakapi/routes/api/badge.go:48.16,52.3 3 1 -github.com/muety/wakapi/routes/api/badge.go:56.62,59.3 2 0 -github.com/muety/wakapi/routes/api/badge.go:69.16,73.3 3 0 -github.com/muety/wakapi/routes/api/badge.go:76.66,78.3 1 0 -github.com/muety/wakapi/routes/api/badge.go:79.66,81.3 1 0 -github.com/muety/wakapi/routes/api/badge.go:83.101,85.3 1 1 -github.com/muety/wakapi/routes/api/badge.go:92.53,97.2 4 1 -github.com/muety/wakapi/routes/api/diagnostics.go:20.138,26.2 1 0 -github.com/muety/wakapi/routes/api/diagnostics.go:28.67,30.2 1 0 -github.com/muety/wakapi/routes/api/diagnostics.go:39.78,42.69 2 0 -github.com/muety/wakapi/routes/api/diagnostics.go:49.2,49.66 1 0 -github.com/muety/wakapi/routes/api/diagnostics.go:56.2,56.59 1 0 -github.com/muety/wakapi/routes/api/diagnostics.go:42.69,47.3 4 0 -github.com/muety/wakapi/routes/api/diagnostics.go:49.66,54.3 4 0 -github.com/muety/wakapi/services/diagnostics.go:14.101,19.2 1 0 -github.com/muety/wakapi/services/diagnostics.go:21.101,24.2 2 0 -github.com/muety/wakapi/services/housekeeping.go:20.144,29.2 1 0 -github.com/muety/wakapi/services/housekeeping.go:31.42,32.43 1 0 -github.com/muety/wakapi/services/housekeeping.go:36.2,38.47 2 0 -github.com/muety/wakapi/services/housekeeping.go:62.2,62.16 1 0 -github.com/muety/wakapi/services/housekeeping.go:32.43,34.3 1 0 -github.com/muety/wakapi/services/housekeeping.go:38.47,41.17 2 0 -github.com/muety/wakapi/services/housekeeping.go:47.3,47.27 1 0 -github.com/muety/wakapi/services/housekeeping.go:41.17,44.4 2 0 -github.com/muety/wakapi/services/housekeeping.go:47.27,49.31 1 0 -github.com/muety/wakapi/services/housekeeping.go:53.4,54.35 2 0 -github.com/muety/wakapi/services/housekeeping.go:49.31,50.13 1 0 -github.com/muety/wakapi/services/housekeeping.go:54.35,55.75 1 0 -github.com/muety/wakapi/services/housekeeping.go:55.75,57.6 1 0 -github.com/muety/wakapi/services/housekeeping.go:62.16,64.3 1 0 -github.com/muety/wakapi/services/housekeeping.go:67.94,69.36 2 0 -github.com/muety/wakapi/services/housekeeping.go:75.2,75.73 1 0 -github.com/muety/wakapi/services/housekeeping.go:80.2,81.74 2 0 -github.com/muety/wakapi/services/housekeeping.go:85.2,85.12 1 0 -github.com/muety/wakapi/services/housekeeping.go:69.36,72.3 2 0 -github.com/muety/wakapi/services/housekeeping.go:75.73,77.3 1 0 -github.com/muety/wakapi/services/housekeeping.go:81.74,83.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:18.118,24.2 1 0 +github.com/muety/wakapi/services/language_mapping.go:26.86,28.2 1 0 +github.com/muety/wakapi/services/language_mapping.go:30.96,31.53 1 0 +github.com/muety/wakapi/services/language_mapping.go:35.2,36.16 2 0 +github.com/muety/wakapi/services/language_mapping.go:39.2,40.22 2 0 +github.com/muety/wakapi/services/language_mapping.go:31.53,33.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:36.16,38.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:43.92,46.16 3 0 +github.com/muety/wakapi/services/language_mapping.go:50.2,50.33 1 0 +github.com/muety/wakapi/services/language_mapping.go:53.2,53.22 1 0 +github.com/muety/wakapi/services/language_mapping.go:46.16,48.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:50.33,52.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:56.109,58.16 2 0 +github.com/muety/wakapi/services/language_mapping.go:62.2,63.20 2 0 +github.com/muety/wakapi/services/language_mapping.go:58.16,60.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:66.82,67.26 1 0 +github.com/muety/wakapi/services/language_mapping.go:70.2,72.12 3 0 +github.com/muety/wakapi/services/language_mapping.go:67.26,69.3 1 0 +github.com/muety/wakapi/services/language_mapping.go:75.74,78.2 1 0 github.com/muety/wakapi/services/summary.go:28.189,40.33 3 1 github.com/muety/wakapi/services/summary.go:46.2,46.12 1 1 github.com/muety/wakapi/services/summary.go:40.33,41.31 1 1 @@ -1277,6 +889,106 @@ github.com/muety/wakapi/services/summary.go:481.3,481.24 1 1 github.com/muety/wakapi/services/summary.go:472.17,473.33 1 1 github.com/muety/wakapi/services/summary.go:473.33,475.5 1 1 github.com/muety/wakapi/services/summary.go:478.28,480.4 1 1 +github.com/muety/wakapi/services/housekeeping.go:20.144,29.2 1 0 +github.com/muety/wakapi/services/housekeeping.go:31.42,32.43 1 0 +github.com/muety/wakapi/services/housekeeping.go:36.2,38.47 2 0 +github.com/muety/wakapi/services/housekeeping.go:62.2,62.16 1 0 +github.com/muety/wakapi/services/housekeeping.go:32.43,34.3 1 0 +github.com/muety/wakapi/services/housekeeping.go:38.47,41.17 2 0 +github.com/muety/wakapi/services/housekeeping.go:47.3,47.27 1 0 +github.com/muety/wakapi/services/housekeeping.go:41.17,44.4 2 0 +github.com/muety/wakapi/services/housekeeping.go:47.27,49.31 1 0 +github.com/muety/wakapi/services/housekeeping.go:53.4,54.35 2 0 +github.com/muety/wakapi/services/housekeeping.go:49.31,50.13 1 0 +github.com/muety/wakapi/services/housekeeping.go:54.35,55.75 1 0 +github.com/muety/wakapi/services/housekeeping.go:55.75,57.6 1 0 +github.com/muety/wakapi/services/housekeeping.go:62.16,64.3 1 0 +github.com/muety/wakapi/services/housekeeping.go:67.94,69.36 2 0 +github.com/muety/wakapi/services/housekeeping.go:75.2,75.73 1 0 +github.com/muety/wakapi/services/housekeeping.go:80.2,81.74 2 0 +github.com/muety/wakapi/services/housekeeping.go:85.2,85.12 1 0 +github.com/muety/wakapi/services/housekeeping.go:69.36,72.3 2 0 +github.com/muety/wakapi/services/housekeeping.go:75.73,77.3 1 0 +github.com/muety/wakapi/services/housekeeping.go:81.74,83.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:30.159,43.33 3 0 +github.com/muety/wakapi/services/leaderboard.go:67.2,67.12 1 0 +github.com/muety/wakapi/services/leaderboard.go:43.33,44.31 1 0 +github.com/muety/wakapi/services/leaderboard.go:44.31,50.18 3 0 +github.com/muety/wakapi/services/leaderboard.go:54.4,54.41 1 0 +github.com/muety/wakapi/services/leaderboard.go:50.18,52.5 1 0 +github.com/muety/wakapi/services/leaderboard.go:54.41,57.5 2 0 +github.com/muety/wakapi/services/leaderboard.go:57.10,57.48 1 0 +github.com/muety/wakapi/services/leaderboard.go:57.48,59.64 2 0 +github.com/muety/wakapi/services/leaderboard.go:62.5,62.22 1 0 +github.com/muety/wakapi/services/leaderboard.go:59.64,61.6 1 0 +github.com/muety/wakapi/services/leaderboard.go:70.43,73.21 2 0 +github.com/muety/wakapi/services/leaderboard.go:82.2,82.76 1 0 +github.com/muety/wakapi/services/leaderboard.go:73.21,75.17 2 0 +github.com/muety/wakapi/services/leaderboard.go:79.3,79.91 1 0 +github.com/muety/wakapi/services/leaderboard.go:75.17,78.4 2 0 +github.com/muety/wakapi/services/leaderboard.go:82.76,83.77 1 0 +github.com/muety/wakapi/services/leaderboard.go:83.77,85.4 1 0 +github.com/muety/wakapi/services/leaderboard.go:89.121,92.29 2 0 +github.com/muety/wakapi/services/leaderboard.go:127.2,129.12 3 0 +github.com/muety/wakapi/services/leaderboard.go:92.29,93.83 1 0 +github.com/muety/wakapi/services/leaderboard.go:98.3,99.17 2 0 +github.com/muety/wakapi/services/leaderboard.go:104.3,104.85 1 0 +github.com/muety/wakapi/services/leaderboard.go:109.3,109.25 1 0 +github.com/muety/wakapi/services/leaderboard.go:93.83,95.12 2 0 +github.com/muety/wakapi/services/leaderboard.go:99.17,101.12 2 0 +github.com/muety/wakapi/services/leaderboard.go:104.85,106.12 2 0 +github.com/muety/wakapi/services/leaderboard.go:109.25,111.18 2 0 +github.com/muety/wakapi/services/leaderboard.go:116.4,116.23 1 0 +github.com/muety/wakapi/services/leaderboard.go:120.4,120.60 1 0 +github.com/muety/wakapi/services/leaderboard.go:111.18,113.13 2 0 +github.com/muety/wakapi/services/leaderboard.go:116.23,117.13 1 0 +github.com/muety/wakapi/services/leaderboard.go:120.60,122.13 2 0 +github.com/muety/wakapi/services/leaderboard.go:132.77,135.2 2 0 +github.com/muety/wakapi/services/leaderboard.go:137.60,140.52 2 0 +github.com/muety/wakapi/services/leaderboard.go:144.2,145.16 2 0 +github.com/muety/wakapi/services/leaderboard.go:148.2,148.19 1 0 +github.com/muety/wakapi/services/leaderboard.go:140.52,142.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:145.16,147.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:151.153,153.2 1 0 +github.com/muety/wakapi/services/leaderboard.go:155.144,157.2 1 0 +github.com/muety/wakapi/services/leaderboard.go:159.174,162.52 2 0 +github.com/muety/wakapi/services/leaderboard.go:166.2,167.16 2 0 +github.com/muety/wakapi/services/leaderboard.go:171.2,171.18 1 0 +github.com/muety/wakapi/services/leaderboard.go:184.2,185.19 2 0 +github.com/muety/wakapi/services/leaderboard.go:162.52,164.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:167.16,169.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:171.18,173.17 2 0 +github.com/muety/wakapi/services/leaderboard.go:173.17,175.4 1 0 +github.com/muety/wakapi/services/leaderboard.go:175.9,176.31 1 0 +github.com/muety/wakapi/services/leaderboard.go:176.31,177.40 1 0 +github.com/muety/wakapi/services/leaderboard.go:177.40,179.6 1 0 +github.com/muety/wakapi/services/leaderboard.go:188.165,191.52 2 0 +github.com/muety/wakapi/services/leaderboard.go:195.2,196.16 2 0 +github.com/muety/wakapi/services/leaderboard.go:200.2,200.17 1 0 +github.com/muety/wakapi/services/leaderboard.go:211.2,212.19 2 0 +github.com/muety/wakapi/services/leaderboard.go:191.52,193.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:196.16,198.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:200.17,202.17 2 0 +github.com/muety/wakapi/services/leaderboard.go:202.17,204.4 1 0 +github.com/muety/wakapi/services/leaderboard.go:204.9,205.31 1 0 +github.com/muety/wakapi/services/leaderboard.go:205.31,207.5 1 0 +github.com/muety/wakapi/services/leaderboard.go:215.129,217.16 2 0 +github.com/muety/wakapi/services/leaderboard.go:221.2,222.16 2 0 +github.com/muety/wakapi/services/leaderboard.go:227.2,233.8 2 0 +github.com/muety/wakapi/services/leaderboard.go:217.16,219.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:222.16,224.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:236.151,238.16 2 0 +github.com/muety/wakapi/services/leaderboard.go:242.2,243.16 2 0 +github.com/muety/wakapi/services/leaderboard.go:247.2,250.42 3 0 +github.com/muety/wakapi/services/leaderboard.go:262.2,262.19 1 0 +github.com/muety/wakapi/services/leaderboard.go:238.16,240.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:243.16,245.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:250.42,260.3 2 0 +github.com/muety/wakapi/services/leaderboard.go:265.131,267.47 2 0 +github.com/muety/wakapi/services/leaderboard.go:270.2,270.23 1 0 +github.com/muety/wakapi/services/leaderboard.go:273.2,273.10 1 0 +github.com/muety/wakapi/services/leaderboard.go:267.47,269.3 1 0 +github.com/muety/wakapi/services/leaderboard.go:270.23,272.3 1 0 github.com/muety/wakapi/services/user.go:26.99,36.33 3 0 github.com/muety/wakapi/services/user.go:57.2,57.12 1 0 github.com/muety/wakapi/services/user.go:36.33,37.31 1 0 @@ -1333,215 +1045,6 @@ github.com/muety/wakapi/services/user.go:211.38,213.2 1 0 github.com/muety/wakapi/services/user.go:215.55,217.2 1 0 github.com/muety/wakapi/services/user.go:219.57,224.2 1 0 github.com/muety/wakapi/services/user.go:226.57,231.2 1 0 -github.com/muety/wakapi/services/duration.go:18.78,24.2 2 1 -github.com/muety/wakapi/services/duration.go:26.123,29.42 2 1 -github.com/muety/wakapi/services/duration.go:35.2,36.16 2 1 -github.com/muety/wakapi/services/duration.go:43.2,48.31 4 1 -github.com/muety/wakapi/services/duration.go:99.2,101.31 2 1 -github.com/muety/wakapi/services/duration.go:114.2,114.49 1 1 -github.com/muety/wakapi/services/duration.go:118.2,118.32 1 1 -github.com/muety/wakapi/services/duration.go:29.42,30.90 1 1 -github.com/muety/wakapi/services/duration.go:30.90,32.4 1 1 -github.com/muety/wakapi/services/duration.go:36.16,38.3 1 0 -github.com/muety/wakapi/services/duration.go:48.31,49.42 1 1 -github.com/muety/wakapi/services/duration.go:53.3,54.34 2 1 -github.com/muety/wakapi/services/duration.go:58.3,58.62 1 1 -github.com/muety/wakapi/services/duration.go:62.3,62.20 1 1 -github.com/muety/wakapi/services/duration.go:67.3,77.15 3 1 -github.com/muety/wakapi/services/duration.go:80.3,86.84 2 1 -github.com/muety/wakapi/services/duration.go:96.3,96.10 1 1 -github.com/muety/wakapi/services/duration.go:49.42,50.12 1 1 -github.com/muety/wakapi/services/duration.go:54.34,56.4 1 1 -github.com/muety/wakapi/services/duration.go:58.62,60.4 1 1 -github.com/muety/wakapi/services/duration.go:62.20,64.12 2 1 -github.com/muety/wakapi/services/duration.go:77.15,79.4 1 0 -github.com/muety/wakapi/services/duration.go:86.84,88.41 2 1 -github.com/muety/wakapi/services/duration.go:91.4,91.15 1 1 -github.com/muety/wakapi/services/duration.go:88.41,90.5 1 1 -github.com/muety/wakapi/services/duration.go:92.9,94.4 1 1 -github.com/muety/wakapi/services/duration.go:101.31,102.26 1 1 -github.com/muety/wakapi/services/duration.go:102.26,107.23 1 1 -github.com/muety/wakapi/services/duration.go:110.4,110.36 1 1 -github.com/muety/wakapi/services/duration.go:107.23,109.5 1 1 -github.com/muety/wakapi/services/duration.go:114.49,116.3 1 1 -github.com/muety/wakapi/services/language_mapping.go:18.118,24.2 1 0 -github.com/muety/wakapi/services/language_mapping.go:26.86,28.2 1 0 -github.com/muety/wakapi/services/language_mapping.go:30.96,31.53 1 0 -github.com/muety/wakapi/services/language_mapping.go:35.2,36.16 2 0 -github.com/muety/wakapi/services/language_mapping.go:39.2,40.22 2 0 -github.com/muety/wakapi/services/language_mapping.go:31.53,33.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:36.16,38.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:43.92,46.16 3 0 -github.com/muety/wakapi/services/language_mapping.go:50.2,50.33 1 0 -github.com/muety/wakapi/services/language_mapping.go:53.2,53.22 1 0 -github.com/muety/wakapi/services/language_mapping.go:46.16,48.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:50.33,52.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:56.109,58.16 2 0 -github.com/muety/wakapi/services/language_mapping.go:62.2,63.20 2 0 -github.com/muety/wakapi/services/language_mapping.go:58.16,60.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:66.82,67.26 1 0 -github.com/muety/wakapi/services/language_mapping.go:70.2,72.12 3 0 -github.com/muety/wakapi/services/language_mapping.go:67.26,69.3 1 0 -github.com/muety/wakapi/services/language_mapping.go:75.74,78.2 1 0 -github.com/muety/wakapi/services/project_label.go:21.111,28.2 1 0 -github.com/muety/wakapi/services/project_label.go:30.80,32.2 1 0 -github.com/muety/wakapi/services/project_label.go:34.90,35.51 1 0 -github.com/muety/wakapi/services/project_label.go:39.2,40.16 2 0 -github.com/muety/wakapi/services/project_label.go:43.2,44.20 2 0 -github.com/muety/wakapi/services/project_label.go:35.51,37.3 1 0 -github.com/muety/wakapi/services/project_label.go:40.16,42.3 1 0 -github.com/muety/wakapi/services/project_label.go:48.108,50.16 2 0 -github.com/muety/wakapi/services/project_label.go:53.2,53.112 1 0 -github.com/muety/wakapi/services/project_label.go:56.2,56.26 1 0 -github.com/muety/wakapi/services/project_label.go:50.16,52.3 1 0 -github.com/muety/wakapi/services/project_label.go:53.112,55.3 1 0 -github.com/muety/wakapi/services/project_label.go:60.116,62.16 2 0 -github.com/muety/wakapi/services/project_label.go:65.2,65.112 1 0 -github.com/muety/wakapi/services/project_label.go:68.2,68.26 1 0 -github.com/muety/wakapi/services/project_label.go:62.16,64.3 1 0 -github.com/muety/wakapi/services/project_label.go:65.112,67.3 1 0 -github.com/muety/wakapi/services/project_label.go:71.98,73.16 2 0 -github.com/muety/wakapi/services/project_label.go:77.2,79.20 3 0 -github.com/muety/wakapi/services/project_label.go:73.16,75.3 1 0 -github.com/muety/wakapi/services/project_label.go:82.74,83.24 1 0 -github.com/muety/wakapi/services/project_label.go:86.2,89.12 4 0 -github.com/muety/wakapi/services/project_label.go:83.24,85.3 1 0 -github.com/muety/wakapi/services/project_label.go:92.89,94.14 2 0 -github.com/muety/wakapi/services/project_label.go:97.2,100.4 1 0 -github.com/muety/wakapi/services/project_label.go:94.14,96.3 1 0 -github.com/muety/wakapi/services/alias.go:19.77,24.2 1 1 -github.com/muety/wakapi/services/alias.go:28.60,29.43 1 1 -github.com/muety/wakapi/services/alias.go:32.2,32.14 1 1 -github.com/muety/wakapi/services/alias.go:29.43,31.3 1 1 -github.com/muety/wakapi/services/alias.go:35.62,37.16 2 1 -github.com/muety/wakapi/services/alias.go:40.2,40.12 1 1 -github.com/muety/wakapi/services/alias.go:37.16,39.3 1 1 -github.com/muety/wakapi/services/alias.go:43.59,44.51 1 1 -github.com/muety/wakapi/services/alias.go:44.51,46.3 1 0 -github.com/muety/wakapi/services/alias.go:49.76,50.32 1 0 -github.com/muety/wakapi/services/alias.go:53.2,53.49 1 0 -github.com/muety/wakapi/services/alias.go:50.32,52.3 1 0 -github.com/muety/wakapi/services/alias.go:53.49,55.3 1 0 -github.com/muety/wakapi/services/alias.go:55.8,57.3 1 0 -github.com/muety/wakapi/services/alias.go:60.102,61.38 1 0 -github.com/muety/wakapi/services/alias.go:64.2,64.39 1 0 -github.com/muety/wakapi/services/alias.go:61.38,63.3 1 0 -github.com/muety/wakapi/services/alias.go:67.113,68.38 1 0 -github.com/muety/wakapi/services/alias.go:71.2,71.39 1 0 -github.com/muety/wakapi/services/alias.go:68.38,70.3 1 0 -github.com/muety/wakapi/services/alias.go:74.108,75.32 1 1 -github.com/muety/wakapi/services/alias.go:79.2,79.49 1 1 -github.com/muety/wakapi/services/alias.go:87.2,87.19 1 1 -github.com/muety/wakapi/services/alias.go:75.32,77.3 1 1 -github.com/muety/wakapi/services/alias.go:79.49,80.47 1 1 -github.com/muety/wakapi/services/alias.go:80.47,81.49 1 1 -github.com/muety/wakapi/services/alias.go:81.49,83.5 1 1 -github.com/muety/wakapi/services/alias.go:90.77,92.16 2 0 -github.com/muety/wakapi/services/alias.go:96.2,100.20 3 0 -github.com/muety/wakapi/services/alias.go:92.16,94.3 1 0 -github.com/muety/wakapi/services/alias.go:103.60,104.24 1 0 -github.com/muety/wakapi/services/alias.go:107.2,110.16 2 0 -github.com/muety/wakapi/services/alias.go:114.2,116.12 2 0 -github.com/muety/wakapi/services/alias.go:104.24,106.3 1 0 -github.com/muety/wakapi/services/alias.go:110.16,112.3 1 0 -github.com/muety/wakapi/services/alias.go:119.69,123.28 3 0 -github.com/muety/wakapi/services/alias.go:131.2,134.16 2 0 -github.com/muety/wakapi/services/alias.go:140.2,140.31 1 0 -github.com/muety/wakapi/services/alias.go:144.2,144.12 1 0 -github.com/muety/wakapi/services/alias.go:123.28,124.21 1 0 -github.com/muety/wakapi/services/alias.go:127.3,128.16 2 0 -github.com/muety/wakapi/services/alias.go:124.21,126.4 1 0 -github.com/muety/wakapi/services/alias.go:134.16,135.29 1 0 -github.com/muety/wakapi/services/alias.go:135.29,137.4 1 0 -github.com/muety/wakapi/services/alias.go:140.31,142.3 1 0 -github.com/muety/wakapi/services/alias.go:147.74,148.14 1 0 -github.com/muety/wakapi/services/alias.go:148.14,149.57 1 0 -github.com/muety/wakapi/services/alias.go:149.57,153.4 3 0 -github.com/muety/wakapi/services/alias.go:154.8,155.57 1 0 -github.com/muety/wakapi/services/alias.go:155.57,157.48 2 0 -github.com/muety/wakapi/services/alias.go:162.4,162.52 1 0 -github.com/muety/wakapi/services/alias.go:157.48,158.26 1 0 -github.com/muety/wakapi/services/alias.go:158.26,160.6 1 0 -github.com/muety/wakapi/services/alias.go:167.116,168.32 1 0 -github.com/muety/wakapi/services/alias.go:171.2,171.49 1 0 -github.com/muety/wakapi/services/alias.go:168.32,170.3 1 0 -github.com/muety/wakapi/services/alias.go:171.49,173.47 2 0 -github.com/muety/wakapi/services/alias.go:178.3,178.30 1 0 -github.com/muety/wakapi/services/alias.go:173.47,174.16 1 0 -github.com/muety/wakapi/services/alias.go:174.16,176.5 1 0 -github.com/muety/wakapi/services/alias.go:179.8,181.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:26.141,40.33 3 0 -github.com/muety/wakapi/services/heartbeat.go:48.2,48.12 1 0 -github.com/muety/wakapi/services/heartbeat.go:40.33,41.31 1 0 -github.com/muety/wakapi/services/heartbeat.go:41.31,45.4 3 0 -github.com/muety/wakapi/services/heartbeat.go:51.72,54.2 2 0 -github.com/muety/wakapi/services/heartbeat.go:56.80,57.26 1 0 -github.com/muety/wakapi/services/heartbeat.go:61.2,65.32 3 0 -github.com/muety/wakapi/services/heartbeat.go:74.2,75.16 2 0 -github.com/muety/wakapi/services/heartbeat.go:78.2,78.12 1 0 -github.com/muety/wakapi/services/heartbeat.go:57.26,59.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:65.32,66.31 1 0 -github.com/muety/wakapi/services/heartbeat.go:71.3,71.46 1 0 -github.com/muety/wakapi/services/heartbeat.go:66.31,70.4 3 0 -github.com/muety/wakapi/services/heartbeat.go:75.16,77.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:81.69,83.8 2 0 -github.com/muety/wakapi/services/heartbeat.go:86.2,87.16 2 0 -github.com/muety/wakapi/services/heartbeat.go:90.2,90.19 1 0 -github.com/muety/wakapi/services/heartbeat.go:83.8,85.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:87.16,89.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:93.76,96.8 3 0 -github.com/muety/wakapi/services/heartbeat.go:99.2,100.16 2 0 -github.com/muety/wakapi/services/heartbeat.go:103.2,103.19 1 0 -github.com/muety/wakapi/services/heartbeat.go:96.8,98.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:100.16,102.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:106.96,110.26 3 0 -github.com/muety/wakapi/services/heartbeat.go:120.2,121.16 2 0 -github.com/muety/wakapi/services/heartbeat.go:125.2,125.28 1 0 -github.com/muety/wakapi/services/heartbeat.go:131.2,131.24 1 0 -github.com/muety/wakapi/services/heartbeat.go:110.26,113.9 3 0 -github.com/muety/wakapi/services/heartbeat.go:113.9,115.4 1 0 -github.com/muety/wakapi/services/heartbeat.go:115.9,117.4 1 0 -github.com/muety/wakapi/services/heartbeat.go:121.16,123.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:125.28,129.3 3 0 -github.com/muety/wakapi/services/heartbeat.go:134.111,136.16 2 0 -github.com/muety/wakapi/services/heartbeat.go:139.2,139.43 1 0 -github.com/muety/wakapi/services/heartbeat.go:136.16,138.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:142.145,144.16 2 0 -github.com/muety/wakapi/services/heartbeat.go:147.2,147.43 1 0 -github.com/muety/wakapi/services/heartbeat.go:144.16,146.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:150.92,152.2 1 0 -github.com/muety/wakapi/services/heartbeat.go:154.116,156.2 1 0 -github.com/muety/wakapi/services/heartbeat.go:158.78,160.2 1 0 -github.com/muety/wakapi/services/heartbeat.go:162.104,164.54 2 0 -github.com/muety/wakapi/services/heartbeat.go:170.2,171.16 2 0 -github.com/muety/wakapi/services/heartbeat.go:175.2,176.28 2 0 -github.com/muety/wakapi/services/heartbeat.go:182.2,183.22 2 0 -github.com/muety/wakapi/services/heartbeat.go:164.54,168.3 3 0 -github.com/muety/wakapi/services/heartbeat.go:171.16,173.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:176.28,177.33 1 0 -github.com/muety/wakapi/services/heartbeat.go:177.33,179.4 1 0 -github.com/muety/wakapi/services/heartbeat.go:186.62,189.2 2 0 -github.com/muety/wakapi/services/heartbeat.go:191.68,194.2 2 0 -github.com/muety/wakapi/services/heartbeat.go:196.87,199.2 2 0 -github.com/muety/wakapi/services/heartbeat.go:201.116,203.16 2 0 -github.com/muety/wakapi/services/heartbeat.go:207.2,207.28 1 0 -github.com/muety/wakapi/services/heartbeat.go:211.2,211.24 1 0 -github.com/muety/wakapi/services/heartbeat.go:203.16,205.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:207.28,209.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:214.96,216.2 1 0 -github.com/muety/wakapi/services/heartbeat.go:218.107,220.55 2 0 -github.com/muety/wakapi/services/heartbeat.go:220.55,226.36 4 0 -github.com/muety/wakapi/services/heartbeat.go:226.36,231.4 2 0 -github.com/muety/wakapi/services/heartbeat.go:235.85,243.2 7 0 -github.com/muety/wakapi/services/heartbeat.go:245.74,246.32 1 0 -github.com/muety/wakapi/services/heartbeat.go:246.32,251.3 1 0 -github.com/muety/wakapi/services/heartbeat.go:254.72,256.2 1 0 -github.com/muety/wakapi/services/heartbeat.go:258.58,260.2 1 0 -github.com/muety/wakapi/services/heartbeat.go:262.60,264.2 1 0 -github.com/muety/wakapi/services/heartbeat.go:266.94,268.48 2 0 -github.com/muety/wakapi/services/heartbeat.go:274.2,274.18 1 0 -github.com/muety/wakapi/services/heartbeat.go:268.48,270.18 2 0 -github.com/muety/wakapi/services/heartbeat.go:270.18,272.4 1 0 github.com/muety/wakapi/services/misc.go:44.188,56.2 1 0 github.com/muety/wakapi/services/misc.go:58.36,60.95 2 0 github.com/muety/wakapi/services/misc.go:64.2,65.111 2 0 @@ -1622,34 +1125,6 @@ github.com/muety/wakapi/services/misc.go:280.16,282.3 1 0 github.com/muety/wakapi/services/misc.go:286.64,288.16 2 0 github.com/muety/wakapi/services/misc.go:291.2,291.25 1 0 github.com/muety/wakapi/services/misc.go:288.16,290.3 1 0 -github.com/muety/wakapi/services/report.go:33.122,46.2 2 0 -github.com/muety/wakapi/services/report.go:48.38,51.45 2 0 -github.com/muety/wakapi/services/report.go:69.2,69.49 1 0 -github.com/muety/wakapi/services/report.go:89.2,89.16 1 0 -github.com/muety/wakapi/services/report.go:51.45,52.46 1 0 -github.com/muety/wakapi/services/report.go:52.46,55.57 2 0 -github.com/muety/wakapi/services/report.go:60.4,60.58 1 0 -github.com/muety/wakapi/services/report.go:55.57,57.5 1 0 -github.com/muety/wakapi/services/report.go:60.58,63.5 2 0 -github.com/muety/wakapi/services/report.go:64.18,66.4 1 0 -github.com/muety/wakapi/services/report.go:69.49,72.17 2 0 -github.com/muety/wakapi/services/report.go:78.3,78.78 1 0 -github.com/muety/wakapi/services/report.go:83.3,84.27 2 0 -github.com/muety/wakapi/services/report.go:72.17,75.4 2 0 -github.com/muety/wakapi/services/report.go:78.78,80.4 1 0 -github.com/muety/wakapi/services/report.go:84.27,86.4 1 0 -github.com/muety/wakapi/services/report.go:89.16,91.3 1 0 -github.com/muety/wakapi/services/report.go:94.87,95.22 1 0 -github.com/muety/wakapi/services/report.go:100.2,106.16 5 0 -github.com/muety/wakapi/services/report.go:112.2,115.40 3 0 -github.com/muety/wakapi/services/report.go:127.2,135.65 2 0 -github.com/muety/wakapi/services/report.go:140.2,141.12 2 0 -github.com/muety/wakapi/services/report.go:95.22,98.3 2 0 -github.com/muety/wakapi/services/report.go:106.16,109.3 2 0 -github.com/muety/wakapi/services/report.go:115.40,118.17 3 0 -github.com/muety/wakapi/services/report.go:122.3,124.30 3 0 -github.com/muety/wakapi/services/report.go:118.17,120.9 2 0 -github.com/muety/wakapi/services/report.go:135.65,138.3 2 0 github.com/muety/wakapi/services/aggregation.go:31.142,41.2 1 0 github.com/muety/wakapi/services/aggregation.go:50.43,53.52 2 0 github.com/muety/wakapi/services/aggregation.go:53.52,54.80 1 0 @@ -1689,6 +1164,69 @@ github.com/muety/wakapi/services/aggregation.go:169.34,171.4 1 0 github.com/muety/wakapi/services/aggregation.go:177.79,180.27 3 0 github.com/muety/wakapi/services/aggregation.go:180.27,182.3 1 0 github.com/muety/wakapi/services/aggregation.go:185.34,188.2 2 0 +github.com/muety/wakapi/services/alias.go:19.77,24.2 1 1 +github.com/muety/wakapi/services/alias.go:28.60,29.43 1 1 +github.com/muety/wakapi/services/alias.go:32.2,32.14 1 1 +github.com/muety/wakapi/services/alias.go:29.43,31.3 1 1 +github.com/muety/wakapi/services/alias.go:35.62,37.16 2 1 +github.com/muety/wakapi/services/alias.go:40.2,40.12 1 1 +github.com/muety/wakapi/services/alias.go:37.16,39.3 1 1 +github.com/muety/wakapi/services/alias.go:43.59,44.51 1 1 +github.com/muety/wakapi/services/alias.go:44.51,46.3 1 0 +github.com/muety/wakapi/services/alias.go:49.76,50.32 1 0 +github.com/muety/wakapi/services/alias.go:53.2,53.49 1 0 +github.com/muety/wakapi/services/alias.go:50.32,52.3 1 0 +github.com/muety/wakapi/services/alias.go:53.49,55.3 1 0 +github.com/muety/wakapi/services/alias.go:55.8,57.3 1 0 +github.com/muety/wakapi/services/alias.go:60.102,61.38 1 0 +github.com/muety/wakapi/services/alias.go:64.2,64.39 1 0 +github.com/muety/wakapi/services/alias.go:61.38,63.3 1 0 +github.com/muety/wakapi/services/alias.go:67.113,68.38 1 0 +github.com/muety/wakapi/services/alias.go:71.2,71.39 1 0 +github.com/muety/wakapi/services/alias.go:68.38,70.3 1 0 +github.com/muety/wakapi/services/alias.go:74.108,75.32 1 1 +github.com/muety/wakapi/services/alias.go:79.2,79.49 1 1 +github.com/muety/wakapi/services/alias.go:87.2,87.19 1 1 +github.com/muety/wakapi/services/alias.go:75.32,77.3 1 1 +github.com/muety/wakapi/services/alias.go:79.49,80.47 1 1 +github.com/muety/wakapi/services/alias.go:80.47,81.49 1 1 +github.com/muety/wakapi/services/alias.go:81.49,83.5 1 1 +github.com/muety/wakapi/services/alias.go:90.77,92.16 2 0 +github.com/muety/wakapi/services/alias.go:96.2,100.20 3 0 +github.com/muety/wakapi/services/alias.go:92.16,94.3 1 0 +github.com/muety/wakapi/services/alias.go:103.60,104.24 1 0 +github.com/muety/wakapi/services/alias.go:107.2,110.16 2 0 +github.com/muety/wakapi/services/alias.go:114.2,116.12 2 0 +github.com/muety/wakapi/services/alias.go:104.24,106.3 1 0 +github.com/muety/wakapi/services/alias.go:110.16,112.3 1 0 +github.com/muety/wakapi/services/alias.go:119.69,123.28 3 0 +github.com/muety/wakapi/services/alias.go:131.2,134.16 2 0 +github.com/muety/wakapi/services/alias.go:140.2,140.31 1 0 +github.com/muety/wakapi/services/alias.go:144.2,144.12 1 0 +github.com/muety/wakapi/services/alias.go:123.28,124.21 1 0 +github.com/muety/wakapi/services/alias.go:127.3,128.16 2 0 +github.com/muety/wakapi/services/alias.go:124.21,126.4 1 0 +github.com/muety/wakapi/services/alias.go:134.16,135.29 1 0 +github.com/muety/wakapi/services/alias.go:135.29,137.4 1 0 +github.com/muety/wakapi/services/alias.go:140.31,142.3 1 0 +github.com/muety/wakapi/services/alias.go:147.74,148.14 1 0 +github.com/muety/wakapi/services/alias.go:148.14,149.57 1 0 +github.com/muety/wakapi/services/alias.go:149.57,153.4 3 0 +github.com/muety/wakapi/services/alias.go:154.8,155.57 1 0 +github.com/muety/wakapi/services/alias.go:155.57,157.48 2 0 +github.com/muety/wakapi/services/alias.go:162.4,162.52 1 0 +github.com/muety/wakapi/services/alias.go:157.48,158.26 1 0 +github.com/muety/wakapi/services/alias.go:158.26,160.6 1 0 +github.com/muety/wakapi/services/alias.go:167.116,168.32 1 0 +github.com/muety/wakapi/services/alias.go:171.2,171.49 1 0 +github.com/muety/wakapi/services/alias.go:168.32,170.3 1 0 +github.com/muety/wakapi/services/alias.go:171.49,173.47 2 0 +github.com/muety/wakapi/services/alias.go:178.3,178.30 1 0 +github.com/muety/wakapi/services/alias.go:173.47,174.16 1 0 +github.com/muety/wakapi/services/alias.go:174.16,176.5 1 0 +github.com/muety/wakapi/services/alias.go:179.8,181.3 1 0 +github.com/muety/wakapi/services/diagnostics.go:14.101,19.2 1 0 +github.com/muety/wakapi/services/diagnostics.go:21.101,24.2 2 0 github.com/muety/wakapi/services/key_value.go:14.89,19.2 1 0 github.com/muety/wakapi/services/key_value.go:21.83,23.2 1 0 github.com/muety/wakapi/services/key_value.go:25.90,27.2 1 0 @@ -1697,82 +1235,543 @@ github.com/muety/wakapi/services/key_value.go:37.2,37.11 1 0 github.com/muety/wakapi/services/key_value.go:31.16,36.3 1 0 github.com/muety/wakapi/services/key_value.go:40.72,42.2 1 0 github.com/muety/wakapi/services/key_value.go:44.60,46.2 1 0 -github.com/muety/wakapi/services/leaderboard.go:30.159,43.33 3 0 -github.com/muety/wakapi/services/leaderboard.go:67.2,67.12 1 0 -github.com/muety/wakapi/services/leaderboard.go:43.33,44.31 1 0 -github.com/muety/wakapi/services/leaderboard.go:44.31,50.18 3 0 -github.com/muety/wakapi/services/leaderboard.go:54.4,54.41 1 0 -github.com/muety/wakapi/services/leaderboard.go:50.18,52.5 1 0 -github.com/muety/wakapi/services/leaderboard.go:54.41,57.5 2 0 -github.com/muety/wakapi/services/leaderboard.go:57.10,57.48 1 0 -github.com/muety/wakapi/services/leaderboard.go:57.48,59.64 2 0 -github.com/muety/wakapi/services/leaderboard.go:62.5,62.22 1 0 -github.com/muety/wakapi/services/leaderboard.go:59.64,61.6 1 0 -github.com/muety/wakapi/services/leaderboard.go:70.43,73.21 2 0 -github.com/muety/wakapi/services/leaderboard.go:82.2,82.76 1 0 -github.com/muety/wakapi/services/leaderboard.go:73.21,75.17 2 0 -github.com/muety/wakapi/services/leaderboard.go:79.3,79.91 1 0 -github.com/muety/wakapi/services/leaderboard.go:75.17,78.4 2 0 -github.com/muety/wakapi/services/leaderboard.go:82.76,83.77 1 0 -github.com/muety/wakapi/services/leaderboard.go:83.77,85.4 1 0 -github.com/muety/wakapi/services/leaderboard.go:89.121,92.29 2 0 -github.com/muety/wakapi/services/leaderboard.go:127.2,129.12 3 0 -github.com/muety/wakapi/services/leaderboard.go:92.29,93.83 1 0 -github.com/muety/wakapi/services/leaderboard.go:98.3,99.17 2 0 -github.com/muety/wakapi/services/leaderboard.go:104.3,104.85 1 0 -github.com/muety/wakapi/services/leaderboard.go:109.3,109.25 1 0 -github.com/muety/wakapi/services/leaderboard.go:93.83,95.12 2 0 -github.com/muety/wakapi/services/leaderboard.go:99.17,101.12 2 0 -github.com/muety/wakapi/services/leaderboard.go:104.85,106.12 2 0 -github.com/muety/wakapi/services/leaderboard.go:109.25,111.18 2 0 -github.com/muety/wakapi/services/leaderboard.go:116.4,116.23 1 0 -github.com/muety/wakapi/services/leaderboard.go:120.4,120.60 1 0 -github.com/muety/wakapi/services/leaderboard.go:111.18,113.13 2 0 -github.com/muety/wakapi/services/leaderboard.go:116.23,117.13 1 0 -github.com/muety/wakapi/services/leaderboard.go:120.60,122.13 2 0 -github.com/muety/wakapi/services/leaderboard.go:132.77,135.2 2 0 -github.com/muety/wakapi/services/leaderboard.go:137.60,140.52 2 0 -github.com/muety/wakapi/services/leaderboard.go:144.2,145.16 2 0 -github.com/muety/wakapi/services/leaderboard.go:148.2,148.19 1 0 -github.com/muety/wakapi/services/leaderboard.go:140.52,142.3 1 0 -github.com/muety/wakapi/services/leaderboard.go:145.16,147.3 1 0 -github.com/muety/wakapi/services/leaderboard.go:151.153,153.2 1 0 -github.com/muety/wakapi/services/leaderboard.go:155.144,157.2 1 0 -github.com/muety/wakapi/services/leaderboard.go:159.174,162.52 2 0 -github.com/muety/wakapi/services/leaderboard.go:166.2,167.16 2 0 -github.com/muety/wakapi/services/leaderboard.go:171.2,171.18 1 0 -github.com/muety/wakapi/services/leaderboard.go:184.2,185.19 2 0 -github.com/muety/wakapi/services/leaderboard.go:162.52,164.3 1 0 -github.com/muety/wakapi/services/leaderboard.go:167.16,169.3 1 0 -github.com/muety/wakapi/services/leaderboard.go:171.18,173.17 2 0 -github.com/muety/wakapi/services/leaderboard.go:173.17,175.4 1 0 -github.com/muety/wakapi/services/leaderboard.go:175.9,176.31 1 0 -github.com/muety/wakapi/services/leaderboard.go:176.31,177.40 1 0 -github.com/muety/wakapi/services/leaderboard.go:177.40,179.6 1 0 -github.com/muety/wakapi/services/leaderboard.go:188.165,191.52 2 0 -github.com/muety/wakapi/services/leaderboard.go:195.2,196.16 2 0 -github.com/muety/wakapi/services/leaderboard.go:200.2,200.17 1 0 -github.com/muety/wakapi/services/leaderboard.go:211.2,212.19 2 0 -github.com/muety/wakapi/services/leaderboard.go:191.52,193.3 1 0 -github.com/muety/wakapi/services/leaderboard.go:196.16,198.3 1 0 -github.com/muety/wakapi/services/leaderboard.go:200.17,202.17 2 0 -github.com/muety/wakapi/services/leaderboard.go:202.17,204.4 1 0 -github.com/muety/wakapi/services/leaderboard.go:204.9,205.31 1 0 -github.com/muety/wakapi/services/leaderboard.go:205.31,207.5 1 0 -github.com/muety/wakapi/services/leaderboard.go:215.129,217.16 2 0 -github.com/muety/wakapi/services/leaderboard.go:221.2,222.16 2 0 -github.com/muety/wakapi/services/leaderboard.go:227.2,233.8 2 0 -github.com/muety/wakapi/services/leaderboard.go:217.16,219.3 1 0 -github.com/muety/wakapi/services/leaderboard.go:222.16,224.3 1 0 -github.com/muety/wakapi/services/leaderboard.go:236.151,238.16 2 0 -github.com/muety/wakapi/services/leaderboard.go:242.2,243.16 2 0 -github.com/muety/wakapi/services/leaderboard.go:247.2,250.42 3 0 -github.com/muety/wakapi/services/leaderboard.go:262.2,262.19 1 0 -github.com/muety/wakapi/services/leaderboard.go:238.16,240.3 1 0 -github.com/muety/wakapi/services/leaderboard.go:243.16,245.3 1 0 -github.com/muety/wakapi/services/leaderboard.go:250.42,260.3 2 0 -github.com/muety/wakapi/services/leaderboard.go:265.131,267.47 2 0 -github.com/muety/wakapi/services/leaderboard.go:270.2,270.23 1 0 -github.com/muety/wakapi/services/leaderboard.go:273.2,273.10 1 0 -github.com/muety/wakapi/services/leaderboard.go:267.47,269.3 1 0 -github.com/muety/wakapi/services/leaderboard.go:270.23,272.3 1 0 +github.com/muety/wakapi/services/duration.go:18.78,24.2 2 1 +github.com/muety/wakapi/services/duration.go:26.123,29.42 2 1 +github.com/muety/wakapi/services/duration.go:35.2,36.16 2 1 +github.com/muety/wakapi/services/duration.go:43.2,48.31 4 1 +github.com/muety/wakapi/services/duration.go:99.2,101.31 2 1 +github.com/muety/wakapi/services/duration.go:114.2,114.49 1 1 +github.com/muety/wakapi/services/duration.go:118.2,118.32 1 1 +github.com/muety/wakapi/services/duration.go:29.42,30.90 1 1 +github.com/muety/wakapi/services/duration.go:30.90,32.4 1 1 +github.com/muety/wakapi/services/duration.go:36.16,38.3 1 0 +github.com/muety/wakapi/services/duration.go:48.31,49.42 1 1 +github.com/muety/wakapi/services/duration.go:53.3,54.34 2 1 +github.com/muety/wakapi/services/duration.go:58.3,58.62 1 1 +github.com/muety/wakapi/services/duration.go:62.3,62.20 1 1 +github.com/muety/wakapi/services/duration.go:67.3,77.15 3 1 +github.com/muety/wakapi/services/duration.go:80.3,86.84 2 1 +github.com/muety/wakapi/services/duration.go:96.3,96.10 1 1 +github.com/muety/wakapi/services/duration.go:49.42,50.12 1 1 +github.com/muety/wakapi/services/duration.go:54.34,56.4 1 1 +github.com/muety/wakapi/services/duration.go:58.62,60.4 1 1 +github.com/muety/wakapi/services/duration.go:62.20,64.12 2 1 +github.com/muety/wakapi/services/duration.go:77.15,79.4 1 0 +github.com/muety/wakapi/services/duration.go:86.84,88.41 2 1 +github.com/muety/wakapi/services/duration.go:91.4,91.15 1 1 +github.com/muety/wakapi/services/duration.go:88.41,90.5 1 1 +github.com/muety/wakapi/services/duration.go:92.9,94.4 1 1 +github.com/muety/wakapi/services/duration.go:101.31,102.26 1 1 +github.com/muety/wakapi/services/duration.go:102.26,107.23 1 1 +github.com/muety/wakapi/services/duration.go:110.4,110.36 1 1 +github.com/muety/wakapi/services/duration.go:107.23,109.5 1 1 +github.com/muety/wakapi/services/duration.go:114.49,116.3 1 1 +github.com/muety/wakapi/services/heartbeat.go:26.141,40.33 3 0 +github.com/muety/wakapi/services/heartbeat.go:48.2,48.12 1 0 +github.com/muety/wakapi/services/heartbeat.go:40.33,41.31 1 0 +github.com/muety/wakapi/services/heartbeat.go:41.31,45.4 3 0 +github.com/muety/wakapi/services/heartbeat.go:51.72,54.2 2 0 +github.com/muety/wakapi/services/heartbeat.go:56.80,57.26 1 0 +github.com/muety/wakapi/services/heartbeat.go:61.2,65.32 3 0 +github.com/muety/wakapi/services/heartbeat.go:74.2,75.16 2 0 +github.com/muety/wakapi/services/heartbeat.go:78.2,78.12 1 0 +github.com/muety/wakapi/services/heartbeat.go:57.26,59.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:65.32,66.31 1 0 +github.com/muety/wakapi/services/heartbeat.go:71.3,71.46 1 0 +github.com/muety/wakapi/services/heartbeat.go:66.31,70.4 3 0 +github.com/muety/wakapi/services/heartbeat.go:75.16,77.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:81.69,83.8 2 0 +github.com/muety/wakapi/services/heartbeat.go:86.2,87.16 2 0 +github.com/muety/wakapi/services/heartbeat.go:90.2,90.19 1 0 +github.com/muety/wakapi/services/heartbeat.go:83.8,85.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:87.16,89.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:93.76,96.8 3 0 +github.com/muety/wakapi/services/heartbeat.go:99.2,100.16 2 0 +github.com/muety/wakapi/services/heartbeat.go:103.2,103.19 1 0 +github.com/muety/wakapi/services/heartbeat.go:96.8,98.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:100.16,102.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:106.96,110.26 3 0 +github.com/muety/wakapi/services/heartbeat.go:120.2,121.16 2 0 +github.com/muety/wakapi/services/heartbeat.go:125.2,125.28 1 0 +github.com/muety/wakapi/services/heartbeat.go:131.2,131.24 1 0 +github.com/muety/wakapi/services/heartbeat.go:110.26,113.9 3 0 +github.com/muety/wakapi/services/heartbeat.go:113.9,115.4 1 0 +github.com/muety/wakapi/services/heartbeat.go:115.9,117.4 1 0 +github.com/muety/wakapi/services/heartbeat.go:121.16,123.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:125.28,129.3 3 0 +github.com/muety/wakapi/services/heartbeat.go:134.111,136.16 2 0 +github.com/muety/wakapi/services/heartbeat.go:139.2,139.43 1 0 +github.com/muety/wakapi/services/heartbeat.go:136.16,138.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:142.145,144.16 2 0 +github.com/muety/wakapi/services/heartbeat.go:147.2,147.43 1 0 +github.com/muety/wakapi/services/heartbeat.go:144.16,146.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:150.92,152.2 1 0 +github.com/muety/wakapi/services/heartbeat.go:154.116,156.2 1 0 +github.com/muety/wakapi/services/heartbeat.go:158.78,160.2 1 0 +github.com/muety/wakapi/services/heartbeat.go:162.104,164.54 2 0 +github.com/muety/wakapi/services/heartbeat.go:170.2,171.16 2 0 +github.com/muety/wakapi/services/heartbeat.go:175.2,176.28 2 0 +github.com/muety/wakapi/services/heartbeat.go:182.2,183.22 2 0 +github.com/muety/wakapi/services/heartbeat.go:164.54,168.3 3 0 +github.com/muety/wakapi/services/heartbeat.go:171.16,173.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:176.28,177.33 1 0 +github.com/muety/wakapi/services/heartbeat.go:177.33,179.4 1 0 +github.com/muety/wakapi/services/heartbeat.go:186.62,189.2 2 0 +github.com/muety/wakapi/services/heartbeat.go:191.68,194.2 2 0 +github.com/muety/wakapi/services/heartbeat.go:196.87,199.2 2 0 +github.com/muety/wakapi/services/heartbeat.go:201.116,203.16 2 0 +github.com/muety/wakapi/services/heartbeat.go:207.2,207.28 1 0 +github.com/muety/wakapi/services/heartbeat.go:211.2,211.24 1 0 +github.com/muety/wakapi/services/heartbeat.go:203.16,205.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:207.28,209.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:214.96,216.2 1 0 +github.com/muety/wakapi/services/heartbeat.go:218.107,220.55 2 0 +github.com/muety/wakapi/services/heartbeat.go:220.55,226.36 4 0 +github.com/muety/wakapi/services/heartbeat.go:226.36,231.4 2 0 +github.com/muety/wakapi/services/heartbeat.go:235.85,243.2 7 0 +github.com/muety/wakapi/services/heartbeat.go:245.74,246.32 1 0 +github.com/muety/wakapi/services/heartbeat.go:246.32,251.3 1 0 +github.com/muety/wakapi/services/heartbeat.go:254.72,256.2 1 0 +github.com/muety/wakapi/services/heartbeat.go:258.58,260.2 1 0 +github.com/muety/wakapi/services/heartbeat.go:262.60,264.2 1 0 +github.com/muety/wakapi/services/heartbeat.go:266.94,268.48 2 0 +github.com/muety/wakapi/services/heartbeat.go:274.2,274.18 1 0 +github.com/muety/wakapi/services/heartbeat.go:268.48,270.18 2 0 +github.com/muety/wakapi/services/heartbeat.go:270.18,272.4 1 0 +github.com/muety/wakapi/services/project_label.go:21.111,28.2 1 0 +github.com/muety/wakapi/services/project_label.go:30.80,32.2 1 0 +github.com/muety/wakapi/services/project_label.go:34.90,35.51 1 0 +github.com/muety/wakapi/services/project_label.go:39.2,40.16 2 0 +github.com/muety/wakapi/services/project_label.go:43.2,44.20 2 0 +github.com/muety/wakapi/services/project_label.go:35.51,37.3 1 0 +github.com/muety/wakapi/services/project_label.go:40.16,42.3 1 0 +github.com/muety/wakapi/services/project_label.go:48.108,50.16 2 0 +github.com/muety/wakapi/services/project_label.go:53.2,53.112 1 0 +github.com/muety/wakapi/services/project_label.go:56.2,56.26 1 0 +github.com/muety/wakapi/services/project_label.go:50.16,52.3 1 0 +github.com/muety/wakapi/services/project_label.go:53.112,55.3 1 0 +github.com/muety/wakapi/services/project_label.go:60.116,62.16 2 0 +github.com/muety/wakapi/services/project_label.go:65.2,65.112 1 0 +github.com/muety/wakapi/services/project_label.go:68.2,68.26 1 0 +github.com/muety/wakapi/services/project_label.go:62.16,64.3 1 0 +github.com/muety/wakapi/services/project_label.go:65.112,67.3 1 0 +github.com/muety/wakapi/services/project_label.go:71.98,73.16 2 0 +github.com/muety/wakapi/services/project_label.go:77.2,79.20 3 0 +github.com/muety/wakapi/services/project_label.go:73.16,75.3 1 0 +github.com/muety/wakapi/services/project_label.go:82.74,83.24 1 0 +github.com/muety/wakapi/services/project_label.go:86.2,89.12 4 0 +github.com/muety/wakapi/services/project_label.go:83.24,85.3 1 0 +github.com/muety/wakapi/services/project_label.go:92.89,94.14 2 0 +github.com/muety/wakapi/services/project_label.go:97.2,100.4 1 0 +github.com/muety/wakapi/services/project_label.go:94.14,96.3 1 0 +github.com/muety/wakapi/services/report.go:33.122,46.2 2 0 +github.com/muety/wakapi/services/report.go:48.38,51.45 2 0 +github.com/muety/wakapi/services/report.go:69.2,69.49 1 0 +github.com/muety/wakapi/services/report.go:89.2,89.16 1 0 +github.com/muety/wakapi/services/report.go:51.45,52.46 1 0 +github.com/muety/wakapi/services/report.go:52.46,55.57 2 0 +github.com/muety/wakapi/services/report.go:60.4,60.58 1 0 +github.com/muety/wakapi/services/report.go:55.57,57.5 1 0 +github.com/muety/wakapi/services/report.go:60.58,63.5 2 0 +github.com/muety/wakapi/services/report.go:64.18,66.4 1 0 +github.com/muety/wakapi/services/report.go:69.49,72.17 2 0 +github.com/muety/wakapi/services/report.go:78.3,78.78 1 0 +github.com/muety/wakapi/services/report.go:83.3,84.27 2 0 +github.com/muety/wakapi/services/report.go:72.17,75.4 2 0 +github.com/muety/wakapi/services/report.go:78.78,80.4 1 0 +github.com/muety/wakapi/services/report.go:84.27,86.4 1 0 +github.com/muety/wakapi/services/report.go:89.16,91.3 1 0 +github.com/muety/wakapi/services/report.go:94.87,95.22 1 0 +github.com/muety/wakapi/services/report.go:100.2,106.16 5 0 +github.com/muety/wakapi/services/report.go:112.2,115.40 3 0 +github.com/muety/wakapi/services/report.go:127.2,135.65 2 0 +github.com/muety/wakapi/services/report.go:140.2,141.12 2 0 +github.com/muety/wakapi/services/report.go:95.22,98.3 2 0 +github.com/muety/wakapi/services/report.go:106.16,109.3 2 0 +github.com/muety/wakapi/services/report.go:115.40,118.17 3 0 +github.com/muety/wakapi/services/report.go:122.3,124.30 3 0 +github.com/muety/wakapi/services/report.go:118.17,120.9 2 0 +github.com/muety/wakapi/services/report.go:135.65,138.3 2 0 +github.com/muety/wakapi/models/language_mapping.go:11.42,13.2 1 0 +github.com/muety/wakapi/models/language_mapping.go:15.51,17.2 1 0 +github.com/muety/wakapi/models/language_mapping.go:19.52,21.2 1 0 +github.com/muety/wakapi/models/leaderboard.go:28.73,30.2 1 0 +github.com/muety/wakapi/models/leaderboard.go:34.56,35.103 1 0 +github.com/muety/wakapi/models/leaderboard.go:35.103,37.3 1 0 +github.com/muety/wakapi/models/leaderboard.go:37.13,39.3 1 0 +github.com/muety/wakapi/models/leaderboard.go:42.63,43.29 1 0 +github.com/muety/wakapi/models/leaderboard.go:43.29,45.3 1 0 +github.com/muety/wakapi/models/leaderboard.go:48.41,49.123 1 0 +github.com/muety/wakapi/models/leaderboard.go:49.123,51.3 1 0 +github.com/muety/wakapi/models/leaderboard.go:54.50,56.2 1 0 +github.com/muety/wakapi/models/leaderboard.go:58.65,59.95 1 0 +github.com/muety/wakapi/models/leaderboard.go:59.95,61.3 1 0 +github.com/muety/wakapi/models/leaderboard.go:64.49,72.25 3 0 +github.com/muety/wakapi/models/leaderboard.go:83.2,83.129 1 0 +github.com/muety/wakapi/models/leaderboard.go:86.2,86.67 1 0 +github.com/muety/wakapi/models/leaderboard.go:90.2,90.79 1 0 +github.com/muety/wakapi/models/leaderboard.go:72.25,73.58 1 0 +github.com/muety/wakapi/models/leaderboard.go:76.3,77.38 2 0 +github.com/muety/wakapi/models/leaderboard.go:80.3,80.40 1 0 +github.com/muety/wakapi/models/leaderboard.go:73.58,74.12 1 0 +github.com/muety/wakapi/models/leaderboard.go:77.38,79.4 1 0 +github.com/muety/wakapi/models/leaderboard.go:83.129,85.3 1 0 +github.com/muety/wakapi/models/leaderboard.go:86.67,88.3 1 0 +github.com/muety/wakapi/models/leaderboard.go:90.79,92.3 1 0 +github.com/muety/wakapi/models/leaderboard.go:95.70,96.107 1 0 +github.com/muety/wakapi/models/leaderboard.go:96.107,98.3 1 0 +github.com/muety/wakapi/models/leaderboard.go:101.45,103.25 2 0 +github.com/muety/wakapi/models/leaderboard.go:108.2,108.19 1 0 +github.com/muety/wakapi/models/leaderboard.go:103.25,104.43 1 0 +github.com/muety/wakapi/models/leaderboard.go:104.43,106.4 1 0 +github.com/muety/wakapi/models/mail.go:23.44,27.2 3 0 +github.com/muety/wakapi/models/mail.go:29.44,33.2 3 0 +github.com/muety/wakapi/models/mail.go:35.34,36.18 1 0 +github.com/muety/wakapi/models/mail.go:39.2,39.21 1 0 +github.com/muety/wakapi/models/mail.go:42.2,42.23 1 0 +github.com/muety/wakapi/models/mail.go:45.2,45.10 1 0 +github.com/muety/wakapi/models/mail.go:36.18,38.3 1 0 +github.com/muety/wakapi/models/mail.go:39.21,41.3 1 0 +github.com/muety/wakapi/models/mail.go:42.23,44.3 1 0 +github.com/muety/wakapi/models/mail.go:48.32,67.2 1 0 +github.com/muety/wakapi/models/mail.go:69.41,71.2 1 0 +github.com/muety/wakapi/models/models.go:3.14,5.2 0 1 +github.com/muety/wakapi/models/heartbeat.go:34.34,36.2 1 1 +github.com/muety/wakapi/models/heartbeat.go:38.55,41.2 2 0 +github.com/muety/wakapi/models/heartbeat.go:43.43,49.80 1 0 +github.com/muety/wakapi/models/heartbeat.go:53.2,56.10 3 0 +github.com/muety/wakapi/models/heartbeat.go:49.80,51.3 1 0 +github.com/muety/wakapi/models/heartbeat.go:59.65,61.46 2 1 +github.com/muety/wakapi/models/heartbeat.go:61.46,62.108 1 1 +github.com/muety/wakapi/models/heartbeat.go:62.108,65.4 2 1 +github.com/muety/wakapi/models/heartbeat.go:69.50,70.11 1 1 +github.com/muety/wakapi/models/heartbeat.go:87.2,87.15 1 1 +github.com/muety/wakapi/models/heartbeat.go:91.2,91.12 1 1 +github.com/muety/wakapi/models/heartbeat.go:71.22,72.18 1 1 +github.com/muety/wakapi/models/heartbeat.go:73.21,74.17 1 1 +github.com/muety/wakapi/models/heartbeat.go:75.23,76.19 1 1 +github.com/muety/wakapi/models/heartbeat.go:77.17,78.26 1 1 +github.com/muety/wakapi/models/heartbeat.go:79.22,80.18 1 1 +github.com/muety/wakapi/models/heartbeat.go:81.21,82.17 1 0 +github.com/muety/wakapi/models/heartbeat.go:83.21,84.17 1 0 +github.com/muety/wakapi/models/heartbeat.go:87.15,89.3 1 1 +github.com/muety/wakapi/models/heartbeat.go:94.37,110.2 1 0 +github.com/muety/wakapi/models/heartbeat.go:118.41,120.16 2 1 +github.com/muety/wakapi/models/heartbeat.go:123.2,124.10 2 1 +github.com/muety/wakapi/models/heartbeat.go:120.16,122.3 1 0 +github.com/muety/wakapi/models/heartbeat.go:127.38,137.2 1 0 +github.com/muety/wakapi/models/heartbeats.go:7.31,9.2 1 0 +github.com/muety/wakapi/models/heartbeats.go:11.41,13.2 1 0 +github.com/muety/wakapi/models/heartbeats.go:15.36,17.2 1 0 +github.com/muety/wakapi/models/heartbeats.go:19.43,22.2 2 0 +github.com/muety/wakapi/models/heartbeats.go:24.41,26.18 1 0 +github.com/muety/wakapi/models/heartbeats.go:29.2,29.16 1 0 +github.com/muety/wakapi/models/heartbeats.go:26.18,28.3 1 0 +github.com/muety/wakapi/models/heartbeats.go:32.40,34.18 1 0 +github.com/muety/wakapi/models/heartbeats.go:37.2,37.24 1 0 +github.com/muety/wakapi/models/heartbeats.go:34.18,36.3 1 0 +github.com/muety/wakapi/models/shared.go:38.52,40.2 1 0 +github.com/muety/wakapi/models/shared.go:42.52,45.16 3 0 +github.com/muety/wakapi/models/shared.go:48.2,50.12 3 0 +github.com/muety/wakapi/models/shared.go:45.16,47.3 1 0 +github.com/muety/wakapi/models/shared.go:53.52,59.22 2 0 +github.com/muety/wakapi/models/shared.go:74.2,77.12 3 0 +github.com/muety/wakapi/models/shared.go:60.14,64.17 2 0 +github.com/muety/wakapi/models/shared.go:67.17,69.8 2 0 +github.com/muety/wakapi/models/shared.go:70.10,71.64 1 0 +github.com/muety/wakapi/models/shared.go:64.17,66.4 1 0 +github.com/muety/wakapi/models/shared.go:80.51,83.2 2 0 +github.com/muety/wakapi/models/shared.go:85.45,87.2 1 1 +github.com/muety/wakapi/models/shared.go:89.37,91.2 1 0 +github.com/muety/wakapi/models/shared.go:93.35,95.2 1 1 +github.com/muety/wakapi/models/shared.go:97.34,99.2 1 0 +github.com/muety/wakapi/models/user.go:13.13,15.2 1 1 +github.com/muety/wakapi/models/user.go:90.34,92.2 1 0 +github.com/muety/wakapi/models/user.go:94.36,95.22 1 1 +github.com/muety/wakapi/models/user.go:98.2,99.16 2 1 +github.com/muety/wakapi/models/user.go:102.2,102.11 1 1 +github.com/muety/wakapi/models/user.go:95.22,97.3 1 1 +github.com/muety/wakapi/models/user.go:99.16,101.3 1 0 +github.com/muety/wakapi/models/user.go:107.41,110.2 2 1 +github.com/muety/wakapi/models/user.go:112.53,115.54 3 0 +github.com/muety/wakapi/models/user.go:118.2,118.51 1 0 +github.com/muety/wakapi/models/user.go:121.2,121.20 1 0 +github.com/muety/wakapi/models/user.go:115.54,117.3 1 0 +github.com/muety/wakapi/models/user.go:118.51,120.3 1 0 +github.com/muety/wakapi/models/user.go:125.52,126.28 1 0 +github.com/muety/wakapi/models/user.go:129.2,129.17 1 0 +github.com/muety/wakapi/models/user.go:126.28,128.3 1 0 +github.com/muety/wakapi/models/user.go:133.45,135.2 1 1 +github.com/muety/wakapi/models/user.go:137.51,139.2 1 1 +github.com/muety/wakapi/models/user.go:145.65,147.32 2 0 +github.com/muety/wakapi/models/user.go:150.2,150.30 1 0 +github.com/muety/wakapi/models/user.go:153.2,154.24 2 0 +github.com/muety/wakapi/models/user.go:147.32,149.3 1 0 +github.com/muety/wakapi/models/user.go:150.30,152.3 1 0 +github.com/muety/wakapi/models/user.go:157.39,159.55 2 1 +github.com/muety/wakapi/models/user.go:163.2,163.51 1 1 +github.com/muety/wakapi/models/user.go:159.55,161.3 1 1 +github.com/muety/wakapi/models/user.go:166.43,169.2 1 0 +github.com/muety/wakapi/models/user.go:171.45,174.2 1 0 +github.com/muety/wakapi/models/user.go:176.33,181.2 1 0 +github.com/muety/wakapi/models/user.go:183.41,185.2 1 0 +github.com/muety/wakapi/models/user.go:187.45,189.2 1 0 +github.com/muety/wakapi/models/user.go:191.45,193.2 1 0 +github.com/muety/wakapi/models/user.go:196.39,198.2 1 0 +github.com/muety/wakapi/models/user.go:200.39,203.2 2 0 +github.com/muety/wakapi/models/duration.go:27.75,28.23 1 0 +github.com/muety/wakapi/models/duration.go:31.2,35.35 1 0 +github.com/muety/wakapi/models/duration.go:38.2,38.18 1 0 +github.com/muety/wakapi/models/duration.go:28.23,30.3 1 0 +github.com/muety/wakapi/models/duration.go:35.35,37.3 1 0 +github.com/muety/wakapi/models/duration.go:41.55,56.2 2 0 +github.com/muety/wakapi/models/duration.go:58.50,61.2 2 0 +github.com/muety/wakapi/models/duration.go:63.39,65.16 2 0 +github.com/muety/wakapi/models/duration.go:68.2,69.10 2 0 +github.com/muety/wakapi/models/duration.go:65.16,67.3 1 0 +github.com/muety/wakapi/models/duration.go:72.49,73.11 1 0 +github.com/muety/wakapi/models/duration.go:90.2,90.15 1 0 +github.com/muety/wakapi/models/duration.go:94.2,94.12 1 0 +github.com/muety/wakapi/models/duration.go:74.22,75.18 1 0 +github.com/muety/wakapi/models/duration.go:76.21,77.17 1 0 +github.com/muety/wakapi/models/duration.go:78.23,79.19 1 0 +github.com/muety/wakapi/models/duration.go:80.17,81.26 1 0 +github.com/muety/wakapi/models/duration.go:82.22,83.18 1 0 +github.com/muety/wakapi/models/duration.go:84.21,85.17 1 0 +github.com/muety/wakapi/models/duration.go:86.21,87.17 1 0 +github.com/muety/wakapi/models/duration.go:90.15,92.3 1 0 +github.com/muety/wakapi/models/mail_address.go:18.13,21.2 2 1 +github.com/muety/wakapi/models/mail_address.go:27.38,29.2 1 0 +github.com/muety/wakapi/models/mail_address.go:31.35,33.21 2 1 +github.com/muety/wakapi/models/mail_address.go:39.2,39.11 1 1 +github.com/muety/wakapi/models/mail_address.go:33.21,34.21 1 1 +github.com/muety/wakapi/models/mail_address.go:37.3,37.18 1 1 +github.com/muety/wakapi/models/mail_address.go:34.21,36.4 1 1 +github.com/muety/wakapi/models/mail_address.go:42.38,44.21 2 0 +github.com/muety/wakapi/models/mail_address.go:47.2,47.17 1 0 +github.com/muety/wakapi/models/mail_address.go:44.21,46.3 1 0 +github.com/muety/wakapi/models/mail_address.go:50.35,52.2 1 1 +github.com/muety/wakapi/models/mail_address.go:54.43,56.22 2 0 +github.com/muety/wakapi/models/mail_address.go:59.2,59.12 1 0 +github.com/muety/wakapi/models/mail_address.go:56.22,58.3 1 0 +github.com/muety/wakapi/models/mail_address.go:62.46,64.22 2 1 +github.com/muety/wakapi/models/mail_address.go:67.2,67.12 1 1 +github.com/muety/wakapi/models/mail_address.go:64.22,66.3 1 1 +github.com/muety/wakapi/models/mail_address.go:70.40,71.22 1 1 +github.com/muety/wakapi/models/mail_address.go:76.2,76.13 1 1 +github.com/muety/wakapi/models/mail_address.go:71.22,72.17 1 1 +github.com/muety/wakapi/models/mail_address.go:72.17,74.4 1 1 +github.com/muety/wakapi/models/interval.go:41.47,42.23 1 0 +github.com/muety/wakapi/models/interval.go:47.2,47.14 1 0 +github.com/muety/wakapi/models/interval.go:42.23,43.13 1 0 +github.com/muety/wakapi/models/interval.go:43.13,45.4 1 0 +github.com/muety/wakapi/models/summary.go:66.29,68.2 1 1 +github.com/muety/wakapi/models/summary.go:70.35,72.2 1 0 +github.com/muety/wakapi/models/summary.go:74.38,76.2 1 0 +github.com/muety/wakapi/models/summary.go:78.37,88.2 9 1 +github.com/muety/wakapi/models/summary.go:90.35,92.2 1 1 +github.com/muety/wakapi/models/summary.go:94.57,105.2 1 1 +github.com/muety/wakapi/models/summary.go:107.64,108.21 1 1 +github.com/muety/wakapi/models/summary.go:126.2,126.12 1 0 +github.com/muety/wakapi/models/summary.go:109.22,110.21 1 1 +github.com/muety/wakapi/models/summary.go:111.23,112.22 1 1 +github.com/muety/wakapi/models/summary.go:113.21,114.20 1 1 +github.com/muety/wakapi/models/summary.go:115.17,116.29 1 1 +github.com/muety/wakapi/models/summary.go:117.22,118.21 1 1 +github.com/muety/wakapi/models/summary.go:119.20,120.19 1 1 +github.com/muety/wakapi/models/summary.go:121.21,122.21 1 1 +github.com/muety/wakapi/models/summary.go:123.21,124.21 1 1 +github.com/muety/wakapi/models/summary.go:129.59,130.21 1 1 +github.com/muety/wakapi/models/summary.go:134.2,134.35 1 1 +github.com/muety/wakapi/models/summary.go:140.2,140.10 1 1 +github.com/muety/wakapi/models/summary.go:130.21,132.3 1 1 +github.com/muety/wakapi/models/summary.go:134.35,135.41 1 1 +github.com/muety/wakapi/models/summary.go:135.41,137.4 1 1 +github.com/muety/wakapi/models/summary.go:156.33,161.26 4 1 +github.com/muety/wakapi/models/summary.go:168.2,168.37 1 1 +github.com/muety/wakapi/models/summary.go:173.2,174.16 2 1 +github.com/muety/wakapi/models/summary.go:177.2,177.33 1 1 +github.com/muety/wakapi/models/summary.go:161.26,162.30 1 1 +github.com/muety/wakapi/models/summary.go:162.30,164.4 1 1 +github.com/muety/wakapi/models/summary.go:168.37,170.3 1 0 +github.com/muety/wakapi/models/summary.go:174.16,176.3 1 0 +github.com/muety/wakapi/models/summary.go:177.33,179.3 1 1 +github.com/muety/wakapi/models/summary.go:183.56,189.28 5 1 +github.com/muety/wakapi/models/summary.go:193.2,194.42 2 1 +github.com/muety/wakapi/models/summary.go:201.2,202.15 2 1 +github.com/muety/wakapi/models/summary.go:189.28,191.3 1 1 +github.com/muety/wakapi/models/summary.go:194.42,195.22 1 0 +github.com/muety/wakapi/models/summary.go:195.22,197.9 2 0 +github.com/muety/wakapi/models/summary.go:202.15,203.28 1 1 +github.com/muety/wakapi/models/summary.go:203.28,205.4 1 0 +github.com/muety/wakapi/models/summary.go:205.9,211.4 1 1 +github.com/muety/wakapi/models/summary.go:215.45,220.16 4 1 +github.com/muety/wakapi/models/summary.go:223.2,223.39 1 1 +github.com/muety/wakapi/models/summary.go:227.2,227.30 1 1 +github.com/muety/wakapi/models/summary.go:220.16,222.3 1 0 +github.com/muety/wakapi/models/summary.go:223.39,225.3 1 1 +github.com/muety/wakapi/models/summary.go:230.73,232.55 2 1 +github.com/muety/wakapi/models/summary.go:237.2,237.16 1 1 +github.com/muety/wakapi/models/summary.go:232.55,233.31 1 1 +github.com/muety/wakapi/models/summary.go:233.31,235.4 1 1 +github.com/muety/wakapi/models/summary.go:240.88,242.55 2 1 +github.com/muety/wakapi/models/summary.go:250.2,250.16 1 1 +github.com/muety/wakapi/models/summary.go:242.55,243.31 1 1 +github.com/muety/wakapi/models/summary.go:243.31,244.23 1 1 +github.com/muety/wakapi/models/summary.go:247.4,247.46 1 1 +github.com/muety/wakapi/models/summary.go:244.23,245.13 1 1 +github.com/muety/wakapi/models/summary.go:253.73,255.34 2 1 +github.com/muety/wakapi/models/summary.go:258.2,258.14 1 1 +github.com/muety/wakapi/models/summary.go:255.34,257.3 1 1 +github.com/muety/wakapi/models/summary.go:261.56,264.55 3 0 +github.com/muety/wakapi/models/summary.go:271.2,271.12 1 0 +github.com/muety/wakapi/models/summary.go:264.55,265.31 1 0 +github.com/muety/wakapi/models/summary.go:265.31,266.44 1 0 +github.com/muety/wakapi/models/summary.go:266.44,268.5 1 0 +github.com/muety/wakapi/models/summary.go:274.58,276.16 2 0 +github.com/muety/wakapi/models/summary.go:279.2,279.16 1 0 +github.com/muety/wakapi/models/summary.go:276.16,278.3 1 0 +github.com/muety/wakapi/models/summary.go:282.71,283.63 1 1 +github.com/muety/wakapi/models/summary.go:327.2,336.10 8 1 +github.com/muety/wakapi/models/summary.go:283.63,284.20 1 1 +github.com/muety/wakapi/models/summary.go:288.3,290.45 2 1 +github.com/muety/wakapi/models/summary.go:299.3,299.31 1 1 +github.com/muety/wakapi/models/summary.go:306.3,306.31 1 1 +github.com/muety/wakapi/models/summary.go:323.3,323.16 1 1 +github.com/muety/wakapi/models/summary.go:284.20,286.4 1 1 +github.com/muety/wakapi/models/summary.go:290.45,291.32 1 1 +github.com/muety/wakapi/models/summary.go:296.4,296.14 1 1 +github.com/muety/wakapi/models/summary.go:291.32,292.24 1 1 +github.com/muety/wakapi/models/summary.go:292.24,294.6 1 1 +github.com/muety/wakapi/models/summary.go:299.31,301.60 1 1 +github.com/muety/wakapi/models/summary.go:301.60,303.5 1 1 +github.com/muety/wakapi/models/summary.go:306.31,308.60 1 1 +github.com/muety/wakapi/models/summary.go:308.60,309.55 1 1 +github.com/muety/wakapi/models/summary.go:309.55,311.6 1 1 +github.com/muety/wakapi/models/summary.go:311.11,319.6 1 1 +github.com/muety/wakapi/models/summary.go:339.57,340.30 1 1 +github.com/muety/wakapi/models/summary.go:345.2,345.43 1 0 +github.com/muety/wakapi/models/summary.go:340.30,341.28 1 1 +github.com/muety/wakapi/models/summary.go:341.28,343.4 1 1 +github.com/muety/wakapi/models/summary.go:348.43,350.2 1 0 +github.com/muety/wakapi/models/summary.go:352.49,353.21 1 0 +github.com/muety/wakapi/models/summary.go:356.2,357.54 2 0 +github.com/muety/wakapi/models/summary.go:353.21,355.3 1 0 +github.com/muety/wakapi/models/summary.go:360.51,361.27 1 0 +github.com/muety/wakapi/models/summary.go:364.2,365.19 2 0 +github.com/muety/wakapi/models/summary.go:361.27,363.3 1 0 +github.com/muety/wakapi/models/summary.go:368.50,372.2 1 1 +github.com/muety/wakapi/models/summary.go:374.33,376.2 1 1 +github.com/muety/wakapi/models/summary.go:378.43,380.2 1 1 +github.com/muety/wakapi/models/summary.go:382.38,384.2 1 1 +github.com/muety/wakapi/models/durations.go:7.30,9.2 1 0 +github.com/muety/wakapi/models/durations.go:11.40,13.2 1 0 +github.com/muety/wakapi/models/durations.go:15.35,17.2 1 0 +github.com/muety/wakapi/models/durations.go:19.45,21.22 2 0 +github.com/muety/wakapi/models/durations.go:24.2,24.14 1 0 +github.com/muety/wakapi/models/durations.go:21.22,23.3 1 0 +github.com/muety/wakapi/models/durations.go:27.39,30.2 2 0 +github.com/muety/wakapi/models/durations.go:32.39,34.18 1 0 +github.com/muety/wakapi/models/durations.go:37.2,37.16 1 0 +github.com/muety/wakapi/models/durations.go:34.18,36.3 1 0 +github.com/muety/wakapi/models/durations.go:40.38,42.18 1 0 +github.com/muety/wakapi/models/durations.go:45.2,45.24 1 0 +github.com/muety/wakapi/models/durations.go:42.18,44.3 1 0 +github.com/muety/wakapi/models/project_label.go:14.39,16.2 1 0 +github.com/muety/wakapi/models/alias.go:18.32,20.2 1 0 +github.com/muety/wakapi/models/alias.go:22.37,23.35 1 0 +github.com/muety/wakapi/models/alias.go:28.2,28.14 1 0 +github.com/muety/wakapi/models/alias.go:23.35,24.18 1 0 +github.com/muety/wakapi/models/alias.go:24.18,26.4 1 0 +github.com/muety/wakapi/models/filters.go:22.33,24.2 1 1 +github.com/muety/wakapi/models/filters.go:26.48,27.22 1 1 +github.com/muety/wakapi/models/filters.go:32.2,32.14 1 1 +github.com/muety/wakapi/models/filters.go:27.22,28.48 1 1 +github.com/muety/wakapi/models/filters.go:28.48,30.4 1 1 +github.com/muety/wakapi/models/filters.go:40.56,42.2 1 1 +github.com/muety/wakapi/models/filters.go:44.66,47.2 2 1 +github.com/muety/wakapi/models/filters.go:49.59,51.2 1 1 +github.com/muety/wakapi/models/filters.go:53.70,54.16 1 1 +github.com/muety/wakapi/models/filters.go:72.2,72.10 1 1 +github.com/muety/wakapi/models/filters.go:55.22,56.41 1 1 +github.com/muety/wakapi/models/filters.go:57.17,58.31 1 0 +github.com/muety/wakapi/models/filters.go:59.23,60.43 1 1 +github.com/muety/wakapi/models/filters.go:61.21,62.39 1 0 +github.com/muety/wakapi/models/filters.go:63.22,64.41 1 0 +github.com/muety/wakapi/models/filters.go:65.20,66.37 1 1 +github.com/muety/wakapi/models/filters.go:67.21,68.39 1 0 +github.com/muety/wakapi/models/filters.go:69.21,70.39 1 0 +github.com/muety/wakapi/models/filters.go:75.49,76.44 1 1 +github.com/muety/wakapi/models/filters.go:93.2,93.29 1 1 +github.com/muety/wakapi/models/filters.go:76.44,78.3 1 1 +github.com/muety/wakapi/models/filters.go:78.8,78.41 1 1 +github.com/muety/wakapi/models/filters.go:78.41,80.3 1 0 +github.com/muety/wakapi/models/filters.go:80.8,80.53 1 1 +github.com/muety/wakapi/models/filters.go:80.53,82.3 1 1 +github.com/muety/wakapi/models/filters.go:82.8,82.49 1 1 +github.com/muety/wakapi/models/filters.go:82.49,84.3 1 0 +github.com/muety/wakapi/models/filters.go:84.8,84.51 1 1 +github.com/muety/wakapi/models/filters.go:84.51,86.3 1 0 +github.com/muety/wakapi/models/filters.go:86.8,86.47 1 1 +github.com/muety/wakapi/models/filters.go:86.47,88.3 1 0 +github.com/muety/wakapi/models/filters.go:88.8,88.49 1 1 +github.com/muety/wakapi/models/filters.go:88.49,90.3 1 0 +github.com/muety/wakapi/models/filters.go:90.8,90.49 1 1 +github.com/muety/wakapi/models/filters.go:90.49,92.3 1 0 +github.com/muety/wakapi/models/filters.go:96.46,97.30 1 1 +github.com/muety/wakapi/models/filters.go:100.2,100.66 1 0 +github.com/muety/wakapi/models/filters.go:97.30,99.3 1 1 +github.com/muety/wakapi/models/filters.go:103.34,106.2 2 1 +github.com/muety/wakapi/models/filters.go:108.31,110.51 2 0 +github.com/muety/wakapi/models/filters.go:113.2,113.14 1 0 +github.com/muety/wakapi/models/filters.go:110.51,112.3 1 0 +github.com/muety/wakapi/models/filters.go:116.51,118.2 1 0 +github.com/muety/wakapi/models/filters.go:120.37,122.51 2 0 +github.com/muety/wakapi/models/filters.go:127.2,127.14 1 0 +github.com/muety/wakapi/models/filters.go:122.51,123.37 1 0 +github.com/muety/wakapi/models/filters.go:123.37,125.4 1 0 +github.com/muety/wakapi/models/filters.go:130.59,131.18 1 0 +github.com/muety/wakapi/models/filters.go:132.22,133.20 1 0 +github.com/muety/wakapi/models/filters.go:134.23,135.21 1 0 +github.com/muety/wakapi/models/filters.go:136.21,137.19 1 0 +github.com/muety/wakapi/models/filters.go:138.17,139.15 1 0 +github.com/muety/wakapi/models/filters.go:140.22,141.20 1 0 +github.com/muety/wakapi/models/filters.go:142.20,143.18 1 0 +github.com/muety/wakapi/models/filters.go:144.21,145.19 1 0 +github.com/muety/wakapi/models/filters.go:146.21,147.19 1 0 +github.com/muety/wakapi/models/filters.go:148.10,149.21 1 0 +github.com/muety/wakapi/models/filters.go:153.33,155.16 2 0 +github.com/muety/wakapi/models/filters.go:158.2,158.32 1 0 +github.com/muety/wakapi/models/filters.go:155.16,157.3 1 0 +github.com/muety/wakapi/models/filters.go:161.44,167.2 1 1 +github.com/muety/wakapi/models/filters.go:170.70,171.22 1 1 +github.com/muety/wakapi/models/filters.go:179.2,179.17 1 1 +github.com/muety/wakapi/models/filters.go:187.2,187.23 1 1 +github.com/muety/wakapi/models/filters.go:195.2,195.21 1 1 +github.com/muety/wakapi/models/filters.go:203.2,203.22 1 1 +github.com/muety/wakapi/models/filters.go:211.2,211.21 1 1 +github.com/muety/wakapi/models/filters.go:220.2,220.10 1 1 +github.com/muety/wakapi/models/filters.go:171.22,173.31 2 1 +github.com/muety/wakapi/models/filters.go:177.3,177.22 1 1 +github.com/muety/wakapi/models/filters.go:173.31,176.4 2 1 +github.com/muety/wakapi/models/filters.go:179.17,181.26 2 0 +github.com/muety/wakapi/models/filters.go:185.3,185.17 1 0 +github.com/muety/wakapi/models/filters.go:181.26,184.4 2 0 +github.com/muety/wakapi/models/filters.go:187.23,189.32 2 1 +github.com/muety/wakapi/models/filters.go:193.3,193.23 1 1 +github.com/muety/wakapi/models/filters.go:189.32,192.4 2 1 +github.com/muety/wakapi/models/filters.go:195.21,197.30 2 0 +github.com/muety/wakapi/models/filters.go:201.3,201.21 1 0 +github.com/muety/wakapi/models/filters.go:197.30,200.4 2 0 +github.com/muety/wakapi/models/filters.go:203.22,205.31 2 0 +github.com/muety/wakapi/models/filters.go:209.3,209.22 1 0 +github.com/muety/wakapi/models/filters.go:205.31,208.4 2 0 +github.com/muety/wakapi/models/filters.go:211.21,213.30 2 0 +github.com/muety/wakapi/models/filters.go:217.3,217.21 1 0 +github.com/muety/wakapi/models/filters.go:213.30,216.4 2 0 +github.com/muety/wakapi/models/filters.go:223.83,224.41 1 1 +github.com/muety/wakapi/models/filters.go:227.2,227.28 1 1 +github.com/muety/wakapi/models/filters.go:230.2,230.10 1 1 +github.com/muety/wakapi/models/filters.go:224.41,226.3 1 0 +github.com/muety/wakapi/models/filters.go:227.28,229.3 1 1 +github.com/muety/wakapi/models/filters.go:233.43,235.2 1 0 diff --git a/models/compat/wakatime/v1/data_dump.go b/models/compat/wakatime/v1/data_dump.go new file mode 100644 index 0000000..d788df0 --- /dev/null +++ b/models/compat/wakatime/v1/data_dump.go @@ -0,0 +1,24 @@ +package v1 + +type DataDumpViewModel struct { + Data []*DataDumpData `json:"data"` + Total int `json:"total"` + TotalPages int `json:"total_pages"` +} + +type DataDumpResultViewModel struct { + Data *DataDumpData `json:"data"` +} + +type DataDumpData struct { + Id string `json:"id"` + Type string `json:"type"` + DownloadUrl string `json:"download_url"` + Status string `json:"status"` + PercentComplete float32 `json:"percent_complete"` + Expires string `json:"expires"` + CreatedAt string `json:"created_at"` + HasFailed bool `json:"has_failed"` + IsStuck bool `json:"is_stuck"` + IsProcessing bool `json:"is_processing"` +} diff --git a/models/compat/wakatime/v1/json_export.go b/models/compat/wakatime/v1/json_export.go new file mode 100644 index 0000000..4677bc7 --- /dev/null +++ b/models/compat/wakatime/v1/json_export.go @@ -0,0 +1,17 @@ +package v1 + +type JsonExportViewModel struct { + //User *User `json:"user"` + Range *JsonExportRange `json:"range"` + Days []*JsonExportDay `json:"days"` +} + +type JsonExportRange struct { + Start int64 `json:"start"` + End int64 `json:"end"` +} + +type JsonExportDay struct { + Date string `json:"date"` + Heartbeats []*HeartbeatEntry `json:"heartbeats"` +} diff --git a/routes/settings.go b/routes/settings.go index 34ea0fe..86d941f 100644 --- a/routes/settings.go +++ b/routes/settings.go @@ -513,19 +513,26 @@ func (h *SettingsHandler) actionImportWakatime(w http.ResponseWriter, r *http.Re go func(user *models.User) { start := time.Now() - importer := imports.NewWakatimeHeartbeatImporter(user.WakatimeApiKey) + importer := imports.NewWakatimeImporter(user.WakatimeApiKey) countBefore, err := h.heartbeatSrvc.CountByUser(user) if err != nil { println(err) } - var stream <-chan *models.Heartbeat + var ( + stream <-chan *models.Heartbeat + importErr error + ) if latest, err := h.heartbeatSrvc.GetLatestByOriginAndUser(imports.OriginWakatime, user); latest == nil || err != nil { - stream = importer.ImportAll(user) + stream, importErr = importer.ImportAll(user) } else { // if an import has happened before, only import heartbeats newer than the latest of the last import - stream = importer.Import(user, latest.Time.T(), time.Now()) + stream, importErr = importer.Import(user, latest.Time.T(), time.Now()) + } + if importErr != nil { + conf.Log().Error("wakatime import for user '%s' failed - %v", user.ID, importErr) + return } count := 0 diff --git a/services/imports/importers.go b/services/imports/importers.go index 9f07b8e..668bd91 100644 --- a/services/imports/importers.go +++ b/services/imports/importers.go @@ -5,7 +5,7 @@ import ( "time" ) -type HeartbeatImporter interface { - Import(*models.User, time.Time, time.Time) <-chan *models.Heartbeat - ImportAll(*models.User) <-chan *models.Heartbeat +type DataImporter interface { + Import(*models.User, time.Time, time.Time) (<-chan *models.Heartbeat, error) + ImportAll(*models.User) (<-chan *models.Heartbeat, error) } diff --git a/services/imports/wakatime.go b/services/imports/wakatime.go index c652cf3..db8731c 100644 --- a/services/imports/wakatime.go +++ b/services/imports/wakatime.go @@ -1,342 +1,30 @@ package imports import ( - "context" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "github.com/duke-git/lancet/v2/datetime" - "github.com/muety/artifex/v2" - "github.com/muety/wakapi/utils" - "net/http" - "strings" - "time" - - "github.com/emvi/logbuch" "github.com/muety/wakapi/config" "github.com/muety/wakapi/models" - wakatime "github.com/muety/wakapi/models/compat/wakatime/v1" - "go.uber.org/atomic" - "golang.org/x/sync/semaphore" + "strings" + "time" ) -const OriginWakatime = "wakatime" -const ( - // wakatime api permits a max. rate of 10 req / sec - // https://github.com/wakatime/wakatime/issues/261 - // with 5 workers, each sleeping slightly over 1/2 sec after every req., we should stay well below that limit - maxWorkers = 5 - throttleDelay = 550 * time.Millisecond -) - -type WakatimeHeartbeatImporter struct { - ApiKey string - httpClient *http.Client - queue *artifex.Dispatcher +type WakatimeImporter struct { + apiKey string } -func NewWakatimeHeartbeatImporter(apiKey string) *WakatimeHeartbeatImporter { - return &WakatimeHeartbeatImporter{ - ApiKey: apiKey, - httpClient: &http.Client{Timeout: 10 * time.Second}, - queue: config.GetQueue(config.QueueImports), - } +func NewWakatimeImporter(apiKey string) *WakatimeImporter { + return &WakatimeImporter{apiKey: apiKey} } -func (w *WakatimeHeartbeatImporter) Import(user *models.User, minFrom time.Time, maxTo time.Time) <-chan *models.Heartbeat { - out := make(chan *models.Heartbeat) - - process := func(user *models.User, minFrom time.Time, maxTo time.Time, out chan *models.Heartbeat) { - logbuch.Info("running wakatime import for user '%s'", user.ID) - - baseUrl := user.WakaTimeURL(config.WakatimeApiUrl) - - startDate, endDate, err := w.fetchRange(baseUrl) - if err != nil { - config.Log().Error("failed to fetch date range while importing wakatime heartbeats for user '%s' - %v", user.ID, err) - return - } - - if startDate.Before(minFrom) { - startDate = minFrom - } - if endDate.After(maxTo) { - endDate = maxTo - } - - userAgents := map[string]*wakatime.UserAgentEntry{} - if data, err := w.fetchUserAgents(baseUrl); err == nil { - userAgents = data - } else if strings.Contains(baseUrl, "wakatime.com") { - // when importing from wakatime, resolving user agents is mandatorily required - config.Log().Error("failed to fetch user agents while importing wakatime heartbeats for user '%s' - %v", user.ID, err) - return - } - - machinesNames := map[string]*wakatime.MachineEntry{} - if data, err := w.fetchMachineNames(baseUrl); err == nil { - machinesNames = data - } else if strings.Contains(baseUrl, "wakatime.com") { - // when importing from wakatime, resolving machine names is mandatorily required - config.Log().Error("failed to fetch machine names while importing wakatime heartbeats for user '%s' - %v", user.ID, err) - return - } - - days := generateDays(startDate, endDate) - - c := atomic.NewUint32(uint32(len(days))) - ctx := context.TODO() - sem := semaphore.NewWeighted(maxWorkers) - - for _, d := range days { - if err := sem.Acquire(ctx, 1); err != nil { - logbuch.Error("failed to acquire semaphore - %v", err) - break - } - - go func(day time.Time) { - defer sem.Release(1) - defer time.Sleep(throttleDelay) - - d := day.Format(config.SimpleDateFormat) - heartbeats, err := w.fetchHeartbeats(d, baseUrl) - if err != nil { - config.Log().Error("failed to fetch heartbeats for day '%s' and user '%s' - %v", d, user.ID, err) - } - - for _, h := range heartbeats { - out <- mapHeartbeat(h, userAgents, machinesNames, user) - } - - if c.Dec() == 0 { - close(out) - } - }(d) - } +func (w *WakatimeImporter) Import(user *models.User, minFrom time.Time, maxTo time.Time) (<-chan *models.Heartbeat, error) { + if strings.Contains(user.WakaTimeURL(config.WakatimeApiUrl), "wakatime.com") { + return NewWakatimeDumpImporter(w.apiKey).Import(user, minFrom, maxTo) } - - if minDataAge := user.MinDataAge(); minFrom.Before(minDataAge) { - logbuch.Info("wakatime data import for user '%s' capped to [%v, &v]", user.ID, minDataAge, maxTo) - } - - logbuch.Info("scheduling wakatime import for user '%s' (interval [%v, %v])", user.ID, minFrom, maxTo) - if err := w.queue.Dispatch(func() { - process(user, minFrom, maxTo, out) - }); err != nil { - config.Log().Error("failed to dispatch wakatime import job for user '%s', %v", user.ID, err) - } - - return out + return NewWakatimeHeartbeatImporter(w.apiKey).Import(user, minFrom, maxTo) } -func (w *WakatimeHeartbeatImporter) ImportAll(user *models.User) <-chan *models.Heartbeat { - return w.Import(user, time.Time{}, time.Now()) -} - -// https://wakatime.com/api/v1/users/current/heartbeats?date=2021-02-05 -// https://pastr.de/p/b5p4od5s8w0pfntmwoi117jy -func (w *WakatimeHeartbeatImporter) fetchHeartbeats(day string, baseUrl string) ([]*wakatime.HeartbeatEntry, error) { - req, err := http.NewRequest(http.MethodGet, baseUrl+config.WakatimeApiHeartbeatsUrl, nil) - if err != nil { - return nil, err - } - - q := req.URL.Query() - q.Add("date", day) - req.URL.RawQuery = q.Encode() - - var empty []*wakatime.HeartbeatEntry - - res, err := w.httpClient.Do(w.withHeaders(req)) - if err != nil { - return empty, err - } else if res.StatusCode == 402 { - return empty, nil // date outside free plan range -> return empty data, but do not throw error - } else if res.StatusCode >= 400 { - return empty, errors.New(fmt.Sprintf("got status %d from wakatime api", res.StatusCode)) - } - defer res.Body.Close() - - var heartbeatsData wakatime.HeartbeatsViewModel - if err := json.NewDecoder(res.Body).Decode(&heartbeatsData); err != nil { - return empty, err - } - - return heartbeatsData.Data, nil -} - -// https://wakatime.com/api/v1/users/current/all_time_since_today -// https://pastr.de/p/w8xb4biv575pu32pox7jj2gr -func (w *WakatimeHeartbeatImporter) fetchRange(baseUrl string) (time.Time, time.Time, error) { - notime := time.Time{} - - req, err := http.NewRequest(http.MethodGet, baseUrl+config.WakatimeApiAllTimeUrl, nil) - if err != nil { - return notime, notime, err - } - - res, err := w.httpClient.Do(w.withHeaders(req)) - if err != nil { - return notime, notime, err - } - - // see https://github.com/muety/wakapi/issues/370 - allTimeData, err := utils.ParseJsonDropKeys[wakatime.AllTimeViewModel](res.Body, "text") - if err != nil { - return notime, notime, err - } - - startDate, err := time.Parse(config.SimpleDateFormat, allTimeData.Data.Range.StartDate) - if err != nil { - return notime, notime, err - } - - endDate, err := time.Parse(config.SimpleDateFormat, allTimeData.Data.Range.EndDate) - if err != nil { - return notime, notime, err - } - - return startDate, endDate, nil -} - -// https://wakatime.com/api/v1/users/current/user_agents -// https://pastr.de/p/05k5do8q108k94lic4lfl3pc -func (w *WakatimeHeartbeatImporter) fetchUserAgents(baseUrl string) (map[string]*wakatime.UserAgentEntry, error) { - userAgents := make(map[string]*wakatime.UserAgentEntry) - - for page := 1; ; page++ { - url := fmt.Sprintf("%s%s?page=%d", baseUrl, config.WakatimeApiUserAgentsUrl, page) - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - return nil, err - } - - res, err := w.httpClient.Do(w.withHeaders(req)) - if err != nil { - return nil, err - } - defer res.Body.Close() - - var userAgentsData wakatime.UserAgentsViewModel - if err := json.NewDecoder(res.Body).Decode(&userAgentsData); err != nil { - return nil, err - } - - for _, ua := range userAgentsData.Data { - userAgents[ua.Id] = ua - } - - if page == userAgentsData.TotalPages { - break - } - } - - return userAgents, nil -} - -// https://wakatime.com/api/v1/users/current/machine_names -// https://pastr.de/p/v58cv0xrupp3zvyyv8o6973j -func (w *WakatimeHeartbeatImporter) fetchMachineNames(baseUrl string) (map[string]*wakatime.MachineEntry, error) { - httpClient := &http.Client{Timeout: 10 * time.Second} - - machines := make(map[string]*wakatime.MachineEntry) - - for page := 1; ; page++ { - url := fmt.Sprintf("%s%s?page=%d", baseUrl, config.WakatimeApiMachineNamesUrl, page) - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - return nil, err - } - - res, err := httpClient.Do(w.withHeaders(req)) - if err != nil { - return nil, err - } - defer res.Body.Close() - - var machineData wakatime.MachineViewModel - if err := json.NewDecoder(res.Body).Decode(&machineData); err != nil { - return nil, err - } - - for _, ma := range machineData.Data { - machines[ma.Id] = ma - } - - if page == machineData.TotalPages { - break - } - } - - return machines, nil -} - -func (w *WakatimeHeartbeatImporter) withHeaders(req *http.Request) *http.Request { - req.Header.Set("Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(w.ApiKey)))) - return req -} - -func mapHeartbeat( - entry *wakatime.HeartbeatEntry, - userAgents map[string]*wakatime.UserAgentEntry, - machineNames map[string]*wakatime.MachineEntry, - user *models.User, -) *models.Heartbeat { - ua := userAgents[entry.UserAgentId] - if ua == nil { - // try to parse id as an actual user agent string (as returned by wakapi) - if opSys, editor, err := utils.ParseUserAgent(entry.UserAgentId); err == nil { - ua = &wakatime.UserAgentEntry{ - Editor: editor, - Os: opSys, - } - } else { - ua = &wakatime.UserAgentEntry{ - Editor: "unknown", - Os: "unknown", - } - } - } - - ma := machineNames[entry.MachineNameId] - if ma == nil { - ma = &wakatime.MachineEntry{ - Id: entry.MachineNameId, - Value: entry.MachineNameId, - } - } - - return (&models.Heartbeat{ - User: user, - UserID: user.ID, - Entity: entry.Entity, - Type: entry.Type, - Category: entry.Category, - Project: entry.Project, - Branch: entry.Branch, - Language: entry.Language, - IsWrite: entry.IsWrite, - Editor: ua.Editor, - OperatingSystem: ua.Os, - Machine: ma.Value, - UserAgent: ua.Value, - Time: models.CustomTime(time.Unix(0, int64(entry.Time*1e9))), - Origin: OriginWakatime, - OriginId: entry.Id, - CreatedAt: models.CustomTime(entry.CreatedAt), - }).Hashed() -} - -func generateDays(from, to time.Time) []time.Time { - days := make([]time.Time, 0) - - from = datetime.BeginOfDay(from) - to = datetime.BeginOfDay(to.AddDate(0, 0, 1)) - - for d := from; d.Before(to); d = d.AddDate(0, 0, 1) { - days = append(days, d) - } - - return days +func (w *WakatimeImporter) ImportAll(user *models.User) (<-chan *models.Heartbeat, error) { + if strings.Contains(user.WakaTimeURL(config.WakatimeApiUrl), "wakatime.com") { + return NewWakatimeDumpImporter(w.apiKey).ImportAll(user) + } + return NewWakatimeHeartbeatImporter(w.apiKey).ImportAll(user) } diff --git a/services/imports/wakatime_dump.go b/services/imports/wakatime_dump.go new file mode 100644 index 0000000..02b51ec --- /dev/null +++ b/services/imports/wakatime_dump.go @@ -0,0 +1,162 @@ +package imports + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "github.com/duke-git/lancet/v2/slice" + "github.com/emvi/logbuch" + "github.com/muety/artifex/v2" + "github.com/muety/wakapi/config" + "github.com/muety/wakapi/models" + wakatime "github.com/muety/wakapi/models/compat/wakatime/v1" + "net/http" + "time" +) + +// data example: https://pastr.de/p/0viiv8e0rwq27dim8gyq1jrc + +type WakatimeDumpImporter struct { + apiKey string + httpClient *http.Client + queue *artifex.Dispatcher +} + +func NewWakatimeDumpImporter(apiKey string) *WakatimeDumpImporter { + return &WakatimeDumpImporter{ + apiKey: apiKey, + httpClient: &http.Client{Timeout: 10 * time.Second}, + queue: config.GetQueue(config.QueueImports), + } +} + +func (w *WakatimeDumpImporter) Import(user *models.User, minFrom time.Time, maxTo time.Time) (<-chan *models.Heartbeat, error) { + out := make(chan *models.Heartbeat) + logbuch.Info("running wakatime dump import for user '%s'", user.ID) + + url := config.WakatimeApiUrl + config.WakatimeApiDataDumpUrl // this importer only works with wakatime currently, so no point in using user's custom wakatime api url + req, _ := http.NewRequest(http.MethodPost, url, bytes.NewBuffer([]byte(`{ "type": "heartbeats", "email_when_finished": "false" }`))) + + res, err := w.httpClient.Do(w.withHeaders(req)) + if err != nil { + return nil, err + } else if res.StatusCode >= 400 { + return nil, errors.New(fmt.Sprintf("got status %d from wakatime data dump api (post)", res.StatusCode)) + } + defer res.Body.Close() + + var datadumpData wakatime.DataDumpResultViewModel + if err := json.NewDecoder(res.Body).Decode(&datadumpData); err != nil { + return nil, err + } + + checkDumpReady := func(dumpId string, user *models.User) (bool, *wakatime.DataDumpData, error) { + req, _ := http.NewRequest(http.MethodGet, url, nil) + + res, err := w.httpClient.Do(w.withHeaders(req)) + if err != nil { + return false, nil, err + } else if res.StatusCode >= 400 { + return false, nil, errors.New(fmt.Sprintf("got status %d from wakatime data dump api (get)", res.StatusCode)) + } + + var datadumpData wakatime.DataDumpViewModel + if err := json.NewDecoder(res.Body).Decode(&datadumpData); err != nil { + return false, nil, err + } + + dump, ok := slice.FindBy[*wakatime.DataDumpData](datadumpData.Data, func(i int, item *wakatime.DataDumpData) bool { + return item.Id == dumpId + }) + if !ok { + return false, nil, errors.New(fmt.Sprintf("data dump with id '%s' for user '%s' not found", dumpId, user.ID)) + } + + return dump.Status == "Completed", dump, nil + } + + // start polling for dump to be ready + var readyPollTimer *artifex.DispatchTicker + + onDumpFailed := func(err error, user *models.User) { + config.Log().Error("fetching data dump for user '%s' failed - %v", user.ID, err) + readyPollTimer.Stop() + close(out) + } + + onDumpReady := func(dump *wakatime.DataDumpData, user *models.User, out chan *models.Heartbeat) { + config.Log().Info("data dump for user '%s' is available for download", user.ID) + readyPollTimer.Stop() + + defer close(out) + + // download + req, _ := http.NewRequest(http.MethodGet, dump.DownloadUrl, nil) + res, err := w.httpClient.Do(req) + if err != nil { + config.Log().Error("failed to download %s - %v", dump.DownloadUrl, err) + return + } else if res.StatusCode >= 400 { + config.Log().Error("failed to download %s - %v", dump.DownloadUrl, errors.New(fmt.Sprintf("got status %d from wakatime", res.StatusCode))) + return + } + defer res.Body.Close() + + logbuch.Info("fetched %d bytes data dump for user '%s'", res.ContentLength, user.ID) + + // decode + var data wakatime.JsonExportViewModel + if err := json.NewDecoder(res.Body).Decode(&data); err != nil { + config.Log().Error("failed to decode data dump for user '%s' ('%s') - %v", user.ID, dump.DownloadUrl, err) + return + } + + // fetch user agents and machine names + var userAgents map[string]*wakatime.UserAgentEntry + if userAgents, err = fetchUserAgents(config.WakatimeApiUrl, w.apiKey); err != nil { + config.Log().Error("failed to fetch user agents while importing wakatime heartbeats for user '%s' - %v", user.ID, err) + return + } + var machinesNames map[string]*wakatime.MachineEntry + if machinesNames, err = fetchMachineNames(config.WakatimeApiUrl, w.apiKey); err != nil { + config.Log().Error("failed to fetch machine names while importing wakatime heartbeats for user '%s' - %v", user.ID, err) + return + } + + for _, d := range data.Days { + for _, h := range d.Heartbeats { + hb := mapHeartbeat(h, userAgents, machinesNames, user) + if hb.Time.T().Before(minFrom) || hb.Time.T().After(maxTo) { + continue + } + out <- hb + } + } + } + + readyPollTimer, err = w.queue.DispatchEvery(func() { + u := *user + ok, dump, err := checkDumpReady(datadumpData.Data.Id, &u) + logbuch.Info("waiting for data dump '%s' for user '%s' to become downloadable (%.2f percent complete)", datadumpData.Data.Id, u.ID, dump.PercentComplete) + if err != nil { + onDumpFailed(err, &u) + } else if ok { + onDumpReady(dump, &u, out) + } + }, 10*time.Second) + + return out, nil +} + +func (w *WakatimeDumpImporter) ImportAll(user *models.User) (<-chan *models.Heartbeat, error) { + return w.Import(user, time.Time{}, time.Now()) +} + +func (w *WakatimeDumpImporter) withHeaders(req *http.Request) *http.Request { + req.Header.Set("Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(w.apiKey)))) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") + return req +} diff --git a/services/imports/wakatime_heartbeats.go b/services/imports/wakatime_heartbeats.go new file mode 100644 index 0000000..f53fcac --- /dev/null +++ b/services/imports/wakatime_heartbeats.go @@ -0,0 +1,219 @@ +package imports + +import ( + "context" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "github.com/duke-git/lancet/v2/datetime" + "github.com/muety/artifex/v2" + "github.com/muety/wakapi/utils" + "net/http" + "strings" + "time" + + "github.com/emvi/logbuch" + "github.com/muety/wakapi/config" + "github.com/muety/wakapi/models" + wakatime "github.com/muety/wakapi/models/compat/wakatime/v1" + "go.uber.org/atomic" + "golang.org/x/sync/semaphore" +) + +const OriginWakatime = "wakatime" +const ( + // wakatime api permits a max. rate of 10 req / sec + // https://github.com/wakatime/wakatime/issues/261 + // with 5 workers, each sleeping slightly over 1/2 sec after every req., we should stay well below that limit + maxWorkers = 5 + throttleDelay = 550 * time.Millisecond +) + +type WakatimeHeartbeatsImporter struct { + ApiKey string + httpClient *http.Client + queue *artifex.Dispatcher +} + +func NewWakatimeHeartbeatImporter(apiKey string) *WakatimeHeartbeatsImporter { + return &WakatimeHeartbeatsImporter{ + ApiKey: apiKey, + httpClient: &http.Client{Timeout: 10 * time.Second}, + queue: config.GetQueue(config.QueueImports), + } +} + +func (w *WakatimeHeartbeatsImporter) Import(user *models.User, minFrom time.Time, maxTo time.Time) (<-chan *models.Heartbeat, error) { + out := make(chan *models.Heartbeat) + + process := func(user *models.User, minFrom time.Time, maxTo time.Time, out chan *models.Heartbeat) { + logbuch.Info("running wakatime import for user '%s'", user.ID) + + baseUrl := user.WakaTimeURL(config.WakatimeApiUrl) + + startDate, endDate, err := w.fetchRange(baseUrl) + if err != nil { + config.Log().Error("failed to fetch date range while importing wakatime heartbeats for user '%s' - %v", user.ID, err) + return + } + + if startDate.Before(minFrom) { + startDate = minFrom + } + if endDate.After(maxTo) { + endDate = maxTo + } + + userAgents := map[string]*wakatime.UserAgentEntry{} + if data, err := fetchUserAgents(baseUrl, w.ApiKey); err == nil { + userAgents = data + } else if strings.Contains(baseUrl, "wakatime.com") { + // when importing from wakatime, resolving user agents is mandatorily required + config.Log().Error("failed to fetch user agents while importing wakatime heartbeats for user '%s' - %v", user.ID, err) + return + } + + machinesNames := map[string]*wakatime.MachineEntry{} + if data, err := fetchMachineNames(baseUrl, w.ApiKey); err == nil { + machinesNames = data + } else if strings.Contains(baseUrl, "wakatime.com") { + // when importing from wakatime, resolving machine names is mandatorily required + config.Log().Error("failed to fetch machine names while importing wakatime heartbeats for user '%s' - %v", user.ID, err) + return + } + + days := generateDays(startDate, endDate) + + c := atomic.NewUint32(uint32(len(days))) + ctx := context.TODO() + sem := semaphore.NewWeighted(maxWorkers) + + for _, d := range days { + if err := sem.Acquire(ctx, 1); err != nil { + logbuch.Error("failed to acquire semaphore - %v", err) + break + } + + go func(day time.Time) { + defer sem.Release(1) + defer time.Sleep(throttleDelay) + + d := day.Format(config.SimpleDateFormat) + heartbeats, err := w.fetchHeartbeats(d, baseUrl) + if err != nil { + config.Log().Error("failed to fetch heartbeats for day '%s' and user '%s' - %v", d, user.ID, err) + } + + for _, h := range heartbeats { + out <- mapHeartbeat(h, userAgents, machinesNames, user) + } + + if c.Dec() == 0 { + close(out) + } + }(d) + } + } + + if minDataAge := user.MinDataAge(); minFrom.Before(minDataAge) { + logbuch.Info("wakatime data import for user '%s' capped to [%v, &v]", user.ID, minDataAge, maxTo) + } + + logbuch.Info("scheduling wakatime import for user '%s' (interval [%v, %v])", user.ID, minFrom, maxTo) + if err := w.queue.Dispatch(func() { + process(user, minFrom, maxTo, out) + }); err != nil { + config.Log().Error("failed to dispatch wakatime import job for user '%s', %v", user.ID, err) + } + + return out, nil +} + +func (w *WakatimeHeartbeatsImporter) ImportAll(user *models.User) (<-chan *models.Heartbeat, error) { + return w.Import(user, time.Time{}, time.Now()) +} + +// https://wakatime.com/api/v1/users/current/heartbeats?date=2021-02-05 +// https://pastr.de/p/b5p4od5s8w0pfntmwoi117jy +func (w *WakatimeHeartbeatsImporter) fetchHeartbeats(day string, baseUrl string) ([]*wakatime.HeartbeatEntry, error) { + req, err := http.NewRequest(http.MethodGet, baseUrl+config.WakatimeApiHeartbeatsUrl, nil) + if err != nil { + return nil, err + } + + q := req.URL.Query() + q.Add("date", day) + req.URL.RawQuery = q.Encode() + + var empty []*wakatime.HeartbeatEntry + + res, err := w.httpClient.Do(w.withHeaders(req)) + if err != nil { + return empty, err + } else if res.StatusCode == 402 { + return empty, nil // date outside free plan range -> return empty data, but do not throw error + } else if res.StatusCode >= 400 { + return empty, errors.New(fmt.Sprintf("got status %d from wakatime api", res.StatusCode)) + } + defer res.Body.Close() + + var heartbeatsData wakatime.HeartbeatsViewModel + if err := json.NewDecoder(res.Body).Decode(&heartbeatsData); err != nil { + return empty, err + } + + return heartbeatsData.Data, nil +} + +// https://wakatime.com/api/v1/users/current/all_time_since_today +// https://pastr.de/p/w8xb4biv575pu32pox7jj2gr +func (w *WakatimeHeartbeatsImporter) fetchRange(baseUrl string) (time.Time, time.Time, error) { + notime := time.Time{} + + req, err := http.NewRequest(http.MethodGet, baseUrl+config.WakatimeApiAllTimeUrl, nil) + if err != nil { + return notime, notime, err + } + + res, err := w.httpClient.Do(w.withHeaders(req)) + if err != nil { + return notime, notime, err + } + + // see https://github.com/muety/wakapi/issues/370 + allTimeData, err := utils.ParseJsonDropKeys[wakatime.AllTimeViewModel](res.Body, "text") + if err != nil { + return notime, notime, err + } + + startDate, err := time.Parse(config.SimpleDateFormat, allTimeData.Data.Range.StartDate) + if err != nil { + return notime, notime, err + } + + endDate, err := time.Parse(config.SimpleDateFormat, allTimeData.Data.Range.EndDate) + if err != nil { + return notime, notime, err + } + + return startDate, endDate, nil +} + +func (w *WakatimeHeartbeatsImporter) withHeaders(req *http.Request) *http.Request { + req.Header.Set("Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(w.ApiKey)))) + return req +} + +func generateDays(from, to time.Time) []time.Time { + days := make([]time.Time, 0) + + from = datetime.BeginOfDay(from) + to = datetime.BeginOfDay(to.AddDate(0, 0, 1)) + + for d := from; d.Before(to); d = d.AddDate(0, 0, 1) { + days = append(days, d) + } + + return days +} diff --git a/services/imports/wakatime_utils.go b/services/imports/wakatime_utils.go new file mode 100644 index 0000000..5d76c43 --- /dev/null +++ b/services/imports/wakatime_utils.go @@ -0,0 +1,140 @@ +package imports + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "github.com/muety/wakapi/config" + "github.com/muety/wakapi/models" + wakatime "github.com/muety/wakapi/models/compat/wakatime/v1" + "github.com/muety/wakapi/utils" + "net/http" + "time" +) + +// https://wakatime.com/api/v1/users/current/machine_names +// https://pastr.de/p/v58cv0xrupp3zvyyv8o6973j +func fetchMachineNames(baseUrl, apiKey string) (map[string]*wakatime.MachineEntry, error) { + httpClient := &http.Client{Timeout: 10 * time.Second} + + machines := make(map[string]*wakatime.MachineEntry) + + for page := 1; ; page++ { + url := fmt.Sprintf("%s%s?page=%d", baseUrl, config.WakatimeApiMachineNamesUrl, page) + req, err := http.NewRequest(http.MethodGet, url, nil) + req.Header.Set("Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(apiKey)))) + if err != nil { + return nil, err + } + + res, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer res.Body.Close() + + var machineData wakatime.MachineViewModel + if err := json.NewDecoder(res.Body).Decode(&machineData); err != nil { + return nil, err + } + + for _, ma := range machineData.Data { + machines[ma.Id] = ma + } + + if page == machineData.TotalPages { + break + } + } + + return machines, nil +} + +// https://wakatime.com/api/v1/users/current/user_agents +// https://pastr.de/p/05k5do8q108k94lic4lfl3pc +func fetchUserAgents(baseUrl, apiKey string) (map[string]*wakatime.UserAgentEntry, error) { + httpClient := &http.Client{Timeout: 10 * time.Second} + + userAgents := make(map[string]*wakatime.UserAgentEntry) + + for page := 1; ; page++ { + url := fmt.Sprintf("%s%s?page=%d", baseUrl, config.WakatimeApiUserAgentsUrl, page) + req, err := http.NewRequest(http.MethodGet, url, nil) + req.Header.Set("Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(apiKey)))) + if err != nil { + return nil, err + } + + res, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer res.Body.Close() + + var userAgentsData wakatime.UserAgentsViewModel + if err := json.NewDecoder(res.Body).Decode(&userAgentsData); err != nil { + return nil, err + } + + for _, ua := range userAgentsData.Data { + userAgents[ua.Id] = ua + } + + if page == userAgentsData.TotalPages { + break + } + } + + return userAgents, nil +} + +func mapHeartbeat( + entry *wakatime.HeartbeatEntry, + userAgents map[string]*wakatime.UserAgentEntry, + machineNames map[string]*wakatime.MachineEntry, + user *models.User, +) *models.Heartbeat { + ua := userAgents[entry.UserAgentId] + if ua == nil { + // try to parse id as an actual user agent string (as returned by wakapi) + if opSys, editor, err := utils.ParseUserAgent(entry.UserAgentId); err == nil { + ua = &wakatime.UserAgentEntry{ + Editor: editor, + Os: opSys, + } + } else { + ua = &wakatime.UserAgentEntry{ + Editor: "unknown", + Os: "unknown", + } + } + } + + ma := machineNames[entry.MachineNameId] + if ma == nil { + ma = &wakatime.MachineEntry{ + Id: entry.MachineNameId, + Value: entry.MachineNameId, + } + } + + return (&models.Heartbeat{ + User: user, + UserID: user.ID, + Entity: entry.Entity, + Type: entry.Type, + Category: entry.Category, + Project: entry.Project, + Branch: entry.Branch, + Language: entry.Language, + IsWrite: entry.IsWrite, + Editor: ua.Editor, + OperatingSystem: ua.Os, + Machine: ma.Value, + UserAgent: ua.Value, + Time: models.CustomTime(time.Unix(0, int64(entry.Time*1e9))), + Origin: OriginWakatime, + OriginId: entry.Id, + CreatedAt: models.CustomTime(entry.CreatedAt), + }).Hashed() +}