IPost/js/posts.js
Mystikfluu 7369910f84 increase max file size
100KiB => 1MiB
2022-11-19 20:56:41 +01:00

565 lines
15 KiB
JavaScript

let username,reply_id=0,highest_id,currentChannel = sessionStorage.getItem("lastchannel") || "everyone"
const
wss_server = "wss://ipost.tk",
wss_port = "443",
wss_URI = wss_server + ":" + wss_port,
decURIComp = decodeURIComponent
function createElement(s){return document.createElement(s)}
function getById(i){return document.getElementById(i)}
let socket = new WebSocket(wss_URI);
socket.addEventListener("message", async function (event) {
console.log("new websocket message arrived");
if(wss_server == event.origin) {
let data = event.data;
let ds = JSON.parse(data)
let message = ds.message
let item = ds.data
let username = decURIComp(item.post_user_name)
if(message == "new_post" && decURIComp(item.post_receiver_name) == currentChannel) {
await createPost(
username,
decURIComp(item.post_text),
item.post_time,
item.post_special_text,
highest_id+1,
item.post_from_bot,
item.post_reply_id,
true,
item.user_avatar,
item.files[0],
item.files[1],
item.files[2],
item.files[3],
item.files[4]
)
console.log("created new post");
if(user["username"]!=username)mainNoti(username)
let highest_known_posts = await (await fetch(`/api/getPostsLowerThan?id=${highest_id+28}&channel=${currentChannel}`)).json()
for (let i = 0; i < highest_known_posts.length; i++) {
if(getById(highest_known_posts[i].post_id) == undefined) {
main()
return;
}
}
highest_id++;
} else {
console.warn("unknown message")
}
} else {
console.warn("unknown ws origin")
}
})
socket.addEventListener("open",()=> {
switchChannel(currentChannel)
})
var cd = true //inversed "cooldown"
let last_called_postMsg = Date.now()
/*
Tell the api to create a new post with the given information
previously called "postMessage"
*/
function postMsg() {
if((Date.now() - last_called_postMsg) < 100) {
createModal("slow down there")
debugger;
return;
}
last_called_postMsg = Date.now()
let msg = getById("post-text").value
let len = msg.length
if(len==0){
alert("you have to enter a message!")
return;
};
if(len > 1000) {
alert(`Your message cant contain more than 1000 characters! (${len})`)
return
}
if(encodeURIComponent(msg).length > 3000) {
alert("Your message is too long! (Too many special characters)")
return
}
if(cd && posting_id!=undefined) {
cd = false
setTimeout(function(){
cd = true
},400)
let formdata = new FormData()
formdata.append("message",msg)
formdata.append("reply_id",reply_id)
formdata.append("receiver",currentChannel)
formdata.append("pid",posting_id)
for(let i in files) {
formdata.append("file_"+i,files[i])
}
files = []
getById("filesDiv").innerHTML=""
fetch("/api/post", {
method: "POST", body: formdata
});
posting_id = undefined
update_pid()
getById("post-text").value=""
unreply()
} else {
alert("Please wait a tiny bit before posting again")
}
}
async function update_pid() {
let r = await (await fetch("/api/pid")).json()
console.log("new pid info: ",r)
if(r.error) {
//an error occurred
if(r.error == "you cannot access the api without being logged in") {
//account error, go to login page
location.replace("/")
return
}
throw new Error(r.error)
}
posting_id = r.pid
console.log("Updated pid",posting_id)
}
function spacerTextNode() {
return document.createTextNode(" | ")
}
async function reply_link_clicked(reply_channel,reply_id) {
console.log("clicked link")
if(reply_channel != currentChannel) {
console.log("reply is in another channel")
switchChannel(reply_channel)
console.log("switched channel")
await main()
console.log("loaded new messages")
let replied_msg = getById(reply_id)
if(replied_msg) {
console.log("found element")
replied_msg.scrollIntoView()
}
} else {
let replied_msg = getById(reply_id)
if(replied_msg) {
console.log("found element")
replied_msg.scrollIntoView()
}
}
}
const image_types = {
"png":true,
"jpg":true,
"jpeg":true,
"webp":true,
"jfif":true
}
function iconLink(name) {
if(!name){
//if(typeof name === 'undefined' || typeof name === "null"){
return undefined;
}
console.log(name,name.lastIndexOf("\."),name.substring(name.lastIndexOf("\.")+1));
let extension = name.substring(name.lastIndexOf("\.")+1)
if(extension in image_types) {
return "/user_uploads/previews/"+name;
}
return "/api/getFileIcon/"+extension
}
async function createPost(username,text,time,specialtext,postid,isbot,reply_id,add_on_top,avatar_src,file0,file1,file2,file3,file4) {
if(!specialtext)specialtext=""
const newDiv = createElement("div");
const newP = createElement("p");
const newA = createElement("a");
const newSpan2 = createElement("span");
const newSpan3 = createElement("span");
const avatar = createElement("img");
const boticon = createElement("img");
const replyDiv = createElement("div");
const replyA = createElement("a");
const replyAvatar = createElement("img");
const replySpan = createElement("span");
const replyBr = createElement("br");
boticon.src = "/images/bot.png"
boticon.height = 25
boticon.width = 25
boticon.classList.add("boticon")
const newUsername = document.createTextNode(username);
const newTime = document.createTextNode(new Date(time).toLocaleTimeString())
const newSpecialText = document.createTextNode(specialtext)
newDiv.classList.add("post");
newSpan3.classList.add("specialtext")
avatar.width=25;
avatar.height=25;
avatar.classList.add("avatar")
if(avatar_src)avatar.src = "/avatars/"+avatar_src
else {
avatar.src = "/images/default_avatar.png"
}
newA.appendChild(avatar)
newA.appendChild(newUsername)
newA.href = `/users/${username}`
newSpan2.appendChild(newTime)
newSpan3.appendChild(newSpecialText)
newP.appendChild(newA)
newP.appendChild(spacerTextNode())
newP.appendChild(newSpan2)
if(specialtext != "")newP.appendChild(spacerTextNode())
newP.appendChild(newSpan3)
if(isbot==1){
newP.appendChild(spacerTextNode())
newP.appendChild(boticon)
}
newP.appendChild(spacerTextNode())
// |\>.</|
newP.innerHTML += `<button onclick="reply(${postid})">Reply to this Post</button>`
if(reply_id != 0) {
try {
const reply_obj = await (await fetch(`/api/getPost?id=${reply_id}`)).json()
const reply_username = decURIComp(reply_obj.post_user_name)
const reply_username_text = document.createTextNode(reply_username)
const reply_text = decURIComp(reply_obj.post_text)
const reply_channel = reply_obj.post_receiver_name
replyAvatar.width=10;
replyAvatar.height=10;
replyAvatar.classList.add("avatar")
if(reply_obj.User_Avatar)replyAvatar.src = "/avatars/"+reply_obj.User_Avatar
else {
replyAvatar.src = "/images/default_avatar.png"
}
replyA.appendChild(replyAvatar)
replyA.appendChild(reply_username_text)
replyA.appendChild(spacerTextNode())
replyA.innerHTML += filterReply(reply_text.replace("\n"," ").substring(0,20))
replyA.appendChild(replyBr)
replyA.classList.add("no-link-style")
replyDiv.appendChild(replyA)
newDiv.appendChild(replyDiv)
replyDiv.outerHTML = replyDiv.outerHTML.replace(/\>/im,` onclick="reply_link_clicked('${reply_channel}',${reply_id})" \>`)
} catch (ignored) {
console.log(ignored)
}
}
newDiv.appendChild(newP)
newDiv.innerHTML += filterPost(text)
newDiv.id = postid
/*
FILES
*/
const filesP = createElement("p")
const file0_img = createElement("img")
const file1_img = createElement("img")
const file2_img = createElement("img")
const file3_img = createElement("img")
const file4_img = createElement("img")
file0_img.src = iconLink(file0)
file1_img.src = iconLink(file1)
file2_img.src = iconLink(file2)
file3_img.src = iconLink(file3)
file4_img.src = iconLink(file4)
file0_img.width = 50
file1_img.width = 50
file2_img.width = 50
file3_img.width = 50
file4_img.width = 50
if(file0){
filesP.appendChild(file0_img)
file0_img.onclick = function(event) {
console.warn("TODO: Create Modal");
}
}
if(file1){
filesP.appendChild(file1_img)
file1_img.onclick = function(event) {
console.warn("TODO: Create Modal");
}
}
if(file2){
filesP.appendChild(file2_img)
file2_img.onclick = function(event) {
console.warn("TODO: Create Modal");
}
}
if(file3){
filesP.appendChild(file3_img)
file3_img.onclick = function(event) {
console.warn("TODO: Create Modal");
}
}
if(file4){
filesP.appendChild(file4_img)
file4_img.onclick = function(event) {
console.warn("TODO: Create Modal");
}
}
newDiv.appendChild(filesP)
/*
Adding the post to the posts list
*/
let posts_div = getById("posts")
if(add_on_top) {
posts_div.insertBefore(newDiv, posts_div.children[0]);
} else {
posts_div.appendChild(newDiv)
}
}
async function main(){
if(!user){
user = await (await fetch("/api/getuser")).json()
username = user.username
if(!username){
user = undefined
getById("noaccount").style=""
getById("loading").style="display:none;"
console.log("no account");
return;
}
}
username = user.username
getById("username-self").innerText = username
let all_posts = await (await fetch(`/api/getPosts?channel=${currentChannel}`)).json()
if(!all_posts)return;
getById("posts").innerHTML = ""
getById("loading").style="display:none;"
getById("scriptonly").style = ""
highest_id = all_posts[0].post_id
let post_promises = []
for(i in all_posts) {
let item = all_posts[i]
let created = createPost(
decURIComp(item.post_user_name),
decURIComp(item.post_text),
item.post_time,
item.post_special_text,
item.post_id,
item.post_from_bot,
item.post_reply_id,
false,
item.User_Avatar,
item.file_0,
item.file_1,
item.file_2,
item.file_3,
item.file_4
)
post_promises.push(created)
}
await Promise.all(post_promises)
Array.from(getById("posts").childNodes).sort((a,b) => {
if(Number(a.id) > Number(b.id))return -1;
if(Number(a.id) < Number(b.id))return 1;
return 0
}).forEach(e => {
getById("posts").appendChild(e)
})
let links = document.getElementsByClassName("insertedlink")
for (let i = 0; i < links.length; i++) {
links[i].innerText = links[i].innerText.split("\/\/")[1].split("\/")[0]
}
let mentions = document.getElementsByClassName("mention")
for (let i = 0; i < mentions.length; i++) {
if(mentions[i]!=undefined && mentions[i].innerText == "@"+username) {
mentions[i].classList.add("user-mention");
mentions[i].classList.remove("mention");
i--;
}
}
}
async function reply(postid) {
let post = await(await fetch("/api/getPost?id="+postid)).json()
let username = post.post_user_name
let posttext = post.post_text
getById("reply").style = ""
getById("reply_username").innerText = decURIComp(username)
getById("reply_text").innerHTML = filterPost(decURIComp(posttext))
reply_id = postid
}
function unreply() {
getById("reply").style = "display:none;"
reply_id = 0
}
var cansendNoti = false
function askNotiPerms() {
return Notification.requestPermission()
}
async function firstAsk() {
if(Notification.permission === 'denied' || Notification.permission === 'default') {
await askNotiPerms()
}
}
async function mainNoti(user) {
if(Notification.permission === 'denied' || Notification.permission === 'default') {
await askNotiPerms()
} else {
if(cansendNoti) {
let notification = new Notification('IPost', { body: "new message posted from " + user , tag: "new_post"});
notification = await notification
notification.addEventListener("click",function(){
notification.close()
})
console.log(notification);
}
}
}
document.addEventListener("visibilitychange", function() {
if (document.visibilityState === 'visible') {
cansendNoti = false
} else {
cansendNoti = true
}
});
if(window.location.href.includes("message=")) {
getById("post-text").innerText = `${decURIComp(window.location.href.split("message=")[1])} `
}
function switchChannel(channelname) {
sessionStorage.setItem("lastchannel", channelname);
currentChannel = channelname
socket.send(JSON.stringify({"id":"switchChannel","data":channelname}))
}
function loadChannels() {
// <!-- <p class="channel">- Channel Name -</p> -->
let tab = getById("channelTab")
tab.innerHTML = ""
for (let i = 0; i < channels.length; i++) {
let channelname = decURIComp(channels[i])
if(channelname == "")continue;
let channelp = createElement("p")
channelp.classList.add("channel")
let textnode = document.createTextNode(channelname)
channelp.appendChild(textnode)
channelp.addEventListener("click",async function(){
switchChannel(channelname)
main()
let settings = await (await fetch("/api/settings")).json() // skipqc
console.log(settings) // skipqc
if(settings != "null") {
if(settings.ACCR == false) {
unreply()
}
}
})
tab.appendChild(channelp)
}
}
var files = []
function addFile(file) {
if(file.size > 1_000_000) {
alert("that file is too large, max size: 1MiB")
console.log("file is too big: ", file.name, file.type, file.size);
return;
}
if(files.length >= 5) {
console.log("too many files already: ", files);
return;
}
files[files.length]=file
const fileimg = createElement("img")
console.log(file.name,file.name.lastIndexOf("\."),file.name.substring(file.name.lastIndexOf("\.")+1));
fileimg.src = "/api/getFileIcon/"+file.name.substring(file.name.lastIndexOf("\.")+1)
getById("filesDiv").appendChild(fileimg)
//filesDiv
console.log("File added: ", file.name, file.type, file.size);
}
function dropHandler(ev) {
console.log("file dropped");
ev.preventDefault();
if (ev.dataTransfer.items) {
// Use DataTransferItemList interface to access the file(s)
[...ev.dataTransfer.items].forEach((item, i) => {
// If dropped items aren't files, reject them
if (item.kind === 'file') {
const file = item.getAsFile();
addFile(file)
}
});
} else {
// Use DataTransfer interface to access the file(s)
[...ev.dataTransfer.files].forEach((file, i) => {
addFile(file)
});
}
}
function init() {
setInterval(update_pid,30000)
if(posting_id=="")update_pid()
main()
firstAsk()
loadChannels()
}
init()