run(msg, args) { const member = args.member.displayName || 'yourself'; Canvas.registerFont(path.join(__dirname, '..', '..', 'Assets', 'fonts', 'Roboto.ttf'), { family: 'Roboto' }); // eslint-disable-line max-len Canvas.registerFont(path.join(__dirname, '..', '..', 'Assets', 'fonts', 'NotoEmoji-Regular.ttf'), { family: 'Roboto' }); // eslint-disable-line max-len const canvas = Canvas.createCanvas(); const ctx = canvas.getContext('2d'); const { width, height } = this._textSizes(ctx, member); canvas.width = width < 130 ? 130 : width; canvas.height = height; const generate = () => { ctx.font = '700 32px Arial'; ctx.fillStyle = '#B93F2C'; ctx.textAlign = 'center'; ctx.fillText('Blame', canvas.width / 2, 35); ctx.fillStyle = '#F01111'; ctx.fillText(member, canvas.width / 2, 70); }; generate(); return msg.channel.send({ files: [{ attachment: canvas.toBuffer(), name: 'blame.png' }] }); }
fonts.forEach((font) => { if (!fs.statSync(font.src).isFile()) { notFound.push(font); return; } Canvas.registerFont(font.src, { family: font.name }); });
constructor(options) { Object.assign(this, options) this.imageWidth = 640 this.imageHeight = 384 this.width = this.orientation === 'landscape' ? this.imageWidth : this.imageHeight this.height = this.orientation === 'landscape' ? this.imageHeight : this.imageWidth this.bg = '#000000' this.fg = '#FFFFFF' this.font = 'SourceCodePro-Regular' registerFont(path.join(__dirname, '../../', 'assets/fonts/Source_Code_Pro/SourceCodePro-Regular.ttf'), {family: 'SourceCodePro-Regular'}) this.canvas = createCanvas(this.width, this.height) this.imageCanvas = createCanvas(this.imageWidth, this.imageHeight) this.ctx = this.canvas.getContext('2d') this.imgCtx = this.imageCanvas.getContext('2d') //this.ctx.antialias = 'none' this.ctx.imageSmoothingEnabled = false this.imgCtx.imageSmoothingEnabled = false this.sctx = shapely(this.ctx) }
const Canvas = require('canvas'); const Color = require('color'); const isHex = color => { const regex = /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/; const colorText = /#/.test(color) ? color : `#${color}`; return regex.test(colorText); }; function getFontFile(name) { return path.resolve(__dirname, '../assets/', name); } Canvas.registerFont(getFontFile('Asap-Bold.ttf'), { family: 'Asap', weight: 'bold', }); module.exports.drawImage = (req, res) => { const palette = req.params.palette.replace('.png', ''); if (!palette === -1) { res.status(404); return res.end('Error'); } const formattedPalette = palette.split('-').filter(color => isHex(color)); if (formattedPalette.length === 0) { res.status(404); return res.end('Error');
async run(message, channel, user, args) { const metric = args.indexOf("-f") > -1; let geolocation; // Remove -f identifier if (metric) { const pos = args.indexOf("-f"); args.splice(pos, 1); } // No Args Supplied if (args.length === 0 && message.pung.length === 0) { const userDB = await Database.Models.Users.findOne({ where: { id: user.id } }); const error = `Please provide a query, or set your location with \`${message.prefix}set location <location>\``; // Check if User exists in DB if (userDB) { const data = JSON.parse(userDB.data); // Checks if User has a set location if (data.weather || data.location) { geolocation = data.weather || data.location; if (typeof geolocation === "string") return this.error(geolocation, channel); if (Array.isArray(geolocation)) { geolocation = { line1: geolocation[0].long_name, line2: geolocation[1].long_name || "", geocode: geolocation[2] }; } this.log(`Using Cached Geolocation (${geolocation.line1}, ${geolocation.line2})`, "debug"); } else { return message.reply(error); } } else { return message.reply(error); } } // If Pinged User if (message.pung.length > 0) { this.log(`Getting Weather for user ${message.pung[0].id}`, "debug"); const userDB = await Database.Models.Users.findOne({ where: { id: message.pung[0].id } }); // Check if User exists in DB if (userDB) { const data = JSON.parse(userDB.data); // Checks if User has a set location if (data.weather || data.location) { geolocation = data.weather || data.location; if (typeof geolocation === "string") return this.error(geolocation, channel); if (Array.isArray(geolocation)) { geolocation = { line1: geolocation[0].long_name, line2: geolocation[1].long_name || "", geocode: geolocation[2] }; } this.log(`Using Cached Geolocation (${geolocation.line1}, ${geolocation.line2})`, "debug"); } else { return message.reply("this user has not set their location."); } } else { return message.reply("this user does not have a database entry for their location."); } } // Ignore geolocation request if User has set a location if (!geolocation) { geolocation = await this.fetchGeolocation(args); if (typeof geolocation === "string") return this.error(geolocation, channel); if (Array.isArray(geolocation)) { geolocation = { line1: geolocation[0].long_name, line2: geolocation[1].long_name, geocode: geolocation[2] }; } } // console.log(geolocation); // Get Weather const weather = await request({ headers: { "User-Agent": "Mozilla/5.0" }, uri: `https://api.darksky.net/forecast/${this.keychain.darksky}/${geolocation.geocode.join(",")}`, json: true, qs: { units: metric ? "us" : "si", excludes: "minutely,hourly,alerts" } }).catch(error => this.error(error.response.body.error, channel)); // console.log(weather); if (!weather) return false; const locale = weather.flags.units === "us" ? "F" : "C"; const condition = weather.currently.summary; const icon = weather.currently.icon; const temperature = Math.round(weather.currently.temperature); const datetime = moment().tz(weather.timezone).format("h:mm A"); const forecast = weather.daily.data; this.log(`${geolocation.line1}, ${geolocation.line2}: ${temperature}°${locale}, ${condition}, ${datetime}`, "debug"); Canvas.registerFont(path.join(__dirname, "fonts", "Inter-UI-Medium.ttf"), { family: "InterUI" }); // Generate Response Image const canvas = Canvas.createCanvas(800, 430); const ctx = canvas.getContext("2d"); const { Image } = Canvas; const base = new Image(); const cond = new Image(); const day1 = new Image(); const day2 = new Image(); const high = new Image(); const low = new Image(); base.src = path.join(__dirname, "base", `${this.getBaseImage(icon)}.png`); cond.src = path.join(__dirname, "icons", `${this.getConditionImage(icon)}.png`); day1.src = path.join(__dirname, "icons", `${this.getConditionImage(forecast[1].icon)}.png`); day2.src = path.join(__dirname, "icons", `${this.getConditionImage(forecast[2].icon)}.png`); high.src = path.join(__dirname, "icons", "high.png"); low.src = path.join(__dirname, "icons", "low.png"); // Environment Variables ctx.drawImage(base, 0, 0); ctx.scale(1, 1); ctx.patternQuality = "bilinear"; ctx.filter = "bilinear"; ctx.antialias = "subpixel"; // Town/City/District ctx.font = "40px InterUI"; ctx.fillStyle = "rgba(255, 255, 255, 1)"; ctx.fillText(geolocation.line1, 60, 70); // State/Region/Country ctx.font = "28px InterUI"; ctx.fillStyle = "rgba(255, 255, 255, 0.75)"; ctx.fillText(geolocation.line2, 60, 115); // Condition ctx.drawImage(cond, 643, 30); // Temperature ctx.font = "56px InterUI"; ctx.fillStyle = "rgba(255, 255, 255, 1)"; ctx.fillText(`${temperature}°${locale}`, 60, 240); // Daily Forecast const width = 200 + (temperature.toString().length - 1) * 28; // eslint-disable-line no-mixed-operators ctx.font = "28px InterUI"; ctx.fillStyle = "rgba(255, 255, 255, 1)"; ctx.fillText(`${Math.round(forecast[0].temperatureMax)}°`, width + 40, 210); ctx.drawImage(high, width, 188); ctx.fillStyle = "rgba(255, 255, 255, 0.75)"; ctx.fillText(`${Math.round(forecast[0].temperatureMin)}°`, width + 40, 247); ctx.drawImage(low, width, 226); // Time ctx.textAlign = "right"; ctx.font = "32px InterUI"; ctx.fillStyle = "rgba(255, 255, 255, 0.9)"; ctx.fillText(datetime, 740, 231); // Details ctx.textAlign = "left"; ctx.font = "28px InterUI"; ctx.fillStyle = "rgba(255, 255, 255, 1)"; ctx.fillText(`${Math.round(weather.currently.humidity * 100)}%`, 112, 341); ctx.fillText(`${Math.round(weather.currently.precipProbability * 100)}%`, 112, 391); // Forecast ctx.textAlign = "right"; ctx.font = "28px InterUI"; ctx.fillStyle = "rgba(255, 255, 255, 1)"; // tomorrow ctx.fillText("Tomorrow", 530, 341); ctx.fillStyle = "rgba(255, 255, 255, 0.75)"; ctx.fillText(`${Math.round(forecast[1].temperatureMin)}°`, 530, 391); ctx.fillStyle = "rgba(255, 255, 255, 1)"; ctx.fillText(`${Math.round(forecast[1].temperatureMax)}°`, 465, 391); ctx.drawImage(day1, 360, 364, 36, 36); // day after ctx.fillText(moment.unix(forecast[2].time).format("dddd"), 740, 341); ctx.fillStyle = "rgba(255, 255, 255, 0.75)"; ctx.fillText(`${Math.round(forecast[2].temperatureMin)}°`, 740, 391); ctx.fillStyle = "rgba(255, 255, 255, 1)"; ctx.fillText(`${Math.round(forecast[2].temperatureMax)}°`, 675, 391); ctx.drawImage(day2, 570, 364, 36, 36); // Send /* const etho = require("os").networkInterfaces().eth0; if (!etho || !etho[0] || etho[0].mac !== this.config.server) { const { RichEmbed } = require("discord.js"); const embed = new RichEmbed() .setColor(this.config.colours.warn) .setTitle("Notice") .setDescription("This command is currently under active redevelopment. As such, you may experience unexpected results when running this command. Feel free to ping me (Kurisu#7700) if you have any questions."); channel.send({ embed }); } */ await channel.send({ files: [{ attachment: canvas.toBuffer(), url: "weather.png" }] }); return this.delete(message); }
async run(msg, args) { const { location } = args; const Image = Canvas.Image; Canvas.registerFont(path.join(__dirname, '..', '..', 'assets', 'weather', 'fonts', 'Roboto-Regular.ttf'), { family: 'Roboto' }); // eslint-disable-line max-len Canvas.registerFont(path.join(__dirname, '..', '..', 'assets', 'weather', 'fonts', 'RobotoCondensed-Regular.ttf'), { family: 'Roboto Condensed' }); // eslint-disable-line max-len Canvas.registerFont(path.join(__dirname, '..', '..', 'assets', 'weather', 'fonts', 'RobotoMono-Light.ttf'), { family: 'Roboto Mono' }); // eslint-disable-line max-len if (!GOOGLE_API) return msg.reply('my Commander has not set the Google API Key. Go yell at him.'); if (!WEATHER_API) return msg.reply('my Commander has not set the Weather API Key. Go yell at him.'); const locationURI = encodeURIComponent(location.replace(/ /g, '+')); const response = await request({ uri: `https://maps.googleapis.com/maps/api/geocode/json?address=${locationURI}&key=${GOOGLE_API}`, headers: { 'User-Agent': `Commando v${version} (https://github.com/WeebDev/Commando/)` }, json: true }); if (response.status !== 'OK') return msg.reply(this.handleNotOK(msg, response.status)); if (response.results.length === 0) return msg.reply('your request returned no results.'); const geocodelocation = response.results[0].formatted_address; const params = `${response.results[0].geometry.location.lat},${response.results[0].geometry.location.lng}`; const locality = response.results[0].address_components.find(loc => loc.types.includes('locality')); const governing = response.results[0].address_components.find(gov => gov.types.includes('administrative_area_level_1')); // eslint-disable-line max-len const country = response.results[0].address_components.find(cou => cou.types.includes('country')); const continent = response.results[0].address_components.find(con => con.types.includes('continent')); const city = locality || governing || country || continent || {}; const state = locality && governing ? governing : locality ? country : {}; const res = await request({ uri: `https://api.darksky.net/forecast/${WEATHER_API}/${params}?exclude=minutely,hourly,flags&units=auto`, headers: { 'User-Agent': `Commando v${version} (https://github.com/WeebDev/Commando/)` }, json: true }); const condition = res.currently.summary; const icon = res.currently.icon; const chanceofrain = Math.round((res.currently.precipProbability * 100) / 5) * 5; const temperature = Math.round(res.currently.temperature); const humidity = Math.round(res.currently.humidity * 100); const canvas = new Canvas(400, 180); const ctx = canvas.getContext('2d'); const base = new Image(); const cond = new Image(); const humid = new Image(); const precip = new Image(); let theme = 'light'; let fontColor = '#FFFFFF'; if (icon === 'snow' || icon === 'sleet' || icon === 'fog') { theme = 'dark'; fontColor = '#444444'; } const generate = () => { // Environment Variables ctx.drawImage(base, 0, 0); ctx.scale(1, 1); ctx.patternQuality = 'billinear'; ctx.filter = 'bilinear'; ctx.antialias = 'subpixel'; // City Name ctx.font = '20px Roboto'; ctx.fillStyle = fontColor; ctx.fillText(city.long_name ? city.long_name : 'Unknown', 35, 50); // Prefecture Name ctx.font = '16px Roboto'; ctx.fillStyle = theme === 'light' ? 'rgba(255, 255, 255, 0.8)' : 'rgba(0, 0, 0, 0.8)'; ctx.fillText(state.long_name ? state.long_name : '', 35, 72.5); // Temperature ctx.font = "48px 'Roboto Mono'"; ctx.fillStyle = fontColor; ctx.fillText(`${temperature}°`, 35, 140); // Condition ctx.font = '16px Roboto'; ctx.textAlign = 'right'; ctx.fillText(condition, 370, 142); // Condition Image ctx.drawImage(cond, 325, 31); // Humidity Image ctx.drawImage(humid, 358, 88); // Precip Image ctx.drawImage(precip, 358, 108); // Titles ctx.font = "16px 'Roboto Condensed'"; ctx.fillText(`${humidity}%`, 353, 100); ctx.fillText(`${chanceofrain}%`, 353, 121); }; base.src = await fs.readFileAsync(this.getBase(icon)); cond.src = await fs.readFileAsync(path.join(__dirname, '..', '..', 'assets', 'weather', 'icons', theme, `${icon}.png`)); // eslint-disable-line max-len humid.src = await fs.readFileAsync(path.join(__dirname, '..', '..', 'assets', 'weather', 'icons', theme, 'humidity.png')); // eslint-disable-line max-len precip.src = await fs.readFileAsync(path.join(__dirname, '..', '..', 'assets', 'weather', 'icons', theme, 'precip.png')); // eslint-disable-line max-len generate(); return msg.channel.send({ files: [{ attachment: canvas.toBuffer(), name: `${geocodelocation}.png` }] }); }
fonts.forEach(function(font){ Canvas.registerFont(font.file, _.pick(font, "family", "weight", "style")); });
async parse(data, debug) { this.log("Running EEW Parser", "debug"); const channel = debug ? this.debugChannel : this.postChannel; const response = await request({ headers: { "User-Agent": "Mozilla/5.0" }, uri: "https://maps.googleapis.com/maps/api/staticmap", encoding: "binary", qs: { zoom: 6, size: "386x159", format: "png", maptype: "roadmap", style: "feature:road|color:0xFFFFF", center: `${data.details.geography.lat},${data.details.geography.long}`, markers: `${data.details.geography.lat},${data.details.geography.long}` } }).catch(err => { this.log(err, "fatal", true); return this.error(err, this.debugChannel); }); Canvas.registerFont(path.join(__dirname, "Roboto.ttf"), { family: "Roboto" }); const canvas = new Canvas(400, 280); const ctx = canvas.getContext("2d"); const { Image } = Canvas; const map = new Image(); const base = new Image(); map.src = new Buffer(response, "binary"); base.src = fs.readFileSync(path.join(__dirname, "base.png")); // Draw Image ctx.drawImage(base, 0, 0); ctx.drawImage(map, 7, 73); ctx.scale(1, 1); ctx.patternQuality = "bilinear"; ctx.filter = "bilinear"; ctx.antialias = "subpixel"; // Epicenter ctx.font = "17px Roboto"; ctx.fillStyle = "#FFF"; ctx.fillText(data.details.epicenter.en, 20, 35); // Details ctx.font = "15px Roboto"; ctx.fillStyle = "rgba(255, 255, 255, 0.75)"; ctx.fillText(`Magnitude ${data.details.magnitude}, Seismic ${data.details.seismic.en}, Depth ${data.details.geography.depth}km`, 20, 58); // Footer ctx.font = "15px Roboto"; ctx.fillStyle = "#000"; ctx.fillText("Information is preliminary", 56, 257); // New Quake if (!(data.id in previous_quake)) { previous_quake[data.id] = data; previous_message = await channel.sendFile(canvas.toBuffer()); this.log(`Posted Image to #${channel.name}`, "debug"); return true; // Last Revision } else if (data.situation === 1) { previous_quake[data.id] = data; await previous_message.delete().catch(err => err.message); this.log(`Deleted Previous Image from #${channel.name}`, "debug"); previous_message = ""; await channel.sendFile(canvas.toBuffer()); this.log(`Posted Image to #${channel.name}`, "debug"); return true; } return false; }