command_fastdl.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. #!/bin/bash
  2. # LinuxGSM command_fastdl.sh module
  3. # Author: Daniel Gibbs
  4. # Contributors: https://linuxgsm.com/contrib
  5. # Website: https://linuxgsm.com
  6. # Description: Creates a Fastdl directory.
  7. commandname="FASTDL"
  8. commandaction="Fastdl"
  9. moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
  10. fn_firstcommand_set
  11. # Directories.
  12. if [ -z "${webdir}" ]; then
  13. webdir="${rootdir}/public_html"
  14. fi
  15. fastdldir="${webdir}/fastdl"
  16. addonsdir="${systemdir}/addons"
  17. # Server lua autorun dir, used to autorun lua on client connect to the server.
  18. luasvautorundir="${systemdir}/lua/autorun/server"
  19. luafastdlfile="lgsm_cl_force_fastdl.lua"
  20. luafastdlfullpath="${luasvautorundir}/${luafastdlfile}"
  21. # Header
  22. fn_print_header
  23. fn_print_nl "More info: ${italic}https://docs.linuxgsm.com/commands/fastdl"
  24. fn_print_nl ""
  25. # Prompts user for Fastdl creation settings.
  26. fn_print_nl "${bold}${lightyellow}${commandaction} Setup"
  27. fn_messages_separator
  28. # Prompt for clearing old files if directory was already here.
  29. if [ -d "${fastdldir}" ]; then
  30. fn_print_warning_nl "Fastdl directory already exists."
  31. fn_print_nl "${fastdldir}"
  32. fn_print_nl ""
  33. if fn_prompt_yn "Overwrite existing directory?" Y; then
  34. fn_script_log_info "Overwrite existing directory: YES"
  35. else
  36. core_exit.sh
  37. fi
  38. fi
  39. # Garry's Mod Specific.
  40. if [ "${shortname}" == "gmod" ]; then
  41. # Prompt for download enforcer, which is using a .lua addfile resource generator.
  42. if fn_prompt_yn "Force clients to download files?" Y; then
  43. luaresource="on"
  44. fn_script_log_info "Force clients to download files: YES"
  45. else
  46. luaresource="off"
  47. fn_script_log_info "Force clients to download filesr: NO"
  48. fi
  49. fi
  50. # Clears any fastdl directory content.
  51. fn_clear_old_fastdl() {
  52. # Clearing old Fastdl.
  53. if [ -d "${fastdldir}" ]; then
  54. fn_print "clearing existing Fastdl directory ${fastdldir}"
  55. rm -rf "${fastdldir:?}"
  56. exitcode=$?
  57. if [ "${exitcode}" -ne 0 ]; then
  58. fn_print_fail_eol_nl
  59. fn_script_log_fail "Clearing existing Fastdl directory ${fastdldir}"
  60. core_exit.sh
  61. else
  62. fn_print_ok_eol_nl
  63. fn_script_log_pass "Clearing existing Fastdl directory ${fastdldir}"
  64. fi
  65. fi
  66. }
  67. fn_fastdl_dirs() {
  68. # Check and create directories.
  69. if [ ! -d "${webdir}" ]; then
  70. fn_print "creating web directory ${webdir}"
  71. mkdir -p "${webdir}"
  72. exitcode=$?
  73. if [ "${exitcode}" -ne 0 ]; then
  74. fn_print_fail_eol_nl
  75. fn_script_log_fail "Creating web directory ${webdir}"
  76. core_exit.sh
  77. else
  78. fn_print_ok_eol_nl
  79. fn_script_log_pass "Creating web directory ${webdir}"
  80. fi
  81. fi
  82. if [ ! -d "${fastdldir}" ]; then
  83. fn_print "creating fastdl directory ${fastdldir}"
  84. mkdir -p "${fastdldir}"
  85. exitcode=$?
  86. if [ "${exitcode}" -ne 0 ]; then
  87. fn_print_fail_eol_nl
  88. fn_script_log_fail "Creating fastdl directory ${fastdldir}"
  89. core_exit.sh
  90. else
  91. fn_print_ok_eol_nl
  92. fn_script_log_pass "Creating fastdl directory ${fastdldir}"
  93. fi
  94. fi
  95. }
  96. # Using this gist https://gist.github.com/agunnerson-ibm/efca449565a3e7356906
  97. fn_human_readable_file_size() {
  98. local abbrevs=(
  99. "1152921504606846976:ZB"
  100. "1125899906842624:EB"
  101. "1099511627776:TB"
  102. "1073741824:GB"
  103. "1048576:MB"
  104. "1024:KB"
  105. "1:bytes"
  106. )
  107. local bytes="${1}"
  108. local precision="${2}"
  109. if [[ "${bytes}" == "1" ]]; then
  110. fn_print_nl "1 byte"
  111. else
  112. for item in "${abbrevs[@]}"; do
  113. local factor="${item%:*}"
  114. local abbrev="${item#*:}"
  115. if [[ "${bytes}" -ge "${factor}" ]]; then
  116. size=$(bc -l <<< "${bytes} / ${factor}")
  117. printf "%.*f %s\n" "${precision}" "${size}" "${abbrev}"
  118. break
  119. fi
  120. done
  121. fi
  122. }
  123. # Sets the GoldSrc file types to include for the current directory.
  124. fn_fastdl_goldsrc_extensions() {
  125. fastdl_find_maxdepth=()
  126. if [ "${directory}" == "." ]; then
  127. allowed_extentions_array=("*.wad")
  128. fastdl_find_maxdepth=("-maxdepth" "1")
  129. elif [ "${directory}" == "maps" ]; then
  130. allowed_extentions_array=("*.bsp" "*.res" "*.txt")
  131. elif [ "${directory}" == "models" ]; then
  132. allowed_extentions_array=("*.mdl")
  133. elif [ "${directory}" == "sound" ]; then
  134. allowed_extentions_array=("*.wav")
  135. elif [ "${directory}" == "sprites" ]; then
  136. allowed_extentions_array=("*.spr" "*.txt")
  137. elif [ "${directory}" == "gfx" ]; then
  138. allowed_extentions_array=("*.tga" "*.bmp")
  139. elif [ "${directory}" == "overviews" ]; then
  140. allowed_extentions_array=("*.bmp" "*.tga" "*.txt")
  141. fi
  142. }
  143. # Provides info about the fastdl directory content and prompts for confirmation.
  144. fn_fastdl_preview() {
  145. # Remove any file list.
  146. if [ -f "${tmpdir}/fastdl_files_to_compress.txt" ]; then
  147. rm -f "${tmpdir:?}/fastdl_files_to_compress.txt"
  148. fi
  149. fn_print_nl "analysing required files"
  150. fn_script_log_info "Analysing required files"
  151. # Garry's Mod
  152. if [ "${shortname}" == "gmod" ]; then
  153. cd "${systemdir}" || exit
  154. allowed_extentions_array=("*.ain" "*.bsp" "*.mdl" "*.mp3" "*.ogg" "*.otf" "*.pcf" "*.phy" "*.png" "*.svg" "*.vtf" "*.vmt" "*.vtx" "*.vvd" "*.ttf" "*.wav")
  155. for allowed_extention in "${allowed_extentions_array[@]}"; do
  156. fileswc=0
  157. tput sc
  158. while read -r ext; do
  159. ((fileswc++))
  160. tput rc
  161. tput el
  162. fn_print "gathering ${allowed_extention} : ${fileswc}"
  163. echo -e "${ext}" >> "${tmpdir}/fastdl_files_to_compress.txt"
  164. done < <(find . -type f -iname "${allowed_extention}")
  165. if [ ${fileswc} != 0 ]; then
  166. fn_print_ok_eol_nl
  167. else
  168. fn_print_skip_eol_nl
  169. fi
  170. done
  171. # Source and GoldSrc engines
  172. else
  173. if [ "${engine}" == "goldsrc" ]; then
  174. fastdl_directories_array=("." "maps" "models" "sound" "sprites" "gfx" "overviews")
  175. else
  176. fastdl_directories_array=("maps" "materials" "models" "particles" "sound" "resource")
  177. fi
  178. for directory in "${fastdl_directories_array[@]}"; do
  179. if [ -d "${systemdir}/${directory}" ]; then
  180. if [ "${engine}" == "goldsrc" ]; then
  181. fn_fastdl_goldsrc_extensions
  182. elif [ "${directory}" == "maps" ]; then
  183. local allowed_extentions_array=("*.bsp" "*.ain" "*.nav" "*.jpg" "*.txt")
  184. elif [ "${directory}" == "materials" ]; then
  185. local allowed_extentions_array=("*.vtf" "*.vmt" "*.vbf" "*.png" "*.svg")
  186. elif [ "${directory}" == "models" ]; then
  187. local allowed_extentions_array=("*.vtx" "*.vvd" "*.mdl" "*.phy" "*.jpg" "*.png" "*.vmt" "*.vtf")
  188. elif [ "${directory}" == "particles" ]; then
  189. local allowed_extentions_array=("*.pcf")
  190. elif [ "${directory}" == "sound" ]; then
  191. local allowed_extentions_array=("*.wav" "*.mp3" "*.ogg")
  192. elif [ "${directory}" == "resource" ]; then
  193. local allowed_extentions_array=("*")
  194. fi
  195. for allowed_extention in "${allowed_extentions_array[@]}"; do
  196. fileswc=0
  197. tput sc
  198. while read -r ext; do
  199. ((fileswc++))
  200. tput rc
  201. tput el
  202. fn_print "gathering ${directory} ${allowed_extention} : ${fileswc}"
  203. echo -e "${ext}" >> "${tmpdir}/fastdl_files_to_compress.txt"
  204. done < <(find "${systemdir}/${directory}" "${fastdl_find_maxdepth[@]}" -type f -iname "${allowed_extention}")
  205. tput rc
  206. tput el
  207. fn_print "gathering ${directory} ${allowed_extention} : ${fileswc}"
  208. if [ ${fileswc} != 0 ]; then
  209. fn_print_ok_eol_nl
  210. else
  211. fn_print_info_eol_nl
  212. fi
  213. done
  214. fi
  215. done
  216. fi
  217. if [ -f "${tmpdir}/fastdl_files_to_compress.txt" ]; then
  218. fn_print_nl "calculating total file size"
  219. fn_sleep_time_1
  220. totalfiles=$(wc -l < "${tmpdir}/fastdl_files_to_compress.txt")
  221. # Calculates total file size.
  222. while read -r dufile; do
  223. filesize=$(stat -c %s "${dufile}")
  224. filesizetotal=$((filesizetotal + filesize))
  225. exitcode=$?
  226. if [ "${exitcode}" -ne 0 ]; then
  227. fn_print_fail_eol_nl
  228. fn_script_log_fail "Calculating total file size"
  229. core_exit.sh
  230. fi
  231. done < "${tmpdir}/fastdl_files_to_compress.txt"
  232. else
  233. fn_print_fail_eol_nl "generating file list"
  234. fn_script_log_fail "Generating file list."
  235. core_exit.sh
  236. fi
  237. if [ "${engine}" == "source" ]; then
  238. echo -e "about to compress ${totalfiles} files, total size $(fn_human_readable_file_size "${filesizetotal}" 0)"
  239. elif [ "${engine}" == "goldsrc" ]; then
  240. echo -e "about to copy ${totalfiles} files, total size $(fn_human_readable_file_size "${filesizetotal}" 0)"
  241. fi
  242. fn_script_log_info "${totalfiles} files, total size $(fn_human_readable_file_size "${filesizetotal}" 0)"
  243. rm -f "${tmpdir:?}/fastdl_files_to_compress.txt"
  244. if ! fn_prompt_yn "Continue?" Y; then
  245. exitcode=0
  246. core_exit.sh
  247. fi
  248. }
  249. # Builds Garry's Mod fastdl directory content.
  250. fn_fastdl_gmod() {
  251. cd "${systemdir}" || exit
  252. for allowed_extention in "${allowed_extentions_array[@]}"; do
  253. fileswc=0
  254. tput sc
  255. while read -r fastdlfile; do
  256. ((fileswc++))
  257. tput rc
  258. tput el
  259. fn_print "copying ${allowed_extention} : ${fileswc}"
  260. cp --parents "${fastdlfile}" "${fastdldir}"
  261. exitcode=$?
  262. if [ "${exitcode}" -ne 0 ]; then
  263. fn_print_fail_eol_nl
  264. fn_script_log_fail "Copying ${fastdlfile} > ${fastdldir}"
  265. core_exit.sh
  266. else
  267. fn_script_log_pass "Copying ${fastdlfile} > ${fastdldir}"
  268. fi
  269. done < <(find . -type f -iname "${allowed_extention}")
  270. if [ ${fileswc} != 0 ]; then
  271. fn_print_ok_eol_nl
  272. fi
  273. done
  274. # Correct addons directory structure for Fastdl.
  275. if [ -d "${fastdldir}/addons" ]; then
  276. fn_print "updating addons file structure..."
  277. cp -Rf "${fastdldir}"/addons/*/* "${fastdldir}"
  278. exitcode=$?
  279. if [ "${exitcode}" -ne 0 ]; then
  280. fn_print_fail_eol_nl
  281. fn_script_log_fail "Updating addons file structure"
  282. core_exit.sh
  283. else
  284. fn_print_ok_eol_nl
  285. fn_script_log_pass "Updating addons file structure"
  286. fi
  287. # Clear addons directory in fastdl.
  288. fn_print "clearing addons dir from fastdl dir..."
  289. fn_sleep_time_1
  290. rm -rf "${fastdldir:?}/addons"
  291. exitcode=$?
  292. if [ "${exitcode}" -ne 0 ]; then
  293. fn_print_fail_eol_nl
  294. fn_script_log_fail "Clearing addons dir from fastdl dir"
  295. core_exit.sh
  296. else
  297. fn_print_ok_eol_nl
  298. fn_script_log_pass "Clearing addons dir from fastdl dir"
  299. fi
  300. fi
  301. # Correct content that may be into a lua directory by mistake like some darkrpmodification addons.
  302. if [ -d "${fastdldir}/lua" ]; then
  303. fn_print "correcting DarkRP files..."
  304. fn_sleep_time_1
  305. cp -Rf "${fastdldir}/lua/"* "${fastdldir}"
  306. exitcode=$?
  307. if [ "${exitcode}" -ne 0 ]; then
  308. fn_print_fail_eol_nl
  309. fn_script_log_fail "Correcting DarkRP files"
  310. core_exit.sh
  311. else
  312. fn_print_ok_eol_nl
  313. fn_script_log_pass "Correcting DarkRP files"
  314. fi
  315. fi
  316. if [ -f "${tmpdir}/fastdl_files_to_compress.txt" ]; then
  317. totalfiles=$(wc -l < "${tmpdir}/fastdl_files_to_compress.txt")
  318. # Calculates total file size.
  319. while read -r dufile; do
  320. filesize=$(du -b "${dufile}" | awk '{ print $1 }')
  321. filesizetotal=$((filesizetotal + filesize))
  322. done < "${tmpdir}/fastdl_files_to_compress.txt"
  323. fi
  324. }
  325. fn_fastdl_source() {
  326. for directory in "${fastdl_directories_array[@]}"; do
  327. if [ -d "${systemdir}/${directory}" ]; then
  328. if [ "${engine}" == "goldsrc" ]; then
  329. fn_fastdl_goldsrc_extensions
  330. elif [ "${directory}" == "maps" ]; then
  331. local allowed_extentions_array=("*.bsp" "*.ain" "*.nav" "*.jpg" "*.txt")
  332. elif [ "${directory}" == "materials" ]; then
  333. local allowed_extentions_array=("*.vtf" "*.vmt" "*.vbf" "*.png" "*.svg")
  334. elif [ "${directory}" == "models" ]; then
  335. local allowed_extentions_array=("*.vtx" "*.vvd" "*.mdl" "*.phy" "*.jpg" "*.png")
  336. elif [ "${directory}" == "particles" ]; then
  337. local allowed_extentions_array=("*.pcf")
  338. elif [ "${directory}" == "sound" ]; then
  339. local allowed_extentions_array=("*.wav" "*.mp3" "*.ogg")
  340. elif [ "${directory}" == "resource" ]; then
  341. local allowed_extentions_array=("*")
  342. fi
  343. for allowed_extention in "${allowed_extentions_array[@]}"; do
  344. fileswc=0
  345. tput sc
  346. while read -r fastdlfile; do
  347. ((fileswc++))
  348. tput rc
  349. tput el
  350. fn_print "copying ${directory} ${allowed_extention} : ${fileswc}"
  351. fn_sleep_time
  352. # get relative path of file in the dir
  353. tmprelfilepath="${fastdlfile#"${systemdir}/"}"
  354. copytodir="${tmprelfilepath%/*}"
  355. # create relative path for fastdl
  356. if [ ! -d "${fastdldir}/${copytodir}" ]; then
  357. mkdir -p "${fastdldir}/${copytodir}"
  358. fi
  359. cp "${fastdlfile}" "${fastdldir}/${copytodir}"
  360. exitcode=$?
  361. if [ "${exitcode}" -ne 0 ]; then
  362. fn_print_fail_eol_nl
  363. fn_script_log_fail "Copying ${fastdlfile} > ${fastdldir}/${copytodir}"
  364. core_exit.sh
  365. else
  366. fn_script_log_pass "Copying ${fastdlfile} > ${fastdldir}/${copytodir}"
  367. fi
  368. done < <(find "${systemdir}/${directory}" "${fastdl_find_maxdepth[@]}" -type f -iname "${allowed_extention}")
  369. if [ ${fileswc} != 0 ]; then
  370. fn_print_ok_eol_nl
  371. fi
  372. done
  373. fi
  374. done
  375. }
  376. # Builds the fastdl directory content.
  377. fn_fastdl_build() {
  378. # Copy all needed files for Fastdl.
  379. fn_print_nl "copying files to ${fastdldir}"
  380. fn_script_log_info "Copying files to ${fastdldir}"
  381. if [ "${shortname}" == "gmod" ]; then
  382. fn_fastdl_gmod
  383. fn_fastdl_gmod_dl_enforcer
  384. else
  385. fn_fastdl_source
  386. fi
  387. }
  388. # Generate lua file that will force download any file into the Fastdl directory.
  389. fn_fastdl_gmod_dl_enforcer() {
  390. # Clear old lua file.
  391. if [ -f "${luafastdlfullpath}" ]; then
  392. fn_print "removing existing download enforcer: ${luafastdlfile}"
  393. rm -f "${luafastdlfullpath:?}"
  394. exitcode=$?
  395. if [ "${exitcode}" -ne 0 ]; then
  396. fn_print_fail_eol_nl
  397. fn_script_log_fail "Removing existing download enforcer ${luafastdlfullpath}"
  398. core_exit.sh
  399. else
  400. fn_print_ok_eol_nl
  401. fn_script_log_pass "Removing existing download enforcer ${luafastdlfullpath}"
  402. fi
  403. fi
  404. # Generate new one if user said yes.
  405. if [ "${luaresource}" == "on" ]; then
  406. fn_print "creating new download enforcer: ${luafastdlfile}"
  407. touch "${luafastdlfullpath}"
  408. # Read all filenames and put them into a lua file at the right path.
  409. while read -r line; do
  410. echo -e "resource.AddFile( \"${line}\" )" >> "${luafastdlfullpath}"
  411. done < <(find "${fastdldir:?}" \( -type f ! -name "*.bz2" \) -printf '%P\n')
  412. exitcode=$?
  413. if [ "${exitcode}" -ne 0 ]; then
  414. fn_print_fail_eol_nl
  415. fn_script_log_fail "Creating new download enforcer ${luafastdlfullpath}"
  416. core_exit.sh
  417. else
  418. fn_print_ok_eol_nl
  419. fn_script_log_pass "Creating new download enforcer ${luafastdlfullpath}"
  420. fi
  421. fi
  422. }
  423. # Compresses Fastdl files using bzip2.
  424. fn_fastdl_bzip2() {
  425. while read -r filetocompress; do
  426. fn_print "compressing ${filetocompress}"
  427. bzip2 -f "${filetocompress}"
  428. exitcode=$?
  429. if [ "${exitcode}" -ne 0 ]; then
  430. fn_print_fail_eol_nl
  431. fn_script_log_fail "Compressing ${filetocompress}"
  432. core_exit.sh
  433. else
  434. fn_print_ok_eol_nl
  435. fn_script_log_pass "Compressing ${filetocompress}"
  436. fi
  437. done < <(find "${fastdldir:?}" \( -type f ! -name "*.bz2" \))
  438. }
  439. check.sh
  440. # Run functions.
  441. fn_fastdl_preview
  442. fn_clear_old_fastdl
  443. fn_fastdl_dirs
  444. fn_fastdl_build
  445. if [ "${engine}" == "source" ]; then
  446. fn_fastdl_bzip2
  447. fi
  448. # Finished message.
  449. fn_print_nl "Fastdl files are located in:"
  450. fn_print_nl "${fastdldir}"
  451. fn_print_nl "Fastdl completed"
  452. fn_script_log_info "Fastdl completed"
  453. core_exit.sh