Advertisement
Guest User

Untitled

a guest
Oct 1st, 2014
312
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.33 KB | None | 0 0
  1. # # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## #
  2. #~ This file is part of NZBmegasearch by 0byte.
  3. #~
  4. #~ NZBmegasearch is free software: you can redistribute it and/or modify
  5. #~ it under the terms of the GNU General Public License as published by
  6. #~ the Free Software Foundation, either version 3 of the License, or
  7. #~ (at your option) any later version.
  8. #~
  9. #~ NZBmegasearch is distributed in the hope that it will be useful,
  10. #~ but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. #~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. #~ GNU General Public License for more details.
  13. #~
  14. #~ You should have received a copy of the GNU General Public License
  15. #~ along with NZBmegasearch. If not, see <http://www.gnu.org/licenses/>.
  16. # # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## #
  17. from flask import Flask, request, Response, redirect, render_template, send_from_directory, jsonify
  18. from urlparse import urlparse
  19. import logging
  20. import logging.handlers
  21. import os
  22. import sys
  23. import threading
  24. import SearchModule
  25. import DeepsearchModule
  26. from ApiModule import ApiResponses
  27. from SuggestionModule import SuggestionResponses
  28. from WarperModule import Warper
  29. import megasearch
  30. import config_settings
  31. import miscdefs
  32. import random
  33. import time
  34. import socket
  35. import base64
  36.  
  37. openssl_imported = True
  38. try:
  39. from OpenSSL import SSL
  40. except ImportError as exc:
  41. print ">> Warning: failed to import OPENSSL module ({})".format(exc)
  42. openssl_imported = False
  43.  
  44. sessionid_string = base64.urlsafe_b64encode(os.urandom(10)).replace('-','').replace('=','').replace('/','').replace('+','')
  45.  
  46. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  47. def loginit():
  48. log = logging.getLogger()
  49. handler = logging.handlers.RotatingFileHandler(logsdir+'nzbmegasearch.log', maxBytes=cfgsets.cgen['log_size'], backupCount=cfgsets.cgen['log_backupcount'])
  50. log.setLevel(logging.INFO)
  51. formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  52. handler.setFormatter(formatter)
  53. log.addHandler(handler)
  54. log.info(motd)
  55.  
  56. #~ HOOK INTO STDOUT CONSOLE
  57. stdout_logger = logging.getLogger('TERMINAL')
  58. sl = miscdefs.StreamToLogger(stdout_logger, logging.INFO)
  59. sys.stdout = sl
  60.  
  61. stderr_logger = logging.getLogger('TERMINAL_ERR')
  62. sl = miscdefs.StreamToLogger(stderr_logger, logging.ERROR)
  63. sys.stderr = sl
  64.  
  65. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  66.  
  67. def reload_all():
  68. print '>> Bootstrapping...'
  69. global cfgsets, sugg, ds, mega_parall, wrp, apiresp, auth, getsmartinfo, testserver
  70. cfgsets = config_settings.CfgSettings()
  71. cfgsets.cgen['large_server'] = LARGESERVER
  72. sugg = SuggestionResponses(cfgsets.cfg, cfgsets.cgen)
  73. ds = DeepsearchModule.DeepSearch(cfgsets.cfg_deep, cfgsets.cgen)
  74. wrp = Warper (cfgsets.cgen, cfgsets.cfg, ds)
  75. mega_parall = megasearch.DoParallelSearch(cfgsets.cfg, cfgsets.cgen, ds, wrp)
  76. apiresp = ApiResponses(cfgsets.cfg, cfgsets.cgen, wrp, ds)
  77. getsmartinfo = nzbsanity.GetNZBInfo(cfgsets.cfg, cfgsets.cgen, ds, app)
  78. auth = miscdefs.Auth(cfgsets)
  79. testserver = miscdefs.ChkServer(cfgsets.cgen)
  80.  
  81. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  82. motd = '\n\n~*~ ~*~ NZBMegasearcH ~*~ ~*~'
  83. print motd
  84.  
  85. DEBUGFLAG = False
  86. LARGESERVER = False
  87.  
  88. logsdir = SearchModule.resource_path('logs/')
  89. if(len(os.getenv('OPENSHIFT_DATA_DIR', ''))):
  90. logsdir = os.environ.get('OPENSHIFT_DATA_DIR')
  91.  
  92. if(len(sys.argv) > 1):
  93. for argv in sys.argv:
  94. if(argv == 'help'):
  95. print ''
  96. print '`debug`: start in debug mode'
  97. print '`large`: modality for GUNICORN + NGINX large server'
  98. print '`daemon`: start in daemon mode, detached from terminal'
  99. print ''
  100. exit()
  101.  
  102. if(argv == 'debug'):
  103. print '====== DEBUGMODE DEBUGMODE DEBUGMODE DEBUGMODE ======'
  104. DEBUGFLAG = True
  105.  
  106. if(argv == 'large'):
  107. print '====== GUNICORN + NGIX server ======'
  108. LARGESERVER = True
  109.  
  110. if(argv == 'daemon'):
  111. print '====== DAEMON MODE ======'
  112. miscdefs.daemonize(logsdir)
  113.  
  114. #~ detect if started from gunicorn
  115. oshift_dirconf = os.getenv('OPENSHIFT_DATA_DIR', '')
  116. if( __name__ == 'mega2' and len(oshift_dirconf)==0):
  117. print '====== GUNICORN + NGIX server ======'
  118. LARGESERVER = True
  119.  
  120. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  121. cver = miscdefs.ChkVersion(DEBUGFLAG)
  122. print '>> version: '+ str(cver.ver_notify['curver'])
  123. motd = motd + ' v.'+str(cver.ver_notify['curver']) + ' large_server: ' + str(LARGESERVER) + ' debug: ' + str(DEBUGFLAG)
  124. cfgsets = config_settings.CfgSettings()
  125. first_time = 0
  126. #~ init logger
  127. log = loginit()
  128.  
  129. if (cfgsets.cfg is None or cfgsets.cfg_deep is None ):
  130. first_time = 1
  131. '>> It will be configured'
  132.  
  133. certdir = SearchModule.resource_path('certificates/')
  134. templatedir = SearchModule.resource_path('templates')
  135. app = Flask(__name__, template_folder=templatedir)
  136.  
  137. #~ bootstrap
  138. import nzbsanity
  139. reload_all()
  140.  
  141. #~ SearchModule.loadSearchModules()
  142. if(DEBUGFLAG):
  143. cfgsets.cgen['general_trend'] = 0
  144. cfgsets.cgen['general_suggestion'] = 0
  145. print '====== DEBUGFLAG MUST BE SET TO FALSE BEFORE DEPLOYMENT ======'
  146.  
  147. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  148.  
  149. @app.route('/poweroff', methods=['GET'])
  150. @auth.requires_auth
  151. def poweroff():
  152. if(cfgsets.cgen['large_server'] == False):
  153. if('sid' in request.args):
  154. if(request.args['sid'] == sessionid_string):
  155. os._exit(0)
  156. return main_index()
  157.  
  158. @app.route('/restart', methods=['GET'])
  159. @auth.requires_auth
  160. def reboot():
  161. if(cfgsets.cgen['large_server'] == False):
  162. if('sid' in request.args):
  163. if(request.args['sid'] == sessionid_string):
  164. app.restart()
  165. return render_template('restart.html');
  166. return main_index();
  167.  
  168. @app.route('/legal', methods=['GET'])
  169. @auth.requires_auth
  170. def legal():
  171. if(cfgsets.cgen['large_server'] == True):
  172. return render_template('legal.html')
  173. return main_index()
  174.  
  175.  
  176. @app.route('/robots.txt')
  177. def static_from_root():
  178. return send_from_directory(app.static_folder, request.path[1:])
  179.  
  180.  
  181. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  182.  
  183. @app.route('/log', methods=['GET'])
  184. @auth.requires_conf
  185. def log():
  186. return miscdefs.logviewer(logsdir);
  187.  
  188.  
  189. @app.route('/s', methods=['GET'])
  190. @auth.requires_auth
  191. def search():
  192. if(first_time and cfgsets.cgen['large_server'] == False):
  193. return (main_index)
  194.  
  195. sugg.asktrend_allparallel()
  196. #~ parallel suggestion and search
  197. if(cfgsets.cgen['general_suggestion'] == 1):
  198. t1 = threading.Thread(target=sugg.ask, args=(request.args,) )
  199. if(cfgsets.cgen['predb_active'] == 1):
  200. t3 = threading.Thread(target=sugg.ask_predb, args=(request.args,) )
  201. t2 = threading.Thread(target=mega_parall.dosearch, args=(request.args,) )
  202. t2.start()
  203. if(cfgsets.cgen['general_suggestion'] == 1):
  204. t1.start()
  205. if(cfgsets.cgen['predb_active'] == 1):
  206. t3.start()
  207. if(cfgsets.cgen['general_suggestion'] == 1):
  208. t1.join()
  209. if(cfgsets.cgen['predb_active'] == 1):
  210. t3.join()
  211. t2.join()
  212.  
  213. params_dosearch = {'args': request.args,
  214. 'sugg': sugg.sugg_info,
  215. 'predb': sugg.predb_info,
  216. 'trend_movie': sugg.movie_trend,
  217. 'trend_show': sugg.show_trend,
  218. 'ver': cver.ver_notify,
  219. 'debugflag':DEBUGFLAG,
  220. 'sid': sessionid_string
  221. }
  222. return mega_parall.renderit(params_dosearch)
  223.  
  224. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  225. @app.route('/config', methods=['GET','POST'])
  226. @auth.requires_conf
  227. def config():
  228. #~ flask bug in threads, had to solve like that
  229. cfgsets.cgen['large_server'] = LARGESERVER
  230.  
  231. if(cfgsets.cgen['large_server'] == False):
  232. return cfgsets.edit_config()
  233. else:
  234. return main_index();
  235.  
  236. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  237.  
  238. @app.route('/warp', methods=['GET'])
  239. def warpme():
  240. res = wrp.beam(request.args)
  241.  
  242. if(res == -1):
  243. return main_index()
  244. else:
  245. return res
  246. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  247.  
  248. @app.route('/serverchk')
  249. def serverchk():
  250. return jsonify(code=testserver.check(request.args))
  251.  
  252. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  253.  
  254. @app.route('/rss')
  255. def rss():
  256. if(len(cfgsets.cgen['general_apikey'])):
  257. if('apikey' in request.args):
  258. if(request.args['apikey'] == cfgsets.cgen['general_apikey']):
  259. return apiresp.dosearch_rss(request.args, urlparse(request.url)), 200, {'Content-Type':'application/rss+xml'}
  260. else:
  261. return '[API key protection ACTIVE] Wrong key selected'
  262. else:
  263. return '[API key protection ACTIVE] API key required'
  264. else:
  265. return apiresp.dosearch_rss(request.args, urlparse(request.url)), 200, {'Content-Type':'application/rss+xml'}
  266.  
  267.  
  268. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  269.  
  270. @app.route('/smartget', methods=['POST'])
  271. def smartget():
  272. jsonret = jsonify(code=getsmartinfo.process( request.data, urlparse(request.url) ))
  273. return jsonret
  274.  
  275.  
  276. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  277.  
  278. @app.route('/tosab')
  279. def tosab():
  280. return jsonify(code=mega_parall.tosab(request.args, urlparse(request.url) ))
  281.  
  282. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  283.  
  284. @app.route('/tonzbget')
  285. def tonzbget():
  286. return jsonify(code=mega_parall.tonzbget(request.args, urlparse(request.url) ))
  287.  
  288. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  289.  
  290. @app.route('/saveconfig', methods=['POST'])
  291. @auth.requires_auth
  292. def saveconfig():
  293. global first_time
  294. savedok = 0
  295. if request.method == 'POST':
  296. #~ just for showing a minimum waiting
  297. time.sleep(1)
  298. if(len(request.form) > 0):
  299. cfgsets.write(request.form)
  300. first_time = 0
  301. savedok = 1
  302. reload_all()
  303.  
  304. return jsonify(code=savedok)
  305.  
  306. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  307.  
  308. @app.route('/', methods=['GET'])
  309. @auth.requires_auth
  310. def main_index():
  311. #~ flask bug in threads, had to solve like that
  312. cfgsets.cgen['large_server'] = LARGESERVER
  313. #~ ~
  314. global first_time
  315. if(cfgsets.cgen['large_server'] == False):
  316.  
  317. if first_time == 1:
  318. return cfgsets.edit_config()
  319.  
  320. sugg.asktrend_allparallel()
  321. cver.chk_update()
  322. params_dosearch = {'args': '',
  323. 'sugg': [],
  324. 'trend': [],
  325. 'trend_movie': sugg.movie_trend,
  326. 'trend_show': sugg.show_trend,
  327. 'ver': cver.ver_notify,
  328. 'debugflag':DEBUGFLAG,
  329. 'sid': sessionid_string}
  330. return mega_parall.renderit_empty(params_dosearch)
  331.  
  332. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  333.  
  334. @app.route('/api', methods=['GET'])
  335. def api():
  336. if(len(cfgsets.cgen['general_apikey'])):
  337. if('apikey' in request.args):
  338. if(request.args['apikey'] == cfgsets.cgen['general_apikey']):
  339. return apiresp.dosearch(request.args, urlparse(request.url)), 200, {'Content-Type':'application/rss+xml'}
  340. else:
  341. return '[API key protection ACTIVE] Wrong key selected'
  342. else:
  343. return '[API key protection ACTIVE] API key required'
  344. else:
  345. return apiresp.dosearch(request.args, urlparse(request.url)), 200, {'Content-Type':'application/rss+xml'}
  346.  
  347. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  348.  
  349. @app.route('/favicon.ico')
  350. def favicon():
  351. return send_from_directory(os.path.join(app.root_path, 'static'),
  352. 'favicon.ico', mimetype='image/vnd.microsoft.icon')
  353.  
  354. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  355.  
  356. @app.route('/connect', methods=['GET'])
  357. @auth.requires_auth
  358. def connect():
  359. return miscdefs.connectinfo()
  360.  
  361. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  362.  
  363. @app.errorhandler(404)
  364. def generic_error(error):
  365. return main_index()
  366.  
  367. #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
  368.  
  369.  
  370. if __name__ == "__main__":
  371.  
  372. sugg.asktrend_allparallel()
  373. chost = '0.0.0.0'
  374. print '>> Running on port ' + str(cfgsets.cgen['portno'])
  375.  
  376. ctx = None
  377.  
  378. if(cfgsets.cgen['general_https'] == 1 and openssl_imported == True):
  379. print '>> HTTPS security activated'
  380. ctx = SSL.Context(SSL.SSLv23_METHOD)
  381. ctx.use_privatekey_file(certdir+'server.key')
  382. ctx.use_certificate_file(certdir+'server.crt')
  383.  
  384. app.run(host=chost,port=cfgsets.cgen['portno'], debug = True, ssl_context=ctx)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement