IPost/js/dms.js
2025-04-29 00:29:00 +02:00

550 lines
16 KiB
JavaScript

let username
const wss_server = 'wss://ipost.rocks'
const wss_port = '443'
const wss_URI = wss_server + ':' + wss_port
var reply_id = 0
var highest_id
var currentChannel
let socket = new WebSocket(wss_URI)
socket.addEventListener('message', async function (_event) {
console.info('TODO: add websocket support to dms')
// return
// if(wss_server === event.origin) {
// let data = event.data;
// let ds = JSON.parse(data)
// let message = ds.message
// let item = ds.data
// let username = decodeURIComponent(item.post_user_name)
// if(message === "new_post") {
// await createPost(decodeURIComponent(item.post_user_name),decodeURIComponent(item.post_text),item.post_time,item.post_special_text,highest_id+1,item.post_from_bot,item.post_reply_id,true)
// 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(document.getElementById(highest_known_posts[i].post_id) === undefined) {
// main()
// return;
// }
// }
// highest_id++;
// }
// }
})
var cd = true //inversed "cooldown"
let encryption_keys = ''
function set_keys(s_key) {
let key = extend(s_key, 512)
let msgkey = key.substring(0, 128)
let sigkey = key.substring(129, 512)
let packed = pack_keys({
signkey: sigkey,
messagekey: msgkey,
})
localStorage.setItem(currentChannel + 'enc_key', packed)
encryption_keys = packed
main()
}
let last_called_postMsg = Date.now()
/*
previously called postMessage
*/
async function postMsg() {
if (Date.now() - last_called_postMsg < 100) {
createModal('slow down there')
debugger
return
}
last_called_postMsg = Date.now()
let len = document.getElementById('post-text').value.length
if (len >= 1001) {
alert(`Your message cant contain more than 1000 characters! (${len})`)
return
}
if (cd && posting_id !== undefined) {
cd = false
let text = document.getElementById('post-text').value
if (typeof encrypt === 'function' && encryption_keys !== '') {
text = encrypt(text, {
packed: encryption_keys,
})
}
let r = await post('/api/dms/post', {
message: text,
reply_id: reply_id,
receiver: currentChannel,
pid: posting_id,
})
update_pid()
if (window.location.href.split('?mention=')[1])
location.replace('/posts')
document.getElementById('post-text').value = ''
unreply()
setTimeout(function () {
cd = true
}, 200)
} else {
alert('Please wait a tiny bit before posting again')
}
}
async function update_pid() {
let r = await (await fetch('/api/dms/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
}
//possibly more errors coming soon :tm: ?
return
}
posting_id = r.pid
console.log('Updated pid', posting_id)
}
function spacerTextNode() {
return document.createTextNode(' | ')
}
const user_cache = {}
async function getavatar(username) {
let user = user_cache[username]
if (user === undefined) {
user = (
await (
await fetch(
'/api/getotheruser?user=' + encodeURIComponent(username)
)
).json()
)['avatar']
if (user) {
user = '/avatars/' + user
} else {
user = '/images/default_avatar.png'
}
user_cache[username] = user
}
return user
}
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 = document.getElementById(reply_id)
if (replied_msg) {
console.log('found element')
replied_msg.scrollIntoView()
}
} else {
let replied_msg = document.getElementById(reply_id)
if (replied_msg) {
console.log('found element')
replied_msg.scrollIntoView()
}
}
}
async function createPost(
username,
text,
time,
specialtext,
postid,
isbot,
reply_id,
add_on_top
) {
if (!specialtext) specialtext = ''
const newDiv = document.createElement('div')
const newP = document.createElement('p')
const newA = document.createElement('a')
const newSpan2 = document.createElement('span')
const newSpan3 = document.createElement('span')
const avatar = document.createElement('img')
const boticon = document.createElement('img')
const replyDiv = document.createElement('div')
const replyA = document.createElement('a')
const replyAvatar = document.createElement('img')
const replySpan = document.createElement('span')
const replyBr = document.createElement('br')
boticon.src = '/images/bot.png'
boticon.height = 25
boticon.width = 25
boticon.classList.add('boticon')
const newUsername = document.createTextNode(username)
let timedate = new Date(time)
time = timedate
time = time.toString()
time = time.split(' ')
time =
time[0] + ' ' + time[1] + ' ' + time[2] + ' ' + time[3] + ' ' + time[4]
if (
timedate ===
'Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time)'
)
time = 'unknown time'
const newTime = document.createTextNode(time)
const newSpecialText = document.createTextNode(specialtext)
newDiv.classList.add('post')
newSpan3.classList.add('specialtext')
avatar.width = 25
avatar.height = 25
avatar.classList.add('avatar')
avatar.src = await getavatar(username)
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/dms/getDM?id=${reply_id}`)
).json()
const reply_username = decodeURIComponent(reply_obj.dms_user_name)
const reply_username_text = document.createTextNode(reply_username)
let reply_text = decodeURIComponent(reply_obj.dms_text)
const reply_channel = reply_obj.dms_receiver
replyAvatar.width = 10
replyAvatar.height = 10
replyAvatar.classList.add('avatar')
replyAvatar.src = await getavatar(reply_username)
replyA.appendChild(replyAvatar)
replyA.appendChild(reply_username_text)
replyA.appendChild(spacerTextNode())
if (typeof decrypt === 'function' && encryption_keys !== '') {
reply_text = decrypt(reply_text, {
packed: encryption_keys,
}).msg
}
replyA.innerHTML += filterReply(
reply_text.replace('\n', ' ').substring(0, 20)
)
replyA.appendChild(replyBr)
replyA.classList.add('no-link-style')
// async function onclick(event) {
// event.preventDefault()
// }
// replyDiv.onclick = function() {
// reply_link_clicked(reply_channel, reply_id)
// }
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)
}
}
if (typeof decrypt === 'function' && encryption_keys !== '') {
text = decrypt(text, { packed: encryption_keys }).msg
}
newDiv.appendChild(newP)
newDiv.innerHTML += filterPost(text)
newDiv.id = postid
let posts_div = document.getElementById('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
document.getElementById('noaccount').style = ''
document.getElementById('loading').style = 'display:none;'
console.log('no account')
return
}
}
username = user.username
document.getElementById('username-self').innerText = username
let all_posts = await (
await fetch(`/api/getPersonalPosts?otherperson=${currentChannel}`)
).json()
if (!all_posts) {
document.getElementById('loading').style = 'display:none;'
document.getElementById('scriptonly').style = ''
}
document.getElementById('posts').innerHTML = ''
if (all_posts.length <= 0) {
document.getElementById('loading').style = 'display:none;'
document.getElementById('scriptonly').style = ''
//TODO: empty page
return
}
highest_id = all_posts[0].post_id
for (i in all_posts) {
let item = all_posts[i]
await createPost(
decodeURIComponent(item.dms_user_name),
decodeURIComponent(item.dms_text),
item.dms_time,
item.dms_special_text,
item.dms_id,
item.dms_from_bot,
item.dms_reply_id,
false
)
}
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--
}
}
document.getElementById('loading').style = 'display:none;'
document.getElementById('scriptonly').style = ''
}
async function reply(postid) {
let post = await (await fetch('/api/dms/getDM?id=' + postid)).json()
let username = post.dms_user_name
let posttext = post.dms_text
document.getElementById('reply').style = ''
document.getElementById('reply_username').innerText =
decodeURIComponent(username)
posttext = decodeURIComponent(posttext)
if (typeof decrypt === 'function' && encryption_keys !== '') {
posttext = decrypt(posttext, { packed: encryption_keys }).msg
}
document.getElementById('reply_text').innerHTML = filterPost(posttext)
reply_id = postid
}
function unreply() {
document.getElementById('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 dm from ' + user,
tag: 'new_post',
})
notification = await notification
notification.addEventListener('click', function () {
notification.close()
})
console.log(notification)
}
}
}
document.addEventListener('visibilitychange', function () {
//cansendNoti = document.visibilityState !== 'visible'
if (document.visibilityState === 'visible') {
cansendNoti = false
} else {
cansendNoti = true
}
})
function switchChannel(channelname) {
sessionStorage.setItem('lastdm', channelname)
currentChannel = channelname
if (localStorage.getItem(currentChannel + 'enc_key') !== null) {
encryption_keys = localStorage.getItem(currentChannel + 'enc_key')
} else {
encryption_keys = ''
}
try {
socket.send(JSON.stringify({ id: 'switchChannel', data: channelname }))
} catch (err) {
console.error(err)
}
}
function removeDuplicates(a) {
let prims = { boolean: {}, number: {}, string: {} },
objs = []
return a.filter(function (item) {
let type = typeof item
if (type in prims)
return Object.prototype.hasOwnProperty.call(prims[type], item)
? false
: (prims[type][item] = true)
else return objs.indexOf(item) >= 0 ? false : objs.push(item)
})
}
function createChannel(channelname, tab) {
channelname = decodeURIComponent(channelname)
let channelp = document.createElement('p')
channelp.classList.add('channel')
channelp.id = channelname
let textnode = document.createTextNode(channelname)
channelp.appendChild(textnode)
channelp.addEventListener('click', function () {
switchChannel(channelname)
main()
unreply()
})
tab.appendChild(channelp)
}
async function loadChannels() {
// <!-- <p class="channel">- Channel Name -</p> -->
let dms = await (await fetch('/api/dms/conversations')).json()
let channels = []
for (let dm of dms) {
if (dm.dms_user_name === username) {
channels[channels.length] = dm.dms_receiver
} else {
channels[channels.length] = dm.dms_user_name
}
}
channels = removeDuplicates(channels)
let tab = document.getElementById('channelTab')
tab.innerHTML = ''
for (let i = 0; i < channels.length; i++) {
if (channels[i] === '') continue
createChannel(channels[i], tab)
}
}
function init() {
switchChannel(sessionStorage.getItem('lastdm') || 'none')
setInterval(update_pid, 30000)
update_pid()
main()
firstAsk()
loadChannels()
}
async function clickPress(event) {
if (event.key === 'Enter') {
user = await (
await fetch(
'/api/getotheruser?user=' +
encodeURIComponent(
document.getElementById('Username_input').value
)
)
).json()
if (user.username === undefined) {
alert('invalid username entered')
return
} else {
if (document.getElementById(user.username) === undefined) {
let tab = document.getElementById('channelTab')
createChannel(encodeURIComponent(user.username), tab)
}
document.getElementById(user.username).click()
document.getElementById('Username_input').value = ''
}
}
}
init()