123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- import URI from 'urijs';
- import log from '../log.js';
- import { settings_api } from '../shared/settings/api.js';
- import { URL_PARSE_OPTIONS } from '../shared/constants.js';
- const settings = settings_api;
- /**
- * Will return false if URL is malformed or contains disallowed characters
- * @param {string} text
- * @returns {boolean}
- */
- export function isValidURL (text) {
- try {
- return !!(new URL(text));
- } catch {
- return false;
- }
- }
- /**
- * @param {string|URI} url
- */
- export function getURI (url) {
- try {
- return url instanceof URI ? url : new URI(url);
- } catch (error) {
- log.debug(error);
- return null;
- }
- }
- /**
- * Given the an array of file extensions, check whether a URL points to a file
- * ending in one of them.
- * @param {string[]} types - An array of file extensions
- * @param {string} url
- * @returns {boolean}
- * @example
- * checkFileTypes(['.gif'], 'https://conversejs.org/cat.gif?foo=bar');
- */
- export function checkFileTypes (types, url) {
- const uri = getURI(url);
- if (uri === null) {
- throw new Error(`checkFileTypes: could not parse url ${url}`);
- }
- const filename = uri.filename().toLowerCase();
- return !!types.filter(ext => filename.endsWith(ext)).length;
- }
- export function filterQueryParamsFromURL (url) {
- const paramsArray = settings.get('filter_url_query_params');
- if (!paramsArray) return url;
- const parsed_uri = getURI(url);
- return parsed_uri.removeQuery(paramsArray).toString();
- }
- export function isURLWithImageExtension (url) {
- return checkFileTypes(['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.svg'], url);
- }
- export function isGIFURL (url) {
- return checkFileTypes(['.gif'], url);
- }
- export function isAudioURL (url) {
- return checkFileTypes(['.ogg', '.mp3', '.m4a'], url);
- }
- export function isVideoURL (url) {
- return checkFileTypes(['.mp4', '.webm'], url);
- }
- export function isImageURL (url) {
- const regex = settings.get('image_urls_regex');
- return regex?.test(url) || isURLWithImageExtension(url);
- }
- export function isEncryptedFileURL (url) {
- return url.startsWith('aesgcm://');
- }
- /**
- * @typedef {Object} MediaURLMetadata
- * An object representing the metadata of a URL found in a chat message
- * The actual URL is not saved, it can be extracted via the `start` and `end` indexes.
- * @property {boolean} [is_audio]
- * @property {boolean} [is_image]
- * @property {boolean} [is_video]
- * @property {boolean} [is_encrypted]
- * @property {number} [end]
- * @property {number} [start]
- */
- /**
- * An object representing a URL found in a chat message
- * @typedef {MediaURLMetadata} MediaURLData
- * @property {string} url
- */
- /**
- * @param {string} text
- * @param {number} offset
- * @returns {{media_urls?: MediaURLMetadata[]}}
- */
- export function getMediaURLsMetadata (text, offset=0) {
- const objs = [];
- if (!text) {
- return {};
- }
- try {
- URI.withinString(
- text,
- (url, start, end) => {
- if (url.startsWith('_')) {
- url = url.slice(1);
- start += 1;
- }
- if (url.endsWith('_')) {
- url = url.slice(0, url.length-1);
- end -= 1;
- }
- objs.push({ url, 'start': start+offset, 'end': end+offset });
- return url;
- },
- URL_PARSE_OPTIONS
- );
- } catch (error) {
- log.debug(error);
- }
- const media_urls = objs
- .map(o => ({
- 'end': o.end,
- 'is_audio': isAudioURL(o.url),
- 'is_image': isImageURL(o.url),
- 'is_video': isVideoURL(o.url),
- 'is_encrypted': isEncryptedFileURL(o.url),
- 'start': o.start
- }));
- return media_urls.length ? { media_urls } : {};
- }
- /**
- * Given an array of {@link MediaURLMetadata} objects and text, return an
- * array of {@link MediaURL} objects.
- * @param {Array<MediaURLMetadata>} arr
- * @param {string} text
- * @returns {MediaURLData[]}
- */
- export function getMediaURLs (arr, text, offset=0) {
- return arr.map(o => {
- const start = o.start - offset;
- const end = o.end - offset;
- if (start < 0 || start >= text.length) {
- return null;
- }
- return (Object.assign({}, o, {
- start,
- end,
- 'url': text.substring(o.start-offset, o.end-offset),
- }));
- }).filter(o => o);
- }
|