AlexCatze 58 Опубликовано: 24 февраля, 2021 (изменено) Предположим, Вы написали крутую программу. И она размазана, скажем на 10 файлов. Или нет, лучше на 50. И Вам захотелось сделать инсталятор. Первая мысль - вручную заливать все файлы на pastebin, потом писать инсталятор, в нём же вручную прописывать коды файлов на pastebin, и их целевые адреса в системе. Это предложение даже читать больно, не то что совершать описанное в нём действие. Но, выход есть. И так, нам понадобятся две вещи: Github аккаунт Хостинг, на котором можно разместить серверную часть. И если с первым всё предельно понятно, то со вторым возникает вопрс: А где его, собственно, взять? Вариантов много. Можно арендовать VPS, поднять сервер на домашнем компьютере или Raspberry Pi, можно воспользоваться услугами таких сайтов как Heroku или PythonAnywhere. Последний вариант примечателен тем, что он полностью бесплатный. И так, какой из сайтов выбрать? PythonAnywhere имеет более ограниченный функционал, по сравнению с Heroku. Но, при этом он намного легче в настройке и эксплуатации, так что остановимся на нём. Далее по пунктам: 1)Заливаем программу на гитхаб. 2)Переходим по ссылке, и создаём токен. Ставим только одну галочку: После создания запоминаем копируем токен, он нам дальше пригодится. Обращаю внимание, что токен нужно держать в секрете. 3) На этом этапе нам нужен хостинг. Я рассмотрю пример с www.pythonanywhere.com . Идём на сайт, регистрируем аккаунт и создаём Flask приложение. В этом нет ничего сложного, если знать английский. Находим файл flask_app.py, и вставляем в него следующее содержимое: from flask import Flask from flask import request import requests import json def request_url(url, result): r = requests.get(url) j = json.loads(r.text) for x in j: if x["type"] == "file": result = result + "\"" + x["path"] + "\"," else: result = request_url(x["url"],result) return result app = Flask(__name__) #@app.route('/',methods=['POST']) def main(): uname = ""# Сюда нужно прописать логин аккаунта Github token = ""# А сюда полученный токен if uname != request.args["owner"]: return "{}" result = request_url("https://"+uname+":"+token+"@api.github.com/repos/"+request.args["owner"]+"/"+request.args["repo"]+"/contents"+request.args["path"]+"?ref="+request.args["ref"],"{") result = result + "}" return result app.add_url_rule("/", "main", main,methods=['GET']) Заполняем поля uname и token, и можно двигаться дальше. 4) На своём компьютере создаём Lua файл, и вставляем в него: local internet = require("internet") local fs = require("filesystem") local shell = require("shell") local ser = require("serialization") local host = ""--Хост, на котором расположена серверная часть local owner = ""--Логин аккаунта Github local repo = ""--Название репозитория local ref = "master"--Название ветки local path = "/"--Путь к папке, из которой скачивать файлы local deploy_to = "/"--Куда скачивать файлы function request(url) local data = "" local result, response = pcall(internet.request, url) if result then local result = pcall(function() for chunk in response do data = data .. chunk end end) end return data end files = ser.unserialize(request("http://"..host.."/?owner="..owner.."&repo="..repo.."&path="..path.."&ref="..ref)) for _,v in pairs(files) do local pth = deploy_to..v if not fs.exists(pth:match(".*/")) then fs.makeDirectory(pth:match(".*/")) end shell.execute("wget -f ".."https://raw.githubusercontent.com/"..owner.."/"..repo.."/"..ref.."/"..v.." "..pth) end Заполняем поля, и готово. Изменено 6 марта, 2021 пользователем AlexCatze 3 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 24 февраля, 2021 @AlexCatze Есть два предложения: Немного упростить гайд, чтобы не заставлять пользователя возвращаться туда-сюда: 11 минуту назад, AlexCatze сказал: 2)Заливаем нашу папку на github 3) Создаём на компьютере файл installer.lua, в него вставляем следующее содержимое: ... 4)Возвращаемся к github`у, открываем любой файл, и нажимаем "raw". Нас интересует адрес файла. Копируем эту часть(без "/" в конце): 5)Возвращаемся к нашему файлу, вставляем полученный адрес в поле prefix. Должно получится так: Пишем проще: заливаем на гитхаб..., копируем адрес..., создаём файл..., вставляем адрес... Дописать установщику возможность динамически считывать структуру репозитория, например, из каталога https://github.com/AlexCatze/racoon-dev/installer Страницы разбираются не сложно, по фразе data-pjax="#repo-content-pjax-container". Это позволит пользователю не повторять процедуру при смене структуры каталогов или добавлении и удалении файлов. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
AlexCatze Автор темы 58 Опубликовано: 24 февраля, 2021 5 минут назад, eu_tomat сказал: Дописать установщику возможность динамически считывать структуру репозитория Собственно, с начала я это и хотел сделать, но не разобрался, как получить список всех файлов в репозитории. 8 минут назад, eu_tomat сказал: Страницы разбираются не сложно, по фразе data-pjax="#repo-content-pjax-container". Можно, пожалуйста, по подробнее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 24 февраля, 2021 52 минуты назад, AlexCatze сказал: Можно, пожалуйста, по подробнее. Вот пример скрипта, считывающую ссылки на элементы каталога: local url = "https://github.com/AlexCatze/racoon-dev/" local internet = require("internet") local html = "" local result, response = pcall(internet.request, url) if result then local result = pcall(function() for chunk in response do html = html .. chunk end end) end if result then html:gsub( 'data%-pjax="#repo%-content%-pjax%-container" href="(.-)">', function(s)print(s)end ) end Результатом его выполнения вывод будет следующий вывод: /AlexCatze/racoon-dev/tree/master/bin /AlexCatze/racoon-dev/tree/master/boot /AlexCatze/racoon-dev/tree/master/etc /AlexCatze/racoon-dev/tree/master/lib /AlexCatze/racoon-dev/tree/master/www Далее потребуется рекурсивно обойти все каталоги и найти в них файлы. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
AlexCatze Автор темы 58 Опубликовано: 24 февраля, 2021 8 минут назад, eu_tomat сказал: Вот пример скрипта, считывающую ссылки на элементы каталога: Понял, спасибо. Осталось только прикрутить распознавание файлов и каталогов, и будет считывалка. Завтра постараюсь сделать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 24 февраля, 2021 1 минуту назад, AlexCatze сказал: Понял, спасибо. Осталось только прикрутить распознавание файлов и каталогов, и будет считывалка. Я забыл сразу упомянуть один важный момент. Надо как-то отличать каталоги от файлов. Интуитивно понятное решение: искать в тексте ссылку на raw-формат файла. Но оно потребует дублирования запроса и ожидания отдачи страницы. Есть более быстрое решение: сразу запрашивать сырой формат. Если получишь 404, значит это не файл, а каталог. Это решение потребует меньше трафика и времени на ожидание. Скорее всего, гитхаб имеет API, позволяющий избежать и лишнего трафика и этих трюков с парсингом. Моё решение следует рассматривать как отправную точку, интуитивно понятную, но вряд ли оптимальную. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 24 февраля, 2021 20 минут назад, eu_tomat сказал: Скорее всего, гитхаб имеет API, позволяющий избежать и лишнего трафика и этих трюков с парсингом. Ну, точно! Есть API: Скрытый текст $ curl -i https://api.github.com/repos/AlexCatze/racoon-dev/contents/ 2>/dev/zero | egrep '"(path|url|type)"' "path": "bin", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin?ref=master", "type": "dir", "path": "boot", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/boot?ref=master", "type": "dir", "path": "etc", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/etc?ref=master", "type": "dir", "path": "lib", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/lib?ref=master", "type": "dir", "path": "www", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/www?ref=master", "type": "dir", $ curl -i https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin 2>/dev/zero | egrep '"(path|url|type)"' "path": "bin/chat.lua", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin/chat.lua?ref=master", "type": "file", "path": "bin/chat_server.lua", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin/chat_server.lua?ref=master", "type": "file", "path": "bin/loader.lua", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin/loader.lua?ref=master", "type": "file", "path": "bin/mc.lua", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin/mc.lua?ref=master", "type": "file", "path": "bin/ping.lua", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin/ping.lua?ref=master", "type": "file", "path": "bin/rnconfig.lua", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin/rnconfig.lua?ref=master", "type": "file", "path": "bin/routconf.lua", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin/routconf.lua?ref=master", "type": "file", "path": "bin/router.lua", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin/router.lua?ref=master", "type": "file", "path": "bin/webserver.lua", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin/webserver.lua?ref=master", "type": "file", "path": "bin/wr.lua", "url": "https://api.github.com/repos/AlexCatze/racoon-dev/contents/bin/wr.lua?ref=master", "type": "file", 2 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
AlexCatze Автор темы 58 Опубликовано: 24 февраля, 2021 3 минуты назад, eu_tomat сказал: Ну, точно! Есть API Огромное спасибо!!! Я как бы знал, что оно есть, но найти в документации нужый метод не получилось. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
AlexCatze Автор темы 58 Опубликовано: 25 февраля, 2021 @eu_tomat переделал. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Doob 2 749 Опубликовано: 25 февраля, 2021 А если мне не надо все файлы качать? Зачем мне ридми, тесты, лицензия? В свое время я это сделал проще - качается файл version.lua, в нем текущая версия программы и список файлов, если версии не совпадают, то программа качает файлы и перезапускается. Потом я это немного переосмыслил и сделал в виде бутлоадера. Бутлоадер представляет собой замену Lua BIOS, с функционалом, позволяющим устанавливать и обновлять программы без операционки. Сам обновляется, обновляет нужные файлы, ставит вейкап сообщения на модем, связанную карту и редстоун. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
AlexCatze Автор темы 58 Опубликовано: 25 февраля, 2021 11 минуту назад, Doob сказал: А если мне не надо все файлы качать? Можно в последней строке между "/contents/" и "?ref=" вписать путь к папке, которую нужно скачать. Изначально инсталятор делался "под себя". Т.е. у меня была задача одной командой скачивать репозиторий, и этот инсталятор решает её. 18 минут назад, Doob сказал: В свое время я это сделал проще - качается файл version.lua Мне оказалось проще сделать такой инсталятор, чем список файлов, который к тому же, нужно будет вручную обновлять. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 25 февраля, 2021 @AlexCatze Я столкнулся с неприятным свойством API GitHub: https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting Цитата For unauthenticated requests, the rate limit allows for up to 60 requests per hour. Unauthenticated requests are associated with the originating IP address, and not the user making requests. Простым языком: для анонимных пользователей доступно не более 60 запросов в час с одного IP-адреса. Из-за этого решение на базе API может оказаться нестабильным. Особенно, учитывая, что на одном IP может работать несколько серверов, и на каждом сервере может играть больше одного игрока. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
AlexCatze Автор темы 58 Опубликовано: 25 февраля, 2021 Тогда есть смысл использовать старый инсталятор. Чуть позже сделаю по нему нормальный гайд. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 26 февраля, 2021 14 часа назад, AlexCatze сказал: Тогда есть смысл использовать старый инсталятор. Лучше тогда разбирать web-версию гитхаба. Решение, конечно, медленное, но зато не требует обновлять код установщика при изменениях файловой структуры. Можно даже комбинировать вызовы к API и Web в зависимости от исчерпания лимита. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
AlexCatze Автор темы 58 Опубликовано: 26 февраля, 2021 3 часа назад, eu_tomat сказал: разбирать Меня от этого слова уже тошнит. Я пока пару дней отдохну от расчленения гитхаба. Как будет апдейт сети, которую я пишу, к нему сделаю такой инсталятор. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
hohserg 197 Опубликовано: 26 февраля, 2021 (изменено) Зацени этот инсталятор. https://github.com/hohserg1/HoverHelm/blob/master/server/home/hoverhelm/update-or-repair.lua Он использует github api, чтобы получить список файлов в репозитории Изменено 26 февраля, 2021 пользователем hohserg Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
AlexCatze Автор темы 58 Опубликовано: 27 февраля, 2021 В 24.02.2021 в 21:27, eu_tomat сказал: Результатом его выполнения вывод будет следующий вывод: Попробовал на эмуляторе ocelot, получил TLWY. Видимо ответ слишком большой для gsub. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 27 февраля, 2021 2 часа назад, AlexCatze сказал: Попробовал на эмуляторе ocelot, получил TLWY. Видимо ответ слишком большой для gsub. Проверил у себя на компьютере, gsub в моём примере выполнился за 2.5 сек. А стандартный таймаут для TLWY составляет 5 сек. Запас по времени маловат, поэтому решение неустойчивое, на слабом железе работать не будет. Предлагаю в вызываемую функцию добавить os.sleep(0). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
AlexCatze Автор темы 58 Опубликовано: 27 февраля, 2021 7 минут назад, eu_tomat сказал: Предлагаю в вызываемую функцию добавить os.sleep(0). Так? local url = "https://github.com/AlexCatze/racoon-dev/" local internet = require("internet") local html = "" local result, response = pcall(internet.request, url) if result then local result = pcall(function() for chunk in response do html = html .. chunk end end) end if result then html:gsub( 'data%-pjax="#repo%-content%-pjax%-container" href="(.-)">', function(s) os.sleep(0) print(s)end ) end Только что попробовал, эффект тот же. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 27 февраля, 2021 14 минуты назад, AlexCatze сказал: Так? ... Только что попробовал, эффект тот же. Да, верно. А хоть что-нибудь успевает распарситься? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах