initial
This commit is contained in:
commit
c68076859a
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
result
|
||||
gostart
|
||||
.direnv
|
||||
*.db
|
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
12
.idea/dataSources.xml
Normal file
12
.idea/dataSources.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="startpage.db" uuid="075da49b-4ea0-40a7-a0d6-f3c1a5d4859e">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:startpage.db</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
10
.idea/gostart.iml
Normal file
10
.idea/gostart.iml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="Go" enabled="true" />
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
6
.idea/misc.xml
Normal file
6
.idea/misc.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/gostart.iml" filepath="$PROJECT_DIR$/.idea/gostart.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
24
.idea/sqlDataSources.xml
Normal file
24
.idea/sqlDataSources.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DdlMappings">
|
||||
<mapping uuid="79025c83-5c52-4dc3-8cb0-252aeb699812" name="startpage.db Mapping">
|
||||
<data-sources db="075da49b-4ea0-40a7-a0d6-f3c1a5d4859e" ddl="a18207f2-7e6b-440c-b070-d4e9b699dc57" />
|
||||
</mapping>
|
||||
</component>
|
||||
<component name="SqlDataSourceStorage">
|
||||
<option name="dataSources">
|
||||
<list>
|
||||
<State>
|
||||
<option name="id" value="a18207f2-7e6b-440c-b070-d4e9b699dc57" />
|
||||
<option name="name" value="startpage.db (DDL)" />
|
||||
<option name="languageId" value="SQLite" />
|
||||
<option name="urls">
|
||||
<array>
|
||||
<option value="file://$PROJECT_DIR$/schema.sql" />
|
||||
</array>
|
||||
</option>
|
||||
</State>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
7
.idea/sqldialects.xml
Normal file
7
.idea/sqldialects.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="SqlDialectMappings">
|
||||
<file url="file://$PROJECT_DIR$/queries.sql" dialect="GenericSQL" />
|
||||
<file url="PROJECT" dialect="SQLite" />
|
||||
</component>
|
||||
</project>
|
28
app.go
Normal file
28
app.go
Normal file
@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"suah.dev/gostart/data"
|
||||
"tailscale.com/client/tailscale"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/tsnet"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
tsServer *tsnet.Server
|
||||
tsLocalClient *tailscale.LocalClient
|
||||
ctx context.Context
|
||||
queries *data.Queries
|
||||
watches *WatchResults
|
||||
}
|
||||
|
||||
func (a *App) getOwner(r *http.Request) (*tailcfg.Node, error) {
|
||||
who, err := a.tsLocalClient.WhoIs(r.Context(), r.RemoteAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return who.Node, nil
|
||||
}
|
518
assets/bolt.css
Normal file
518
assets/bolt.css
Normal file
@ -0,0 +1,518 @@
|
||||
/**
|
||||
* Bolt.css
|
||||
* Version 0.5.0
|
||||
* https://github.com/tbolt/boltcss
|
||||
*
|
||||
* Sections
|
||||
* 1. Content sectioning
|
||||
* 2. Text content
|
||||
* 3. Inline text semantics
|
||||
* 4. Image and multimedia
|
||||
* 5. Tables
|
||||
* 6. Forms
|
||||
* 7. Interactive elements
|
||||
*
|
||||
*/
|
||||
|
||||
:root {
|
||||
--highlight-border-radius: 7px;
|
||||
--border-radius: 11px;
|
||||
|
||||
--links: #0f6dff;
|
||||
--background-body: #fff;
|
||||
--background-main: #f1f1f1;
|
||||
--background-inputs: #fcfcfc;
|
||||
--text: #1c1d1e;
|
||||
--border: #dddddd;
|
||||
--focus-highlight: #b8b8b8;
|
||||
--shadow-color: #545454;
|
||||
--table-highlight: #f1f1f1;
|
||||
--select-icon-url: url("data:image/svg+xml,%3Csvg width='292' height='292' viewBox='0 0 292 292' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cpath id='Path' fill='%23222222' stroke='none' d='M 287 69 C 283.606537 65.469971 278.895844 63.513214 274 63.600006 L 18.4 63.600006 C 13.4 63.600006 9.1 65.400009 5.5 69 C 1.984143 72.328568 -0.005267 76.958466 -0 81.800003 C -0 86.800003 1.8 91.100006 5.4 94.699997 L 133.399994 222.600006 C 137 226.200012 141.199997 228 146.199997 228 C 151.199997 228 155.399994 226.200012 159 222.600006 L 287 94.600006 C 290.5 91.100006 292.399994 86.800003 292.399994 81.800003 C 292.399994 76.800003 290.5 72.600006 286.899994 69 Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--links: #4589ee;
|
||||
--background-body: #0f0f0f;
|
||||
--background-main: #222;
|
||||
--background-inputs: #222;
|
||||
--text: #efefef;
|
||||
--border: #444;
|
||||
--focus-highlight: #888;
|
||||
--shadow-color: #bebebe;
|
||||
--table-highlight: #222;
|
||||
--select-icon-url: url("data:image/svg+xml,%3Csvg width='292' height='292' viewBox='0 0 292 292' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cpath id='Path' fill='%23ffffff' stroke='none' d='M 287 69 C 283.606537 65.469971 278.895844 63.513214 274 63.600006 L 18.4 63.600006 C 13.4 63.600006 9.1 65.400009 5.5 69 C 1.984143 72.328568 -0.005267 76.958466 -0 81.800003 C -0 86.800003 1.8 91.100006 5.4 94.699997 L 133.399994 222.600006 C 137 226.200012 141.199997 228 146.199997 228 C 151.199997 228 155.399994 226.200012 159 222.600006 L 287 94.600006 C 290.5 91.100006 292.399994 86.800003 292.399994 81.800003 C 292.399994 76.800003 290.5 72.600006 286.899994 69 Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
::after,
|
||||
::before {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
font-size: 12pt;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue",
|
||||
sans-serif;
|
||||
color: var(--text);
|
||||
background: var(--background-body);
|
||||
}
|
||||
|
||||
/* Content sectioning */
|
||||
address {
|
||||
font-style: normal;
|
||||
line-height: 1.6rem;
|
||||
}
|
||||
|
||||
/* Todo: Revisit this and try to find a way to handle margin depending on float direction */
|
||||
aside {
|
||||
width: 40%;
|
||||
padding: 0.84rem;
|
||||
margin: 0.16rem;
|
||||
font-style: italic;
|
||||
color: var(--text);
|
||||
background-color: var(--background-main);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
/* No styles provided */
|
||||
footer {
|
||||
}
|
||||
header {
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
b,
|
||||
strong,
|
||||
th {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Not provided */
|
||||
hgroup {
|
||||
}
|
||||
|
||||
/* Not provided */
|
||||
main {
|
||||
}
|
||||
|
||||
/* Not provided */
|
||||
nav {
|
||||
}
|
||||
|
||||
/* Not provided */
|
||||
section {
|
||||
}
|
||||
|
||||
/* Text content */
|
||||
blockquote {
|
||||
position: relative;
|
||||
padding-left: 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
blockquote:before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
border-left: 7px solid var(--border);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-left: 0;
|
||||
padding-bottom: 11px;
|
||||
}
|
||||
|
||||
dl {
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
padding-top: 10px;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 2px solid var(--border);
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
}
|
||||
|
||||
li {
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
p {
|
||||
display: block;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
/* Inline text elements */
|
||||
a {
|
||||
color: var(--links);
|
||||
}
|
||||
|
||||
a:active,
|
||||
a:hover,
|
||||
a:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
mark,
|
||||
samp,
|
||||
kbd,
|
||||
code,
|
||||
time {
|
||||
border-radius: var(--highlight-border-radius, 4px);
|
||||
box-decoration-break: clone;
|
||||
-webkit-box-decoration-break: clone;
|
||||
}
|
||||
|
||||
mark {
|
||||
background-color: #fffab7;
|
||||
padding: 3px 5px;
|
||||
}
|
||||
|
||||
samp {
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
padding: 10px 20px;
|
||||
background-color: var(--background-main);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
kbd,
|
||||
time {
|
||||
padding: 2px 4px;
|
||||
background-color: var(--background-main);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
code,
|
||||
pre {
|
||||
font-size: 1em;
|
||||
padding: 2px 4px;
|
||||
background: var(--background-main);
|
||||
border: 1px solid darkgray;
|
||||
max-width: fit-content;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
padding: 10px;
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
sup,
|
||||
sub {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/* Image and multimedia */
|
||||
audio,
|
||||
img,
|
||||
video {
|
||||
border-radius: var(--border-radius);
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
img {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
table {
|
||||
width: fit-content;
|
||||
border: 1px solid var(--background-main);
|
||||
background: var(--background-main);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
table tr:last-child td:first-child {
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
|
||||
table tr:last-child td:last-child {
|
||||
border-bottom-right-radius: 8px;
|
||||
}
|
||||
|
||||
table tr:first-child th:first-child {
|
||||
border-top-left-radius: 8px;
|
||||
}
|
||||
|
||||
table tr:first-child th:last-child {
|
||||
border-top-right-radius: 8px;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: var(--background-main);
|
||||
}
|
||||
|
||||
td {
|
||||
background: var(--background-body);
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
thead {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
tfoot {
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
table tr:hover td,
|
||||
tbody tr:nth-child(even):hover td {
|
||||
background-color: var(--table-highlight);
|
||||
}
|
||||
|
||||
/* Form elements */
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button,
|
||||
select,
|
||||
input[type="submit"],
|
||||
input[type="button"],
|
||||
input[type="checkbox"],
|
||||
input[type="range"],
|
||||
input[type="radio"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button {
|
||||
color: var(--text);
|
||||
background-color: var(--background-main);
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
padding: 6px 15px 6px 15px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0px 1px 1.5px rgb(158 158 158 / 60%);
|
||||
}
|
||||
|
||||
button:active {
|
||||
box-shadow: none;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
button:disabled,
|
||||
button[disabled] {
|
||||
box-shadow: none;
|
||||
border: 1px solid var(--border);
|
||||
cursor: initial;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
max-width: fit-content;
|
||||
}
|
||||
|
||||
input {
|
||||
font-size: 1em;
|
||||
background-color: var(--background-inputs);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text);
|
||||
margin: 6px 0px;
|
||||
padding: 11px;
|
||||
border-radius: var(--border-radius);
|
||||
max-width: fit-content;
|
||||
outline: none;
|
||||
display: inline-block;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
margin-right: 0.33em;
|
||||
margin-top: 0.31em;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked,
|
||||
input[type="radio"]:checked {
|
||||
border: 1px solid var(--links);
|
||||
background: var(--links);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3.5' d='M6 10l3 3l6-6'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
input[type="radio"]:checked {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
vertical-align: middle;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
font-size: 1em;
|
||||
background-color: var(--background-inputs);
|
||||
border: 1px solid var(--border);
|
||||
padding: 11px;
|
||||
color: var(--text);
|
||||
border-radius: var(--border-radius);
|
||||
outline: none;
|
||||
/* resize: none; Todo: research if there is a non-js way to style/move grippie */
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
select {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
font-size: 1rem;
|
||||
color: var(--text);
|
||||
padding: 0.6em 2em 0.5em 0.8em;
|
||||
margin: 6px 0px;
|
||||
max-width: fit-content;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid var(--border);
|
||||
box-shadow: 0 1px 0 1px rgba(0, 0, 0, 0.04);
|
||||
border-radius: 0.5em;
|
||||
appearance: none;
|
||||
background-color: var(--background-inputs);
|
||||
background-image: var(--select-icon-url);
|
||||
background-repeat: no-repeat, repeat;
|
||||
background-position: right 0.7em top 50%, 0 0;
|
||||
background-size: 0.65em auto, 100%;
|
||||
}
|
||||
|
||||
/* Todo: update styles when using multiple mode */
|
||||
select:is([multiple]) {
|
||||
background: none;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
fieldset:focus-within,
|
||||
input:focus-within,
|
||||
textarea:focus-within,
|
||||
select:focus-within {
|
||||
border-color: var(--focus-highlight);
|
||||
}
|
||||
|
||||
fieldset:hover,
|
||||
input:hover,
|
||||
textarea:hover,
|
||||
select:hover {
|
||||
border-color: var(--focus-highlight);
|
||||
}
|
||||
|
||||
meter {
|
||||
height: 2.2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: 1px var(--border) solid;
|
||||
border-radius: 6px;
|
||||
margin: 0;
|
||||
margin-bottom: 6px;
|
||||
padding: 10px;
|
||||
max-width: fit-content;
|
||||
}
|
||||
|
||||
/* Interactive elements */
|
||||
details {
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 7px;
|
||||
padding: 0.5em 0.5em 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
font-weight: bold;
|
||||
margin: -0.5em -0.5em 0;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
details[open] {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
details[open] summary {
|
||||
border-bottom: 1px solid #aaa;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
2493
assets/pico.css
Normal file
2493
assets/pico.css
Normal file
File diff suppressed because it is too large
Load Diff
31
data/db.go
Normal file
31
data/db.go
Normal file
@ -0,0 +1,31 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.16.0
|
||||
|
||||
package data
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
|
||||
PrepareContext(context.Context, string) (*sql.Stmt, error)
|
||||
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
|
||||
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
60
data/models.go
Normal file
60
data/models.go
Normal file
@ -0,0 +1,60 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.16.0
|
||||
|
||||
package data
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Icon struct {
|
||||
ID int64 `json:"id"`
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Url string `json:"url"`
|
||||
ContentType string `json:"content_type"`
|
||||
Data []byte `json:"data"`
|
||||
}
|
||||
|
||||
type Link struct {
|
||||
ID int64 `json:"id"`
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Url string `json:"url"`
|
||||
Name string `json:"name"`
|
||||
LogoUrl sql.NullString `json:"logo_url"`
|
||||
}
|
||||
|
||||
type Owner struct {
|
||||
ID int64 `json:"id"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type PullRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Number int64 `json:"number"`
|
||||
Repo string `json:"repo"`
|
||||
Description sql.NullString `json:"description"`
|
||||
Commitid sql.NullString `json:"commitid"`
|
||||
}
|
||||
|
||||
type PullRequestIgnore struct {
|
||||
ID int64 `json:"id"`
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Number int64 `json:"number"`
|
||||
Repo string `json:"repo"`
|
||||
}
|
||||
|
||||
type WatchItem struct {
|
||||
ID int64 `json:"id"`
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Name string `json:"name"`
|
||||
Descr sql.NullString `json:"descr"`
|
||||
}
|
446
data/queries.sql.go
Normal file
446
data/queries.sql.go
Normal file
@ -0,0 +1,446 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.16.0
|
||||
// source: queries.sql
|
||||
|
||||
package data
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
const addIcon = `-- name: AddIcon :one
|
||||
insert into icons (owner_id, url, content_type, data)
|
||||
values (?, ?, ?, ?) returning id, owner_id, created_at, url, content_type, data
|
||||
`
|
||||
|
||||
type AddIconParams struct {
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
Url string `json:"url"`
|
||||
ContentType string `json:"content_type"`
|
||||
Data []byte `json:"data"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddIcon(ctx context.Context, arg AddIconParams) (Icon, error) {
|
||||
row := q.db.QueryRowContext(ctx, addIcon,
|
||||
arg.OwnerID,
|
||||
arg.Url,
|
||||
arg.ContentType,
|
||||
arg.Data,
|
||||
)
|
||||
var i Icon
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.Url,
|
||||
&i.ContentType,
|
||||
&i.Data,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const addLink = `-- name: AddLink :one
|
||||
insert into links (owner_id, url, name, logo_url)
|
||||
values (?, ?, ?, ?) returning id, owner_id, created_at, url, name, logo_url
|
||||
`
|
||||
|
||||
type AddLinkParams struct {
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
Url string `json:"url"`
|
||||
Name string `json:"name"`
|
||||
LogoUrl sql.NullString `json:"logo_url"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddLink(ctx context.Context, arg AddLinkParams) (Link, error) {
|
||||
row := q.db.QueryRowContext(ctx, addLink,
|
||||
arg.OwnerID,
|
||||
arg.Url,
|
||||
arg.Name,
|
||||
arg.LogoUrl,
|
||||
)
|
||||
var i Link
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.Url,
|
||||
&i.Name,
|
||||
&i.LogoUrl,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const addOwner = `-- name: AddOwner :one
|
||||
insert into owners (id, name)
|
||||
values (?, ?) returning id, created_at, name
|
||||
`
|
||||
|
||||
type AddOwnerParams struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddOwner(ctx context.Context, arg AddOwnerParams) (Owner, error) {
|
||||
row := q.db.QueryRowContext(ctx, addOwner, arg.ID, arg.Name)
|
||||
var i Owner
|
||||
err := row.Scan(&i.ID, &i.CreatedAt, &i.Name)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const addPullRequest = `-- name: AddPullRequest :one
|
||||
insert into pull_requests (owner_id, number, repo, description)
|
||||
values (?, ?, ?, ?) returning id, owner_id, created_at, number, repo, description, commitid
|
||||
`
|
||||
|
||||
type AddPullRequestParams struct {
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
Number int64 `json:"number"`
|
||||
Repo string `json:"repo"`
|
||||
Description sql.NullString `json:"description"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddPullRequest(ctx context.Context, arg AddPullRequestParams) (PullRequest, error) {
|
||||
row := q.db.QueryRowContext(ctx, addPullRequest,
|
||||
arg.OwnerID,
|
||||
arg.Number,
|
||||
arg.Repo,
|
||||
arg.Description,
|
||||
)
|
||||
var i PullRequest
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.Number,
|
||||
&i.Repo,
|
||||
&i.Description,
|
||||
&i.Commitid,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const addPullRequestIgnore = `-- name: AddPullRequestIgnore :one
|
||||
insert into pull_request_ignores (owner_id, number, repo)
|
||||
values (?, ?, ?) returning id, owner_id, created_at, number, repo
|
||||
`
|
||||
|
||||
type AddPullRequestIgnoreParams struct {
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
Number int64 `json:"number"`
|
||||
Repo string `json:"repo"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddPullRequestIgnore(ctx context.Context, arg AddPullRequestIgnoreParams) (PullRequestIgnore, error) {
|
||||
row := q.db.QueryRowContext(ctx, addPullRequestIgnore, arg.OwnerID, arg.Number, arg.Repo)
|
||||
var i PullRequestIgnore
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.Number,
|
||||
&i.Repo,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const addWatchItem = `-- name: AddWatchItem :one
|
||||
insert into watch_items (owner_id, name, descr)
|
||||
values (?, ?, ?) returning id, owner_id, created_at, name, descr
|
||||
`
|
||||
|
||||
type AddWatchItemParams struct {
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
Name string `json:"name"`
|
||||
Descr sql.NullString `json:"descr"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddWatchItem(ctx context.Context, arg AddWatchItemParams) (WatchItem, error) {
|
||||
row := q.db.QueryRowContext(ctx, addWatchItem, arg.OwnerID, arg.Name, arg.Descr)
|
||||
var i WatchItem
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Descr,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteLink = `-- name: DeleteLink :exec
|
||||
delete from links where id = ? and owner_id = ?
|
||||
`
|
||||
|
||||
type DeleteLinkParams struct {
|
||||
ID int64 `json:"id"`
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteLink(ctx context.Context, arg DeleteLinkParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteLink, arg.ID, arg.OwnerID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deletePullRequest = `-- name: DeletePullRequest :exec
|
||||
delete from pull_requests where id = ? and owner_id = ?
|
||||
`
|
||||
|
||||
type DeletePullRequestParams struct {
|
||||
ID int64 `json:"id"`
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeletePullRequest(ctx context.Context, arg DeletePullRequestParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deletePullRequest, arg.ID, arg.OwnerID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteWatchItem = `-- name: DeleteWatchItem :exec
|
||||
delete from watch_items where id = ? and owner_id = ?
|
||||
`
|
||||
|
||||
type DeleteWatchItemParams struct {
|
||||
ID int64 `json:"id"`
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteWatchItem(ctx context.Context, arg DeleteWatchItemParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteWatchItem, arg.ID, arg.OwnerID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAllIcons = `-- name: GetAllIcons :many
|
||||
select id, owner_id, created_at, url, content_type, data
|
||||
from icons
|
||||
where owner_id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllIcons(ctx context.Context, ownerID int64) ([]Icon, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllIcons, ownerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []Icon{}
|
||||
for rows.Next() {
|
||||
var i Icon
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.Url,
|
||||
&i.ContentType,
|
||||
&i.Data,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getAllLinks = `-- name: GetAllLinks :many
|
||||
select id, owner_id, created_at, url, name, logo_url
|
||||
from links
|
||||
where owner_id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllLinks(ctx context.Context, ownerID int64) ([]Link, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllLinks, ownerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []Link{}
|
||||
for rows.Next() {
|
||||
var i Link
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.Url,
|
||||
&i.Name,
|
||||
&i.LogoUrl,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getAllPullRequestIgnores = `-- name: GetAllPullRequestIgnores :many
|
||||
select id, owner_id, created_at, number, repo
|
||||
from pull_request_ignores
|
||||
where owner_id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllPullRequestIgnores(ctx context.Context, ownerID int64) ([]PullRequestIgnore, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllPullRequestIgnores, ownerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []PullRequestIgnore{}
|
||||
for rows.Next() {
|
||||
var i PullRequestIgnore
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.Number,
|
||||
&i.Repo,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getAllPullRequests = `-- name: GetAllPullRequests :many
|
||||
select id, owner_id, created_at, number, repo, description, commitid
|
||||
from pull_requests
|
||||
where number not in (select number
|
||||
from pull_request_ignores
|
||||
where pull_request_ignores.owner_id = ?)
|
||||
and pull_requests.owner_id = ?
|
||||
`
|
||||
|
||||
type GetAllPullRequestsParams struct {
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
OwnerID_2 int64 `json:"owner_id_2"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetAllPullRequests(ctx context.Context, arg GetAllPullRequestsParams) ([]PullRequest, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllPullRequests, arg.OwnerID, arg.OwnerID_2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []PullRequest{}
|
||||
for rows.Next() {
|
||||
var i PullRequest
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.Number,
|
||||
&i.Repo,
|
||||
&i.Description,
|
||||
&i.Commitid,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getAllWatchItems = `-- name: GetAllWatchItems :many
|
||||
select id, owner_id, created_at, name, descr
|
||||
from watch_items
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllWatchItems(ctx context.Context) ([]WatchItem, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllWatchItems)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []WatchItem{}
|
||||
for rows.Next() {
|
||||
var i WatchItem
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Descr,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getAllWatchItemsByOwner = `-- name: GetAllWatchItemsByOwner :many
|
||||
select id, owner_id, created_at, name, descr
|
||||
from watch_items
|
||||
where owner_id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllWatchItemsByOwner(ctx context.Context, ownerID int64) ([]WatchItem, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllWatchItemsByOwner, ownerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []WatchItem{}
|
||||
for rows.Next() {
|
||||
var i WatchItem
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Descr,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getOwner = `-- name: GetOwner :one
|
||||
select id, created_at, name
|
||||
from owners
|
||||
where id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) GetOwner(ctx context.Context, id int64) (Owner, error) {
|
||||
row := q.db.QueryRowContext(ctx, getOwner, id)
|
||||
var i Owner
|
||||
err := row.Scan(&i.ID, &i.CreatedAt, &i.Name)
|
||||
return i, err
|
||||
}
|
26
flake.lock
Normal file
26
flake.lock
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1668417584,
|
||||
"narHash": "sha256-yeuEyxKPwsm5fIHN49L/syn9g5coxnPp3GsVquhrv5A=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "013fcdd106823416918004bb684c3c186d3c460f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-unstable",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
40
flake.nix
Normal file
40
flake.nix
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
description = "gostart: a tailscale aware start page";
|
||||
|
||||
inputs.nixpkgs.url = "nixpkgs/nixos-unstable";
|
||||
|
||||
outputs = { self, nixpkgs }:
|
||||
let
|
||||
supportedSystems =
|
||||
[ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
|
||||
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||
nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; });
|
||||
in {
|
||||
packages = forAllSystems (system:
|
||||
let pkgs = nixpkgsFor.${system};
|
||||
in {
|
||||
gostart = pkgs.buildGoModule {
|
||||
pname = "gostart";
|
||||
version = "v0.0.0";
|
||||
src = ./.;
|
||||
|
||||
vendorSha256 = "sha256-RNhu1gQ62Hg8Fhiw9uIS+b4YaAHtZMaqbelMKv+oZjM=";
|
||||
proxyVendor = true;
|
||||
};
|
||||
});
|
||||
|
||||
defaultPackage = forAllSystems (system: self.packages.${system}.gostart);
|
||||
devShells = forAllSystems (system:
|
||||
let pkgs = nixpkgsFor.${system};
|
||||
in {
|
||||
default = pkgs.mkShell {
|
||||
shellHook = ''
|
||||
PS1='\u@\h:\@; '
|
||||
echo "Go `${pkgs.go}/bin/go version`"
|
||||
'';
|
||||
nativeBuildInputs = with pkgs; [ git go gopls go-tools sqlc sqlite esbuild yarn ];
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
|
88
go.mod
Normal file
88
go.mod
Normal file
@ -0,0 +1,88 @@
|
||||
module suah.dev/gostart
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/go-chi/chi/v5 v5.0.7
|
||||
github.com/go-chi/render v1.0.2
|
||||
modernc.org/sqlite v1.19.5
|
||||
tailscale.com v1.32.2
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
|
||||
github.com/ajg/form v1.5.1 // indirect
|
||||
github.com/akutz/memconn v0.1.0 // indirect
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.11.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.11.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.6.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.17.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.6.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.11.1 // indirect
|
||||
github.com/aws/smithy-go v1.9.0 // indirect
|
||||
github.com/coreos/go-iptables v0.6.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/godbus/dbus/v5 v5.0.6 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect
|
||||
github.com/insomniacslk/dhcp v0.0.0-20211209223715-7d93572ebe8e // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/josharian/native v1.0.0 // indirect
|
||||
github.com/jsimonetti/rtnetlink v1.1.2-0.20220408201609-d380b505068b // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/klauspost/compress v1.15.4 // indirect
|
||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mdlayher/genetlink v1.2.0 // indirect
|
||||
github.com/mdlayher/netlink v1.6.0 // indirect
|
||||
github.com/mdlayher/sdnotify v1.0.0 // indirect
|
||||
github.com/mdlayher/socket v0.2.3 // indirect
|
||||
github.com/mitchellh/go-ps v1.0.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d // indirect
|
||||
github.com/tailscale/golang-x-crypto v0.0.0-20221009170451-62f465106986 // indirect
|
||||
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect
|
||||
github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 // indirect
|
||||
github.com/tcnksm/go-httpstat v0.2.0 // indirect
|
||||
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 // indirect
|
||||
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go4.org/mem v0.0.0-20210711025021-927187094b94 // indirect
|
||||
go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf // indirect
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f // indirect
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/net v0.0.0-20221002022538-bcab6841153b // indirect
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect
|
||||
golang.org/x/tools v0.1.11 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
|
||||
golang.zx2c4.com/wireguard v0.0.0-20220904105730-b51010ba13f0 // indirect
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
|
||||
gvisor.dev/gvisor v0.0.0-20220817001344-846276b3dbc5 // indirect
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
modernc.org/cc/v3 v3.40.0 // indirect
|
||||
modernc.org/ccgo/v3 v3.16.13 // indirect
|
||||
modernc.org/libc v1.21.5 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.4.0 // indirect
|
||||
modernc.org/opt v0.1.3 // indirect
|
||||
modernc.org/strutil v1.1.3 // indirect
|
||||
modernc.org/token v1.0.1 // indirect
|
||||
nhooyr.io/websocket v1.8.7 // indirect
|
||||
)
|
326
go.sum
Normal file
326
go.sum
Normal file
@ -0,0 +1,326 @@
|
||||
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
|
||||
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
||||
filippo.io/mkcert v1.4.3 h1:axpnmtrZMM8u5Hf4N3UXxboGemMOV+Tn+e+pkHM6E3o=
|
||||
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
|
||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A=
|
||||
github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||
github.com/aws/aws-sdk-go-v2 v1.11.2 h1:SDiCYqxdIYi6HgQfAWRhgdZrdnOuGyLDJVRSWLeHWvs=
|
||||
github.com/aws/aws-sdk-go-v2 v1.11.2/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.11.0 h1:Czlld5zBB61A3/aoegA9/buZulwL9mHHfizh/Oq+Kqs=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.11.0/go.mod h1:VrQDJGFBM5yZe+IOeenNZ/DWoErdny+k2MHEIpwDsEY=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.6.4 h1:2hvbUoHufns0lDIsaK8FVCMukT1WngtZPavN+W2FkSw=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.6.4/go.mod h1:tTrhvBPHyPde4pdIPSba4Nv7RYr4wP9jxXEDa1bKn/8=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2 h1:KiN5TPOLrEjbGCvdTQR4t0U4T87vVwALZ5Bg3jpMqPY=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2/go.mod h1:dF2F6tXEOgmW5X1ZFO/EPtWrcm7XkW07KNcJUGNtt4s=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2 h1:XJLnluKuUxQG255zPNe+04izXl7GSyUVafIsgfv9aw4=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2/go.mod h1:SgKKNBIoDC/E1ZCDhhMW3yalWjwuLjMcpLzsM/QQnWo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2 h1:EauRoYZVNPlidZSZJDscjJBQ22JhVF2+tdteatax2Ak=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2/go.mod h1:xT4XX6w5Sa3dhg50JrYyy3e4WPYo/+WjY/BXtqXVunU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2 h1:IQup8Q6lorXeiA/rK72PeToWoWK8h7VAPgHNWdSrtgE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2/go.mod h1:VITe/MdW6EMXPb0o0txu/fsonXbMHUU2OC2Qp7ivU4o=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2 h1:CKdUNKmuilw/KNmO2Q53Av8u+ZyXMC2M9aX8Z+c/gzg=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2/go.mod h1:FgR1tCsn8C6+Hf+N5qkfrE4IXvUL1RgW87sunJ+5J4I=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.17.1 h1:E/2WewR1wegBnthK8Yz+E87E8Mm4RJC/7R6vg6oAfl0=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.17.1/go.mod h1:jqRk4h1lv2pV4G1DTYRj71JIMEoU/gEGvLU5O6ZnpLM=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.6.2 h1:2IDmvSb86KT44lSg1uU4ONpzgWLOuApRl6Tg54mZ6Dk=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.6.2/go.mod h1:KnIpszaIdwI33tmc/W/GGXyn22c1USYxA/2KyvoeDY0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.11.1 h1:QKR7wy5e650q70PFKMfGF9sTo0rZgUevSSJ4wxmyWXk=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.11.1/go.mod h1:UV2N5HaPfdbDpkgkz4sRzWCvQswZjdO1FfqCWl0t7RA=
|
||||
github.com/aws/smithy-go v1.9.0 h1:c7FUdEqrQA1/UVKKCNDFQPNKGp4FQg3YW4Ck5SLTG58=
|
||||
github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||
github.com/cilium/ebpf v0.8.1 h1:bLSSEbBLqGPXxls55pGr5qWZaTqcmfDJHhou7t254ao=
|
||||
github.com/cilium/ebpf v0.8.1/go.mod h1:f5zLIM0FSNuAkSyLAN7X+Hy6yznlF1mNiWUMfxMtrgk=
|
||||
github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk=
|
||||
github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
|
||||
github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
|
||||
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
|
||||
github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
|
||||
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/github/fakeca v0.1.0 h1:Km/MVOFvclqxPM9dZBC4+QE564nU4gz4iZ0D9pMw28I=
|
||||
github.com/github/fakeca v0.1.0/go.mod h1:+bormgoGMMuamOscx7N91aOuUST7wdaJ2rNjeohylyo=
|
||||
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
|
||||
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg=
|
||||
github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
|
||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 h1:aSVUgRRRtOrZOC1fYmY9gV0e9z/Iu+xNVSASWjsuyGU=
|
||||
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3/go.mod h1:5PC6ZNPde8bBqU/ewGZig35+UIZtw9Ytxez8/q5ZyFE=
|
||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20211209223715-7d93572ebe8e h1:IQpunlq7T+NiJJMO7ODYV2YWBiv/KnObR3gofX0mWOo=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20211209223715-7d93572ebe8e/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk=
|
||||
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
|
||||
github.com/jsimonetti/rtnetlink v1.1.2-0.20220408201609-d380b505068b h1:Yws7RV6kZr2O7PPdT+RkbSmmOponA8i/1DuGHe8BRsM=
|
||||
github.com/jsimonetti/rtnetlink v1.1.2-0.20220408201609-d380b505068b/go.mod h1:TzDCVOZKUa79z6iXbbXqhtAflVgUKaFkZ21M5tK5tzY=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.15.4 h1:1kn4/7MepF/CHmYub99/nNX8az0IJjfSOU/jbnTVfqQ=
|
||||
github.com/klauspost/compress v1.15.4/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a h1:+RR6SqnTkDLWyICxS1xpjCi/3dhyV+TgZwA6Ww3KncQ=
|
||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a/go.mod h1:YTtCCM3ryyfiu4F7t8HQ1mxvp1UBdWM2r6Xa+nGWvDk=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
|
||||
github.com/mdlayher/genetlink v1.2.0 h1:4yrIkRV5Wfk1WfpWTcoOlGmsWgQj3OtQN9ZsbrE+XtU=
|
||||
github.com/mdlayher/genetlink v1.2.0/go.mod h1:ra5LDov2KrUCZJiAtEvXXZBxGMInICMXIwshlJ+qRxQ=
|
||||
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
|
||||
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
||||
github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0=
|
||||
github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA=
|
||||
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
github.com/mdlayher/sdnotify v1.0.0 h1:Ma9XeLVN/l0qpyx1tNeMSeTjCPH6NtuD6/N9XdTlQ3c=
|
||||
github.com/mdlayher/sdnotify v1.0.0/go.mod h1:HQUmpM4XgYkhDLtd+Uad8ZFK1T9D5+pNxnXQjCeJlGE=
|
||||
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
|
||||
github.com/mdlayher/socket v0.2.3 h1:XZA2X2TjdOwNoNPVPclRCURoX/hokBY8nkTmRZFEheM=
|
||||
github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY=
|
||||
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
|
||||
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
|
||||
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 h1:Ha8xCaq6ln1a+R91Km45Oq6lPXj2Mla6CRJYcuV2h1w=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d h1:K3j02b5j2Iw1xoggN9B2DIEkhWGheqFOeDkdJdBrJI8=
|
||||
github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d/go.mod h1:2P+hpOwd53e7JMX/L4f3VXkv1G+33ES6IWZSrkIeWNs=
|
||||
github.com/tailscale/golang-x-crypto v0.0.0-20221009170451-62f465106986 h1:jWSwTR9CY13oa2oxhR3FInk1ybqC1NbF9cFeoWrrx+E=
|
||||
github.com/tailscale/golang-x-crypto v0.0.0-20221009170451-62f465106986/go.mod h1:95n9fbUCixVSI4QXLEvdKJjnYK2eUlkTx9+QwLPXFKU=
|
||||
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 h1:4chzWmimtJPxRs2O36yuGRW3f9SYV+bMTTvMBI0EKio=
|
||||
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05/go.mod h1:PdCqy9JzfWMJf1H5UJW2ip33/d4YkoKN0r67yKH1mG8=
|
||||
github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 h1:zrsUcqrG2uQSPhaUPjUQwozcRdDdSxxqhNgNZ3drZFk=
|
||||
github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85/go.mod h1:NzVQi3Mleb+qzq8VmcWpSkcSYxXIg0DkI6XDzpVkhJ0=
|
||||
github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0=
|
||||
github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8=
|
||||
github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
|
||||
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 h1:hl6sK6aFgTLISijk6xIzeqnPzQcsLqqvL6vEfTPinME=
|
||||
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 h1:8mhqcHPqTMhSPoslhGYihEgSfc77+7La1P6kiB6+9So=
|
||||
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE=
|
||||
go4.org/mem v0.0.0-20210711025021-927187094b94 h1:OAAkygi2Js191AJP1Ds42MhJRgeofeKGjuoUqNp1QC4=
|
||||
go4.org/mem v0.0.0-20210711025021-927187094b94/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g=
|
||||
go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf h1:IdwJUzqoIo5lkr2EOyKoe5qipUaEjbOKKY5+fzPBZ3A=
|
||||
go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf/go.mod h1:+QXzaoURFd0rGDIjDNpyIkv+F9R7EmeKorvlKRnhqgA=
|
||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 h1:FyBZqvoA/jbNzuAWLQE2kG820zMAkcilx6BMjGbL/E4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc=
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
|
||||
golang.org/x/exp/typeparams v0.0.0-20220328175248-053ad81199eb h1:fP6C8Xutcp5AlakmT/SkQot0pMicROAsEX7OfNPuG10=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20221002022538-bcab6841153b h1:6e93nYa3hNqAvLr0pD4PN1fFS+gKzp2zAXqrnTCstqU=
|
||||
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8=
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y=
|
||||
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
|
||||
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY=
|
||||
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20220904105730-b51010ba13f0 h1:5ZkdpbduT/g+9OtbSDvbF3KvfQG45CtH/ppO8FUmvCQ=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20220904105730-b51010ba13f0/go.mod h1:enML0deDxY1ux+B6ANGiwtg0yAJi1rctkTpcHNAVPyg=
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gvisor.dev/gvisor v0.0.0-20220817001344-846276b3dbc5 h1:cv/zaNV0nr1mJzaeo4S5mHIm5va1W0/9J3/5prlsuRM=
|
||||
gvisor.dev/gvisor v0.0.0-20220817001344-846276b3dbc5/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM=
|
||||
honnef.co/go/tools v0.4.0-0.dev.0.20220404092545-59d7a2877f83 h1:lZ9GIYaU+o5+X6ST702I/Ntyq9Y2oIMZ42rBQpem64A=
|
||||
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
||||
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
|
||||
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
|
||||
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
|
||||
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
modernc.org/libc v1.21.5 h1:xBkU9fnHV+hvZuPSRszN0AXDG4M7nwPLwTWwkYcvLCI=
|
||||
modernc.org/libc v1.21.5/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk=
|
||||
modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.19.5 h1:E3iHL55c1Vw1knqIeU9N7B0fSjuiOjHZo7iVMsO6U5U=
|
||||
modernc.org/sqlite v1.19.5/go.mod h1:EsYz8rfOvLCiYTy5ZFsOYzoCcRMu98YYkwAcCw5YIYw=
|
||||
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
||||
modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34=
|
||||
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
|
||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE=
|
||||
nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
|
||||
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
||||
software.sslmate.com/src/go-pkcs12 v0.0.0-20210415151418-c5206de65a78 h1:SqYE5+A2qvRhErbsXFfUEUmpWEKxxRSMgGLkvRAFOV4=
|
||||
tailscale.com v1.32.2 h1:bTYbeNPhC3OBH0g5kYWXBEoUOiEsNYf0WSvsvFsYlB0=
|
||||
tailscale.com v1.32.2/go.mod h1:AwKk+tI7z1+EXzmLxVNXA4dBpgTKd6RVV1VjFYEiv94=
|
199
handlers.go
Normal file
199
handlers.go
Normal file
@ -0,0 +1,199 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/render"
|
||||
"suah.dev/gostart/data"
|
||||
)
|
||||
|
||||
func OwnerCtx(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
owner, err := app.getOwner(r)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
ownerID := int64(owner.ID)
|
||||
ctx := context.WithValue(r.Context(), "ownerid", ownerID)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
func watchitemGET(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
ownerID, ok := ctx.Value("ownerid").(int64)
|
||||
if !ok {
|
||||
http.Error(w, http.StatusText(422), 422)
|
||||
return
|
||||
}
|
||||
watches, err := app.queries.GetAllWatchItemsByOwner(app.ctx, ownerID)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
wJson, err := json.Marshal(watches)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Add("Content-type", "application/json")
|
||||
w.WriteHeader(200)
|
||||
_, err = w.Write(wJson)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func pullrequestsPOST(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func pullrequestsDELETE(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
ownerID, ok := ctx.Value("ownerid").(int64)
|
||||
if !ok {
|
||||
http.Error(w, http.StatusText(422), 422)
|
||||
return
|
||||
}
|
||||
prID, err := strconv.Atoi(chi.URLParam(r, "prID"))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
err = app.queries.DeletePullRequest(app.ctx, data.DeletePullRequestParams{ID: int64(prID), OwnerID: ownerID})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func pullrequestsGET(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
ownerID, ok := ctx.Value("ownerid").(int64)
|
||||
if !ok {
|
||||
http.Error(w, http.StatusText(422), 422)
|
||||
return
|
||||
}
|
||||
prs, err := app.queries.GetAllPullRequests(app.ctx, data.GetAllPullRequestsParams{
|
||||
OwnerID: ownerID,
|
||||
OwnerID_2: ownerID,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
prJson, err := json.Marshal(prs)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Add("Content-type", "application/json")
|
||||
w.WriteHeader(200)
|
||||
_, err = w.Write(prJson)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func linksGET(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
ownerID, ok := ctx.Value("ownerid").(int64)
|
||||
if !ok {
|
||||
http.Error(w, http.StatusText(422), 422)
|
||||
return
|
||||
}
|
||||
links, err := app.queries.GetAllLinks(app.ctx, ownerID)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
linksJson, err := json.Marshal(links)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Add("Content-type", "application/json")
|
||||
w.WriteHeader(200)
|
||||
_, err = w.Write(linksJson)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func linksPOST(w http.ResponseWriter, r *http.Request) {
|
||||
d := &data.AddLinkParams{}
|
||||
if err := render.Decode(r, d); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
ctx := r.Context()
|
||||
ownerID, ok := ctx.Value("ownerid").(int64)
|
||||
if !ok {
|
||||
http.Error(w, http.StatusText(422), 422)
|
||||
return
|
||||
}
|
||||
|
||||
d.OwnerID = ownerID
|
||||
|
||||
_, err := app.queries.AddLink(app.ctx, *d)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(422), 422)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func index(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
owner, err := app.getOwner(r)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(422), 422)
|
||||
return
|
||||
}
|
||||
ownerID, ok := ctx.Value("ownerid").(int64)
|
||||
if !ok {
|
||||
http.Error(w, http.StatusText(422), 422)
|
||||
return
|
||||
}
|
||||
dbCtx := context.Background()
|
||||
links, err := app.queries.GetAllLinks(dbCtx, ownerID)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
prs, err := app.queries.GetAllPullRequests(dbCtx, data.GetAllPullRequestsParams{
|
||||
OwnerID: ownerID,
|
||||
OwnerID_2: ownerID,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
stuff := &Page{
|
||||
Node: *owner,
|
||||
Title: "StartPage",
|
||||
Links: links,
|
||||
PullRequests: prs,
|
||||
Watches: app.watches.forID(ownerID),
|
||||
CurrentLimits: app.watches.GetLimits(),
|
||||
}
|
||||
|
||||
stuff.Sort()
|
||||
|
||||
tmpl := template.Must(template.ParseFS(templates, "templates/main.html"))
|
||||
err = tmpl.Execute(w, stuff)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
139
main.go
Normal file
139
main.go
Normal file
@ -0,0 +1,139 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"database/sql"
|
||||
"embed"
|
||||
_ "embed"
|
||||
"flag"
|
||||
"github.com/go-chi/render"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
_ "modernc.org/sqlite"
|
||||
"suah.dev/gostart/data"
|
||||
"tailscale.com/client/tailscale"
|
||||
"tailscale.com/tsnet"
|
||||
)
|
||||
|
||||
//go:embed schema.sql
|
||||
var schema string
|
||||
|
||||
//go:embed templates
|
||||
var templates embed.FS
|
||||
|
||||
//go:embed assets
|
||||
var assets embed.FS
|
||||
|
||||
var app = &App{
|
||||
ctx: context.Background(),
|
||||
tsServer: &tsnet.Server{},
|
||||
tsLocalClient: &tailscale.LocalClient{},
|
||||
}
|
||||
|
||||
func main() {
|
||||
name := flag.String("name", "startpage", "name of service")
|
||||
key := flag.String("key", "", "path to file containing the api key")
|
||||
dbFile := flag.String("db", "", "path to on-disk database file")
|
||||
tokenFile := flag.String("auth", "", "path to file containing GH auth token")
|
||||
flag.Parse()
|
||||
|
||||
var db *sql.DB
|
||||
var err error
|
||||
if *dbFile == "" {
|
||||
db, err = sql.Open("sqlite", ":memory:")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
app.queries = data.New(db)
|
||||
app.tsServer = &tsnet.Server{
|
||||
Hostname: *name,
|
||||
}
|
||||
app.tsLocalClient, err = app.tsServer.LocalClient()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
tmpDBPopulate(db)
|
||||
|
||||
if *key != "" {
|
||||
keyData, err := os.ReadFile(*key)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
app.tsServer.AuthKey = string(keyData)
|
||||
}
|
||||
|
||||
ln, err := app.tsServer.Listen("tcp", ":443")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := app.tsServer.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
fileServer := http.FileServer(http.FS(assets))
|
||||
r := chi.NewRouter()
|
||||
|
||||
r.Use(middleware.Logger)
|
||||
r.Use(OwnerCtx)
|
||||
|
||||
r.Mount("/assets", fileServer)
|
||||
r.Route("/", func(r chi.Router) {
|
||||
r.Get("/", index)
|
||||
})
|
||||
r.Route("/pullrequests", func(r chi.Router) {
|
||||
r.Use(render.SetContentType(render.ContentTypeJSON))
|
||||
r.Get("/", pullrequestsGET)
|
||||
r.Delete("/{prID:[0-9]+}", pullrequestsDELETE)
|
||||
r.Post("/", pullrequestsPOST)
|
||||
})
|
||||
r.Route("/links", func(r chi.Router) {
|
||||
r.Use(render.SetContentType(render.ContentTypeJSON))
|
||||
r.Get("/", linksGET)
|
||||
r.Post("/", linksPOST)
|
||||
})
|
||||
r.Route("/watches", func(r chi.Router) {
|
||||
r.Use(render.SetContentType(render.ContentTypeJSON))
|
||||
r.Get("/", watchitemGET)
|
||||
})
|
||||
|
||||
app.watches = &WatchResults{}
|
||||
ghToken := os.Getenv("GH_AUTH_TOKEN")
|
||||
|
||||
if *tokenFile != "" && ghToken == "" {
|
||||
tfBytes, err := os.ReadFile(*tokenFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
ghToken = string(tfBytes)
|
||||
}
|
||||
|
||||
go func() {
|
||||
err := app.watches.Update(ghToken)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
time.Sleep(5 * time.Minute)
|
||||
}()
|
||||
|
||||
hs := &http.Server{
|
||||
Handler: r,
|
||||
TLSConfig: &tls.Config{
|
||||
GetCertificate: app.tsLocalClient.GetCertificate,
|
||||
},
|
||||
}
|
||||
|
||||
log.Panic(hs.ServeTLS(ln, "", ""))
|
||||
}
|
191
page.go
Normal file
191
page.go
Normal file
@ -0,0 +1,191 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"suah.dev/gostart/data"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
const gqEndPoint = "https://api.github.com/graphql"
|
||||
|
||||
const graphQuery = `
|
||||
{
|
||||
search(
|
||||
query: "is:open is:public archived:false repo:nixos/nixpkgs in:title %s",
|
||||
type: ISSUE,
|
||||
first: 20
|
||||
) {
|
||||
issueCount
|
||||
edges {
|
||||
node {
|
||||
... on Issue {
|
||||
number
|
||||
title
|
||||
url
|
||||
repository {
|
||||
nameWithOwner
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
... on PullRequest {
|
||||
number
|
||||
title
|
||||
repository {
|
||||
nameWithOwner
|
||||
}
|
||||
createdAt
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rateLimit {
|
||||
remaining
|
||||
resetAt
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
type GQLQuery struct {
|
||||
Query string `json:"query"`
|
||||
}
|
||||
|
||||
func getData(q GQLQuery, token string) (*WatchResult, error) {
|
||||
var req *http.Request
|
||||
var err error
|
||||
var re = &WatchResult{}
|
||||
|
||||
client := &http.Client{}
|
||||
buf := new(bytes.Buffer)
|
||||
if err := json.NewEncoder(buf).Encode(q); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err = http.NewRequest("POST", gqEndPoint, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", fmt.Sprintf("bearer %s", token))
|
||||
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
if err = json.NewDecoder(res.Body).Decode(re); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return re, nil
|
||||
}
|
||||
|
||||
type Page struct {
|
||||
Title string
|
||||
PullRequests []data.PullRequest
|
||||
Links []data.Link
|
||||
Node tailcfg.Node
|
||||
Watches WatchResults
|
||||
CurrentLimits *RateLimit
|
||||
}
|
||||
|
||||
func (p *Page) Sort() {
|
||||
sort.Slice(p.Links, func(i, j int) bool {
|
||||
return p.Links[i].Name > p.Links[j].Name
|
||||
})
|
||||
sort.Slice(p.PullRequests, func(i, j int) bool {
|
||||
return p.PullRequests[i].Number > p.PullRequests[j].Number
|
||||
})
|
||||
sort.Slice(p.Watches, func(i, j int) bool {
|
||||
return p.Watches[i].Name < p.Watches[j].Name
|
||||
})
|
||||
for _, w := range p.Watches {
|
||||
sort.Slice(w.Data.Search.Edges, func(i, j int) bool {
|
||||
return w.Data.Search.Edges[i].Node.CreatedAt.After(w.Data.Search.Edges[j].Node.CreatedAt)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type WatchResults []WatchResult
|
||||
|
||||
func (w WatchResults) forID(ownerID int64) WatchResults {
|
||||
newResults := WatchResults{}
|
||||
fmt.Printf("%v\n", w)
|
||||
for _, r := range w {
|
||||
if r.OwnerID == ownerID {
|
||||
newResults = append(newResults, r)
|
||||
}
|
||||
}
|
||||
|
||||
return newResults
|
||||
}
|
||||
|
||||
func (w WatchResults) GetLimits() *RateLimit {
|
||||
sort.Slice(w, func(i, j int) bool {
|
||||
return w[i].Data.RateLimit.Remaining < w[j].Data.RateLimit.Remaining
|
||||
})
|
||||
return &w[0].Data.RateLimit
|
||||
}
|
||||
|
||||
func (w *WatchResults) Update(ghToken string) error {
|
||||
ctx := context.Background()
|
||||
watches, err := app.queries.GetAllWatchItems(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, watch := range watches {
|
||||
qd := GQLQuery{Query: fmt.Sprintf(graphQuery, watch.Name)}
|
||||
wr, err := getData(qd, ghToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: cross ref the list of ignores and prune the wr accordingly
|
||||
wr.OwnerID = watch.OwnerID
|
||||
wr.Name = watch.Name
|
||||
*w = append(*w, *wr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type WatchResult struct {
|
||||
Data Data `json:"data,omitempty"`
|
||||
OwnerID int64
|
||||
Name string
|
||||
}
|
||||
type Repository struct {
|
||||
NameWithOwner string `json:"nameWithOwner,omitempty"`
|
||||
}
|
||||
type Node struct {
|
||||
Number int `json:"number,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Repository Repository `json:"repository,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
type Edges struct {
|
||||
Node Node `json:"node,omitempty"`
|
||||
}
|
||||
type Search struct {
|
||||
IssueCount int `json:"issueCount,omitempty"`
|
||||
Edges []Edges `json:"edges,omitempty"`
|
||||
}
|
||||
type RateLimit struct {
|
||||
Remaining int `json:"remaining,omitempty"`
|
||||
ResetAt time.Time `json:"resetAt,omitempty"`
|
||||
}
|
||||
type Data struct {
|
||||
Search Search `json:"search,omitempty"`
|
||||
RateLimit RateLimit `json:"rateLimit,omitempty"`
|
||||
}
|
69
queries.sql
Normal file
69
queries.sql
Normal file
@ -0,0 +1,69 @@
|
||||
-- name: AddOwner :one
|
||||
insert into owners (id, name)
|
||||
values (?, ?) returning *;
|
||||
|
||||
-- name: GetOwner :one
|
||||
select *
|
||||
from owners
|
||||
where id = ?;
|
||||
|
||||
-- name: GetAllWatchItems :many
|
||||
select *
|
||||
from watch_items;
|
||||
|
||||
-- name: GetAllWatchItemsByOwner :many
|
||||
select *
|
||||
from watch_items
|
||||
where owner_id = ?;
|
||||
|
||||
-- name: AddWatchItem :one
|
||||
insert into watch_items (owner_id, name, descr)
|
||||
values (?, ?, ?) returning *;
|
||||
|
||||
-- name: DeleteWatchItem :exec
|
||||
delete from watch_items where id = ? and owner_id = ?;
|
||||
|
||||
-- name: GetAllLinks :many
|
||||
select *
|
||||
from links
|
||||
where owner_id = ?;
|
||||
|
||||
-- name: AddLink :one
|
||||
insert into links (owner_id, url, name, logo_url)
|
||||
values (?, ?, ?, ?) returning *;
|
||||
|
||||
-- name: DeleteLink :exec
|
||||
delete from links where id = ? and owner_id = ?;
|
||||
|
||||
-- name: GetAllIcons :many
|
||||
select *
|
||||
from icons
|
||||
where owner_id = ?;
|
||||
|
||||
-- name: AddIcon :one
|
||||
insert into icons (owner_id, url, content_type, data)
|
||||
values (?, ?, ?, ?) returning *;
|
||||
|
||||
-- name: GetAllPullRequests :many
|
||||
select *
|
||||
from pull_requests
|
||||
where number not in (select number
|
||||
from pull_request_ignores
|
||||
where pull_request_ignores.owner_id = ?)
|
||||
and pull_requests.owner_id = ?;
|
||||
|
||||
-- name: AddPullRequest :one
|
||||
insert into pull_requests (owner_id, number, repo, description)
|
||||
values (?, ?, ?, ?) returning *;
|
||||
|
||||
-- name: DeletePullRequest :exec
|
||||
delete from pull_requests where id = ? and owner_id = ?;
|
||||
|
||||
-- name: GetAllPullRequestIgnores :many
|
||||
select *
|
||||
from pull_request_ignores
|
||||
where owner_id = ?;
|
||||
|
||||
-- name: AddPullRequestIgnore :one
|
||||
insert into pull_request_ignores (owner_id, number, repo)
|
||||
values (?, ?, ?) returning *;
|
51
schema.sql
Normal file
51
schema.sql
Normal file
@ -0,0 +1,51 @@
|
||||
create table owners
|
||||
(
|
||||
id integer primary key not null,
|
||||
created_at datetime default current_timestamp,
|
||||
name text not null unique
|
||||
);
|
||||
create table watch_items
|
||||
(
|
||||
id integer primary key autoincrement,
|
||||
owner_id INTEGER REFERENCES owners (id) not null,
|
||||
created_at datetime default current_timestamp not null,
|
||||
name text not null unique,
|
||||
descr text
|
||||
);
|
||||
create table pull_request_ignores
|
||||
(
|
||||
id integer primary key autoincrement,
|
||||
owner_id INTEGER REFERENCES owners (id) not null,
|
||||
created_at datetime default current_timestamp not null,
|
||||
number integer not null,
|
||||
repo text not null,
|
||||
unique (number, repo)
|
||||
);
|
||||
create table links
|
||||
(
|
||||
id integer primary key autoincrement,
|
||||
owner_id INTEGER REFERENCES owners (id) not null,
|
||||
created_at datetime default current_timestamp not null,
|
||||
url text not null unique,
|
||||
name text not null,
|
||||
logo_url text
|
||||
);
|
||||
create table pull_requests
|
||||
(
|
||||
id integer primary key autoincrement,
|
||||
owner_id INTEGER REFERENCES owners (id) not null,
|
||||
created_at datetime default current_timestamp not null,
|
||||
number integer not null unique,
|
||||
repo text not null,
|
||||
description text,
|
||||
commitid text
|
||||
);
|
||||
create table icons
|
||||
(
|
||||
id integer primary key autoincrement,
|
||||
owner_id INTEGER REFERENCES owners (id) not null,
|
||||
created_at datetime default current_timestamp not null,
|
||||
url text not null unique,
|
||||
content_type text not null,
|
||||
data blob not null
|
||||
);
|
11
sqlc.yaml
Normal file
11
sqlc.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
version: 2
|
||||
sql:
|
||||
- engine: "sqlite"
|
||||
schema: "schema.sql"
|
||||
queries: "queries.sql"
|
||||
gen:
|
||||
go:
|
||||
package: "data"
|
||||
out: "data"
|
||||
emit_json_tags: true
|
||||
emit_empty_slices: true
|
55
templates/main.html
Normal file
55
templates/main.html
Normal file
@ -0,0 +1,55 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- <link rel="stylesheet" href="assets/bolt.css">-->
|
||||
<link rel="stylesheet" href="assets/pico.css">
|
||||
<style>
|
||||
.icons li {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
margin: 10px;
|
||||
width: 130px;
|
||||
height: 130px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid black;
|
||||
list-style-type: none;
|
||||
text-align: center;
|
||||
}
|
||||
.icons li img {
|
||||
width: 50px;
|
||||
hight: 50px;
|
||||
}
|
||||
</style>
|
||||
<title>{{.Title}}::{{.Node.ComputedName}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{.Title}} for {{.Node.ComputedName}}</h1>
|
||||
<h3>Pull Requests</h3>
|
||||
<ul>
|
||||
{{range .PullRequests}}
|
||||
<li>{{.Repo}} {{.Number}} ( {{.ID}} )</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
|
||||
<h3>Watch Items</h3>
|
||||
<ul class="">
|
||||
{{range .Watches}}
|
||||
<li>{{.Name}}
|
||||
<ul>
|
||||
{{range .Data.Search.Edges}}
|
||||
<li>{{.Node.Title}} ({{.Node.CreatedAt}})</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
|
||||
<h3>Links</h3>
|
||||
<ul class="icons">
|
||||
{{range .Links}}
|
||||
<li>{{.Name}}</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
|
||||
<foot>Remaining queries: {{.CurrentLimits.Remaining}}</foot>
|
||||
</body>
|
||||
</html>
|
50
tmp.go
Normal file
50
tmp.go
Normal file
@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
"suah.dev/gostart/data"
|
||||
)
|
||||
|
||||
func tmpDBPopulate(db *sql.DB) {
|
||||
// create tables
|
||||
if _, err := db.ExecContext(app.ctx, schema); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
ownerID := int64(57395170551826799)
|
||||
|
||||
a, err := app.queries.AddOwner(app.ctx, data.AddOwnerParams{
|
||||
ID: 57395170551826799,
|
||||
Name: "europa.humpback-trout.ts.net.",
|
||||
})
|
||||
log.Println(a, err)
|
||||
|
||||
b, err := app.queries.AddLink(app.ctx, data.AddLinkParams{
|
||||
OwnerID: ownerID,
|
||||
Url: "https://tapenet.org",
|
||||
Name: "Tape::Net",
|
||||
})
|
||||
log.Println(b, err)
|
||||
|
||||
c, err := app.queries.AddPullRequest(app.ctx, data.AddPullRequestParams{
|
||||
OwnerID: ownerID,
|
||||
Number: 1234,
|
||||
Repo: "NixOS/nixpkgs",
|
||||
Description: sql.NullString{String: "who knows"},
|
||||
})
|
||||
log.Println(c, err)
|
||||
|
||||
d, err := app.queries.AddWatchItem(app.ctx, data.AddWatchItemParams{
|
||||
Name: "tailscale",
|
||||
OwnerID: ownerID,
|
||||
})
|
||||
log.Println(d, err)
|
||||
|
||||
e, err := app.queries.AddWatchItem(app.ctx, data.AddWatchItemParams{
|
||||
Name: "openssh",
|
||||
OwnerID: ownerID,
|
||||
})
|
||||
log.Println(e, err)
|
||||
}
|
Loading…
Reference in New Issue
Block a user