Comments 10
Говорили, говорили, говорили не размещать .svn, .git, .env в папках, которые доступны веб-серверу, а воз и нынче там…
[RFC] Typed Properties 2.0 — Предложение по типизированным свойства принято практически единогласно: 70 против 1! Типизированные свойства будут добавлены в PHP 7.4.
А против проголосовал как раз Дмитрий Стогов. Интересно, кстати, почему?
Думаю из-за оверхеда по производительности gist.github.com/dstogov/b9fc0fdccfb8bf7bae121ce3d3ff1db1 ведь Дмитрий как раз производительностью занимается, а эта фича ухудшает ее.
Ник на рэддите [объяснял](https://www.reddit.com/r/PHP/comments/9j2oel/rfc_about_typed_properties_has_been_accepted/e6o94hd/).
Прикольный слон. Кстати сделан скорее всего с помощью https://github.com/fogleman/primitive.
Вот бота писал для телеграмм
Заголовок спойлера
const fs = require('fs');
const exec = require('child_process').execSync;
const temp = require("temp").track();
const pathComponent = require('path');
const TelegramBot = require('node-telegram-bot-api');
const Settings = function () {
this.defaultSettings = {
rect: 1,
type: 0
};
this.container = {};
};
Settings.prototype = {
getValue: function (chatId, value = null) {
if (this.container.hasOwnProperty(chatId)) {
return value ? this.container[chatId][value] : this.container[chatId]
}
return value ? this.getDefault()[value] : this.getDefault();
},
setValue: function (chatId, key, value) {
if (!this.container.hasOwnProperty(chatId)) {
this.container[chatId] = this.getDefault();
}
if (Object.keys(this.defaultSettings).indexOf(key) === -1) {
console.log('Try to set unknown setting: ' + key);
return;
}
if (key === 'type' || key === 'rect') {
value = parseInt(value, 10)
}
this.container[chatId][key] = value;
},
getDefault: function () {
return Object.assign({}, this.defaultSettings);
}
};
const settingsContainer = new Settings();
// Устанавливаем токен, который выдавал нам бот.
const token = '';
const downloadDir = './downloaded/';
const rectOptions = {
reply_markup: JSON.stringify({
inline_keyboard: [
[{text: 'Треугольники', callback_data: 'rect_1'}],
[{text: 'Прямоугольники', callback_data: 'rect_2'}],
[{text: 'Эллипсы', callback_data: 'rect_3'}],
[{text: 'Круги', callback_data: 'rect_4'}],
[{text: 'Прямоугольники(rotated)', callback_data: 'rect_5'}],
[{text: 'Кривые', callback_data: 'rect_6'}],
[{text: 'Эллипсы(rotated)', callback_data: 'rect_7'}],
[{text: 'Полигоны', callback_data: 'rect_8'}],
]
})
};
const typeOptions = {
reply_markup: JSON.stringify({
inline_keyboard: [
[{text: 'Простая картинка', callback_data: 'type_0'}],
[{text: 'Движущаяся картинка', callback_data: 'type_1'}]
]
})
};
// Включить опрос сервера
const bot = new TelegramBot(token, {polling: true});
bot.onText(/\/start/, function (msg) {
bot.sendMessage(msg.chat.id, '/status /settype /setfig');
});
bot.onText(/\/status/, function (msg) {
bot.sendMessage(msg.chat.id, 'I am alive!');
});
bot.onText(/\/setfig/, function (msg) {
bot.sendMessage(msg.chat.id, 'Выберите фигуры из которых будет формируется изображение:', rectOptions);
});
bot.onText(/\/settype/, function (msg) {
bot.sendMessage(msg.chat.id, 'Выберите тип возвращаемого изображения:', typeOptions);
});
bot.on('callback_query', function (msg) {
let chatId = msg.message.chat.id;
let answer = msg.data.split('_');
if (answer.length === 2) {
settingsContainer.setValue(chatId, answer[0], answer[1]);
}
bot.sendMessage(chatId, 'ok');
});
bot.on('message', function (msg) {
console.log(msg);
});
bot.on('photo', onPhoto);
async function onPhoto (msg) {
let chatId = msg.chat.id;
try {
let image = initImage(msg);
let originalImagePath = await bot.downloadFile(image.file_id, downloadDir);
let ext = pathComponent.extname(originalImagePath);
let resizedImagePath = temp.path({suffix: ext});
let processedImagePath;
await resizeImage(image, originalImagePath, resizedImagePath);
let settings = settingsContainer.getValue(chatId);
console.log(settings);
if (settings.type === 0) {
processedImagePath = temp.path({suffix: ext});
makeSimpleImage(settings, resizedImagePath, processedImagePath);
await bot.sendPhoto(chatId, processedImagePath, {});
} else if (settings.type === 1) {
processedImagePath = temp.path({suffix: '.gif'});
await makeGif(settings, image, resizedImagePath, processedImagePath);
await bot.sendVideo(chatId, processedImagePath, {});
}
temp.cleanupSync();
} catch (err) {
console.log(err);
return bot.sendMessage(chatId, err);
}
}
function initImage(msg) {
let photo = msg.photo || [];
let lastFileSize = 0;
let maxResId = -1;
let i;
for (i = 0; i < photo.length; i++) {
if ((photo[i].file_size || 0) > lastFileSize) {
maxResId = i;
}
}
if (maxResId === -1) {
throw new Error('No photo info');
}
let msgPhoto = photo[maxResId];
['file_id', 'width', 'height'].forEach(function (prop) {
if (!msgPhoto.hasOwnProperty(prop)) {
throw new Error('No photo size');
}
});
return msgPhoto;
}
function resizeImage (image, from_path, to_path) {
let resize = image.width > image.height ? '256x' : 'x256';
return exec('convert -geometry ' + resize + ' ' + from_path + ' ' + to_path)
}
function makeSimpleImage(settings, from_path, to_path) {
return exec('primitive -n 250 -m ' + settings.rect + ' -i ' + from_path + ' -o ' + to_path)
}
async function makeGif(settings, image, from_path, to_path) {
let dir = './series/' + makeRandName();
let size = image.width > image.height ? '512:' : ':512';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
for (let i = 1; i <=5 ; i++) {
makeSimpleImage(settings, from_path, '/ ' + i + '.svg');
exec('node node_modules/svgexport/bin/index.js ' + dir + '/' + i + '.svg ' + dir + '/' + i +'.png ' + size);
}
let makeGifCommand = 'convert -loop 0 -delay 12 ' +
dir + '/1.png ' +
dir + '/2.png ' +
dir + '/3.png ' +
dir + '/4.png ' +
dir + '/5.png ' +
to_path;
console.log(makeGifCommand);
return exec(makeGifCommand);
}
function makeRandName() {
let text = "";
let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < 8; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
Sign up to leave a comment.
PHP-Дайджест № 140 (17 – 30 сентября 2018)