ocr.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. import os
  2. from sys import exit as exx
  3. import time
  4. import uuid
  5. import re
  6. from subprocess import Popen,PIPE
  7. HOME = os.path.expanduser("~")
  8. CWD = os.getcwd()
  9. tokens = {}
  10. class ngrok:
  11. def __init__(self, TOKEN=None, USE_FREE_TOKEN=True,
  12. service=[['Service1', 80, 'tcp'], ['Service2', 8080, 'tcp']],
  13. region='us',
  14. dBug=[f"{HOME}/.ngrok2/ngrok.yml", 4040]):
  15. self.region = region
  16. self.configPath, self.dport = dBug
  17. self.TOKEN = TOKEN
  18. self.USE_FREE_TOKEN = USE_FREE_TOKEN
  19. self.service = service
  20. if USE_FREE_TOKEN:
  21. self.sdict = {}
  22. for i, sn in enumerate(service):
  23. tempcP = f'{HOME}/.ngrok2/'+sn[0]+'.yml'
  24. # Port, Protocol, config path
  25. self.sdict[sn[0]] = [self.dport+i, sn[2], tempcP]
  26. def nameport(self, TOKEN, AUTO):
  27. if AUTO:
  28. try:
  29. return tokens.popitem()[1]
  30. except KeyError:
  31. return "Invalid Token"
  32. elif not TOKEN:
  33. if not 'your' in tokens.keys():
  34. from IPython import get_ipython
  35. from IPython.display import clear_output
  36. ipython = get_ipython()
  37. print(r"Copy authtoken from https://dashboard.ngrok.com/auth")
  38. __temp = ipython.magic('%sx read -p "Token :"')
  39. tokens['your'] = __temp[0].split(':')[1]
  40. USR_Api = "your"
  41. clear_output()
  42. else:
  43. USR_Api = "your"
  44. else:
  45. USR_Api = "mind"
  46. tokens["mind"] = TOKEN
  47. return tokens[USR_Api]
  48. def ngrok_config(self, token, Gport, configPath, region, service):
  49. import os
  50. data = """
  51. region: {}
  52. update: false
  53. update_channel: stable
  54. web_addr: localhost:{}
  55. tunnels:\n""".format(region, Gport)
  56. if not self.USE_FREE_TOKEN:
  57. auth ="""
  58. authtoken: {}""".format(token)
  59. data = auth+data
  60. tunnels = ""
  61. for S in service:
  62. Sn, Sp, SpC = S
  63. tunnels += """ {}:
  64. addr: {}
  65. proto: {}
  66. inspect: false\n""".format(Sn, Sp, SpC)
  67. data = data + tunnels
  68. os.makedirs(f'{HOME}/.ngrok2/', exist_ok=True)
  69. with open(configPath, "w+") as configFile:
  70. configFile.write(data)
  71. return True
  72. def startWebUi(self, token, dport, nServer, region, btc, configPath,
  73. displayB, service, v):
  74. import os, time, urllib
  75. from IPython.display import clear_output
  76. from json import loads
  77. if token == "Invalid Token":
  78. print(tokens)
  79. os.exit()
  80. installNgrok()
  81. if v:
  82. clear_output()
  83. loadingAn(name="lds")
  84. textAn("Starting ngrok ...", ty='twg')
  85. if self.USE_FREE_TOKEN:
  86. for sn in service:
  87. self.ngrok_config(
  88. token,
  89. self.sdict[nServer][0],
  90. self.sdict[nServer][2],
  91. region,
  92. service)
  93. if sn[0] == nServer:
  94. runSh(f"ngrok {sn[2]} -config={self.sdict[nServer][2]} {sn[1]} &", shell=True)
  95. else:
  96. self.ngrok_config(token, dport, configPath, region, service)
  97. runSh(f"ngrok start --config {configPath} --all &", shell=True)
  98. time.sleep(3)
  99. try:
  100. if self.USE_FREE_TOKEN:
  101. dport = self.sdict[nServer][0]
  102. nServer = 'command_line'
  103. host = urllib.request.urlopen(f"http://localhost:{dport}/api/tunnels")
  104. else:
  105. host = urllib.request.urlopen(f"http://localhost:{dport}/api/tunnels")
  106. host = loads(host.read())['tunnels']
  107. for h in host:
  108. if h['name'] == nServer:
  109. host = h['public_url'][8:]
  110. break
  111. except urllib.error.URLError:
  112. if v:
  113. clear_output()
  114. loadingAn(name="lds")
  115. textAn("Ngrok Token is in used!. Again trying token ...", ty='twg')
  116. time.sleep(2)
  117. return True
  118. data = {"url": f"https://{host}"}
  119. if displayB:
  120. displayUrl(data, btc)
  121. return data
  122. def start(self, nServer, btc='b', displayB=True, v=True):
  123. import urllib
  124. from IPython.display import clear_output
  125. from json import loads
  126. try:
  127. nServerbk = nServer
  128. if self.USE_FREE_TOKEN:
  129. dport = self.sdict[nServer][0]
  130. nServer = 'command_line'
  131. else:
  132. dport = self.dport
  133. host = urllib.request.urlopen(f"http://localhost:{dport}/api/tunnels")
  134. host = loads(host.read())['tunnels']
  135. for h in host:
  136. if h['name'] == nServer:
  137. host = h['public_url'][8:]
  138. data = {"url": f"https://{host}"}
  139. if displayB:
  140. displayUrl(data, btc)
  141. return data
  142. raise Exception('Not found tunnels')
  143. except urllib.error.URLError:
  144. for run in range(10):
  145. if v:
  146. clear_output()
  147. loadingAn(name='lds')
  148. dati = self.startWebUi(
  149. self.nameport(self.TOKEN, self.USE_FREE_TOKEN) if not self.USE_FREE_TOKEN else {},
  150. self.dport,
  151. nServerbk,
  152. self.region,
  153. btc,
  154. self.configPath,
  155. displayB,
  156. self.service,
  157. v
  158. )
  159. if dati == True:
  160. continue
  161. return dati
  162. def checkAvailable(path_="", userPath=False):
  163. from os import path as _p
  164. if path_ == "":
  165. return False
  166. else:
  167. return (
  168. _p.exists(path_)
  169. if not userPath
  170. else _p.exists(f"/usr/local/sessionSettings/{path_}")
  171. )
  172. def accessSettingFile(file="", setting={}, v=True):
  173. from json import load, dump
  174. if not isinstance(setting, dict):
  175. if v:print("Only accept Dictionary object.")
  176. exx()
  177. fullPath = f"/usr/local/sessionSettings/{file}"
  178. try:
  179. if not len(setting):
  180. if not checkAvailable(fullPath):
  181. if v:print(f"File unavailable: {fullPath}.")
  182. exx()
  183. with open(fullPath) as jsonObj:
  184. return load(jsonObj)
  185. else:
  186. with open(fullPath, "w+") as outfile:
  187. dump(setting, outfile)
  188. except:
  189. if v:print(f"Error accessing the file: {fullPath}.")
  190. def displayUrl(data, btc='b', pNamU='Public URL: ', EcUrl=None, ExUrl=None, cls=True):
  191. from IPython.display import HTML, clear_output
  192. if cls:
  193. clear_output()
  194. showTxT = f'{pNamU}{data["url"]}'
  195. if EcUrl:
  196. showUrL = data["url"]+EcUrl
  197. elif ExUrl:
  198. showUrL = ExUrl
  199. else:
  200. showUrL = data["url"]
  201. if btc == 'b':
  202. # blue
  203. bttxt = 'hsla(210, 50%, 85%, 1)'
  204. btcolor = 'hsl(210, 80%, 42%)'
  205. btshado = 'hsla(210, 40%, 52%, .4)'
  206. elif btc == 'g':
  207. # green
  208. bttxt = 'hsla(110, 50%, 85%, 1)'
  209. btcolor = 'hsla(110, 86%, 56%, 1)'
  210. btshado = 'hsla(110, 40%, 52%, .4)'
  211. elif btc == 'r':
  212. # red
  213. bttxt = 'hsla(10, 50%, 85%, 1)'
  214. btcolor = 'hsla(10, 86%, 56%, 1)'
  215. btshado = 'hsla(10, 40%, 52%, .4)'
  216. return display(HTML('''<style>@import url('https://fonts.googleapis.com/css?family=Source+Code+Pro:200,900'); :root { --text-color: '''+bttxt+'''; --shadow-color: '''+btshado+'''; --btn-color: '''+btcolor+'''; --bg-color: #141218; } * { box-sizing: border-box; } button { position:relative; padding: 10px 20px; border: none; background: none; cursor: pointer; font-family: "Source Code Pro"; font-weight: 900; font-size: 100%; color: var(--text-color); background-color: var(--btn-color); box-shadow: var(--shadow-color) 2px 2px 22px; border-radius: 4px; z-index: 0; overflow: hidden; } button:focus { outline-color: transparent; box-shadow: var(--btn-color) 2px 2px 22px; } .right::after, button::after { content: var(--content); display: block; position: absolute; white-space: nowrap; padding: 40px 40px; pointer-events:none; } button::after{ font-weight: 200; top: -30px; left: -20px; } .right, .left { position: absolute; width: 100%; height: 100%; top: 0; } .right { left: 66%; } .left { right: 66%; } .right::after { top: -30px; left: calc(-66% - 20px); background-color: var(--bg-color); color:transparent; transition: transform .4s ease-out; transform: translate(0, -90%) rotate(0deg) } button:hover .right::after { transform: translate(0, -47%) rotate(0deg) } button .right:hover::after { transform: translate(0, -50%) rotate(-7deg) } button .left:hover ~ .right::after { transform: translate(0, -50%) rotate(7deg) } /* bubbles */ button::before { content: ''; pointer-events: none; opacity: .6; background: radial-gradient(circle at 20% 35%, transparent 0, transparent 2px, var(--text-color) 3px, var(--text-color) 4px, transparent 4px), radial-gradient(circle at 75% 44%, transparent 0, transparent 2px, var(--text-color) 3px, var(--text-color) 4px, transparent 4px), radial-gradient(circle at 46% 52%, transparent 0, transparent 4px, var(--text-color) 5px, var(--text-color) 6px, transparent 6px); width: 100%; height: 300%; top: 0; left: 0; position: absolute; animation: bubbles 5s linear infinite both; } @keyframes bubbles { from { transform: translate(); } to { transform: translate(0, -66.666%); } } Resources</style><center><a href="'''+showUrL+'''" target="_blank"><div style="width: 700px; height: 80px; padding-top:15px"><button style='--content: "'''+showTxT+'''";'"> <div class="left"></div>'''+showTxT+'''<div class="right"></div> </div></button></a></center>'''))
  217. def findProcess(process, command="", isPid=False):
  218. from psutil import pids, Process
  219. if isinstance(process, int):
  220. if process in pids():
  221. return True
  222. else:
  223. for pid in pids():
  224. try:
  225. p = Process(pid)
  226. if process in p.name():
  227. for arg in p.cmdline():
  228. if command in str(arg):
  229. return True if not isPid else str(pid)
  230. else:
  231. pass
  232. else:
  233. pass
  234. except:
  235. continue
  236. def installArgoTunnel():
  237. if checkAvailable(f"{HOME}/tools/argotunnel/cloudflared"):
  238. return
  239. else:
  240. import os
  241. from shutil import unpack_archive
  242. from urllib.request import urlretrieve
  243. os.makedirs(f'{HOME}/tools/argotunnel/', exist_ok=True)
  244. aTURL = findPackageR("cloudflare/cloudflared", "cloudflared-linux-amd64")
  245. urlretrieve(aTURL, f'{HOME}/tools/argotunnel/cloudflared')
  246. # unpack_archive('cloudflared.tgz',
  247. # f'{HOME}/tools/argotunnel')
  248. os.chmod(f'{HOME}/tools/argotunnel/cloudflared', 0o755)
  249. # os.unlink('cloudflared.tgz')
  250. def installNgrok():
  251. if checkAvailable("/usr/local/bin/ngrok"):
  252. return
  253. else:
  254. import os
  255. from zipfile import ZipFile
  256. from urllib.request import urlretrieve
  257. ngURL = "https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip"
  258. urlretrieve(ngURL, 'ngrok-amd64.zip')
  259. with ZipFile('ngrok-amd64.zip', 'r') as zip_ref:
  260. zip_ref.extractall('/usr/local/bin/')
  261. os.chmod('/usr/local/bin/ngrok', 0o755)
  262. os.unlink('ngrok-amd64.zip')
  263. def installAutoSSH():
  264. if checkAvailable("/usr/bin/autossh"):
  265. return
  266. else:
  267. runSh("apt-get install autossh -qq -y")
  268. def runSh(args, *, output=False, shell=False, cd=None):
  269. import subprocess, shlex
  270. if not shell:
  271. if output:
  272. proc = subprocess.Popen(
  273. shlex.split(args), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=cd
  274. )
  275. while True:
  276. output = proc.stdout.readline()
  277. if output == b"" and proc.poll() is not None:
  278. return
  279. if output:
  280. print(output.decode("utf-8").strip())
  281. return subprocess.run(shlex.split(args), cwd=cd).returncode
  282. else:
  283. if output:
  284. return (
  285. subprocess.run(
  286. args,
  287. shell=True,
  288. stdout=subprocess.PIPE,
  289. stderr=subprocess.STDOUT,
  290. cwd=cd,
  291. )
  292. .stdout.decode("utf-8")
  293. .strip()
  294. )
  295. return subprocess.run(args, shell=True, cwd=cd).returncode
  296. def loadingAn(name="cal"):
  297. from IPython.display import HTML
  298. if name == "cal":
  299. return display(HTML('<style>.lds-ring { display: inline-block; position: relative; width: 34px; height: 34px; } .lds-ring div { box-sizing: border-box; display: block; position: absolute; width: 34px; height: 34px; margin: 4px; border: 5px solid #cef; border-radius: 50%; animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; border-color: #cef transparent transparent transparent; } .lds-ring div:nth-child(1) { animation-delay: -0.45s; } .lds-ring div:nth-child(2) { animation-delay: -0.3s; } .lds-ring div:nth-child(3) { animation-delay: -0.15s; } @keyframes lds-ring { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }</style><div class="lds-ring"><div></div><div></div><div></div><div></div></div>'))
  300. elif name == "lds":
  301. return display(HTML('''<style>.lds-hourglass { display: inline-block; position: relative; width: 34px; height: 34px;}.lds-hourglass:after { content: " "; display: block; border-radius: 50%; width: 34px; height: 34px; margin: 0px; box-sizing: border-box; border: 20px solid #dfc; border-color: #dfc transparent #dfc transparent; animation: lds-hourglass 1.2s infinite;}@keyframes lds-hourglass { 0% { transform: rotate(0); animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); } 50% { transform: rotate(900deg); animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); } 100% { transform: rotate(1800deg); }}</style><div class="lds-hourglass"></div>'''))
  302. def textAn(TEXT, ty='d'):
  303. from IPython.display import HTML
  304. if ty == 'd':
  305. return display(HTML('''<style>@import url(https://fonts.googleapis.com/css?family=Raleway:400,700,900,400italic,700italic,900italic);#wrapper { font: 17px 'Raleway', sans-serif;animation: text-shadow 1.5s ease-in-out infinite; margin-left: auto; margin-right: auto; }#container { display: flex; flex-direction: column; float: left; }@keyframes text-shadow { 0% 20% { transform: translateY(-0.1em); text-shadow: 0 0.1em 0 #0c2ffb, 0 0.1em 0 #2cfcfd, 0 -0.1em 0 #fb203b, 0 -0.1em 0 #fefc4b; } 40% { transform: translateY(0.1em); text-shadow: 0 -0.1em 0 #0c2ffb, 0 -0.1em 0 #2cfcfd, 0 0.1em 0 #fb203b, 0 0.1em 0 #fefc4b; } 60% { transform: translateY(-0.1em); text-shadow: 0 0.1em 0 #0c2ffb, 0 0.1em 0 #2cfcfd, 0 -0.1em 0 #fb203b, 0 -0.1em 0 #fefc4b; } }@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; }}</style><div id="wrapper"><div id="container">'''+TEXT+'''</div></div>'''))
  306. elif ty == 'twg':
  307. textcover = str(len(TEXT)*0.55)
  308. return display(HTML('''<style>@import url(https://fonts.googleapis.com/css?family=Anonymous+Pro);.line-1{font-family: 'Anonymous Pro', monospace; position: relative; border-right: 1px solid; font-size: 15px; white-space: nowrap; overflow: hidden; }.anim-typewriter{ animation: typewriter 0.4s steps(44) 0.2s 1 normal both, blinkTextCursor 600ms steps(44) infinite normal;}@keyframes typewriter{ from{width: 0;} to{width: '''+textcover+'''em;}}@keyframes blinkTextCursor{ from{border-right:2px;} to{border-right-color: transparent;}}</style><div class="line-1 anim-typewriter">'''+TEXT+'''</div>'''))
  309. class LocalhostRun:
  310. def __init__(self,port,id=None,interval=30,retries=30):
  311. import os
  312. filePath = "/usr/local/sessionSettings/localhostDB.json"
  313. if not os.path.exists(filePath):
  314. os.makedirs(filePath[:-16], exist_ok=True)
  315. open(filePath, 'w').close()
  316. installAutoSSH()
  317. if not id:id=str(uuid.uuid4())[:8]
  318. self.connection=None
  319. self.id=id
  320. self.port=port
  321. self.interval=interval
  322. self.retries=retries
  323. def start(self):
  324. if self.connection:self.connection.kill()
  325. self.connection=Popen(f"ssh -R 80:localhost:{self.port} {self.id}@ssh.localhost.run -o StrictHostKeyChecking=no".split(), stdout=PIPE, stdin=PIPE)
  326. try:
  327. return re.findall("http://(.*?.localhost.run)",self.connection.stdout.readline().decode("utf-8"))[0]
  328. except:
  329. raise Exception(self.connection.stdout.readline().decode("utf-8"))
  330. def keep_alive(self):
  331. # if self.connection:self.connection.kill()
  332. import urllib
  333. try:
  334. localhostOpenDB = dict(accessSettingFile("localhostDB.json", v=False))
  335. except TypeError:
  336. localhostOpenDB = dict()
  337. if findProcess("autossh", f"80:localhost:{self.port}"):
  338. try:
  339. oldAddr = localhostOpenDB[str(self.port)]
  340. urllib.request.urlopen("http://"+oldAddr)
  341. return oldAddr
  342. except:
  343. pass
  344. for _ in range(2):
  345. self.connection=Popen(f"autossh -R 80:localhost:{self.port} {self.id}@ssh.localhost.run -o StrictHostKeyChecking=no -o ServerAliveInterval={self.interval} -o ServerAliveCountMax={self.retries}".split(),
  346. stdout=PIPE, stdin=PIPE, stderr=PIPE)
  347. #print("ssh -R 80:localhost:{self.port} {self.id}@ssh.localhost.run -o StrictHostKeyChecking=no -o ServerAliveInterval={self.interval} -o ServerAliveCountMax={self.retries}")
  348. try:
  349. newAddr = re.findall("(.*?.localhost.run)", self.connection.stdout.readline().decode("utf-8"))[0]
  350. localhostOpenDB[str(self.port)] = newAddr
  351. accessSettingFile("localhostDB.json" , localhostOpenDB, v=False)
  352. return newAddr
  353. except:
  354. outs, errs = self.connection.communicate(timeout=15)
  355. self.connection.kill()
  356. # print(outs)
  357. # print(errs)
  358. if re.search(r"Permission\sdenied\s\(publickey\)", errs.decode("utf-8")):
  359. os.system("ssh-keygen -q -t rsa -N '' -f ~/.ssh/id_rsa")
  360. continue
  361. raise Exception(errs.decode("utf-8"))
  362. break
  363. def kill(self):
  364. self.connection.kill()
  365. class ArgoTunnel:
  366. def __init__(self, port, proto='http', metrics=49589, interval=30, retries=30):
  367. import os
  368. filePath = "/usr/local/sessionSettings/argotunnelDB.json"
  369. if not os.path.exists(filePath):
  370. os.makedirs(filePath[:-17], exist_ok=True)
  371. open(filePath, 'w').close()
  372. #Installing argotunnel
  373. installArgoTunnel()
  374. self.connection=None
  375. self.proto=proto
  376. self.port=port
  377. self.metricPort=metrics
  378. self.interval=interval
  379. self.retries=retries
  380. # def start(self):
  381. # if self.connection:self.connection.kill()
  382. # # self.connection=Popen(f"ssh -R 80:localhost:{self.port} {self.id}@ssh.localhost.run -o StrictHostKeyChecking=no".split(), stdout=PIPE, stdin=PIPE)
  383. # self.connection=Popen(f"/content/tools/argotunnel/cloudflared tunnel --url {self.proto}://0.0.0.0:{self.port} --logfile cloudflared.log".split(), stdout=PIPE, stdin=PIPE)
  384. # try:
  385. # return re.findall("https://(.*?.trycloudflare.com)",self.connection.stdout.readline().decode("utf-8"))[0]
  386. # except:
  387. # raise Exception(self.connection.stdout.readline().decode("utf-8"))
  388. def keep_alive(self):
  389. # if self.connection:self.connection.kill()
  390. import urllib, requests, re
  391. from urllib.error import HTTPError
  392. try:
  393. argotunnelOpenDB = dict(accessSettingFile("argotunnelDB.json", v=False))
  394. except TypeError:
  395. argotunnelOpenDB = dict()
  396. if findProcess("cloudflared", f"localhost:{self.metricPort}"):
  397. try:
  398. oldAddr = argotunnelOpenDB[str(self.port)]
  399. if requests.get("http://"+oldAddr).status_code == 200:
  400. return oldAddr
  401. except:
  402. pass
  403. self.connection=Popen(f"{HOME}/tools/argotunnel/cloudflared tunnel --url {self.proto}://0.0.0.0:{self.port} --logfile {HOME}/tools/argotunnel/cloudflared_{self.port}.log --metrics localhost:{self.metricPort}".split(),
  404. stdout=PIPE, stdin=PIPE, stderr=PIPE, universal_newlines=True)
  405. time.sleep(5)
  406. hostname = None
  407. for i in range(20):
  408. try:
  409. with urllib.request.urlopen(f"http://127.0.0.1:{self.metricPort}/metrics") as response:
  410. hostname = re.search(r'userHostname=\"https://(.+)\"',
  411. response.read().decode('utf-8'), re.MULTILINE)
  412. if not hostname:
  413. time.sleep(1)
  414. continue
  415. hostname = hostname.group(1)
  416. break
  417. except HTTPError:
  418. time.sleep(2)
  419. if not hostname:
  420. raise RuntimeError("Failed to get user hostname from cloudflared")
  421. argotunnelOpenDB[str(self.port)] = hostname
  422. accessSettingFile("argotunnelDB.json" , argotunnelOpenDB, v=False)
  423. return hostname
  424. def kill(self):
  425. self.connection.kill()
  426. class jprq:
  427. def __init__(self, port, proto='http', ids=None):
  428. import os, uuid
  429. filePath = "/usr/local/sessionSettings/jprqDB.json"
  430. if not os.path.exists(filePath):
  431. os.makedirs(filePath[:-11], exist_ok=True)
  432. open(filePath, 'w').close()
  433. if not ids:self.ids=str(uuid.uuid4())[:12]
  434. #Installing jprq
  435. runSh("pip install jprq")
  436. self.connection=None
  437. self.proto=proto
  438. self.port=port
  439. def keep_alive(self):
  440. # if self.connection:self.connection.kill()
  441. import urllib, requests, re
  442. try:
  443. jprqOpenDB = dict(accessSettingFile("jprqDB.json", v=False))
  444. except TypeError:
  445. jprqOpenDB = dict()
  446. if findProcess("jprq", f"{self.port}"):
  447. try:
  448. oldAddr = jprqOpenDB[str(self.port)]
  449. if requests.get("http://"+oldAddr).status_code == 200:
  450. return oldAddr
  451. except:
  452. pass
  453. hostname = f"OneClickRun-{self.ids}"
  454. self.connection=Popen(f"jprq -s {hostname} {self.port}".split(),
  455. stdout=PIPE, stdin=PIPE, stderr=PIPE)
  456. time.sleep(3)
  457. # try:
  458. # return re.findall("https://(.*?.jprq.live/)", self.connection.stdout.readline().decode("utf-8"))[0]
  459. # except:
  460. # raise Exception(self.connection.stdout.readline().decode("utf-8"))
  461. hostname += ".jprq.live"
  462. jprqOpenDB[str(self.port)] = hostname
  463. accessSettingFile("jprqDB.json" , jprqOpenDB, v=False)
  464. return hostname
  465. def kill(self):
  466. self.connection.kill()
  467. class PortForward:
  468. def __init__(self,connections,region=None,SERVICE="localhost",TOKEN=None,USE_FREE_TOKEN=None,config=None):
  469. c=dict()
  470. for con in connections:
  471. c[con[0]]=dict(port=con[1],proto=con[2])
  472. self.connections=c
  473. if config:config[1] = closePort(config[1])
  474. self.config = config
  475. if SERVICE=="ngrok":self.ngrok=ngrok(TOKEN,USE_FREE_TOKEN,connections,region,self.config)
  476. self.SERVICE = SERVICE
  477. def start(self,name,btc='b',displayB=True,v=True):
  478. from IPython.display import clear_output
  479. if self.SERVICE == "localhost":
  480. con=self.connections[name]
  481. port=con["port"]
  482. proto=con["proto"]
  483. if(proto=="tcp"):
  484. return self.ngrok.start(name,btc,displayB,v)
  485. else:
  486. if v:
  487. clear_output()
  488. loadingAn(name="lds")
  489. textAn("Starting localhost ...", ty="twg")
  490. data = dict(url="https://"+LocalhostRun(port).keep_alive())
  491. if displayB:
  492. displayUrl(data, btc)
  493. return data
  494. elif self.SERVICE == "ngrok":
  495. return self.ngrok.start(name,btc,displayB,v)
  496. elif self.SERVICE == "argotunnel":
  497. con=self.connections[name]
  498. port=con["port"]
  499. proto=con["proto"]
  500. if v:
  501. clear_output()
  502. loadingAn(name="lds")
  503. textAn("Starting Argo Tunnel ...", ty="twg")
  504. data = dict(url="https://"+ArgoTunnel(port, proto, closePort(self.config[1])).keep_alive())
  505. if displayB:
  506. displayUrl(data, btc)
  507. return data
  508. elif self.SERVICE == "jprq":
  509. con=self.connections[name]
  510. port=con["port"]
  511. proto=con["proto"]
  512. if v:
  513. clear_output()
  514. loadingAn(name="lds")
  515. textAn("Starting jprq ...", ty="twg")
  516. data = dict(url="https://"+jprq(port, proto).keep_alive())
  517. if displayB:
  518. displayUrl(data, btc)
  519. return data
  520. class PortForward_wrapper(PortForward):
  521. def __init__(self,SERVICE,TOKEN,USE_FREE_TOKEN,connections,region,config):
  522. super(self.__class__,self).__init__(connections,region,SERVICE,TOKEN,USE_FREE_TOKEN,config)
  523. def findPackageR(id_repo, p_name, tag_name=False, all_=False):
  524. import requests
  525. for rawData in requests.get(f"https://api.github.com/repos/{id_repo}/releases").json():
  526. if tag_name:
  527. if rawData['tag_name'] != tag_name:
  528. continue
  529. for f in rawData['assets']:
  530. if p_name == f['browser_download_url'][-len(p_name):]:
  531. rawData['assets'] = f
  532. return f['browser_download_url'] if not all_ else rawData
  533. raise Exception("not found or maybe api changed!\n Try again with Change packages name")
  534. def closePort(port):
  535. import socket
  536. with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
  537. for _ in range(100):
  538. if s.connect_ex(('localhost', port)) == 0:
  539. port += 1
  540. else:
  541. return port
  542. raise Exception("Close port not found!")