#!/usr/bin/env luajit --[[ if type(arg) ~= "table" then error"Something wrong with Lua installation (unable to handle arguments)" end local p = require"posix"; local uid = p.getuid(); local cmd = {}; table.insert(cmd,arg[-1]) arg[-1]=nil for _,opt in pairs(arg) do table.insert(cmd,opt); end cmd=table.concat(cmd," ") if tonumber(uid) ~= 250 then assert(not(arg[#arg]:match("under_sudo_portage")),"Broken Gentoo installation (portage not UID=250)") local exitcode=os.execute("sudo -u portage "..cmd.." #under_sudo_portage") os.exit(exitcode); end ]] local cURL = require"cURL"; local html = require"htmlparser" --local lfs = require"lfs" math.randomseed(tonumber(math.randomseed(os.time()) or os.time())+os.time()); -- randomize local st; local env_filename = os.tmpname(); st = os.execute("emerge --info > "..env_filename) assert(st==0,"emerge --info failed") local env_fd=io.open(env_filename) local op,pt; for line in env_fd:lines() do local mop=line:match([=[location: (/.*lua)]=]); local mpt=line:match([=[PORTAGE_TMPDIR=['"](/.*)['"]]=]); if mop then op=mop; elseif mpt then pt=mpt; end end env_fd:close(); os.remove(env_filename) assert(op~=nil,"Unable to get Lua overlay path from emerge --info") assert(pt~=nil,"Unable to get PORTAGE_TMPDIR from emerge --info") local UAs = { "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20130101 Firefox/37.0"; -- Firefox 37, Windows 7, 64bit "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:37.0) Gecko/20130101 Firefox/37.0"; -- Firefox 37, Ubuntu 12, 32bit "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.22"; -- Chrome 34, Windows 7, 64bit "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/43.0.2357.10 Safari/537.22"; -- Chrome 34, Windows XP "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/42.0.2311.82 Safari/537.22"; -- Chrome 25, Mac OS 10.7 "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/43.0.2537.10 Safari/537.22"; -- Chrome 25, Linux, 64bit "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/43.0.2537.10 Safari/537.22"; -- Chrome 25, Linux, 32bit "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"; -- Internet Explorer 9, Windows 7, 64bit "Mozilla/5.0 (compatible; MSIE 11.0; Windows NT 8.1; WOW64; Trident/7.0)"; -- Internet Explorer 11, Windows 8.1, 64bit "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17"; -- Safari, Mac OS 10.8 } local headers = { "Accept: text/*", "Accept-Language: ru,en", "Accept-Charset: utf-8,cp1251,koi8-r,iso-8859-5,*", "Cache-Control: no-cache" } local modules = {} local e_p = op.."/net-im/prosody-modules/prosody-modules-9999.ebuild"; local md_p = op.."/net-im/prosody-modules/metadata.xml"; local function ebuild(ph) return os.execute("sudo -u portage ebuild "..e_p.." "..ph.." >/dev/null"); end assert(ebuild"clean unpack","Failed to fetch modules") --for mod in lfs.dir(pt.."/portage/net-im/prosody-modules-9999/work/prosody-modules-9999") do for mod in io.popen([[sudo -u portage find ]]..pt..[[/portage/net-im/prosody-modules-9999/work/prosody-modules-9999 -maxdepth 1 -mindepth 1 -type d -name 'mod_*']]):lines() do table.insert(modules,mod:match("mod_(.*)")); end table.sort(modules); assert(ebuild"clean","Failed to cleanup modules") local function wrap(str, limit, indent, indent1) local indent = indent or "" local indent1 = indent1 or indent local limit = limit or 72 local here = 1-#indent1 return indent1..str:gsub("(%s+)()(%S+)()", function(sp, st, word, fi) if fi-here > limit then here = st - #indent return "\n"..indent..word end end) end local eol="\n" local temp_fd,err=io.tmpfile(); assert(temp_fd,err); local function manage_ebuild() local eb_fd,err=io.open(e_p); assert(eb_fd,err); local inside=false; for line in eb_fd:lines() do if line:match([[^PROSODY_MODULES="$]]) then temp_fd:write(line); temp_fd:write(eol) inside=true; elseif inside and (line:match([[^"$]])) then inside=false; temp_fd:write("\t"); temp_fd:write((wrap(table.concat(modules," ")):gsub(eol,eol.."\t"))); temp_fd:write(eol); temp_fd:write(line); temp_fd:write(eol); elseif inside and (line:match("^\t")) then local nop; else temp_fd:write(line); temp_fd:write(eol); end end temp_fd:flush(); assert(temp_fd:seek("set")==0,"WARNING: OS is broken!") eb_fd:close(); local eb_fd,err=io.open(e_p,"w+"); assert(eb_fd,err); for line in temp_fd:lines() do eb_fd:write(line..eol) end assert(temp_fd:seek("set")==0,"WARNING: OS is broken!") eb_fd:close(); end manage_ebuild(); local c = cURL.easy_init() c:setopt_httpheader(headers) c:setopt_cookiefile("") c:setopt_followlocation(1) local function get_flag_desc(flag) local buf,desc="",""; local base_url="https://modules.prosody.im/mod_"..flag..".html"; c:setopt_useragent(UAs[math.random(1,#UAs)]); c:setopt_url(base_url); c:setopt_writefunction(function(result) buf=buf..result; return true; end); c:perform(); local dom=html.parse(buf)('div.container.container-fluid div.col-md-8 p'); if #dom>0 then desc=dom[1]:getcontent(); if desc:match("^NOTE: ") then desc=dom[2]:getcontent(); end end desc=desc and desc:gsub([=[(href=["'])(mod_[^"']+.html)(["'])]=],"%1https://modules.prosody.im/%2%3") desc=desc and desc.." (info: https://modules.prosody.im/mod_"..flag..")" return desc or "No documentation yet :(" end local function manage_metadata() local md_fd,err=io.open(md_p); assert(md_fd,err); local inside=false; for line in md_fd:lines() do if line:match([[]]) then temp_fd:write(line); -- temp_fd:write(eol) inside=true; elseif inside and (line:match([[]])) then inside=false; for _,mod in ipairs(modules) do temp_fd:write("\t"..get_flag_desc(mod)..""); temp_fd:write(eol); end -- temp_fd:write((wrap(table.concat(modules," ")):gsub(eol,eol.."\t"))); temp_fd:write(eol); temp_fd:write(line); temp_fd:write(eol); elseif inside and (line:match("