def get_files(self, ids, servers_known = False, bl = 0): ''' Devuelve los datos de los ficheros correspondientes a los ids dados en formato hexadecimal. @param ids: Lista de identificadores de los ficheros a recuperar. Si server_known es False, es una lista de cadenas. Si server_known es True, es una lista de tuplas, que incluyen el identificador del fichero y el número de servidor. @param servers_known: Indica si la lista de identificadores incluye el servidor donde se encuentra el fichero. @type bl: int o None @param bl: valor de bl para buscar, None para no restringir @rtype generator @return Generador con los documentos de ficheros ''' if len(ids) == 0: return () sids = defaultdict(list) # si conoce los servidores en los que están los ficheros, # se analiza ids como un iterable (id, servidor, ...) # y evitamos buscar los servidores if servers_known: for x in ids: sids[x[1]].append(hex2mid(x[0])) else: # averigua en qué servidor está cada fichero nindir = self.server_conn.foofind.indir.find({"_id": {"$in": [hex2mid(fid) for fid in ids]}}) for ind in nindir: if "t" in ind: # si apunta a otro id, lo busca en vez del id dado sids[ind["s"]].append(ind["t"]) else: sids[ind["s"]].append(ind["_id"]) self.server_conn.end_request() if len(sids) == 0: # Si no hay servidores, no hay ficheros return tuple() elif len(sids) == 1: # Si todos los ficheros pertenecen al mismo servidor, evita MultiAsync sid = sids.keys()[0] if not "conn" in self.servers_conn[sid]: return () conn = self.servers_conn[sid]["conn"] return end_request( conn.foofind.foo.find( {"_id":{"$in": sids[sid]}} if bl is None else {"_id":{"$in": sids[sid]},"bl":bl})) # función que recupera ficheros def get_server_files(async, sid, ids): ''' Recupera los datos de los ficheros con los ids dados del servidor mongo indicado por sid y los devuelve a través del objeto async. ''' if not "conn" in self.servers_conn[sid]: return conn = self.servers_conn[sid]["conn"] async.return_value(end_request(conn.foofind.foo.find( {"_id": {"$in": ids}} if bl is None else {"_id": {"$in": ids},"bl":bl})))
def update_file(self, data, remove=None, direct_connection=False, update_sphinx=True): ''' Actualiza los datos del fichero dado. @type data: dict @param data: Diccionario con los datos del fichero a guardar. Se debe incluir '_id', y es recomendable incluir 's' por motivos de rendimiento. @type remove: iterable @param remove: Lista de campos a quitar del registro. @type direct_connection: bool @param direct_connection: Especifica si se crea una conexión directa, ineficiente e independiente al foo primario. @type update_sphinx: bool @param update_sphinx: si se especifica bl, de este parámetro depende el si se conecta al sphinx para actualizarlo ''' update = {"$set":data.copy()} if remove is not None: update["$unset"] = {} for rem in remove: if rem in update["$set"]: del update["$set"][rem] update["$unset"][rem] = 1 fid = hex2mid(data["_id"]) _indir = self.server_conn.foofind.indir.find_one({"_id": fid}) if _indir and "t" in _indir: fid = hex2mid(_indir['t']) if "s" in data: server = str(data["s"]) else: try: server = str(self.get_file(fid, bl=None)["s"]) except (TypeError, KeyError) as e: logging.error("Se ha intentado actualizar un fichero que no se encuentra en la base de datos", extra=data) raise if update_sphinx and "bl" in data: try: file_name = i["fn"].itervalues().next()["n"] except: file_name = None block_files(mongo_ids=((i["_id"],file_name),), block=data["bl"]) for i in ("_id", "s"): if i in update["$set"]: del update["$set"][i] # TODO: update cache self.servers_conn[server].foofind.foo.update({"_id":fid}, update)
def get_file(self, fid, sid=None, bl=0): ''' Obtiene un fichero del servidor @type fid: str @param fid: id de fichero en hexadecimal @type sid: str @param sid: id del servidor @type bl: int o None @param bl: valor de bl para buscar, None para no restringir @rtype mongodb document @return Documento del fichero ''' mfid = hex2mid(fid) if sid is None: # averigua en qué servidor está el fichero ind = self.server_conn.foofind.indir.find_one({"_id":mfid}) if ind is None: return None if "t" in ind: mfid = ind["t"] sid = ind["s"] self.server_conn.end_request() if not "conn" in self.servers_conn[sid]: return None conn = self.servers_conn[sid]["conn"] return end_request(conn.foofind.foo.find_one( {"_id":mfid} if bl is None else {"_id":mfid,"bl":bl}), conn)
def getserver(fileid, filename=None): ''' Apaño porque Fer tarda mucho en arreglar indir ''' # TODO(felipe): posibilidad de bloquear form = GetServerForm(request.form) data = None if request.method == 'POST': fname = form.filename.data sid = get_id_server_from_search(hex2mid(fileid), fname) if sid: try: data = filesdb.get_file(fileid, sid = sid, bl = None) except filesdb.BogusMongoException as e: logging.exception(e) flash(e, "error") else: flash("admin_file_search_server_not_found", "error") elif filename: form.filename.data = filename return render_template('admin/getserver.html', fileid = fileid, searchform = form, file_data = data )
def update_user(self, data, remove=None): ''' Actualiza los datos del usuario @param data: Diccionario con los datos del usuario a guardar. @param remove: Lista de campos a quitar del registro. ''' update = {"$set":data.copy()} if "password" in data: update["$set"]["password"] = sha256(data["password"]).hexdigest() if remove is not None: update["$unset"]={} for rem in remove: del update["$set"][rem] update["$unset"][rem]=1 del update["$set"]["_id"] parser = self._userParse update["$set"].update( (key, parser[key](value) if key in parser else parser["*"](value)) for key, value in update["$set"].iteritems()) self.user_conn.foofind.users.update({"_id":hex2mid(data["_id"])}, update) self.user_conn.end_request()
def set_file_vote(self,file_id,user,lang,vote): ''' Guarda el voto en la colección y actualiza el archivo correspondiente con los nuevos datos ''' self.user_conn.foofind.vote.save({"_id":"%s_%s"%(file_id,user.id),"u":hex2mid(user.id),"k":user.karma if vote==1 else -user.karma,"d":datetime.utcnow(),"l":lang}) #para cada idioma guarda el karma, la cuenta total y la suma map_function=Code(''' function() { emit(this.l,{ k:this.k, c:new Array((this.k>0)?1:0,(this.k<0)?1:0), s:new Array((this.k>0)?this.k:0,(this.k<0)?this.k:0) }) }''') #suma todo y aplica la funcion 1/1+E^(-X) para que el valor este entre 0 y 1 reduce_function=Code(''' function(lang, vals) { c=new Array(0,0); s=new Array(0,0); for (var i in vals) { c[0]+=vals[i].c[0]; c[1]+=vals[i].c[1]; s[0]+=vals[i].s[0]; s[1]+=vals[i].s[1]; } return {t:1/(1+Math.exp(-((s[0]*c[0]+s[1]*c[1])/(c[0]+c[1])))), c:c, s:s}; }''') #tercer parametro para devolverlo en vez de generar una coleccion nueva votes=self.user_conn.foofind.vote.map_reduce(map_function,reduce_function,{"inline":1},query={'_id':{'$regex':"^%s"%file_id}}) #devolver un diccionario de la forma idioma:valores return end_request({values["_id"]:values["value"] for values in votes["results"]}, self.user_conn)
def get_file_comment_votes(self,file_id): ''' Recuper los votos de los comentarios de un archivo ''' cursor = self.user_conn.users.comment_vote.find({"f":hex2mid(file_id)}) for document in cursor: yield cursor self.user_conn.end_request()
def get_file_comments(self,file_id,lang): ''' Recupera los comentarios de un archivo ''' cursor = self.user_conn.users.comment.find({"f": hex2mid(file_id),"l": lang}) for document in cursor: yield document self.user_conn.end_request()
def remove_userid(self, userid): ''' Borra un usuario con el userid dado @type userid: hex u ObjectID @param userid: identificador del usuario ''' self.user_conn.foofind.users.remove({"_id":hex2mid(userid)})
def get_complaint(self, hexid): ''' Obtiene la información de un enlace reportado @type hexid: str @param hexid: cadena id de MongoDB en hexadecimal @rtype: MongoDB document or None @return: resultado ''' return end_request(self.pages_conn.foofind.complaint.find_one({"_id":hex2mid(hexid)}), self.pages_conn)
def get_file_comments_sum(self, file_id): ''' Cuenta los comentarios que hay para cada idioma ''' data = { lang["l"]: lang["c"] for lang in self.user_conn.users.comment.group( {"l": 1}, {'f': hex2mid(file_id)}, {"c": 0}, Code("function(o,p){p.c++}")) } self.user_conn.end_request() return data
def get_translation(self, hexid): ''' Obtiene la información de una traducción @type hexid: str @param hexid: cadena id de MongoDB en hexadecimal @rtype: MongoDB document or None @return: resultado ''' return end_request( self.pages_conn.foofind.translation.find_one({"_id":hex2mid(hexid)}), self.pages_conn)
def update_translation(self, data, remove=None): ''' Actualiza una traducción. @type data: dict @param data: datos ''' update = {"$set":data.copy()} if remove is not None: update["$unset"]=dict() for rem in remove: del update["$set"][rem] update["$unset"][rem]=1 del update["$set"]["_id"] self.pages_conn.users.translation.update({"_id":hex2mid(data["_id"])}, update) self.pages_conn.end_request()
def update_complaint(self, data, remove=None): ''' Actualiza una queja. @type data: dict @param data: datos ''' update = {"$set":data.copy()} if remove is not None: update["$unset"]=dict() for rem in remove: del update["$set"][rem] update["$unset"][rem]=1 del update["$set"]["_id"] self.pages_conn.foofind.complaint.update({"_id":hex2mid(data["_id"])}, update) self.pages_conn.end_request()
def update_file(self, data, remove=None, direct_connection=False, update_sphinx=True): ''' Actualiza los datos del fichero dado. @type data: dict @param data: Diccionario con los datos del fichero a guardar. Se debe incluir '_id', y es recomendable incluir 's' por motivos de rendimiento. @type remove: iterable @param remove: Lista de campos a quitar del registro. @type direct_connection: bool @param direct_connection: Especifica si se crea una conexión directa, ineficiente e independiente al foo primario. @type update_sphinx: bool @param update_sphinx: si se especifica bl, de este parámetro depende el si se conecta al sphinx para actualizarlo ''' update = {"$set":data.copy()} if remove is not None: update["$unset"]=dict() for rem in remove: del update["$set"][rem] update["$unset"][rem]=1 fid = hex2mid(data["_id"]) if "s" in data: server = data["s"] else: try: server = self.get_file(fid, bl=None)["s"] except (TypeError, KeyError) as e: logging.error("Se ha intentado actualizar un fichero que no se encuentra en la base de datos", extra=data) raise if update_sphinx and "bl" in data: block_files(mongo_ids=(i["_id"],), block=data["bl"]) for i in ("_id", "s"): if i in update["$set"]: del update["$set"][i] if direct_connection: # TODO: update cache with self.servers_conn[server].contextmaster as context: context.conn.foofind.foo.update({"_id":fid}, update) context.conn.end_request() else: #TODO(felipe): implementar usando el EventManager raise NotImplemented("No se ha implementado una forma eficiente de actualizar un foo")
def update_file(self, data, remove=None, direct_connection=False, update_sphinx=True): ''' Actualiza los datos del fichero dado. @type data: dict @param data: Diccionario con los datos del fichero a guardar. Se debe incluir '_id', y es recomendable incluir 's' por motivos de rendimiento. @type remove: iterable @param remove: Lista de campos a quitar del registro. @type direct_connection: bool @param direct_connection: Especifica si se crea una conexión directa, ineficiente e independiente al foo primario. @type update_sphinx: bool @param update_sphinx: si se especifica bl, de este parámetro depende el si se conecta al sphinx para actualizarlo ''' update = {"$set":data.copy()} if remove is not None: update["$unset"]=dict() for rem in remove: del update["$set"][rem] update["$unset"][rem]=1 fid = hex2mid(data["_id"]) if "s" in data: server = data["s"] else: server = self.get_file(fid, bl=None)["s"] if update_sphinx and "bl" in data: block_files(mongo_ids=(i["_id"],), block=data["bl"]) for i in ("_id", "s"): if i in update["$set"]: del update["$set"][i] if direct_connection: # TODO: update cache foocon = self.connect_foo(server,1) foocon.foofind.foo.update({"_id":fid}, update) foocon.end_request() else: raise NotImplemented("No se ha implementado una forma eficiente de actualizar un foo")
def lock_file(complaint_id=None): ''' Información y bloqueo de ficheros, puede recibir un id de queja, o una lista de ids (en hex) de ficheros separados por la letra "g" ''' page = request.args.get("page", 0, int) mode = request.args.get("show", "old", str) size = request.args.get("size", 15, int) filenames = {} bugged = [] fileids = () if request.method == 'POST': if not "fileids" in request.form: searchform = BlockFileSearchForm(request.form) identifiers = searchform.identifier.data.split() if searchform.mode.data == "hexid": fileids = [ mid2hex(hex2mid(i)) for i in identifiers if all(x in "0123456789abcdef" for x in i) ] elif searchform.mode.data == "b64id": fileids = [ mid2hex(url2mid(i)) for i in identifiers if all(x in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!-" for x in i) and (len(i)*8)%6 == 0 ] elif searchform.mode.data == "url": filenames.update( ( mid2hex(fileurl2mid(i)), u".".join(urllib2.unquote(i.split("/")[-1]).split(".")[:-1]) ) for i in identifiers if i.startswith("http") and len(i.split("//")[1].split("/")) > 3 ) fileids = filenames.keys() if not fileids: return redirect(url_for('admin.locks', page=page, mode=mode, size=size)) else: block = request.form.get("block", False, bool) unblock = request.form.get("unblock", False, bool) if block or unblock: # submit confirmar if complaint_id: pagesdb.update_complaint({"_id":complaint_id,"processed":True}) fileids = dict(i.split(":") for i in request.form["fileids"].split(",")) sphinx_block = [] sphinx_unblock = [] for fileid, server in fileids.iteritems(): (sphinx_block if block and not unblock else sphinx_unblock).append(fileid) req = {"_id":fileid, "bl": int(block and not unblock)} if server: req["s"] = int(server) # si recibo el servidor, lo uso por eficiencia try: # TODO(felipe): comprobar en qué casos se puede llegar aquí sin "s" filesdb.update_file(req, direct_connection=True, update_sphinx=False) except: flash("No se ha podido actualizar el fichero con id %s" % fileid, "error") if sphinx_block: block_files_in_sphinx(mongo_ids=sphinx_block, block=True) if sphinx_unblock: block_files_in_sphinx(mongo_ids=sphinx_unblock, block=False) flash("admin_locks_locked" if block else "admin_locks_unlocked", "success") elif request.form.get("cancel", False, bool): # submit cancelar if complaint_id: pagesdb.update_complaint({"_id":complaint_id,"processed":True}) flash("admin_locks_not_locked", "success") return redirect(url_for('admin.locks', page=page, mode=mode, size=size)) complaint_data = None # Hay un único o ningún registro de queja por formulario files_data = OrderedDict() # Pueden haber varios ficheros por formulario if complaint_id: # Si hay queja, sólo hay una url, la de la queja complaint_data = pagesdb.get_complaint(complaint_id) if complaint_data and "urlreported" in complaint_data: # extracción el id de complaint["urlreported"] de base64 a hexadecimal files_data[mid2hex(fileurl2mid(complaint_data["urlreported"]))] = None elif fileids: # Si no hay queja, los ficheros se sacan de la url files_data.update((i,None) for i in fileids) # Suponemos si queremos bloquear, desbloquear, o mostrar las dos opciones # dependiendo de sí de los ficheros están bloqueados o no # además rellenamos la información de los ficheros blocked = 0 unblocked = 0 for fileid in files_data.iterkeys(): data = filesdb.get_file(fileid, bl=None) if data is None and fileid in filenames: bugged.append(fileid) sid = get_id_server_from_search(fileid, filenames[fileid]) if sid: data = filesdb.get_file(fileid, sid = sid, bl = None) files_data[fileid] = data or {} if not "bl" in files_data[fileid] or files_data[fileid]["bl"] == 0: unblocked += 1 else: blocked += 1 return render_template('admin/lock_file.html', page_title=_('admin_locks_fileinfo'), complaint_data=complaint_data, files_data=files_data, filenames = filenames, bugged = bugged, fileids=",".join( "%s:%s" % (fileid, prop["s"] if "s" in prop else "") for fileid, prop in files_data.iteritems()), blocked=None if blocked and unblocked else blocked > 0, list_mode=mode, page=page, title=admin_title('admin_losfdcks_fileinfo'))
def choose_filename(f,text=False): ''' Elige el archivo correcto ''' text=slugify(text) if text else text srcs = f['file']['src'] fns = f['file']['fn'] chosen = None max_count = -1 has_text = 0 try: for hexuri,src in srcs.items(): if 'bl' in src and src['bl']!=0: continue this_has_text=0 for crc,srcfn in src['fn'].items(): #si no tiene nombre no se tiene en cuenta m = srcfn['m'] if len(fns[crc]['n'])>0 else 0 if 'c' in fns[crc]: fns[crc]['c']+=m else: fns[crc]['c']=m if text: slugified_fn = slugify(fns[crc]['n']).strip() if len(slugified_fn)>0: #TODO hace lo mismo que para poner el nombre en negrita y sacar el mejor texto aunque no tenga tildes o no venga unido por espacios if slugified_fn.upper().find(text.upper())!=-1: this_has_text = 2000 else: matches = 0 for word in [re.escape(w) for w in text.split(" ")]: matches += len(re.findall(r"/((?:\b|_)%s(?:\b|_))/i"%word, slugified_fn)) if matches>0: this_has_text = 1000 + matches f['file']['fn'][crc]['tht'] = this_has_text better = fns[crc]['c']>max_count if this_has_text > has_text or (better and this_has_text==has_text): has_text = this_has_text chosen = crc max_count = fns[crc]['c'] except KeyError as e: #para los sources que tienen nombre pero no estan en el archivo logging.exception(e) f['view']['url'] = mid2url(hex2mid(f['file']['_id'])) if chosen: filename = fns[chosen]['n'] ext = fns[chosen]['x'] else: #uses filename from src srcurl = "" for hexuri,src in srcs.items(): if src['url'].find("/")!=-1: srcurl = src['url'] if srcurl=="": return srcurl = srcurl[srcurl.rfind("/")+1:] ext = srcurl[srcurl.rfind(".")+1:] filename = srcurl[0:srcurl.rfind(".")] filename = Markup(filename).striptags()[:512] if not ext in EXTENSIONS: filename += ext ext="" nfilename = filename else: #clean filename end = filename.upper().rfind("."+ext.upper()) if end == -1: nfilename = filename else: nfilename = filename.strip()[0:end] f['view']['fn'] = filename #TODO para los tipo archive buscar el tipo real en el nombre (mp3,avi...) f['view']['fnx'] = ext f['view']['efn'] = filename.replace(" ", "%20") #poner bonito nombre del archivo if nfilename.find(" ")==-1: nfilename = nfilename.replace(".", " ") f['view']['nfn'] = nfilename.replace("_", " ") #nombre del archivo escapado para generar las url de descarga f['view']['qfn'] = u(filename).encode("UTF-8") #nombre del archivo con las palabras que coinciden con la busqueda resaltadas if not text:# or not has_text: f['view']['fnh'] = f['view']['fnhs'] = filename else: f['view']['fnh'], f['view']['fnhs'] = highlight(text,filename,True) return has_text>0
def choose_filename(f,text_cache=None): ''' Elige el archivo correcto ''' srcs = f['file']['src'] fns = f['file']['fn'] chosen = None max_count = -1 current_weight = -1 if text_cache and text_cache[0] in fns: # Si text es en realidad un ID de fn chosen = text_cache[0] else: for hexuri,src in srcs.items(): if 'bl' in src and src['bl']!=0: continue for crc,srcfn in src['fn'].items(): if crc not in fns: #para los sources que tienen nombre pero no estan en el archivo continue #si no tiene nombre no se tiene en cuenta m = srcfn['m'] if len(fns[crc]['n'])>0 else 0 if 'c' in fns[crc]: fns[crc]['c']+=m else: fns[crc]['c']=m text_weight = 0 if text_cache: fn_parts = slugify(fns[crc]['n']).strip().split(" ") if len(fn_parts)>0: text_words = slugify(text_cache[0]).split(" ") # valora numero y orden coincidencias last_pos = -1 max_length = length = 0 occurrences = [0]*len(text_words) for part in fn_parts: pos = text_words.index(part) if part in text_words else -1 if pos != -1 and (last_pos==-1 or pos==last_pos+1): length += 1 else: if length > max_length: max_length = length length = 0 if pos != -1: occurrences[pos]=1 last_pos = pos if length > max_length: max_length = length text_weight = sum(occurrences)*100 + max_length f['file']['fn'][crc]['tht'] = text_weight better = fns[crc]['c']>max_count if text_weight > current_weight or (better and text_weight==current_weight): current_weight = text_weight chosen = crc max_count = fns[crc]['c'] f['view']['url'] = mid2url(hex2mid(f['file']['_id'])) f['view']['fnid'] = chosen if chosen: filename = fns[chosen]['n'] ext = fns[chosen]['x'] else: #uses filename from src filename = "" for hexuri,src in srcs.items(): if src['url'].find("/")!=-1: filename = src['url'] if filename=="": return filename = filename[filename.rfind("/")+1:] ext = filename[filename.rfind(".")+1:] filename = filename[0:filename.rfind(".")] #TODO si no viene nombre de archivo buscar en los metadatos para formar uno (por ejemplo serie - titulo capitulo) filename = extension_filename(filename,ext) f['view']['fn'] = filename.replace("?", "") f['view']['qfn'] = qfn = u(filename).encode("UTF-8") #nombre del archivo escapado para generar las url de descarga f['view']['pfn'] = urllib.quote(qfn).replace(" ", "%20") # P2P filename nfilename = seoize_text(filename, " ",True, 0) f['view']['nfn'] = nfilename # añade el nombre del fichero como palabra clave g.keywords.update(set(keyword for keyword in nfilename.split(" ") if len(keyword)>1)) #nombre del archivo con las palabras que coinciden con la busqueda resaltadas if text_cache: f['view']['fnh'], f['view']['fnhs'] = highlight(text_cache[2],filename,True) else: f['view']['fnh'] = filename #esto es solo para download que nunca tiene text return current_weight>0 # indica si ha encontrado el texto buscado
def choose_filename(f,text=False): ''' Elige el archivo correcto ''' srcs = f['file']['src'] fns = f['file']['fn'] hist= "" chosen="" maxCount = 0 hasText = 0 for hexuri,src in srcs.items(): if 'bl' in src and src['bl']!=0: continue srcfns = src['fn'] for crc,srcfn in srcfns.items(): fnn = fns[crc]['n'] if len(fnn.strip())==0: continue thisHasText=0 if 'c' in fns[crc]: fns[crc]['c']+=srcfn['m'] else: fns[crc]['c']=srcfn['m'] if text: if fnn.upper().find(text.upper())!=-1: thisHasText = 2000 else: matches = 0 for word in [re.escape(w) for w in text.split(" ")]: matches += len(re.findall(r"/((?:\b|_)%s(?:\b|_))/i"%word, fnn)) if matches>0: thisHasText = 1000 + matches f['file']['fn'][crc]['tht'] = thisHasText better = fns[crc]['c']>maxCount if thisHasText > hasText or (better and thisHasText==hasText): hasText = thisHasText chosen = crc maxCount = fns[crc]['c'] f['view']['url'] = mid2url(hex2mid(f['file']['_id'])) if chosen!="": filename = fns[chosen]['n'] ext = fns[chosen]['x'] else: #uses filename from src srcurl = "" for crc,srcfn in srcfns.items(): if src['url'].find("/")!=-1: srcurl = src['url'] if srcurl=="": return srcurl = srcurl[srcurl.rfind("/")+1:] ext = srcurl[srcurl.rfind(".")+1:] filename = srcurl[0:srcurl.rfind(".")] if not ext in current_app.config["EXTENSIONS"].keys(): filename += ext ext="" nfilename = filename else: #clean filename end = filename.upper().rfind("."+ext.upper()) if end == -1: nfilename = filename else: nfilename = filename.strip()[0:end] f['view']['fn'] = filename f['view']['efn'] = filename.replace(" ", "%20") f['view']['fnx'] = ext #nombre del archivo con las palabras que coinciden con la busqueda resaltadas if not text: f['view']['fnh']=filename else: separators = u"".join({i for i in filename if not unicodedata.category(i)[0] in ("N","L")}) separated_text = tuple(multipartition(text.lower(), separators)) f['view']['fnh'] = u"".join( (u"<strong>%s</strong>" % filename_part) if filename_part.lower() in separated_text and not filename_part in separators else filename_part for filename_part in multipartition(filename, separators) ) if nfilename.find(" ")==-1: nfilename = nfilename.replace(".", " ") nfilename = nfilename.replace("_", " ") f['view']['nfn'] = nfilename
def main(processes, part, server, xml_file, fileid, favs, stats_update): global sources, sources_innergroups, sources_domains, counters batch_size = 1024*10 setup_logging(SentryHandler(Client(config["SENTRY_SPHINX_DNS"]))) fields, attrs = get_definitions() if favs: attrs.append( {"name":"list", "type":"str", "bits":64, # Group "field": "_g" }) sources = {int(float(s["_id"])):s for s in server_conn.foofind.source.find({"$or": [{"crbl": { "$exists" : False } }, {"crbl":0}]})} sources_domains = {source_id:"%s%s"%(FILTER_PREFIX_SOURCE, source["d"].lower().replace(".","")) for source_id, source in sources.iteritems()} g = globals() def get_function(i): if not (i in sources and "ig" in sources[i]): return None try: ig = sources[i]["ig"] return partial(g["innergroup_%s"%ig[0]], *ig[1:]) except: return None sources_innergroups = [None]+[get_function(i+1) for i in xrange(0,max(sources.iterkeys()))] if not server: servers = server_conn.foofind.server.find_one({"_id":part}) server = "mongodb://%s:%d"%(servers["ip"],servers["p"]) ntts_server = config["DATA_SOURCE_ENTITIES"] xmlpipe2.set_globals(fields, attrs, init_file, fav_stats if favs else file_stats) incremental_index = False if favs: counters.append(0) user_conn = pymongo.Connection(config["DATA_SOURCE_USER"]) # TO-DO: maybe won't work with shared connections settings xml = xmlpipe2.XmlPipe2(processes, fields, attrs, None, generate_fav_id) xml.generate_header() for doc in user_conn.foofind.favfile.find({"files.server":part}): if not doc.get("files", None): continue counters[0] = 0 files_filter = {"_id":{"$in":[f["id"] for f in doc["files"]]}} xml.generate(server, ntts_server, (doc["name"], doc["user_id"] << 24, part << 16), files_filter, batch_size, headers=False) xml.generate_footer() user_conn.end_request() else: counters.extend((0,)*2**16) # 16 bits del hash hacen el contador files_filter = {'bl': 0} if fileid: files_filter["_id"] = hex2mid(fileid) stats = {"_id": part, "sg":defaultdict(int), "z":defaultdict(int), "l":defaultdict(int), "lc":defaultdict(int), "la":defaultdict(float), "lpa":defaultdict(float), "zc":defaultdict(int), "za":defaultdict(float), "zpa":defaultdict(float), "ra":defaultdict(float), "rpa":defaultdict(float), "rM":defaultdict(float), "rc":defaultdict(int), "__dtags":{tag:{subcat:0 for word, subcat in DYNAMIC_TAGS[tag].iteritems() if word==subcat} for tag in DYNAMIC_TAGS.iterkeys()}} if xml_file: if exists(xml_file): incremental_index = True line = last_line(xml_file) counters, stop_set, saved_stats, last_count = json.loads(line[4:-3]) stop_set = set(stop_set) stop_set_len = len(stop_set) for key, value in saved_stats.iteritems(): if isinstance(value, defaultdict): stats[key].update(value) else: # primer fichero stop_set = set() stop_set_len = 10 last_count = 0 xml = xmlpipe2.XmlPipe2(processes, fields, attrs, stats, generate_id) # genera cabeceras para el primer fichero if not incremental_index: xml.generate_header() new_stop_set = xml.generate(server, ntts_server, part<<16, files_filter, batch_size, stop_set=stop_set, stop_set_len=stop_set_len, last_count=last_count, headers=False) # solo imprime estado si ha añadido algun fichero if xml.count: print "\n<!--%s-->"%json.dumps((counters, list(new_stop_set), stats, xml.total_count)), else: xml = xmlpipe2.XmlPipe2(processes, fields, attrs, stats, generate_id) xml.generate(server, ntts_server, part<<16, files_filter, batch_size) dtags_stats = stats["__dtags"] del stats["__dtags"] if stats_update and not incremental_index: for tag, dtags in dtags_stats.iteritems(): server_conn.torrents.subcategory.update({"_id":tag}, {"$set":{"sc.%s.c"%dtag:count for dtag, count in dtags.iteritems()}}) server_conn.foofind.search_stats.insert({"_id":part, "d0":time(), "d1":time()}) server_conn.foofind.search_stats.update({"_id":part}, {"$set":stats}) server_conn.foofind.server.update({"_id":part},{"$set":{"ss":0}})
def find_userid(self,userid): ''' Busca los datos del usuario a partir del id ''' return self.__search({"_id":hex2mid(userid)})
def get_files(self, ids, servers_known = False, bl = 0): ''' Devuelve los datos de los ficheros correspondientes a los ids dados en formato hexadecimal. @param ids: Lista de identificadores de los ficheros a recuperar. Si server_known es False, es una lista de cadenas. Si server_known es True, es una lista de tuplas, que incluyen el identificador del fichero y el número de servidor. @param servers_known: Indica si la lista de identificadores incluye el servidor donde se encuentra el fichero. @type bl: int o None @param bl: valor de bl para buscar, None para no restringir @rtype generator @return Generador con los documentos de ficheros ''' if not ids: return () sids = defaultdict(list) # si conoce los servidores en los que están los ficheros, # se analiza ids como un iterable (id, servidor, ...) # y evitamos buscar los servidores if servers_known: for x in ids: sids[x[1]].append(hex2mid(x[0])) else: # averigua en qué servidor está cada fichero nindir = self.server_conn.foofind.indir.find({"_id": {"$in": [hex2mid(fid) for fid in ids]}, "s": {"$exists": 1}}) for ind in nindir: indserver = str(int(ind["s"])) # Bug en indir: 's' como float if indserver in self.servers_conn: if "t" in ind: # si apunta a otro id, lo busca en vez del id dado sids[indserver].append(ind["t"]) else: sids[indserver].append(ind["_id"]) self.server_conn.end_request() lsids = len(sids) if lsids == 0: # Si no hay servidores, no hay ficheros return () elif lsids == 1: k, v = sids.iteritems().next() return self._get_server_files((k, v, bl)) else: # crea el pool de hilos si no existe if not self.thread_pool: self.thread_pool = ThreadPool(processes=self.thread_pool_size) # obtiene la información de los ficheros de cada servidor results = [] chunks = self.thread_pool.imap_unordered(self._get_server_files, ((k, v, bl) for k, v in sids.iteritems())) end = time.time()+self.get_files_timeout try: for i in xrange(len(sids)): now = time.time() if now>end: break for r in chunks.next(end-now): results.append(r) except TimeoutError: pass except BaseException as e: logging.error("Error on get_files.") return results
def get_file_comment_votes(self,file_id): ''' Recuper los votos de los comentarios de un archivo ''' return end_request(self.user_conn.foofind.comment_vote.find({"f":hex2mid(file_id)}))
def get_file_comments(self,file_id,lang): ''' Recupera los comentarios de un archivo ''' return end_request(self.user_conn.foofind.comment.find({"f":hex2mid(file_id),"l":lang}))
def get_files_metadata(files, block_on_sphinx=True): names = {hex2mid(i["id"]):i["name"] for i in files} for f in get_files( [(i["id"], i["server"]) for i in files], block_on_sphinx = block_on_sphinx): yield fill_data(f, names[f["_id"]])
def db_confirm(collection, document_id=None): """ Confirmación de edición de base de datos """ page = request.args.get("page", 0, int) grps = request.args.get("mode", "all", str) mode = request.args.get("show", "current", str) size = request.args.get("size", 15, int) goback = lambda: redirect(url_for(url_id, page=page, mode=grps, show=mode, size=size)) document = json.loads(request.form.get("defaults")) document_writeable = json.loads(request.form.get("editable")) request_form_dict = MultiDict(request.form) success_msgid = "admin_saved" unchanged_msgid = "admin_nochanges" if collection == "user": page_title = "admin_users" form_title = "admin_users_info" success_msgid = "admin_users_updated" url_id = "admin.users" save_fnc = lambda data: usersdb.update_user(data) new_password = request_form_dict.pop(db_fnm("new password"), None) if new_password: document_writeable.append("password") request_form_dict[db_fnm("password")] = new_password elif collection == "origin": page_title = "admin_origins_info" form_title = "admin_origins_info" url_id = "admin.origins" save_fnc = lambda data: filesdb.update_source(data) if request.form.get("confirmed", "False") == "True": # La petición ha sido realizada por el formulario de confirmación, # lo procesamos. check_form = expanded_instance( EditForm, {db_fnm(k): BooleanField(k) for k in document_writeable}, request_form_dict ) data = {k: document[k] for k in document_writeable if check_form[db_fnm(k)].data} if data: data["_id"] = hex2mid(document_id) save_fnc(data) flash(success_msgid, "success") return goback() else: flash(unchanged_msgid, "error") return goback() else: # No se trata del petición confirmada, procesamos el formulario como # viene de db_edit, generamos el formulario de confirmación. edit_form = expanded_instance( EditForm, {db_fnm(k): TextField(k, default=db_dtf(collection, k, document[k])) for k in document_writeable}, request_form_dict, ) document_changes = [ (k, document[k], db_ftd(collection, k, edit_form[db_fnm(k)].data)) for k in document_writeable if edit_form[db_fnm(k)].data != db_dtf(collection, k, document[k]) ] if document_changes: check_form = expanded_instance( EditForm, {db_fnm(k): BooleanField(k, default=False) for k, w, w in document_changes} ) check_form.defaults.data = json.dumps({k: v for k, w, v in document_changes}) check_form.editable.data = json.dumps([k for k, w, v in document_changes]) check_form.confirmed.data = True else: flash(unchanged_msgid, "error") return goback() return render_template( "admin/confirm.html", collection=collection, document_id=document_id, title=admin_title(page_title), page_title=_(page_title), check_form=check_form, form_title=_(form_title), fieldname=db_fnm, repr=repr, document_changes=document_changes, list_mode=grps, mode=mode, page_size=size, page=page, )