Compare commits

..

No commits in common. "6337350b60645199ebabfebf60e73b6e786c6b33" and "abce2e03d1e47992d234779cd38d476e0bfc766a" have entirely different histories.

6 changed files with 30 additions and 62 deletions

View File

@ -1,5 +1,5 @@
from snek.system.service import BaseService
from snek.system.template import sanitize_html
from snek.system.template import whitelist_attributes
import time
class ChannelMessageService(BaseService):
@ -69,10 +69,10 @@ class ChannelMessageService(BaseService):
"color": user["color"],
}
)
context['message'] = whitelist_attributes(context['message'])
try:
template = self.app.jinja2_env.get_template("message.html")
model["html"] = template.render(**context)
model['html'] = sanitize_html(model['html'])
except Exception as ex:
print(ex, flush=True)
@ -118,6 +118,7 @@ class ChannelMessageService(BaseService):
async def save(self, model):
context = {}
context.update(model.record)
context['message'] = whitelist_attributes(context['message'])
user = await self.app.services.user.get(model["user_uid"])
context.update(
{
@ -129,7 +130,6 @@ class ChannelMessageService(BaseService):
)
template = self.app.jinja2_env.get_template("message.html")
model["html"] = template.render(**context)
model['html'] = sanitize_html(model['html'])
return await super().save(model)
async def offset(self, channel_uid, page=0, timestamp=None, page_size=30):

View File

@ -3,15 +3,8 @@ export class EventHandler {
this.subscribers = {};
}
addEventListener(type, handler, { once = false } = {}) {
addEventListener(type, handler) {
if (!this.subscribers[type]) this.subscribers[type] = [];
if (once) {
const originalHandler = handler;
handler = (...args) => {
originalHandler(...args);
this.removeEventListener(type, handler);
};
}
this.subscribers[type].push(handler);
}
@ -19,15 +12,4 @@ export class EventHandler {
if (this.subscribers[type])
this.subscribers[type].forEach((handler) => handler(...data));
}
removeEventListener(type, handler) {
if (!this.subscribers[type]) return;
this.subscribers[type] = this.subscribers[type].filter(
(h) => h !== handler
);
if (this.subscribers[type].length === 0) {
delete this.subscribers[type];
}
}
}

View File

@ -57,6 +57,17 @@ export class ReplyEvent extends Event {
class MessageElement extends HTMLElement {
// static observedAttributes = ['data-uid', 'data-color', 'data-channel_uid', 'data-user_nick', 'data-created_at', 'data-user_uid'];
isVisible() {
if (!this) return false;
const rect = this.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
updateUI() {
if (this._originalChildren === undefined) {
const { color, user_nick, created_at, user_uid} = this.dataset;
@ -93,8 +104,8 @@ class MessageElement extends HTMLElement {
})
}
if ((!this.siblingGenerated || this.siblingGenerated !== this.nextElementSibling) && this.nextElementSibling) {
this.siblingGenerated = this.nextElementSibling;
if (!this.siblingGenerated && this.nextElementSibling) {
this.siblingGenerated = true;
if (this.nextElementSibling?.dataset?.user_uid !== this.dataset.user_uid) {
this.classList.add('switch-user');
} else {
@ -166,10 +177,6 @@ class MessageList extends HTMLElement {
threshold: 0,
})
this.endOfMessages = document.createElement('div');
this.endOfMessages.classList.add('message-list-bottom');
this.prepend(this.endOfMessages);
for(const c of this.children) {
this._observer.observe(c);
if (c instanceof MessageElement) {
@ -177,6 +184,10 @@ class MessageList extends HTMLElement {
}
}
this.endOfMessages = document.createElement('div');
this.endOfMessages.classList.add('message-list-bottom');
this.prepend(this.endOfMessages);
this.scrollToBottom(true);
}
@ -232,13 +243,13 @@ class MessageList extends HTMLElement {
);
}
isScrolledToBottom() {
return this.visibleSet.has(this.endOfMessages)
return this.isElementVisible(this.endOfMessages);
}
scrollToBottom(force = false, behavior= 'instant') {
if (force || !this.isScrolledToBottom()) {
this.endOfMessages.scrollIntoView({ behavior, block: 'end' });
this.firstElementChild.scrollIntoView({ behavior, block: 'end' });
setTimeout(() => {
this.endOfMessages.scrollIntoView({ behavior, block: 'end' });
this.firstElementChild.scrollIntoView({ behavior, block: 'end' });
}, 200);
}
}
@ -291,7 +302,7 @@ class MessageList extends HTMLElement {
}
const scrolledToBottom = this.isScrolledToBottom();
this.endOfMessages.after(message);
this.prepend(message);
if (scrolledToBottom) this.scrollToBottom(true);
}
}

View File

@ -142,9 +142,10 @@ export class Socket extends EventHandler {
method,
args,
};
const me = this;
return new Promise((resolve) => {
this.addEventListener(call.callId, (data) => resolve(data), { once: true});
this.sendJson(call);
me.addEventListener(call.callId, (data) => resolve(data));
me.sendJson(call);
});
}
}

View File

@ -82,32 +82,6 @@ emoji.EMOJI_DATA[
ALLOWED_TAGS = list(bleach.sanitizer.ALLOWED_TAGS) + ["picture"]
def sanitize_html(value):
soup = BeautifulSoup(value, 'html.parser')
for script in soup.find_all('script'):
script.decompose()
#for iframe in soup.find_all('iframe'):
#iframe.decompose()
for tag in soup.find_all(['object', 'embed']):
tag.decompose()
for tag in soup.find_all():
event_attributes = ['onclick', 'onerror', 'onload', 'onmouseover', 'onfocus']
for attr in event_attributes:
if attr in tag.attrs:
del tag[attr]
for img in soup.find_all('img'):
if 'onerror' in img.attrs:
img.decompose()
return soup.prettify()
def sanitize_html2(value):
return bleach.clean(
value,
protocols=list(bleach.sanitizer.ALLOWED_PROTOCOLS) + ["data"],

View File

@ -12,7 +12,7 @@ function showTerm(options){
class StarField {
constructor({ count = 50, container = document.body } = {}) {
constructor({ count = 100, container = document.body } = {}) {
this.container = container;
this.starCount = count;
this.stars = [];
@ -567,7 +567,7 @@ const count = Array.from(messages).filter(el => el.textContent.trim() === text).
const starField = new StarField({starCount: 50});
const starField = new StarField({starCount: 100});
app.starField = starField;
class DemoSequence {