update.lua 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #!/usr/bin/lua
  2. ------------------------------------------------
  3. -- This file is part of the luci-app-ssr-plus update.lua
  4. -- By Mattraks
  5. ------------------------------------------------
  6. require "luci.sys"
  7. require "luci.model.uci"
  8. local icount = 0
  9. local args = arg[1]
  10. local uci = luci.model.uci.cursor()
  11. local TMP_DNSMASQ_PATH = luci.sys.exec("find /tmp/dnsmasq.*/dnsmasq-ssrplus.d -type d -print 2>/dev/null"):gsub("%s+", "")
  12. local TMP_PATH = "/var/etc/ssrplus"
  13. -- match comments/title/whitelist/ip address/excluded_domain
  14. local comment_pattern = "^[!\\[@]+"
  15. local ip_pattern = "^%d+%.%d+%.%d+%.%d+"
  16. local domain_pattern = "([%w%-%_]+%.[%w%.%-%_]+)[%/%*]*"
  17. local excluded_domain = {"apple.com", "sina.cn", "sina.com.cn", "baidu.com", "byr.cn", "jlike.com", "weibo.com", "zhongsou.com", "youdao.com", "sogou.com", "so.com", "soso.com", "aliyun.com", "taobao.com", "jd.com", "qq.com"}
  18. -- gfwlist parameter
  19. local mydnsip = '127.0.0.1'
  20. local mydnsport = '5335'
  21. local ipsetname = 'gfwlist'
  22. local bc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  23. -- base64decoding
  24. local function base64_dec(data)
  25. data = string.gsub(data, '[^' .. bc .. '=]', '')
  26. return (data:gsub('.', function(x)
  27. if (x == '=') then
  28. return ''
  29. end
  30. local r, f = '', (bc:find(x) - 1)
  31. for i = 6, 1, -1 do
  32. r = r .. (f % 2 ^ i - f % 2 ^ (i - 1) > 0 and '1' or '0')
  33. end
  34. return r;
  35. end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
  36. if (#x ~= 8) then
  37. return ''
  38. end
  39. local c = 0
  40. for i = 1, 8 do
  41. c = c + (x:sub(i, i) == '1' and 2 ^ (8 - i) or 0)
  42. end
  43. return string.char(c)
  44. end))
  45. end
  46. -- check if domain is excluded
  47. local function check_excluded_domain(value)
  48. for _, domain in ipairs(excluded_domain) do
  49. if value:find(domain) then
  50. return true
  51. end
  52. end
  53. end
  54. -- gfwlist转码至dnsmasq格式
  55. local function generate_gfwlist(type)
  56. local domains, domains_map = {}, {}
  57. local out = io.open("/tmp/ssr-update." .. type, "w")
  58. for line in io.lines("/tmp/ssr-update.tmp") do
  59. if not (string.find(line, comment_pattern) or string.find(line, ip_pattern) or check_excluded_domain(line)) then
  60. local start, finish, match = string.find(line, domain_pattern)
  61. if start and not domains_map[match] then
  62. domains_map[match] = true
  63. table.insert(domains, match)
  64. end
  65. end
  66. end
  67. for _, domain in ipairs(domains) do
  68. out:write(string.format("server=/%s/%s#%s\n", domain, mydnsip, mydnsport))
  69. out:write(string.format("ipset=/%s/%s\n", domain, ipsetname))
  70. end
  71. out:close()
  72. os.remove("/tmp/ssr-update.tmp")
  73. end
  74. -- adblock转码至dnsmasq格式
  75. local function generate_adblock(type)
  76. local domains, domains_map = {}, {}
  77. local out = io.open("/tmp/ssr-update." .. type, "w")
  78. for line in io.lines("/tmp/ssr-update.tmp") do
  79. if not (string.find(line, comment_pattern)) then
  80. local start, finish, match = string.find(line, domain_pattern)
  81. if start and not domains_map[match] then
  82. domains_map[match] = true
  83. table.insert(domains, match)
  84. end
  85. end
  86. end
  87. for _, domain in ipairs(domains) do
  88. out:write(string.format("address=/%s/\n", domain))
  89. end
  90. out:close()
  91. os.remove("/tmp/ssr-update.tmp")
  92. end
  93. local log = function(...)
  94. if args then
  95. print("{ret=" .. table.concat({...}, ",retcount=") .. "}")
  96. else
  97. print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({...}, " "))
  98. end
  99. end
  100. local function update(url, file, type, file2)
  101. local Num = 1
  102. local refresh_cmd = "wget --no-check-certificate -q -O /tmp/ssr-update." .. type .. " " .. url
  103. local sret = luci.sys.call(refresh_cmd)
  104. if sret == 0 then
  105. if type == "gfw_data" then
  106. local gfwlist = io.open("/tmp/ssr-update." .. type, "r")
  107. local decode = gfwlist:read("*a")
  108. if not decode:find("google") then
  109. decode = base64_dec(decode)
  110. end
  111. gfwlist:close()
  112. -- 写回gfwlist
  113. gfwlist = io.open("/tmp/ssr-update.tmp", "w")
  114. gfwlist:write(decode)
  115. gfwlist:close()
  116. generate_gfwlist(type)
  117. Num = 2
  118. end
  119. if type == "ad_data" then
  120. local adblock = io.open("/tmp/ssr-update." .. type, "r")
  121. local decode = adblock:read("*a")
  122. if decode:find("address=") then
  123. adblock:close()
  124. else
  125. adblock:close()
  126. -- 写回adblock
  127. adblock = io.open("/tmp/ssr-update.tmp", "w")
  128. adblock:write(decode)
  129. adblock:close()
  130. generate_adblock(type)
  131. end
  132. end
  133. local new_md5 = luci.sys.exec("echo -n $([ -f '/tmp/ssr-update." .. type .. "' ] && md5sum /tmp/ssr-update." .. type .. " | awk '{print $1}')")
  134. local old_md5 = luci.sys.exec("echo -n $([ -f '" .. file .. "' ] && md5sum " .. file .. " | awk '{print $1}')")
  135. if new_md5 == old_md5 then
  136. if args then
  137. log(1)
  138. else
  139. log("你已经是最新数据,无需更新!")
  140. end
  141. else
  142. icount = luci.sys.exec("cat /tmp/ssr-update." .. type .. " | wc -l")
  143. luci.sys.exec("cp -f /tmp/ssr-update." .. type .. " " .. file)
  144. if file2 then
  145. luci.sys.exec("cp -f /tmp/ssr-update." .. type .. " " .. file2)
  146. end
  147. if type == "gfw_data" or type == "ad_data" then
  148. luci.sys.call("/usr/share/shadowsocksr/gfw2ipset.sh")
  149. else
  150. luci.sys.call("/usr/share/shadowsocksr/chinaipset.sh " .. TMP_PATH .. "/china_ssr.txt")
  151. end
  152. if args then
  153. log(0, tonumber(icount) / Num)
  154. else
  155. log("更新成功! 新的总记录数:" .. tostring(tonumber(icount) / Num))
  156. end
  157. end
  158. else
  159. if args then
  160. log(-1)
  161. else
  162. log("更新失败!")
  163. end
  164. end
  165. os.remove("/tmp/ssr-update." .. type)
  166. end
  167. if args then
  168. if args == "gfw_data" then
  169. update(uci:get_first("shadowsocksr", "global", "gfwlist_url"), "/etc/ssrplus/gfw_list.conf", args, TMP_DNSMASQ_PATH .. "/gfw_list.conf")
  170. os.exit(0)
  171. end
  172. if args == "ip_data" then
  173. update(uci:get_first("shadowsocksr", "global", "chnroute_url"), "/etc/ssrplus/china_ssr.txt", args, TMP_PATH .. "/china_ssr.txt")
  174. os.exit(0)
  175. end
  176. if args == "ad_data" then
  177. update(uci:get_first("shadowsocksr", "global", "adblock_url"), "/etc/ssrplus/ad.conf", args, TMP_DNSMASQ_PATH .. "/ad.conf")
  178. os.exit(0)
  179. end
  180. if args == "nfip_data" then
  181. update(uci:get_first("shadowsocksr", "global", "nfip_url"), "/etc/ssrplus/netflixip.list", args)
  182. os.exit(0)
  183. end
  184. else
  185. log("正在更新【GFW列表】数据库")
  186. update(uci:get_first("shadowsocksr", "global", "gfwlist_url"), "/etc/ssrplus/gfw_list.conf", "gfw_data", TMP_DNSMASQ_PATH .. "/gfw_list.conf")
  187. log("正在更新【国内IP段】数据库")
  188. update(uci:get_first("shadowsocksr", "global", "chnroute_url"), "/etc/ssrplus/china_ssr.txt", "ip_data", TMP_PATH .. "/china_ssr.txt")
  189. if uci:get_first("shadowsocksr", "global", "adblock", "0") == "1" then
  190. log("正在更新【广告屏蔽】数据库")
  191. update(uci:get_first("shadowsocksr", "global", "adblock_url"), "/etc/ssrplus/ad.conf", "ad_data", TMP_DNSMASQ_PATH .. "/ad.conf")
  192. end
  193. -- log("正在更新【Netflix IP段】数据库")
  194. -- update(uci:get_first("shadowsocksr", "global", "nfip_url"), "/etc/ssrplus/netflixip.list", "nfip_data")
  195. end