mirror of
				https://git.sleeping.town/mirrors/foxy-moxy
				synced 2025-11-03 18:12:17 -08:00 
			
		
		
		
	Deprecate v1 urls, upgraded things
This commit is contained in:
		
							parent
							
								
									21a47e0c45
								
							
						
					
					
						commit
						a674d6a79c
					
				
					 5 changed files with 32 additions and 151 deletions
				
			
		| 
						 | 
					@ -1,118 +0,0 @@
 | 
				
			||||||
const Chance = require('chance')
 | 
					 | 
				
			||||||
const colors = require('./constants/colors.js')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const hsl = function (h, s, l) {
 | 
					 | 
				
			||||||
  return 'hsl(' + h + ',' + s + '%, ' + l + '%)'
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const Fox = function (IMG_WIDTH, IMG_HEIGHT, seed) {
 | 
					 | 
				
			||||||
  const chance = seed ? new Chance(seed) : new Chance()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // origin: head top left corner
 | 
					 | 
				
			||||||
  const kappa = chance.floating({min: 0.2, max: 0.45})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  chance.bool()
 | 
					 | 
				
			||||||
  chance.bool()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const headColor = (function () {
 | 
					 | 
				
			||||||
    const level = chance.floating({min: 0, max: 1})
 | 
					 | 
				
			||||||
    const result = []
 | 
					 | 
				
			||||||
    const min = colors.head.brick
 | 
					 | 
				
			||||||
    const max = colors.head.yellow
 | 
					 | 
				
			||||||
    for (let i = 0; i < min.length; i++) {
 | 
					 | 
				
			||||||
      result.push(min[i] + (max[i] - min[i]) * level)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return hsl.apply(null, result)
 | 
					 | 
				
			||||||
  })()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const head = {
 | 
					 | 
				
			||||||
    width: 0.6 * IMG_WIDTH,
 | 
					 | 
				
			||||||
    height: 0.6 * IMG_HEIGHT,
 | 
					 | 
				
			||||||
    kappa: kappa,
 | 
					 | 
				
			||||||
    color: headColor
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const origin = {x: IMG_WIDTH / 2 - head.width / 2, y: 0.5 * IMG_HEIGHT - head.height / 2}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const ears = (function (origin, headWidth, headHeight, headColor) {
 | 
					 | 
				
			||||||
    const offsetX = chance.floating({min: 0.17 * headWidth, max: 0.2 * headWidth})
 | 
					 | 
				
			||||||
    const angle = chance.floating({min: 0.05 * Math.PI, max: 0.2 * Math.PI})
 | 
					 | 
				
			||||||
    return {
 | 
					 | 
				
			||||||
      color: headColor,
 | 
					 | 
				
			||||||
      kappa: 0.9 * kappa,
 | 
					 | 
				
			||||||
      left: {
 | 
					 | 
				
			||||||
        x: origin.x + (headWidth / 2) - offsetX,
 | 
					 | 
				
			||||||
        y: origin.y + (0.15 * headHeight),
 | 
					 | 
				
			||||||
        angle: angle,
 | 
					 | 
				
			||||||
        width: 0.4 * headWidth,
 | 
					 | 
				
			||||||
        height: 0.8 * headHeight
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      right: {
 | 
					 | 
				
			||||||
        x: origin.x + (headWidth / 2) + offsetX,
 | 
					 | 
				
			||||||
        y: origin.y + (0.15 * headHeight),
 | 
					 | 
				
			||||||
        angle: -angle,
 | 
					 | 
				
			||||||
        width: 0.4 * headWidth,
 | 
					 | 
				
			||||||
        height: 0.8 * headHeight
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }(origin, head.width, head.height, head.color))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const eyes = (function (origin, headWidth, headHeight) {
 | 
					 | 
				
			||||||
    // TODO: color
 | 
					 | 
				
			||||||
    const offsetY = chance.floating({min: -0.05 * headHeight, max: -0.025 * headHeight})
 | 
					 | 
				
			||||||
    const offsetX = chance.floating({min: 0.13 * headWidth, max: 0.25 * headWidth})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const eyeHeight = chance.floating({min: 0.08 * headHeight, max: 0.13 * headHeight})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return {
 | 
					 | 
				
			||||||
      height: eyeHeight,
 | 
					 | 
				
			||||||
      width: eyeHeight / 2,
 | 
					 | 
				
			||||||
      style: 'ellipse',
 | 
					 | 
				
			||||||
      // style: chance.pickone(['ellipse', 'smiley']),
 | 
					 | 
				
			||||||
      left: {
 | 
					 | 
				
			||||||
        x: origin.x + (headWidth / 2) - offsetX,
 | 
					 | 
				
			||||||
        y: origin.y + (headHeight / 2) + offsetY
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      right: {
 | 
					 | 
				
			||||||
        x: origin.x + (headWidth / 2) + offsetX,
 | 
					 | 
				
			||||||
        y: origin.y + (headHeight / 2) + offsetY
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }(origin, head.width, head.height))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const nose = {
 | 
					 | 
				
			||||||
    x: origin.x + (head.width / 2),
 | 
					 | 
				
			||||||
    y: (eyes.left.y + chance.floating({min: 0.2, max: 0.4}) * (origin.y + head.height - eyes.left.y)),
 | 
					 | 
				
			||||||
    width: chance.floating({min: 0.03, max: 0.04}) * head.width,
 | 
					 | 
				
			||||||
    height: chance.floating({min: 0.03, max: 0.04}) * head.width
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const mouth = {
 | 
					 | 
				
			||||||
    x: origin.x + (head.width / 2),
 | 
					 | 
				
			||||||
    y: (nose.y + chance.floating({min: 0.2, max: 0.35}) * (origin.y + head.height - nose.y)),
 | 
					 | 
				
			||||||
    width: chance.floating({min: 0.08, max: 0.15}) * head.width,
 | 
					 | 
				
			||||||
    height: chance.floating({min: 0.03, max: 0.06}) * head.width,
 | 
					 | 
				
			||||||
    style: chance.pickone(['smirk', 'cat', 'none'])
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const mask = {
 | 
					 | 
				
			||||||
    width: chance.floating({min: 0.5 * IMG_WIDTH, max: IMG_WIDTH}),
 | 
					 | 
				
			||||||
    height: chance.floating({min: 1.7 * (IMG_HEIGHT - eyes.left.y), max: 1.85 * (IMG_HEIGHT - eyes.left.y)})
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  head.mask = mask
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return {
 | 
					 | 
				
			||||||
    canvas: {
 | 
					 | 
				
			||||||
      height: IMG_HEIGHT,
 | 
					 | 
				
			||||||
      width: IMG_WIDTH,
 | 
					 | 
				
			||||||
      color: chance.pickone(Object.keys(colors.bg).map(function (key) { return colors.bg[key] }))
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    head: head,
 | 
					 | 
				
			||||||
    ears: ears,
 | 
					 | 
				
			||||||
    eyes: eyes,
 | 
					 | 
				
			||||||
    nose: nose,
 | 
					 | 
				
			||||||
    mouth: mouth
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = Fox
 | 
					 | 
				
			||||||
							
								
								
									
										25
									
								
								js/fox.js
									
										
									
									
									
								
							
							
						
						
									
										25
									
								
								js/fox.js
									
										
									
									
									
								
							| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
const Chance = require('chance')
 | 
					const Chance = require('chance')
 | 
				
			||||||
 | 
					const colors = require('./constants/colors.js')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const hsl = function (h, s, l) {
 | 
					const hsl = function (h, s, l) {
 | 
				
			||||||
  return 'hsl(' + h + ',' + s + '%, ' + l + '%)'
 | 
					  return 'hsl(' + h + ',' + s + '%, ' + l + '%)'
 | 
				
			||||||
| 
						 | 
					@ -10,15 +11,25 @@ const Fox = function (IMG_WIDTH, IMG_HEIGHT, seed) {
 | 
				
			||||||
  // origin: head top left corner
 | 
					  // origin: head top left corner
 | 
				
			||||||
  const kappa = chance.floating({min: 0.2, max: 0.45})
 | 
					  const kappa = chance.floating({min: 0.2, max: 0.45})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const hue = chance.integer({min: 5, max: 50})
 | 
					  chance.bool()
 | 
				
			||||||
  const saturation = chance.integer({min: 70, max: 90})
 | 
					  chance.bool()
 | 
				
			||||||
  const lightness = chance.integer({min: 40, max: 60})
 | 
					
 | 
				
			||||||
 | 
					  const headColor = (function () {
 | 
				
			||||||
 | 
					    const level = chance.floating({min: 0, max: 1})
 | 
				
			||||||
 | 
					    const result = []
 | 
				
			||||||
 | 
					    const min = colors.head.brick
 | 
				
			||||||
 | 
					    const max = colors.head.yellow
 | 
				
			||||||
 | 
					    for (let i = 0; i < min.length; i++) {
 | 
				
			||||||
 | 
					      result.push(min[i] + (max[i] - min[i]) * level)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return hsl.apply(null, result)
 | 
				
			||||||
 | 
					  })()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const head = {
 | 
					  const head = {
 | 
				
			||||||
    width: 0.6 * IMG_WIDTH,
 | 
					    width: 0.6 * IMG_WIDTH,
 | 
				
			||||||
    height: 0.6 * IMG_HEIGHT,
 | 
					    height: 0.6 * IMG_HEIGHT,
 | 
				
			||||||
    kappa: kappa,
 | 
					    kappa: kappa,
 | 
				
			||||||
    color: hsl(hue, saturation, lightness)
 | 
					    color: headColor
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const origin = {x: IMG_WIDTH / 2 - head.width / 2, y: 0.5 * IMG_HEIGHT - head.height / 2}
 | 
					  const origin = {x: IMG_WIDTH / 2 - head.width / 2, y: 0.5 * IMG_HEIGHT - head.height / 2}
 | 
				
			||||||
| 
						 | 
					@ -94,11 +105,7 @@ const Fox = function (IMG_WIDTH, IMG_HEIGHT, seed) {
 | 
				
			||||||
    canvas: {
 | 
					    canvas: {
 | 
				
			||||||
      height: IMG_HEIGHT,
 | 
					      height: IMG_HEIGHT,
 | 
				
			||||||
      width: IMG_WIDTH,
 | 
					      width: IMG_WIDTH,
 | 
				
			||||||
      color: hsl(
 | 
					      color: chance.pickone(Object.keys(colors.bg).map(function (key) { return colors.bg[key] }))
 | 
				
			||||||
        chance.integer({min: 0, max: 360}),
 | 
					 | 
				
			||||||
        chance.integer({min: 0, max: 100}),
 | 
					 | 
				
			||||||
        chance.integer({min: 10, max: 100})
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    head: head,
 | 
					    head: head,
 | 
				
			||||||
    ears: ears,
 | 
					    ears: ears,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,9 @@
 | 
				
			||||||
const renderFox = function (canvas, opts) {
 | 
					const renderFox = function (canvas, opts) {
 | 
				
			||||||
  const width = opts.canvas.width
 | 
					  const width = opts.canvas.width
 | 
				
			||||||
  const height = opts.canvas.height
 | 
					  const height = opts.canvas.height
 | 
				
			||||||
  const ctx = canvas.getContext('2d')
 | 
					  const ctx = canvas.getContext('2d', {
 | 
				
			||||||
 | 
					    pixelFormat: 'RGB16_565',
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ctx.fillStyle = opts.canvas.color
 | 
					  ctx.fillStyle = opts.canvas.color
 | 
				
			||||||
  ctx.fillRect(0, 0, width, height)
 | 
					  ctx.fillRect(0, 0, width, height)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								package.json
									
										
									
									
									
								
							| 
						 | 
					@ -18,18 +18,18 @@
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "homepage": "https://github.com/Patreon/foxy-moxy#readme",
 | 
					  "homepage": "https://github.com/Patreon/foxy-moxy#readme",
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "canvas": "^1.6.2",
 | 
					    "canvas": "^2.0.1",
 | 
				
			||||||
    "chance": "^1.0.4",
 | 
					    "chance": "^1.0.16",
 | 
				
			||||||
    "connect-datadog": "*",
 | 
					    "connect-datadog": "*",
 | 
				
			||||||
    "express": "^4.14.0",
 | 
					    "express": "^4.16.4",
 | 
				
			||||||
    "express-cluster": "0.0.4",
 | 
					    "express-cluster": "0.0.4",
 | 
				
			||||||
    "node-gyp": "^3.4.0",
 | 
					    "node-gyp": "^3.8.0",
 | 
				
			||||||
    "sanitize-filename": "^1.6.1",
 | 
					    "sanitize-filename": "^1.6.1",
 | 
				
			||||||
    "uuid": "^3.0.1"
 | 
					    "uuid": "^3.3.2"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "mocha": "^3.4.2",
 | 
					    "mocha": "^5.2.0",
 | 
				
			||||||
    "sharp": "^0.18.1",
 | 
					    "sharp": "^0.18.4",
 | 
				
			||||||
    "supertest": "^3.0.0"
 | 
					    "supertest": "^3.3.0"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								server.js
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								server.js
									
										
									
									
									
								
							| 
						 | 
					@ -5,22 +5,12 @@ const sanitize = require('sanitize-filename')
 | 
				
			||||||
const Canvas = require('canvas')
 | 
					const Canvas = require('canvas')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Fox = require('./js/fox.js')
 | 
					const Fox = require('./js/fox.js')
 | 
				
			||||||
const FoxAmerica = require('./js/fox-america.js')
 | 
					 | 
				
			||||||
const renderFox = require('./js/render-fox.js')
 | 
					const renderFox = require('./js/render-fox.js')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function composeImage (width, height, seed, version) {
 | 
					function composeImage (width, height, seed, version) {
 | 
				
			||||||
  seed = seed || uuid()
 | 
					  seed = seed || uuid()
 | 
				
			||||||
  let fox
 | 
					  const fox = Fox(width, height, seed)
 | 
				
			||||||
  switch (version) {
 | 
					  const canvas = Canvas.createCanvas(width, height)
 | 
				
			||||||
    case 2:
 | 
					 | 
				
			||||||
      // America-color bg and fox
 | 
					 | 
				
			||||||
      fox = FoxAmerica(width, height, seed)
 | 
					 | 
				
			||||||
      break
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
      // original fox
 | 
					 | 
				
			||||||
      fox = Fox(width, height, seed)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  const canvas = new Canvas(width, height)
 | 
					 | 
				
			||||||
  renderFox(canvas, fox)
 | 
					  renderFox(canvas, fox)
 | 
				
			||||||
  return canvas
 | 
					  return canvas
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -30,7 +20,7 @@ function getFox (req, res, version) {
 | 
				
			||||||
  if (width > 400) width = 400
 | 
					  if (width > 400) width = 400
 | 
				
			||||||
  const seed = sanitize(req.params.seed) || uuid()
 | 
					  const seed = sanitize(req.params.seed) || uuid()
 | 
				
			||||||
  const canvas = composeImage(width, width, seed, version)
 | 
					  const canvas = composeImage(width, width, seed, version)
 | 
				
			||||||
  const buffer = canvas.toBuffer()
 | 
					  const buffer = canvas.toBuffer('image/png')
 | 
				
			||||||
  res.set('Cache-Control', 'max-age=' + cacheTimeout)
 | 
					  res.set('Cache-Control', 'max-age=' + cacheTimeout)
 | 
				
			||||||
  res.set('Content-length', buffer.length)
 | 
					  res.set('Content-length', buffer.length)
 | 
				
			||||||
  res.type('png')
 | 
					  res.type('png')
 | 
				
			||||||
| 
						 | 
					@ -46,11 +36,11 @@ app.get('/healthcheck', (req, res) => {
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.get('/:width/:seed', (req, res) => {
 | 
					app.get('/:width/:seed', (req, res) => {
 | 
				
			||||||
  getFox(req, res, 1)
 | 
					  getFox(req, res)
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.get('/2/:width/:seed', (req, res) => {
 | 
					app.get('/2/:width/:seed', (req, res) => {
 | 
				
			||||||
  getFox(req, res, 2)
 | 
					  getFox(req, res)
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = app
 | 
					module.exports = app
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue