diff --git a/commands/gamexplain.js b/commands/gamexplain.js index cebec0aa..4f73cdc0 100644 --- a/commands/gamexplain.js +++ b/commands/gamexplain.js @@ -11,7 +11,7 @@ exports.run = async (message) => { const template = "./assets/images/gamexplain.png"; const path = `/tmp/${Math.random().toString(36).substring(2, 15)}.${image.type}`; require("util").promisify(fs.writeFile)(path, image.data); - const command = gm(template).background("white").out("null:").out("(").out(path).out("-virtual-pixel", "transparent").resize("1181x571!").coalesce().out(")").compose("over").gravity("Center").out("-geometry", "+0+40").out("-layers", "composite").out("-layers", "optimize"); + const command = gm(template).background("white").out("null:").out("(").out(path).coalesce().out("-virtual-pixel", "transparent").resize("1181x571!").out(")").compose("over").gravity("Center").out("-geometry", "+0+40").out("-layers", "composite").out("-layers", "optimize"); return message.channel.createMessage("", { file: await gmToBuffer(command, image.type), name: `gamexplain.${image.type}` diff --git a/commands/screenshot.js b/commands/screenshot.js new file mode 100644 index 00000000..93b6b383 --- /dev/null +++ b/commands/screenshot.js @@ -0,0 +1,30 @@ +const urlRegex = /(?:\w+:)?\/\/(\S+)/; +const puppeteer = require("puppeteer-core"); +const fetch = require("node-fetch"); + +exports.run = async (message, args) => { + message.channel.sendTyping(); + if (args.length === 0) return `${message.author.mention}, you need to provide a URL to screenshot!`; + const getEndpoint = await fetch("http://192.168.99.100:9222/json/version"); + const endpoint = await getEndpoint.json(); + const url = urlRegex.test(args[0]) ? args[0] : `http://${args[0]}`; + const browser = await puppeteer.connect({ + browserWSEndpoint: endpoint.webSocketDebuggerUrl, + defaultViewport: { + width: 1280, + height: 720 + } + }); + const page = await browser.newPage(); + await page.goto(url); + const screenshot = await page.screenshot(); + await page.close(); + return message.channel.createMessage("", { + file: screenshot, + name: "screenshot.png" + }); +}; + +exports.aliases = ["webshot", "ss", "shot", "page"]; +exports.category = 5; +exports.help = "Screenshots a webpage"; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4b2f11c4..7fd5f9be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "esmbot", - "version": "1.1.5", + "version": "1.1.7", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -29,6 +29,11 @@ "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz", "integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w==" }, + "@types/mime-types": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz", + "integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=" + }, "@types/node": { "version": "13.1.8", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.1.8.tgz", @@ -46,6 +51,11 @@ "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", "dev": true }, + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==" + }, "ajv": { "version": "6.10.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", @@ -165,6 +175,11 @@ "lodash": "^4.17.11" } }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -183,8 +198,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base64-js": { "version": "1.3.1", @@ -237,7 +251,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -470,8 +483,47 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } }, "console-control-strings": { "version": "1.1.0", @@ -896,6 +948,32 @@ } } }, + "extract-zip": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", + "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", + "requires": { + "concat-stream": "1.6.2", + "debug": "2.6.9", + "mkdirp": "0.5.1", + "yauzl": "2.4.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -922,6 +1000,14 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==" }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "requires": { + "pend": "~1.2.0" + } + }, "fecha": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", @@ -1008,8 +1094,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "functional-red-black-tree": { "version": "1.0.1", @@ -1092,7 +1177,6 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1167,6 +1251,25 @@ "sshpk": "^1.7.0" } }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "requires": { + "agent-base": "5", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1207,7 +1310,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -1458,7 +1560,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -1822,8 +1923,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { "version": "1.0.2", @@ -1842,6 +1942,11 @@ "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-3.1.0.tgz", "integrity": "sha512-KGuODSTV6hcgdZvDrIDBUkN0utcAVj1LL7FfGbM0viKTtCHmtZcuEJ+lGqsp0fTFkGqesdtemV2yUSMeyy3ddA==" }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -1895,8 +2000,12 @@ "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=" }, "pseudomap": { "version": "1.0.2", @@ -1922,6 +2031,46 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, + "puppeteer-core": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-2.1.1.tgz", + "integrity": "sha512-n13AWriBMPYxnpbb6bnaY5YoY6rGj8vPLrz6CZF3o0qJNEwlcfJVxBzYZ0NJsQ21UbdJoijPCDrM++SUVEz7+w==", + "requires": { + "@types/mime-types": "^2.1.0", + "debug": "^4.1.0", + "extract-zip": "^1.6.6", + "https-proxy-agent": "^4.0.0", + "mime": "^2.0.3", + "mime-types": "^2.1.25", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^2.6.1", + "ws": "^6.1.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==" + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, "qrcode": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.4.4.tgz", @@ -2146,7 +2295,6 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -2601,6 +2749,11 @@ "prelude-ls": "~1.1.2" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -2857,6 +3010,14 @@ "decamelize": "^1.2.0" } }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "requires": { + "fd-slicer": "~1.0.1" + } + }, "zlib-sync": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/zlib-sync/-/zlib-sync-0.1.6.tgz", diff --git a/package.json b/package.json index 928d11ac..8fdce6fb 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,10 @@ "engines": { "node": ">=8" }, + "scripts": { + "docker:build": "docker build -t headless-chrome-alpine --no-cache ./utils/screenshot", + "docker:run": "docker run --rm -it --network=\"host\" headless-chrome-alpine" + }, "author": "Essem ", "license": "MIT", "repository": { @@ -25,6 +29,7 @@ "moment-duration-format": "^2.3.2", "mongoose": "^5.8.9", "node-fetch": "^2.6.0", + "puppeteer-core": "^2.1.1", "qrcode": "^1.4.4", "retrotext": "github:TheEssem/retrotext", "sharp": "^0.23.4", diff --git a/utils/screenshot/Dockerfile b/utils/screenshot/Dockerfile new file mode 100644 index 00000000..23006cb0 --- /dev/null +++ b/utils/screenshot/Dockerfile @@ -0,0 +1,23 @@ +# if your install supports docker and you don't want to run chromium directly then you can use this dockerfile instead +# this also comes with a squid proxy to automatically handle errors and some privacy stuff +# adapted from https://github.com/westy92/headless-chrome-alpine/blob/master/Dockerfile + +FROM alpine:edge + +RUN apk --no-cache upgrade && apk add --no-cache chromium && apk add --no-cache squid && apk add --no-cache sudo + +ENV ALL_PROXY "http://localhost:3128" +RUN echo -e "\nvisible_hostname esmBot\nforwarded_for delete\nvia off\nfollow_x_forwarded_for deny all \ +\nrequest_header_access X-Forwarded-For deny all\nerror_default_language en\n" >> /etc/squid/squid.conf +COPY ./ERR_DNS_FAIL /usr/share/squid/errors/en/ + +RUN adduser esmBot -s /bin/sh -D +WORKDIR /home/esmBot/.internal +COPY . . +RUN chmod +x start.sh +RUN echo -e "\nesmBot ALL=(ALL) NOPASSWD:ALL\n" >> /etc/sudoers +USER esmBot + +EXPOSE 9222 + +ENTRYPOINT ["sh", "./start.sh"] \ No newline at end of file diff --git a/utils/screenshot/ERR_DNS_FAIL b/utils/screenshot/ERR_DNS_FAIL new file mode 100644 index 00000000..b8bc2b17 --- /dev/null +++ b/utils/screenshot/ERR_DNS_FAIL @@ -0,0 +1,63 @@ + + + + + + + + + +
+
+ +

An error was encountered while trying to load %H:

+

%z

+
+
+ + + diff --git a/utils/screenshot/start.sh b/utils/screenshot/start.sh new file mode 100644 index 00000000..7cc610fb --- /dev/null +++ b/utils/screenshot/start.sh @@ -0,0 +1,16 @@ +sudo squid & chromium-browser \ + --disable-background-networking \ + --disable-default-apps \ + --disable-extensions \ + --disable-gpu \ + --disable-sync \ + --disable-translate \ + --headless \ + --hide-scrollbars \ + --metrics-recording-only \ + --mute-audio \ + --no-first-run \ + --no-sandbox \ + --remote-debugging-address=0.0.0.0 \ + --remote-debugging-port=9222 \ + --safebrowsing-disable-auto-update \ No newline at end of file