ttsselfhoster.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #!/usr/bin/env python3
  2. def main():
  3. import os
  4. import json
  5. import re
  6. import sys
  7. from urllib.parse import urlparse
  8. p = parser()
  9. args = p.parse_args()
  10. if args.input_file == "-":
  11. args.input_file = "/dev/stdin"
  12. with open(args.input_file) as fd:
  13. js = json.load(fd)
  14. jsgen = dict_generator(js)
  15. url_regex = re.compile("^https?://")
  16. for it in jsgen:
  17. val = it[-1]
  18. if type(val)==str and url_regex.match(val):
  19. # print(it, file=sys.stderr)
  20. if args.server_dir:
  21. sha_f = cache_file(val, args.server_dir, force=args.no_cache)
  22. # print(sha_f, file=sys.stderr)
  23. if args.url and sha_f:
  24. newurl = args.url
  25. newurl = newurl._replace(path=os.path.join(newurl.path,"blocks", sha_f))
  26. dict_set(js, it[:-1], newurl.geturl())
  27. if args.output_file == None:
  28. if "SaveName" in js:
  29. args.output_file = os.path.join(args.server_dir, safe_name(js["SaveName"]) + ".json")
  30. else:
  31. if args.input_file[:4] == "/dev":
  32. args.output_file = os.path.join(args.server_dir , os.path.basename(args.input_file))
  33. else:
  34. args.output_file = "-"
  35. if args.output_file == "-":
  36. args.output_file = "/dev/stdout"
  37. with open(args.output_file, "w") as fd:
  38. json.dump(js, fd, indent=4)
  39. def parser():
  40. import argparse
  41. from urllib.parse import urlparse
  42. p = argparse.ArgumentParser()
  43. p.add_argument("-i","--input_file", default="-")
  44. p.add_argument("-o","--output_file", default=None)
  45. p.add_argument("-s","--server_dir", default="repo")
  46. p.add_argument("-n","--no_cache", action="store_true")
  47. p.add_argument("-u","--url", type=urlparse, default=None)
  48. return p
  49. def dict_set(dic , path, val):
  50. iter_dic = dic
  51. for p in path:
  52. last_dic = iter_dic
  53. iter_dic = iter_dic[p]
  54. last_dic[p] = val
  55. def safe_name(fname):
  56. import re
  57. fname = fname.replace(" ","_")
  58. return re.sub("[^a-zA-Z0-9_]+", "", fname)
  59. def cache_file(url, cache_dir, force=False):
  60. import os
  61. import hashlib
  62. import json
  63. import sys
  64. sha_url = hashlib.sha512()
  65. sha_url.update(url.encode())
  66. sha_url = sha_url.hexdigest()
  67. sha_dir = os.path.join(cache_dir, "sha")
  68. sha_file = os.path.join(sha_dir, sha_url)
  69. url_file = os.path.join(cache_dir, "urls.txt")
  70. if not os.path.isdir(sha_dir):
  71. os.makedirs(sha_dir)
  72. sha_f = None
  73. if force or (not os.path.isfile(sha_file)):
  74. sha_f = get_file(url, cache_dir, sha_file)
  75. if sha_f:
  76. with open(url_file, "w+") as fd:
  77. for line in fd.readlines():
  78. if json.loads(line)["sha_f"] == sha_f:
  79. return sha_f
  80. new_line = json.dumps({"url":url,"sha_f":sha_f,"sha_url":sha_url})+"\n"
  81. print(new_line, file=sys.stderr)
  82. fd.write(new_line)
  83. else:
  84. print("Download Error:", url, file=sys.stderr)
  85. else:
  86. try:
  87. # print("Trying Cache:", sha_file, file=sys.stderr)
  88. sha_f = open(sha_file).read()
  89. except Exception as ex:
  90. print(ex, file=sys.stderr)
  91. sha_f = None
  92. return sha_f
  93. def get_file(url, cache_dir, sha_file):
  94. from urllib.request import urlopen
  95. from urllib.error import HTTPError
  96. import hashlib
  97. import sys
  98. import os
  99. import uuid
  100. blocks_dir = os.path.join(cache_dir,"blocks")
  101. if not os.path.isdir(blocks_dir):
  102. os.makedirs(blocks_dir)
  103. tmpfile = os.path.join(blocks_dir, uuid.uuid4().hex)
  104. sha_f = hashlib.sha512()
  105. try:
  106. with urlopen(url) as req:
  107. with open(tmpfile,"wb") as fd:
  108. BUF = True
  109. while BUF:
  110. BUF = req.read()
  111. fd.write(BUF)
  112. sha_f.update(BUF)
  113. except HTTPError as ex:
  114. print(ex, file=sys.stderr)
  115. try:
  116. os.unlink(tmpfile)
  117. os.unlink(sha_file)
  118. except:
  119. pass
  120. return None
  121. sha_f = sha_f.hexdigest()
  122. cachefile = os.path.join(blocks_dir, sha_f)
  123. os.rename(tmpfile, cachefile)
  124. with open(sha_file, "w") as fd:
  125. fd.write(sha_f)
  126. return sha_f
  127. def dict_generator(indict, pre=None):
  128. pre = pre[:] if pre else []
  129. if isinstance(indict, dict):
  130. for key, value in indict.items():
  131. if isinstance(value, dict):
  132. for d in dict_generator(value, pre + [key]):
  133. yield d
  134. elif isinstance(value, list) or isinstance(value, tuple):
  135. i = 0
  136. for v in value:
  137. for d in dict_generator(v, pre + [key,i]):
  138. yield d
  139. i += 1
  140. else:
  141. yield pre + [key, value]
  142. else:
  143. yield pre + [indict]
  144. if __name__ == "__main__":
  145. main()