Last active
April 20, 2025 14:15
-
-
Save sneha-belkhale/e7a1fe52e33b5c98f1ea2081a3b4ed8a to your computer and use it in GitHub Desktop.
Local Network Chat -- (python server + frontend + linux daemon Init Script for the server )
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<style> | |
body { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
margin: 0px; | |
background-color: black; | |
width: 100%; | |
height: 100vh; | |
color: white; | |
font-family: monospace | |
} | |
.center { | |
display: flex; | |
flex-direction: column; | |
margin: auto; | |
width: 60%; | |
height: 100%; | |
position: relative; | |
margin: 20px 0 20px 0; | |
} | |
.input-container { | |
display: flex; | |
flex-direction: row; | |
justify-content: space-between; | |
width: 100%; | |
height: 30px; | |
z-index: 10; | |
margin-bottom: 20px; | |
} | |
.message-input { | |
width: 100%; | |
border: 2px solid white; | |
background-color: #ff00b1; | |
color: white; | |
font-family: monospace | |
} | |
.name-input { | |
width: 120px; | |
border: 2px solid white; | |
background-color: #ff00b1; | |
color: white; | |
font-family: monospace; | |
} | |
::placeholder { | |
color: white; | |
font-family: monospace; | |
} | |
.message-area { | |
position: relative; | |
display: flex; | |
height: 100%; | |
flex-direction: column; | |
justify-content: flex-end; | |
margin-bottom: 30px; | |
} | |
.date { | |
background-color: blue; | |
} | |
.message { | |
display: grid; | |
grid-template-columns: 100px 120px auto; | |
gap: 15px; | |
margin-bottom: 5px; | |
} | |
.name { | |
width: 80px; | |
width: 100%; | |
text-align: right; | |
overflow: hidden; | |
word-wrap: break-word; | |
} | |
#green { | |
color: #00ff5c; | |
} | |
#blue { | |
color: blue; | |
} | |
#magenta { | |
color: magenta; | |
} | |
#teal { | |
color: #00dcff; | |
} | |
#yellow { | |
color: #f0ff00; | |
} | |
#sendButton { | |
cursor: pointer; | |
height: 100%; | |
border: 2px solid white; | |
background-color: blueviolet; | |
color: white; | |
font-family: monospace; | |
} | |
@media only screen and (max-width: 600px) { | |
.center { | |
width: 100%; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div class="center"> | |
<div class="message-area"> | |
</div> | |
<div class="input-container"> | |
<input class="name-input" placeholder="Alias" /> | |
<input class="message-input" placeholder="Symbols" /> | |
<button id="sendButton">Send</button> | |
</div> | |
</div> | |
<script>; | |
const apiUrl = 'http://192.168.8.1:8989'; | |
// const apiUrl = '/'; | |
const messageArea = document.querySelector(".message-area"); | |
const nameColorList = ["yellow", "magenta", "green", "teal", "yellow", "blue"] | |
let sentSecretKey = false; | |
const newMessageEl = (message) => { | |
const messageEl = document.createElement("div"); | |
const d = new Date(message.date); | |
let [month, date, year] = d.toLocaleDateString().split("/") | |
let [hour, minute, second] = d.toLocaleTimeString().split(/:| /) | |
let charSum = 0; | |
for (let i = 0; i < message.name.length; i++) { | |
let c = message.name.charCodeAt(i); | |
charSum += c; | |
} | |
let color = nameColorList[charSum % nameColorList.length]; | |
messageEl.innerHTML = ` | |
<div class="message"> | |
<div class="date">[${hour}:${minute}:${second}]</div> | |
<div id=${color} class="name">${message.name}:</div> | |
<div class="text">${message.text}</div> | |
</div> | |
`; | |
return messageEl; | |
} | |
const fetchMessages = async () => { | |
try { | |
const res = await fetch(apiUrl) | |
const messages = await res.json(); | |
messageArea.innerHTML = ''; | |
messages.forEach(message => { | |
const msgEl = newMessageEl(message) | |
messageArea.appendChild(msgEl); | |
}); | |
} catch (error) { | |
console.log('Error fetching messages', error) | |
} | |
} | |
fetchMessages(); | |
setInterval(() => { | |
fetchMessages() | |
}, 3000) | |
const sendBtn = document.querySelector('#sendButton'); | |
sendBtn.addEventListener('click', async () => { | |
const nameEl = document.querySelector('.name-input') | |
const msgEl = document.querySelector('.message-input') | |
if (nameEl.value.length < 1 || msgEl.value.length < 1) { | |
return | |
} | |
const payload = { | |
name: nameEl.value, | |
text: msgEl.value | |
}; | |
try { | |
const res = await fetch(apiUrl, { | |
method: 'post', | |
body: JSON.stringify(payload) | |
}); | |
const body = await res.json(); | |
if (res.ok) { | |
// Add message to UI | |
const msgEl = newMessageEl(body) | |
messageArea.appendChild(msgEl); | |
if (!sentSecretKey) { | |
const secretMsgEl = newMessageEl({ "name": "YOUR KEY", "text": "fvxyaZ9ix95ZaLuWn7XqcbRW5", "date": "2012-01-26T00:00:00.417-07:00" }) | |
messageArea.appendChild(secretMsgEl); | |
sentSecretKey = true; | |
} | |
} else { | |
// TODO: Display that error in the UI | |
console.log(body.message) | |
} | |
} catch (error) { | |
console.log('Error posting message.', error) | |
} | |
}) | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2 | |
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler | |
import SocketServer | |
import logging | |
import json | |
import datetime | |
PORT = 8989 | |
db = '/root/data.json' | |
class GetHandler(BaseHTTPRequestHandler): | |
def do_GET(self): | |
self.send_response(200) | |
self.send_header('Content-type', 'application/json') | |
self.send_header('Access-Control-Allow-Origin', '*') | |
self.send_header('Access-Control-Allow-Methods', 'GET') | |
self.end_headers() | |
with open(db) as json_file: | |
data = json.load(json_file) | |
self.wfile.write(json.dumps(data)) | |
def do_POST(self): | |
self.send_response(200) | |
self.send_header('Content-type', 'application/json') | |
self.send_header('Access-Control-Allow-Origin', '*') | |
self.send_header('Access-Control-Allow-Methods', 'POST') | |
self.end_headers() | |
content_len = int(self.headers.getheader('content-length', 0)) | |
post_body = self.rfile.read(content_len) | |
post_data = json.loads(post_body) | |
try: | |
name = post_data["name"] | |
text = post_data["text"] | |
except: | |
return | |
data = 0 | |
with open(db) as json_file: | |
data = json.load(json_file) | |
entry = {'name': name, 'text': text, 'date': datetime.datetime.now().strftime("%m/%d/%Y, %H:%M:%S")} | |
data.append(entry) | |
with open(db, 'w') as outfile: | |
json.dump(data, outfile, indent=4) | |
self.wfile.write(json.dumps(entry)) | |
# override the log message function, because it crashes headless OpenWRT since there is no output stream? | |
def log_message(self, format, *args): | |
return | |
Handler = GetHandler | |
httpd = SocketServer.TCPServer(("", PORT), Handler) | |
httpd.serve_forever() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh /etc/rc.common | |
START=98 | |
STOP=98 | |
start() { | |
# commands to launch application | |
echo "starting chat server" | |
# run in the background because init.d scripts seem to be blocking | |
# sleep 20 seconds, because it seems whatever python servers need to initialize is not ready on boot | |
(sleep 20; python /root/server.py)& | |
} | |
stop() { | |
# commands to kill application | |
echo stop | |
killall python | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment