def get_files(ids): ''' Recibe lista de tuplas de tamaño 3 (como devueltas por get_ids de search) y devuelve los ficheros del mongo correspondiente que no estén bloqueados. Si se recibe un fichero bloqueado, lo omite y bloquea en el sphinx. @type ids: iterable de tuplas de tamaño 3 o mayor @param ids: lista de tuplas (mongoid, id servidor, id sphinx) @yield: cada uno de los resultados de los ids en los mongos ''' toblock = [] already = False for f in filesdb.get_files(ids, servers_known = True, bl = None): if f["bl"] == 0 or f["bl"] is None: yield f else: toblock.append(mid2bin(f["_id"])) # bloquea en sphinx los ficheros bloqueados if toblock: cache.cacheme = False id_list = {i[0]:i[2] for i in ids} block_files( sphinx_ids=[id_list[i] for i in toblock] )
def get_id_server_from_search(mongoid, file_name): uri1, uri2, uri3 = struct.unpack("III", mid2bin(mongoid)) sph = sphinxapi2.SphinxClient() sph.SetMatchMode(sphinxapi2.SPH_MATCH_ALL) sph.SetServer(current_app.config["SERVICE_SPHINX"], current_app.config["SERVICE_SPHINX_PORT"]) sph.SetConnectTimeout(current_app.config["SERVICE_SPHINX_CONNECT_TIMEOUT"]) sph.SetMaxQueryTime(current_app.config["SERVICE_SPHINX_MAX_QUERY_TIME"]) sph.SetLimits(0, 1, 1, 1) sph.SetFilter("uri1", [uri1]) sph.SetFilter("uri2", [uri2]) sph.SetFilter("uri3", [uri3]) if file_name: query = " ".join(split_phrase(file_name, True)[0]) query = sph.EscapeString(query) else: query = "" query = sph.Query(query, "idx_files") warn = error = ret = None if query and "total" in query and query["total"] == 1: if query["warning"]: warn = query["warning"] if query["error"]: error = query["error"] ret = query["matches"][0]["id"] / 0x100000000 else: warn = sph.GetLastWarning() error = sph.GetLastError() if warn: logging.warn( "Warning on a Sphinx response", extra={"method": "get_id_server_from_search", "id": mongoid, "orig_msg": warn}, ) if error: logging.error( "Error on a Sphinx response", extra={"method": "get_id_server_from_search", "id": mongoid, "orig_msg": error}, ) sph.Close() feedbackdb.notify_indir(mongoid, ret) return ret
def get_files(ids): ''' Recibe lista de tuplas de tamaño 3 (como devueltas por get_ids de search) y devuelve los ficheros del mongo correspondiente que no estén bloqueados. Si se recibe un fichero bloqueado, lo omite y bloquea en el sphinx. @type ids: iterable de tuplas de tamaño 3 o mayor @param ids: lista de tuplas (mongoid, id servidor, id sphinx) @yield: cada uno de los resultados de los ids en los mongos ''' already = False files = filesdb.get_files(ids, servers_known = True, bl = None) for r in files: if r["bl"] == 0 or r["bl"] is None: yield r elif not already: already = True id_list = {i[0]:i[2] for i in ids} block_files( sphinx_ids=[id_list[mid2bin(i["_id"])] for i in files if i["bl"] != 0 and not i["bl"] is None ])
def block_files(sphinx_ids=(), mongo_ids=(), block=True): """ Recibe ids de sphinx u ObjectIDs de mongodb de ficheros y los bloquea en el sphinx (atributo bl a 1). """ sph = sphinxapi2.SphinxClient() sph.SetServer(current_app.config["SERVICE_SPHINX"], current_app.config["SERVICE_SPHINX_PORT"]) sph.SetConnectTimeout(current_app.config["SERVICE_SPHINX_CONNECT_TIMEOUT"]) sph.SetMatchMode(sphinxapi2.SPH_MATCH_FULLSCAN) sph.SetLimits(0, 1, 1, 1) sphinx_ids = list(sphinx_ids) if mongo_ids: # Si recibo ids de mongo, ejecuto una petición múltiple para encontrar # los ids de sphinx for i in xrange(0, len(mongo_ids), 32): # Proceso los ids de mongo en grupos de 32, que es el límite que # me permite sphinx for mongoid in mongo_ids[i : i + 32]: uri1, uri2, uri3 = struct.unpack("III", mid2bin(mongoid)) sph.ResetFilters() sph.SetFilter("uri1", [uri1]) sph.SetFilter("uri2", [uri2]) sph.SetFilter("uri3", [uri3]) sph.AddQuery("", "idx_files", "Searching fileid %s" % mid2hex(mongoid)) results = sph.RunQueries() if results: for result in results: if "matches" in result and result["matches"]: sphinx_ids.append(result["matches"][0]["id"]) if "warning" in result and result["warning"]: logging.warning(result["warning"]) else: logging.error(sph.GetLastError()) sph.ResetFilters() tr = sph.UpdateAttributes("idx_files", ["bl"], {i: [1 if block else 0] for i in sphinx_ids}) sph.Close() return tr == len(sphinx_ids) and tr == len(mongo_ids)
def download(file_id,file_name=None): ''' Muestra el archivo a descargar, votos, comentarios y archivos relacionados ''' def choose_filename_related(file_data): ''' Devuelve el nombre de fichero elegido ''' f=init_data(file_data) choose_filename(f) return f def comment_votes(file_id,comment): ''' Obtiene los votos de comentarios ''' comment_votes={} if "vs" in comment: for i,comment_vote in enumerate(usersdb.get_file_comment_votes(file_id)): if not comment_vote["_id"] in comment_votes: comment_votes[comment_vote["_id"][0:40]]=[0,0,0] if comment_vote["k"]>0: comment_votes[comment_vote["_id"][0:40]][0]+=1 else: comment_votes[comment_vote["_id"][0:40]][1]+=1 #si el usuario esta logueado y ha votado se guarda para mostrarlo activo if current_user.is_authenticated() and comment_vote["u"]==current_user.id: comment_votes[comment_vote["_id"][0:40]][2]=comment_vote["k"] return comment_votes #guardar los parametros desde donde se hizo la busqueda si procede args={} if request.referrer: querystring = urlparse(request.referrer).query if querystring: for params in u(querystring).encode("UTF-8").split("&"): param=params.split("=") if len(param) == 2: args[param[0]]=u(urllib.unquote_plus(param[1])) try: file_id=url2mid(file_id) except Exception as e: # Comprueba que se trate de un ID antiguo try: possible_file_id = filesdb.get_newid(file_id) if possible_file_id is None: logging.warn("%s - %s" % (e, file_id)) flash("link_not_exist", "error") abort(404) return redirect( url_for(".download", file_id=mid2url(possible_file_id), file_name=file_name), code=301) except filesdb.BogusMongoException as e: logging.exception(e) abort(503) try: data = filesdb.get_file(file_id, bl = None) except filesdb.BogusMongoException as e: logging.exception(e) abort(503) # intenta sacar el id del servidor de sphinx, # resuelve inconsistencias de los datos if not data: sid = get_id_server_from_search(file_id, file_name) if sid: try: data = filesdb.get_file(file_id, sid = sid, bl = None) except filesdb.BogusMongoException as e: logging.exception(e) abort(503) if data: if not data["bl"] in (0, None): if data["bl"] == 1: flash("link_not_exist", "error") elif data["bl"] == 3: flash("error_link_removed", "error") goback = True #block_files( mongo_ids=(data["_id"],) ) abort(404) else: flash("link_not_exist", "error") abort(404) #obtener los datos file_data=fill_data(data, True, file_name) if file_data["view"]["sources"]=={}: #si tiene todos los origenes bloqueados flash("error_link_removed", "error") abort(404) save_visited([file_data]) # Título title = u(file_data['view']['fn']) g.title = u"%s \"%s%s\"%s%s" % ( _(file_data['view']['action']).capitalize(), title[:50], "..." if len(title) > 50 else "", " - " if g.title else "", g.title) #obtener los archivos relacionados related_files = search_related(split_file(file_data["file"])[0][:10]) bin_file_id=mid2bin(file_id) ids=sorted({fid[0:3] for related in related_files for fid in get_ids(related) if fid[0]!=bin_file_id})[:5] files_related=[choose_filename_related(data) for data in get_files(ids)] #si el usuario esta logueado se comprueba si ha votado el archivo para el idioma activo vote=None if current_user.is_authenticated(): vote=usersdb.get_file_vote(file_id,current_user,g.lang) if vote is None: vote={"k":0} #formulario para enviar comentarios form = CommentForm(request.form) if request.method=='POST' and current_user.is_authenticated() and (current_user.type is None or current_user.type==0) and form.validate(): usersdb.set_file_comment(file_id,current_user,g.lang,form.t.data) form.t.data="" flash("comment_published_succesfully") #actualizar el fichero con la suma de los comentarios por idioma filesdb.update_file({"_id":file_id,"cs":usersdb.get_file_comments_sum(file_id),"s":file_data["file"]["s"]},direct_connection=True) #si tiene comentarios se guarda el número del comentario, el usuario que lo ha escrito, el comentario en si y los votos que tiene comments=[] if "cs" in file_data["file"]: comments=[(i,usersdb.find_userid(comment["_id"][0:24]),comment,comment_votes(file_id,comment)) for i,comment in enumerate(usersdb.get_file_comments(file_id,g.lang),1)] return render_template('files/download.html',file=file_data,args=args,vote=vote,files_related=files_related,comments=comments,form=form)
def download(file_id,file_name=None): ''' Muestra el archivo a descargar, votos, comentarios y archivos relacionados ''' def choose_filename_related(file_data): ''' Devuelve el nombre de fichero elegido ''' f=init_data(file_data) choose_filename(f) return f def comment_votes(file_id,comment): ''' Obtiene los votos de comentarios ''' comment_votes={} if "vs" in comment: for i,comment_vote in enumerate(usersdb.get_file_comment_votes(file_id)): if not comment_vote["_id"] in comment_votes: comment_votes[comment_vote["_id"][0:40]]=[0,0,0] if comment_vote["k"]>0: comment_votes[comment_vote["_id"][0:40]][0]+=1 else: comment_votes[comment_vote["_id"][0:40]][1]+=1 #si el usuario esta logueado y ha votado se guarda para mostrarlo activo if current_user.is_authenticated() and comment_vote["u"]==current_user.id: comment_votes[comment_vote["_id"][0:40]][2]=comment_vote["k"] return comment_votes if file_name is not None: g.title = _("download").capitalize()+" "+file_name+" - "+g.title else: g.title =_("download").capitalize() #guardar los parametros desde donde se hizo la busqueda si procede args={} if request.referrer: querystring = urlparse(request.referrer).query if querystring: for params in querystring.split("&"): param=params.split("=") if len(param) == 2: args[param[0]]=u(urllib.unquote_plus(param[1])) try: file_id=url2mid(file_id) except BaseException as e: logging.warn((e, file_id)) abort(404) data = filesdb.get_file(file_id, bl = None) if data: if not data["bl"] in (0, None): if data["bl"] == 1: flash("link_not_exist", "error") elif data["bl"] == 3: flash("error_link_removed", "error") goback = True #block_files( mongo_ids=(data["_id"],) ) abort(404) else: flash("link_not_exist", "error") abort(404) #obtener los datos file_data=fill_data(data, True, file_name) save_visited([file_data]) #obtener los archivos relacionados related_files = search_related(split_file(file_data["file"])[0][0:50]) bin_file_id=mid2bin(file_id) ids=sorted({fid for related in related_files for fid in get_ids(related) if fid[0]!=bin_file_id})[:5] files_related=[choose_filename_related(data) for data in get_files(ids)] #si el usuario esta logueado se comprueba si ha votado el archivo para el idioma activo vote=None if current_user.is_authenticated(): vote=usersdb.get_file_vote(file_id,current_user,g.lang) if vote is None: vote={"k":0} #formulario para enviar comentarios form = CommentForm(request.form) if request.method=='POST' and current_user.is_authenticated() and (current_user.type is None or current_user.type==0) and form.validate(): usersdb.set_file_comment(file_id,current_user,g.lang,form.t.data) form.t.data="" flash("comment_published_succesfully") #actualizar el fichero con la suma de los comentarios por idioma filesdb.update_file({"_id":file_id,"cs":usersdb.get_file_comments_sum(file_id),"s":file_data["file"]["s"]},direct_connection=True) #si tiene comentarios se guarda el número del comentario, el usuario que lo ha escrito, el comentario en si y los votos que tiene comments=[] if "cs" in file_data["file"]: comments=[(i,usersdb.find_userid(comment["_id"][0:24]),comment,comment_votes(file_id,comment)) for i,comment in enumerate(usersdb.get_file_comments(file_id,g.lang),1)] return render_template('files/download.html',file=file_data,args=args,vote=vote,files_related=files_related,comments=comments,form=form)
def get_id_server_from_search(self, file_id, file_name, timeout=1000): return self.sphinx.get_id_server_from_search(mid2bin(file_id), escape_string(" ".join(slugify(file_name).split(" ")[:4])) if file_name else "", timeout)