diff --git a/package.json b/package.json index 34cd7a8..235b037 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ }, "devDependencies": { "@esbuild-plugins/node-resolve": "^0.1.4", - "@types/bad-words": "^3.0.1", "@types/node": "^17.0.38", "@typescript-eslint/eslint-plugin": "^5.25.0", "@typescript-eslint/parser": "^5.25.0", diff --git a/src/index.ts b/src/index.ts index aa19a04..5f3a8ae 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,7 +14,7 @@ import * as fs from 'fs'; import * as path from 'path'; import { SuccessfulParsedMessage } from 'discord-command-parser'; import * as dotenv from 'dotenv'; -import { parseLog } from './mclogs'; +import { parseLog } from './logs'; dotenv.config(); export interface Command { diff --git a/src/logproviders/0x0.ts b/src/logproviders/0x0.ts new file mode 100644 index 0000000..6bc436a --- /dev/null +++ b/src/logproviders/0x0.ts @@ -0,0 +1,19 @@ +const reg = /https\:\/\/0x0.st\/[^ ]*/; + +export async function read0x0(s: string): Promise { + const r = s.match(reg); + if (r == null || !r[0]) return null; + const link = r[0]; + let log: string; + try { + const f = await fetch(link); + if (f.status != 200) { + throw 'nope'; + } + log = await f.text(); + } catch (err) { + console.log('Log analyze fail', err); + return null; + } + return log; +} diff --git a/src/logproviders/haste.ts b/src/logproviders/haste.ts new file mode 100644 index 0000000..331fa43 --- /dev/null +++ b/src/logproviders/haste.ts @@ -0,0 +1,21 @@ +const reg = /https\:\/\/hst.sh\/[\w]*/; + +export async function readHastebin(s: string): Promise { + const r = s.match(reg); + if (r == null || !r[0]) return null; + const link = r[0]; + const id = link.replace('https://hst.sh/', ''); + if (!id) return null; + let log: string; + try { + const f = await fetch(`https://hst.sh/raw/${id}`); + if (f.status != 200) { + throw 'nope'; + } + log = await f.text(); + } catch (err) { + console.log('Log analyze fail', err); + return null; + } + return log; +} diff --git a/src/logproviders/mclogs.ts b/src/logproviders/mclogs.ts new file mode 100644 index 0000000..8972614 --- /dev/null +++ b/src/logproviders/mclogs.ts @@ -0,0 +1,22 @@ +const reg = /https\:\/\/mclo.gs\/[^ ]*/; + +export async function readMcLogs(s: string): Promise { + const r = s.match(reg); + if (r == null || !r[0]) return null; + const link = r[0]; + const id = link.replace('https://mclo.gs/', ''); + if (!id) return null; + const apiUrl = 'https://api.mclo.gs/1/raw/' + id; + let log: string; + try { + const f = await fetch(apiUrl); + if (f.status != 200) { + throw 'nope'; + } + log = await f.text(); + } catch (err) { + console.log('Log analyze fail', err); + return null; + } + return log; +} diff --git a/src/logproviders/pastegg.ts b/src/logproviders/pastegg.ts new file mode 100644 index 0000000..f721532 --- /dev/null +++ b/src/logproviders/pastegg.ts @@ -0,0 +1,30 @@ +const reg = /https\:\/\/paste.gg\/p\/[\w]*\/[\w]*/; + +export async function readPasteGG(s: string): Promise { + const r = s.match(reg); + if (r == null || !r[0]) return null; + const link = r[0]; + const id = link.replace(/https\:\/\/paste.gg\/p\/[\w]*\//, ''); + if (!id) return null; + let log: string; + try { + const pasteJson = await ( + await fetch('https://api.paste.gg/v1/pastes/' + id) + ).json(); + if (pasteJson.status != 'success') throw 'up'; + const pasteData = await ( + await fetch( + 'https://api.paste.gg/v1/pastes/' + + id + + '/files/' + + pasteJson.result.files[0].id + ) + ).json(); + if (pasteData.status != 'success') throw 'up'; + return pasteData.result.content.value; + } catch (err) { + console.log('Log analyze fail', err); + return null; + } + return log; +} diff --git a/src/logs.ts b/src/logs.ts new file mode 100644 index 0000000..8985665 --- /dev/null +++ b/src/logs.ts @@ -0,0 +1,143 @@ +import { getLatest } from './version'; +import { MessageEmbed } from 'discord.js'; +// log providers +import { readMcLogs } from './logproviders/mclogs'; +import { read0x0 } from './logproviders/0x0'; +import { readPasteGG } from './logproviders/pastegg'; +import { readHastebin } from './logproviders/haste'; + +const reg = /https\:\/\/mclo.gs\/[^ ]*/g; + +type analyzer = (text: string) => Promise | null>; +type logProvider = (text: string) => Promise; + +const javaAnalyzer: analyzer = async (text) => { + if (text.includes('This instance is not compatible with Java version')) { + const xp = + /Please switch to one of the following Java versions for this instance:[\r\n]+([^\r\n]+)/g; + + let ver: string; + const m = text.match(xp); + if (!m || !m[0]) { + ver = ''; + } else { + ver = m[0].split('\n')[1]; + } + + return [ + 'Wrong Java Version', + `Please switch to the following: \`${ver}\`\nFor more information, type \`!java\``, + ]; + } + return null; +}; + +const versionAnalyzer: analyzer = async (text) => { + const vers = text.match(/PolyMC version: [0-9].[0-9].[0-9]/g); + if (vers && vers[0]) { + const latest = await getLatest(); + const current = vers[0].replace('PolyMC version: ', ''); + if (latest != current) { + return [ + 'Outdated PolyMC', + `Your installed version is ${current}, while the newest version is ${latest}.\nPlease update, for more info see https://polymc.org/download/`, + ]; + } + } + return null; +}; + +const flatpakNvidiaAnalyzer: analyzer = async (text) => { + if ( + text.includes('org.lwjgl.LWJGLException: Could not choose GLX13 config') + ) { + return [ + 'Outdated Nvidia Flatpak Driver', + `The Nvidia driver for flatpak is outdated.\nPlease run \`flatpak update\` to fix this issue. If that does not solve it, please wait until the driver is added to Flathub and run it again.`, + ]; + } + return null; +}; + +const forgeJavaAnalyzer: analyzer = async (text) => { + if ( + text.includes( + 'java.lang.NoSuchMethodError: sun.security.util.ManifestEntryVerifier.(Ljava/util/jar/Manifest;)V' + ) + ) { + return [ + 'Forge Java Bug', + 'Old versions of Forge crash with Java 8u321+. For this reason, using Java 8u312 or lower is reccomended.\nYou can also update Forge via the Versions tab.', + ]; + } + return null; +}; + +const intelHDAnalyzer: analyzer = async (text) => { + if (text.includes('org.lwjgl.LWJGLException: Pixel format not accelerated')) { + return [ + 'Intel HD Windows 10', + "Your drivers don't support windows 10 officially\nSee https://polymc.org/wiki/getting-started/installing-java/#a-note-about-intel-hd-20003000-on-windows-10 for more info", + ]; + } + return null; +}; + +const macOSNSWindowAnalyzer: analyzer = async (text) => { + if ( + text.includes( + "Terminating app due to uncaught exception 'NSInternalInconsistencyException'" + ) + ) { + return [ + 'MacOS NSInternalInconsistencyException', + 'You need to downgrade your Java 8 version. See https://polymc.org/wiki/getting-started/installing-java/#older-minecraft-on-macos', + ]; + } + return null; +}; + +const analyzers: analyzer[] = [ + javaAnalyzer, + versionAnalyzer, + flatpakNvidiaAnalyzer, + forgeJavaAnalyzer, + intelHDAnalyzer, + macOSNSWindowAnalyzer, +]; + +const providers: logProvider[] = [ + readMcLogs, + read0x0, + readPasteGG, + readHastebin, +]; + +export async function parseLog(s: string): Promise { + let log: string = ''; + for (let i in providers) { + const provider = providers[i]; + const res = await provider(s); + if (res) { + log = res; + break; + } else { + continue; + } + } + if (!log) return null; + + const embed = new MessageEmbed() + .setTitle('Log analysis') + .setColor('DARK_GREEN'); + for (let i in analyzers) { + const analyzer = analyzers[i]; + const out = await analyzer(log); + if (out) embed.addField(out[0], out[1]); + } + if (embed.fields[0]) return embed; + else { + embed.addField('Analyze failed', 'No issues found automatically'); + return embed; + } +} diff --git a/src/mclogs.ts b/src/mclogs.ts deleted file mode 100644 index 1ee4c81..0000000 --- a/src/mclogs.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { getLatest } from './version'; -import { MessageEmbed } from 'discord.js'; -const reg = /https\:\/\/mclo.gs\/[^ ]*/g; - -type analyzer = (text: string) => Promise | null>; -const javaAnalyzer: analyzer = async (text) => { - if (text.includes('This instance is not compatible with Java version')) { - const xp = - /Please switch to one of the following Java versions for this instance:[\r\n]+([^\r\n]+)/g; - - let ver: string; - const m = text.match(xp); - if (!m || !m[0]) { - ver = ''; - } else { - ver = m[0].split('\n')[1]; - } - - return [ - 'WrongJavaVersion', - `Please switch to the following: \`${ver}\`\nFor more information, type \`!java\``, - ]; - } - return null; -}; - -const versionAnalyzer: analyzer = async (text) => { - const vers = text.match(/PolyMC version: [0-9].[0-9].[0-9]/g); - if (vers && vers[0]) { - const latest = await getLatest(); - const current = vers[0].replace('PolyMC version: ', ''); - if (latest != current) { - return [ - 'OutdatedPolyMC', - `Your installed version is ${current}, while the newest version is ${latest}.\nPlease update, for more info see https://polymc.org/download/`, - ]; - } - } - return null; -}; - -const analyzers: analyzer[] = [javaAnalyzer, versionAnalyzer]; - -export async function parseLog(s: string): Promise { - const r = s.match(reg); - if (r == null || !r[0]) return null; - const link = r[0]; // for now only first url - const id = link.replace('https://mclo.gs/', ''); - if (!id) return null; - const apiUrl = 'https://api.mclo.gs/1/raw/' + id; - - let log: string; - try { - const f = await fetch(apiUrl); - if (f.status != 200) { - throw 'nope'; - } - log = await f.text(); - } catch (err) { - console.log('Log analyze fail', err); - return null; - } - console.log(apiUrl); - const embed = new MessageEmbed() - .setTitle('Log analyzer') - .setColor('DARK_GREEN') - .setDescription(`Analysis of ${link} [${apiUrl}] [ID: ${id}]`); - for (let i in analyzers) { - const analyzer = analyzers[i]; - const out = await analyzer(log); - if (out) embed.addField(out[0], out[1]); - } - if (embed.fields[0]) return embed; - else { - embed.addField('Analyze failed', 'No issues found automatically'); - return embed; - } -} diff --git a/src/tags.json b/src/tags.json index 776c4a1..333536c 100644 --- a/src/tags.json +++ b/src/tags.json @@ -5,7 +5,7 @@ "aliases": ["migr", "mmc"] }, { - "name": "matrix-space", + "name": "thematrix", "text": "https://matrix.to/#/#polymc:matrix.org" }, { diff --git a/yarn.lock b/yarn.lock index 34492b1..e7815e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -191,11 +191,6 @@ dependencies: defer-to-connect "^1.0.1" -"@types/bad-words@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/bad-words/-/bad-words-3.0.1.tgz#6a20fb08814af5e1f2428fa9e0098ca7b36f730a" - integrity sha512-7la3ZDJG1tlRqySO+pnXycZpacaMEw/iLEm8kc4l+I+jN8KjBfoQVwO6jm98xzXVLrxV8vDrB5TaMoop8sKclQ== - "@types/chrome@^0.0.183": version "0.0.183" resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.183.tgz#c12649c00ae5ae8fca511248256c0b11f91c95e2" @@ -2006,9 +2001,9 @@ typedarray-to-buffer@^3.1.5: is-typedarray "^1.0.0" typescript@^4.6.4: - version "4.6.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" - integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== + version "4.7.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d" + integrity sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA== undefsafe@^2.0.5: version "2.0.5"