Перейти к содержимому
AlexCatze

Как сделать простой инсталятор на основе github

Рекомендуемые сообщения

2 минуты назад, eu_tomat сказал:

А хоть что-нибудь успевает распарситься?

Нет. В веб версии оцелота то же самое.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@AlexCatze Похоже,  на этом железе и на таком объёме данных gsub не успевает выполнить даже одну итерацию за отпущенный ему таймаут. Жаль. Придётся использовать более сложные способа разбора.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
23 минуты назад, AlexCatze сказал:

В веб версии оцелота то же самое.

У меня аналогичный опыт. Но это очень странно. Веб-версия оцелота отработала до истечения таймаута на два порядка больше итераций пустого цикла, чем в игре на моём компьютере. Зато при обработке gsub почему-то валится в TLWY. Может, Ocelot кривоват?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Только что, eu_tomat сказал:

Может, Ocelot кривоват?

Возможно. В любом случае, на нормальном майне смогу проверить только в понедельник.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@AlexCatze Предлагаю вместо этой конструкции:

html:gsub( 'data%-pjax="#repo%-content%-pjax%-container" href="(.-)">', function(s)os.sleep(0)print(s)end )

использовать такую:

for s in html:gmatch( 'data%-pjax="#repo%-content%-pjax%-container" href="(.-)">')do os.sleep(0)print(s)end

Работает раза в два быстрее.

Web-версия оцелота успешно отработала этот код.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
10 часов назад, eu_tomat сказал:

@AlexCatze Предлагаю вместо этой конструкции:


html:gsub( 'data%-pjax="#repo%-content%-pjax%-container" href="(.-)">', function(s)os.sleep(0)print(s)end )

использовать такую:


for s in html:gmatch( 'data%-pjax="#repo%-content%-pjax%-container" href="(.-)">')do os.sleep(0)print(s)end

Работает раза в два быстрее.

Web-версия оцелота успешно отработала этот код.

Попробовал, веб в  версии отрабатывает, а в локальной всё тот же TLWY.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
6 часов назад, AlexCatze сказал:

Попробовал, веб в  версии отрабатывает, а в локальной всё тот же TLWY.

Тогда я не вижу другого варианта кроме использования find без шаблонов. Код распухнет строк на 10, но, как ни странно, он работает гораздо быстрее библиотечных функций:

local sHead, sTail = 'data-pjax="#repo-content-pjax-container" href="', '">'
local pTail, pHead = 1
while true do
  pHead = html:find( sHead, pTail, true )
  if not pHead then break end
  pTail = html:find( sTail, pHead+#sHead, true )
  if not pTail then break end
  print( html:sub(pHead+#sHead,pTail-1) )
  pTail = pTail+#sTail
end

На моём компьютере этот код можно выполнить примерно 1-1.5 тысячи раз до наступления TLWY, запас огромный.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Сейчас попробовал. TLWY нету, но работает это краааайне медленно. Сейчас воюю с парсингом raw ссылки, но что-то мне кажется, что это бессмысленно. Первый вариант, с предварительно заданным списком файлов хоть и требует потратить  минуту на задание этого самого списка, но в перспективе работает на пару порядков быстрее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, AlexCatze сказал:

TLWY нету, но работает это краааайне медленно.

Сам разбор работает очень быстро, если использовать find без шаблонов. Медленно работает получение страницы, тратя один такт времени на каждый кусок. А кусков много, Web-версия гораздо объёмнее, нежели API. Очень странный подход у владельца гитхаба – ограничивать быстрый и компактный вариант, не ограничивая медленный.

 

1 час назад, AlexCatze сказал:

Первый вариант, с предварительно заданным списком файлов хоть и требует потратить  минуту на задание этого самого списка, но в перспективе работает на пару порядков быстрее.

С этим я согласен. Но инсталляция требуется один раз, на эксплуатации программы это никак не скажется. Зато программист может не тратить своё внимание на обновление установщика при каждом изменении. Но я не настаиваю на этом решении. Я могу лишь предлагать.

 

1 час назад, AlexCatze сказал:

Сейчас воюю с парсингом raw ссылки, но что-то мне кажется, что это бессмысленно.

Почему же бессмысленно? Фраза id="raw-url" встречается на странице лишь один раз или не встречается вовсе.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, eu_tomat сказал:

Фраза id="raw-url" встречается на странице лишь один раз или не встречается вовсе.

Как конечную точку я её и использую, а вот с начальной нужно возиться. В теории, можно получение списка файлов , возложить на плечи какого нибудь heroku и pythonanywhere.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
11 час назад, AlexCatze сказал:

Сейчас воюю с парсингом raw ссылки, но что-то мне кажется, что это бессмысленно.

Кстати, да. С утра мне это тоже показалось бессмысленным.

 

Нам же не обязательно скачивать и разбирать web-страницу файла. Достаточно разобрать ссылку! И если обнаружена ссылка на файл, то можно сразу  скачивать её raw-версию:

https://github.com/{AUTHOR}/{REPO}/tree/{BRANCH}/{PATH}
https://github.com/{AUTHOR}/{REPO}/blob/{BRANCH}/{PATH}/{NAME}
https://raw.githubusercontent.com/{AUTHOR}/{REPO}/{BRANCH}/{PATH}/{NAME}

Строки ссылок короткие, поэтому тут можно смело применять шаблоны, не опасаясь TLWY.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вот два инсталятора:

Первый парсит странички и получает список файлов:

local owner = "AlexCatze"
local repo = "RacoonNet"
local branch = "v0.2"

local internet = require("internet")
local fs = require("filesystem")
local shell = require("shell")

function request(url)
  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
  return html  
end

function parse( html,sHead, sTail, fnc)
  local pTail, pHead = 1
  while true do
    pHead = html:find( sHead, pTail, true )
    if not pHead then break end
    pTail = html:find( sTail, pHead+#sHead, true )
    if not pTail then break end
    fnc( html:sub(pHead+#sHead,pTail-1) )
    pTail = pTail+#sTail
  end
end

function get_files(url)
  local result = request(url)
  if result then
    parse(result, 'data-pjax="#repo-content-pjax-container" href="', '">', function(s)
	  result = request("https://github.com"..s)
	  os.sleep(0)
	  if result then
	    os.sleep(0)
	    local raw
	    parse(result, '/raw/', '" id="raw-url"', function(s) raw = s end)
		if raw ~= "" and raw ~= nil then
		  local path = "/"..raw:match("[^/]/(.*)")
		  if not fs.exists(path:match(".*/")) then fs.makeDirectory(path:match(".*/")) end
          shell.execute("wget -f ".."https://raw.githubusercontent.com/"..owner.."/"..repo.."/"..raw.." "..path)
		  os.sleep(0)
		else
		  os.sleep(0)
		  get_files("https://github.com"..s)
		end
	  end
	end)
  end
end
get_files("https://github.com/"..owner.."/"..repo.."/tree/"..branch)

У второго же список файлов заранее задан(используя мою утилитку):

local shell = require("shell")
local fs = require("filesystem")
local prefix = "https://raw.githubusercontent.com/AlexCatze/RacoonNet/v0.2"
local files = {"/bin/chat.lua","/bin/chat_server.lua","/bin/loader.lua","/bin/mc.lua","/bin/ping.lua","/bin/rnconfig.lua","/bin/routconf.lua","/bin/router.lua","/bin/webserver.lua","/bin/wr.lua","/boot/05_config.lua","/etc/config/mc.cfg","/etc/config/sys.cfg","/etc/lang/en.mc.lang","/etc/lang/ru.mc.lang","/etc/lang/ru.router.lang","/etc/themes/monochrome.thm","/etc/themes/redstone.thm","/etc/themes/standart.thm","/lib/forms.lua","/lib/opennet.lua","/lib/racoon.lua","/lib/racoonnet.lua","/lib/rainbow.lua","/lib/rn_modem.lua","/lib/rn_stem.lua","/lib/rn_tunnel.lua","/lib/stem.lua","/www/index.html","/www/second.html",}


for _,v in pairs(files) do
  if not fs.exists(v:match(".*/")) then fs.makeDirectory(v:match(".*/")) end
  shell.execute("wget -f "..prefix..v.." "..v)
end

Оба настроены на скачивание одинаковых файлов. Но первый делает это за семь минут, пятьдесят три секунды, а второй за ноль минут, двенадцать секунд. Результат на лицо. Вывод: первый вариант мало применим. Можно либо использовать второй вариант, либо выносить получение списка файлов за пределы майнкрафта.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
В 26.02.2021 в 16:25, hohserg сказал:

Зацени этот инсталятор.

https://github.com/hohserg1/HoverHelm/blob/master/server/home/hoverhelm/update-or-repair.lua

Он использует github api, чтобы получить список файлов в репозитории

4f91345dc78c59223726c68c9ae714a9.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
17 часов назад, AlexCatze сказал:

Но первый делает это за семь минут, пятьдесят три секунды, а второй за ноль минут, двенадцать секунд. Результат на лицо. Вывод: первый вариант мало применим. Можно либо использовать второй вариант, либо выносить получение списка файлов за пределы майнкрафта.

А если отказаться от скачивания web-версии файла и разбирать сразу ссылку, как говорилось здесь:

В 02.03.2021 в 07:46, eu_tomat сказал:

Нам же не обязательно скачивать и разбирать web-страницу файла. Достаточно разобрать ссылку! И если обнаружена ссылка на файл, то можно сразу  скачивать её raw-версию

То время сократится до 90-100 секунд.

 

А если web-версию использовать лишь для подстраховки при отказе обслуживания API, то время сократится ещё сильнее.

 

 

@hohserg Мы выше разбирали вариант с API, но есть трудность:

В 25.02.2021 в 18:09, eu_tomat сказал:

https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting

Простым языком: для анонимных пользователей доступно не более 60 запросов в час с одного IP-адреса.

 

Из-за этого решение на базе API может оказаться нестабильным. Особенно, учитывая, что на одном IP может работать несколько серверов, и на каждом сервере может играть больше одного игрока.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вроде разгрёб завал на учёбе, потихоньку возвращаюсь к OC. Вот очередная реализация, правда уже не очень простая. За то по скорости не уступает варианту с предварительно заданным списком файлов.

Сам инсталятор:

local internet = require("internet")
local fs = require("filesystem")
local shell = require("shell")
local ser = require("serialization")

local host = "alexcatze.pythonanywhere.com"
local owner = "AlexCatze"
local repo = "RacoonNet"
local ref = "v0.2"
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

Как видно, он стучится мне на pythonanywhere, откуда и берёт список файлов.

Вот код с pythonanywhere:

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__)

def main():
    uname = "AlexCatze"
    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'])

Тут мы получаем запрос, из него извлекаем нужные данные. Потом используя api ключ(тогда лимит запросов 5000 в час), рекурсивно получаем список файлов, и отправляем его на клиент.

Вечером подробно распишу, как это настроить.

  • Нравится 5
  • Спасибо 1
  • В шоке 2

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Оказалось, что web-версия GitHub также имеет ограничение частоты запросов. Правда, OpenComputers настолько сильно ограничивает скорость приёма данных, что ограничения самого GitHub перестают играть реальную роль.

 

Я обнаружил это случайно во время поиска по двум ключевым словам в репозитории. Одно ключевое слово я вводил в поисковой запрос на странице репозитория, а другое слово искал на странице средствами браузера. Если слово на странице не обнаруживалось, я быстро пролистывал страницу и выбирал следующую. На пропуск каждой бесполезной страницы уходит секунды две времени. Если второе слово на странице присутствует, то времени на анализ страницы уходит больше.  Примерно на 15-ой странице я вместо страницы с результатами поиска получил следующий текст:

Цитата

Whoa there!

You have triggered an abuse detection mechanism.

Please wait a few minutes before you try again;
in some cases this may take up to an hour.

Если коротко: GitHub обнаружил злоупотребление и предлагает мне замедлиться.

Фраза же "Whoa there!" вообще пытается намекнуть на мою неадекватность.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...