Skip to content

Commit 7d23f48

Browse files
committed
✨ Add history listing for Edge and Chrome plugins
1 parent 244285c commit 7d23f48

12 files changed

+851
-6
lines changed

plugins/chrome/downloads.go

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package main
2+
3+
import (
4+
"database/sql"
5+
"fmt"
6+
"log"
7+
"time"
8+
9+
"github.com/julien040/anyquery/rpc"
10+
)
11+
12+
// A constructor to create a new table instance
13+
// This function is called everytime a new connection is made to the plugin
14+
//
15+
// It should return a new table instance, the database schema and if there is an error
16+
func downloadsCreator(args rpc.TableCreatorArgs) (rpc.Table, *rpc.DatabaseSchema, error) {
17+
if databaseHistoryPath == "" {
18+
return nil, nil, fmt.Errorf("failed to find the history database path")
19+
}
20+
21+
db, err := sql.Open("sqlite", fmt.Sprintf("file:%s?mode=ro", databaseHistoryPath))
22+
if err != nil {
23+
return nil, nil, fmt.Errorf("failed to find the history database: %w", err)
24+
}
25+
26+
return &downloadsTable{
27+
db: db,
28+
}, &rpc.DatabaseSchema{
29+
Columns: []rpc.DatabaseSchemaColumn{
30+
{
31+
Name: "id",
32+
Type: rpc.ColumnTypeInt,
33+
Description: "The ID of the download",
34+
},
35+
{
36+
Name: "path",
37+
Type: rpc.ColumnTypeString,
38+
Description: "The path where the download is stored",
39+
},
40+
{
41+
Name: "started_at",
42+
Type: rpc.ColumnTypeDateTime,
43+
Description: "The datetime (RFC3339) when the download started",
44+
},
45+
{
46+
Name: "ended_at",
47+
Type: rpc.ColumnTypeDateTime,
48+
Description: "The datetime (RFC3339) when the download ended",
49+
},
50+
{
51+
Name: "url",
52+
Type: rpc.ColumnTypeString,
53+
Description: "The URL of the download",
54+
},
55+
{
56+
Name: "size",
57+
Type: rpc.ColumnTypeInt,
58+
Description: "The size of the download in bytes",
59+
},
60+
{
61+
Name: "mime_type",
62+
Type: rpc.ColumnTypeString,
63+
Description: "The MIME type of the download",
64+
},
65+
},
66+
}, nil
67+
}
68+
69+
// The table struct
70+
// There is one per connection to the plugin and is created by the creator function
71+
// In there, you can store any state you need to read the rows (e.g. a database connection, an API token, etc.)
72+
type downloadsTable struct {
73+
db *sql.DB
74+
}
75+
76+
// The cursor struct
77+
// There is one per query and is created by the createReader function
78+
// In there, you can store any state you need to read the rows (e.g. a database connection from downloadsTable, an offset, a cursor, etc.)
79+
type downloadsCursor struct {
80+
db *sql.DB
81+
}
82+
83+
// Create a new cursor that will be used to read rows
84+
func (t *downloadsTable) CreateReader() rpc.ReaderInterface {
85+
return &downloadsCursor{
86+
db: t.db,
87+
}
88+
}
89+
90+
const queryDownloads = `
91+
SELECT
92+
id,
93+
CURRENT_PATH,
94+
start_time,
95+
end_time,
96+
tab_url,
97+
total_bytes AS size,
98+
mime_type
99+
FROM
100+
downloads
101+
ORDER BY
102+
start_time DESC;
103+
`
104+
105+
// Return a slice of rows that will be returned to Anyquery and filtered.
106+
// The second return value is true if the cursor has no more rows to return
107+
//
108+
// The constraints are used for optimization purposes to "pre-filter" the rows
109+
// If the rows returned don't match the constraints, it's not an issue. Anyquery will filter them out
110+
func (t *downloadsCursor) Query(constraints rpc.QueryConstraint) ([][]interface{}, bool, error) {
111+
112+
rows, err := t.db.Query(queryDownloads)
113+
if err != nil {
114+
return nil, true, fmt.Errorf("failed to query downloads: %w", err)
115+
}
116+
117+
var result [][]interface{}
118+
for rows.Next() {
119+
var id, size int64
120+
var path, url, mimeType string
121+
var startedAt int64
122+
var endedAt sql.NullInt64
123+
124+
err := rows.Scan(&id, &path, &startedAt, &endedAt, &url, &size, &mimeType)
125+
if err != nil {
126+
return nil, true, fmt.Errorf("failed to scan downloads: %w", err)
127+
}
128+
129+
// Convert the WebKit timestamp to a RFC3339 datetime
130+
startedAtStr := time.Unix(startedAt/1000000-11644473600, 0).Format(time.RFC3339)
131+
endAtStr := interface{}(nil)
132+
if endedAt.Valid {
133+
endAtStr = time.Unix(endedAt.Int64/1000000-11644473600, 0).Format(time.RFC3339)
134+
}
135+
136+
log.Printf("id: %d, path: %s, startedAt: %s, endedAt: %s, url: %s, size: %d, mimeType: %s", id, path, startedAtStr, endAtStr, url, size, mimeType)
137+
138+
result = append(result, []interface{}{
139+
id,
140+
path,
141+
startedAtStr,
142+
endAtStr,
143+
url,
144+
size,
145+
mimeType,
146+
})
147+
}
148+
149+
return result, true, nil
150+
}
151+
152+
// A destructor to clean up resources
153+
func (t *downloadsTable) Close() error {
154+
return t.db.Close()
155+
}

plugins/chrome/go.mod

+12-1
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,32 @@ module github.com/julien040/anyquery/plugins/chrome
22

33
go 1.23.2
44

5-
require github.com/julien040/anyquery v0.1.6
5+
require (
6+
github.com/julien040/anyquery v0.1.6
7+
modernc.org/sqlite v1.35.0
8+
)
69

710
require (
11+
github.com/dustin/go-humanize v1.0.1 // indirect
812
github.com/fatih/color v1.17.0 // indirect
913
github.com/golang/protobuf v1.5.4 // indirect
14+
github.com/google/uuid v1.6.0 // indirect
1015
github.com/hashicorp/go-hclog v1.6.3 // indirect
1116
github.com/hashicorp/go-plugin v1.6.2 // indirect
1217
github.com/hashicorp/yamux v0.1.1 // indirect
1318
github.com/mattn/go-colorable v0.1.13 // indirect
1419
github.com/mattn/go-isatty v0.0.20 // indirect
20+
github.com/ncruces/go-strftime v0.1.9 // indirect
1521
github.com/oklog/run v1.1.0 // indirect
22+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
23+
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d // indirect
1624
golang.org/x/net v0.32.0 // indirect
1725
golang.org/x/sys v0.28.0 // indirect
1826
golang.org/x/text v0.21.0 // indirect
1927
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
2028
google.golang.org/grpc v1.66.2 // indirect
2129
google.golang.org/protobuf v1.34.2 // indirect
30+
modernc.org/libc v1.61.13 // indirect
31+
modernc.org/mathutil v1.7.1 // indirect
32+
modernc.org/memory v1.8.2 // indirect
2233
)

plugins/chrome/go.sum

+42
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,19 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
44
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
55
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
66
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7+
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
8+
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
79
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
810
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
911
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
1012
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
1113
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
1214
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
1315
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
16+
github.com/google/pprof v0.0.0-20241206021119-61a79c692802 h1:US08AXzP0bLurpzFUV3Poa9ZijrRdd1zAIOVtoHEiS8=
17+
github.com/google/pprof v0.0.0-20241206021119-61a79c692802/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
18+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
19+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
1420
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
1521
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
1622
github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog=
@@ -30,17 +36,27 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
3036
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
3137
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
3238
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
39+
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
40+
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
3341
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
3442
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
3543
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
3644
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
3745
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
46+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
47+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
3848
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
3949
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
4050
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
4151
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
52+
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0=
53+
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
54+
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
55+
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
4256
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
4357
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
58+
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
59+
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
4460
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
4561
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
4662
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -52,6 +68,8 @@ golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
5268
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
5369
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
5470
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
71+
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
72+
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
5573
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
5674
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
5775
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
@@ -61,3 +79,27 @@ google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWn
6179
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
6280
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
6381
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
82+
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
83+
modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
84+
modernc.org/ccgo/v4 v4.23.16 h1:Z2N+kk38b7SfySC1ZkpGLN2vthNJP1+ZzGZIlH7uBxo=
85+
modernc.org/ccgo/v4 v4.23.16/go.mod h1:nNma8goMTY7aQZQNTyN9AIoJfxav4nvTnvKThAeMDdo=
86+
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
87+
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
88+
modernc.org/gc/v2 v2.6.3 h1:aJVhcqAte49LF+mGveZ5KPlsp4tdGdAOT4sipJXADjw=
89+
modernc.org/gc/v2 v2.6.3/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
90+
modernc.org/libc v1.61.13 h1:3LRd6ZO1ezsFiX1y+bHd1ipyEHIJKvuprv0sLTBwLW8=
91+
modernc.org/libc v1.61.13/go.mod h1:8F/uJWL/3nNil0Lgt1Dpz+GgkApWh04N3el3hxJcA6E=
92+
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
93+
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
94+
modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI=
95+
modernc.org/memory v1.8.2/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU=
96+
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
97+
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
98+
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
99+
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
100+
modernc.org/sqlite v1.35.0 h1:yQps4fegMnZFdphtzlfQTCNBWtS0CZv48pRpW3RFHRw=
101+
modernc.org/sqlite v1.35.0/go.mod h1:9cr2sicr7jIaWTBKQmAxQLfBv9LL0su4ZTEV+utt3ic=
102+
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
103+
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
104+
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
105+
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=

0 commit comments

Comments
 (0)