text: const AWS = require("aws-sdk");
  AWS.config.update({ region: "us-west-2" });
  
  const s3 = new AWS.S3();
  
  function getFile(key) {
    return new Promise((resolve, reject) => {
      const bucketName = "winamp2-js-skins";
      s3.getObject({ Bucket: bucketName, Key: key }, (err, data) => {
        if (err) {
          reject(err);
          return;
        }
        const body = Buffer.from(data.Body).toString("utf8");
        resolve(body);
      });
    });
  }
  
  function putFile(key, body) {
    return new Promise((resolve, reject) => {
      const bucketName = "winamp2-js-skins";
      s3.putObject({ Bucket: bucketName, Key: key, Body: body }, err => {
        if (err) {
          reject(err);
          return;
        }
        resolve();
      });
    });
  }
  
  function getLines(body) {
    return body.split("\n").map(line => line.trim());
  }
  
  async function getStatus(md5) {
    const [approved, rejected, tweeted] = await Promise.all([
      getFile("approved.txt"),
      getFile("rejected.txt"),
      getFile("tweeted.txt")
    ]);
    const approvedSet = new Set(getLines(approved));
    const rejectedSet = new Set(getLines(rejected));
    const tweetedSet = new Set(getLines(tweeted));
    if (tweetedSet.has(md5)) {
      return "TWEETED";
    }
    if (rejectedSet.has(md5)) {
      return "REJECTED";
    }
    if (approvedSet.has(md5)) {
      return "APPROVED";
    }
    return "UNREVIEWED";
  }
  
  async function getStats() {
    const [approved, rejected, tweeted] = await Promise.all([
      getFile("approved.txt"),
      getFile("rejected.txt"),
      getFile("tweeted.txt")
    ]);
    return {
      approved: new Set(approved).size - new Set(tweeted).size,
      rejected: new Set(rejected).size,
      tweeted: new Set(tweeted).size
    };
  }
  
  async function getSkinToReview() {
    const [filenames, approved, rejected, tweeted] = await Promise.all([
      getFile("filenames.txt"),
      getFile("approved.txt"),
      getFile("rejected.txt"),
      getFile("tweeted.txt")
    ]);
  
    const approvedSet = new Set(getLines(approved));
    const rejectedSet = new Set(getLines(rejected));
    const tweetedSet = new Set(getLines(tweeted));
  
    const filenameLines = getLines(filenames);
    const skins = filenameLines.map(line => {
      const [md5, ...filename] = line.split(" ");
      return { md5, filename: filename.join(" ") };
    });
    const toReview = skins.filter(({ md5 }) => {
      return !(
        approvedSet.has(md5) ||
        rejectedSet.has(md5) ||
        tweetedSet.has(md5)
      );
    });
    return toReview[0];
  }
  
  async function appendLine(key, line) {
    const currentContent = await getFile(key);
    const newContent = `${currentContent}${line}\n`;
    return putFile(key, newContent);
  }
  
  async function approve(md5) {
    return appendLine("approved.txt", md5);
  }
  
  async function reject(md5) {
    return appendLine("rejected.txt", md5);
  }
  
  module.exports = { getSkinToReview, approve, reject, getStatus, getStats };
  