aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2023-09-27 20:27:48 -0400
committerXe Iaso <me@xeiaso.net>2023-09-27 20:27:48 -0400
commit243005626f53711cb98bba06f349c159d1b91afd (patch)
tree6766366a67eea811f603fd940c59ea0bea551547
parent066bf3207ab04f75d9ed038dd1b5f78340276812 (diff)
downloadxesite-243005626f53711cb98bba06f349c159d1b91afd.tar.xz
xesite-243005626f53711cb98bba06f349c159d1b91afd.zip
add gokrazy post
Signed-off-by: Xe Iaso <me@xeiaso.net>
-rw-r--r--cmd/patreon-saasproxy/main.go146
-rw-r--r--cmd/patreon-saasproxy/var/.gitignore2
-rw-r--r--cmd/xesite/github.go (renamed from xesite/github.go)0
-rw-r--r--cmd/xesite/main.go (renamed from xesite/main.go)37
-rw-r--r--cmd/xesite/patreon.go98
-rw-r--r--dhall/package.dhall4
-rw-r--r--flake.lock33
-rw-r--r--flake.nix127
-rw-r--r--fly/patreon-saasproxy/fly.toml17
-rw-r--r--fly/xesite/fly.toml38
-rw-r--r--go.mod65
-rw-r--r--go.sum200
-rw-r--r--gomod2nix.toml183
-rw-r--r--internal/cached_token_source.go86
-rw-r--r--internal/lume/lume.go9
-rw-r--r--internal/saasproxytoken/tokensource.go68
-rw-r--r--lume/src/blog/gokrazy.mdx391
-rw-r--r--var/.gitignore2
-rw-r--r--xesite/patreon.go195
19 files changed, 1425 insertions, 276 deletions
diff --git a/cmd/patreon-saasproxy/main.go b/cmd/patreon-saasproxy/main.go
new file mode 100644
index 0000000..cfe9717
--- /dev/null
+++ b/cmd/patreon-saasproxy/main.go
@@ -0,0 +1,146 @@
+package main
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "expvar"
+ "flag"
+ "log"
+ "log/slog"
+ "net/http"
+ "os"
+ "path/filepath"
+
+ "github.com/facebookgo/flagenv"
+ _ "github.com/joho/godotenv/autoload"
+ "golang.org/x/oauth2"
+ "gopkg.in/mxpv/patreon-go.v1"
+ "tailscale.com/client/tailscale"
+ "tailscale.com/hostinfo"
+ "tailscale.com/metrics"
+ "tailscale.com/tsnet"
+ "tailscale.com/tsweb"
+ "xeiaso.net/v4/internal"
+)
+
+var (
+ clientID = flag.String("client-id", "", "Patreon client ID")
+ clientSecret = flag.String("client-secret", "", "Patreon client secret")
+ dataDir = flag.String("data-dir", "./var", "Directory to store data in")
+ tailscaleHostname = flag.String("tailscale-hostname", "patreon-saasproxy", "Tailscale hostname to use")
+
+ tokenFetches = metrics.LabelMap{Label: "host"}
+)
+
+func main() {
+ flagenv.Parse()
+ flag.Parse()
+ internal.Slog()
+
+ hostinfo.SetApp("xeiaso.net/v4/cmd/patreon-saasproxy")
+
+ expvar.Publish("gauge_xesite_patreon_token_fetch", &tokenFetches)
+
+ os.MkdirAll(*dataDir, 0700)
+ os.MkdirAll(filepath.Join(*dataDir, "tsnet"), 0700)
+
+ srv := &tsnet.Server{
+ Hostname: *tailscaleHostname,
+ Dir: filepath.Join(*dataDir, "tsnet"),
+ Logf: func(string, ...any) {},
+ }
+
+ defer srv.Close()
+
+ lc, err := srv.LocalClient()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ config := oauth2.Config{
+ ClientID: *clientID,
+ ClientSecret: *clientSecret,
+ Endpoint: oauth2.Endpoint{
+ AuthURL: patreon.AuthorizationURL,
+ TokenURL: patreon.AccessTokenURL,
+ },
+ Scopes: []string{"users", "pledges-to-me", "my-campaign"},
+ }
+
+ if !internal.FileExists(filepath.Join(*dataDir, "patreon-token.json")) {
+ val, ok := os.LookupEnv("PATREON_TOKEN_JSON_B64")
+ if !ok {
+ log.Fatal("PATREON_TOKEN_JSON_B64 not set")
+ }
+
+ fout, err := os.Create(filepath.Join(*dataDir, "patreon-token.json"))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer fout.Close()
+
+ decoded, err := base64.StdEncoding.DecodeString(val)
+ if err != nil {
+ slog.Error("can't decode token", "err", err, "val", val)
+ log.Fatal(err)
+ }
+
+ if _, err := fout.Write(decoded); err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ token, err := internal.ReadToken(filepath.Join(*dataDir, "patreon-token.json"))
+ if err != nil {
+ log.Fatalf("error reading token: %v", err)
+ }
+
+ cts := internal.CachingTokenSource(filepath.Join(*dataDir, "patreon-token.json"), &config, token)
+
+ s := &Server{
+ lc: lc,
+ cts: cts,
+ }
+
+ http.HandleFunc("/give-token", s.GiveToken)
+ http.HandleFunc("/metrics", tsweb.VarzHandler)
+
+ ln, err := srv.Listen("tcp", ":80")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ slog.Info("listening over tailscale", "hostname", *tailscaleHostname)
+
+ log.Fatal(http.Serve(ln, nil))
+}
+
+type Server struct {
+ lc *tailscale.LocalClient
+ cts oauth2.TokenSource
+}
+
+func (s *Server) GiveToken(w http.ResponseWriter, r *http.Request) {
+ whois, err := s.lc.WhoIs(r.Context(), r.RemoteAddr)
+ if err != nil {
+ slog.Error("whois failed", "err", err, "remoteAddr", r.RemoteAddr)
+ http.Error(w, "invalid remote address", http.StatusBadRequest)
+ return
+ }
+
+ tokenFetches.Add(whois.Node.Name, 1)
+
+ token, err := s.cts.Token()
+ if err != nil {
+ slog.Error("token fetch failed", "err", err)
+ http.Error(w, "token fetch failed", http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+
+ if err := json.NewEncoder(w).Encode(token); err != nil {
+ slog.Error("token encode failed", "err", err)
+ return
+ }
+}
diff --git a/cmd/patreon-saasproxy/var/.gitignore b/cmd/patreon-saasproxy/var/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/cmd/patreon-saasproxy/var/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/xesite/github.go b/cmd/xesite/github.go
index bde7c9d..bde7c9d 100644
--- a/xesite/github.go
+++ b/cmd/xesite/github.go
diff --git a/xesite/main.go b/cmd/xesite/main.go
index 31c1d4f..c37ce41 100644
--- a/xesite/main.go
+++ b/cmd/xesite/main.go
@@ -8,23 +8,30 @@ import (
"log/slog"
"net"
"net/http"
+ "os"
+ "path/filepath"
"github.com/donatj/hmacsig"
"github.com/facebookgo/flagenv"
"github.com/go-git/go-git/v5"
_ "github.com/joho/godotenv/autoload"
+ "tailscale.com/hostinfo"
+ "tailscale.com/tsnet"
"tailscale.com/tsweb"
"xeiaso.net/v4/internal"
"xeiaso.net/v4/internal/lume"
)
var (
- bind = flag.String("bind", ":3000", "Port to listen on")
- devel = flag.Bool("devel", false, "Enable development mode")
- gitBranch = flag.String("git-branch", "main", "Git branch to clone")
- gitRepo = flag.String("git-repo", "https://github.com/Xe/site", "Git repository to clone")
- githubSecret = flag.String("github-secret", "", "GitHub secret to use for webhooks")
- siteURL = flag.String("site-url", "https://xeiaso.net/", "URL to use for the site")
+ bind = flag.String("bind", ":3000", "Port to listen on")
+ devel = flag.Bool("devel", false, "Enable development mode")
+ dataDir = flag.String("data-dir", "./var", "Directory to store data in")
+ gitBranch = flag.String("git-branch", "main", "Git branch to clone")
+ gitRepo = flag.String("git-repo", "https://github.com/Xe/site", "Git repository to clone")
+ githubSecret = flag.String("github-secret", "", "GitHub secret to use for webhooks")
+ patreonSaasProxyURL = flag.String("patreon-saasproxy-url", "http://patreon-saasproxy/give-token", "URL to use for the patreon saasproxy")
+ siteURL = flag.String("site-url", "https://xeiaso.net/", "URL to use for the site")
+ tsnetHostname = flag.String("tailscale-hostname", "xesite", "Tailscale hostname to use")
)
func main() {
@@ -32,6 +39,8 @@ func main() {
flag.Parse()
internal.Slog()
+ hostinfo.SetApp("xeiaso.net/v4/cmd/xesite")
+
ctx := context.Background()
ln, err := net.Listen("tcp", *bind)
@@ -39,7 +48,20 @@ func main() {
log.Fatal(err)
}
- pc, err := NewPatreonClient()
+ os.MkdirAll(*dataDir, 0700)
+ os.MkdirAll(filepath.Join(*dataDir, "tsnet"), 0700)
+
+ srv := &tsnet.Server{
+ Hostname: *tsnetHostname + "-" + os.Getenv("FLY_REGION"),
+ Logf: func(string, ...any) {},
+ Dir: filepath.Join(*dataDir, "tsnet"),
+ }
+
+ if err := srv.Start(); err != nil {
+ log.Fatal(err)
+ }
+
+ pc, err := NewPatreonClient(srv.HTTPClient())
if err != nil {
slog.Error("can't create patreon client", "err", err)
}
@@ -51,6 +73,7 @@ func main() {
URL: *siteURL,
Development: *devel,
PatreonClient: pc,
+ DataDir: *dataDir,
})
if err != nil {
log.Fatal(err)
diff --git a/cmd/xesite/patreon.go b/cmd/xesite/patreon.go
new file mode 100644
index 0000000..94462cc
--- /dev/null
+++ b/cmd/xesite/patreon.go
@@ -0,0 +1,98 @@
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io"
+ "log/slog"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/go-git/go-git/v5"
+ "golang.org/x/oauth2"
+ "gopkg.in/mxpv/patreon-go.v1"
+ "xeiaso.net/v4/internal/lume"
+ "xeiaso.net/v4/internal/saasproxytoken"
+)
+
+var (
+ patreonWebhookSecret = flag.String("patreon-webhook-secret", "", "Patreon webhook secret")
+)
+
+func NewPatreonClient(hc *http.Client) (*patreon.Client, error) {
+ ts := saasproxytoken.RemoteTokenSource(*patreonSaasProxyURL, hc)
+ tc := oauth2.NewClient(context.Background(), ts)
+
+ client := patreon.NewClient(tc)
+ if u, err := client.FetchUser(); err != nil {
+ return nil, err
+ } else {
+ slog.Info("logged in as", "user", u.Data.Attributes.FullName)
+ }
+
+ return client, nil
+}
+
+type PatreonWebhook struct {
+ fs *lume.FS
+}
+
+func (p *PatreonWebhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if !strings.HasPrefix(r.Header.Get(patreon.HeaderEventType), "pledges:") {
+ slog.Debug("not a pledge event", "event", r.Header.Get(patreon.HeaderEventType))
+ http.Error(w, "invalid request", http.StatusBadRequest)
+ return
+ }
+
+ defer r.Body.Close()
+
+ data, err := io.ReadAll(http.MaxBytesReader(w, r.Body, 8*1024*1024)) // 8 kb limit
+ if err != nil {
+ slog.Error("error reading body", "error", err)
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+
+ ok, err := patreon.VerifySignature(data, *patreonWebhookSecret, r.Header.Get(patreon.HeaderSignature))
+ if err != nil {
+ slog.Error("error verifying signature", "error", err)
+ http.Error(w, "error reading body", http.StatusBadRequest)
+ return
+ }
+
+ if !ok {
+ slog.Error("invalid signature")
+ http.Error(w, "error reading body", http.StatusBadRequest)
+ return
+ }
+
+ webhookCount.Add("patreon", 1)
+
+ var event patreon.WebhookPledge
+ if err := json.Unmarshal(data, &event); err != nil {
+ slog.Error("error decoding event", "error", err)
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+
+ slog.Info("new pledge!", "patron", event.Data.Relationships.Patron.Data.ID, "pledge", event.Data.ID, "amount", event.Data.Attributes.AmountCents)
+
+ go func() {
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
+ defer cancel()
+ if err := p.fs.Update(ctx); err != nil {
+ buildErrors.Add(err.Error(), 1)
+ if err == git.NoErrAlreadyUpToDate {
+ slog.Info("already up to date")
+ return
+ }
+
+ slog.Error("error updating", "error", err)
+ }
+ }()
+
+ fmt.Fprintln(w, "Rebuild triggered")
+}
diff --git a/dhall/package.dhall b/dhall/package.dhall
index 33ff48c..74aa011 100644
--- a/dhall/package.dhall
+++ b/dhall/package.dhall
@@ -25,6 +25,10 @@ in Config::{
, "Sir Terry Pratchett"
, "Satoru Iwata"
, "Kris NĂ³va"
+ , "Joe Armstrong"
+ , "Paul Allen"
+ , "Kevin Mitnick"
+ , "Sir Clive Sinclair"
]
, jobHistory = ./jobHistory.dhall
, seriesDescriptions = desc.descriptions
diff --git a/flake.lock b/flake.lock
index f6335b0..ec00c75 100644
--- a/flake.lock
+++ b/flake.lock
@@ -239,26 +239,6 @@
"type": "github"
}
},
- "naersk": {
- "inputs": {
- "nixpkgs": [
- "nixpkgs"
- ]
- },
- "locked": {
- "lastModified": 1694081375,
- "narHash": "sha256-vzJXOUnmkMCm3xw8yfPP5m8kypQ3BhAIRe4RRCWpzy8=",
- "owner": "nix-community",
- "repo": "naersk",
- "rev": "3f976d822b7b37fc6fb8e6f157c2dd05e7e94e89",
- "type": "github"
- },
- "original": {
- "owner": "nix-community",
- "repo": "naersk",
- "type": "github"
- }
- },
"nixpkgs": {
"locked": {
"lastModified": 1678898370,
@@ -276,11 +256,11 @@
},
"nixpkgs_2": {
"locked": {
- "lastModified": 1695145219,
- "narHash": "sha256-Eoe9IHbvmo5wEDeJXKFOpKUwxYJIOxKUesounVccNYk=",
+ "lastModified": 1695644571,
+ "narHash": "sha256-asS9dCCdlt1lPq0DLwkVBbVoEKuEuz+Zi3DG7pR/RxA=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "5ba549eafcf3e33405e5f66decd1a72356632b96",
+ "rev": "6500b4580c2a1f3d0f980d32d285739d8e156d92",
"type": "github"
},
"original": {
@@ -296,7 +276,6 @@
"flake-utils": "flake-utils",
"gomod2nix": "gomod2nix",
"iosevka": "iosevka",
- "naersk": "naersk",
"nixpkgs": "nixpkgs_2",
"typst": "typst"
}
@@ -383,11 +362,11 @@
]
},
"locked": {
- "lastModified": 1695284807,
- "narHash": "sha256-y7kf1ziudYVm5wl50M5CFxjWYW9TAjAZ7YPGyxhleSo=",
+ "lastModified": 1695810029,
+ "narHash": "sha256-L2twUdRypSWCfyFCirUEz679WcXBHMYNca+SpQeHF40=",
"owner": "typst",
"repo": "typst",
- "rev": "3dcbe859fb6c0db3672feddf4c2b5043d5c24e0e",
+ "rev": "ffcd951bc8a698af99d43f5245aea47a7c09adaf",
"type": "github"
},
"original": {
diff --git a/flake.nix b/flake.nix
index e1837d5..58e774e 100644
--- a/flake.nix
+++ b/flake.nix
@@ -10,11 +10,6 @@
flake = false;
};
- naersk = {
- url = "github:nix-community/naersk";
- inputs.nixpkgs.follows = "nixpkgs";
- };
-
deno2nix = {
url = "github:Xe/deno2nix";
inputs.nixpkgs.follows = "nixpkgs";
@@ -35,12 +30,24 @@
};
outputs =
- { self, nixpkgs, flake-utils, naersk, deno2nix, iosevka, typst, gomod2nix, ... }:
- flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ] (system:
+ { self
+ , nixpkgs
+ , flake-utils
+ , deno2nix
+ , iosevka
+ , typst
+ , gomod2nix
+ , ...
+ }:
+ flake-utils.lib.eachSystem [
+ "x86_64-linux"
+ "aarch64-linux"
+ "aarch64-darwin"
+ ]
+ (system:
let
- graft = pkgs: pkg: pkg.override {
- buildGoModule = pkgs.buildGo121Module;
- };
+ graft = pkgs: pkg:
+ pkg.override { buildGoModule = pkgs.buildGo121Module; };
pkgs = import nixpkgs {
inherit system;
overlays = [
@@ -55,17 +62,13 @@
gomod2nix.overlays.default
];
};
- naersk-lib = naersk.lib."${system}";
src = ./.;
lib = pkgs.lib;
- tex = with pkgs;
- texlive.combine { inherit (texlive) scheme-medium bitter titlesec; };
-
fontsConf = pkgs.symlinkJoin {
- name = "typst-fonts";
- paths = [ "${self.packages.${system}.iosevka}/static/css/iosevka" ];
- };
+ name = "typst-fonts";
+ paths = [ "${self.packages.${system}.iosevka}/static/css/iosevka" ];
+ };
typstWithIosevka = pkgs.writeShellApplication {
name = "typst";
@@ -79,29 +82,83 @@
};
# Generate a user-friendly version number.
- version = builtins.substring 0 8 self.lastModifiedDate;
- in rec {
+ version = builtins.substring 0 8 self.lastModifiedDate;
+ in
+ rec {
packages = rec {
bin = pkgs.buildGoApplication {
pname = "xesite_v4";
inherit version;
src = ./.;
modules = ./gomod2nix.toml;
- subPackages = [ "xesite" ];
+ subPackages = [ "cmd/xesite" ];
+ };
+
+ patreon-bin = pkgs.buildGoApplication {
+ pname = "patreon-saasproxy";
+ inherit version;
+ src = ./.;
+ modules = ./gomod2nix.toml;
+ subPackages = [ "cmd/patreon-saasproxy" ];
+ };
+
+ iosevka = pkgs.stdenvNoCC.mkDerivation {
+ name = "xesite-iosevka";
+ buildInputs = with pkgs; [
+ python311Packages.brotli
+ python311Packages.fonttools
+ ];
+ dontUnpack = true;
+ buildPhase = ''
+ mkdir -p out
+ ${pkgs.unzip}/bin/unzip ${
+ self.inputs.iosevka.packages.${system}.default
+ }/ttf.zip
+ for ttf in ttf/*.ttf; do
+ cp $ttf out
+ name=`basename -s .ttf $ttf`
+ pyftsubset \
+ $ttf \
+ --output-file=out/"$name".woff2 \
+ --flavor=woff2 \
+ --layout-features=* \
+ --no-hinting \
+ --desubroutinize \
+ --unicodes="U+0000-0170,U+00D7,U+00F7,U+2000-206F,U+2074,U+20AC,U+2122,U+2190-21BB,U+2212,U+2215,U+F8FF,U+FEFF,U+FFFD,U+00E8"
+ done
+
+ '';
+ installPhase = ''
+ mkdir -p $out/static/css/iosevka
+ cp out/* $out/static/css/iosevka
+ '';
};
docker = pkgs.dockerTools.buildLayeredImage {
- name = "xena/xesite";
- tag = version;
- contents = with pkgs; [ ca-certificates typstWithIosevka dhall-json deno ];
+ name = "ghcr.io/xe/site/bin";
+ tag = "latest";
+ contents = with pkgs; [ cacert typst-dev dhall-json deno pagefind ];
config = {
Cmd = [ "${bin}/bin/xesite" ];
Env = [
- "TMPDIR=/data"
+ "HOME=/data"
+ "DHALL_PRELUDE=${pkgs.dhallPackages.Prelude}"
+ "TYPST_FONT_PATHS=${fontsConf}"
+ ];
+ Volumes."/data" = { };
+ };
+ };
+
+ patreon-docker = pkgs.dockerTools.buildLayeredImage {
+ name = "ghcr.io/xe/site/patreon";
+ tag = "latest";
+ contents = with pkgs; [ cacert ];
+ config = {
+ Cmd = [ "${patreon-bin}/bin/patreon-saasproxy" ];
+ Env = [
+ "HOME=/data"
];
- Volumes = {
- "/data" = {};
- };
+ Volumes."/data" = { };
};
};
};
@@ -113,13 +170,12 @@
go-tools
gotools
gopls
+ gomod2nix.packages.${system}.default
# dhall
dhall
dhall-json
- tex
- pandoc
- #typstWithIosevka
+ typst-dev
pagefind
# frontend
@@ -135,15 +191,10 @@
python311Packages.fonttools
];
- SITE_PREFIX = "devel.";
- CLACK_SET = "Ashlynn,Terry Davis,Dennis Ritchie";
- ESBUILD_BINARY_PATH = "${pkgs.esbuild}/bin/esbuild";
- RUST_LOG = "debug";
- RUST_BACKTRACE = "1";
GITHUB_SHA = "devel";
DHALL_PRELUDE = "${pkgs.dhallPackages.Prelude}";
+ TYPST_FONT_PATHS = "${fontsConf}";
+ FLY_REGION = "dev";
};
- }) // {
- nixosModules.default = import ./nix/xesite.nix self;
- };
+ });
}
diff --git a/fly/patreon-saasproxy/fly.toml b/fly/patreon-saasproxy/fly.toml
new file mode 100644
index 0000000..ad05073
--- /dev/null
+++ b/fly/patreon-saasproxy/fly.toml
@@ -0,0 +1,17 @@
+# fly.toml file generated for xesite-patreon-saasproxy on 2023-09-27T19:47:18-04:00
+
+app = "xesite-patreon-saasproxy"
+
+kill_signal = "SIGINT"
+kill_timeout = 5
+processes = []
+
+[mounts]
+source = "data"
+destination = "/data"
+
+[env]
+DATA_DIR = "/data"
+
+[build]
+image = "ghcr.io/xe/site/patreon:latest"
diff --git a/fly/xesite/fly.toml b/fly/xesite/fly.toml
new file mode 100644
index 0000000..d897352
--- /dev/null
+++ b/fly/xesite/fly.toml
@@ -0,0 +1,38 @@
+# fly.toml file generated for xesite on 2023-09-27T19:39:44-04:00
+
+app = "xesite"
+
+kill_signal = "SIGINT"
+kill_timeout = 5
+
+[mounts]
+source = "data"
+destination = "/data"
+
+[build]
+image = "ghcr.io/xe/site/bin:latest"
+
+[env]
+DATA_DIR = "/data"
+GIT_BRANCH = "static_site"
+SITE_URL = "https://xesite.fly.dev"
+PATH = "/bin"
+
+[[services]]
+ internal_port = 3000
+ processes = ["app"]
+ protocol = "tcp"
+
+ [services.concurrency]
+ hard_limit = 300
+ soft_limit = 250
+ type = "connections"
+
+ [[services.ports]]
+ force_https = true
+ handlers = ["http"]
+ port = 80
+
+ [[services.ports]]
+ handlers = ["tls", "http"]
+ port = 443
diff --git a/go.mod b/go.mod
index ad15f2a..fd153e1 100644
--- a/go.mod
+++ b/go.mod
@@ -7,36 +7,88 @@ require (
github.com/facebookgo/flagenv v0.0.0-20160425205200-fcd59fca7456
github.com/go-git/go-git/v5 v5.9.0
github.com/joho/godotenv v1.5.1
+ golang.org/x/oauth2 v0.12.0
+ gopkg.in/mxpv/patreon-go.v1 v1.0.0-20171031001022-1d2f253ac700
tailscale.com v1.48.2
+ within.website/x v1.7.0
)
require (
dario.cat/mergo v1.0.0 // indirect
+ filippo.io/edwards25519 v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
github.com/acomagu/bufpipe v1.0.4 // 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.18.0 // indirect
+ github.com/aws/aws-sdk-go-v2/config v1.18.22 // indirect
+ github.com/aws/aws-sdk-go-v2/credentials v1.13.21 // indirect
+ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 // indirect
+ github.com/aws/aws-sdk-go-v2/service/ssm v1.36.3 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sso v1.12.9 // indirect
+ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.9 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sts v1.18.10 // indirect
+ github.com/aws/smithy-go v1.13.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
+ github.com/coreos/go-iptables v0.6.0 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
+ github.com/dblohm7/wingoes v0.0.0-20230803162905-5c6286bb8c6e // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c // indirect
- github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 // indirect
+ github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
+ github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
+ github.com/google/btree v1.1.2 // indirect
+ github.com/google/go-cmp v0.5.9 // indirect
+ github.com/google/nftables v0.1.1-0.20230115205135-9aa6fdf5a28c // indirect
+ github.com/hdevalence/ed25519consensus v0.1.0 // indirect
+ github.com/illarion/gonotify v1.0.1 // indirect
+ github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
+ github.com/jmespath/go-jmespath v0.4.0 // indirect
+ github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 // indirect
+ github.com/jsimonetti/rtnetlink v1.3.2 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
+ github.com/klauspost/compress v1.16.7 // indirect
+ github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+ github.com/mdlayher/genetlink v1.3.2 // indirect
+ github.com/mdlayher/netlink v1.7.2 // indirect
+ github.com/mdlayher/sdnotify v1.0.0 // indirect
+ github.com/mdlayher/socket v0.4.1 // indirect
+ github.com/miekg/dns v1.1.55 // indirect
+ github.com/mitchellh/go-ps v1.0.0 // indirect
+ github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.15.1 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/sergi/go-diff v1.3.1 // indirect
github.com/skeema/knownhosts v1.2.0 // indirect
+ github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d // indirect
+ github.com/tailscale/golang-x-crypto v0.0.0-20230713185742-f0b76a10a08e // 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/tailscale/wireguard-go v0.0.0-20230710185534-bb2c8f22eccf // indirect
+ github.com/tcnksm/go-httpstat v0.2.0 // indirect
+ github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect
+ github.com/vishvananda/netlink v1.2.1-beta.2 // indirect
+ github.com/vishvananda/netns v0.0.4 // indirect
+ github.com/x448/float16 v0.8.4 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
go4.org/mem v0.0.0-20220726221520-4f986261bf13 // indirect
go4.org/netipx v0.0.0-20230728180743-ad4cb58a6516 // indirect
@@ -44,11 +96,18 @@ require (
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.15.0 // indirect
- golang.org/x/oauth2 v0.12.0 // indirect
+ golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.12.0 // indirect
+ golang.org/x/term v0.12.0 // indirect
+ golang.org/x/text v0.13.0 // indirect
+ golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.13.0 // indirect
+ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
+ golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect
- gopkg.in/mxpv/patreon-go.v1 v1.0.0-20171031001022-1d2f253ac700 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
+ gvisor.dev/gvisor v0.0.0-20230504175454-7b0a1988a28f // indirect
+ inet.af/peercred v0.0.0-20210906144145-0893ea02156a // indirect
+ nhooyr.io/websocket v1.8.7 // indirect
)
diff --git a/go.sum b/go.sum
index c4cda2e..15f7640 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,11 @@
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
+filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
+filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
+filippo.io/mkcert v1.4.4 h1:8eVbbwfVlaqUM7OwuftKc2nuYOoTDQWqsoXmzoXZdbc=
+filippo.io/mkcert v1.4.4/go.mod h1:VyvOchVuAye3BoUsPUOOofKygVwLV2KQMVFJNRq+1dA=
+github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
+github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
@@ -7,22 +13,60 @@ github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCv
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
+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/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
+github.com/aws/aws-sdk-go-v2 v1.18.0 h1:882kkTpSFhdgYRKVZ/VCgf7sd0ru57p2JCxz4/oN5RY=
+github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
+github.com/aws/aws-sdk-go-v2/config v1.18.22 h1:7vkUEmjjv+giht4wIROqLs+49VWmiQMMHSduxmoNKLU=
+github.com/aws/aws-sdk-go-v2/config v1.18.22/go.mod h1:mN7Li1wxaPxSSy4Xkr6stFuinJGf3VZW3ZSNvO0q6sI=
+github.com/aws/aws-sdk-go-v2/credentials v1.13.21 h1:VRiXnPEaaPeGeoFcXvMZOB5K/yfIXOYE3q97Kgb0zbU=
+github.com/aws/aws-sdk-go-v2/credentials v1.13.21/go.mod h1:90Dk1lJoMyspa/EDUrldTxsPns0wn6+KpRKpdAWc0uA=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 h1:jJPgroehGvjrde3XufFIJUZVK5A2L9a3KwSFgKy9n8w=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3/go.mod h1:4Q0UFP0YJf0NrsEuEYHpM9fTSEVnD16Z3uyEF7J9JGM=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 h1:kG5eQilShqmJbv11XL1VpyDbaEJzWxd4zRiCG30GSn4=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 h1:vFQlirhuM8lLlpI7imKOMsjdQLuN9CPi+k44F/OFVsk=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 h1:gGLG7yKaXG02/jBlg210R7VgQIotiQntNhsCFejawx8=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34/go.mod h1:Etz2dj6UHYuw+Xw830KfzCfWGMzqvUTCjUj5b76GVDc=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 h1:0iKliEXAcCa2qVtRs7Ot5hItA2MsufrphbRFlz1Owxo=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27/go.mod h1:EOwBD4J4S5qYszS5/3DpkejfuK+Z5/1uzICfPaZLtqw=
+github.com/aws/aws-sdk-go-v2/service/ssm v1.36.3 h1:TQZH0Djie8VVgTBDOQ02M4zVHJFrNzLMsYMbNfRitVM=
+github.com/aws/aws-sdk-go-v2/service/ssm v1.36.3/go.mod h1:p6MaesK9061w6NTiFmZpUzEkKUY5blKlwD2zYyErxKA=
+github.com/aws/aws-sdk-go-v2/service/sso v1.12.9 h1:GAiaQWuQhQQui76KjuXeShmyXqECwQ0mGRMc/rwsL+c=
+github.com/aws/aws-sdk-go-v2/service/sso v1.12.9/go.mod h1:ouy2P4z6sJN70fR3ka3wD3Ro3KezSxU6eKGQI2+2fjI=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.9 h1:TraLwncRJkWqtIBVKI/UqBymq4+hL+3M