Exemplo n.º 1
0
def revert_api(request, ref, lang, version, revision):
	"""
	API for reverting a text segment to a previous revision.
	"""
	if not request.user.is_authenticated():
		return jsonResponse({"error": "You must be logged in to revert changes."})

	if request.method != "POST":
		return jsonResponse({"error": "Unsupported HTTP method."})

	revision = int(revision)
	version = version.replace("_", " ")
	ref = norm_ref(ref)
	if not ref:
		# pass along the error message if norm_ref failed
		return jsonResponse(parse_ref(ref))

	existing = get_text(ref, commentary=0, version=version, lang=lang)
	if "error" in existing:
		return jsonResponse(existing)

	text = {
		"versionTitle": version,
		"versionSource": existing["versionSource"] if lang == "en" else existing["heVersionSource"],
		"language": lang,
		"text": text_at_revision(ref, version, lang, revision)
	}

	return jsonResponse(save_text(ref, text, request.user.id, type="revert text"))
Exemplo n.º 2
0
def count_sources(sources, sheet_id):
	global refs, texts, categories
	global sources_count, comments_count, outside_count, untrans_count
	global untrans_texts, untrans_categories, untrans_refs
	global fragments, fragments_count

	for s in sources:
		if "ref" in s:
			sources_count += 1
			pRef = parse_ref(s["ref"])
			if "error" in pRef:
				continue
			refs[s["ref"]] += 1
			texts[pRef["book"]] += 1
			categories[pRef["categories"][0]] += 1

			if not is_ref_translated(s["ref"]):
				untrans_categories[pRef["categories"][0]] +=1 
				untrans_texts[pRef["book"]] += 1
				untrans_refs[s["ref"]] += 1
				untrans_count += 1

				en = strip_tags(s.get("text", {}).get("en", ""))
				if len(en) > 25:
					fragments[s["ref"]].append(sheet_id)
					fragments_count += 1

			if "subsources" in s:
				count_sources(s["subsources"], sheet_id)
		
		elif "comment" in s:
			comments_count += 1
		
		elif "outsideText" in s or "outsideBiText" in s:
			outside_count += 1
Exemplo n.º 3
0
def get_sheets_for_ref(ref, pad=True, context=1):
	"""
	Returns a list of sheets that include ref,
	formating as need for the Client Sidebar.
	"""	
	ref = norm_ref(ref, pad=pad, context=context)
	ref_re = make_ref_re(ref)
	results = []
	sheets = db.sheets.find({"included_refs": {"$regex": ref_re}, "status": {"$in": LISTED_SHEETS}}, 
								{"id": 1, "title": 1, "owner": 1, "included_refs": 1})
	for sheet in sheets:
		# Check for multiple matching refs within this sheet
		matched = [ref for ref in sheet["included_refs"] if regex.match(ref_re, ref)]
		for match in matched:
			com = {}
			anchorRef = parse_ref(match)

			com["category"]    = "Sheets"
			com["type"]        = "sheet"
			com["owner"]       = sheet["owner"]
			com["_id"]         = str(sheet["_id"])
			com["anchorRef"]   = match
			com["anchorVerse"] = anchorRef["sections"][-1]
			com["public"]      = True
			com["commentator"] = user_link(sheet["owner"])
			com["text"]        = "<a class='sheetLink' href='/sheets/%d'>%s</a>" % (sheet["id"], strip_tags(sheet["title"]))

			results.append(com)

	return results
Exemplo n.º 4
0
def url_ref(value):
	if not value:
		return ""
	pRef = parse_ref(value, pad=False)
	if "error" in pRef:
		return value
	link = '<a href="/' + url(value) + '">' + value + '</a>'
	return mark_safe(link)
Exemplo n.º 5
0
def url_ref(value):
    if not value:
        return ""
    pRef = parse_ref(value, pad=False)
    if "error" in pRef:
        return value
    link = '<a href="/' + url(value) + '">' + value + '</a>'
    return mark_safe(link)
Exemplo n.º 6
0
def url_ref(value):
	if value in url_ref_cache:
		return url_ref_cache[value]
	if not value:
		return ""
	pRef = parse_ref(value, pad=False)
	if "error" in pRef:
		return value
	link = '<a href="/' + url(value) + '">' + value + '</a>'
	url_ref_cache[value] = mark_safe(link)
	return url_ref_cache[value]
Exemplo n.º 7
0
def reviews_api(request, ref=None, lang=None, version=None, review_id=None):
	if request.method == "GET":
		if ref and lang and version:
			pRef = parse_ref(ref)
			if "error" in pRef:
				return jsonResponse(pRef)
			ref = make_ref(pRef)
			version = version.replace("_", " ")

			reviews = get_reviews(ref, lang, version)
			last_edit = get_last_edit_date(ref, lang, version)
			score_since_last_edit = get_review_score_since_last_edit(ref, lang, version, reviews=reviews, last_edit=last_edit)

			for r in reviews:
				r["date"] = r["date"].isoformat()

			response = {
				"ref":                ref,
				"lang":               lang,
				"version":            version,
				"reviews":            reviews,
				"reviewCount":        len(reviews),
				"scoreSinceLastEdit": score_since_last_edit,
				"lastEdit":           last_edit.isoformat() if last_edit else None,
			}
		elif review_id:
			response = {}

		return jsonResponse(response)


	elif request.method == "POST":
		if not request.user.is_authenticated():
			return jsonResponse({"error": "You must be logged in to write reviews."})
		j = request.POST.get("json")
		if not j:
			return jsonResponse({"error": "No post JSON."})
		j = json.loads(j)
		
		response = save_review(j, request.user.id)
		return jsonResponse(response)

	elif request.method == "DELETE":
		if not review_id:
			return jsonResponse({"error": "No review ID given for deletion."})

		return jsonResponse(delete_review(review_id, request.user.id))

	else:
		return jsonResponse({"error": "Unsuported HTTP method."})
Exemplo n.º 8
0
def links_api(request, link_id_or_ref=None):
	"""
	API for textual links.
	Currently also handles post notes.
	"""
	#TODO: can we distinguish between a link_id (mongo id) for POSTs and a ref for GETs?
	if request.method == "GET":
		if link_id_or_ref is None:
			return jsonResponse({"error": "Missing text identifier"})
		#TODO is there are better way to validate the ref from GET params?
		pRef = parse_ref(link_id_or_ref)
		if "error" in pRef:
			return jsonResponse(pRef)
		with_text = int(request.GET.get("with_text", 1))
		return jsonResponse(get_links(link_id_or_ref, with_text))

	if request.method == "POST":
		j = request.POST.get("json")
		if not j:
			return jsonResponse({"error": "Missing 'json' parameter in post data."})
		j = json.loads(j)
		if isinstance(j, list):
			func = save_link_batch
		else:
			# use the correct function if params indicate this is a note save
			func = save_note if "type" in j and j["type"] == "note" else save_link

		if not request.user.is_authenticated():
			key = request.POST.get("apikey")
			if not key:
				return jsonResponse({"error": "You must be logged in or use an API key to add, edit or delete links."})
			apikey = db.apikeys.find_one({"key": key})
			if not apikey:
				return jsonResponse({"error": "Unrecognized API key."})
			return jsonResponse(func(j, apikey["uid"], method="API"))
		else:
			@csrf_protect
			def protected_link_post(request):
				response = func(j, request.user.id)
				return jsonResponse(response)
			return protected_link_post(request)
	
	if request.method == "DELETE":
		if not link_id_or_ref:
			return jsonResponse({"error": "No link id given for deletion."})

		return jsonResponse(delete_link(link_id_or_ref, request.user.id))

	return jsonResponse({"error": "Unsuported HTTP method."})
Exemplo n.º 9
0
def ref_link(value, absolute=False):
	"""
	Transform a ref into an <a> tag linking to that ref.
	e.g. "Genesis 1:3" -> "<a href='/Genesis.1.2'>Genesis 1:2</a>"
	"""
	if value in ref_link_cache:
		return ref_link_cache[value]
	if not value:
		return ""
	pRef = parse_ref(value, pad=False)
	if "error" in pRef:
		return value
	link = '<a href="/' + url_ref(value) + '">' + value + '</a>'
	ref_link_cache[value] = mark_safe(link)
	return ref_link_cache[value]
Exemplo n.º 10
0
def versions_api(request, ref):
	"""
	API for retrieving available text versions list of a ref.
	"""
	pRef = parse_ref(ref)
	if "error" in pRef:
		return jsonResponse(pRef)
	versions = db.texts.find({"title": pRef["book"]})
	results = []
	for v in versions:
		results.append({ 
				"title": v["versionTitle"],
				"source": v["versionSource"],
				"langauge": v["language"]
			})

	return jsonResponse(results)
Exemplo n.º 11
0
def segment_history(request, ref, lang, version):
	"""
	View revision history for the text segment named by ref / lang / version. 
	"""
	nref = norm_ref(ref)
	if not nref:
		return HttpResponse("There was an error in your text reference: %s" % parse_ref(ref)["error"])

	version = version.replace("_", " ")
	filter_type = request.GET.get("type", None)
	history = text_history(nref, version, lang, filter_type=filter_type)

	email = request.user.email if request.user.is_authenticated() else False
	return render_to_response('activity.html', 
							 {'activity': history,
							   "single": True,
							   "ref": nref, 
							   "lang": lang, 
							   "version": version,
							   'email': email,
							   'filter_type': filter_type,
							 }, 
							 RequestContext(request))
Exemplo n.º 12
0
def translation_flow(request, ref):
	"""
	Assign a user a paritcular bit of text to translate within 'ref',
	either a text title or category. 
	"""
	ref = ref.replace("_", " ")
	generic_response = { "title": "Help Translate %s" % ref, "content": "" }
	categories = get_text_categories()
	next_text = None
	next_section = None

	# expire old locks before checking for a currently unlocked text
	sefaria.locks.expire_locks()

	pRef = parse_ref(ref, pad=False)
	if "error" not in pRef and len(pRef["sections"]) == 0:
		# ref is an exact text Title
		text = norm_ref(ref)

		# normalize URL
		if request.path != "/translate/%s" % url_ref(text):
			return redirect("/translate/%s" % url_ref(text), permanent=True)

		# Check for completion
		if get_percent_available(text) == 100:
			generic_response["content"] = "<h3>Sefaria now has a complete translation of %s</h3>But you can still contribute in other ways.</h3> <a href='/contribute'>Learn More.</a>" % ref
			return render_to_response('static/generic.html', generic_response, RequestContext(request))

		if "random" in request.GET:
			# choose a ref from a random section within this text
			skip = int(request.GET.get("skip")) if "skip" in request.GET else None
			assigned_ref = random_untranslated_ref_in_text(text, skip=skip)
			
			if assigned_ref:
				next_section = parse_ref(assigned_ref)["sections"][0]
		
		elif "section" in request.GET:
			# choose the next ref within the specified section
			next_section = int(request.GET["section"])
			assigned_ref = next_untranslated_ref_in_text(text, section=next_section)
		
		else:
			# choose the next ref in this text in order
			assigned_ref = next_untranslated_ref_in_text(text)
	
		if not assigned_ref:
			generic_response["content"] = "All remaining sections in %s are being worked on by other contributors. Work on <a href='/translate/%s'>another text</a> for now." % (text, ref)
			return render_to_response('static/generic.html', generic_response, RequestContext(request))
		
	elif "error" not in pRef and len(pRef["sections"]) > 0:
		# ref is a citation to a particular location in a text
		# for now, send this to the edit_text view
		return edit_text(request, ref)
		
	elif "error" in pRef and ref in categories:
		# ref is a text Category
		cat = ref

		# Check for completion
		if get_percent_available(cat) == 100:
			generic_response["content"] = "<h3>Sefaria now has a complete translation of %s</h3>But you can still contribute in other ways.</h3> <a href='/contribute'>Learn More.</a>" % ref
			return render_to_response('static/generic.html', generic_response, RequestContext(request))

		if "random" in request.GET:
			# choose a random text from this cateogory
			skip = int(request.GET.get("skip")) if "skip" in request.GET else None
			text = random_untranslated_text_in_category(cat, skip=skip)
			assigned_ref = next_untranslated_ref_in_text(text)
			next_text = text

		elif "text" in request.GET:
			# choose the next text requested in URL
			text = norm_ref(request.GET["text"])
			next_text = text
			if get_percent_available(text) == 100:
				generic_response["content"] = "%s is complete! Work on <a href='/translate/%s'>another text</a>." % (next, ref)
				return render_to_response('static/generic.html', generic_response, RequestContext(request))
			
			assigned_ref = next_untranslated_ref_in_text(text)
			if "error" in assigned_ref:
				generic_response["content"] = "All remaining sections in %s are being worked on by other contributors. Work on <a href='/translate/%s'>another text</a> for now." % (next, ref)
				return render_to_response('static/generic.html', generic_response, RequestContext(request))

		else:
			# choose the next text in order
			skip = 0
			assigned_ref = {"error": "haven't chosen yet"}
			# TODO -- need an escape valve here
			while "error" in assigned_ref:
				text = next_untranslated_text_in_category(cat, skip=skip)
				assigned_ref = next_untranslated_ref_in_text(text)
				skip += 1
	
	else:
		# we don't know what this is
		generic_response["content"] = "<b>%s</b> isn't a known text or category.<br>But you can still contribute in other ways.</h3> <a href='/contribute'>Learn More.</a>" % (ref)
		return render_to_response('static/generic.html', generic_response, RequestContext(request))


	# get the assigned text
	assigned = get_text(assigned_ref, context=0, commentary=False)

	# Put a lock on this assignment
	user = request.user.id if request.user.is_authenticated() else 0
	sefaria.locks.set_lock(assigned_ref, "en", "Sefaria Community Translation", user)
	
	# if the assigned text is actually empty, run this request again
	# but leave the new lock in place to skip over it
	if "he" not in assigned or not len(assigned["he"]):
		return translation_flow(request, ref)

	# get percentage and remaining counts
	# percent   = get_percent_available(assigned["book"])
	translated = get_translated_count_by_unit(assigned["book"], unit=assigned["sectionNames"][-1])
	remaining = get_untranslated_count_by_unit(assigned["book"], unit=assigned["sectionNames"][-1])
	percent = 100 * translated / float(translated + remaining)


	return render_to_response('translate_campaign.html', 
									{"title": "Help Translate %s" % ref,
									"base_ref": ref,
									"assigned_ref": assigned_ref,
									"assigned_ref_url": url_ref(assigned_ref),
									"assigned_text": assigned["he"],
									"assigned_segment_name": assigned["sectionNames"][-1],
									"assigned": assigned,
									"translated": translated,
									"remaining": remaining,
									"percent": percent,
									"thanks": "thank" in request.GET,
									"random_param": "&skip=%d" % assigned["sections"][0] if request.GET.get("random") else "",
									"next_text": next_text,
									"next_section": next_section,
									},
									RequestContext(request))
Exemplo n.º 13
0
def reader(request, ref, lang=None, version=None):

	# Redirect to standard URLs
	# Let unknown refs pass through 
	uref = url_ref(ref)
	if uref and ref != uref:
		url = "/" + uref
		if lang and version:
			url += "/%s/%s" % (lang, version)

		response = redirect(url, permanent=True)
		params = request.GET.urlencode()
		response['Location'] += "?%s" % params if params else ""
		return response

	# BANDAID - return the first section only of a spanning ref
	pRef = parse_ref(ref)
	if "error" not in pRef and is_spanning_ref(pRef):
		ref = split_spanning_ref(pRef)[0]
		url = "/" + ref
		if lang and version:
			url += "/%s/%s" % (lang, version)
		response = redirect(url)
		params = request.GET.urlencode()
		response['Location'] += "?%s" % params if params else ""
		return response

	version = version.replace("_", " ") if version else None
	text = get_text(ref, lang=lang, version=version)
	if not "error" in text:
		notes = get_notes(ref, uid=request.user.id, context=1)
		text["commentary"] += notes
	initJSON = json.dumps(text)
	
	lines = True if "error" in text or text["type"] not in ('Tanach', 'Talmud') or text["book"] == "Psalms" else False
	email = request.user.email if request.user.is_authenticated() else ""
	
	zippedText = map(None, text["text"], text["he"]) if not "error" in text else []

	# Pull language setting from cookie or Accept-Lanugage header
	langMode = request.COOKIES.get('langMode') or request.LANGUAGE_CODE or 'en'
	langMode = 'he' if langMode == 'he-il' else langMode
	# URL parameter trumps cookie
	langMode = request.GET.get("lang", langMode)
	langMode = "bi" if langMode in ("he-en", "en-he") else langMode
	# Don't allow languages other than what we currently handle
	langMode = 'en' if langMode not in ('en', 'he', 'bi') else langMode
	# Substitue language mode if text not available in that language
	if not "error" in text:
		if is_text_empty(text["text"]) and not langMode == "he":
			langMode = "he"
		if is_text_empty(text["he"]) and not langMode == "en":
			langMode = "en"
	langClass = {"en": "english", "he": "hebrew", "bi": "bilingual heLeft"}[langMode]

	return render_to_response('reader.html', 
							 {'text': text,
							 'initJSON': initJSON,
							 'zippedText': zippedText,
							 'lines': lines,
							 'langClass': langClass,
							 'page_title': norm_ref(ref) or "Unknown Text",
							 'title_variants': "(%s)" % ", ".join(text.get("titleVariants", []) + [text.get("heTitle", "")]),
							 'email': email}, 
							 RequestContext(request))