Exemple #1
0
        def create_generic(userid, submission, **kwargs):
            tags = kwargs['tags']

            if submission.subtype not in valid_types:
                submission.subtype = expected_type * 1000 + 999

            if not submission.title:
                raise WeasylError("titleInvalid")
            elif not submission.rating:
                raise WeasylError("ratingInvalid")
            elif len(tags) < 2:
                raise WeasylError("notEnoughTags")
            elif not folder.check(userid, submission.folderid):
                raise WeasylError("Unexpected")

            profile.check_user_rating_allowed(userid, submission.rating)

            newid = create_specific(
                userid=userid,
                submission=submission,
                **kwargs)
            if newid:
                p = d.meta.tables['profile']
                d.connect().execute(p.update().where(p.c.userid == userid).values(latest_submission_time=arrow.utcnow()))
            return newid
Exemple #2
0
def create_user(full_name="", birthday=arrow.get(586162800), config=None,
                username=None, password=None, email_addr=None, user_id=None):
    """ Creates a new user and profile, and returns the user ID. """
    if username is None:
        username = "******" + str(next(_user_index))

    while True:
        user = add_entity(users.Login(login_name=legacy.login_name(username),
                                      last_login=arrow.get(0)))

        if user.userid not in staff.MODS and user.userid not in staff.DEVELOPERS:
            break

        db = d.connect()
        db.delete(user)
        db.flush()

    add_entity(users.Profile(userid=user.userid, username=username,
                             full_name=full_name, unixtime=arrow.get(0), config=config))
    add_entity(users.UserInfo(userid=user.userid, birthday=birthday))
    # Set a password for this user
    if password is not None:
        d.engine.execute("INSERT INTO authbcrypt VALUES (%(id)s, %(bcrypthash)s)",
                         id=user.userid, bcrypthash=login.passhash(password))
    # Set an email address for this user
    if email_addr is not None:
        d.engine.execute("UPDATE login SET email = %(email)s WHERE userid = %(id)s",
                         email=email_addr, id=user.userid)
    # Force the userID to a user-defined value and return it
    if user_id is not None:
        d.engine.execute("UPDATE login SET userid = %(newid)s WHERE userid = %(oldid)s", newid=user_id, oldid=user.userid)
        return user_id
    return user.userid
Exemple #3
0
def main():
    db = d.connect()
    q = (
        sa.select([sa.func.array_agg(orm.MediaItem.mediaid)])
        .where(orm.MediaItem.sha256 != None)
        .group_by(orm.MediaItem.sha256)
        .having(sa.func.count() > 1))
    [[count]] = db.execute(
        sa.select([sa.func.count()])
        .select_from(q.alias('query'))
    ).fetchall()
    for e, (mediaids,) in enumerate(db.execute(q), start=1):
        sys.stdout.write('\r%d/%d' % (e, count))
        sys.stdout.flush()
        old_media_item = db.query(orm.DiskMediaItem).get(mediaids[0])
        new_media_item = orm.DiskMediaItem(
            sha256=old_media_item.sha256, file_type=old_media_item.file_type)
        with open(old_media_item.full_file_path, 'rb') as infile:
            data = infile.read()
        new_media_item.init_from_data(data)
        db.add(new_media_item)
        db.flush()
        for table, column in [('submission_media_links', 'mediaid'),
                              ('user_media_links', 'mediaid'),
                              ('media_media_links', 'described_with_id'),
                              ('media_media_links', 'describee_id')]:
            table_obj = d.meta.tables[table]
            q = (
                table_obj.update()
                .values(**{column: new_media_item.mediaid})
                .where(table_obj.c[column].in_(mediaids)))
            db.execute(q)
    print
Exemple #4
0
def main():
    db = define.connect()
    all_media = sa.union(
        sa.select([orm.UserMediaLink.mediaid]),
        sa.select([orm.SubmissionMediaLink.mediaid]),
        sa.select([orm.MediaMediaLink.describee_id]),
        sa.select([orm.MediaMediaLink.described_with_id]),
    ).alias('all_media')
    q = (
        db.query(orm.MediaItem)
        .with_polymorphic([orm.DiskMediaItem])
        .outerjoin(all_media)
        .filter(all_media.c.mediaid == None))
    count = q.count()
    for e, media_item in enumerate(q, start=1):
        sys.stdout.write('\r%d/%d' % (e, count))
        sys.stdout.flush()
        db.delete(media_item)
        try:
            os.unlink(media_item.full_file_path)
        except OSError as e:
            if e.errno == errno.ENOENT:
                continue
            raise
    db.flush()
    print
Exemple #5
0
def finduser(userid, form):
    form.userid = d.get_int(form.userid)
    lo = d.meta.tables['login']
    sh = d.meta.tables['comments']
    q = d.sa.select([
        lo.c.userid,
        lo.c.login_name,
        lo.c.email,
        (d.sa.select([d.sa.func.count()])
         .select_from(sh)
         .where(sh.c.target_user == lo.c.userid)
         .where(sh.c.settings.op('~')('s'))).label('staff_notes'),
    ])

    if form.userid:
        q = q.where(lo.c.userid == form.userid)
    elif form.username:
        q = q.where(lo.c.login_name.op('~')(form.username))
    elif form.email:
        q = q.where(d.sa.or_(
            lo.c.email.op('~')(form.email),
            lo.c.email.op('ilike')('%%%s%%' % form.email),
        ))
    else:
        return []

    q = q.limit(100).order_by(lo.c.login_name.asc())
    db = d.connect()
    return db.execute(q)
Exemple #6
0
def main():
    do_users, min_submission = sys.argv[1:]
    db = connect()
    if do_users == 'yes':
        print 'starting users'
        port_users(db)
    print 'starting submissions'
    port_submissions(db, int(min_submission))
Exemple #7
0
def check_for_duplicate_media(userid, mediaid):
    db = d.connect()
    q = (
        db.query(orm.Submission)
        .filter_by(userid=userid, is_hidden=False)
        .join(orm.SubmissionMediaLink)
        .filter_by(mediaid=mediaid, link_type='submission'))
    if q.first():
        raise WeasylError('duplicateSubmission')
Exemple #8
0
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
Exemple #9
0
def tag_history(submitid):
    db = d.connect()
    tu = d.meta.tables['tag_updates']
    pr = d.meta.tables['profile']
    return db.execute(
        sa.select([pr.c.username, tu.c.updated_at, tu.c.added, tu.c.removed])
        .select_from(tu.join(pr, tu.c.userid == pr.c.userid))
        .where(tu.c.submitid == submitid)
        .order_by(tu.c.updated_at.desc()))
Exemple #10
0
def edit_preferences(userid, timezone=None,
                     preferences=None, jsonb_settings=None):
    """
    Apply changes to stored preferences for a given user.
    :param userid: The userid to apply changes to
    :param timezone: (optional) new Timezone to set for user
    :param preferences: (optional) old-style char preferences, overwrites all previous settings
    :param jsonb_settings: (optional) JSON preferences, overwrites all previous settings
    :return: None
    """
    config = d.get_config(userid)

    tooyoung = False
    if preferences is not None:
        tooyoung |= get_user_age(userid) < preferences.rating.minimum_age
    if jsonb_settings is not None:
        sfwrating = jsonb_settings.max_sfw_rating
        sfwrating = ratings.CODE_MAP.get(sfwrating, ratings.GENERAL)
        tooyoung |= get_user_age(userid) < sfwrating.minimum_age

    if tooyoung:
        raise WeasylError("birthdayInsufficient")
    if timezone is not None and timezone not in pytz.all_timezones:
        raise WeasylError('invalidTimezone')

    db = d.connect()
    updates = {}
    if preferences is not None:
        # update legacy preferences
        # clear out the option codes that are being replaced.
        for i in Config.all_option_codes:
            config = config.replace(i, "")
        config_str = config + preferences.to_code()
        updates['config'] = config_str
        d._get_config.invalidate(userid)
    if jsonb_settings is not None:
        # update jsonb preferences
        updates['jsonb_settings'] = jsonb_settings.get_raw()
        d._get_profile_settings.invalidate(userid)

    d.engine.execute(
        tables.profile.update().where(tables.profile.c.userid == userid),
        updates
    )

    # update TZ
    if timezone is not None:
        tz = db.query(orm.UserTimezone).get(userid)
        if tz is None:
            tz = orm.UserTimezone(userid=userid)
            db.add(tz)
        tz.timezone = timezone
        db.flush()
        tz.cache()
    else:
        db.flush()
Exemple #11
0
def create_submission_tag(tagid, targetid, settings=None):
    db = d.connect()
    db.add(
        content.SubmissionTag(tagid=tagid, targetid=targetid, settings=settings))
    db.flush()

    db.execute(
        'INSERT INTO submission_tags (submitid, tags) VALUES (:submission, ARRAY[:tag]) '
        'ON CONFLICT (submitid) DO UPDATE SET tags = submission_tags.tags || :tag',
        {'submission': targetid, 'tag': tagid})
Exemple #12
0
def editprofiletext(userid, otherid, content):
    pr = d.meta.tables['profile']
    db = d.connect()
    condition = pr.c.userid == otherid
    previous_profile = db.scalar(sa.select([pr.c.profile_text]).where(condition))
    db.execute(pr.update().where(condition).values(profile_text=content))
    note_about(
        userid, otherid,
        'Profile text replaced with:',
        '%s\n\n## Profile text was:\n\n%s' % (content, previous_profile))
Exemple #13
0
def editcatchphrase(userid, otherid, content):
    pr = d.meta.tables['profile']
    db = d.connect()
    condition = pr.c.userid == otherid
    previous_catchphrase = db.scalar(sa.select([pr.c.catchphrase]).where(condition))
    db.execute(pr.update().where(condition).values(catchphrase=content))
    note_about(
        userid, otherid,
        'Catchphrase replaced with:',
        '%s\n\n## Catchphrase was:\n\n%s' % (content, previous_catchphrase))
Exemple #14
0
def count(ownerid, staffnotes=False):
    db = d.connect()
    sh = d.meta.tables['comments']
    op = '~' if staffnotes else '!~'
    q = (
        d.sa.select([d.sa.func.count()])
        .select_from(sh)
        .where(sh.c.settings.op(op)('s'))
        .where(sh.c.target_user == ownerid))
    (ret,), = db.execute(q)
    return ret
Exemple #15
0
def create_session(user):
    """
    Creates a session for a user and returns the corresponding WZL cookie.
    """
    session = sessions.create_session(user)

    db = d.connect()
    db.add(session)
    db.flush()

    return 'WZL=' + session.sessionid.encode('utf-8')
Exemple #16
0
def test_verify_login_record_is_updated():
    # Use a fake session for this test.
    user_id = db_utils.create_user()
    sess = get_current_request().weasyl_session = create_session(user_id)
    db = d.connect()
    db.add(sess)
    db.flush()
    d.engine.execute("UPDATE login SET last_login = -1 WHERE userid = %(id)s", id=user_id)
    login.signin(get_current_request(), user_id)
    last_login = d.engine.scalar("SELECT last_login FROM login WHERE userid = %(id)s", id=user_id)
    assert last_login > -1
Exemple #17
0
def note_about(userid, target_user, title, message=None):
    staff_note = '## ' + title
    if message:
        staff_note = '%s\n\n%s' % (staff_note, message)

    db = d.connect()
    db.execute(
        d.meta.tables['comments'].insert()
        .values(
            userid=userid, target_user=target_user, unixtime=arrow.utcnow(),
            settings='s', content=staff_note,
        ))
Exemple #18
0
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,
    }
Exemple #19
0
def create_session(user):
    """
    Creates a session for a user and returns the corresponding WZL cookie.
    """
    session = orm.Session()
    session.sessionid = security.generate_key(64)
    session.userid = user

    db = d.connect()
    db.add(session)
    db.flush()

    return 'WZL=' + session.sessionid.encode('utf-8')
Exemple #20
0
def db(request):
    db = define.connect()

    def tear_down():
        """ Clears all rows from the test database. """
        for k, cls in registry.iteritems():
            if not k[0].isupper():
                continue
            db.query(cls).delete()
        db.flush()

    request.addfinalizer(tear_down)
    return db
Exemple #21
0
def select_list(map_table, targetids):
    if not targetids:
        return {}

    mt = map_table
    q = (
        d.sa
        .select([mt.c.targetid, d.sa.func.array_agg(mt.c.tagid)])
        .select_from(mt)
        .where(mt.c.targetid.in_(targetids))
        .group_by(mt.c.targetid))

    db = d.connect()
    return dict(list(db.execute(q)))
Exemple #22
0
def create(userid, x1, y1, x2, y2, auto=False, config=None):
    x1, y1, x2, y2 = d.get_int(x1), d.get_int(y1), d.get_int(x2), d.get_int(y2)
    db = d.connect()
    im = db.query(orm.MediaItem).get(avatar_source(userid)['mediaid']).as_image()
    file_type = image.image_file_type(im)
    bounds = None
    size = im.size.width, im.size.height
    if not auto and image.check_crop(size, x1, y1, x2, y2):
        bounds = geometry.Rectangle(x1, y1, x2, y2)
    thumb = image.shrinkcrop(im, geometry.Size(100, 100), bounds)
    media_item = orm.fetch_or_create_media_item(
        thumb.to_buffer(format=file_type), file_type=file_type, im=thumb)
    orm.UserMediaLink.make_or_replace_link(userid, 'avatar', media_item)
    orm.UserMediaLink.clear_link(userid, 'avatar-source')
Exemple #23
0
 def render_form(self, scopes, credentials, mobile, error=None,
                 username='', password='', remember_me=False, not_me=False):
     db = d.connect()
     client = db.query(orm.OAuthConsumer).get(credentials['client_id'])
     if self.user_id:
         user = db.query(orm.Login).get(self.user_id)
         user_media = media.get_user_media(self.user_id)
     else:
         user = user_media = None
     credentials['scopes'] = scopes
     return d.render('oauth2/authorize.html', [
         scopes, credentials, client, user, user_media, mobile, error,
         username, password, remember_me, not_me,
     ])
Exemple #24
0
def verify(token, ip_address=None):
    lo = d.meta.tables["login"]
    lc = d.meta.tables["logincreate"]
    query = d.engine.execute(lc.select().where(lc.c.token == token)).first()

    # Did the token match a pending login create record?
    if not query:
        raise WeasylError("logincreateRecordMissing")
    elif query.invalid:
        # If the record is explicitly marked as invalid, treat the record as if it doesn't exist.
        raise WeasylError("logincreateRecordMissing")

    db = d.connect()
    with db.begin():
        # Create login record
        userid = db.scalar(lo.insert().returning(lo.c.userid), {
            "login_name": d.get_sysname(query.username),
            "last_login": arrow.now(),
            "email": query.email,
            "ip_address_at_signup": ip_address,
        })

        # Create profile records
        db.execute(d.meta.tables["authbcrypt"].insert(), {
            "userid": userid,
            "hashsum": query.hashpass,
        })
        db.execute(d.meta.tables["profile"].insert(), {
            "userid": userid,
            "username": query.username,
            "full_name": query.username,
            "unixtime": arrow.now(),
            "config": "kscftj",
        })
        db.execute(d.meta.tables["userinfo"].insert(), {
            "userid": userid,
            "birthday": query.birthday,
        })
        db.execute(d.meta.tables["userstats"].insert(), {
            "userid": userid,
        })
        db.execute(d.meta.tables["welcomecount"].insert(), {
            "userid": userid,
        })

        # Update logincreate records
        db.execute(lc.delete().where(lc.c.token == token))

    d.metric('increment', 'verifiedusers')
Exemple #25
0
def select_list(map_table, targetids):
    if not targetids:
        return {}

    mt = map_table
    st = d.meta.tables['searchtag']
    q = (
        d.sa
        .select([mt.c.targetid, d.sa.func.array_agg(st.c.title)])
        .select_from(mt.join(st, mt.c.tagid == st.c.tagid))
        .where(mt.c.targetid.in_(targetids))
        .group_by(mt.c.targetid))

    db = d.connect()
    return dict(list(db.execute(q)))
Exemple #26
0
def select_with_artist_tags(submitid):
    db = d.connect()
    tags = (
        db.query(orm.Tag.title, orm.SubmissionTag.is_artist_tag)
        .join(orm.SubmissionTag)
        .filter_by(targetid=submitid)
        .order_by(orm.Tag.title)
        .all())
    ret = []
    artist_tags = set()
    for tag, is_artist_tag in tags:
        ret.append(tag)
        if is_artist_tag:
            artist_tags.add(tag)
    return ret, artist_tags
Exemple #27
0
def db(request):
    db = define.connect()

    def tear_down():
        """ Clears all rows from the test database. """
        db.flush()
        for table in metadata.tables.values():
            db.execute(table.delete())

    request.addfinalizer(tear_down)

    if request.cls is not None:
        request.cls.db = db

    return db
Exemple #28
0
def select_friends(userid, otherid, limit=None, backid=None, nextid=None, choose=False):
    """
    Return accepted friends. If `choose` is an integer, results will be ordered
    randomly.
    """
    fr = d.meta.tables['frienduser']
    pr = d.meta.tables['profile']
    iu = d.meta.tables['ignoreuser']

    friends = d.sa.union(
        (d.sa
         .select([fr.c.otherid, pr.c.username, pr.c.config])
         .select_from(fr.join(pr, fr.c.otherid == pr.c.userid))
         .where(d.sa.and_(fr.c.userid == otherid, fr.c.settings.op('!~')('p')))),
        (d.sa
         .select([fr.c.userid, pr.c.username, pr.c.config])
         .select_from(fr.join(pr, fr.c.userid == pr.c.userid))
         .where(d.sa.and_(fr.c.otherid == otherid, fr.c.settings.op('!~')('p')))))
    friends = friends.alias('friends')

    query = d.sa.select(friends.c)

    if userid:
        query = query.where(
            ~friends.c.otherid.in_(d.sa.select([iu.c.otherid]).where(iu.c.userid == userid)))
    if backid:
        query = query.where(
            friends.c.username < d.sa.select([pr.c.username]).where(pr.c.userid == backid))
    elif nextid:
        query = query.where(
            friends.c.username > d.sa.select([pr.c.username]).where(pr.c.userid == nextid))

    if choose:
        query = query.order_by('RANDOM()')
    else:
        query = query.order_by(
            friends.c.username.desc() if backid else friends.c.username.asc())
        query = query.limit(limit)

    db = d.connect()
    query = [{
        "userid": r.otherid,
        "username": r.username,
    } for r in db.execute(query)]

    ret = (d.get_random_set(query, choose) if choose else query[::-1] if backid else query)
    media.populate_with_user_media(ret)
    return ret
Exemple #29
0
def select_by_id(updateid):
    su = d.meta.tables['siteupdate']
    pr = d.meta.tables['profile']
    q = (
        sa.select([
            pr.c.userid, pr.c.username, su.c.title, su.c.content, su.c.unixtime,
        ])
        .select_from(su.join(pr, su.c.userid == pr.c.userid))
        .where(su.c.updateid == updateid))
    db = d.connect()
    results = db.execute(q).fetchall()
    if not results:
        raise WeasylError('RecordMissing')
    results = dict(results[0])
    results['user_media'] = media.get_user_media(results['userid'])
    results['timestamp'] = results['unixtime'].timestamp + UNIXTIME_OFFSET
    return results
Exemple #30
0
def run_periodic_tasks():
    web.ctx.clear()

    now = arrow.utcnow()
    time_now = get_time()

    db = connect().connection()
    with db.begin():
        locked = db.scalar("SELECT pg_try_advisory_xact_lock(0)")
        if not locked:
            return
        last_run = arrow.get(db.scalar("SELECT last_run FROM cron_runs"))
        if not last_run or now < last_run.replace(seconds=59):
            return

        # Recache the latest submissions
        # Every 2 minutes
        if now.minute % 2 == 0:
            index.recent_submissions.refresh()
            log.msg('refreshed recent submissions')

        # Recache the active user counts
        # Every 5 minutes
        if now.minute % 5 == 0:
            active_users.refresh()
            log.msg('refreshed active user counts')

        # Recalculate recently popular submissions
        # Every 10 minutes
        if now.minute % 10 == 0:
            submission.select_recently_popular.refresh()
            log.msg('refreshed recently popular submissions')

        # Delete all records from contentview table
        # Every 15 minutes
        if now.minute % 15 == 0:
            db.execute("DELETE FROM views")
            log.msg('cleared views')

        # Delete password resets older than one day
        # Daily at 0:00
        if now.hour == 0 and now.minute == 0:
            db.execute("DELETE FROM forgotpassword WHERE set_time < %(expiry)s", expiry=time_now - 86400)
            log.msg('cleared old forgotten password requests')

        db.execute("UPDATE cron_runs SET last_run = %(now)s", now=now.naive)
Exemple #31
0
def insert(userid,
           submitid=None,
           charid=None,
           journalid=None,
           parentid=None,
           content=None):
    if not submitid and not charid and not journalid:
        raise WeasylError("Unexpected")
    elif not content:
        raise WeasylError("commentInvalid")

    # Determine indent and parentuserid
    if parentid:
        query = d.execute(
            "SELECT userid, indent FROM %s WHERE commentid = %i", [
                "comments" if submitid else
                "charcomment" if charid else "journalcomment", parentid
            ],
            options="single")

        if not query:
            raise WeasylError("Unexpected")

        indent = query[1] + 1
        parentuserid = query[0]
    else:
        indent = 0
        parentuserid = None

    # Determine otherid
    otherid = d.execute(
        "SELECT userid FROM %s WHERE %s = %i AND settings !~ 'h'",
        ["submission", "submitid", submitid]
        if submitid else ["character", "charid", charid]
        if charid else ["journal", "journalid", journalid],
        options="element")

    # Check permissions
    if not otherid:
        raise WeasylError("submissionRecordMissing")
    elif ignoreuser.check(otherid, userid):
        raise WeasylError("pageOwnerIgnoredYou")
    elif ignoreuser.check(userid, otherid):
        raise WeasylError("youIgnoredPageOwner")
    elif parentuserid and ignoreuser.check(parentuserid, userid):
        raise WeasylError("replyRecipientIgnoredYou")
    elif parentuserid and ignoreuser.check(userid, parentuserid):
        raise WeasylError("youIgnoredReplyRecipient")

    # Create comment
    if submitid:
        co = d.meta.tables['comments']
        db = d.connect()
        commentid = db.scalar(co.insert().values(userid=userid,
                                                 target_sub=submitid,
                                                 parentid=parentid or None,
                                                 content=content,
                                                 unixtime=arrow.utcnow(),
                                                 indent=indent).returning(
                                                     co.c.commentid))
    else:
        commentid = d.execute(
            "INSERT INTO %s (userid, targetid, parentid, "
            "content, unixtime, indent) VALUES (%i, %i, %i, '%s', %i, %i) RETURNING "
            "commentid", [
                "charcomment" if charid else "journalcomment", userid,
                d.get_targetid(submitid, charid, journalid), parentid, content,
                d.get_time(), indent
            ],
            options="element")

    # Create notification
    if parentid and (userid != parentuserid):
        welcome.commentreply_insert(userid, commentid, parentuserid, parentid,
                                    submitid, charid, journalid)
    elif not parentid:
        # build a list of people this comment should notify
        # circular imports are cool and fun
        from weasyl.collection import find_owners
        notified = set(find_owners(submitid))

        # check to see who we should deliver comment notifications to
        def can_notify(other):
            other_jsonb = d.get_profile_settings(other)
            allow_notify = other_jsonb.allow_collection_notifs
            ignored = ignoreuser.check(other, userid)
            return allow_notify and not ignored

        notified = set(filter(can_notify, notified))
        # always give notification on own content
        notified.add(otherid)
        # don't give me a notification for my own comment
        notified.discard(userid)

        for other in notified:
            welcome.comment_insert(userid, commentid, other, submitid, charid,
                                   journalid)

    d.metric('increment', 'comments')

    return commentid
Exemple #32
0
def create_multimedia(userid,
                      submission,
                      embedlink=None,
                      friends_only=None,
                      tags=None,
                      coverfile=None,
                      thumbfile=None,
                      submitfile=None,
                      critique=False,
                      create_notifications=True,
                      auto_thumb=False):
    embedlink = embedlink.strip()

    # Determine filesizes
    coversize = len(coverfile)
    thumbsize = len(thumbfile)
    submitsize = len(submitfile)

    if not submitsize and not embedlink:
        raise WeasylError("submitSizeZero")
    elif embedlink and not embed.check_valid(embedlink):
        raise WeasylError("embedlinkInvalid")
    elif coversize > 10 * _MEGABYTE:
        raise WeasylError("coverSizeExceedsLimit")
    elif thumbsize > 10 * _MEGABYTE:
        raise WeasylError("thumbSizeExceedsLimit")

    if submitsize:
        submitextension = files.get_extension_for_category(
            submitfile, m.MULTIMEDIA_SUBMISSION_CATEGORY)
        if submitextension is None:
            raise WeasylError("submitType")
        elif submitextension not in [".mp3", ".swf"] and not embedlink:
            raise WeasylError("submitType")
        elif _limit(submitsize, submitextension):
            raise WeasylError("submitSizeExceedsLimit")
        submit_media_item = orm.MediaItem.fetch_or_create(
            submitfile, file_type=submitextension.lstrip('.'))
        check_for_duplicate_media(userid, submit_media_item.mediaid)
    else:
        submit_media_item = None

    thumb_media_item = media.make_cover_media_item(thumbfile)
    cover_media_item = media.make_cover_media_item(coverfile)
    if cover_media_item and not thumb_media_item:
        thumb_media_item = cover_media_item

    tempthumb_media_item = None
    im = None
    if auto_thumb:
        if thumbsize == 0 and coversize == 0:
            # Fetch default thumbnail from source if available
            thumb_url = embed.thumbnail(embedlink)
            if thumb_url:
                resp = d.http_get(thumb_url, timeout=5)
                im = image.from_string(resp.content)
    if not im and (thumbsize or coversize):
        im = image.from_string(thumbfile or coverfile)
    if im:
        tempthumb = images.make_thumbnail(im)
        tempthumb_type = images.image_file_type(tempthumb)
        tempthumb_media_item = orm.MediaItem.fetch_or_create(
            tempthumb.to_buffer(format=tempthumb_type),
            file_type=tempthumb_type,
            im=tempthumb)

    # Assign settings
    settings = []
    settings.append("f" if friends_only else "")
    settings.append("q" if critique else "")
    settings.append("v" if embedlink else "")
    settings = "".join(settings)

    # Inject embedlink
    if embedlink:
        submission.content = "".join([embedlink, "\n", submission.content])

    # Create submission
    db = d.connect()
    now = arrow.get()
    q = (d.meta.tables['submission'].insert().values([{
        "folderid":
        submission.folderid,
        "userid":
        userid,
        "unixtime":
        now,
        "title":
        submission.title,
        "content":
        submission.content,
        "subtype":
        submission.subtype,
        "rating":
        submission.rating,
        "settings":
        settings,
        "favorites":
        0,
        "submitter_ip_address":
        submission.submitter_ip_address,
        "submitter_user_agent_id":
        submission.submitter_user_agent_id,
    }]).returning(d.meta.tables['submission'].c.submitid))
    submitid = db.scalar(q)

    # Assign search tags
    searchtag.associate(userid, tags, submitid=submitid)

    if submit_media_item:
        orm.SubmissionMediaLink.make_or_replace_link(submitid, 'submission',
                                                     submit_media_item)
    if cover_media_item:
        orm.SubmissionMediaLink.make_or_replace_link(submitid, 'cover',
                                                     cover_media_item)
    if thumb_media_item:
        orm.SubmissionMediaLink.make_or_replace_link(submitid,
                                                     'thumbnail-source',
                                                     thumb_media_item)
    if tempthumb_media_item:
        orm.SubmissionMediaLink.make_or_replace_link(submitid,
                                                     'thumbnail-custom',
                                                     tempthumb_media_item)

    # Create notifications
    if create_notifications:
        _create_notifications(userid, submitid, submission.rating, settings)

    d.metric('increment', 'submissions')
    d.metric('increment', 'multimediasubmissions')

    return submitid, bool(thumb_media_item)
Exemple #33
0
def create_character_tag(tagid, targetid, settings=None):
    db = d.connect()
    db.add(
        content.CharacterTag(tagid=tagid, targetid=targetid,
                             settings=settings))
    db.flush()
Exemple #34
0
def create_visual(userid, submission,
                  friends_only, tags, imageURL, thumbfile,
                  submitfile, critique, create_notifications):
    premium = d.get_premium(userid)

    if imageURL:
        resp = d.http_get(imageURL, timeout=5)
        submitfile = resp.content

    # Determine filesizes
    thumbsize = len(thumbfile)
    submitsize = len(submitfile)

    if not submitsize:
        files.clear_temporary(userid)
        raise WeasylError("submitSizeZero")
    elif thumbsize > 10 * _MEGABYTE:
        files.clear_temporary(userid)
        raise WeasylError("thumbSizeExceedsLimit")

    im = image.from_string(submitfile)
    submitextension = image.image_extension(im)
    if _limit(submitsize, submitextension, premium):
        raise WeasylError("submitSizeExceedsLimit")
    elif submitextension not in [".jpg", ".png", ".gif"]:
        raise WeasylError("submitType")
    submit_file_type = submitextension.lstrip('.')
    submit_media_item = orm.fetch_or_create_media_item(
        submitfile, file_type=submit_file_type, im=im)
    check_for_duplicate_media(userid, submit_media_item.mediaid)
    cover_media_item = submit_media_item.ensure_cover_image(im)

    # Thumbnail stuff.
    # Always create a 'generated' thumbnail from the source image.
    thumb_generated = images.make_thumbnail(im)
    if thumb_generated is im:
        thumb_generated_media_item = submit_media_item
    else:
        thumb_generated_media_item = orm.fetch_or_create_media_item(
            thumb_generated.to_buffer(format=submit_file_type), file_type=submit_file_type,
            im=thumb_generated)
    # If requested, also create a 'custom' thumbnail.
    thumb_media_item = media.make_cover_media_item(thumbfile)
    if thumb_media_item:
        thumb_custom = images.make_thumbnail(image.from_string(thumbfile))
        thumb_custom_media_item = orm.fetch_or_create_media_item(
            thumb_custom.to_buffer(format=submit_file_type), file_type=submit_file_type,
            im=thumb_custom)

    # Assign settings
    settings = []
    settings.append("f" if friends_only else "")
    settings.append("q" if critique else "")
    settings = "".join(settings)

    # TODO(kailys): maintain ORM object
    db = d.connect()
    now = arrow.get()
    q = (
        d.meta.tables['submission'].insert().values([{
            "folderid": submission.folderid,
            "userid": userid,
            "unixtime": now,
            "title": submission.title,
            "content": submission.content,
            "subtype": submission.subtype,
            "rating": submission.rating.code,
            "settings": settings,
            "sorttime": now,
        }]).returning(d.meta.tables['submission'].c.submitid))
    submitid = db.scalar(q)

    orm.SubmissionMediaLink.make_or_replace_link(
        submitid, 'submission', submit_media_item)
    orm.SubmissionMediaLink.make_or_replace_link(
        submitid, 'cover', cover_media_item)
    orm.SubmissionMediaLink.make_or_replace_link(
        submitid, 'thumbnail-generated', thumb_generated_media_item)
    if thumb_media_item:
        orm.SubmissionMediaLink.make_or_replace_link(submitid, 'thumbnail-source', thumb_media_item)
        orm.SubmissionMediaLink.make_or_replace_link(
            submitid, 'thumbnail-custom', thumb_custom_media_item)

    # Assign search tags
    searchtag.associate(userid, tags, submitid=submitid)

    # Create notifications
    if create_notifications:
        _create_notifications(userid, submitid, submission.rating, settings,
                              submission.title, tags)

    d.metric('increment', 'submissions')
    d.metric('increment', 'visualsubmissions')

    return submitid
Exemple #35
0
def finduser(targetid, username, email, dateafter, datebefore, excludesuspended, excludebanned, excludeactive, ipaddr,
             row_offset):
    targetid = d.get_int(targetid)

    # If we don't have any of these variables, nothing will be displayed. So fast-return an empty list.
    if not targetid and not username and not email and not dateafter \
            and not datebefore and not excludesuspended and not excludebanned \
            and not excludeactive and not ipaddr:
        return []

    lo = d.meta.tables['login']
    sh = d.meta.tables['comments']
    pr = d.meta.tables['profile']
    sess = d.meta.tables['sessions']
    permaban = d.meta.tables['permaban']
    suspension = d.meta.tables['suspension']

    is_banned = d.sa.exists(
        d.sa.select([])
        .select_from(permaban)
        .where(permaban.c.userid == lo.c.userid)
    ).label('is_banned')

    is_suspended = d.sa.exists(
        d.sa.select([])
        .select_from(suspension)
        .where(suspension.c.userid == lo.c.userid)
    ).label('is_suspended')

    q = d.sa.select([
        lo.c.userid,
        lo.c.login_name,
        lo.c.email,
        (d.sa.select([d.sa.func.count()])
         .select_from(sh)
         .where(sh.c.target_user == lo.c.userid)
         .where(sh.c.settings.op('~')('s'))).label('staff_notes'),
        is_banned,
        is_suspended,
        lo.c.ip_address_at_signup,
        (d.sa.select([sess.c.ip_address])
            .select_from(sess)
            .where(lo.c.userid == sess.c.userid)
            .limit(1)
            .order_by(sess.c.created_at.desc())
            .correlate(sess)
         ).label('ip_address_session'),
    ]).select_from(
        lo.join(pr, lo.c.userid == pr.c.userid)
          .join(sess, sess.c.userid == pr.c.userid, isouter=True)
    )

    # Is there a better way to only select unique accounts, when _also_ joining sessions? This _does_ work, though.
    q = q.distinct(lo.c.login_name)

    if targetid:
        q = q.where(lo.c.userid == targetid)
    elif username:
        q = q.where(lo.c.login_name.op('~')(username))
    elif email:
        q = q.where(d.sa.or_(
            lo.c.email.op('~')(email),
            lo.c.email.op('ilike')('%%%s%%' % email),
        ))

    # Filter for banned and/or suspended accounts
    if excludeactive == "on":
        q = q.where(is_banned | is_suspended)
    if excludebanned == "on":
        q = q.where(~is_banned)
    if excludesuspended == "on":
        q = q.where(~is_suspended)

    # Filter for IP address
    if ipaddr:
        q = q.where(d.sa.or_(
            lo.c.ip_address_at_signup.op('ilike')('%s%%' % ipaddr),
            sess.c.ip_address.op('ilike')('%s%%' % ipaddr)
        ))

    # Filter for date-time
    if dateafter and datebefore:
        q = q.where(d.sa.between(pr.c.created_at, arrow.get(dateafter).datetime, arrow.get(datebefore).datetime))
    elif dateafter:
        q = q.where(pr.c.created_at >= arrow.get(dateafter).datetime)
    elif datebefore:
        q = q.where(pr.c.created_at <= arrow.get(datebefore).datetime)

    # Apply any row offset
    if row_offset:
        q = q.offset(row_offset)

    q = q.limit(250).order_by(lo.c.login_name.asc())
    db = d.connect()
    return db.execute(q)
Exemple #36
0
 def _notification_count(self, userid):
     return (d.connect().query(site.SavedNotification).filter(
         site.SavedNotification.userid == userid).count())
Exemple #37
0
def associate(userid, tags, submitid=None, charid=None, journalid=None, preferred_tags_userid=None, optout_tags_userid=None):
    """
    Associates searchtags with a content item.

    Parameters:
        userid: The userid of the user associating tags
        tags: A set of tags
        submitid: The ID number of a submission content item to associate
        ``tags`` to. (default: None)
        charid: The ID number of a character content item to associate
        ``tags`` to. (default: None)
        journalid: The ID number of a journal content item to associate
        ``tags`` to. (default: None)
        preferred_tags_userid: The ID number of a user to associate
        ``tags`` to for Preferred tags. (default: None)
        optout_tags_userid: The ID number of a user to associate
        ``tags`` to for Opt-Out tags. (default: None)

    Returns:
        A dict containing two elements. 1) ``add_failure_restricted_tags``, which contains a space separated
        string of tag titles which failed to be added to the content item due to the user or global restricted
        tag lists; and 2) ``remove_failure_owner_set_tags``, which contains a space separated string of tag
        titles which failed to be removed from the content item due to the owner of the aforementioned item
        prohibiting users from removing tags set by the content owner.

        If an element does not have tags, the element is set to None. If neither elements are set,
        the function returns None.
    """
    targetid = d.get_targetid(submitid, charid, journalid)

    # Assign table, feature, ownerid
    if submitid:
        table, feature = "searchmapsubmit", "submit"
        ownerid = d.get_ownerid(submitid=targetid)
    elif charid:
        table, feature = "searchmapchar", "char"
        ownerid = d.get_ownerid(charid=targetid)
    elif journalid:
        table, feature = "searchmapjournal", "journal"
        ownerid = d.get_ownerid(journalid=targetid)
    elif preferred_tags_userid:
        table, feature = "artist_preferred_tags", "user"
        targetid = ownerid = preferred_tags_userid
    elif optout_tags_userid:
        table, feature = "artist_optout_tags", "user"
        targetid = ownerid = optout_tags_userid
    else:
        raise WeasylError("Unexpected")

    # Check permissions and invalid target
    if not ownerid:
        raise WeasylError("TargetRecordMissing")
    elif userid != ownerid and ("g" in d.get_config(userid) or preferred_tags_userid or optout_tags_userid):
        # disallow if user is forbidden from tagging, or trying to set artist tags on someone other than themselves
        raise WeasylError("InsufficientPermissions")
    elif ignoreuser.check(ownerid, userid):
        raise WeasylError("contentOwnerIgnoredYou")

    # Determine previous tagids, titles, and settings
    existing = d.engine.execute(
        "SELECT tagid, title, settings FROM {} INNER JOIN searchtag USING (tagid) WHERE targetid = %(target)s".format(table),
        target=targetid).fetchall()

    # Retrieve tag titles and tagid pairs, for new (if any) and existing tags
    query = add_and_get_searchtags(tags)

    existing_tagids = {t.tagid for t in existing}
    entered_tagids = {t.tagid for t in query}

    # Assign added and removed
    added = entered_tagids - existing_tagids
    removed = existing_tagids - entered_tagids

    # enforce the limit on artist preference tags
    if preferred_tags_userid and (len(added) - len(removed) + len(existing)) > MAX_PREFERRED_TAGS:
        raise WeasylError("tooManyPreferenceTags")

    # Track which tags fail to be added or removed to later notify the user (Note: These are tagids at this stage)
    add_failure_restricted_tags = None
    remove_failure_owner_set_tags = None

    # If the modifying user is not the owner of the object, and is not staff, check user/global restriction lists
    if userid != ownerid and userid not in staff.MODS:
        user_rtags = set(query_user_restricted_tags(ownerid))
        global_rtags = set(query_global_restricted_tags())
        add_failure_restricted_tags = remove_restricted_tags(user_rtags | global_rtags, query)
        added -= add_failure_restricted_tags
        if len(add_failure_restricted_tags) == 0:
            add_failure_restricted_tags = None

    # Check removed artist tags
    if not can_remove_tags(userid, ownerid):
        existing_artist_tags = {t.tagid for t in existing if 'a' in t.settings}
        remove_failure_owner_set_tags = removed & existing_artist_tags
        removed.difference_update(existing_artist_tags)
        entered_tagids.update(existing_artist_tags)
        # Submission items use a different method of tag protection for artist tags; ignore them
        if submitid or len(remove_failure_owner_set_tags) == 0:
            remove_failure_owner_set_tags = None

    # Remove tags
    if removed:
        d.engine.execute(
            "DELETE FROM {} WHERE targetid = %(target)s AND tagid = ANY (%(removed)s)".format(table),
            target=targetid, removed=list(removed))

    if added:
        d.engine.execute(
            "INSERT INTO {} SELECT tag, %(target)s FROM UNNEST (%(added)s) AS tag".format(table),
            target=targetid, added=list(added))

        # preference/optout tags can only be set by the artist, so this settings column does not apply
        if userid == ownerid and not (preferred_tags_userid or optout_tags_userid):
            d.engine.execute(
                "UPDATE {} SET settings = settings || 'a' WHERE targetid = %(target)s AND tagid = ANY (%(added)s)".format(table),
                target=targetid, added=list(added))

    if submitid:
        d.engine.execute(
            'INSERT INTO submission_tags (submitid, tags) VALUES (%(submission)s, %(tags)s) '
            'ON CONFLICT (submitid) DO UPDATE SET tags = %(tags)s',
            submission=submitid, tags=list(entered_tagids))

        db = d.connect()
        db.execute(
            d.meta.tables['tag_updates'].insert()
            .values(submitid=submitid, userid=userid,
                    added=tag_array(added), removed=tag_array(removed)))
        if userid != ownerid:
            welcome.tag_update_insert(ownerid, submitid)

    files.append(
        "%stag.%s.%s.log" % (m.MACRO_SYS_LOG_PATH, feature, d.get_timestamp()),
        "-%sID %i  -T %i  -UID %i  -X %s\n" % (feature[0].upper(), targetid, d.get_time(), userid,
                                               " ".join(tags)))

    # Return dict with any tag titles as a string that failed to be added or removed
    if add_failure_restricted_tags or remove_failure_owner_set_tags:
        if add_failure_restricted_tags:
            add_failure_restricted_tags = " ".join({tag.title for tag in query if tag.tagid in add_failure_restricted_tags})
        if remove_failure_owner_set_tags:
            remove_failure_owner_set_tags = " ".join({tag.title for tag in existing if tag.tagid in remove_failure_owner_set_tags})
        return {"add_failure_restricted_tags": add_failure_restricted_tags,
                "remove_failure_owner_set_tags": remove_failure_owner_set_tags}
    else:
        return None
Exemple #38
0
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))
Exemple #39
0
def finduser(userid, form):
    form.userid = d.get_int(form.userid)

    # If we don't have any of these variables, nothing will be displayed. So fast-return an empty list.
    if not form.userid and not form.username and not form.email and not form.dateafter \
            and not form.datebefore and not form.excludesuspended and not form.excludebanned \
            and not form.excludeactive and not form.ipaddr:
        return []

    lo = d.meta.tables['login']
    sh = d.meta.tables['comments']
    pr = d.meta.tables['profile']
    sess = d.meta.tables['sessions']

    q = d.sa.select([
        lo.c.userid,
        lo.c.login_name,
        lo.c.email,
        (d.sa.select([d.sa.func.count()])
         .select_from(sh)
         .where(sh.c.target_user == lo.c.userid)
         .where(sh.c.settings.op('~')('s'))).label('staff_notes'),
        lo.c.settings,
        lo.c.ip_address_at_signup,
        (d.sa.select([sess.c.ip_address])
            .select_from(sess)
            .where(lo.c.userid == sess.c.userid)
            .limit(1)
            .order_by(sess.c.created_at.desc())
            .correlate(sess)
         ).label('ip_address_session'),
    ]).select_from(
        lo.join(pr, lo.c.userid == pr.c.userid)
          .join(sess, sess.c.userid == pr.c.userid, isouter=True)
    )

    # Is there a better way to only select unique accounts, when _also_ joining sessions? This _does_ work, though.
    q = q.distinct(lo.c.login_name)

    if form.userid:
        q = q.where(lo.c.userid == form.userid)
    elif form.username:
        q = q.where(lo.c.login_name.op('~')(form.username))
    elif form.email:
        q = q.where(d.sa.or_(
            lo.c.email.op('~')(form.email),
            lo.c.email.op('ilike')('%%%s%%' % form.email),
        ))

    # Filter for banned and/or suspended accounts
    if form.excludeactive == "on":
        q = q.where(lo.c.settings.op('~')('[bs]'))
    if form.excludebanned == "on":
        q = q.where(lo.c.settings.op('!~')('b'))
    if form.excludesuspended == "on":
        q = q.where(lo.c.settings.op('!~')('s'))

    # Filter for IP address
    if form.ipaddr:
        q = q.where(d.sa.or_(
            lo.c.ip_address_at_signup.op('ilike')('%s%%' % form.ipaddr),
            sess.c.ip_address.op('ilike')('%s%%' % form.ipaddr)
        ))

    # Filter for date-time
    if form.dateafter and form.datebefore:
        q = q.where(d.sa.between(pr.c.unixtime, arrow.get(form.dateafter), arrow.get(form.datebefore)))
    elif form.dateafter:
        q = q.where(pr.c.unixtime >= arrow.get(form.dateafter))
    elif form.datebefore:
        q = q.where(pr.c.unixtime <= arrow.get(form.datebefore))

    # Apply any row offset
    if form.row_offset:
        q = q.offset(form.row_offset)

    q = q.limit(250).order_by(lo.c.login_name.asc())
    db = d.connect()
    return db.execute(q)
Exemple #40
0
def update_last_submission_time(userid, unixtime):
    profile = d.meta.tables['profile']
    db = d.connect()
    db.execute(profile.update().where(profile.c.userid == userid).values(
        latest_submission_time=unixtime))
    db.flush()
Exemple #41
0
def create_friendship(user1, user2, settings=None):
    db = d.connect()
    db.add(users.Friendship(userid=user1, otherid=user2, settings=settings))
    db.flush()
Exemple #42
0
def add_entity(entity):
    db = d.connect()
    db.add(entity)
    db.flush()
    return entity
Exemple #43
0
def create_blocktag(userid, tagid, rating):
    db = d.connect()
    db.add(content.Blocktag(userid=userid, tagid=tagid, rating=rating))
    db.flush()
Exemple #44
0
def insert(userid,
           submitid=None,
           charid=None,
           journalid=None,
           updateid=None,
           parentid=None,
           content=None):
    if not submitid and not charid and not journalid and not updateid:
        raise WeasylError("Unexpected")
    elif not content:
        raise WeasylError("commentInvalid")

    # Determine indent and parentuserid
    if parentid:
        if updateid:
            parentuserid = d.engine.scalar(
                "SELECT userid FROM siteupdatecomment WHERE commentid = %(parent)s",
                parent=parentid)

            if parentuserid is None:
                raise WeasylError("Unexpected")
        else:
            parent = d.engine.execute(
                "SELECT userid, indent FROM {table} WHERE commentid = %(parentid)s"
                .format(table="comments" if submitid else
                        "charcomment" if charid else "journalcomment", ),
                parentid=parentid,
            ).first()

            if not parent:
                raise WeasylError("Unexpected")

            indent = parent.indent + 1
            parentuserid = parent.userid
    elif updateid:
        parentid = None  # parentid == 0
        parentuserid = None
    else:
        indent = 0
        parentuserid = None

    if updateid:
        otherid = d.engine.scalar(
            "SELECT userid FROM siteupdate WHERE updateid = %(update)s",
            update=updateid)

        if not otherid:
            raise WeasylError("submissionRecordMissing")
    else:
        # Determine the owner of the target
        otherid = d.engine.scalar(
            "SELECT userid FROM %s WHERE %s = %i AND settings !~ 'h'" %
            (("submission", "submitid", submitid) if submitid else
             ("character", "charid", charid) if charid else
             ("journal", "journalid", journalid)))

        # Check permissions
        if not otherid:
            raise WeasylError("submissionRecordMissing")
        elif ignoreuser.check(otherid, userid):
            raise WeasylError("pageOwnerIgnoredYou")
        elif ignoreuser.check(userid, otherid):
            raise WeasylError("youIgnoredPageOwner")

    if parentuserid and ignoreuser.check(parentuserid, userid):
        raise WeasylError("replyRecipientIgnoredYou")
    elif parentuserid and ignoreuser.check(userid, parentuserid):
        raise WeasylError("youIgnoredReplyRecipient")

    # Create comment
    if submitid:
        co = d.meta.tables['comments']
        db = d.connect()
        commentid = db.scalar(co.insert().values(userid=userid,
                                                 target_sub=submitid,
                                                 parentid=parentid or None,
                                                 content=content,
                                                 unixtime=arrow.utcnow(),
                                                 indent=indent).returning(
                                                     co.c.commentid))
    elif updateid:
        commentid = d.engine.scalar(
            "INSERT INTO siteupdatecomment (userid, targetid, parentid, content)"
            " VALUES (%(user)s, %(update)s, %(parent)s, %(content)s)"
            " RETURNING commentid",
            user=userid,
            update=updateid,
            parent=parentid,
            content=content,
        )
    else:
        commentid = d.engine.scalar(
            "INSERT INTO {table} (userid, targetid, parentid, content, unixtime, indent)"
            " VALUES (%(user)s, %(target)s, %(parent)s, %(content)s, %(now)s, %(indent)s)"
            " RETURNING commentid".format(
                table="charcomment" if charid else "journalcomment"),
            user=userid,
            target=d.get_targetid(charid, journalid),
            parent=parentid or 0,
            content=content,
            now=d.get_time(),
            indent=indent,
        )

    # Create notification
    if parentid and (userid != parentuserid):
        welcome.commentreply_insert(userid, commentid, parentuserid, parentid,
                                    submitid, charid, journalid, updateid)
    elif not parentid:
        # build a list of people this comment should notify
        # circular imports are cool and fun
        from weasyl.collection import find_owners
        notified = set(find_owners(submitid))

        # check to see who we should deliver comment notifications to
        def can_notify(other):
            other_jsonb = d.get_profile_settings(other)
            allow_notify = other_jsonb.allow_collection_notifs
            ignored = ignoreuser.check(other, userid)
            return allow_notify and not ignored

        notified = set(filter(can_notify, notified))
        # always give notification on own content
        notified.add(otherid)
        # don't give me a notification for my own comment
        notified.discard(userid)

        for other in notified:
            welcome.comment_insert(userid, commentid, other, submitid, charid,
                                   journalid, updateid)

    d.metric('increment', 'comments')

    return commentid
Exemple #45
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)
                             and not staffnotes):
        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
Exemple #46
0
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
        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(
            os.path.join(MediaItem._base_file_path,
                         submitfile['file_url'][1:]))
    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])

    sub_media = media.get_submission_media(submitid)

    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),
    }
Exemple #47
0
def select_info(folderid):
    db = d.connect()
    f = d.meta.tables['folder']
    q = sa.select([f.c.title, f.c.settings]).where(f.c.folderid == folderid)
    results = db.execute(q).fetchall()
    return results[0]
Exemple #48
0
def edit(userid,
         submission,
         embedlink=None,
         friends_only=False,
         critique=False):
    query = d.engine.execute(
        "SELECT userid, subtype, settings FROM submission WHERE submitid = %(id)s",
        id=submission.submitid).first()

    if not query or "h" in query[2]:
        raise WeasylError("Unexpected")
    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, )))
Exemple #49
0
def is_hidden(submitid):
    db = d.connect()
    su = d.meta.tables['submission']
    q = d.sa.select([su.c.settings.op('~')('h')]).where(su.c.submitid == submitid)
    results = db.execute(q).fetchall()
    return bool(results and results[0][0])
Exemple #50
0
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,
    }
Exemple #51
0
def create_follow(user1, user2, settings='scftj'):
    db = d.connect()
    db.add(users.Follow(userid=user1, otherid=user2, settings=settings))
    db.flush()
Exemple #52
0
def setupdb(request):
    db = define.connect()
    db.execute('DROP SCHEMA public CASCADE')
    db.execute('CREATE SCHEMA public')
    db.execute('CREATE EXTENSION HSTORE')
    define.meta.create_all(define.engine)
Exemple #53
0
def create_visual(userid, submission, friends_only, tags, imageURL, thumbfile,
                  submitfile, critique, create_notifications):
    if imageURL:
        resp = _http_get_if_crosspostable(imageURL)
        submitfile = resp.content

    # Determine filesizes
    thumbsize = len(thumbfile)
    submitsize = len(submitfile)

    if not submitsize:
        raise WeasylError("submitSizeZero")
    elif thumbsize > 10 * _MEGABYTE:
        raise WeasylError("thumbSizeExceedsLimit")

    im = image.from_string(submitfile)
    submitextension = images.image_extension(im)
    if submitextension not in [".jpg", ".png", ".gif"]:
        raise WeasylError("submitType")
    if _limit(submitsize, submitextension):
        raise WeasylError("submitSizeExceedsLimit")

    submit_file_type = submitextension.lstrip('.')
    submit_media_item = orm.MediaItem.fetch_or_create(
        submitfile, file_type=submit_file_type, im=im)
    check_for_duplicate_media(userid, submit_media_item.mediaid)
    cover_media_item = submit_media_item.ensure_cover_image(im)

    # Thumbnail stuff.
    # Always create a 'generated' thumbnail from the source image.
    with BytesIO(submitfile) as buf:
        thumbnail_formats = images_new.get_thumbnail(buf)

    thumb_generated, thumb_generated_file_type, thumb_generated_attributes = thumbnail_formats.compatible
    thumb_generated_media_item = orm.MediaItem.fetch_or_create(
        thumb_generated,
        file_type=thumb_generated_file_type,
        attributes=thumb_generated_attributes,
    )

    if thumbnail_formats.webp is None:
        thumb_generated_media_item_webp = None
    else:
        thumb_generated, thumb_generated_file_type, thumb_generated_attributes = thumbnail_formats.webp
        thumb_generated_media_item_webp = orm.MediaItem.fetch_or_create(
            thumb_generated,
            file_type=thumb_generated_file_type,
            attributes=thumb_generated_attributes,
        )

    # If requested, also create a 'custom' thumbnail.
    thumb_media_item = media.make_cover_media_item(thumbfile)
    if thumb_media_item:
        thumb_custom = images.make_thumbnail(image.from_string(thumbfile))
        thumb_custom_media_item = orm.MediaItem.fetch_or_create(
            thumb_custom.to_buffer(format=submit_file_type),
            file_type=submit_file_type,
            im=thumb_custom)

    # Assign settings
    settings = []
    settings.append("f" if friends_only else "")
    settings.append("q" if critique else "")
    settings = "".join(settings)

    # TODO(kailys): maintain ORM object
    db = d.connect()
    now = arrow.get()
    q = (d.meta.tables['submission'].insert().values([{
        "folderid":
        submission.folderid,
        "userid":
        userid,
        "unixtime":
        now,
        "title":
        submission.title,
        "content":
        submission.content,
        "subtype":
        submission.subtype,
        "rating":
        submission.rating.code,
        "settings":
        settings,
        "favorites":
        0,
        "submitter_ip_address":
        submission.submitter_ip_address,
        "submitter_user_agent_id":
        submission.submitter_user_agent_id,
    }]).returning(d.meta.tables['submission'].c.submitid))
    submitid = db.scalar(q)

    orm.SubmissionMediaLink.make_or_replace_link(submitid, 'submission',
                                                 submit_media_item)
    orm.SubmissionMediaLink.make_or_replace_link(submitid, 'cover',
                                                 cover_media_item)

    orm.SubmissionMediaLink.make_or_replace_link(submitid,
                                                 'thumbnail-generated',
                                                 thumb_generated_media_item)

    if thumb_generated_media_item_webp is not None:
        orm.SubmissionMediaLink.make_or_replace_link(
            submitid, 'thumbnail-generated-webp',
            thumb_generated_media_item_webp)

    if thumb_media_item:
        orm.SubmissionMediaLink.make_or_replace_link(submitid,
                                                     'thumbnail-source',
                                                     thumb_media_item)
        orm.SubmissionMediaLink.make_or_replace_link(submitid,
                                                     'thumbnail-custom',
                                                     thumb_custom_media_item)

    # Assign search tags
    searchtag.associate(userid, tags, submitid=submitid)

    # Create notifications
    if create_notifications:
        _create_notifications(userid, submitid, submission.rating, settings)

    d.metric('increment', 'submissions')
    d.metric('increment', 'visualsubmissions')

    return submitid
Exemple #54
0
def create_ignoreuser(ignorer, ignoree):
    db = d.connect()
    db.add(users.Ignorama(userid=ignorer, otherid=ignoree))
    db.flush()
Exemple #55
0
def create_literary(userid,
                    submission,
                    embedlink=None,
                    friends_only=False,
                    tags=None,
                    coverfile=None,
                    thumbfile=None,
                    submitfile=None,
                    critique=False,
                    create_notifications=True):
    if embedlink:
        check_google_doc_embed_data(embedlink)

    # Determine filesizes
    coversize = len(coverfile)
    thumbsize = len(thumbfile)
    submitsize = len(submitfile)

    if not submitsize and not embedlink:
        raise WeasylError("submitSizeZero")
    elif coversize > 10 * _MEGABYTE:
        raise WeasylError("coverSizeExceedsLimit")
    elif thumbsize > 10 * _MEGABYTE:
        raise WeasylError("thumbSizeExceedsLimit")

    if submitsize:
        submitextension = files.get_extension_for_category(
            submitfile, m.TEXT_SUBMISSION_CATEGORY)
        if submitextension is None:
            raise WeasylError("submitType")
        if _limit(submitsize, submitextension):
            raise WeasylError("submitSizeExceedsLimit")
        submit_media_item = orm.MediaItem.fetch_or_create(
            submitfile, file_type=submitextension.lstrip('.'))
        check_for_duplicate_media(userid, submit_media_item.mediaid)
    else:
        submit_media_item = None

    thumb_media_item = media.make_cover_media_item(thumbfile)
    cover_media_item = media.make_cover_media_item(coverfile)
    if cover_media_item and not thumb_media_item:
        thumb_media_item = cover_media_item

    # Assign settings
    settings = []
    settings.append("f" if friends_only else "")
    settings.append("q" if critique else "")
    if embedlink:
        settings.append('D')
    settings = "".join(settings)

    # Create submission
    # TODO(kailys): use ORM object
    db = d.connect()
    now = arrow.get()
    q = (d.meta.tables['submission'].insert().values([{
        "folderid":
        submission.folderid,
        "userid":
        userid,
        "unixtime":
        now,
        "title":
        submission.title,
        "content":
        submission.content,
        "subtype":
        submission.subtype,
        "rating":
        submission.rating.code,
        "settings":
        settings,
        "favorites":
        0,
        "submitter_ip_address":
        submission.submitter_ip_address,
        "submitter_user_agent_id":
        submission.submitter_user_agent_id,
    }]).returning(d.meta.tables['submission'].c.submitid))
    submitid = db.scalar(q)
    if embedlink:
        q = (d.meta.tables['google_doc_embeds'].insert().values(
            submitid=submitid, embed_url=embedlink))
        db.execute(q)

    # Assign search tags
    searchtag.associate(userid, tags, submitid=submitid)

    if submit_media_item:
        orm.SubmissionMediaLink.make_or_replace_link(submitid, 'submission',
                                                     submit_media_item)
    if cover_media_item:
        orm.SubmissionMediaLink.make_or_replace_link(submitid, 'cover',
                                                     cover_media_item)
    if thumb_media_item:
        orm.SubmissionMediaLink.make_or_replace_link(submitid,
                                                     'thumbnail-source',
                                                     thumb_media_item)

    # Create notifications
    if create_notifications:
        _create_notifications(userid, submitid, submission.rating, settings)

    d.metric('increment', 'submissions')
    d.metric('increment', 'literarysubmissions')

    return submitid, bool(thumb_media_item)
Exemple #56
0
def create_journal_tag(tagid, targetid, settings=None):
    db = d.connect()
    db.add(
        content.JournalTag(tagid=tagid, targetid=targetid, settings=settings))
    db.flush()
Exemple #57
0
def main():
    db = connect()
    print 'starting media_items'
    port_media_items(db)