diff --git a/README.md b/README.md index 7514898..6ce1eb8 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ within a restricted amount of time to make art. 2. Run the command `go run .` inside this folder 3. View the website at [127.0.0.1:8080](http://127.0.0.1:8080/) +You can choose a different IP address or port using the flags: +`go run . -ip=192.168.0.1 -port=3000` + ## Go project structure * [go.mod](go.mod) Go version and library dependencies * [go.sum](go.sum) Checksums for libraries @@ -24,4 +27,4 @@ CSS framework. * [Registration page](static/register.html) yaya -testing \ No newline at end of file +testing diff --git a/cat.jpg b/cat.jpg new file mode 100644 index 0000000..37e3107 Binary files /dev/null and b/cat.jpg differ diff --git a/email.go b/email.go new file mode 100644 index 0000000..06b0eb8 --- /dev/null +++ b/email.go @@ -0,0 +1,42 @@ +package main + +import ( + "crypto/tls" + "fmt" + "gopkg.in/gomail.v2" + "net/smtp" +) + +func Send(body string) { + from := "xterminate18181@gmail.com" + pass := "nvzp fodm ihzw gter" + to := "joson.anthoney@frontdomain.org" + + msg := "From: " + from + "\n" + + "To: " + to + "\n" + + "Subject: Hello there\n\n" + + body + + err := smtp.SendMail("smtp.gmail.com:587", + smtp.PlainAuth("", from, pass, "smtp.gmail.com"), + from, []string{to}, []byte(msg)) + + if err != nil { + fmt.Printf("smtp error: %s", err) + return + } + fmt.Println("Successfully sended to " + to) +} + +func MailTest() { + d := gomail.NewDialer("smtp.gmail.com", 587, "xterminate18181@gmail.com", "nvzp fodm ihzw gter") + d.TLSConfig = &tls.Config{InsecureSkipVerify: true} + m := gomail.NewMessage() + m.SetHeader("From", "xterminate18181@gmail.com") + m.SetHeader("To", "logan@gatlintc.com") + m.SetHeader("Subject", "Confirm Email") + m.SetBody("text/html", "Test body") + if err := d.DialAndSend(m); err != nil { + panic(err) + } +} diff --git a/go.mod b/go.mod index 55c3846..69ffa76 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,8 @@ require ( golang.org/x/crypto v0.27.0 ) -require github.com/gorilla/securecookie v1.1.2 // indirect +require ( + github.com/gorilla/securecookie v1.1.2 // indirect + gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect + gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect +) diff --git a/go.sum b/go.sum index b04990b..1b240e4 100644 --- a/go.sum +++ b/go.sum @@ -6,3 +6,7 @@ github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzq github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= +gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= +gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= diff --git a/server.go b/server.go index 6b9f195..d9f2c3b 100644 --- a/server.go +++ b/server.go @@ -1,6 +1,7 @@ package main import ( + "flag" "fmt" "log" "net/http" @@ -8,8 +9,8 @@ import ( "github.com/gorilla/sessions" ) -const ADDRESS = "127.0.0.1" -const PORT = "8080" +const CANVAS_WIDTH = 1000 +const CANVAS_HEIGHT = 1000 type Server struct { // Registered user information @@ -19,12 +20,19 @@ type Server struct { } func main() { + // Grab command line arguments + ipFlag := flag.String("ip", "127.0.0.1", "IP address to receive traffic from") + portFlag := flag.String("port", "8080", "Port to receive traffic from") + flag.Parse() + address := *ipFlag + port := *portFlag // Create server object secret := []byte("super-secret-key") server := Server{ Users: make(map[string]UserData), Sessions: sessions.NewCookieStore(secret), } + // Host static files static_files := http.FileServer(http.Dir("static/")) http.Handle("/", static_files) @@ -39,9 +47,10 @@ func main() { http.Redirect(w, r, "/", http.StatusFound) }) http.HandleFunc("/secret", server.secret) + http.HandleFunc("/confirm-email", server.handle_confirmation) // Start web server at 127.0.0.1:8080 - fmt.Printf("Listening to %s on port %s...\n", ADDRESS, PORT) - err := http.ListenAndServe(ADDRESS+":"+PORT, nil) + fmt.Printf("Listening to %s on port %s...\n", address, port) + err := http.ListenAndServe(address+":"+port, nil) // Print any errors if err != nil { fmt.Println("Error starting server:") diff --git a/static/canvas.css b/static/canvas.css new file mode 100644 index 0000000..82b4c9c --- /dev/null +++ b/static/canvas.css @@ -0,0 +1,70 @@ +* { + padding: 0; + margin: 0; +} + +html, body { + height: 100%; +} + +.wrapper { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.navbarCont { + background-color: grey; + width: 100%; + text-align: center; + margin-bottom: 10px; +} + +.canvasCont { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: yellow; + border: solid black; + border-radius: 20px; +} + +.toolbar { + display: flex; + justify-content: space-around; + align-items: center; + border-top: solid black 1px; + width: 100%; + height: 60px; + z-index: 10; +} + +.toolbarItems { + display: flex; + flex-direction: column; + justify-content: center; + font-weight: 900; + color: blue; + text-align: center; + height: 100%; + width: 100px; +} + +.strokePicker { + padding: 0; + margin: 0; + width: 100%; +} + +.strokePicker:hover { + cursor: pointer; +} + + +canvas { + background-color: lightblue; + margin: 20px; + image-rendering: pixelated; +} diff --git a/static/canvas.html b/static/canvas.html index e8e4dc2..031a8be 100644 --- a/static/canvas.html +++ b/static/canvas.html @@ -7,8 +7,32 @@ UTSA Placeholders + - - + +
+ + +
+ +
+
+ +
+
+ + +
+
+ +
+
+
+ +
+ + \ No newline at end of file diff --git a/static/canvas.js b/static/canvas.js new file mode 100644 index 0000000..236e9cb --- /dev/null +++ b/static/canvas.js @@ -0,0 +1,107 @@ +const canvas = document.getElementById("canvas"); +const ctx = canvas.getContext("2d"); + +const CANVAS_SIZE = 500; +const DATA_SIZE = 200; +let scale = 1; +let offx = 0; +let offy = 0; + +let clickx = 0; +let clicky = 0; + +let mouseClicked = false; +// Array of [red, blue, green, transparency] * width * height +let image = new ImageData(DATA_SIZE, DATA_SIZE); +// Drawable image +let bitmap = null; + +window.addEventListener("load", async (e) => { + // Create drawable image, update it every half second + await redraw(); + setInterval(redraw, 500); + setInterval(draw, 500); +}); + + +async function redraw() { + bitmap = await createImageBitmap(image); +} + +// Color is an array of four numbers 0-255 (RGB + transparency) +function setPixel(data, x, y, color) { + let start = (y * DATA_SIZE + x) * 4; + for (let i = 0; i < 4; i++) { + data[start + i] = color[i]; + } +} + +function draw() { + ctx.fillStyle = "rgb(0 0 0 255)"; + ctx.clearRect(0, 0, canvas.width, canvas.height); + let drawScale = CANVAS_SIZE / DATA_SIZE * scale; + ctx.imageSmoothingEnabled = false; + ctx.scale(drawScale, drawScale); + ctx.drawImage(bitmap, offx, offy); + ctx.setTransform(1, 0, 0, 1, 0, 0); +} + +canvas.addEventListener("wheel", async (e) => { + let oldScale = scale; + if (e.deltaY < 0) { + scale += 0.1; + } else if (e.deltaY > 0) { + scale -= 0.1; + } + /* + offX += (DATA_SIZE * scale - DATA_SIZE * oldScale) / 2; + offY += (DATA_SIZE * scale - DATA_SIZE * oldScale) / 2; + */ + draw(image); +}); + +canvas.addEventListener("contextmenu", (e) => { + e.preventDefault(); +}) + +canvas.addEventListener("mousedown", async (e) => { + // Left click + if (e.button == 0) { + mouseClicked = true; + setTimeout(() => { + mouseClicked = false; + }, 200); + } +}); + +canvas.addEventListener("mouseup", async (e) => { + if (e.button == 0 && mouseClicked) { + mouseClicked = false; + + clickx = e.clientX; + clicky = e.clientY; + + let x = e.clientX - canvas.getBoundingClientRect().left; + let y = e.clientY - canvas.getBoundingClientRect().top; + + let cx = Math.round(x / (CANVAS_SIZE * scale) * DATA_SIZE - offx); + let cy = Math.round(y / (CANVAS_SIZE * scale) * DATA_SIZE - offy); + + console.log(cx, cy); + if (cx < 0 || cx > CANVAS_SIZE || cy < 0 || cy > CANVAS_SIZE) { + return; + } + setPixel(image.data, cx, cy, [255, 0, 0, 255]); + await redraw(); + draw(); + } +}); + +canvas.addEventListener("mousemove", async (e) => { + // `buttons` is a bitflag for some dumb reason + if (e.buttons & 1) { + offx += e.movementX * (1.0 / scale) * 0.45; + offy += e.movementY * (1.0 / scale) * 0.45; + draw(image); + } +}); diff --git a/static/confirmation.css b/static/confirmation.css new file mode 100644 index 0000000..a3ddfeb --- /dev/null +++ b/static/confirmation.css @@ -0,0 +1,15 @@ +input[type=number]::-webkit-inner-spin-button, +input[type=number]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + + +html { + background-color: black; +} +/* + + lol + + */ \ No newline at end of file diff --git a/static/confirmation.html b/static/confirmation.html new file mode 100644 index 0000000..7e5699a --- /dev/null +++ b/static/confirmation.html @@ -0,0 +1,33 @@ + + + + + + + UTSA Placeholders + + + + + +
+
+ Check your email for a 6-digit code and enter it below. +
+ +
+ +
+ +
+ + +
+ +
+ + Send again. +
+
+ + \ No newline at end of file diff --git a/static/forgotpassword.css b/static/forgotpassword.css new file mode 100644 index 0000000..cf481db --- /dev/null +++ b/static/forgotpassword.css @@ -0,0 +1,47 @@ +:root { + --utsa-orange: #f15a22; + --utsa-blue: #0c2340; +} + +html { + background-color: var(--utsa-orange); +} + +#rform { + border-radius: 10px; + border: solid var(--utsa-orange) 2px; + margin: 100px; + padding: 30px; + background-color: white; +} + +#formbg { + background-color: var(--utsa-orange); +} + +#h3bg { + background-color: var(--utsa-blue); +} + +h3 { + border-radius: 10px; + padding: 20px; + margin: 10px; + background-color: var(--utsa-blue); + color: var(--utsa-orange); + font-size: 40px; + font-family: Verdana, Geneva, Tahoma, sans-serif; +} + +.form-label { + font-family: Verdana, Geneva, Tahoma, sans-serif; +} + +.form-control { + font-family: Verdana, Geneva, Tahoma, sans-serif; +} + +.form-text { + padding: 3px; + font-family: Verdana, Geneva, Tahoma, sans-serif; +} \ No newline at end of file diff --git a/static/forgotpassword.html b/static/forgotpassword.html new file mode 100644 index 0000000..6051400 --- /dev/null +++ b/static/forgotpassword.html @@ -0,0 +1,35 @@ + + + + + + + UTSA Placeholders + + + + + +

UTSA Place

+
+
+
+ Forgot Password +
+

+
+ + +
Enter your email and we will send you a 6-digit recovery code.
+
+ +
+
+ + Click here to go back to login. + +
+
+
+ + \ No newline at end of file diff --git a/static/index.html b/static/index.html index a2ad708..c48741e 100644 --- a/static/index.html +++ b/static/index.html @@ -14,22 +14,27 @@