diff --git a/database/community.go b/database/community.go new file mode 100644 index 0000000..7b79f7a --- /dev/null +++ b/database/community.go @@ -0,0 +1,77 @@ +/* + * Amsterdam Web Communities System + * Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +// The database package contains database management and storage logic. +package database + +import ( + "fmt" + "time" + + lru "github.com/hashicorp/golang-lru" +) + +// Community struct contains the high level data for a community. +type Community struct { + Id int32 `db:"commid"` + CreateDate time.Time `db:"createdate"` + LastAccess *time.Time `db:"lastaccess"` + LastUpdate *time.Time `db:"lastupdate"` + ReadLevel uint16 `db:"read_lvl"` + WriteLevel uint16 `db:"write_lvl"` + CreateLevel uint16 `db:"create_lvl"` + JoinLevel uint16 `db:"join_lvl"` + ContactId int32 `db:"contactid"` + HostUid *int32 `db:"host_uid"` + CategoryId int32 `db:"catid"` + HideFromDirectory bool `db:"hide_dir"` + HideFromSearch bool `db:"hide_search"` + MembersOnly bool `db:"membersonly"` + IsAdmin bool `db:"is_admin"` + InitFeature int16 `db:"init_ftr"` + Name string `db:"commname"` + Language *string `db:"language"` + Synopsis *string `db:"synopsis"` + Rules *string `dd:"rules"` + JoinKey *string `db:"joinkey"` + Alias string `db:"alias"` +} + +// communityCache is the cache for Community objects. +var communityCache *lru.TwoQueueCache = nil + +/* AmGetCommunity returns a reference to the specified community. + * Parameters: + * id - The ID of the community. + * Returns: + * Pointer to Community containing community data, or nil + * Standard Go error status + */ +func AmGetCommunity(id int32) (*Community, error) { + var err error = nil + if communityCache == nil { + communityCache, err = lru.New2Q(50) + if err != nil { + return nil, err + } + } + rc, ok := communityCache.Get(id) + if !ok { + var dbdata []Community + err = amdb.Select(&dbdata, "SELECT * from communities WHERE commid = ?", id) + if err != nil { + return nil, err + } + if len(dbdata) > 1 { + return nil, fmt.Errorf("AmGetCommunity(%d): too many responses(%d)", id, len(dbdata)) + } + rc = &(dbdata[0]) + communityCache.Add(id, rc) + } + return rc.(*Community), err +} diff --git a/database/user.go b/database/user.go index 0c299e2..7fb4ecf 100644 --- a/database/user.go +++ b/database/user.go @@ -10,8 +10,11 @@ package database import ( + "database/sql" "fmt" "time" + + lru "github.com/hashicorp/golang-lru" ) // User represents a user in the Amsterdam database. @@ -34,6 +37,12 @@ type User struct { DOB *time.Time `db:"dob"` } +// userCache is the cache for User objects. +var userCache *lru.TwoQueueCache = nil + +// anonUid is the UID of the "anonymous" user. +var anonUid int32 = -1 + /* AmGetUser returns a reference to the specified user. * Parameters: * uid - The UID of the user. @@ -42,15 +51,27 @@ type User struct { * Standard Go error status */ func AmGetUser(uid int32) (*User, error) { - var rc []User - err := amdb.Select(&rc, "SELECT * from users WHERE uid = ?", uid) - if err != nil { - return nil, err + var err error = nil + if userCache == nil { + userCache, err = lru.New2Q(100) + if err != nil { + return nil, err + } } - if len(rc) > 1 { - return nil, fmt.Errorf("AmGetUser(%d): too many responses(%d)", uid, len(rc)) + rc, ok := userCache.Get(uid) + if !ok { + var dbdata []User + err = amdb.Select(&dbdata, "SELECT * from users WHERE uid = ?", uid) + if err != nil { + return nil, err + } + if len(dbdata) > 1 { + return nil, fmt.Errorf("AmGetUser(%d): too many responses(%d)", uid, len(dbdata)) + } + rc = &(dbdata[0]) + userCache.Add(uid, rc) } - return &(rc[0]), err + return rc.(*User), err } /* AmGetAnonUser returns a reference to the anonymous user. @@ -59,13 +80,25 @@ func AmGetUser(uid int32) (*User, error) { * Standard Go error status */ func AmGetAnonUser() (*User, error) { - var rc []User - err := amdb.Select(&rc, "SELECT * from users WHERE is_anon = 1") - if err != nil { - return nil, err + var err error = nil + if anonUid < 0 { + var rows *sql.Rows + rows, err = amdb.Query("SELECT uid FROM users WHERE is_anon = 1") + if err == nil { + defer rows.Close() + if rows.Next() { + err = rows.Scan(&anonUid) + if err == nil && rows.Next() { + err = fmt.Errorf("should be only one anonymous user in Amsterdam database") + } + } else { + err = fmt.Errorf("no anonymous user in Amsterdam database") + } + } } - if len(rc) > 1 { - return nil, fmt.Errorf("AmGetAnonUser: too many responses(%d)", len(rc)) + var rc *User = nil + if err == nil { + rc, err = AmGetUser(anonUid) } - return &(rc[0]), err + return rc, err } diff --git a/go.mod b/go.mod index d604e58..5ce402e 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,8 @@ require ( github.com/gorilla/context v1.1.2 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.4.0 // indirect + github.com/hashicorp/golang-lru v1.0.2 + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/jmoiron/sqlx v1.4.0 // indirect github.com/labstack/echo-contrib v0.17.4 // indirect github.com/mattn/go-colorable v0.1.14 // indirect diff --git a/go.sum b/go.sum index b68c8f5..1c7f520 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,10 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/labstack/echo-contrib v0.17.4 h1:g5mfsrJfJTKv+F5uNKCyrjLK7js+ZW6HTjg4FnDxxgk= diff --git a/ui/views/sb_ftrcomm.jet b/ui/views/sb_ftrcomm.jet index 46b296b..54ddc1d 100644 --- a/ui/views/sb_ftrcomm.jet +++ b/ui/views/sb_ftrcomm.jet @@ -9,7 +9,11 @@
-

Featured Communities:

+ {{ if .CurrentUser().IsAnon }} +

Featured Communities:

+ {{ else }} +

Your Communities:

+ {{ end }}