Permalink
Cannot retrieve contributors at this time
217 lines (172 sloc)
5.39 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
frappe/frappe/chat/doctype/chat_message/chat_message.py /
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains 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
| from __future__ import unicode_literals | |
| # imports - standard imports | |
| import json | |
| # imports - third-party imports | |
| import requests | |
| from bs4 import BeautifulSoup as Soup | |
| # imports - module imports | |
| from frappe.model.document import Document | |
| from frappe import _, _dict | |
| import frappe | |
| # imports - frappe module imports | |
| from frappe.chat import authenticate | |
| from frappe.chat.util import ( | |
| get_if_empty, | |
| check_url, | |
| dictify, | |
| get_emojis, | |
| safe_json_loads, | |
| get_user_doc, | |
| squashify | |
| ) | |
| session = frappe.session | |
| class ChatMessage(Document): | |
| pass | |
| def get_message_urls(content): | |
| soup = Soup(content, 'html.parser') | |
| anchors = soup.find_all('a') | |
| urls = [ ] | |
| for anchor in anchors: | |
| text = anchor.text | |
| if check_url(text): | |
| urls.append(text) | |
| return urls | |
| def get_message_mentions(content): | |
| mentions = [ ] | |
| tokens = content.split(' ') | |
| for token in tokens: | |
| if token.startswith('@'): | |
| what = token[1:] | |
| if frappe.db.exists('User', what): | |
| mentions.append(what) | |
| else: | |
| if frappe.db.exists('User', token): | |
| mentions.append(token) | |
| return mentions | |
| def get_message_meta(content): | |
| ''' | |
| Assumes content to be HTML. Sanitizes the content | |
| into a dict of metadata values. | |
| ''' | |
| meta = _dict( | |
| links = [ ], | |
| mentions = [ ] | |
| ) | |
| meta.content = content | |
| meta.urls = get_message_urls(content) | |
| meta.mentions = get_message_mentions(content) | |
| return meta | |
| def sanitize_message_content(content): | |
| emojis = get_emojis() | |
| tokens = content.split(' ') | |
| for token in tokens: | |
| if token.startswith(':') and token.endswith(':'): | |
| what = token[1:-1] | |
| # Expensive, I know. | |
| for emoji in emojis: | |
| for alias in emoji.aliases: | |
| if what == alias: | |
| content = content.replace(token, emoji.emoji) | |
| return content | |
| def get_new_chat_message_doc(user, room, content, type = "Content", link = True): | |
| user = get_user_doc(user) | |
| room = frappe.get_doc('Chat Room', room) | |
| meta = get_message_meta(content) | |
| mess = frappe.new_doc('Chat Message') | |
| mess.room = room.name | |
| mess.room_type = room.type | |
| mess.content = sanitize_message_content(content) | |
| mess.type = type | |
| mess.user = user.name | |
| mess.mentions = json.dumps(meta.mentions) | |
| mess.urls = ','.join(meta.urls) | |
| mess.save(ignore_permissions = True) | |
| if link: | |
| room.update(dict( | |
| last_message = mess.name | |
| )) | |
| room.save(ignore_permissions = True) | |
| return mess | |
| def get_new_chat_message(user, room, content, type = "Content"): | |
| mess = get_new_chat_message_doc(user, room, content, type) | |
| resp = dict( | |
| name = mess.name, | |
| user = mess.user, | |
| room = mess.room, | |
| room_type = mess.room_type, | |
| content = json.loads(mess.content) if mess.type in ["File"] else mess.content, | |
| urls = mess.urls, | |
| mentions = json.loads(mess.mentions), | |
| creation = mess.creation, | |
| seen = json.loads(mess._seen) if mess._seen else [ ], | |
| ) | |
| return resp | |
| @frappe.whitelist(allow_guest = True) | |
| def send(user, room, content, type = "Content"): | |
| mess = get_new_chat_message(user, room, content, type) | |
| frappe.publish_realtime('frappe.chat.message:create', mess, room = room, | |
| after_commit = True) | |
| @frappe.whitelist(allow_guest = True) | |
| def seen(message, user = None): | |
| authenticate(user) | |
| has_message = frappe.db.exists('Chat Message', message) | |
| if has_message: | |
| mess = frappe.get_doc('Chat Message', message) | |
| mess.add_seen(user) | |
| mess.load_from_db() | |
| room = mess.room | |
| resp = dict(message = message, data = dict(seen = json.loads(mess._seen) if mess._seen else [])) | |
| frappe.publish_realtime('frappe.chat.message:update', resp, room = room, after_commit = True) | |
| def history(room, fields = None, limit = 10, start = None, end = None): | |
| room = frappe.get_doc('Chat Room', room) | |
| mess = frappe.get_all('Chat Message', | |
| filters = [ | |
| ('Chat Message', 'room', '=', room.name), | |
| ('Chat Message', 'room_type', '=', room.type) | |
| ], | |
| fields = fields if fields else [ | |
| 'name', 'room_type', 'room', 'content', 'type', 'user', 'mentions', 'urls', 'creation', '_seen' | |
| ], | |
| order_by = 'creation' | |
| ) | |
| if not fields or 'seen' in fields: | |
| for m in mess: | |
| m['seen'] = json.loads(m._seen) if m._seen else [ ] | |
| del m['_seen'] | |
| if not fields or 'content' in fields: | |
| for m in mess: | |
| m['content'] = json.loads(m.content) if m.type in ["File"] else m.content | |
| frappe.enqueue('frappe.chat.doctype.chat_message.chat_message.mark_messages_as_seen', | |
| message_names=[m.name for m in mess], user=frappe.session.user) | |
| return mess | |
| def mark_messages_as_seen(message_names, user): | |
| ''' | |
| Marks chat messages as seen, updates the _seen for each message | |
| (should be run in background process) | |
| ''' | |
| for name in message_names: | |
| seen = frappe.db.get_value('Chat Message', name, '_seen') or '[]' | |
| seen = json.loads(seen) | |
| seen.append(user) | |
| seen = json.dumps(seen) | |
| frappe.db.set_value('Chat Message', name, '_seen', seen, update_modified=False) | |
| frappe.db.commit() | |
| @frappe.whitelist() | |
| def get(name, rooms = None, fields = None): | |
| rooms, fields = safe_json_loads(rooms, fields) | |
| has_message = frappe.db.exists('Chat Message', name) | |
| if has_message: | |
| dmess = frappe.get_doc('Chat Message', name) | |
| data = dict( | |
| name = dmess.name, | |
| user = dmess.user, | |
| room = dmess.room, | |
| room_type = dmess.room_type, | |
| content = json.loads(dmess.content) if dmess.type in ["File"] else dmess.content, | |
| type = dmess.type, | |
| urls = dmess.urls, | |
| mentions = dmess.mentions, | |
| creation = dmess.creation, | |
| seen = get_if_empty(dmess._seen, [ ]) | |
| ) | |
| return data |