The code and data behind xeiaso.net
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Patron page (#122)

* implement /patrons

* bump go to 1.14

* go mod tidy

* bump go in github actions

authored by

Christine Dodrill and committed by
GitHub
1da61293 6adc88b1

+369 -12
+2
.gitattributes
··· 1 + nix/deps.nix linguist-vendored 2 + nix/sources.nix linguist-vendored
+2 -2
.github/workflows/go.yml
··· 5 5 name: Build 6 6 runs-on: ubuntu-latest 7 7 steps: 8 - - name: Set up Go 1.12 8 + - name: Set up Go 1.14 9 9 uses: actions/setup-go@v1 10 10 with: 11 - go-version: 1.12 11 + go-version: 1.14 12 12 id: go 13 13 - name: Check out code into the Go module directory 14 14 uses: actions/checkout@v1
+1 -1
Dockerfile
··· 1 - FROM xena/go:1.13.6 AS build 1 + FROM xena/go:1.14 AS build 2 2 ENV GOPROXY https://cache.greedo.xeserv.us 3 3 COPY . /site 4 4 WORKDIR /site
+52
blog/patron-page-2020-02-29.markdown
··· 1 + --- 2 + title: "New Site Feature: Patron Thanks Page" 3 + date: 2020-02-29 4 + --- 5 + 6 + # New Site Feature: Patron Thanks Page 7 + 8 + I've added a [patron thanks page](/patrons) to my site. I've been getting a 9 + significant amount of money per month from my patrons and I feel this is a good 10 + way to acknowledge them and thank them for their patronage. I wanted to have it 11 + be _as simple as possible_, so I made it fetch a list of dollar amounts. 12 + 13 + Here are some things I learned while writing this: 14 + 15 + - If you are going to interact with the patreon API in go, use 16 + [`github.com/mxpv/patreon-go`][patreongo], not `gopkg.in/mxpv/patreon-go.v1` 17 + or `gopkg.in/mxpv/patreon-go.v2`. The packages on gopkg.in are NOT compatible 18 + with Go modules in very bizarre ways. 19 + - When using refresh tokens in OAuth2, do not set the expiry date to be 20 + _negative_ like the patreon-go examples show. This will brick your token and 21 + make you have to reprovision it. 22 + - Patreon clients can either be for API version 1 or API version 2. There is no 23 + way to have a Patreon token that works for both API versions. 24 + - The patreon-go package only supports API version 1 and doesn't document this 25 + anywhere. 26 + - Patreon's error messages are vague and not helpful when trying to figure out 27 + that you broke your token with a negative expiry date. 28 + - I may need to set the Patreon information every month for the rest of the time 29 + I maintain this site code. This could get odd. I made a guide for myself in 30 + the [docs folder of the site repo][docsfolder]. 31 + - The Patreon API doesn't let you submit new posts. I wanted to add Patreon to 32 + my syndication server, but apparently that's impossible. My [RSS 33 + feed](/blog.rss), [Atom feed](/blog.atom) and [JSON feed](/blog.json) should 34 + let you keep up to date in the meantime. 35 + 36 + Let me know how you like this. I went back and forth on displaying monetary 37 + amounts on that page, but ultimately decided not to show them there for 38 + confidentiality reasons. If this is a bad idea, please let me know and I can put 39 + the money amounts back. 40 + 41 + I'm working on a more detailed post about [pa'i][pahi] that includes benchmarks 42 + for some artificial and realistic workloads. I'm also working on integrating it 43 + into the [wamscloud][wasmcloud] prototype, but it's fairly slow going at the 44 + moment. 45 + 46 + Be well. 47 + 48 + [patreongo]: https://github.com/mxpv/patreon-go 49 + [docsfolder]: https://github.com/Xe/site/tree/master/docs 50 + [pahi]: https://github.com/Xe/pahi 51 + [wasmcloud]: https://tulpa.dev/within/wasmcloud 52 +
+22 -1
cmd/site/main.go
··· 13 13 "christine.website/cmd/site/internal/middleware" 14 14 "christine.website/jsonfeed" 15 15 "github.com/gorilla/feeds" 16 + _ "github.com/joho/godotenv/autoload" 16 17 "github.com/povilasv/prommod" 17 18 "github.com/prometheus/client_golang/prometheus" 18 19 "github.com/prometheus/client_golang/prometheus/promhttp" ··· 60 61 Gallery blog.Posts 61 62 Resume template.HTML 62 63 Series []string 64 + patrons []string 63 65 64 66 rssFeed *feeds.Feed 65 67 jsonFeed *jsonfeed.Feed ··· 84 86 middleware.RequestID(s.xffmw.Handler(ex.HTTPLog(s.mux))).ServeHTTP(w, r) 85 87 } 86 88 87 - var arbDate = time.Date(2020, time.January, 9, 0, 0, 0, 0, time.UTC) 89 + var arbDate = time.Date(2020, time.February, 29, 0, 0, 0, 0, time.UTC) 88 90 89 91 // Build creates a new Site instance or fails. 90 92 func Build() (*Site, error) { 93 + pc, err := NewPatreonClient() 94 + if err != nil { 95 + return nil, err 96 + } 97 + 98 + pledges, err := GetPledges(pc) 99 + if err != nil { 100 + return nil, err 101 + } 102 + 91 103 smi := sitemap.New() 92 104 smi.Add(&sitemap.URL{ 93 105 Loc: "https://christine.website/resume", ··· 105 117 Loc: "https://christine.website/", 106 118 LastMod: &arbDate, 107 119 ChangeFreq: sitemap.Monthly, 120 + }) 121 + 122 + smi.Add(&sitemap.URL{ 123 + Loc: "https://christine.website/patrons", 124 + LastMod: &arbDate, 125 + ChangeFreq: sitemap.Weekly, 108 126 }) 109 127 110 128 smi.Add(&sitemap.URL{ ··· 143 161 }, 144 162 mux: http.NewServeMux(), 145 163 xffmw: xffmw, 164 + 165 + patrons: pledges, 146 166 } 147 167 148 168 posts, err := blog.LoadPosts("./blog/", "blog") ··· 215 235 s.renderTemplatePage("index.html", nil).ServeHTTP(w, r) 216 236 }) 217 237 s.mux.Handle("/metrics", promhttp.Handler()) 238 + s.mux.Handle("/patrons", middleware.Metrics("patrons", s.renderTemplatePage("patrons.html", s.patrons))) 218 239 s.mux.Handle("/resume", middleware.Metrics("resume", s.renderTemplatePage("resume.html", s.Resume))) 219 240 s.mux.Handle("/blog", middleware.Metrics("blog", s.renderTemplatePage("blogindex.html", s.Posts))) 220 241 s.mux.Handle("/talks", middleware.Metrics("talks", s.renderTemplatePage("talkindex.html", s.Talks)))
+112
cmd/site/patreon.go
··· 1 + package main 2 + 3 + import ( 4 + "context" 5 + "fmt" 6 + "net/http" 7 + "os" 8 + "sort" 9 + "time" 10 + 11 + "github.com/mxpv/patreon-go" 12 + "golang.org/x/oauth2" 13 + "within.website/ln" 14 + ) 15 + 16 + func NewPatreonClient() (*patreon.Client, error) { 17 + for _, name := range []string{"CLIENT_ID", "CLIENT_SECRET", "ACCESS_TOKEN", "REFRESH_TOKEN"} { 18 + if os.Getenv("PATREON_"+name) == "" { 19 + return nil, fmt.Errorf("wanted envvar PATREON_%s", name) 20 + } 21 + } 22 + 23 + config := oauth2.Config{ 24 + ClientID: os.Getenv("PATREON_CLIENT_ID"), 25 + ClientSecret: os.Getenv("PATREON_CLIENT_SECRET"), 26 + Endpoint: oauth2.Endpoint{ 27 + AuthURL: patreon.AuthorizationURL, 28 + TokenURL: patreon.AccessTokenURL, 29 + }, 30 + Scopes: []string{"users", "campaigns", "pledges", "pledges-to-me", "my-campaign"}, 31 + } 32 + 33 + token := oauth2.Token{ 34 + AccessToken: os.Getenv("PATREON_ACCESS_TOKEN"), 35 + RefreshToken: os.Getenv("PATREON_REFRESH_TOKEN"), 36 + // Must be non-nil, otherwise token will not be expired 37 + Expiry: time.Now().Add(90 * 24 * time.Hour), 38 + } 39 + 40 + tc := config.Client(context.Background(), &token) 41 + 42 + trans := tc.Transport 43 + tc.Transport = lnLoggingTransport{next: trans} 44 + client := patreon.NewClient(tc) 45 + 46 + return client, nil 47 + } 48 + 49 + func GetPledges(pc *patreon.Client) ([]string, error) { 50 + campaign, err := pc.FetchCampaign() 51 + if err != nil { 52 + return nil, fmt.Errorf("campaign fetch error: %w", err) 53 + } 54 + 55 + campaignID := campaign.Data[0].ID 56 + 57 + cursor := "" 58 + var result []string 59 + 60 + for { 61 + pledgesResponse, err := pc.FetchPledges(campaignID, patreon.WithPageSize(25), patreon.WithCursor(cursor)) 62 + if err != nil { 63 + return nil, err 64 + } 65 + 66 + users := make(map[string]*patreon.User) 67 + for _, item := range pledgesResponse.Included.Items { 68 + u, ok := item.(*patreon.User) 69 + if !ok { 70 + continue 71 + } 72 + 73 + users[u.ID] = u 74 + } 75 + 76 + for _, pledge := range pledgesResponse.Data { 77 + pid := pledge.Relationships.Patron.Data.ID 78 + patronFullName := users[pid].Attributes.FullName 79 + 80 + result = append(result, patronFullName) 81 + } 82 + 83 + cursor = pledgesResponse.Links.Next 84 + if cursor == "" { 85 + break 86 + } 87 + } 88 + 89 + sort.Strings(result) 90 + return result, nil 91 + } 92 + 93 + type lnLoggingTransport struct{ next http.RoundTripper } 94 + 95 + func (l lnLoggingTransport) RoundTrip(r *http.Request) (*http.Response, error) { 96 + ctx := r.Context() 97 + f := ln.F{ 98 + "url": r.URL.String(), 99 + "has_token": r.Header.Get("Authorization") != "", 100 + } 101 + 102 + resp, err := l.next.RoundTrip(r) 103 + if err != nil { 104 + return nil, err 105 + } 106 + 107 + f["status"] = resp.Status 108 + 109 + ln.Log(ctx, f) 110 + 111 + return resp, nil 112 + }
+45
deps.nix nix/deps.nix
··· 1 1 # file generated from go.mod using vgo2nix (https://github.com/adisbladis/vgo2nix) 2 2 [ 3 3 { 4 + goPackagePath = "cloud.google.com/go"; 5 + fetch = { 6 + type = "git"; 7 + url = "https://code.googlesource.com/gocloud"; 8 + rev = "v0.34.0"; 9 + sha256 = "1kclgclwar3r37zbvb9gg3qxbgzkb50zk3s9778zlh2773qikmai"; 10 + }; 11 + } 12 + { 4 13 goPackagePath = "github.com/alecthomas/template"; 5 14 fetch = { 6 15 type = "git"; ··· 127 136 }; 128 137 } 129 138 { 139 + goPackagePath = "github.com/joho/godotenv"; 140 + fetch = { 141 + type = "git"; 142 + url = "https://github.com/joho/godotenv"; 143 + rev = "v1.3.0"; 144 + sha256 = "0ri8if0pc3x6jg4c3i8wr58xyfpxkwmcjk3rp8gb398a1aa3gpjm"; 145 + }; 146 + } 147 + { 130 148 goPackagePath = "github.com/json-iterator/go"; 131 149 fetch = { 132 150 type = "git"; ··· 226 244 }; 227 245 } 228 246 { 247 + goPackagePath = "github.com/mxpv/patreon-go"; 248 + fetch = { 249 + type = "git"; 250 + url = "https://github.com/mxpv/patreon-go"; 251 + rev = "646111f1d983"; 252 + sha256 = "0cksf3andl8z04lychay2j0l8wrpdq7j5pdb6zy5yr4990iab6aa"; 253 + }; 254 + } 255 + { 229 256 goPackagePath = "github.com/pkg/errors"; 230 257 fetch = { 231 258 type = "git"; ··· 379 406 }; 380 407 } 381 408 { 409 + goPackagePath = "golang.org/x/oauth2"; 410 + fetch = { 411 + type = "git"; 412 + url = "https://go.googlesource.com/oauth2"; 413 + rev = "bf48bf16ab8d"; 414 + sha256 = "1sirdib60zwmh93kf9qrx51r8544k1p9rs5mk0797wibz3m4mrdg"; 415 + }; 416 + } 417 + { 382 418 goPackagePath = "golang.org/x/sync"; 383 419 fetch = { 384 420 type = "git"; ··· 412 448 url = "https://go.googlesource.com/xerrors"; 413 449 rev = "9bdfabe68543"; 414 450 sha256 = "1yjfi1bk9xb81lqn85nnm13zz725wazvrx3b50hx19qmwg7a4b0c"; 451 + }; 452 + } 453 + { 454 + goPackagePath = "google.golang.org/appengine"; 455 + fetch = { 456 + type = "git"; 457 + url = "https://github.com/golang/appengine"; 458 + rev = "v1.4.0"; 459 + sha256 = "06zl7w4sxgdq2pl94wy9ncii6h0z3szl4xpqds0sv3b3wbdlhbnn"; 415 460 }; 416 461 } 417 462 {
+77
docs/patron-page.org
··· 1 + #+TITLE: Patron Page 2 + 3 + #+BEGIN: clocktable :maxlevel 2 :emphasize nil :scope file 4 + #+CAPTION: Clock summary at [2020-02-29 Sat 20:47] 5 + | Headline | Time | | 6 + |------------------------------------------+--------+------| 7 + | *Total time* | *1:36* | | 8 + |------------------------------------------+--------+------| 9 + | figure out how to get list of patrons | 1:05 | | 10 + | \_ get patreon credentials into site | | 0:08 | 11 + | \_ figure out patreon id of my campaign | | 0:25 | 12 + | \_ get list of patrons | | 0:25 | 13 + | \_ show in HTML | | 0:07 | 14 + | figure out how to handle the secrets... | 0:03 | | 15 + | Links | 0:28 | | 16 + | \_ Announcement blogpost | | 0:28 | 17 + #+END: clocktable 18 + 19 + * DONE figure out how to get list of patrons 20 + CLOSED: [2020-02-29 Sat 20:18] 21 + ** DONE get patreon credentials into site 22 + CLOSED: [2020-02-29 Sat 19:14] 23 + :LOGBOOK: 24 + CLOCK: [2020-02-29 Sat 19:06]--[2020-02-29 Sat 19:14] => 0:08 25 + :END: 26 + 27 + Added envvars 28 + 29 + + =PATREON_CLIENT_ID= 30 + + =PATREON_CLIENT_SECRET= 31 + + =PATREON_ACCESS_TOKEN= 32 + + =PATREON_REFRESH_TOKEN= 33 + ** DONE figure out patreon id of my campaign 34 + CLOSED: [2020-02-29 Sat 19:39] 35 + :LOGBOOK: 36 + CLOCK: [2020-02-29 Sat 19:14]--[2020-02-29 Sat 19:39] => 0:25 37 + :END: 38 + ** DONE get list of patrons 39 + CLOSED: [2020-02-29 Sat 20:05] 40 + :LOGBOOK: 41 + CLOCK: [2020-02-29 Sat 19:40]--[2020-02-29 Sat 20:05] => 0:25 42 + :END: 43 + ** DONE show in HTML 44 + CLOSED: [2020-02-29 Sat 20:12] 45 + :LOGBOOK: 46 + CLOCK: [2020-02-29 Sat 20:05]--[2020-02-29 Sat 20:12] => 0:07 47 + :END: 48 + * DONE figure out how to handle the secrets for patreon 49 + CLOSED: [2020-02-29 Sat 20:18] 50 + :LOGBOOK: 51 + CLOCK: [2020-02-29 Sat 20:15]--[2020-02-29 Sat 20:18] => 0:03 52 + :END: 53 + Currently putting them in the dyson secret store, will need to figure out 54 + something else for dhall. 55 + * DONE Links 56 + CLOSED: [2020-02-29 Sat 20:47] 57 + ** DONE Add link in footer 58 + CLOSED: [2020-02-29 Sat 20:13] 59 + ** DONE Add into sitemap 60 + CLOSED: [2020-02-29 Sat 20:13] 61 + ** DONE Announcement blogpost 62 + CLOSED: [2020-02-29 Sat 20:47] 63 + :LOGBOOK: 64 + CLOCK: [2020-02-29 Sat 20:37]--[2020-02-29 Sat 20:47] => 0:10 65 + CLOCK: [2020-02-29 Sat 20:19]--[2020-02-29 Sat 20:37] => 0:18 66 + :END: 67 + 68 + * How to refresh credentials 69 + 70 + 1. Go to https://www.patreon.com/portal/registration/register-clients 71 + 2. Open Mi (API v1) 72 + 3. Hit "Refresh Token" 73 + 4. Copy access token and refresh token to 74 + ~/code/within-terraform-secret/christinewebsite.env as =PATREON_ACCESS_TOKEN= 75 + and =PATREON_REFRESH_TOKEN= 76 + 5. Commit file to repo and push 77 + 6. Retry deployment of the site
+3
go.mod
··· 3 3 require ( 4 4 github.com/celrenheit/sandflake v0.0.0-20190410195419-50a943690bc2 5 5 github.com/gorilla/feeds v1.1.1 6 + github.com/joho/godotenv v1.3.0 7 + github.com/mxpv/patreon-go v0.0.0-20190917022727-646111f1d983 6 8 github.com/povilasv/prommod v0.0.12 7 9 github.com/prometheus/client_golang v1.4.1 8 10 github.com/russross/blackfriday v2.0.0+incompatible ··· 10 12 github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect 11 13 github.com/snabb/sitemap v1.0.0 12 14 github.com/stretchr/testify v1.4.0 15 + golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d 13 16 gopkg.in/yaml.v2 v2.2.8 14 17 within.website/ln v0.8.0 15 18 )
+11 -2
go.sum
··· 1 + cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 1 2 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 2 3 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 3 4 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= ··· 32 33 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 33 34 github.com/gorilla/feeds v1.1.1 h1:HwKXxqzcRNg9to+BbvJog4+f3s/xzvtZXICcQGutYfY= 34 35 github.com/gorilla/feeds v1.1.1/go.mod h1:Nk0jZrvPFZX1OBe5NPiddPw7CfwF6Q9eqzaBbaightA= 36 + github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 37 + github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 35 38 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 36 39 github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 37 40 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= ··· 49 52 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 50 53 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 51 54 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 55 + github.com/mxpv/patreon-go v0.0.0-20190917022727-646111f1d983 h1:r32TFg+FHLnoF8PCqCQNp+R9EjMBuP62FXkD/Eqp9Us= 56 + github.com/mxpv/patreon-go v0.0.0-20190917022727-646111f1d983/go.mod h1:ksYjm2GAbGlgIP7jO9Q5/AdyE4MwwEbgQ+lFMx3hyiM= 52 57 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 53 58 github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 54 59 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= ··· 59 64 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 60 65 github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= 61 66 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 62 - github.com/prometheus/client_golang v1.4.0 h1:YVIb/fVcOTMSqtqZWSKnHpSLBxu8DKgxq8z6RuBZwqI= 63 - github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= 64 67 github.com/prometheus/client_golang v1.4.1 h1:FFSuS004yOQEtDdTq+TAOLP5xUq63KqAFYyOi8zA+Y8= 65 68 github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= 66 69 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= ··· 99 102 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 100 103 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 101 104 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 105 + golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 102 106 golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 103 107 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 108 + golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 104 109 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU= 105 110 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 111 + golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= 112 + golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 106 113 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 107 114 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 108 115 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= ··· 116 123 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 117 124 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 118 125 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 126 + google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 127 + google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 119 128 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 120 129 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 121 130 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
+20 -4
shell.nix
··· 2 2 sources = import ./nix/sources.nix; 3 3 pkgs = import sources.nixpkgs { }; 4 4 niv = (import sources.niv { }).niv; 5 - dhall-yaml = 6 - (import sources.easy-dhall-nix { inherit pkgs; }).dhall-yaml-simple; 5 + dhallpkgs = import sources.easy-dhall-nix { inherit pkgs; }; 6 + dhall-yaml = dhallpkgs.dhall-yaml-simple; 7 + dhall = dhallpkgs.dhall-simple; 7 8 xepkgs = import sources.xepkgs { inherit pkgs; }; 8 9 vgo2nix = import sources.vgo2nix { inherit pkgs; }; 9 - in pkgs.mkShell { 10 - buildInputs = [ pkgs.go xepkgs.gopls dhall-yaml niv vgo2nix ]; 10 + in with pkgs; 11 + with xepkgs; 12 + mkShell { 13 + buildInputs = [ 14 + # Go tools 15 + go 16 + goimports 17 + gopls 18 + vgo2nix 19 + 20 + # kubernetes deployment 21 + dhall 22 + dhall-yaml 23 + 24 + # dependency manager 25 + niv 26 + ]; 11 27 }
+1 -1
site.nix
··· 8 8 version = "latest"; 9 9 goPackagePath = "christine.website"; 10 10 src = ./.; 11 - goDeps = ./deps.nix; 11 + goDeps = ./nix/deps.nix; 12 12 allowGoReference = false; 13 13 14 14 preBuild = ''
+1 -1
templates/base.html
··· 68 68 <footer> 69 69 <blockquote>Copyright 2020 Christine Dodrill. Any and all opinions listed here are my own and not representative of my employers; future, past and present.</blockquote> 70 70 <br /> 71 - <p>Like what you see? Donate on <a href="https://www.patreon.com/cadey">Patreon</a>!</p> 71 + <p>Like what you see? Donate on <a href="https://www.patreon.com/cadey">Patreon</a> like <a href="/patrons">these awesome people</a>!</p> 72 72 </footer> 73 73 74 74 <script>
+20
templates/patrons.html
··· 1 + {{ define "title" }} 2 + <title>Patrons - Christine Dodrill</title> 3 + {{ end }} 4 + 5 + {{ define "content" }} 6 + <h1>Patrons</h1> 7 + 8 + <p>These awesome people donate to me on <a href="https://patreon.com/cadey">Patreon</a>. If you would like to show up in this list, please donate to me on Patreon. This is refreshed every time the site is deployed.</p> 9 + 10 + <p> 11 + <ul> 12 + {{- range . }} 13 + <li>{{ . }}</li> 14 + {{- end }} 15 + </ul> 16 + </p> 17 + 18 + <p>Thank you so much! Your support helps make my projects possible.</p> 19 + 20 + {{ end }}