mirror of
https://github.com/A-Minos/nonebot-plugin-tetris-stats.git
synced 2026-03-05 05:36:54 +08:00
* 🚧 查数据图初版测试 Co-authored-by: C1ystal <m17687496044@163.com> Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com> * 🙈 添加一些 ignore 文件 * 🎨 格式化代码 * 🐛 修复格式化导致的样式爆炸 * 💄 优化曲线图观感 * 💄 将雷达图的指示器名称旋转显示 * 💄 查数据图第二版 Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com> * ✏️ 修复 typo * 💄 把用户头像文件的引用放到 html 里 * 💄 账户绑定图第一版 Co-authored-by: C1ystal <m17687496044@163.com> Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com> * 🚧 模板化测试 * ➕ 添加依赖 fastapi * ✨ 通过 FastAPI 提供静态文件 * ➕ 添加依赖 jinja2 * 💄 更新数据图模板 (#291) * feat(template): show actual value * feat(template): add user avatar * feat(template): fix radar * feat(style): fix name container width fixed caused display misplacement * feat(style): fix vs value wrap display * feat(template): make check data length in template * feat(template): update radar data * feat(jinja): update data * fix(template): fix typo * feat(style): prevent sign too long * feat(template): turn off echarts animation * chore(deps): add identicon.js * fix(template): fix typo * 🙈 更新.gitignore * 🏗️ 大部分重构为 flex 布局 --------- Co-authored-by: shoucandanghehe <wallfjjd@gmail.com> Co-authored-by: 呵呵です <51957264+shoucandanghehe@users.noreply.github.com> * ➕ 添加依赖 nonebot_plugin_userinfo * ✨ 通过 FastAPI 托管渲染后的模板 * ✨ 新增头像 api 使用 playwright 生成 * ✨ 修正模板资源文件引用路径 被托管后的正确路径 * 💄 将绑定图模板化 * 💄 重命名变量 * 🚚 重命名资源 * ✨ 使用 jinja2 渲染模板 * ✨ 使用 playwright 渲染网页 * 🩹 渲染模板时对 IO 进行一些额外处理 * ➕ 添加依赖 pillow * 🚚 修改托管页面的路由路径 * 💬 优化绑定图文案 * ✨ 新增获取自身网络位置的方法 * 🍱 更新 unknown.svg * ✨ 新增获取用户头像的方法 * ✨ 绑定消息使用图片回复 * ✨ 为 identicon api 添加缓存 * 🔥 删除旧文件 * 🚚 重命名模板 * 📄 添加字体 License * 🙈 更新.gitignore --------- Co-authored-by: C1ystal <m17687496044@163.com> Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com> Co-authored-by: 渣渣120 <WOSHIZHAZHA120@qq.com>
206 lines
7.1 KiB
JavaScript
206 lines
7.1 KiB
JavaScript
/**
|
|
* Identicon.js 2.3.3
|
|
* http://github.com/stewartlord/identicon.js
|
|
*
|
|
* PNGLib required for PNG output
|
|
* http://www.xarg.org/download/pnglib.js
|
|
*
|
|
* Copyright 2018, Stewart Lord
|
|
* Released under the BSD license
|
|
* http://www.opensource.org/licenses/bsd-license.php
|
|
*/
|
|
|
|
(function() {
|
|
var PNGlib;
|
|
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
|
PNGlib = require('./pnglib');
|
|
} else {
|
|
PNGlib = window.PNGlib;
|
|
}
|
|
|
|
var Identicon = function(hash, options){
|
|
if (typeof(hash) !== 'string' || hash.length < 15) {
|
|
throw 'A hash of at least 15 characters is required.';
|
|
}
|
|
|
|
this.defaults = {
|
|
background: [240, 240, 240, 255],
|
|
margin: 0.08,
|
|
size: 64,
|
|
saturation: 0.7,
|
|
brightness: 0.5,
|
|
format: 'png'
|
|
};
|
|
|
|
this.options = typeof(options) === 'object' ? options : this.defaults;
|
|
|
|
// backward compatibility with old constructor (hash, size, margin)
|
|
if (typeof(arguments[1]) === 'number') { this.options.size = arguments[1]; }
|
|
if (arguments[2]) { this.options.margin = arguments[2]; }
|
|
|
|
this.hash = hash
|
|
this.background = this.options.background || this.defaults.background;
|
|
this.size = this.options.size || this.defaults.size;
|
|
this.format = this.options.format || this.defaults.format;
|
|
this.margin = this.options.margin !== undefined ? this.options.margin : this.defaults.margin;
|
|
|
|
// foreground defaults to last 7 chars as hue at 70% saturation, 50% brightness
|
|
var hue = parseInt(this.hash.substr(-7), 16) / 0xfffffff;
|
|
var saturation = this.options.saturation || this.defaults.saturation;
|
|
var brightness = this.options.brightness || this.defaults.brightness;
|
|
this.foreground = this.options.foreground || this.hsl2rgb(hue, saturation, brightness);
|
|
};
|
|
|
|
Identicon.prototype = {
|
|
background: null,
|
|
foreground: null,
|
|
hash: null,
|
|
margin: null,
|
|
size: null,
|
|
format: null,
|
|
|
|
image: function(){
|
|
return this.isSvg()
|
|
? new Svg(this.size, this.foreground, this.background)
|
|
: new PNGlib(this.size, this.size, 256);
|
|
},
|
|
|
|
render: function(){
|
|
var image = this.image(),
|
|
size = this.size,
|
|
baseMargin = Math.floor(size * this.margin),
|
|
cell = Math.floor((size - (baseMargin * 2)) / 5),
|
|
margin = Math.floor((size - cell * 5) / 2),
|
|
bg = image.color.apply(image, this.background),
|
|
fg = image.color.apply(image, this.foreground);
|
|
|
|
// the first 15 characters of the hash control the pixels (even/odd)
|
|
// they are drawn down the middle first, then mirrored outwards
|
|
var i, color;
|
|
for (i = 0; i < 15; i++) {
|
|
color = parseInt(this.hash.charAt(i), 16) % 2 ? bg : fg;
|
|
if (i < 5) {
|
|
this.rectangle(2 * cell + margin, i * cell + margin, cell, cell, color, image);
|
|
} else if (i < 10) {
|
|
this.rectangle(1 * cell + margin, (i - 5) * cell + margin, cell, cell, color, image);
|
|
this.rectangle(3 * cell + margin, (i - 5) * cell + margin, cell, cell, color, image);
|
|
} else if (i < 15) {
|
|
this.rectangle(0 * cell + margin, (i - 10) * cell + margin, cell, cell, color, image);
|
|
this.rectangle(4 * cell + margin, (i - 10) * cell + margin, cell, cell, color, image);
|
|
}
|
|
}
|
|
|
|
return image;
|
|
},
|
|
|
|
rectangle: function(x, y, w, h, color, image){
|
|
if (this.isSvg()) {
|
|
image.rectangles.push({x: x, y: y, w: w, h: h, color: color});
|
|
} else {
|
|
var i, j;
|
|
for (i = x; i < x + w; i++) {
|
|
for (j = y; j < y + h; j++) {
|
|
image.buffer[image.index(i, j)] = color;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
// adapted from: https://gist.github.com/aemkei/1325937
|
|
hsl2rgb: function(h, s, b){
|
|
h *= 6;
|
|
s = [
|
|
b += s *= b < .5 ? b : 1 - b,
|
|
b - h % 1 * s * 2,
|
|
b -= s *= 2,
|
|
b,
|
|
b + h % 1 * s,
|
|
b + s
|
|
];
|
|
|
|
return[
|
|
s[ ~~h % 6 ] * 255, // red
|
|
s[ (h|16) % 6 ] * 255, // green
|
|
s[ (h|8) % 6 ] * 255 // blue
|
|
];
|
|
},
|
|
|
|
toString: function(raw){
|
|
// backward compatibility with old toString, default to base64
|
|
if (raw) {
|
|
return this.render().getDump();
|
|
} else {
|
|
return this.render().getBase64();
|
|
}
|
|
},
|
|
|
|
isSvg: function(){
|
|
return this.format.match(/svg/i)
|
|
}
|
|
};
|
|
|
|
var Svg = function(size, foreground, background){
|
|
this.size = size;
|
|
this.foreground = this.color.apply(this, foreground);
|
|
this.background = this.color.apply(this, background);
|
|
this.rectangles = [];
|
|
};
|
|
|
|
Svg.prototype = {
|
|
size: null,
|
|
foreground: null,
|
|
background: null,
|
|
rectangles: null,
|
|
|
|
color: function(r, g, b, a){
|
|
var values = [r, g, b].map(Math.round);
|
|
values.push((a >= 0) && (a <= 255) ? a/255 : 1);
|
|
return 'rgba(' + values.join(',') + ')';
|
|
},
|
|
|
|
getDump: function(){
|
|
var i,
|
|
xml,
|
|
rect,
|
|
fg = this.foreground,
|
|
bg = this.background,
|
|
stroke = this.size * 0.005;
|
|
|
|
xml = "<svg xmlns='http://www.w3.org/2000/svg'"
|
|
+ " width='" + this.size + "' height='" + this.size + "'"
|
|
+ " style='background-color:" + bg + ";'>"
|
|
+ "<g style='fill:" + fg + "; stroke:" + fg + "; stroke-width:" + stroke + ";'>";
|
|
|
|
for (i = 0; i < this.rectangles.length; i++) {
|
|
rect = this.rectangles[i];
|
|
if (rect.color == bg) continue;
|
|
xml += "<rect "
|
|
+ " x='" + rect.x + "'"
|
|
+ " y='" + rect.y + "'"
|
|
+ " width='" + rect.w + "'"
|
|
+ " height='" + rect.h + "'"
|
|
+ "/>";
|
|
}
|
|
xml += "</g></svg>"
|
|
|
|
return xml;
|
|
},
|
|
|
|
getBase64: function(){
|
|
if ('function' === typeof btoa) {
|
|
return btoa(this.getDump());
|
|
} else if (Buffer) {
|
|
return new Buffer(this.getDump(), 'binary').toString('base64');
|
|
} else {
|
|
throw 'Cannot generate base64 output';
|
|
}
|
|
}
|
|
};
|
|
|
|
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
|
module.exports = Identicon;
|
|
} else {
|
|
window.Identicon = Identicon;
|
|
}
|
|
})();
|