<commit_before>/* @flow */

import {
	APP_PRIORITIES,
	TYPE_NOTE,
	TYPE_TEXTREL,
	NOTE_MENTION,
	ROLE_MENTIONED,
} from '../../lib/Constants';
import promisify from '../../lib/promisify';
import { convertRouteToURL } from '../../lib/Route';
import { note as Note } from '../../models/models';
import { bus, cache, config } from '../../core-server';
import type {
	Note as NoteType,
	Text as TextType,
	Thread as ThreadType,
	Room as RoomType,
} from '../../lib/schemaTypes';

const server = `${config.server.protocol}//${config.server.host}`;

const getEntityAsync = promisify(cache.getEntity.bind(cache));

async function getItemsData(textrel): Promise<{
	text: ?TextType;
	room: ?RoomType;
	thread: ?ThreadType;
}> {
	let room, thread;

	const text = await getEntityAsync(textrel.item);

	if (text && text.parents) {
		thread = await getEntityAsync(text.parents[0]);
		room = await getEntityAsync(text.parents[1]);
	}

	return { text, room, thread };
}

async function createMention(textrel): Promise<?Note> {
	const { text, room, thread } = await getItemsData(textrel);
	const now = Date.now();

	if (
		text && text.id &&
		room && room.id &&
		thread && thread.id
	) {
		const note: NoteType = {
			id: '', // make flow happy
			group: thread.id,
			user: textrel.user,
			event: NOTE_MENTION,
			type: TYPE_NOTE,
			createTime: now,
			updateTime: now,
			count: 1,
			score: 50,
			data: {
				id: text.id,
				creator: text.creator,
				picture: `${server}/i/picture?user=${text.creator}&size=${128}`,
				room: {
					id: room.id,
					name: room.name,
				},
				thread: {
					id: thread.id,
					thread: thread.name,
				},
				link: server + convertRouteToURL({
					name: 'chat',
					props: {
						room: room.id,
						thread: thread.id,
					}
				}),
				title: `${room.name}: ${text.creator} mentioned you in ${thread.name}`,
				body: text.body,
			},
		};

		return new Note(note);
	}

	return null;
}

function isMentioned(entity): boolean {
	return entity.type === TYPE_TEXTREL && entity.roles && entity.roles.includes(ROLE_MENTIONED);
}

async function getNotesFromChanges(changes): Promise<Array<?Note>> {
	const promises = [];

	if (changes.entities) {
		for (const id in changes.entities) {
			const relation = changes.entities[id];

			if (isMentioned(relation)) {
				promises.push(createMention(relation));
			}
		}
	}

	return await Promise.all(promises);
}

async function addNotesToChanges(changes) {
	const notes = await getNotesFromChanges(changes);

	for (let i = 0, l = notes.length; i < l; i++) {
		const note = notes[i];

		if (note && note.id) {
			changes.entities[note.id] = note;
		}
	}
}

bus.on('change', async (changes, next) => {
	try {
		await addNotesToChanges(changes);
		next();
	} catch (err) {
		next(err);
	}
}, APP_PRIORITIES.NOTE);
<commit_msg>fix(note): get the text object from changes as it hasn't been inserted into database yet<commit_after>/* @flow */

import {
	APP_PRIORITIES,
	TYPE_NOTE,
	TYPE_TEXTREL,
	NOTE_MENTION,
	ROLE_MENTIONED,
} from '../../lib/Constants';
import promisify from '../../lib/promisify';
import { convertRouteToURL } from '../../lib/Route';
import { note as Note } from '../../models/models';
import { bus, cache, config } from '../../core-server';
import type {
	Note as NoteType,
	Text as TextType,
	Thread as ThreadType,
	Room as RoomType,
	TextRel as TextRelType,
} from '../../lib/schemaTypes';

const server = `${config.server.protocol}//${config.server.host}`;

const getEntityAsync = promisify(cache.getEntity.bind(cache));

async function createMention(textrel: TextRelType, text: ?TextType): Promise<?Note> {
	let room: ?RoomType, thread: ?ThreadType;

	if (text && text.parents) {
		thread = await getEntityAsync(text.parents[0]);
		room = await getEntityAsync(text.parents[1]);
	}

	if (
		text && text.id &&
		room && room.id &&
		thread && thread.id
	) {
		const now = Date.now();
		const note: NoteType = {
			id: '', // make flow happy
			group: thread.id,
			user: textrel.user,
			event: NOTE_MENTION,
			type: TYPE_NOTE,
			createTime: now,
			updateTime: now,
			count: 1,
			score: 50,
			data: {
				id: text.id,
				creator: text.creator,
				picture: `${server}/i/picture?user=${text.creator}&size=${128}`,
				room: {
					id: room.id,
					name: room.name,
				},
				thread: {
					id: thread.id,
					thread: thread.name,
				},
				link: server + convertRouteToURL({
					name: 'chat',
					props: {
						room: room.id,
						thread: thread.id,
					}
				}),
				title: `${room.name}: ${text.creator} mentioned you in ${thread.name}`,
				body: text.body,
			},
		};

		return new Note(note);
	}

	return null;
}

function isMentioned(entity): boolean {
	return entity.type === TYPE_TEXTREL && entity.roles && entity.roles.includes(ROLE_MENTIONED);
}

async function getNotesFromChanges(changes): Promise<Array<?Note>> {
	const promises = [];

	if (changes.entities) {
		for (const id in changes.entities) {
			const relation = changes.entities[id];

			if (isMentioned(relation)) {
				promises.push(createMention(relation, changes.entities[relation.item]));
			}
		}
	}

	return await Promise.all(promises);
}

async function addNotesToChanges(changes) {
	const notes = await getNotesFromChanges(changes);

	for (let i = 0, l = notes.length; i < l; i++) {
		const note = notes[i];

		if (note && note.id) {
			changes.entities[note.id] = note;
		}
	}
}

bus.on('change', async (changes, next) => {
	try {
		await addNotesToChanges(changes);
		next();
	} catch (err) {
		next(err);
	}
}, APP_PRIORITIES.NOTE);

{'fraction_non_alphanumeric': 0.16241635015373485, 'fraction_numerical': 0.0032555615843733042, 'mean_word_length': 3.3577620173364853, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7025009', 'n_tokens_mistral': 2189, 'n_tokens_neox': 1927, 'n_words': 463}