From 0c8ef1324f0930047987a70313473e5797dba0a6 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Fri, 28 May 2021 18:08:33 +0200 Subject: [PATCH 1/3] Delete TEST --- TEST | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 TEST diff --git a/TEST b/TEST deleted file mode 100644 index e69de29b..00000000 From 3370ee50c5e93937133d9a17b66e6dbdb7c08715 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Fri, 28 May 2021 18:10:59 +0200 Subject: [PATCH 2/3] Create codeql-analysis.yml --- .github/workflows/codeql-analysis.yml | 71 +++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 .github/workflows/codeql-analysis.yml diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000..3a3a8e92 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,71 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ master ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ master ] + schedule: + - cron: '25 10 * * 5' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'javascript' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 From 1383911771032214006fc5e7088b621079fc7b21 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Fri, 28 May 2021 22:40:34 +0200 Subject: [PATCH 3/3] automatically embed links in message --- package-lock.json | Bin 770647 -> 780747 bytes package.json | 3 +- .../#channel_id/messages/#message_id/index.ts | 4 +- src/util/Message.ts | 74 +++++++++++++++++- 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 309e7209c9df4b286ae17bd2c094c41ccc55b72b..35201da45e0e1640d76a299811f6619d5a45378c 100644 GIT binary patch delta 6301 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 DK05r% delta 462 zcmX?oS^s*A{)A7ArV~FupS&wTYO@d%i|_RHHZ1y+UHvttKjmOi2uY79Dab50^vQQm zjjYJ^^!N4%D>KV<49=)bH46@l^e!#WD)TAID=u=32uQ7THO?^Ak1UULbj{1EOfL2I z49iMPbF&Nza|+KX4X+9h&e9L@511Zsfk|=l{OjzSv)T4BPJZPl(tJB``|Uu+M#k+T zA&l;J+jmT3Jnu5y`XQsl^gJextJ4z}GxBXea-VUX({^VSrf|mXTcY-z5bo+*X ztdAF?`ZAOjzD%0_a6O02bOk|nkUy6*Zr5DOHvQrD>~{7ri|w|D*_YXD4`bp;u-Pu_ zz`?_~UB!u`ifOx?J4cwn_SguHizV&L&T(vCc8>G#l { data: { ...toObject(message), nonce: undefined } } as MessageUpdateEvent); + postHandleMessage(message); + return res.json(toObject(message)); }); diff --git a/src/util/Message.ts b/src/util/Message.ts index 0d3cdac7..27796997 100644 --- a/src/util/Message.ts +++ b/src/util/Message.ts @@ -1,14 +1,28 @@ -import { ChannelModel, MessageCreateEvent } from "@fosscord/server-util"; +import { ChannelModel, Embed, Message, MessageCreateEvent, MessageUpdateEvent } from "@fosscord/server-util"; import { Snowflake } from "@fosscord/server-util"; import { MessageModel } from "@fosscord/server-util"; import { PublicMemberProjection } from "@fosscord/server-util"; import { toObject } from "@fosscord/server-util"; import { getPermission } from "@fosscord/server-util"; -import { Message } from "@fosscord/server-util"; import { HTTPError } from "lambert-server"; +import fetch from "node-fetch"; +import cheerio from "cheerio"; import { emitEvent } from "./Event"; // TODO: check webhook, application, system author +const LINK_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g; + +const DEFAULT_FETCH_OPTIONS: any = { + redirect: "follow", + follow: 1, + headers: { + "user-agent": "Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)" + }, + size: 1024 * 1024 * 1, + compress: true, + method: "GET" +}; + export async function handleMessage(opts: Partial) { const channel = await ChannelModel.findOne({ id: opts.channel_id }, { guild_id: true, type: true, permission_overwrites: true }).exec(); if (!channel || !opts.channel_id) throw new HTTPError("Channel not found", 404); @@ -43,6 +57,60 @@ export async function handleMessage(opts: Partial) { }; } +// TODO: cache link result in db +export async function postHandleMessage(message: Message) { + var links = message.content?.match(LINK_REGEX); + if (!links) return; + + const data = { ...message }; + data.embeds = data.embeds.filter((x) => x.type !== "link"); + + links = links.slice(0, 5); // embed max 5 links + + for (const link of links) { + try { + const request = await fetch(link, DEFAULT_FETCH_OPTIONS); + + const text = await request.text(); + const $ = cheerio.load(text); + + const title = $('meta[property="og:title"]').attr("content"); + const provider_name = $('meta[property="og:site_name"]').text(); + const author_name = $('meta[property="article:author"]').attr("content"); + const description = $('meta[property="og:description"]').attr("content") || $('meta[property="description"]').attr("content"); + const image = $('meta[property="og:image"]').attr("content"); + const url = $('meta[property="og:url"]').attr("content"); + // TODO: color + const embed: Embed = { + provider: { + url: link, + name: provider_name + } + }; + + if (author_name) embed.author = { name: author_name }; + if (image) embed.thumbnail = { proxy_url: image, url: image }; + if (title) embed.title = title; + if (url) embed.url = url; + if (description) embed.description = description; + + if (title || description) { + data.embeds.push(embed); + } + } catch (error) {} + } + + await Promise.all([ + emitEvent({ + event: "MESSAGE_UPDATE", + guild_id: message.guild_id, + channel_id: message.channel_id, + data + } as MessageUpdateEvent), + MessageModel.updateOne({ id: message.id, channel_id: message.channel_id }, data).exec() + ]); +} + export async function sendMessage(opts: Partial) { const message = await handleMessage({ ...opts, id: Snowflake.generate(), timestamp: new Date() }); @@ -50,5 +118,7 @@ export async function sendMessage(opts: Partial) { await emitEvent({ event: "MESSAGE_CREATE", channel_id: opts.channel_id, data, guild_id: message.guild_id } as MessageCreateEvent); + postHandleMessage(data); // no await as it shouldnt block the message send function + return data; }