Get an ever updating ics link for all the events you RSVP to on the Atmosphere whenslunch.app
0

Configure Feed

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

home page

+133 -8
+2 -2
.air.toml
··· 4 4 5 5 [build] 6 6 args_bin = [] 7 - bin = "./tmp/main" 8 - cmd = "go build -o ./tmp/main ./cmd" 7 + bin = "./tmp/whenslunch" 8 + cmd = "go build -o ./tmp/whenslunch ./cmd/whenslunch/" 9 9 delay = 500 10 10 exclude_dir = ["assets", "tmp", "vendor", "testdata"] 11 11 exclude_file = []
+48
server/homeHandlers.go
··· 1 + package server 2 + 3 + import ( 4 + "fmt" 5 + "net/http" 6 + "strings" 7 + 8 + "github.com/bluesky-social/indigo/atproto/syntax" 9 + "github.com/labstack/echo/v5" 10 + ) 11 + 12 + // home renders the landing page. When a handle (or DID) is submitted via the 13 + // ?handle= query param it resolves it to a DID and shows the calendar feed URLs. 14 + func (s *Server) home(c *echo.Context) error { 15 + data := map[string]any{ 16 + "Title": "When's Lunch?", 17 + } 18 + 19 + raw := strings.TrimSpace(c.QueryParam("handle")) 20 + if raw == "" { 21 + return c.Render(http.StatusOK, "home.html", data) 22 + } 23 + 24 + // Repopulate the input with what the user submitted. 25 + data["Handle"] = raw 26 + 27 + identifier := strings.TrimPrefix(raw, "@") 28 + var repoDID syntax.DID 29 + if strings.HasPrefix(identifier, "did:") { 30 + repoDID = syntax.DID(identifier) 31 + } else { 32 + resolved, err := s.cdir.ResolveHandle(c.Request().Context(), syntax.Handle(identifier)) 33 + if err != nil { 34 + data["Error"] = fmt.Sprintf("Could not resolve %q. Double-check the handle and try again.", raw) 35 + return c.Render(http.StatusOK, "home.html", data) 36 + } 37 + repoDID = resolved 38 + } 39 + 40 + base := fmt.Sprintf("%s://%s", c.Scheme(), c.Request().Host) 41 + goingURL := fmt.Sprintf("%s/events/%s", base, repoDID) 42 + 43 + data["DID"] = repoDID.String() 44 + data["GoingURL"] = goingURL 45 + data["InterestedURL"] = goingURL + "?includeInterested=true" 46 + 47 + return c.Render(http.StatusOK, "home.html", data) 48 + }
+1 -5
server/server.go
··· 39 39 Template: template.Must(template.ParseFS(templatesFS, "templates/*.html")), 40 40 } 41 41 42 - e.GET("/", func(c *echo.Context) error { 43 - return c.Render(http.StatusOK, "home.html", map[string]any{ 44 - "Title": "When's Lunch?", 45 - }) 46 - }) 42 + e.GET("/", srv.home) 47 43 e.GET("/events/:identity", srv.getEventsForUser) 48 44 49 45 port := viper.Get("server.port")
+82 -1
server/templates/home.html
··· 8 8 <body> 9 9 <main> 10 10 <h1>{{ .Title }}</h1> 11 - <p></p> 11 + 12 + <h2>Calendar feeds for Atmosphere events</h2> 13 + <p> 14 + Ever signed up for an event with 15 + <a href="https://atmo.rsvp">atmo.rsvp</a> or 16 + <a href="https://smokesignal.events">Smoke Signal</a> and wish it would 17 + automatically show up on your calendar? Well now they can with this! You 18 + will never be worndering again when's lunch. 19 + </p> 20 + <a href="https://tangled.org/pds.dad/whens-lunch" 21 + >View source code on tangled.org</a 22 + > 23 + <ul> 24 + <li> 25 + <code>/events/{handle-or-did}</code> &mdash; events you're 26 + <strong>going</strong> to. 27 + </li> 28 + <li> 29 + <code>/events/{handle-or-did}?includeInterested=true</code> &mdash; 30 + events you're <strong>going</strong> to <em>or</em> 31 + <strong>interested</strong> in. 32 + </li> 33 + </ul> 34 + 35 + <h2>Get your feed URLs</h2> 36 + <form method="get" action="/"> 37 + <label for="handle">Atmosphere handle:</label> 38 + <input 39 + id="handle" 40 + name="handle" 41 + value="{{ .Handle }}" 42 + placeholder="@ngerakines.me" 43 + /> 44 + <button type="submit">Get URLs</button> 45 + </form> 46 + 47 + {{ if .Error }} 48 + <p>{{ .Error }}</p> 49 + {{ end }} {{ if .DID }} 50 + <h3>Feed URLs for {{ .Handle }}</h3> 51 + 52 + <p> 53 + <strong>Going:</strong><br /> 54 + <code id="going-url">{{ .GoingURL }}</code> 55 + <button type="button" onclick="copyUrl('going-url')">Copy</button> 56 + </p> 57 + 58 + <p> 59 + <strong>Going + interested:</strong><br /> 60 + <code id="interested-url">{{ .InterestedURL }}</code> 61 + <button type="button" onclick="copyUrl('interested-url')">Copy</button> 62 + </p> 63 + 64 + <h2>Adding to Apple Calendar</h2> 65 + <ol> 66 + <li>Open Apple Calendar</li> 67 + <li>Go to File → New Calendar Subscription</li> 68 + <li>Paste the URL above and click Subscribe</li> 69 + </ol> 70 + 71 + <h2>Adding to Google Calendar</h2> 72 + <ol> 73 + <li>Open Google Calendar in your browser</li> 74 + <li>Click the + next to "Other calendars" in the sidebar</li> 75 + <li>Select "From URL"</li> 76 + <li>Paste the URL above and click "Add calendar"</li> 77 + </ol> 78 + {{ end }} 79 + 80 + <p> 81 + Thank you <a href="https://atmo.rsvp/calendar">atmo.rsvp</a> for the 82 + directions as well as providing a similar feed 83 + </p> 12 84 </main> 85 + 86 + <script> 87 + function copyUrl(id) { 88 + const el = document.getElementById(id); 89 + if (el) { 90 + navigator.clipboard.writeText(el.textContent.trim()); 91 + } 92 + } 93 + </script> 13 94 </body> 14 95 </html>