mirror of
https://github.com/captbaritone/webamp.git
synced 2026-08-04 16:04:55 +00:00
Type !archive
This commit is contained in:
parent
89366e84ac
commit
f4ba178d40
6 changed files with 139 additions and 104 deletions
46
experiments/skin-database/addSkin.ts
Normal file
46
experiments/skin-database/addSkin.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import * as Skins from "./data/skins";
|
||||
import fs from "fs";
|
||||
import md5Buffer from "md5";
|
||||
import * as S3 from "./s3";
|
||||
import Shooter from "./shooter";
|
||||
import _temp from "temp";
|
||||
import * as Analyser from "./analyser";
|
||||
|
||||
const temp = _temp.track();
|
||||
|
||||
// TODO
|
||||
// Extract the readme
|
||||
// Extract the emails
|
||||
// Upload to Internet Archive
|
||||
// Store the Internet Archive item name
|
||||
// Construct IA Webamp UR
|
||||
type Result =
|
||||
| { md5: string; status: "FOUND" }
|
||||
| { md5: string; status: "ADDED"; averageColor: string };
|
||||
|
||||
export async function addSkinFromBuffer(
|
||||
buffer: Buffer,
|
||||
filePath: string,
|
||||
uploader: string
|
||||
): Promise<Result> {
|
||||
const md5 = md5Buffer(buffer);
|
||||
const skin = await Skins.getSkinByMd5(md5);
|
||||
if (skin != null) {
|
||||
return { md5, status: "FOUND" };
|
||||
}
|
||||
const tempFile = temp.path({ suffix: ".wsz" });
|
||||
fs.writeFileSync(tempFile, buffer);
|
||||
const tempScreenshotPath = temp.path({ suffix: ".png" });
|
||||
|
||||
await Shooter.withShooter((shooter) =>
|
||||
shooter.takeScreenshot(tempFile, tempScreenshotPath, {
|
||||
minify: true,
|
||||
})
|
||||
);
|
||||
|
||||
const averageColor = await Analyser.getColor(tempScreenshotPath);
|
||||
await S3.putScreenshot(md5, fs.readFileSync(tempScreenshotPath));
|
||||
await S3.putSkin(md5, buffer);
|
||||
await Skins.addSkin({ md5, filePath, uploader, averageColor });
|
||||
return { md5, status: "ADDED", averageColor };
|
||||
}
|
||||
18
experiments/skin-database/analyser.ts
Normal file
18
experiments/skin-database/analyser.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Functions for deriving information from skins
|
||||
|
||||
import { exec } from "child_process";
|
||||
import shellescape from "shell-escape";
|
||||
|
||||
export function getColor(imgPath: string): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const excapedImgPath = shellescape([imgPath]);
|
||||
const command = `convert ${excapedImgPath} -scale 1x1\! -format '%[pixel:u]' info:-`;
|
||||
exec(command, (error, stdout) => {
|
||||
if (error !== null) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve(stdout.slice(1));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
const fs = require("fs");
|
||||
const fetch = require("node-fetch");
|
||||
const md5Buffer = require("md5");
|
||||
const Skins = require("../../data/skins");
|
||||
const Utils = require("../utils");
|
||||
const S3 = require("../../s3");
|
||||
const Shooter = require("../../shooter");
|
||||
const temp = require("temp").track();
|
||||
|
||||
async function handler(message) {
|
||||
const { attachments } = message;
|
||||
if (attachments.length < 1) {
|
||||
await message.channel.send("Could not archive. No attachment found.");
|
||||
return;
|
||||
}
|
||||
const files = await Promise.all(
|
||||
attachments.map(async (attachment) => {
|
||||
const { filename, url } = attachment;
|
||||
const response = await fetch(url);
|
||||
console.log("got response");
|
||||
const buffer = await response.buffer();
|
||||
console.log("got buffer");
|
||||
const md5 = md5Buffer(buffer);
|
||||
console.log("got md5", md5);
|
||||
return { filename, buffer, md5 };
|
||||
})
|
||||
);
|
||||
|
||||
// TODO
|
||||
// Extract the readme
|
||||
// Extract the emails
|
||||
// Extract the average color
|
||||
// Upload to Internet Archive
|
||||
// Store the Internet Archive item name
|
||||
// Construct IA Webamp URL
|
||||
const shooter = new Shooter("https://webamp.org");
|
||||
|
||||
try {
|
||||
for (const file of files) {
|
||||
const skin = await Skins.getSkinByMd5(file.md5);
|
||||
if (skin != null) {
|
||||
await message.channel.send(`This skin is already in our collection.`);
|
||||
await Utils.postSkin({
|
||||
md5: file.md5,
|
||||
dest: message.channel,
|
||||
});
|
||||
} else {
|
||||
await message.channel.send(
|
||||
`Thanks! ${file.filename} is a brand new skin. 👏 Uploading to our server and taking a screenshot...`
|
||||
);
|
||||
const tempFile = temp.path({ suffix: ".wsz" });
|
||||
fs.writeFileSync(tempFile, file.buffer);
|
||||
const tempScreenshotPath = temp.path({ suffix: ".png" });
|
||||
|
||||
try {
|
||||
await shooter.takeScreenshot(tempFile, tempScreenshotPath, {
|
||||
minify: true,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
await message.channel.send(
|
||||
`Something went wrong taking the screenshot of ${file.filename}. Sorry.`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
await S3.putScreenshot(file.md5, fs.readFileSync(tempScreenshotPath));
|
||||
await S3.putSkin(file.md5, file.buffer);
|
||||
await Skins.addSkin({
|
||||
md5: file.md5,
|
||||
filePath: file.filename,
|
||||
uploader: message.author.username,
|
||||
});
|
||||
await message.channel.send(
|
||||
`Done! ${file.filename} has been queued for archiving. In the mean time, here's a screenshot and a link to it on Webamp.`
|
||||
);
|
||||
await Utils.postSkin({
|
||||
md5: file.md5,
|
||||
dest: message.channel,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
message.channel.send(
|
||||
"There was an error archiving your skin. Please ping @captbaritone."
|
||||
);
|
||||
}
|
||||
shooter.dispose();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
command: "archive",
|
||||
usage: "",
|
||||
description:
|
||||
"Queues the accompanying uploaded skin for inclusion in the Archive",
|
||||
handler,
|
||||
};
|
||||
55
experiments/skin-database/discord-bot/commands/archive.ts
Normal file
55
experiments/skin-database/discord-bot/commands/archive.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import { Message } from "discord.js";
|
||||
import fetch from "node-fetch";
|
||||
import * as Utils from "../utils";
|
||||
import { addSkinFromBuffer } from "../../addSkin";
|
||||
|
||||
async function handler(message: Message) {
|
||||
const { attachments } = message;
|
||||
if (attachments.array().length < 1) {
|
||||
await message.channel.send("Could not archive. No attachment found.");
|
||||
return;
|
||||
}
|
||||
const files = await Promise.all(
|
||||
attachments.map(async (attachment) => {
|
||||
const { filename, url } = attachment;
|
||||
const response = await fetch(url);
|
||||
console.log("got response");
|
||||
const buffer = await response.buffer();
|
||||
console.log("got buffer");
|
||||
return { filename, buffer };
|
||||
})
|
||||
);
|
||||
|
||||
for (const file of files) {
|
||||
let result;
|
||||
try {
|
||||
result = await addSkinFromBuffer(
|
||||
file.buffer,
|
||||
file.filename,
|
||||
message.author.username
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
message.channel.send(
|
||||
"There was an error archiving your skin. Please ping @captbaritone."
|
||||
);
|
||||
throw e;
|
||||
}
|
||||
if (result.status === "FOUND") {
|
||||
await message.channel.send(`This skin is already in our collection.`);
|
||||
} else if (result.status === "ADDED") {
|
||||
await message.channel.send(
|
||||
`Thanks! ${file.filename} is a brand new skin. 👏 It has been queued for archiving. In the mean time, here's a screenshot and a link to it on Webamp.`
|
||||
);
|
||||
}
|
||||
await Utils.postSkin({ md5: result.md5, dest: message.channel });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
command: "archive",
|
||||
usage: "",
|
||||
description:
|
||||
"Queues the accompanying uploaded skin for inclusion in the Archive",
|
||||
handler,
|
||||
};
|
||||
|
|
@ -1,4 +1,11 @@
|
|||
import { RichEmbed, User, MessageReaction, Channel } from "discord.js";
|
||||
import {
|
||||
RichEmbed,
|
||||
User,
|
||||
MessageReaction,
|
||||
TextChannel,
|
||||
DMChannel,
|
||||
GroupDMChannel,
|
||||
} from "discord.js";
|
||||
import rgbHex from "rgb-hex";
|
||||
import * as Skins from "../data/skins";
|
||||
import logger from "../logger";
|
||||
|
|
@ -17,14 +24,14 @@ const filter = (reaction: MessageReaction): boolean => {
|
|||
);
|
||||
};
|
||||
|
||||
async function postSkin({
|
||||
export async function postSkin({
|
||||
md5,
|
||||
title: _title,
|
||||
dest,
|
||||
}: {
|
||||
md5: string;
|
||||
title: (filename: string | null) => string;
|
||||
dest: Channel;
|
||||
title?: (filename: string | null) => string;
|
||||
dest: TextChannel | DMChannel | GroupDMChannel;
|
||||
}) {
|
||||
const skin = await Skins.getSkinByMd5(md5);
|
||||
if (skin == null) {
|
||||
|
|
@ -141,5 +148,3 @@ function getPrettyTwitterStatus(status: TweetStatus): string {
|
|||
return "Tweeted 🐦";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { postSkin };
|
||||
|
|
|
|||
|
|
@ -15,6 +15,15 @@ class Shooter {
|
|||
this._url = url;
|
||||
}
|
||||
|
||||
static async withShooter(cb) {
|
||||
const shooter = new Shooter("https://webamp.org");
|
||||
try {
|
||||
await cb(shooter);
|
||||
} finally {
|
||||
shooter.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
async init() {
|
||||
this._browser = await puppeteer.launch();
|
||||
this._page = await this._browser.newPage();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue