Python module (submodule repositary), which provides content (video streams) from various online stream sources to corresponding Enigma2, Kodi, Plex plugins

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. #!/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. Shortcut.lv proxy server
  5. usage: %s start|stop|restart|manualstart [options]
  6. -p PORT - port number
  7. -s WSGI_SERVER - wsgi server - wsgiref,cheroot,mtwsgi,waitress...
  8. -d - debug printout
  9. -r - remote debug mode (ptvsd)"""
  10. import os, sys, time
  11. import urllib,urlparse, urllib2, requests
  12. from urllib import unquote, quote
  13. import re, json
  14. import ConfigParser, getopt
  15. import arrow
  16. from diskcache import Cache
  17. import daemonize
  18. import bottle
  19. from bottle import Bottle, hook, response, route, request, run
  20. cunicode = lambda s: s.decode("utf8") if isinstance(s, str) else s
  21. cstr = lambda s: s.encode("utf8") if isinstance(s, unicode) else s
  22. headers2dict = lambda h: dict([l.strip().split(": ") for l in h.strip().splitlines()])
  23. headers0 = headers2dict("""
  24. User-Agent: Shortcut.lv v2.9.1 / Dalvik/1.6.0 (Linux; U; Android 4.4.2; SM-G900FD Build/KOT49H)
  25. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
  26. """)
  27. url0 = "https://manstv.lattelecom.tv/api/v1.7/get/content/"
  28. cur_directory = os.path.dirname(os.path.realpath(__file__))
  29. cache_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "cache")
  30. if not os.path.exists(cache_dir):
  31. os.mkdir(cache_dir)
  32. config = ConfigParser.ConfigParser()
  33. proxy_cfg_file = os.path.join(cur_directory, "ltcproxy.cfg")
  34. DEBUG = False
  35. PORT_NUMBER = 8881
  36. REDIRECT = False
  37. CACHE = True
  38. KEY = ["1234","3786"]
  39. SERVER = "wsgiref"
  40. WORKERS = 10
  41. LTC_USER = "ivars777"
  42. LTC_PASSWORD = "kaskade7"
  43. if not os.path.exists(proxy_cfg_file):
  44. config.add_section("ltcproxy")
  45. config.set("ltcproxy", "debug", DEBUG)
  46. config.set("ltcproxy", "port", PORT_NUMBER)
  47. config.set("ltcproxy", "redirect", REDIRECT)
  48. config.set("ltcproxy", "cache", CACHE)
  49. config.set("ltcproxy", "key", " ".join(KEY))
  50. config.set("ltcproxy", "wsgi", SERVER)
  51. config.set("ltcproxy", "workers", WORKERS)
  52. config.set("ltcproxy", "ltc_user", LTC_USER)
  53. config.set("ltcproxy", "ltc_password", LTC_PASSWORD)
  54. config.write(open(proxy_cfg_file, "w"))
  55. else:
  56. config.read(proxy_cfg_file)
  57. DEBUG = config.getboolean("ltcproxy", "debug")
  58. PORT_NUMBER = config.getint("ltcproxy", "port")
  59. REDIRECT = config.getboolean("ltcproxy", "redirect")
  60. CACHE = config.getboolean("ltcproxy", "cache")
  61. KEY = config.get("ltcproxy", "key").split(" ")
  62. SERVER = config.get("ltcproxy", "wsgi")
  63. WORKERS = config.getint("ltcproxy", "workers")
  64. LTC_USER = config.get("ltcproxy", "ltc_user")
  65. LTC_PASSWORD = config.get("ltcproxy", "ltc_password")
  66. s = Cache(cache_dir)
  67. app = Bottle()
  68. token = None
  69. ########################################################################################
  70. @app.hook('before_request')
  71. def set_globals():
  72. global s, headers0, token
  73. key = request.path.split("/")[1]
  74. if not key in KEY:
  75. print "Error: Wrong key - %s"% key
  76. raise bottle.HTTPError(500, "Wrong key")
  77. s = Cache(cache_dir)
  78. if "token" in s and s["token"]:
  79. token = s["token"]
  80. else:
  81. token = login(LTC_USER, LTC_PASSWORD)
  82. if token:
  83. s.set("token", token, expire=3600*24*1) # pēc 1d ekspirejas
  84. print "** %s: token=%s" % (request.remote_addr,token)
  85. else:
  86. print "Can not login"
  87. raise bottle.HTTPError(500, "Can not login")
  88. # @app.route('/playstream/<url:re:.*>')
  89. ### Live playlist ###
  90. @app.route("/<key>/live/<ch>/")
  91. def get_live(key, ch):
  92. global s, token, headers0
  93. path0, rest = hls_split(request.url)
  94. response.content_type = "application/x-mpegURL" # r.headers["content-type"] # 'application/vnd.apple.mpegurl' # application/x-mpegURL
  95. if "c"+ch in s:
  96. stream_url2 = s["c"+ch]
  97. mediaid = s["m"+ch]
  98. print "** %s: serving live playlist for %s (%s) from cache" % (request.remote_addr,path0,mediaid )
  99. else:
  100. stream_url2, mediaid = refresh_live_chunklist_url(ch)
  101. print "** %s: getting ive playlist for %s (%s)" % (request.remote_addr,path0,mediaid )
  102. stream_url2 += token
  103. if REDIRECT:
  104. bottle.redirect(stream_url2, 307)
  105. for i in range(3):
  106. r2 = requests.get(stream_url2,headers=headers0)
  107. if r2.status_code == 200:
  108. break
  109. time.sleep(1)
  110. else:
  111. print "Error %s getting live chunklist %s"% (r2.status_code,stream_url2)
  112. raise bottle.HTTPError(r2.status_code)
  113. return r2.content
  114. ### Live TS chunk ###
  115. @app.route("/<key>/live/<ch>/<tail>")
  116. def get_live_chunk(key, ch, tail):
  117. global s, token, headers0
  118. path0, rest = hls_split(request.url)
  119. chid = re.search("resource_id=c-(\\w+)",rest).group(1)
  120. chunkid = re.search("(\d+)\.ts", request.url).group(1)
  121. path2 = ch + "/" + chunkid
  122. if CACHE and path2 in s:
  123. print "** %s: serving live ts %s from cache" % (request.remote_addr,path2)
  124. f = s.get(path2, read=True)
  125. response.headers["Content-Type"] = s[path2+"@"] #'video/MP2T'
  126. response.headers["Content-Length"] = s[path2+"#"]
  127. while True:
  128. chunk = f.read(8192)
  129. if not chunk:
  130. break
  131. yield chunk
  132. else: # no cache
  133. if ch in s:
  134. stream_url = s[ch]
  135. mediaid= s["m"+ch]
  136. else:
  137. refresh_live_chunklist_url(ch)
  138. if ch in s:
  139. stream_url = s[ch]
  140. mediaid= s["m"+ch]
  141. else:
  142. print "No stream_url %s in cache" % path0
  143. raise bottle.HTTPError(500)
  144. base0, rest0 = hls_base(stream_url)
  145. rest2 = "media_%s_%s.ts?resource_id=c-%s&auth_token=app_" % (mediaid, chunkid, chid)
  146. url = base0 + rest2 + token
  147. url2 = hls_base(stream_url)[0] + rest
  148. headers = dict(request.headers)
  149. del headers["Host"]
  150. # headers["Authorization"] = "Bearer " + token
  151. print "** %s: getting live ts from %s(%s)- %s" % (request.remote_addr, path2, mediaid,url[:40])
  152. if DEBUG:
  153. print "=== Request headers ==="
  154. print_headers(headers)
  155. r = requests.get(url, stream=True, headers=headers0)
  156. if r.status_code <> 200:
  157. r = requests.get(url, stream=True, headers=headers0) # try once more
  158. if r.status_code <> 200:
  159. # Refresh chunklist
  160. print "## %s: Refreshing chunklist/mediaid for live channel %s" %(request.remote_addr, ch)
  161. chunklist_url, mediaid = refresh_live_chunklist_url(ch)
  162. rest2 = "media_%s_%s.ts?resource_id=c-%s&auth_token=app_" % (mediaid, chunkid, chid)
  163. url = base0 + rest2 + token
  164. url2 = chunklist_url + token
  165. print "** %s: getting live ts from %s(%s)- %s" % (request.remote_addr, path2, mediaid,url[:40])
  166. r = requests.get(url, stream=True, headers=headers0)
  167. if r.status_code <> 200:
  168. print "Error %s opening stream \n%s" %(r.status_code,url)
  169. print url2
  170. raise bottle.HTTPError(r.status_code, "Error opening stream "+url)
  171. content = ""
  172. response.content_type = r.headers["content-type"] # 'application/vnd.apple.mpegurl' #
  173. # response.headers.clear()
  174. for k in r.headers:
  175. response.headers[k] = r.headers[k]
  176. if DEBUG:
  177. print "=== Response headers ==="
  178. print_headers(response.headers)
  179. for chunk in r.iter_content(chunk_size=8192):
  180. if chunk:
  181. content += chunk
  182. yield chunk
  183. if len(content) <> int(r.headers["content-length"]):
  184. print "Content length problem"
  185. if CACHE:
  186. s.set(path2, content, expire=3600, read=True)
  187. s.set(path2+"#", len(content), expire=3600, read=True)
  188. s.set(path2+"@", r.headers["Content-Type"], expire=3600, read=True)
  189. ### Archive playlist ###
  190. @app.route("/<key>/live/<ch>/<ts>/")
  191. def get_archive(key, ch, ts):
  192. global s, token, headers0
  193. path0, rest = hls_split(request.url)
  194. start = int(ts) + 60 * 5
  195. epg = get_epg(ch, start)
  196. print "** %s: getting archive playlist for channel %s" % (request.remote_addr,path0)
  197. if epg:
  198. epgid = epg["id"]
  199. epg_start = int(epg["attributes"]["unix-start"])
  200. epg_stop = int(epg["attributes"]["unix-stop"])
  201. epg_title = epg["attributes"]["title"]
  202. else:
  203. print "EPG not found"
  204. raise bottle.HTTPError(500, "EPG not found")
  205. stream_url = epg_get_stream_url(epgid)
  206. if REDIRECT:
  207. bottle.redirect(stream_url, 307)
  208. # Getting chunklist
  209. stream_url2, mediaid = refresh_epg_chunklist_url(stream_url)
  210. r2 = requests.get(stream_url2)
  211. if r2.status_code <> 200:
  212. print "Error %s getting archive chunklist %s"% (r2.status_code,stream_url2)
  213. raise bottle.HTTPError(r2.status_code)
  214. result = re.findall(r"#EXTINF:([\d\.]+),\n(.+)", r2.content)
  215. ll = 0
  216. i = 0
  217. for chunk_len, chunk_url in result:
  218. ll += float(chunk_len)
  219. if ll > (start - epg_start):
  220. break
  221. i += 1
  222. result2 =result[i:]
  223. content = re.search("(^.+?)#EXTINF", r2.content, re.DOTALL).group(1)
  224. for chunk_len, chunk_url in result2:
  225. content += "#EXTINF:%s,\n" % chunk_len
  226. content += chunk_url + "\n"
  227. content += "#EXT-X-ENDLIST"
  228. response.content_type = r2.headers["content-type"] # 'application/vnd.apple.mpegurl' #
  229. return content
  230. def live_get_stream_url(ch):
  231. global s, token, headers0
  232. if ch in s:
  233. stream_url = s[ch]
  234. stream_url += token
  235. else:
  236. # Getting live stream url
  237. url = url0 + "live-streams/%s?include=quality&auth_token=app_%s" % (ch, token)
  238. headers = headers0.copy()
  239. headers["Authorization"] = "Bearer " + token
  240. r = requests.get(url, headers=headers)
  241. if r.status_code <> 200:
  242. print "Error getting epg stream url "+url
  243. raise bottle.HTTPError(r.status_code, "Error getting epg stream url "+url)
  244. js = json.loads(r.content)
  245. stream_url = js["data"][0]["attributes"]["stream-url"]
  246. stream_url0 = stream_url.replace(token, "")
  247. s.set(ch, stream_url0, expire=3600*24*7, read=False)
  248. return str(stream_url)
  249. def epg_get_stream_url(epgid):
  250. global s, token, headers0
  251. if epgid in s:
  252. stream_url = s[epgid]
  253. stream_url += token
  254. else:
  255. # Getting epg stream url
  256. url = url0 + "record-streams/%s?include=quality&auth_token=app_%s" % (epgid, token)
  257. headers = headers0.copy()
  258. headers["Authorization"] = "Bearer " + token
  259. r = requests.get(url, headers=headers)
  260. if r.status_code <> 200:
  261. print "Error getting epg stream url "+url
  262. raise bottle.HTTPError(r.status_code, "Error getting epg stream url "+url)
  263. js = json.loads(r.content)
  264. stream_url = js["data"][0]["attributes"]["stream-url"]
  265. stream_url0 = stream_url.replace(token, "")
  266. s.set(epgid, stream_url0, expire=3600*24*7, read=False)
  267. return str(stream_url)
  268. def refresh_live_chunklist_url(ch):
  269. global s, token, headers0
  270. stream_url = live_get_stream_url(ch)
  271. r = requests.get(stream_url)
  272. if r.status_code <> 200:
  273. print "Error %s getting live chunklist %s"% (r.status_code,stream_url)
  274. raise bottle.HTTPError(r.status_code)
  275. chid = re.search("resource_id=c\\-(\\w+)",stream_url).group(1)
  276. rest2 = re.search("chunklist.+$", r.content).group(0).replace(token,"")
  277. mediaid = re.search("chunklist_(.+?)\\.m3u8",rest2).group(1)
  278. base2 = hls_base(stream_url)[0]
  279. stream_url2 = base2 + rest2 # chunlist url
  280. s.set("m"+ch, mediaid, expire=3600*24*7, read=False)
  281. s.set("c"+ch, stream_url2, expire=3600*24*7, read=False)
  282. return stream_url2,mediaid
  283. def refresh_epg_chunklist_url(stream_url):
  284. global s, token, headers0
  285. r = requests.get(stream_url)
  286. if r.status_code <> 200:
  287. print "Error %s getting archive chunklist %s"% (r.status_code,stream_url)
  288. raise bottle.HTTPError(r.status_code)
  289. epgid = re.search("resource_id=a-(\\d+)",stream_url).group(1)
  290. rest2 = re.search("chunklist.+$", r.content).group(0)
  291. mediaid = re.search("chunklist_(.+?)\\.m3u8",rest2).group(1)
  292. s.set("m"+epgid, mediaid, expire=3600*24*7, read=False)
  293. base2 = hls_base(stream_url)[0]
  294. stream_url2 = base2 + rest2 # chunlist url
  295. return stream_url2,mediaid
  296. ### Archive ts chunk ###
  297. @app.route("/<key>/live/<ch>/<ts>/<tail>")
  298. def get_archive_chunk(key, ch, ts, tail):
  299. global s, token, headers0
  300. path0, rest = hls_split(request.url)
  301. epgid = re.search("resource_id=a-(\\d+)",rest).group(1)
  302. chunkid = re.search("(\\d+)\\.ts", rest).group(1)
  303. path2 = epgid + "/" + chunkid
  304. if CACHE and path2 in s:
  305. print "** %s: serving archive ts from cache %s" % (request.remote_addr,path2)
  306. f = s.get(path2, read=True)
  307. response.headers["Content-Type"] = s[path2+"@"] #'video/MP2T'
  308. response.headers["Content-Length"] = s[path2+"#"]
  309. while True:
  310. chunk = f.read(8192)
  311. if not chunk:
  312. break
  313. yield chunk
  314. else: # No cache
  315. stream_url = epg_get_stream_url(epgid)
  316. if "m"+epgid in s:
  317. mediaid= s["m"+epgid]
  318. else:
  319. chunklist_url, mediaid = refresh_epg_chunklist_url(stream_url)
  320. base0, rest0 = hls_base(stream_url)
  321. #media_w76603200_0.ts?resource_id=a-6559656352477&auth_token=app_
  322. rest2 = "media_%s_%s.ts?resource_id=a-%s&auth_token=app_" % (mediaid, chunkid, epgid)
  323. url = base0 + rest2 + token
  324. print "** %s: getting archive ts from %s(%s) - %s" % (request.remote_addr,path2, mediaid, rest2[:rest2.index("?")])
  325. #print url
  326. headers = dict(request.headers)
  327. del headers["Host"]
  328. # headers["Authorization"] = "Bearer " + token
  329. r = requests.get(url, stream=True, headers=headers)
  330. if r.status_code <> 200:
  331. r = requests.get(url, stream=True, headers=headers) # try once more
  332. if r.status_code <> 200:
  333. # Refresh chunklist
  334. print "## %s: Refreshing chunklist/mediaid for epg %s" %(request.remote_addr, epgid)
  335. chunklist_url, mediaid = refresh_epg_chunklist_url(stream_url)
  336. rest2 = "media_%s_%s.ts?resource_id=a-%s&auth_token=app_" % (mediaid, chunkid, epgid)
  337. url = base0 + rest2 + token
  338. print "** %s: getting archive ts from %s(%s) - %s" % (request.remote_addr, path2, mediaid, rest2[:rest2.index("?")])
  339. r = requests.get(url, stream=True, headers=headers0)
  340. if r.status_code <> 200:
  341. print "Error %s opening stream \n%s" %(r.status_code,url)
  342. raise bottle.HTTPError(r.status_code, "Error opening stream "+url)
  343. content = ""
  344. response.content_type = r.headers["content-type"] # 'application/vnd.apple.mpegurl' #
  345. # response.headers.clear()
  346. for k in r.headers:
  347. response.headers[k] = r.headers[k]
  348. if DEBUG:
  349. print_headers(response.headers)
  350. for chunk in r.iter_content(chunk_size=8192):
  351. if chunk:
  352. content += chunk
  353. yield chunk
  354. if CACHE:
  355. path2 = epgid + "/" + chunkid
  356. s.set(path2, content, expire=3600, read=True)
  357. s.set(path2+"#", len(content), expire=3600, read=True)
  358. s.set(path2+"@", r.headers["Content-Type"], expire=3600, read=True)
  359. @app.route("/<key>/vod/<ch>/")
  360. def get_vod(key, ch):
  361. global s, token, headers0
  362. path0, rest = hls_split(request.url)
  363. if path0 in s:
  364. stream_url = s[path0] + token
  365. print "** %s: getting vod to %s from cache (%s)" % (request.remote_addr, path0)
  366. else:
  367. url = url0 + "vod-streams/%s?include=language,subtitles,quality &auth_token=app_%s" % (ch, token)
  368. headers = headers0.copy()
  369. headers["Authorization"] = "Bearer " + token
  370. r = requests.get(url, headers=headers)
  371. if r.status_code <> 200:
  372. raise bottle.HTTPError(r.status_code, "Error opening stream "+url)
  373. js = json.loads(r.content)
  374. stream_url = js["data"][0]["attributes"]["stream-url"]
  375. stream_url0 = stream_url.replace(token, "")
  376. s.set(path0, stream_url0, expire=3600*24*7, read=False)
  377. print "** %s: changing vod to %s (%s)" % (request.remote_addr, path0)
  378. if True: # REDIRECT:
  379. bottle.redirect(stream_url, 307)
  380. r = requests.get(stream_url)
  381. if r.status_code <> 200:
  382. raise bottle.HTTPError(r.status_code)
  383. response.content_type = r.headers["content-type"] # 'application/vnd.apple.mpegurl' #
  384. return r.content
  385. def get_epg(ch, start):
  386. url = url0 + "epgs/?filter[channel]=%s&filter[utFrom]=%s&filter[utTo]=%s&include=channel&page[size]=40page[number]=1" % (ch, start, start )
  387. r = requests.get(url)
  388. if r.status_code <> 200:
  389. raise bottle.HTTPError(500, "EPG not found")
  390. js = json.loads(r.content)
  391. if "data" in js:
  392. for epg in js["data"]:
  393. if int(epg["id"]) < 0:
  394. continue
  395. else:
  396. break
  397. return epg
  398. else:
  399. return None
  400. ####################################################################
  401. # Run WSGI server
  402. def start(server,port):
  403. print "*** Starting ltcproxy ***"
  404. options = {}
  405. if server == "mtwsgi":
  406. import mtwsgi
  407. server = mtwsgi.MTServer
  408. options = {"thread_count": WORKERS,}
  409. run(app=app,server=server, host='0.0.0.0',
  410. port=port,
  411. reloader=False,
  412. quiet=False,
  413. plugins=None,
  414. debug=True,
  415. config=None,
  416. **options)
  417. def login(user,password):
  418. """Login in to site, get token"""
  419. # Dabūjam tokenu
  420. url = "https://manstv.lattelecom.tv/api/v1.7/post/user/users/%s" % user
  421. params = "uid=5136baee57505694&password=%s&" % (password)
  422. headers = headers2dict("""
  423. User-Agent: Shortcut.lv v2.9.1 / Dalvik/1.6.0 (Linux; U; Android 4.4.2; SM-G900FD Build/KOT49H)
  424. Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  425. Host: manstv.lattelecom.tv
  426. """ )
  427. try:
  428. r = urllib2.Request(url, data=params, headers=headers)
  429. u = urllib2.urlopen(r)
  430. content = u.read()
  431. u.close()
  432. except Exception as ex:
  433. return None
  434. if r and "token" in content:
  435. token = re.search('"token":"(.+?)"', content).group(1)
  436. return token
  437. else:
  438. return False
  439. def refresh_token(token):
  440. """Refresh"""
  441. url = "https://manstv.lattelecom.tv/api/v1.7/post/user/refresh-token/"
  442. params = "uid=5136baee57505694&token=%s&" % (token)
  443. headers = headers2dict("""
  444. User-Agent: Shortcut.lv v2.9.1 / Dalvik/1.6.0 (Linux; U; Android 4.4.2; SM-G900FD Build/KOT49H)
  445. Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  446. Host: manstv.lattelecom.tv
  447. """ )
  448. try:
  449. r = urllib2.Request(url, data=params, headers=headers)
  450. u = urllib2.urlopen(r)
  451. content = u.read()
  452. u.close()
  453. except Exception as ex:
  454. return None
  455. if r and "token" in content:
  456. token2 = re.search('"token":"(.+?)"', content).group(1)
  457. return token2
  458. else:
  459. return False
  460. def print_headers(headers):
  461. for h in headers:
  462. print "%s: %s"%(h,headers[h])
  463. def del_headers(headers0,tags):
  464. headers = headers0.copy()
  465. for t in tags:
  466. if t in headers:
  467. del headers[t]
  468. if t.lower() in headers:
  469. del headers[t.lower()]
  470. return headers
  471. def hls_split(url):
  472. pp = urlparse.urlsplit(url)
  473. path0 = pp.path[:pp.path.rindex("/")+1]
  474. path0 = path0[path0.index("/", 1):]
  475. rest = pp.path[pp.path.rindex("/")+1:] + "?" + pp.query
  476. return path0, rest
  477. def hls_base(url):
  478. base = url.split("?")[0]
  479. base = "/".join(base.split("/")[0:-1])+ "/"
  480. rest = url.replace(base, "")
  481. return base, rest
  482. #########################################################################################
  483. if __name__ == '__main__':
  484. # 1561839586
  485. # get_epg("101", 1561839586)
  486. try:
  487. opts, args = getopt.gnu_getopt(sys.argv[1:], "p:s:dr", ["port=","server=","--debug"])
  488. except getopt.GetoptError as err:
  489. print str(err)
  490. print str(__doc__)
  491. sys.exit(2)
  492. opts = dict(opts)
  493. if not len(args):
  494. print str(__doc__)
  495. sys.exit(2)
  496. if "-r" in opts:
  497. print "Enabling remote debuging (ptvsd)"
  498. import ptvsd
  499. ptvsd.enable_attach(address = ('0.0.0.0', 5678),redirect_output=False)
  500. if "-d" in opts:
  501. print "Enabling debuging mode (more output)"
  502. DEBUG = True
  503. pid = "/var/run/ltcproxy.pid"
  504. daemon = daemonize.Daemon(start, pid)
  505. server = opts["-s"] if "-s" in opts else SERVER
  506. port = opts["-p"] if "-p" in opts else PORT_NUMBER
  507. if "start" == args[0]:
  508. s.clear()
  509. daemon.start(server,port)
  510. daemon.is_running()
  511. elif "stop" == args[0]:
  512. daemon.stop()
  513. elif "restart" == args[0]:
  514. s.clear()
  515. daemon.restart()
  516. daemon.is_running()
  517. elif "manualstart" == args[0]:
  518. s.clear()
  519. start(server,port)
  520. elif "status" == args[0]:
  521. daemon.is_running()
  522. else:
  523. print "Unknown command"
  524. print str(__doc__)
  525. sys.exit(2)
  526. sys.exit(0)