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()) // |\>.Reply to this Post` 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() { // 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()