Skip to content

Commit 37f10fc

Browse files
committed
feat(like counter): counter implemented
like counter and related db changes implemented along with bug fixes
1 parent 2842361 commit 37f10fc

27 files changed

+589
-87
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ __debug_*
3131
# DB files
3232
BloTils.db
3333
*.db
34+
*.session.sql

config.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"DBLocation": "./BloTils.db",
77
"Vacuum": "full",
88
"ForeignKeys": true
9-
}
9+
},
10+
"StaticFiles": "static"
1011
},
1112

1213
"Name": "BloTils",

go.mod

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ require (
77
github.com/mattn/go-sqlite3 v1.14.22
88
)
99

10-
require github.com/felixge/httpsnoop v1.0.3 // indirect
10+
require (
11+
github.com/felixge/httpsnoop v1.0.3 // indirect
12+
github.com/rs/cors v1.11.1 // indirect
13+
)
1114

1215
require (
1316
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
2727
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
2828
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
2929
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
30+
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
31+
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
3032
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3133
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
3234
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

src/app/app.go

+1
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,6 @@ func New(config Config) *App {
6565
Config: config,
6666
}
6767
routes.RegisterRoutes(server)
68+
routes.ServeStaticFiles(server)
6869
return app
6970
}
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,34 @@
11
CREATE TABLE IF NOT EXISTS DomainSettings (
22
id INTEGER PRIMARY KEY AUTOINCREMENT,
3-
likes NUMERIC,
4-
comments NUMERIC,
3+
likes NUMERIC check(
4+
likes = 0
5+
or likes = 1
6+
),
7+
comments NUMERIC check(
8+
comments = 0
9+
or comments = 1
10+
),
511
created_time DATETIME DEFAULT CURRENT_TIMESTAMP
612
);
713
CREATE TABLE IF NOT EXISTS Domain (
814
id INTEGER PRIMARY KEY AUTOINCREMENT,
915
settings_id INTEGER,
10-
domain VARCHAR(255),
16+
domain VARCHAR(255) UNIQUE,
1117
created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
1218
FOREIGN KEY (settings_id) REFERENCES DomainSettings(id)
1319
);
1420
CREATE TABLE IF NOT EXISTS Liked_IPs (
1521
id INTEGER PRIMARY KEY AUTOINCREMENT,
16-
ip VARCHAR(255),
17-
count INTEGER,
22+
ip VARCHAR(255) UNIQUE,
23+
count INTEGER check(count >= 0),
24+
domain VARCHAR(255),
25+
path TEXT,
1826
created_time DATETIME DEFAULT CURRENT_TIMESTAMP
1927
);
2028
CREATE TABLE IF NOT EXISTS Likes (
2129
id INTEGER PRIMARY KEY AUTOINCREMENT,
22-
uri TEXT,
23-
count INTEGER,
30+
uri TEXT UNIQUE,
31+
count INTEGER check(count >= 0),
2432
domain_id INTEGER,
25-
created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
2633
FOREIGN KEY (domain_id) REFERENCES Domain(id)
2734
);

src/db/models.go

+17-7
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type DomainSettings struct {
1818
// The domain field contains the domain name.
1919
// The timestamp field contains the timestamp for when the domain was created or updated.
2020
type Domain struct {
21-
id int
21+
ID int
2222
settings DomainSettings
2323
domain string
2424
timestamp time.Time
@@ -47,20 +47,30 @@ func (domain Domain) CommentsEnabled() bool {
4747
// The timestamp field is the timestamp of when the like was created.
4848
type Likes struct {
4949
id int
50-
domain Domain
51-
uri string
52-
count int
53-
timestamp time.Time
50+
domain_id int
51+
Domain Domain
52+
URI string
53+
Count int
5454
}
5555

5656
func (likes Likes) IsEmpty() bool {
5757
return likes == Likes{}
5858
}
5959

60+
func (likes Likes) GetDomainID() int {
61+
return likes.Domain.ID
62+
}
63+
6064
// LikedIPs represents a record of an IP address that has liked something, along with the count of likes and the timestamp of the last like.
6165
type LikedIPs struct {
6266
id int
63-
ip string
64-
count int
67+
IP string
68+
Count int
69+
Domain string
70+
Path string
6571
timestamp time.Time
6672
}
73+
74+
func (likedIPs LikedIPs) IsEmpty() bool {
75+
return likedIPs == LikedIPs{}
76+
}

src/db/query.go

+48-11
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,57 @@
11
// Package db provides functionality for interacting with the database.
22
package db
33

4-
// getDomainQuery is a SQL query that selects all rows from the Domain and DomainSettings tables
4+
// getDomain is a SQL query that selects all rows from the Domain and DomainSettings tables
55
// where the domain column in the Domain table matches the provided parameter.
66
// The query joins the two tables on the id column.
7-
const getDomainQuery string = `SELECT * FROM Domain
8-
JOIN DomainSettings
9-
ON Domain.id = DomainSettings.id
10-
WHERE domain = ?`
7+
const getDomain = `SELECT * FROM Domain
8+
JOIN DomainSettings
9+
ON Domain.id = DomainSettings.id
10+
WHERE domain = ?`
1111

12-
// getLikesQuery is a SQL query that selects all rows from the Likes table
12+
// getLikes is a SQL query that selects all rows from the Likes table
1313
// where the uri matches the provided value, and the domain matches the
1414
// provided domain. It joins the Likes table with the Domain table to
1515
// retrieve the domain information.
16-
const getLikesQuery string = `SELECT * FROM Likes
17-
JOIN Domain
18-
ON Likes.domain_id = Domain.id
19-
where Domain.domain = ?
20-
AND Likes.uri = ?`
16+
const getLikes = `SELECT
17+
Likes.id,
18+
Likes.uri,
19+
Likes.domain_id,
20+
Likes.count,
21+
Domain.id,
22+
Domain.settings_id,
23+
Domain.domain,
24+
Domain.created_time
25+
FROM Likes
26+
JOIN Domain
27+
ON Likes.domain_id = Domain.id
28+
WHERE Domain.domain = ?
29+
AND Likes.uri = ?`
30+
31+
// getIPlikedOrNot is a SQL query that selects all rows from the Liked_IPs table
32+
// where the ip, path, and domain columns match the provided parameters. This query
33+
// is used to check if a specific IP address has already been liked for a given
34+
// domain and path.
35+
const getIPlikedOrNot = `SELECT * FROM Liked_IPs
36+
WHERE Liked_IPs.ip = ?
37+
AND Liked_IPs.domain = ?
38+
AND Liked_IPs.path = ?`
39+
40+
// updateOrInsertLikedIP is a SQL query that inserts a new row into the Liked_IPs table
41+
// with the provided IP address, an initial count of 1, and the current timestamp. If a
42+
// row already exists for the provided IP address, the query updates the existing row by
43+
// incrementing the Count column by 1.
44+
const updateOrInsertLikedIP = `INSERT INTO Liked_IPs(domain, path, ip, count, created_time)
45+
VALUES(?, ?, ?, 1, datetime())
46+
ON CONFLICT(ip)
47+
DO UPDATE
48+
SET count = count + 1`
49+
50+
// updateLike is a SQL query that inserts a new row into the Likes table with the provided uri and domain_id,
51+
// and an initial count of 1. If a row already exists for the provided uri and domain_id, the query updates
52+
// the existing row by incrementing the count column by 1.
53+
const updateLike = `INSERT INTO Likes(uri, count, domain_id)
54+
VALUES (?, 1, ?)
55+
ON CONFLICT(uri)
56+
DO UPDATE
57+
SET count = count + 1`

src/db/utils.go

+42-10
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
// If the domain is not found, it returns an empty Domain.
1212
func GetDomain(db *sql.DB, domain_name string) Domain {
1313
var domain Domain
14-
err := db.QueryRow(getDomainQuery, domain_name).Scan(&domain.id,
14+
err := db.QueryRow(getDomain, domain_name).Scan(&domain.ID,
1515
&domain.settings.id,
1616
&domain.domain,
1717
&domain.timestamp,
@@ -32,15 +32,15 @@ func GetDomain(db *sql.DB, domain_name string) Domain {
3232

3333
func GetLikes(db *sql.DB, domain_name string, page string) Likes {
3434
var likes Likes
35-
err := db.QueryRow(getLikesQuery, domain_name, page).Scan(&likes.id,
36-
&likes.uri,
37-
&likes.count,
38-
&likes.domain.id,
39-
&likes.timestamp,
40-
&likes.domain.id,
41-
&likes.domain.settings.id,
42-
&likes.domain.domain,
43-
&likes.domain.timestamp)
35+
err := db.QueryRow(getLikes, domain_name, page).Scan(
36+
&likes.id,
37+
&likes.URI,
38+
&likes.domain_id,
39+
&likes.Count,
40+
&likes.Domain.ID,
41+
&likes.Domain.settings.id,
42+
&likes.Domain.domain,
43+
&likes.Domain.timestamp)
4444
if err != nil {
4545
if err == sql.ErrNoRows {
4646
log.Printf("DB: Likes On %s, Not Found In %s", page, domain_name)
@@ -51,3 +51,35 @@ func GetLikes(db *sql.DB, domain_name string, page string) Likes {
5151
}
5252
return likes
5353
}
54+
55+
func GetLikedIP(db *sql.DB, domain string, page string, ip string) LikedIPs {
56+
var likedIP LikedIPs
57+
err := db.QueryRow(getIPlikedOrNot, ip, domain, page).Scan(&likedIP.id,
58+
&likedIP.IP,
59+
&likedIP.Count,
60+
&likedIP.Domain,
61+
&likedIP.Path,
62+
&likedIP.timestamp)
63+
if err != nil {
64+
if err == sql.ErrNoRows {
65+
log.Printf("DB: IP %s, Not Found Liked in %s for %s", ip, domain, page)
66+
return LikedIPs{}
67+
}
68+
log.Printf("Error Getting Likes On %s For %s: %v", ip, page, err)
69+
return LikedIPs{}
70+
}
71+
return likedIP
72+
}
73+
74+
func UpdateIPLikeCount(db *sql.DB, domain string, path string, ip string) {
75+
_, err := db.Exec(updateOrInsertLikedIP, domain, path, ip)
76+
if err != nil {
77+
log.Printf("Error Updating IP Like Count: %v", err)
78+
}
79+
80+
}
81+
82+
func UpdateLikeCount(db *sql.DB, page string, doamin_id int) error {
83+
_, err := db.Exec(updateLike, page, doamin_id)
84+
return err
85+
}

0 commit comments

Comments
 (0)