feat: handle github lines urls and send content

This commit is contained in:
Jozef Steinhübl 2023-08-25 16:46:42 +02:00
parent 6452ec0b6a
commit 49a1492d40
3 changed files with 69 additions and 5 deletions

6
src/commands/github.ts Normal file
View file

@ -0,0 +1,6 @@
import { defineCommand } from "../loaders/commands.ts";
defineCommand({
name: "github",
description: "Search on github"
})

View file

@ -1,14 +1,19 @@
import { Events, Message } from "discord.js"; import { ActionRowBuilder, ButtonBuilder, ButtonStyle, Events, Message } from "discord.js";
import { defineListener } from "../loaders/listeners.ts"; import { defineListener } from "../loaders/listeners.ts";
import { MESSAGE_PREFIX } from "../constants.ts"; import { MESSAGE_PREFIX } from "../constants.ts";
import { COMMANDS } from "../loaders/commands.ts"; import { COMMANDS } from "../loaders/commands.ts";
import { MessageCommandContext } from "../structs/context/CommandContext.ts"; import { MessageCommandContext } from "../structs/context/CommandContext.ts";
import { extname } from "node:path";
import { safeSlice } from "../util.ts";
const GITHUB_LINE_URL_REGEX = /^(?:https?:\/\/)?(?:www\.)?(?:github)\.com\/(?<repo>[a-zA-Z0-9-_]+\/[A-Za-z0-9_.-]+)\/blob\/(?<path>.+?)#L(?<first_line_number>\d+)[-~]?L?(?<second_line_number>\d*)/i;
defineListener({ defineListener({
event: Events.MessageCreate, event: Events.MessageCreate,
run: async(message: Message) => { run: async(message: Message) => {
if (!message.content.toLowerCase().startsWith(MESSAGE_PREFIX)) if (message.system || message.author.bot) return;
return;
if (!message.content.toLowerCase().startsWith(MESSAGE_PREFIX)) return handleOthers(message);
const [commandName, ...args] = message.content const [commandName, ...args] = message.content
.slice(MESSAGE_PREFIX.length) .slice(MESSAGE_PREFIX.length)
@ -30,3 +35,56 @@ defineListener({
}); });
} }
}); });
function handleOthers(message: Message) {
handleGithubLink(message);
}
async function handleGithubLink(message: Message) {
const match = GITHUB_LINE_URL_REGEX.exec(message.content);
const groups = match?.groups;
if (!groups) return;
const repo = groups.repo;
const path = groups.path;
const extension = extname(path).slice(1);
const firstLineNumber = parseInt(groups.first_line_number) - 1;
const secondLineNumber = parseInt(groups.second_line_number) || firstLineNumber + 1;
// limit, max 25 lines - possible flood
if (secondLineNumber - firstLineNumber > 25) {
message.react("❌");
return;
}
const contentUrl = `https://raw.githubusercontent.com/${repo}/${path}`;
const response = await fetch(contentUrl);
const content = await response.text();
const lines = content.split("\n");
let text = "";
for (let i = 0; i < lines.length; i++) {
if (i < firstLineNumber || i >= secondLineNumber) continue;
const line = lines[i];
text += `${line}\n`;
}
// delete the last \n
text = text.slice(0, -1);
message.reply({
content: `\`\`\`${extension}\n${safeSlice(text, 2000 - 6 - extension.length)}\n\`\`\``,
components: [
new ActionRowBuilder<ButtonBuilder>()
.setComponents(
new ButtonBuilder()
.setLabel(repo)
.setStyle(ButtonStyle.Link)
.setURL(`https://github.com/${repo}`)
)
.toJSON()
]
})
}

View file

@ -1,5 +1,5 @@
export function safeSlice<T>(array: T[], length: number) { export function safeSlice<T>(input: T[] | string, length: number) {
return array.length > length ? array.slice(0, length) : array; return input.length > length ? input.slice(0, length) : input;
} }
export async function silently<T>(value: Promise<T>) { export async function silently<T>(value: Promise<T>) {