def bulk_edit_rating(userid, new_rating, submissions=(), characters=(), journals=()): action_string = 'rerated to ' + ratings.CODE_TO_NAME[new_rating] with d.engine.begin() as db: affected = collections.defaultdict(list) copyable = [] for (tbl, pk, title_col, urlpart), ids in zip(_tables, [submissions, characters, journals]): if not ids: continue join = (tbl.select().where(tbl.c[pk].in_(ids)).where( tbl.c.rating != new_rating).with_for_update().alias('join')) results = db.execute(tbl.update().where( tbl.c[pk] == join.c[pk]).values(rating=new_rating).returning( tbl.c[pk], tbl.c[title_col], tbl.c.userid, join.c.rating)) for thingid, title, ownerid, original_rating in results: item_format = '- (from %s) %%s' % (original_rating.name, ) affected[ownerid].append(item_format % text.markdown_link( title, '/%s/%s?anyway=true' % (urlpart, thingid))) copyable.append( item_format % text.markdown_link(title, '/%s/%s' % (urlpart, thingid))) now = arrow.utcnow() values = [] for target, target_affected in affected.iteritems(): staff_note = '## The following items were %s:\n\n%s' % ( action_string, '\n'.join(target_affected)) values.append({ 'userid': userid, 'target_user': target, 'unixtime': now, 'settings': 's', 'content': staff_note, }) if values: db.execute(d.meta.tables['comments'].insert().values(values)) return 'Affected items (%s): \n\n%s' % (action_string, '\n'.join(copyable))
def edit(userid, journal, friends_only=False): if not journal.title: raise WeasylError("titleInvalid") elif not journal.content: raise WeasylError("contentInvalid") elif not journal.rating: raise WeasylError("ratingInvalid") profile.check_user_rating_allowed(userid, journal.rating) query = d.execute("SELECT userid, settings FROM journal WHERE journalid = %i", [journal.journalid], options="single") if not query or "h" in query[1]: raise WeasylError("Unexpected") elif userid != query[0] and userid not in staff.MODS: raise WeasylError("InsufficientPermissions") settings = [query[1].replace("f", "")] settings.append("f" if friends_only else "") settings = "".join(settings) if "f" in settings: welcome.journal_remove(journal.journalid) d.execute("UPDATE journal SET (title, content, rating, settings) = ('%s', '%s', %i, '%s') WHERE journalid = %i", [journal.title, journal.content, journal.rating.code, settings, journal.journalid]) if userid != query[0]: moderation.note_about( userid, query[0], 'The following journal was edited:', '- ' + text.markdown_link(journal.title, '/journal/%s?anyway=true' % (journal.journalid,)))
def bulk_edit_rating(userid, new_rating, submissions=(), characters=(), journals=()): action_string = 'rerated to ' + ratings.CODE_TO_NAME[new_rating] with d.engine.begin() as db: affected = collections.defaultdict(list) copyable = [] for (tbl, pk, title_col, urlpart), ids in zip(_tables, [submissions, characters, journals]): if not ids: continue join = ( tbl.select() .where(tbl.c[pk].in_(ids)) .where(tbl.c.rating != new_rating) .with_for_update() .alias('join')) results = db.execute( tbl.update() .where(tbl.c[pk] == join.c[pk]) .values(rating=new_rating) .returning(tbl.c[pk], tbl.c[title_col], tbl.c.userid, join.c.rating)) for thingid, title, ownerid, original_rating in results: item_format = '- (from %s) %%s' % (original_rating.name,) affected[ownerid].append(item_format % text.markdown_link(title, '/%s/%s?anyway=true' % (urlpart, thingid))) copyable.append(item_format % text.markdown_link(title, '/%s/%s' % (urlpart, thingid))) now = arrow.utcnow() values = [] for target, target_affected in affected.iteritems(): staff_note = '## The following items were %s:\n\n%s' % (action_string, '\n'.join(target_affected)) values.append({ 'userid': userid, 'target_user': target, 'unixtime': now, 'settings': 's', 'content': staff_note, }) if values: db.execute(d.meta.tables['comments'].insert().values(values)) return 'Affected items (%s): \n\n%s' % (action_string, '\n'.join(copyable))
def removethumbnail(userid, submitid): sub = Submission.query.get(submitid) thumbnail.clear_thumbnail(userid, submitid) # Thumbnails may be cached on the front page, so invalidate that cache. index.recent_submissions.invalidate() index.template_fields.invalidate(userid) otherid = sub.owner.userid title = sub.title note_about(userid, otherid, 'Thumbnail was removed for ' + text.markdown_link(title, '/submission/%s?anyway=true' % submitid))
def removecoverart(userid, submitid): sub = Submission.query.get(submitid) if not sub.cover_media: raise WeasylError("noCover") submission.reupload_cover(userid, submitid, None) otherid = sub.owner.userid title = sub.title note_about(userid, otherid, 'Cover was removed for ' + text.markdown_link(title, '/submission/%s?anyway=true' % submitid))
def edit(userid, character, friends_only): query = define.execute( "SELECT userid, settings FROM character WHERE charid = %i", [character.charid], options="single") if not query or "h" in query[1]: raise WeasylError("Unexpected") elif userid != query[0] and userid not in staff.MODS: raise WeasylError("InsufficientPermissions") elif not character.char_name: raise WeasylError("characterNameInvalid") elif not character.rating: raise WeasylError("Unexpected") profile.check_user_rating_allowed(userid, character.rating) # Assign settings settings = [query[1].replace("f", "")] settings.append("f" if friends_only else "") settings = "".join(settings) if "f" in settings: welcome.character_remove(character.charid) define.execute( """ UPDATE character SET (char_name, age, gender, height, weight, species, content, rating, settings) = ('%s', '%s', '%s', '%s', '%s', '%s', '%s', %i, '%s') WHERE charid = %i """, [ character.char_name, character.age, character.gender, character.height, character.weight, character.species, character.content, character.rating.code, settings, character.charid ]) if userid != query[0]: from weasyl import moderation moderation.note_about( userid, query[0], 'The following character was edited:', '- ' + text.markdown_link( character.char_name, '/character/%s?anyway=true' % (character.charid, )))
def edit(userid, journal, friends_only=False): if not journal.title: raise WeasylError("titleInvalid") elif not journal.content: raise WeasylError("contentInvalid") elif not journal.rating: raise WeasylError("ratingInvalid") profile.check_user_rating_allowed(userid, journal.rating) query = d.engine.execute( "SELECT userid, settings FROM journal WHERE journalid = %(id)s", id=journal.journalid, ).first() if not query or "h" in query[1]: raise WeasylError("Unexpected") elif userid != query[0] and userid not in staff.MODS: raise WeasylError("InsufficientPermissions") settings = query[1].replace("f", "") if friends_only: settings += "f" welcome.journal_remove(journal.journalid) jo = d.meta.tables['journal'] d.engine.execute( jo.update().where(jo.c.journalid == journal.journalid).values({ 'title': journal.title, 'content': journal.content, 'rating': journal.rating, 'settings': settings, })) if userid != query[0]: moderation.note_about( userid, query[0], 'The following journal was edited:', '- ' + text.markdown_link( journal.title, '/journal/%s?anyway=true' % (journal.journalid, )))
def edit(userid, character, friends_only): query = define.engine.execute("SELECT userid, settings FROM character WHERE charid = %(id)s", id=character.charid).first() if not query or "h" in query[1]: raise WeasylError("Unexpected") elif userid != query[0] and userid not in staff.MODS: raise WeasylError("InsufficientPermissions") elif not character.char_name: raise WeasylError("characterNameInvalid") elif not character.rating: raise WeasylError("Unexpected") profile.check_user_rating_allowed(userid, character.rating) # Assign settings settings = query[1].replace("f", "") if friends_only: settings += "f" welcome.character_remove(character.charid) ch = define.meta.tables["character"] define.engine.execute( ch.update() .where(ch.c.charid == character.charid) .values({ 'char_name': character.char_name, 'age': character.age, 'gender': character.gender, 'height': character.height, 'weight': character.weight, 'species': character.species, 'content': character.content, 'rating': character.rating, 'settings': settings, }) ) if userid != query[0]: from weasyl import moderation moderation.note_about( userid, query[0], 'The following character was edited:', '- ' + text.markdown_link(character.char_name, '/character/%s?anyway=true' % (character.charid,)))
def edit(userid, journal, friends_only=False): if not journal.title: raise WeasylError("titleInvalid") elif not journal.content: raise WeasylError("contentInvalid") elif not journal.rating: raise WeasylError("ratingInvalid") profile.check_user_rating_allowed(userid, journal.rating) query = d.execute( "SELECT userid, settings FROM journal WHERE journalid = %i", [journal.journalid], options="single") if not query or "h" in query[1]: raise WeasylError("Unexpected") elif userid != query[0] and userid not in staff.MODS: raise WeasylError("InsufficientPermissions") settings = [query[1].replace("f", "")] settings.append("f" if friends_only else "") settings = "".join(settings) if "f" in settings: welcome.journal_remove(journal.journalid) # TODO(kailys): use ORM d.execute( "UPDATE journal SET (title, rating, settings) = ('%s', %i, '%s') WHERE journalid = %i", [journal.title, journal.rating.code, settings, journal.journalid]) # Write journal file files.write( files.make_resource(userid, journal.journalid, "journal/submit"), journal.content) if userid != query[0]: from weasyl import moderation moderation.note_about( userid, query[0], 'The following journal was edited:', '- ' + text.markdown_link( journal.title, '/journal/%s?anyway=true' % (journal.journalid, )))
def edit(userid, character, friends_only): query = define.execute("SELECT userid, settings FROM character WHERE charid = %i", [character.charid], options="single") if not query or "h" in query[1]: raise WeasylError("Unexpected") elif userid != query[0] and userid not in staff.MODS: raise WeasylError("InsufficientPermissions") elif not character.char_name: raise WeasylError("characterNameInvalid") elif not character.rating: raise WeasylError("Unexpected") profile.check_user_rating_allowed(userid, character.rating) # Assign settings settings = [query[1].replace("f", "")] settings.append("f" if friends_only else "") settings = "".join(settings) if "f" in settings: welcome.character_remove(character.charid) define.execute( """ UPDATE character SET (char_name, age, gender, height, weight, species, content, rating, settings) = ('%s', '%s', '%s', '%s', '%s', '%s', '%s', %i, '%s') WHERE charid = %i """, [character.char_name, character.age, character.gender, character.height, character.weight, character.species, character.content, character.rating.code, settings, character.charid]) if userid != query[0]: from weasyl import moderation moderation.note_about( userid, query[0], 'The following character was edited:', '- ' + text.markdown_link(character.char_name, '/character/%s?anyway=true' % (character.charid,)))
def edit(userid, submission, embedlink=None, friends_only=False, critique=False): query = d.execute( "SELECT userid, subtype, settings FROM submission WHERE submitid = %i", [submission.submitid], ["single"]) if not query or "h" in query[2]: raise WeasylError("Unexpected") elif "a" in query[2] and userid not in staff.MODS: raise WeasylError("AdminLocked") elif userid != query[0] and userid not in staff.MODS: raise WeasylError("InsufficientPermissions") elif not submission.title: raise WeasylError("titleInvalid") elif not submission.rating: raise WeasylError("Unexpected") elif not folder.check(query[0], submission.folderid): raise WeasylError("Unexpected") elif submission.subtype / 1000 != query[1] / 1000: raise WeasylError("Unexpected") elif 'v' in query[2] and not embed.check_valid(embedlink): raise WeasylError("embedlinkInvalid") elif 'D' in query[2]: check_google_doc_embed_data(embedlink) profile.check_user_rating_allowed(userid, submission.rating) # Assign settings settings = [query[2].replace("f", "").replace("q", "")] settings.append("f" if friends_only else "") settings.append("q" if critique else "") settings = "".join(settings) if "v" in settings: submission.content = "%s\n%s" % (embedlink, submission.content) if "f" in settings: welcome.submission_became_friends_only(submission.submitid, userid) # TODO(kailys): maintain ORM object db = d.connect() su = d.meta.tables['submission'] q = (su.update().values( folderid=submission.folderid, title=submission.title, content=submission.content, subtype=submission.subtype, rating=submission.rating, settings=settings, ).where(su.c.submitid == submission.submitid)) db.execute(q) if 'D' in settings: db = d.connect() gde = d.meta.tables['google_doc_embeds'] q = (gde.update().values(embed_url=embedlink).where( gde.c.submitid == submission.submitid)) db.execute(q) if userid != query[0]: from weasyl import moderation moderation.note_about( userid, query[0], 'The following submission was edited:', '- ' + text.markdown_link( submission.title, '/submission/%s?anyway=true' % (submission.submitid, )))
def bulk_edit(userid, action, submissions=(), characters=(), journals=()): if not submissions and not characters and not journals or action == 'null': return 'Nothing to do.' if action == 'show': # Unhide (show/make visible) a submission def action(tbl): return ( tbl.update() .values(settings=sa.func.replace(tbl.c.settings, 'h', '')) .where(tbl.c.settings.op('~')('h'))) action_string = 'unhidden' provide_link = True elif action == 'hide': # Hide a submission from public view def action(tbl): return ( tbl.update() .values(settings=tbl.c.settings.op('||')('h')) .where(tbl.c.settings.op('!~')('h'))) action_string = 'hidden' # There's no value in giving the user a link to the submission as they # won't be able to see it. provide_link = False elif action.startswith('rate-'): # Re-rate a submission _, _, rating = action.partition('-') rating = int(rating) def action(tbl): return ( tbl.update() .values(rating=rating) .where(tbl.c.rating != rating)) action_string = 'rerated ' + ratings.CODE_TO_NAME[rating] provide_link = True elif action == 'clearcritique': # Clear the "critique requested" flag def action(tbl): return ( tbl.update() .values(settings=sa.func.replace(tbl.c.settings, 'q', '')) .where(tbl.c.settings.op('~')('q'))) action_string = 'unmarked as "critique requested"' provide_link = True elif action == 'setcritique': # Set the "critique requested" flag def action(tbl): return ( tbl.update() .values(settings=tbl.c.settings.op('||')('q')) .where(tbl.c.settings.op('!~')('q'))) action_string = 'marked as "critique requested"' provide_link = True else: raise WeasylError('Unexpected') db = d.connect() affected = collections.defaultdict(list) copyable = [] for (tbl, col, title_col, urlpart), values in zip(_tables, [submissions, characters, journals]): if values: results = db.execute( action(tbl) .where(tbl.c[col].in_(values)) .returning(tbl.c[col], tbl.c[title_col], tbl.c.userid)) for thingid, title, ownerid in results: affected[ownerid].append('- ' + text.markdown_link(title, '/%s/%s?anyway=true' % (urlpart, thingid))) if provide_link: copyable.append('- ' + text.markdown_link(title, '/%s/%s' % (urlpart, thingid))) else: copyable.append('- %s' % (title,)) now = arrow.utcnow() values = [] for target, target_affected in affected.iteritems(): staff_note = '## The following items were %s:\n\n%s' % (action_string, '\n'.join(target_affected)) values.append({ 'userid': userid, 'target_user': target, 'unixtime': now, 'settings': 's', 'content': staff_note, }) if values: db.execute(d.meta.tables['comments'].insert().values(values)) return 'Affected items (%s): \n\n%s' % (action_string, '\n'.join(copyable))
def bulk_edit(userid, action, submissions=(), characters=(), journals=()): if not submissions and not characters and not journals or action == 'null': return 'Nothing to do.' if action == 'show': # Unhide (show/make visible) a submission def action(tbl): return ( tbl.update() .values(settings=sa.func.replace(tbl.c.settings, 'h', '')) .where(tbl.c.settings.op('~')('h'))) action_string = 'unhidden' provide_link = True elif action == 'hide': # Hide a submission from public view def action(tbl): return ( tbl.update() .values(settings=tbl.c.settings.op('||')('h')) .where(tbl.c.settings.op('!~')('h'))) action_string = 'hidden' # There's no value in giving the user a link to the submission as they # won't be able to see it. provide_link = False elif action.startswith('rate-'): # Re-rate a submission _, _, rating = action.partition('-') rating = int(rating) return bulk_edit_rating(userid, rating, submissions, characters, journals) elif action == 'clearcritique': # Clear the "critique requested" flag def action(tbl): return ( tbl.update() .values(settings=sa.func.replace(tbl.c.settings, 'q', '')) .where(tbl.c.settings.op('~')('q'))) action_string = 'unmarked as "critique requested"' provide_link = True elif action == 'setcritique': # Set the "critique requested" flag def action(tbl): return ( tbl.update() .values(settings=tbl.c.settings.op('||')('q')) .where(tbl.c.settings.op('!~')('q'))) action_string = 'marked as "critique requested"' provide_link = True else: raise WeasylError('Unexpected') db = d.connect() affected = collections.defaultdict(list) copyable = [] for (tbl, col, title_col, urlpart), values in zip(_tables, [submissions, characters, journals]): if values: results = db.execute( action(tbl) .where(tbl.c[col].in_(values)) .returning(tbl.c[col], tbl.c[title_col], tbl.c.userid)) for thingid, title, ownerid in results: affected[ownerid].append('- ' + text.markdown_link(title, '/%s/%s?anyway=true' % (urlpart, thingid))) if provide_link: copyable.append('- ' + text.markdown_link(title, '/%s/%s' % (urlpart, thingid))) else: copyable.append('- %s' % (title,)) now = arrow.utcnow() values = [] for target, target_affected in affected.items(): staff_note = '## The following items were %s:\n\n%s' % (action_string, '\n'.join(target_affected)) values.append({ 'userid': userid, 'target_user': target, 'unixtime': now, 'settings': 's', 'content': staff_note, }) if values: db.execute(d.meta.tables['comments'].insert().values(values)) return 'Affected items (%s): \n\n%s' % (action_string, '\n'.join(copyable))
def edit(userid, submission, embedlink=None, friends_only=False, critique=False): query = d.execute( "SELECT userid, subtype, settings FROM submission WHERE submitid = %i", [submission.submitid], ["single"]) if not query or "h" in query[2]: raise WeasylError("Unexpected") elif "a" in query[2] and userid not in staff.MODS: raise WeasylError("AdminLocked") elif userid != query[0] and userid not in staff.MODS: raise WeasylError("InsufficientPermissions") elif not submission.title: raise WeasylError("titleInvalid") elif not submission.rating: raise WeasylError("Unexpected") elif not folder.check(query[0], submission.folderid): raise WeasylError("Unexpected") elif submission.subtype / 1000 != query[1] / 1000: raise WeasylError("Unexpected") elif 'v' in query[2] and not embed.check_valid(embedlink): raise WeasylError("embedlinkInvalid") elif 'D' in query[2]: check_google_doc_embed_data(embedlink) profile.check_user_rating_allowed(userid, submission.rating) # Assign settings settings = [query[2].replace("f", "").replace("q", "")] settings.append("f" if friends_only else "") settings.append("q" if critique else "") settings = "".join(settings) if "v" in settings: submission.content = "%s\n%s" % (embedlink, submission.content) if "f" in settings: welcome.submission_became_friends_only(submission.submitid, userid) # TODO(kailys): maintain ORM object db = d.connect() su = d.meta.tables['submission'] q = ( su.update() .values( folderid=submission.folderid, title=submission.title, content=submission.content, subtype=submission.subtype, rating=submission.rating, settings=settings, ) .where(su.c.submitid == submission.submitid)) db.execute(q) if 'D' in settings: db = d.connect() gde = d.meta.tables['google_doc_embeds'] q = (gde.update() .values(embed_url=embedlink) .where(gde.c.submitid == submission.submitid)) db.execute(q) if userid != query[0]: from weasyl import moderation moderation.note_about( userid, query[0], 'The following submission was edited:', '- ' + text.markdown_link(submission.title, '/submission/%s?anyway=true' % (submission.submitid,)))
def test_markdown_link(target, expected): assert markdown_link(*target) == expected