def frienduser_(request): if not define.is_vouched_for(request.userid): raise WeasylError("vouchRequired") form = request.web_input(userid="") otherid = define.get_int(form.userid) if request.userid == otherid: raise WeasylError('cannotSelfFriend') if form.action == "sendfriendrequest": if not frienduser.check(request.userid, otherid) and not frienduser.already_pending( request.userid, otherid): frienduser.request(request.userid, otherid) elif form.action == "withdrawfriendrequest": if frienduser.already_pending(request.userid, otherid): frienduser.remove_request(request.userid, otherid) elif form.action == "unfriend": frienduser.remove(request.userid, otherid) if form.feature == "pending": raise HTTPSeeOther(location="/manage/friends?feature=pending") else: # typical value will be user raise HTTPSeeOther( location="/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def select_list(userid, rating, limit, otherid): statement = [ "SELECT jo.journalid, jo.title, jo.unixtime, jo.content FROM journal jo WHERE" ] if userid: # filter own content in SFW mode if d.is_sfw_mode(): statement.append(" (jo.rating <= %i)" % (rating, )) else: statement.append(" (jo.userid = %i OR jo.rating <= %i)" % (userid, rating)) statement.append(m.MACRO_BLOCKTAG_JOURNAL % (userid, userid)) else: statement.append(" jo.rating <= %i" % (rating, )) statement.append( " AND jo.userid = %i AND jo.settings !~ '[%sh]'" % (otherid, "" if frienduser.check(userid, otherid) else "f")) statement.append("ORDER BY jo.journalid DESC LIMIT %i" % limit) return [{ "journalid": i[0], "title": i[1], "created_at": arrow.get(i[2] - UNIXTIME_OFFSET), "content": i[3], } for i in d.execute("".join(statement))]
def frienduser_(request): form = request.web_input(userid="") otherid = define.get_int(form.userid) if request.userid == otherid: return Response( define.errorpage(request.userid, "You cannot friend yourself.")) if form.action == "sendfriendrequest": if not frienduser.check(request.userid, otherid) and not frienduser.already_pending( request.userid, otherid): frienduser.request(request.userid, otherid) elif form.action == "withdrawfriendrequest": if frienduser.already_pending(request.userid, otherid): frienduser.remove_request(request.userid, otherid) elif form.action == "unfriend": frienduser.remove(request.userid, otherid) if form.feature == "pending": raise HTTPSeeOther(location="/manage/friends?feature=pending") else: # typical value will be user raise HTTPSeeOther( location="/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def select_list(userid, rating, limit, otherid=None, backid=None, nextid=None, config=None): if config is None: config = d.get_config(userid) statement = ["SELECT jo.journalid, jo.title, jo.unixtime FROM journal jo WHERE"] if userid: # filter own content in SFW mode if d.is_sfw_mode(): statement.append(" (jo.rating <= %i)" % (rating,)) else: statement.append(" (jo.userid = %i OR jo.rating <= %i)" % (userid, rating)) if not otherid: statement.append(m.MACRO_IGNOREUSER % (userid, "jo")) statement.append(m.MACRO_BLOCKTAG_JOURNAL % (userid, userid)) else: statement.append(" jo.rating <= %i" % (rating,)) if otherid: statement.append( " AND jo.userid = %i AND jo.settings !~ '[%sh]'" % (otherid, "" if frienduser.check(userid, otherid) else "f")) else: statement.append(" AND jo.settings !~ 'h'") statement.append("ORDER BY jo.journalid DESC LIMIT %i" % limit) query = [{ "journalid": i[0], "title": i[1], "unixtime": i[2], } for i in d.execute("".join(statement))] return query[::-1] if backid else query
def select_latest(userid, rating, otherid=None, config=None): if config is None: config = d.get_config(userid) statement = ["SELECT jo.journalid, jo.title, jo.content, jo.unixtime FROM journal jo WHERE"] if userid: if d.is_sfw_mode(): statement.append(" (jo.rating <= %i)" % (rating,)) else: statement.append(" (jo.userid = %i OR jo.rating <= %i)" % (userid, rating)) if not otherid: statement.append(m.MACRO_IGNOREUSER % (userid, "jo")) statement.append(m.MACRO_BLOCKTAG_JOURNAL % (userid, userid)) else: statement.append(" jo.rating <= %i" % (rating,)) if otherid: statement.append( " AND jo.userid = %i AND jo.settings !~ '[%sh]'" % (otherid, "" if frienduser.check(userid, otherid) else "f")) statement.append("ORDER BY jo.journalid DESC LIMIT 1") query = d.execute("".join(statement), options="single") if query: return { "journalid": query[0], "title": query[1], "content": query[2], "unixtime": query[3], "comments": d.execute("SELECT COUNT(*) FROM journalcomment WHERE targetid = %i AND settings !~ 'h'", [query[0]], ["element"]), }
def select_latest(userid, rating, otherid): statement = ["SELECT jo.journalid, jo.title, jo.content, jo.unixtime FROM journal jo WHERE"] if userid: if d.is_sfw_mode(): statement.append(" (jo.rating <= %i)" % (rating,)) else: statement.append(" (jo.userid = %i OR jo.rating <= %i)" % (userid, rating)) statement.append(m.MACRO_BLOCKTAG_JOURNAL % (userid, userid)) else: statement.append(" jo.rating <= %i" % (rating,)) statement.append( " AND jo.userid = %i AND jo.settings !~ '[%sh]'" % (otherid, "" if frienduser.check(userid, otherid) else "f")) statement.append("ORDER BY jo.journalid DESC LIMIT 1") query = d.engine.execute("".join(statement)).first() if query: return { "journalid": query[0], "title": query[1], "content": query[2], "unixtime": query[3], "comments": d.engine.scalar( "SELECT count(*) FROM journalcomment WHERE targetid = %(journal)s AND settings !~ 'h'", journal=query[0], ), }
def insert(userid, target_user, parentid, content, staffnotes): # Check invalid content if not content: raise WeasylError("commentInvalid") elif not target_user or not d.is_vouched_for(target_user): raise WeasylError("Unexpected") # Determine parent userid if parentid: parentuserid = d.engine.scalar( "SELECT userid FROM comments WHERE commentid = %(parent)s", parent=parentid, ) if parentuserid is None: raise WeasylError("shoutRecordMissing") else: parentuserid = None # Check permissions if userid not in staff.MODS: if ignoreuser.check(target_user, userid): raise WeasylError("pageOwnerIgnoredYou") elif ignoreuser.check(userid, target_user): raise WeasylError("youIgnoredPageOwner") elif ignoreuser.check(parentuserid, userid): raise WeasylError("replyRecipientIgnoredYou") elif ignoreuser.check(userid, parentuserid): raise WeasylError("youIgnoredReplyRecipient") _, is_banned, _ = d.get_login_settings(target_user) profile_config = d.get_config(target_user) if is_banned or "w" in profile_config or "x" in profile_config and not frienduser.check( userid, target_user): raise WeasylError("insufficientActionPermissions") # Create comment settings = 's' if staffnotes else '' co = d.meta.tables['comments'] db = d.connect() commentid = db.scalar(co.insert().values(userid=userid, target_user=target_user, parentid=parentid or None, content=content, unixtime=arrow.utcnow(), settings=settings).returning( co.c.commentid)) # Create notification if parentid and userid != parentuserid: if not staffnotes or parentuserid in staff.MODS: welcome.shoutreply_insert(userid, commentid, parentuserid, parentid, staffnotes) elif not staffnotes and target_user and userid != target_user: welcome.shout_insert(userid, commentid, otherid=target_user) d.metric('increment', 'shouts') return commentid
def select_list(userid, rating, limit, otherid=None, backid=None, nextid=None): statement = ["SELECT jo.journalid, jo.title, jo.unixtime FROM journal jo WHERE"] if userid: # filter own content in SFW mode if d.is_sfw_mode(): statement.append(" (jo.rating <= %i)" % (rating,)) else: statement.append(" (jo.userid = %i OR jo.rating <= %i)" % (userid, rating)) if not otherid: statement.append(m.MACRO_IGNOREUSER % (userid, "jo")) statement.append(m.MACRO_BLOCKTAG_JOURNAL % (userid, userid)) else: statement.append(" jo.rating <= %i" % (rating,)) if otherid: statement.append( " AND jo.userid = %i AND jo.settings !~ '[%sh]'" % (otherid, "" if frienduser.check(userid, otherid) else "f")) else: statement.append(" AND jo.settings !~ 'h'") statement.append("ORDER BY jo.journalid DESC LIMIT %i" % limit) query = [{ "journalid": i[0], "title": i[1], "unixtime": i[2], } for i in d.execute("".join(statement))] return query[::-1] if backid else query
def insert(userid, shout, staffnotes=False): # Check invalid content if not shout.content: raise WeasylError("commentInvalid") elif not shout.userid: raise WeasylError("Unexpected") # Determine indent and parentuserid if shout.parentid: query = d.execute("SELECT userid, indent FROM comments WHERE commentid = %i", [shout.parentid], options="single") if not query: raise WeasylError("shoutRecordMissing") indent, parentuserid = query[1] + 1, query[0] else: indent, parentuserid = 0, None # Check permissions if userid not in staff.MODS: if ignoreuser.check(shout.userid, userid): raise WeasylError("pageOwnerIgnoredYou") elif ignoreuser.check(userid, shout.userid): raise WeasylError("youIgnoredPageOwner") elif ignoreuser.check(parentuserid, userid): raise WeasylError("replyRecipientIgnoredYou") elif ignoreuser.check(userid, parentuserid): raise WeasylError("youIgnoredReplyRecipient") settings = d.execute("SELECT lo.settings, pr.config FROM login lo" " INNER JOIN profile pr ON lo.userid = pr.userid" " WHERE lo.userid = %i", [shout.userid], options="single") if "b" in settings[0] or "w" in settings[1] or "x" in settings[1] and not frienduser.check(userid, shout.userid): raise WeasylError("insufficientActionPermissions") # Create comment settings = 's' if staffnotes else '' co = d.meta.tables['comments'] db = d.connect() commentid = db.scalar( co.insert() .values(userid=userid, target_user=shout.userid, parentid=shout.parentid or None, content=shout.content, unixtime=arrow.utcnow(), indent=indent, settings=settings) .returning(co.c.commentid)) # Create notification if shout.parentid and userid != parentuserid: if not staffnotes or parentuserid in staff.MODS: welcome.shoutreply_insert(userid, commentid, parentuserid, shout.parentid, staffnotes) elif not staffnotes and shout.userid and userid != shout.userid: welcome.shout_insert(userid, commentid, otherid=shout.userid) d.metric('increment', 'shouts') return commentid
def insert(userid, submitid=None, charid=None, journalid=None): if submitid: content_table, id_field, target = "submission", "submitid", submitid elif charid: content_table, id_field, target = "character", "charid", charid else: content_table, id_field, target = "journal", "journalid", journalid query = d.execute("SELECT userid, settings FROM %s WHERE %s = %i", [content_table, id_field, target], options="single") if not query: raise WeasylError("TargetRecordMissing") elif userid == query[0]: raise WeasylError("CannotSelfFavorite") elif "f" in query[1] and not frienduser.check(userid, query[0]): raise WeasylError("FriendsOnly") elif ignoreuser.check(userid, query[0]): raise WeasylError("YouIgnored") elif ignoreuser.check(query[0], userid): raise WeasylError("contentOwnerIgnoredYou") insert_result = d.engine.execute( 'INSERT INTO favorite (userid, targetid, type, unixtime) ' 'VALUES (%(user)s, %(target)s, %(type)s, %(now)s) ' 'ON CONFLICT DO NOTHING', user=userid, target=d.get_targetid(submitid, charid, journalid), type='s' if submitid else 'f' if charid else 'j', now=d.get_time()) if insert_result.rowcount == 0: return # create a list of users to notify notified = set(collection.find_owners(submitid)) # conditions under which "other" should be notified def can_notify(other): other_jsonb = d.get_profile_settings(other) allow_notify = other_jsonb.allow_collection_notifs not_ignored = not ignoreuser.check(other, userid) return allow_notify and not_ignored notified = set(filter(can_notify, notified)) # always notify for own content notified.add(query[0]) for other in notified: welcome.favorite_insert(userid, submitid=submitid, charid=charid, journalid=journalid, otherid=other)
def select_view_api(userid, submitid, anyway=False, increment_views=False): rating = d.get_rating(userid) db = d.connect() sub = db.query(orm.Submission).get(submitid) if sub is None or 'hidden' in sub.settings: raise WeasylError("submissionRecordMissing") sub_rating = sub.rating.code if 'friends-only' in sub.settings and not frienduser.check(userid, sub.userid): raise WeasylError("submissionRecordMissing") elif sub_rating > rating and userid != sub.userid: raise WeasylError("RatingExceeded") elif not anyway and ignoreuser.check(userid, sub.userid): raise WeasylError("UserIgnored") elif not anyway and blocktag.check(userid, submitid=submitid): raise WeasylError("TagBlocked") description = sub.content embedlink = None if 'embedded-content' in sub.settings: embedlink, _, description = description.partition('\n') elif 'gdocs-embed' in sub.settings: embedlink = sub.google_doc_embed.embed_url views = sub.page_views if increment_views and d.common_view_content(userid, submitid, 'submit'): views += 1 return { 'submitid': submitid, 'title': sub.title, 'owner': sub.owner.profile.username, 'owner_login': sub.owner.login_name, 'owner_media': api.tidy_all_media(media.get_user_media(sub.userid)), 'media': api.tidy_all_media(media.get_submission_media(submitid)), 'description': text.markdown(description), 'embedlink': embedlink, 'folderid': sub.folderid, 'folder_name': sub.folder.title if sub.folderid else None, 'posted_at': d.iso8601(sub.unixtime), 'tags': searchtag.select(submitid=submitid), 'link': d.absolutify_url("/submission/%d/%s" % (submitid, text.slug_for(sub.title))), 'type': 'submission', 'subtype': m.CATEGORY_PARSABLE_MAP[sub.subtype // 1000 * 1000], 'rating': sub.rating.name, 'views': views, 'favorites': favorite.count(submitid), 'comments': comment.count(submitid), 'favorited': favorite.check(userid, submitid=submitid), 'friends_only': 'friends-only' in sub.settings, }
def _select_journal_and_check(userid, journalid, rating=None, ignore=True, anyway=False, increment_views=True): """Selects a journal, after checking if the user is authorized, etc. Args: userid (int): Currently authenticating user ID. journalid (int): Character ID to fetch. rating (int): Maximum rating to display. Defaults to None. ignore (bool): Whether to respect ignored or blocked tags. Defaults to True. anyway (bool): Whether ignore checks and display anyway. Defaults to False. increment_views (bool): Whether to increment the number of views on the submission. Defaults to True. Returns: A journal and all needed data as a dict. """ query = d.engine.execute(""" SELECT jo.userid, pr.username, jo.unixtime, jo.title, jo.content, jo.rating, jo.settings, jo.page_views, pr.config FROM journal jo JOIN profile pr ON jo.userid = pr.userid WHERE jo.journalid = %(id)s """, id=journalid).first() if not query: # If there's no query result, there's no record, so fast-fail. raise WeasylError('journalRecordMissing') elif journalid and userid in staff.MODS and anyway: pass elif not query or 'h' in query.settings: raise WeasylError('journalRecordMissing') elif query.rating > rating and ( (userid != query.userid and userid not in staff.MODS) or d.is_sfw_mode()): raise WeasylError('RatingExceeded') elif 'f' in query.settings and not frienduser.check(userid, query.userid): raise WeasylError('FriendsOnly') elif ignore and ignoreuser.check(userid, query.userid): raise WeasylError('UserIgnored') elif ignore and blocktag.check(userid, journalid=journalid): raise WeasylError('TagBlocked') query = dict(query) if increment_views and d.common_view_content(userid, journalid, 'journal'): query['page_views'] += 1 return query
def _select_character_and_check(userid, charid, rating=None, ignore=True, anyway=False, increment_views=True): """Selects a character, after checking if the user is authorized, etc. Args: userid (int): Currently authenticating user ID. charid (int): Character ID to fetch. rating (int): Maximum rating to display. Defaults to None. ignore (bool): Whether to respect ignored or blocked tags. Defaults to True. anyway (bool): Whether to ignore checks and display anyway. Defaults to False. increment_views (bool): Whether to increment the number of views on the submission. Defaults to True. Returns: A character and all needed data as a dict. """ query = define.engine.execute(""" SELECT ch.userid, pr.username, ch.unixtime, ch.char_name, ch.age, ch.gender, ch.height, ch.weight, ch.species, ch.content, ch.rating, ch.settings, ch.page_views, pr.config FROM character ch INNER JOIN profile pr USING (userid) WHERE ch.charid = %(charid)s """, charid=charid).first() if query and userid in staff.MODS and anyway: pass elif not query or 'h' in query.settings: raise WeasylError('characterRecordMissing') elif query.rating > rating and ( (userid != query.userid and userid not in staff.MODS) or define.is_sfw_mode()): raise WeasylError('RatingExceeded') elif 'f' in query.settings and not frienduser.check(userid, query.userid): raise WeasylError('FriendsOnly') elif ignore and ignoreuser.check(userid, query.userid): raise WeasylError('UserIgnored') elif ignore and blocktag.check(userid, charid=charid): raise WeasylError('TagBlocked') query = dict(query) if increment_views and define.common_view_content(userid, charid, 'char'): query['page_views'] += 1 return query
def select_latest(userid, rating, otherid=None, config=None): if config is None: config = d.get_config(userid) statement = [ "SELECT jo.journalid, jo.title, jo.unixtime FROM journal jo WHERE" ] if userid: if d.is_sfw_mode(): statement.append(" (jo.rating <= %i)" % (rating, )) else: statement.append(" (jo.userid = %i OR jo.rating <= %i)" % (userid, rating)) if not otherid: statement.append(m.MACRO_IGNOREUSER % (userid, "jo")) statement.append(m.MACRO_BLOCKTAG_JOURNAL % (userid, userid)) else: statement.append(" jo.rating <= %i" % (rating, )) if otherid: statement.append( " AND jo.userid = %i AND jo.settings !~ '[%sh]'" % (otherid, "" if frienduser.check(userid, otherid) else "f")) statement.append("ORDER BY jo.journalid DESC LIMIT 1") query = d.execute("".join(statement), options="single") if query: return { "journalid": query[0], "title": query[1], "unixtime": query[2], "content": files.read("%s%s%i.txt" % (m.MACRO_SYS_JOURNAL_PATH, d.get_hash_path(query[0]), query[0])), "comments": d.execute( "SELECT COUNT(*) FROM journalcomment WHERE targetid = %i AND settings !~ 'h'", [query[0]], ["element"]), }
def _select_character_and_check(userid, charid, rating=None, ignore=True, anyway=False, increment_views=True): """Selects a character, after checking if the user is authorized, etc. Args: userid (int): Currently authenticating user ID. charid (int): Character ID to fetch. rating (int): Maximum rating to display. Defaults to None. ignore (bool): Whether to respect ignored or blocked tags. Defaults to True. anyway (bool): Whether to ignore checks and display anyway. Defaults to False. increment_views (bool): Whether to increment the number of views on the submission. Defaults to True. Returns: A character and all needed data as a dict. """ query = define.engine.execute(""" SELECT ch.userid, pr.username, ch.unixtime, ch.char_name, ch.age, ch.gender, ch.height, ch.weight, ch.species, ch.content, ch.rating, ch.settings, ch.page_views, pr.config FROM character ch INNER JOIN profile pr USING (userid) WHERE ch.charid = %(charid)s """, charid=charid).first() if query and userid in staff.MODS and anyway: pass elif not query or 'h' in query.settings: raise WeasylError('characterRecordMissing') elif query.rating > rating and ((userid != query.userid and userid not in staff.MODS) or define.is_sfw_mode()): raise WeasylError('RatingExceeded') elif 'f' in query.settings and not frienduser.check(userid, query.userid): raise WeasylError('FriendsOnly') elif ignore and ignoreuser.check(userid, query.userid): raise WeasylError('UserIgnored') elif ignore and blocktag.check(userid, charid=charid): raise WeasylError('TagBlocked') query = dict(query) if increment_views and define.common_view_content(userid, charid, 'char'): query['page_views'] += 1 return query
def frienduser_(request): form = request.web_input(userid="") otherid = define.get_int(form.userid) if request.userid == otherid: return Response(define.errorpage(request.userid, "You cannot friend yourself.")) if form.action == "sendfriendrequest": if not frienduser.check(request.userid, otherid) and not frienduser.already_pending(request.userid, otherid): frienduser.request(request.userid, otherid) elif form.action == "withdrawfriendrequest": if frienduser.already_pending(request.userid, otherid): frienduser.remove_request(request.userid, otherid) elif form.action == "unfriend": frienduser.remove(request.userid, otherid) if form.feature == "pending": raise HTTPSeeOther(location="/manage/friends?feature=pending") else: # typical value will be user raise HTTPSeeOther(location="/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def POST(self): form = web.input(userid="") otherid = define.get_int(form.userid) if self.user_id == otherid: return define.errorpage(self.user_id, "You cannot friend yourself.") if form.action == "sendfriendrequest": if not frienduser.check(self.user_id, otherid) and not frienduser.already_pending(self.user_id, otherid): frienduser.request(self.user_id, otherid) elif form.action == "withdrawfriendrequest": if frienduser.already_pending(self.user_id, otherid): frienduser.remove_request(self.user_id, otherid) elif form.action == "unfriend": frienduser.remove(self.user_id, otherid) if form.feature == "pending": raise web.seeother("/manage/friends?feature=pending") else: # typical value will be user raise web.seeother("/~%s" % (define.get_sysname(define.get_display_name(otherid))))
def _select_journal_and_check(userid, journalid, rating=None, ignore=True, anyway=False, increment_views=True): """Selects a journal, after checking if the user is authorized, etc. Args: userid (int): Currently authenticating user ID. journalid (int): Character ID to fetch. rating (int): Maximum rating to display. Defaults to None. ignore (bool): Whether to respect ignored or blocked tags. Defaults to True. anyway (bool): Whether ignore checks and display anyway. Defaults to False. increment_views (bool): Whether to increment the number of views on the submission. Defaults to True. Returns: A journal and all needed data as a dict. """ query = d.engine.execute(""" SELECT jo.userid, pr.username, jo.unixtime, jo.title, jo.content, jo.rating, jo.settings, jo.page_views, pr.config FROM journal jo JOIN profile pr ON jo.userid = pr.userid WHERE jo.journalid = %(id)s """, id=journalid).first() if journalid and userid in staff.MODS and anyway: pass elif not query or 'h' in query.settings: raise WeasylError('journalRecordMissing') elif query.rating > rating and ((userid != query.userid and userid not in staff.MODS) or d.is_sfw_mode()): raise WeasylError('RatingExceeded') elif 'f' in query.settings and not frienduser.check(userid, query.userid): raise WeasylError('FriendsOnly') elif ignore and ignoreuser.check(userid, query.userid): raise WeasylError('UserIgnored') elif ignore and blocktag.check(userid, journalid=journalid): raise WeasylError('TagBlocked') query = dict(query) if increment_views and d.common_view_content(userid, journalid, 'journal'): query['page_views'] += 1 return query
def select_view(userid, submitid, rating, ignore=True, anyway=None): query = d.execute(""" SELECT su.userid, pr.username, su.folderid, su.unixtime, su.title, su.content, su.subtype, su.rating, su.settings, su.page_views, su.sorttime, pr.config, fd.title FROM submission su INNER JOIN profile pr USING (userid) LEFT JOIN folder fd USING (folderid) WHERE su.submitid = %i """, [submitid], options=["single", "list"]) # Sanity check if query and userid in staff.MODS and anyway == "true": pass elif not query or "h" in query[8]: raise WeasylError("submissionRecordMissing") elif query[7] > rating and ((userid != query[0] and userid not in staff.MODS) or d.is_sfw_mode()): raise WeasylError("RatingExceeded") elif "f" in query[8] and not frienduser.check(userid, query[0]): raise WeasylError("FriendsOnly") elif ignore and ignoreuser.check(userid, query[0]): raise WeasylError("UserIgnored") elif ignore and blocktag.check(userid, submitid=submitid): raise WeasylError("TagBlocked") # Get submission filename submitfile = media.get_submission_media(submitid).get('submission', [None])[0] # Get submission text if submitfile and submitfile['file_type'] in ['txt', 'htm']: submittext = files.read(submitfile['full_file_path']) else: submittext = None embedlink = d.text_first_line(query[5]) if "v" in query[8] else None google_doc_embed = None if 'D' in query[8]: db = d.connect() gde = d.meta.tables['google_doc_embeds'] q = (sa.select([gde.c.embed_url]) .where(gde.c.submitid == submitid)) results = db.execute(q).fetchall() if not results: raise WeasylError("can't find embed information") google_doc_embed = results[0] tags, artist_tags = searchtag.select_with_artist_tags(submitid) settings = d.get_profile_settings(query[0]) return { "submitid": submitid, "userid": query[0], "username": query[1], "folderid": query[2], "unixtime": query[3], "title": query[4], "content": (d.text_first_line(query[5], strip=True) if "v" in query[8] else query[5]), "subtype": query[6], "rating": query[7], "settings": query[8], "page_views": ( query[9] + 1 if d.common_view_content(userid, 0 if anyway == "true" else submitid, "submit") else query[9]), "fave_count": d.execute( "SELECT COUNT(*) FROM favorite WHERE (targetid, type) = (%i, 's')", [submitid], ["element"]), "mine": userid == query[0], "reported": report.check(submitid=submitid), "favorited": favorite.check(userid, submitid=submitid), "friends_only": "f" in query[8], "hidden_submission": "h" in query[8], "collectors": collection.find_owners(submitid), "no_request": not settings.allow_collection_requests, "text": submittext, "sub_media": media.get_submission_media(submitid), "user_media": media.get_user_media(query[0]), "submit": submitfile, "embedlink": embedlink, "embed": embed.html(embedlink) if embedlink is not None else None, "google_doc_embed": google_doc_embed, "tags": tags, "artist_tags": artist_tags, "removable_tags": searchtag.removable_tags(userid, query[0], tags, artist_tags), "can_remove_tags": searchtag.can_remove_tags(userid, query[0]), "folder_more": select_near(userid, rating, 1, query[0], query[2], submitid), "folder_title": query[12] if query[12] else "Root", "comments": comment.select(userid, submitid=submitid), }
def select_view(userid, submitid, rating, ignore=True, anyway=None): query = d.engine.execute(""" SELECT su.userid, pr.username, su.folderid, su.unixtime, su.title, su.content, su.subtype, su.rating, su.settings, su.page_views, fd.title, su.favorites, su.image_representations FROM submission su INNER JOIN profile pr USING (userid) LEFT JOIN folder fd USING (folderid) WHERE su.submitid = %(id)s """, id=submitid).first() # Sanity check if query and userid in staff.MODS and anyway == "true": pass elif not query or "h" in query[8]: raise WeasylError("submissionRecordMissing") elif query[7] > rating and ( (userid != query[0] and userid not in staff.MODS) or d.is_sfw_mode()): raise WeasylError("RatingExceeded") elif "f" in query[8] and not frienduser.check(userid, query[0]): raise WeasylError("FriendsOnly") elif ignore and ignoreuser.check(userid, query[0]): raise WeasylError("UserIgnored") elif ignore and blocktag.check(userid, submitid=submitid): raise WeasylError("TagBlocked") # Get submission filename submitfile = media.get_submission_media(submitid).get( 'submission', [None])[0] # Get submission text if submitfile and submitfile['file_type'] in ['txt', 'htm']: submittext = files.read(submitfile['full_file_path']) else: submittext = None embedlink = d.text_first_line(query[5]) if "v" in query[8] else None google_doc_embed = None if 'D' in query[8]: db = d.connect() gde = d.meta.tables['google_doc_embeds'] q = (sa.select([gde.c.embed_url]).where(gde.c.submitid == submitid)) results = db.execute(q).fetchall() if not results: raise WeasylError("can't find embed information") google_doc_embed = results[0] tags, artist_tags = searchtag.select_with_artist_tags(submitid) settings = d.get_profile_settings(query[0]) if query[12] is None: sub_media = media.get_submission_media(submitid) else: sub_media = media.deserialize_image_representations(query[12]) return { "submitid": submitid, "userid": query[0], "username": query[1], "folderid": query[2], "unixtime": query[3], "title": query[4], "content": (d.text_first_line(query[5], strip=True) if "v" in query[8] else query[5]), "subtype": query[6], "rating": query[7], "settings": query[8], "page_views": (query[9] + 1 if d.common_view_content( userid, 0 if anyway == "true" else submitid, "submit") else query[9]), "fave_count": query[11], "mine": userid == query[0], "reported": report.check(submitid=submitid), "favorited": favorite.check(userid, submitid=submitid), "friends_only": "f" in query[8], "hidden_submission": "h" in query[8], "collected": collection.owns(userid, submitid), "no_request": not settings.allow_collection_requests, "text": submittext, "sub_media": sub_media, "user_media": media.get_user_media(query[0]), "submit": submitfile, "embedlink": embedlink, "embed": embed.html(embedlink) if embedlink is not None else None, "google_doc_embed": google_doc_embed, "tags": tags, "artist_tags": artist_tags, "removable_tags": searchtag.removable_tags(userid, query[0], tags, artist_tags), "can_remove_tags": searchtag.can_remove_tags(userid, query[0]), "folder_more": select_near(userid, rating, 1, query[0], query[2], submitid), "folder_title": query[10] if query[10] else "Root", "comments": comment.select(userid, submitid=submitid), }
def send(userid, form): form.title = form.title.strip() form.content = form.content.strip() if not form.content: raise WeasylError("contentInvalid") elif not form.title: raise WeasylError("titleInvalid") elif len(form.title) > 100: raise WeasylError("titleTooLong") users = set(d.get_userid_list(form.recipient)) # can't send a note to yourself users.discard(userid) # can't send a note to a user who ignores you users.difference_update( d.column( d.engine.execute( "SELECT userid FROM ignoreuser WHERE otherid = %(user)s", user=userid))) # can't send a note to an unverified user users.difference_update( d.column( d.engine.execute( "SELECT userid FROM login WHERE userid = ANY (%(users)s) AND voucher IS NULL", users=list(users)))) # can't send a note to a user you're ignoring users.difference_update(ignoreuser.cached_list_ignoring(userid)) if not users: raise WeasylError("recipientInvalid") configs = d.engine.execute( "SELECT userid, config FROM profile WHERE userid = ANY (%(recipients)s)", recipients=list(users)).fetchall() if userid not in staff.MODS: ignore_global_restrictions = { i for (i, ) in d.engine.execute( "SELECT userid FROM permitted_senders WHERE sender = %(user)s", user=userid) } remove = ( # Staff notes only {j[0] for j in configs if "y" in j[1]} | # Friend notes only { j[0] for j in configs if "z" in j[1] and not frienduser.check(userid, j[0]) }) users.difference_update(remove - ignore_global_restrictions) if not users: raise WeasylError("recipientInvalid") elif len(users) > 10: raise WeasylError("recipientExcessive") d.engine.execute( "INSERT INTO message (userid, otherid, title, content, unixtime)" " SELECT %(sender)s, recipient, %(title)s, %(content)s, %(now)s" " FROM UNNEST (%(recipients)s) AS recipient", sender=userid, title=form.title, content=form.content, now=d.get_time(), recipients=list(users), ) for u in users: d._page_header_info.invalidate(u) d.engine.execute( """ INSERT INTO permitted_senders (userid, sender) SELECT %(user)s, sender FROM UNNEST (%(recipients)s) AS sender ON CONFLICT (userid, sender) DO NOTHING """, user=userid, recipients=list(users), ) if form.mod_copy and userid in staff.MODS: mod_content = ( '## The following message was sent as a note to the user.\n\n### %s\n\n%s' % (form.title, form.content)) if form.staff_note: mod_content = '%s\n\n%s' % (form.staff_note, mod_content) now = arrow.utcnow() mod_copies = [] for target in users: mod_copies.append({ 'userid': userid, 'target_user': target, 'unixtime': now, 'settings': 's', 'content': mod_content, }) d.engine.execute(d.meta.tables['comments'].insert().values(mod_copies))
def insert(userid, submitid=None, charid=None, journalid=None): if submitid: content_table, id_field, target = "submission", "submitid", submitid elif charid: content_table, id_field, target = "character", "charid", charid else: content_table, id_field, target = "journal", "journalid", journalid query = d.engine.execute( "SELECT userid, settings FROM %s WHERE %s = %i" % (content_table, id_field, target), ).first() if not query: raise WeasylError("TargetRecordMissing") elif userid == query[0]: raise WeasylError("CannotSelfFavorite") elif "f" in query[1] and not frienduser.check(userid, query[0]): raise WeasylError("FriendsOnly") elif ignoreuser.check(userid, query[0]): raise WeasylError("YouIgnored") elif ignoreuser.check(query[0], userid): raise WeasylError("contentOwnerIgnoredYou") notified = [] def insert_transaction(db): insert_result = db.execute( 'INSERT INTO favorite (userid, targetid, type, unixtime) ' 'VALUES (%(user)s, %(target)s, %(type)s, %(now)s) ' 'ON CONFLICT DO NOTHING', user=userid, target=d.get_targetid(submitid, charid, journalid), type='s' if submitid else 'f' if charid else 'j', now=d.get_time()) if insert_result.rowcount == 0: return if submitid: db.execute( "UPDATE submission SET favorites = favorites + 1" " WHERE submitid = %(target)s", target=submitid, ) if not notified: # create a list of users to notify notified_ = collection.find_owners(submitid) # conditions under which "other" should be notified def can_notify(other): other_jsonb = d.get_profile_settings(other) allow_notify = other_jsonb.allow_collection_notifs return allow_notify and not ignoreuser.check(other, userid) notified.extend(u for u in notified_ if can_notify(u)) # always notify for own content notified.append(query[0]) for other in notified: welcome.favorite_insert(db, userid, submitid=submitid, charid=charid, journalid=journalid, otherid=other) d.serializable_retry(insert_transaction)
def send(userid, form): form.title = form.title.strip() form.content = form.content.strip() if not form.content: raise WeasylError("contentInvalid") elif not form.title: raise WeasylError("titleInvalid") elif len(form.title) > 100: raise WeasylError("titleTooLong") users = set(i for i in d.get_userid_list(form.recipient) if i != userid) users.difference_update( d.execute("SELECT userid FROM ignoreuser WHERE otherid = %i", [userid], options="within")) users.difference_update( d.execute("SELECT otherid FROM ignoreuser WHERE userid = %i", [userid], options="within")) if not users: raise WeasylError("recipientInvalid") configs = d.execute( "SELECT userid, config FROM profile WHERE userid IN %s", [d.sql_number_list(list(users))]) if userid not in staff.MODS: ignore_global_restrictions = { i for (i, ) in d.engine.execute( "SELECT userid FROM permitted_senders WHERE sender = %(user)s", user=userid) } remove = ( # Staff notes only {j[0] for j in configs if "y" in j[1]} | # Friend notes only { j[0] for j in configs if "z" in j[1] and not frienduser.check(userid, j[0]) }) users.difference_update(remove - ignore_global_restrictions) if not users: raise WeasylError("recipientInvalid") elif len(users) > 10: raise WeasylError("recipientExcessive") argv = [] unixtime = d.get_time() statement = [ "INSERT INTO message (userid, otherid, title, content, unixtime) VALUES" ] for i in users: argv.extend([form.title if form.title else "None", form.content]) statement.append(" (%i, %i, '%%s', '%%s', %i)," % (userid, i, unixtime)) d._page_header_info.invalidate(i) statement[-1] = statement[-1][:-1] d.execute("".join(statement), argv) d.engine.execute( """ INSERT INTO permitted_senders (userid, sender) SELECT %(user)s, sender FROM UNNEST (%(recipients)s) AS sender ON CONFLICT (userid, sender) DO NOTHING """, user=userid, recipients=list(users), ) if form.mod_copy and userid in staff.MODS: mod_content = ( '## The following message was sent as a note to the user.\n\n### %s\n\n%s' % (form.title, form.content)) if form.staff_note: mod_content = '%s\n\n%s' % (form.staff_note, mod_content) now = arrow.utcnow() mod_copies = [] for target in users: mod_copies.append({ 'userid': userid, 'target_user': target, 'unixtime': now, 'settings': 's', 'content': mod_content, }) d.engine.execute(d.meta.tables['comments'].insert().values(mod_copies))
def send(userid, form): form.title = form.title.strip() form.content = form.content.strip() if not form.content: raise WeasylError("contentInvalid") elif not form.title: raise WeasylError("titleInvalid") elif len(form.title) > 100: raise WeasylError("titleTooLong") users = set(i for i in d.get_userid_list(form.recipient) if i != userid) users.difference_update( d.execute("SELECT userid FROM ignoreuser WHERE otherid = %i", [userid], options="within")) users.difference_update( d.execute("SELECT otherid FROM ignoreuser WHERE userid = %i", [userid], options="within")) if not users: raise WeasylError("recipientInvalid") configs = d.execute( "SELECT userid, config FROM profile WHERE userid IN %s", [d.sql_number_list(list(users))]) if userid not in staff.MODS: # Staff notes only users.difference_update(j[0] for j in configs if "y" in j[1]) # Friend notes only users.difference_update(j[0] for j in configs if "z" in j[1] and not frienduser.check(userid, j[0])) if not users: raise WeasylError("recipientInvalid") elif len(users) > 10: raise WeasylError("recipientExcessive") argv = [] unixtime = d.get_time() statement = ["INSERT INTO message (userid, otherid, title, content, unixtime) VALUES"] for i in users: argv.extend([form.title if form.title else "None", form.content]) statement.append(" (%i, %i, '%%s', '%%s', %i)," % (userid, i, unixtime)) d._page_header_info.invalidate(i) statement[-1] = statement[-1][:-1] d.execute("".join(statement), argv) if form.mod_copy and userid in staff.MODS: mod_content = ( '## The following message was sent as a note to the user.\n\n### %s\n\n%s' % ( form.title, form.content)) if form.staff_note: mod_content = '%s\n\n%s' % (form.staff_note, mod_content) now = arrow.utcnow() mod_copies = [] for target in users: mod_copies.append({ 'userid': userid, 'target_user': target, 'unixtime': now, 'settings': 's', 'content': mod_content, }) d.engine.execute( d.meta.tables['comments'].insert() .values(mod_copies))