Некоторое время назад я публиковал программку - интернет-мост Stem.
Он очень простой в использовании, но к сожалению пока не лишен некоторых глюков.
А кроме того, у него есть недокументированные возможности.
Предлагаю сейчас поиграться с одной такой тайной фичей. Это будет интересно тем, кто немного знаком с HTML/CSS/JavaScript.
В чём суть?
Всё просто.
У Stem есть веб-клиент. То есть если вы зайдете по адресу https://stem.fomalhaut.me (например), вы увидите окно, которое пригласит вас ввести ID канала и початиться прямо с сайта.
После ввода ID канала, вас перекинет на страничку с "чатом", где вы сможете посылать сообщения вашему компьютеру/роботу в майнкрафте.
Адрес этой странички будет выглядеть примерно так:
https://stem.fomalhaut.me/channel?id=test
Где test это ID вашего канала.
Когда робот будет вам отвечать, это будет видно в логе. Примерно так:
А теперь - тайная фича.
Находясь на страничке канала, как на скриншоте, вы можете приписать к адресу дополнительный флаг: &render=true.
Полный адрес станет выглядеть примерно так:
https://stem.fomalhaut.me/channel?id=test&render=true
И начиная с этого момента, все входящие сообщения от компьютера в OpenComputers будут не отрисовываться в лог, а попадать в JS функцию eval(...).
Что это значит?
Те кто имел дело с JS уже наверное поняли все последствия.
Но я поясню.
Это значит, что компьютер OpenComputers может прислать сообщение с JS кодом, и сайт Stem этот код выполнит.
А это значит, что вы можете творить на сайте вообще всё что угодно. Вы можете удалить интерфейс, показать вместо него новый, скачать что-то с инета, запустить игрушку... да хоть майнить крипту.
Поиграем
Ничего вредоносного мы делать конечно сейчас не будем.
Вместо этого, традиционно, попробуем сделать так, что сайт Stem превратится в сайт для управления светом в нашем доме в Майнкрафте.
Шаг первый. Подготовим дом.
Тут всё просто - стандартный компьютер, с интернет картой, от него кабель к I/O блоку, а на блоке - подопытная лампа.
На компьютер ставим Stem.
Например, ставим HPM такой командой,
pastebin run vf6upeAN
И потом пишем:
hpm install stem
Нажимаем Enter и готово.
Шаг второй. Нам нужен сайт.
Усложнять не будем, и наш революционный дизайн будет выглядеть так:
Что нам нужно сделать, чтобы сайт Stem превратился в то что нам надо?
Методом тыка, через консоль браузера определяем, что достаточно выполнить такой код:
document.body.innerHTML = "
<style>button:active { background: #fac700; }</style>
<button onclick=\"sendMessage(\'toggle\')\">Toggle Light</button>
";
document.body.style.alignItems = "center";
Первой строкой мы просто заменяем всё содержимое тега <body> на то что нам надо. Я добавил еще немного косметики в виде стиля для кнопки. Вторая строка - тоже косметика, я просто поправил стиль на теге <body> чтобы кнопочка была посередине.
Один важный ньюанс - на кнопке повешено свойство onclick с кодом sendMessage("toggle").
Таким образом, когда пользователь тыкнет по кнопке, мы отправим сообщение обратно в OpenComputers.
Функцию sendMessage нам дает веб-клиент Stem. Ей можно безвозмездно пользоваться в своих целях.
Шаг третий. Соединяем это все вместе.
Теперь надо набросать программку для нашего компьютера в Майнкрафте, чтобы он выслал подготовленную JS-"бомбу" по нашему сигналу.
Эники, беники... выходит что-то такое:
local event = require('event')
local stem = require('stem')
local side = require('sides')
local com = require('component')
local redstone = com.isAvailable('redstone') and com.redstone or nil
local channel = "test"
local layout = [===[
document.body.innerHTML = "\
<style>button:active { background: #fac700; }</style>\
<button onclick=\"sendMessage(\'toggle\')\">Toggle Light</button>\
";
document.body.style.alignItems = "center";
]===]
local lampSide = side.top
local lampTurnedOn = false
print("Connecting to the #" .. channel .. " STEM channel...")
local server = stem.connect('stem.fomalhaut.me')
server:subscribe(channel)
print("Done.")
print("Press [q] to quit.")
while true do
local name, a, b = event.pull()
if name == "stem_message" then
local message = b
if message == "connect" then
print("Someone wants to connect - sending the layout...")
server:send(channel, layout)
elseif message == "toggle" then
if redstone ~= nil then
if not lampTurnedOn then
redstone.setOutput(lampSide, 16)
lampTurnedOn = true
else
redstone.setOutput(lampSide, 0)
lampTurnedOn = false
end
end
end
elseif name == "key_down" then
local char = b
if char == 113 then break end
end
end
server:disconnect()
Я думаю тут большая часть очевидна и понятна.
Мы подключаемся к серверу Stem, подписываемся на нужный канал и внимательно слушаем входящие сообщения.
Когда пользователь присылает сообщение connect, мы отправляем ему подготовленный код, который мирно лежит в переменной layout.
Этот код прилетит к пользователю, и, если пользователь смотрит страницу с включенной опцией render=true, код сработает и перерисует страницу.
Если опция будет отключена - он просто увидит код в логе, как простое сообщение.
Шаг четвертый. Тестируем.
Откроем наш канал по ссылке:
https://stem.fomalhaut.me/channel?id=test&render=true
Появится пустой лог.
Запустим программу в OpenComputers.
Она отрисует наше приветствие, что-то вроде:
Сonnecting to the #test STEM channel...
Done.
Press [q] to quit.
Теперь пишем на сайте команду connect.
Если мы все сделали правильно, и Stem не заглючил, интерфейс сайта исчез, и вместо него появилась наша кнопка.
Нажимаем её.
Вуаля! Дома зажегся свет.
Постскриптум
Это конечно же недокументированная хакерская фича, которую можно считать альфа-версией.
Кроме того в Stem сейчас есть неуловимый баг, из за которого сообщения иногда не доходят. Не пугайтесь.
Если кто-нибудь предоставит мне сценарий (прямо по шагам), при котором 100% срабатывает баг - буду очень рад и пофиксить его будет легче.
С помощью описанной фишки можно придумать много хрени. Я показал самое простое что пришло в голову.
Уверен, ваша фантазия будет покруче моей )
Пишите баг-репорты или пожелания по фиче, да и просто комменты в эту тему, либо мне в любой канал связи, где я онлайн.