source: server/watchlist.go

main
Last change on this file was ef1c1c7, checked in by Stefan <trsunovstefan@…>, 6 days ago

Wiki docs, phase 6 and phase 7 added

  • Property mode set to 100644
File size: 4.6 KB
RevLine 
[b715712]1package main
2
3import (
4 "database/sql"
5 "fmt"
6
7 "bp_project/server/db"
8)
9
10// ManageWatchlist - UC0007
11// Ensures the user has a default watchlist, then allows listing, adding,
12// removing entries.
13func ManageWatchlist(s *Session) {
14 wlID, err := ensureDefaultWatchlist(s.UserID)
15 if err != nil {
16 fmt.Println("Error:", err)
17 return
18 }
19 for {
20 fmt.Println("\n-- Watchlist --")
21 fmt.Println("[1] List items")
22 fmt.Println("[2] Add crypto")
23 fmt.Println("[3] Remove crypto")
24 fmt.Println("[0] Back")
25 switch prompt("> ") {
26 case "1":
27 listWatchlist(wlID)
28 case "2":
29 addToWatchlist(wlID)
30 case "3":
31 removeFromWatchlist(wlID)
32 case "0":
33 return
34 default:
35 fmt.Println("Unknown option.")
36 }
37 }
38}
39
40func ensureDefaultWatchlist(userID string) (string, error) {
41 var id string
42 err := db.DB.QueryRow(
43 `SELECT id FROM watchlists WHERE user_id = $1 ORDER BY created_at LIMIT 1`,
44 userID,
45 ).Scan(&id)
46 if err == sql.ErrNoRows {
47 err = db.DB.QueryRow(
48 `INSERT INTO watchlists (user_id, name) VALUES ($1, 'Favorites') RETURNING id`,
49 userID,
50 ).Scan(&id)
51 return id, err
52 }
53 return id, err
54}
55
56func listWatchlist(wlID string) {
57 rows, err := db.DB.Query(`
58 SELECT c.symbol, c.name, COALESCE(lp.price, 0)
59 FROM watchlist_items wi
60 JOIN crypto c ON c.id = wi.crypto_id
61 LEFT JOIN markets m ON m.crypto_id = c.id AND m.quote_currency = 'USD'
62 LEFT JOIN v_latest_prices lp ON lp.market_id = m.id
63 WHERE wi.watchlist_id = $1
64 ORDER BY c.symbol`, wlID)
65 if err != nil {
66 fmt.Println("Error:", err)
67 return
68 }
69 defer rows.Close()
70
71 fmt.Println()
72 fmt.Printf(" %-8s %-20s %15s\n", "Symbol", "Name", "Last price")
73 fmt.Println(" --------------------------------------------------")
74 empty := true
75 for rows.Next() {
76 var sym, name string
77 var price float64
78 if err := rows.Scan(&sym, &name, &price); err != nil {
79 fmt.Println("scan error:", err)
80 return
81 }
82 fmt.Printf(" %-8s %-20s %15.6f\n", sym, name, price)
83 empty = false
84 }
85 if empty {
86 fmt.Println(" (watchlist is empty)")
87 }
88}
89
[ef1c1c7]90// addToWatchlist lists the cryptos that are not on the watchlist yet,
91// numbered, and adds the one the user picks.
[b715712]92func addToWatchlist(wlID string) {
[ef1c1c7]93 rows, err := db.DB.Query(`
94 SELECT c.id, c.symbol, c.name
95 FROM crypto c
96 WHERE NOT EXISTS (SELECT 1 FROM watchlist_items wi
97 WHERE wi.watchlist_id = $1 AND wi.crypto_id = c.id)
98 ORDER BY c.symbol`, wlID)
99 if err != nil {
100 fmt.Println("Error:", err)
[b715712]101 return
102 }
[ef1c1c7]103 type option struct{ id, symbol, name string }
104 var list []option
105 for rows.Next() {
106 var o option
107 if err := rows.Scan(&o.id, &o.symbol, &o.name); err != nil {
108 rows.Close()
109 fmt.Println("scan error:", err)
110 return
111 }
112 list = append(list, o)
113 }
114 rows.Close()
115 if len(list) == 0 {
116 fmt.Println("Every crypto is already on your watchlist.")
117 return
118 }
119 fmt.Println()
120 fmt.Printf(" %-4s %-8s %s\n", "#", "Symbol", "Name")
121 fmt.Println(" ------------------------------")
122 for i, o := range list {
123 fmt.Printf(" %-4d %-8s %s\n", i+1, o.symbol, o.name)
124 }
125 k, err := pickNumber("Crypto # to add: ", len(list))
[b715712]126 if err != nil {
[ef1c1c7]127 fmt.Println(err)
[b715712]128 return
129 }
130 _, err = db.DB.Exec(
131 `INSERT INTO watchlist_items (watchlist_id, crypto_id)
132 VALUES ($1, $2)
133 ON CONFLICT (watchlist_id, crypto_id) DO NOTHING`,
[ef1c1c7]134 wlID, list[k].id,
[b715712]135 )
136 if err != nil {
137 fmt.Println("Error:", err)
138 return
139 }
[ef1c1c7]140 fmt.Printf("Added %s.\n", list[k].symbol)
[b715712]141}
142
[ef1c1c7]143// removeFromWatchlist lists the watchlist's cryptos, numbered, and removes
144// the one the user picks.
[b715712]145func removeFromWatchlist(wlID string) {
[ef1c1c7]146 rows, err := db.DB.Query(`
147 SELECT c.id, c.symbol, c.name
148 FROM watchlist_items wi
149 JOIN crypto c ON c.id = wi.crypto_id
150 WHERE wi.watchlist_id = $1
151 ORDER BY c.symbol`, wlID)
[b715712]152 if err != nil {
153 fmt.Println("Error:", err)
154 return
155 }
[ef1c1c7]156 type option struct{ id, symbol, name string }
157 var list []option
158 for rows.Next() {
159 var o option
160 if err := rows.Scan(&o.id, &o.symbol, &o.name); err != nil {
161 rows.Close()
162 fmt.Println("scan error:", err)
163 return
164 }
165 list = append(list, o)
166 }
167 rows.Close()
168 if len(list) == 0 {
169 fmt.Println("Your watchlist is empty.")
170 return
171 }
172 fmt.Println()
173 fmt.Printf(" %-4s %-8s %s\n", "#", "Symbol", "Name")
174 fmt.Println(" ------------------------------")
175 for i, o := range list {
176 fmt.Printf(" %-4d %-8s %s\n", i+1, o.symbol, o.name)
177 }
178 k, err := pickNumber("Crypto # to remove: ", len(list))
179 if err != nil {
180 fmt.Println(err)
181 return
182 }
183 if _, err := db.DB.Exec(
184 `DELETE FROM watchlist_items WHERE watchlist_id = $1 AND crypto_id = $2`,
185 wlID, list[k].id,
186 ); err != nil {
187 fmt.Println("Error:", err)
[b715712]188 return
189 }
[ef1c1c7]190 fmt.Printf("Removed %s.\n", list[k].symbol)
[b715712]191}
Note: See TracBrowser for help on using the repository browser.