directory

package
v0.0.0-...-ddef314 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 6, 2026 License: MIT Imports: 19 Imported by: 0

README

directory

Authenticated member directory: a grid of member cards (avatar, display name, pronouns, bio, leadership badge, Discord handle) plus a self-service profile editor.

Routes

All routes require authentication.

  • GET /directory - render the member grid
  • GET /directory/avatar/{id} - serve avatar PNG; ?type=discord forces the Discord avatar, otherwise profile picture is preferred with Discord avatar as fallback
  • POST /directory/picture - multipart upload of profile picture
  • GET /directory/profile - render edit form for current user
  • POST /directory/profile - update pronouns, bio, and directory_hidden flag

Schema

New lazily ALTER TABLEs the members table to add profile_picture BLOB, bio TEXT, pronouns TEXT, and directory_hidden INTEGER DEFAULT 0. Errors are ignored, which is how it tolerates the columns already existing. Avatars are stored inline in the DB as PNG blobs.

Listing behavior (queryMembers)

A member appears in the directory only if all hold:

  • access_status = 'Ready'
  • directory_hidden is 0 / NULL
  • COALESCE(name_override, name) is non-empty
  • has a non-empty profile_picture OR discord_avatar

Display name uses name_override when set, otherwise the billing name.

Ordering and privacy

Results are ordered by fob_last_seen DESC, then bucketed into 7-day windows and shuffled within each bucket (shuffleWithinBuckets). This preserves a rough recency signal without leaking who is currently at the space. The current user is then moved to the front of the list.

Image processing (image.go)

  • Upload limit: 20 MB (MaxUploadSize); enforced via http.MaxBytesReader and ParseMultipartForm
  • Accepted content types: image/jpeg, image/png only
  • ProcessProfileImage center-crops to a square, resizes to 160x160 (2x retina for the 96px display) using Catmull-Rom, and re-encodes as PNG
  • Avatar responses set Cache-Control: public, max-age=3600

Profile edit constraints

  • pronouns: max 50 chars
  • bio: max 100 chars
  • Empty strings are stored as NULL
  • After save: redirects to /directory if visible, or back to /directory/profile if directory_hidden was set (since the user wouldn't see themselves in the listing)

Templates

directory.templ and profile.templ are templ-generated (go generate runs templ generate). The profile page includes a live-updating preview card driven by inline JS.

Documentation

Overview

templ: version: v0.3.1001

templ: version: v0.3.1001

Index

Constants

View Source
const (
	MaxUploadSize = 20 * 1024 * 1024 // 20MB

)

Variables

This section is empty.

Functions

func ProcessProfileImage

func ProcessProfileImage(data []byte) ([]byte, error)

ProcessProfileImage takes raw image bytes, center-crops to a square, resizes to 160x160, and returns PNG-encoded bytes.

func ValidImageContentType

func ValidImageContentType(contentType string) bool

ValidImageContentType returns true if the content type is a valid image type.

Types

type DirectoryMember

type DirectoryMember struct {
	ID                int64
	DisplayName       string
	Pronouns          string
	Bio               string
	DiscordUsername   string
	HasProfilePicture bool
	HasDiscordAvatar  bool
	Leadership        bool
	FobLastSeen       int64
}

DirectoryMember represents a member in the directory listing.

type Module

type Module struct {
	// contains filtered or unexported fields
}

func New

func New(db *sql.DB) *Module

func (*Module) AttachRoutes

func (m *Module) AttachRoutes(router *engine.Router)

type ProfileData

type ProfileData struct {
	ID                int64
	Name              string  // Original name from signup
	NameOverride      *string // Custom display name
	Pronouns          string
	Bio               string
	HasProfilePicture bool
	HasDiscordAvatar  bool
	DiscordUsername   string
	Leadership        bool
	DirectoryHidden   bool // If true, hide this member from the directory listing
}

ProfileData represents the current user's profile for editing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL