mirror of
https://github.com/gabehf/massflip.git
synced 2026-03-07 21:48:16 -08:00
bug fixes, ws rate limit, new graph
This commit is contained in:
parent
a3e56fa753
commit
5387401156
5 changed files with 91 additions and 51 deletions
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
"golang.org/x/time/rate"
|
||||||
)
|
)
|
||||||
|
|
||||||
// code adapted from the gorilla websocket chat demo code
|
// code adapted from the gorilla websocket chat demo code
|
||||||
|
|
@ -49,6 +50,8 @@ type Client struct {
|
||||||
username string
|
username string
|
||||||
|
|
||||||
auth bool
|
auth bool
|
||||||
|
|
||||||
|
limiter rate.Limiter
|
||||||
}
|
}
|
||||||
|
|
||||||
type Auth struct {
|
type Auth struct {
|
||||||
|
|
@ -70,6 +73,7 @@ func (c *Client) readPump() {
|
||||||
c.conn.SetReadLimit(maxMessageSize)
|
c.conn.SetReadLimit(maxMessageSize)
|
||||||
c.conn.SetReadDeadline(time.Now().Add(pongWait))
|
c.conn.SetReadDeadline(time.Now().Add(pongWait))
|
||||||
c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
||||||
|
c.limiter = *rate.NewLimiter(1, 5)
|
||||||
for {
|
for {
|
||||||
_, message, err := c.conn.ReadMessage()
|
_, message, err := c.conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -78,6 +82,10 @@ func (c *Client) readPump() {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if !c.limiter.Allow() {
|
||||||
|
c.send <- []byte("{\"type\":\"chaterror\",\"error\":\"You are sending messages too quickly\"}")
|
||||||
|
continue
|
||||||
|
}
|
||||||
var v Auth
|
var v Auth
|
||||||
err = json.Unmarshal(message, &v)
|
err = json.Unmarshal(message, &v)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,15 @@
|
||||||
<div id="until">{{ until }}</div>
|
<div id="until">{{ until }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="BetGraph">
|
<div id="BetGraph">
|
||||||
<div class="pie animate pie-base" :style="tailsStyle"></div>
|
<div class="spin">
|
||||||
<div class="pie animate start-no-round pie-overlap" :style="headsStyle"></div>
|
<div class="tails-pie pie animate pie-base" :style="tailsStyle"></div>
|
||||||
|
<div class="heads-pie pie animate pie-overlap" :style="headsStyle"></div>
|
||||||
|
</div>
|
||||||
<div class="data-overlap" id="data">
|
<div class="data-overlap" id="data">
|
||||||
<div id="headsInfo" class="percent heads">{{ headsPercent }}%</div>
|
<div id="headsInfo" class="percent heads" :class="{ unfocused: User.bet == 'tails' }">{{ headsPercent }}%</div>
|
||||||
<div id="headsPool" class="pool heads"> {{ headsPool }}gp</div>
|
<div id="headsPool" class="pool heads" :class="{ unfocused: User.bet == 'tails' }"> {{ headsPool }}gp</div>
|
||||||
<div id="tailsInfo" class="percent tails">{{ tailsPercent }}%</div>
|
<div id="tailsInfo" class="percent tails" :class="{ unfocused: User.bet == 'heads' }">{{ tailsPercent }}%</div>
|
||||||
<div id="tailsPool" class="pool tails">{{ tailsPool }}gp</div>
|
<div id="tailsPool" class="pool tails" :class="{ unfocused: User.bet == 'heads' }">{{ tailsPool }}gp</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="lower" v-show="userStore().username != ''">
|
<div id="lower" v-show="userStore().username != ''">
|
||||||
|
|
@ -168,35 +170,23 @@ onMounted(() => {
|
||||||
position:absolute;
|
position:absolute;
|
||||||
border-radius:50%;
|
border-radius:50%;
|
||||||
}
|
}
|
||||||
.pie:before {
|
.heads-pie:before {
|
||||||
inset:0;
|
inset:0;
|
||||||
background:
|
background:
|
||||||
radial-gradient(farthest-side,var(--c) 98%,#0000) top/var(--b) var(--b) no-repeat,
|
|
||||||
conic-gradient(var(--c) calc(var(--p)*1%),#0000 0);
|
conic-gradient(var(--c) calc(var(--p)*1%),#0000 0);
|
||||||
-webkit-mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
|
-webkit-mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
|
||||||
mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
|
mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
|
||||||
}
|
}
|
||||||
.pie:after {
|
.tails-pie:before {
|
||||||
inset:calc(50% - var(--b)/2);
|
inset:0;
|
||||||
background:var(--c);
|
background:
|
||||||
transform:rotate(calc(var(--p)*3.6deg - 90deg)) translate(calc(var(--w)/2 - 50%));
|
conic-gradient(var(--c) calc(var(--p)*1%),#0000 0);
|
||||||
|
-webkit-mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
|
||||||
|
mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
|
||||||
}
|
}
|
||||||
.animate {
|
.animate {
|
||||||
animation:p 1s .5s both;
|
animation:p 1s .5s both;
|
||||||
}
|
}
|
||||||
.start-no-round:before {
|
|
||||||
inset:0;
|
|
||||||
background:
|
|
||||||
radial-gradient(farthest-side,var(--c) 98%,#0000) top/var(--b) var(--b) no-repeat,
|
|
||||||
conic-gradient(var(--c) calc(var(--p)*1%),#0000 0);
|
|
||||||
-webkit-mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
|
|
||||||
mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
|
|
||||||
}
|
|
||||||
.start-no-round:after {
|
|
||||||
inset:calc(50% - var(--b)/2);
|
|
||||||
background:var(--c);
|
|
||||||
transform:rotate(calc(var(--p)*3.6deg - 90deg)) translate(calc(var(--w)/2 - 50%));
|
|
||||||
}
|
|
||||||
@-moz-keyframes p{
|
@-moz-keyframes p{
|
||||||
from{--p:0}
|
from{--p:0}
|
||||||
}
|
}
|
||||||
|
|
@ -211,7 +201,7 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
.data-overlap {
|
.data-overlap {
|
||||||
position:relative;
|
position:relative;
|
||||||
bottom:305px;
|
bottom:304px;
|
||||||
left: 50px;
|
left: 50px;
|
||||||
background-color: #001d3d;
|
background-color: #001d3d;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
|
|
@ -238,6 +228,12 @@ onMounted(() => {
|
||||||
.tails {
|
.tails {
|
||||||
color:#dc2f91;
|
color:#dc2f91;
|
||||||
}
|
}
|
||||||
|
.heads.unfocused {
|
||||||
|
color:#7a661b;
|
||||||
|
}
|
||||||
|
.tails.unfocused {
|
||||||
|
color:#6b214b;
|
||||||
|
}
|
||||||
.pool.heads {
|
.pool.heads {
|
||||||
padding-bottom: 2em;
|
padding-bottom: 2em;
|
||||||
}
|
}
|
||||||
|
|
@ -264,4 +260,15 @@ onMounted(() => {
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
}
|
}
|
||||||
|
.spin {
|
||||||
|
animation: rotation 20s infinite linear;
|
||||||
|
}
|
||||||
|
@keyframes rotation {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -40,15 +40,45 @@ const ChatColors = {
|
||||||
|
|
||||||
const _CHAT_MAX_HISTORY = 75;
|
const _CHAT_MAX_HISTORY = 75;
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
let log = document.getElementById("ChatWindow")
|
function appendLog(item) {
|
||||||
function appendLog(item) {
|
var log = document.getElementById("ChatWindow")
|
||||||
var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
|
var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
|
||||||
log.appendChild(item);
|
log.appendChild(item);
|
||||||
if (doScroll) {
|
if (doScroll) {
|
||||||
log.scrollTop = log.scrollHeight - log.clientHeight;
|
log.scrollTop = log.scrollHeight - log.clientHeight;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateChat() {
|
||||||
|
var log = document.getElementById("ChatWindow")
|
||||||
|
log.innerHTML = ""
|
||||||
|
for (let message of Object.values(chatQueue.elements)) {
|
||||||
|
var item = document.createElement("div")
|
||||||
|
let fromUser = document.createElement("span")
|
||||||
|
fromUser.style = `color: ${message.color};`
|
||||||
|
fromUser.innerText = message.username
|
||||||
|
item.appendChild(fromUser)
|
||||||
|
if ('points' in message) {
|
||||||
|
let chatScore = document.createElement("span")
|
||||||
|
chatScore.innerText = `(${message.points})`
|
||||||
|
chatScore.style = `color: ${message.color};font-family: 'Helvetica';font-size: 12px;`
|
||||||
|
item.appendChild(chatScore)
|
||||||
|
}
|
||||||
|
let chatMsg
|
||||||
|
if (!('msgcolor' in message)) {
|
||||||
|
//message['msgcolor'] = '#f3f9f8'
|
||||||
|
}
|
||||||
|
chatMsg = document.createElement("span")
|
||||||
|
chatMsg.style = `color: ${message.msgcolor};`
|
||||||
|
chatMsg.innerText = `: ${message.message}`
|
||||||
|
item.appendChild(chatMsg)
|
||||||
|
appendLog(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
|
||||||
WS.addEventListener("message", function (evt) {
|
WS.addEventListener("message", function (evt) {
|
||||||
let MSGs = evt.data.split('\n')
|
let MSGs = evt.data.split('\n')
|
||||||
MSGs.forEach((i) => {
|
MSGs.forEach((i) => {
|
||||||
|
|
@ -58,27 +88,22 @@ onMounted(() => {
|
||||||
if (chatQueue.length >= _CHAT_MAX_HISTORY) {
|
if (chatQueue.length >= _CHAT_MAX_HISTORY) {
|
||||||
chatQueue.dequeue()
|
chatQueue.dequeue()
|
||||||
}
|
}
|
||||||
log.innerHTML = ""
|
updateChat()
|
||||||
for (let message of Object.values(chatQueue.elements)) {
|
} else if (wsMsg.type == 'chaterror') {
|
||||||
var item = document.createElement("div")
|
chatQueue.enqueue({
|
||||||
let fromUser = document.createElement("span")
|
username: 'Not Sent',
|
||||||
fromUser.style = `color: ${message.color};`
|
color: '#555',
|
||||||
fromUser.innerText = message.username
|
message: wsMsg.error,
|
||||||
item.appendChild(fromUser)
|
msgcolor: '#555'
|
||||||
let chatScore = document.createElement("span")
|
})
|
||||||
chatScore.innerText = `(${message.points})`
|
updateChat()
|
||||||
chatScore.style = `color: ${message.color};font-family: 'Helvetica';font-size: 12px;`
|
|
||||||
item.appendChild(chatScore)
|
|
||||||
let chatMsg = document.createTextNode(`: ${message.message}`)
|
|
||||||
item.appendChild(chatMsg)
|
|
||||||
appendLog(item)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
function sendChat() {
|
function sendChat() {
|
||||||
|
if (chat.value == '') { return }
|
||||||
if (chat.value.startsWith("/color")) {
|
if (chat.value.startsWith("/color")) {
|
||||||
let newColor = chat.value.split(" ")[1]
|
let newColor = chat.value.split(" ")[1]
|
||||||
if (newColor in ChatColors) {
|
if (newColor in ChatColors) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ module.exports = defineConfig({
|
||||||
module.exports = {
|
module.exports = {
|
||||||
devServer: {
|
devServer: {
|
||||||
host: "localhost",
|
host: "localhost",
|
||||||
port: 8000,
|
port: 8080,
|
||||||
proxy: {
|
proxy: {
|
||||||
"/": {
|
"/": {
|
||||||
target: "http://localhost:8000",
|
target: "http://localhost:8000",
|
||||||
|
|
|
||||||
2
main.go
2
main.go
|
|
@ -12,7 +12,7 @@ import (
|
||||||
|
|
||||||
/*
|
/*
|
||||||
0.0.4
|
0.0.4
|
||||||
- added rate limiting
|
- added rate limiting for http and ws
|
||||||
- added captcha for account creation
|
- added captcha for account creation
|
||||||
- added WebSocket authentication
|
- added WebSocket authentication
|
||||||
- fixed BetInput bugs (NaN, decimals)
|
- fixed BetInput bugs (NaN, decimals)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue