예제 #1
0
def subscribe(u=None,uid=0):
	db = open_db()
	
	# User does not exist
	if db.query(User).filter_by(id=uid).first() is None:
		return '',404
	# Already following
	if u.is_following(uid) == True:
		return '',400
	
	# Cant follow self
	if u.id == uid:
		return '',400
	
	sub = UserFollow(user_id=u.id,target_id=uid)
	db.add(sub)
	
	user = db.query(User).filter_by(id=uid).first()
	db.query(User).filter_by(id=uid).update({
		'follow_count':user.follow_count+1})
	
	db.commit()
	
	db.close()
	return '',200
예제 #2
0
def mark_all_as_read(u=None):
	db = open_db()
	db.query(Notification).filter_by(user_id=u.id).update({'is_read':True})
	db.commit()
	db.close()
	cache.delete_memoized(notifications)
	return redirect('/user/notifications')
예제 #3
0
def change_feed_settings(u=None,uid=0):
	db = open_db()
	
	user = db.query(User).filter_by(id=u.id).first()
	if user is None:
		abort(404)
	
	if request.method == 'POST':
		show = strtobool(str(request.values.get('show-feed')))
		receive = strtobool(str(request.values.get('receive')))
		
		sub = db.query(UserFollow).filter_by(user_id=u.id,target_id=uid).first()
		if sub is None:
			abort(404)
		
		db.query(UserFollow).filter_by(user_id=u.id,target_id=uid).update({
			'show_in_feed':show,
			'notify':receive})
		db.commit()
		db.close()
		
		return redirect(f'/user/view?uid={uid}')
	else:
		db.close()
		return render_template('user/follow_settings.html',u=u,title='Edit feed and notification settings',user=user)
예제 #4
0
def messages_of(data=None, u=None):
    if data is None:
        return '', 400

    db = open_db()

    # Messages in channel
    messages = db.query(Message).filter_by(
        channel_id=data['channel_id']).options(joinedload('*')).order_by(
            asc(Message.id)).all()
    messages = messages[-50:]

    all_data = []

    for m in messages:
        data = {
            'time_utc': m.creation_date,
            'username': u.username,
            'uid': u.id,
            'body': m.body_html,
            'msg_id': m.id,
            'channel_id': m.channel_id
        }
        all_data.append(data)

    # Send message list
    emit('messages_of', all_data)

    db.close()
예제 #5
0
def csam_check_profile(uid: int):
	db = open_db()

	# Let's see if this is csam
	user = db.query(User).filter_by(id=uid).first()

	headers = {'User-Agent':'xaiecon-csam-check'}

	for i in range(10):
		x = requests.get(f'https://{os.environ.get("DOMAIN_NAME")}/user/thumb/{uid}',headers=headers)
		if x.status_code in [200, 451]:
			break
		else:
			time.sleep(10)
	
	if x.status_code != 451:
		return

	# Ban user
	db.query(User).filter_by(id=id).update({
		'ban_reason':gettext('CSAM Automatic Removal'),
		'is_banned':True})
	db.commit()
	db.refresh(user)
	
	os.remove(os.path.join('user_data',user.image_file))
	
	db.close()
	return
예제 #6
0
def ban(u=None, bid=0, uid=0):
    if request.method == 'POST':
        db = open_db()

        reason = request.values.get('reason', 'No reason specified')

        if u.mods(bid) == False:
            return '', 401

        # Board does not exist
        if db.query(Board).filter_by(id=bid).first() is None:
            return '', 404
        # Already banned
        if db.query(BoardBan).filter_by(user_id=uid,
                                        board_id=bid).first() is not None:
            return '', 400
        # Do not ban self
        if uid == u.id:
            return '', 400

        sub = BoardBan(user_id=uid, board_id=bid, reason=reason)
        db.add(sub)
        db.commit()

        db.close()
        return redirect(f'/board/view/{bid}')
    else:
        return render_template('board/ban.html',
                               u=u,
                               title='Ban user',
                               bid=bid,
                               uid=uid)
예제 #7
0
    def moderated_boards(self):
        from xaiecon.classes.board import Board

        db = open_db()
        ret = db.query(Board).filter_by(user_id=self.id).all()
        db.close()
        return ret
예제 #8
0
def unnuke(u=None,pid=0):
	db = open_db()
	try:
		if u.is_admin == False:
			raise XaieconException('Only admins can un-nuke')
		
		post = db.query(Post).filter_by(id=pid).first()
		if post is None:
			abort(404)
		
		# Check that post is not already nuked and that user mods
		# the guild
		if post.is_deleted == True or post.is_nuked == False:
			raise XaieconException('Post already deleted or has been unnuked by user or someone else')
		
		# "Un-Nuke" post
		db.query(Post).filter_by(id=pid).update({'is_nuked':False})
		db.commit()
		
		db.close()
		
		cache.delete_memoized(view,pid=pid)
		cache.delete_memoized(list_posts)
		cache.delete_memoized(list_nuked)
		cache.delete_memoized(list_feed)
		
		return redirect(f'/post/view/{pid}')
	except XaieconException as e:
		db.rollback()
		db.close()
		return render_template('user_error.html',u=u,title = 'Whoops!',err=e)
예제 #9
0
def edit(u=None,cid=0):
	try:
		db = open_db()
		
		# Query comment from id
		comment = db.query(Comment).filter_by(id=cid).first()
		if comment is None:
			abort(404)
		if comment.user_id != u.id and u.is_admin == False:
			abort(403)
		
		if request.method == 'POST':
			body = request.form.get('body')
			
			if len(body) == 0:
				raise XaieconException(gettext('Body too short'))
			
			# Update comment
			db.query(Comment).filter_by(id=cid).update({
				'body':body,
				'body_html':md(body)})
			db.commit()
			
			db.close()
			cache.delete_memoized(view)
			return redirect(f'/comment/view/{cid}')
		else:
			db.close()
			return render_template('post/edit_comment.html',u=u,title='Edit comment',comment=comment)
	except XaieconException as e:
		return render_template('user_error.html',u=u,title = 'Whoops!',err=e)
예제 #10
0
def admin_nuke(u=None,cid=0):
	db = open_db()
	
	comment = db.query(Comment).filter_by(id=cid).first()
	if comment is None:
		abort(404)
	
	# Delete all stuff of the comment
	db.query(Comment).filter_by(id=cid).update({
		'body':gettext('[deleted by nuking]'),
		'body_html':gettext('[deleted by nuking]')})
	db.commit()
	
	# Kill user
	user = db.query(User).filter_by(id=comment.user_id).first()
	db.query(User).filter_by(id=comment.user_id).update({
		'ban_reason':'ToS break. Nuking.',
		'is_banned':True})
	db.commit()
	db.refresh(user)
	
	db.close()
	
	# Delete caching
	cache.delete_memoized(view,cid=cid)
	cache.delete_memoized(list_posts)
	cache.delete_memoized(list_nuked)
	cache.delete_memoized(list_feed)
	return '',200
예제 #11
0
def new(u=None):
	try:
		if request.method == 'POST':
			name = request.values.get('name')
			redirect_uri = request.values.get('redirect_uri')
			
			if name is None:
				name = 'Untitled oauth app'
			if redirect_uri == '':
				raise XaieconException('Please provide a redirect url')
			
			db = open_db()
			
			# Create app, with tokens and client id and stuff
			app = OAuthApp(
				client_id=secrets.token_urlsafe(128)[0:128],
				client_secret=secrets.token_urlsafe(128)[0:128],
				redirect_uri=redirect_uri,
				name=name,
				user_id=u.id)
			
			db.add(app)
			db.commit()
			
			db.close()
			return redirect('/oauth/view')
		else:
			return render_template('oauth/new.html',u=u,title='New OAuth App')
	except XaieconException as e:
		return render_template('user_error.html',u=u,title='Whoops!',err=e)
예제 #12
0
def netpoint_leaderboard(u=None,username=None):
	db = open_db()
	user = db.query(User).order_by(desc(User.net_points)).limit(50).all()
	if user is None:
		abort(404)
	db.close()
	
	return render_template('user/leaderboard.html',u=u,title='Network Points Leaderboard',users=user)
예제 #13
0
def notifications(u=None):
	db = open_db()
	
	# Mark all notifications as read
	notifications = db.query(Notification).filter_by(user_id=u.id,is_read=False).order_by(desc(Notification.id)).all()
	
	db.close()
	return render_template('user/notification.html',u=u,title='Your notifications',notifications=notifications)
예제 #14
0
def send_notification(msg: str, target_id: int):
    db = open_db()

    notification = Notification(body=msg, body_html=md(msg), user_id=target_id)
    db.add(notification)
    db.commit()

    db.close()
예제 #15
0
    def unread_notifications_number(self) -> int:
        from xaiecon.classes.notification import Notification

        db = open_db()
        count = db.query(Notification).filter_by(user_id=self.id,
                                                 is_read=False).count()
        db.close()
        return count
예제 #16
0
    def unread_notifications(self):
        from xaiecon.classes.notification import Notification

        db = open_db()
        ret = db.query(Notification).filter_by(user_id=self.id,
                                               is_read=False).all()
        db.close()
        return ret
예제 #17
0
def view_by_id(u=None,uid=0):
	db = open_db()
	user = db.query(User).filter_by(id=uid).first()
	if user is None:
		abort(404)
	db.close()
	
	return render_template('user/info.html',u=u,title=user.username,user=user)
예제 #18
0
def signup(u=None):
	try:
		if request.method == 'POST':
			# TODO: Validate hcaptcha
			#if hcaptcha.verify() == False:
			#	raise XaieconException('Please complete hCaptcha')
			
			# Validate form data
			if len(request.form.get('password','')) < 6:
				raise XaieconException('Please input a password atleast of 6 characters')
			if len(request.form.get('username','')) < 1:
				raise XaieconException('Please input a username atleast of 1 character')
			
			if len(request.form.get('agree_tos','')) == 0:
				raise XaieconException('Agree to the terms, privacy policy and content policy')
			
			# Hash the password
			password = generate_password_hash(request.form.get('password'))
			
			# Create the auth_token of form {username}:{password}
			string = f'{password}:{id}'
			auth_token = generate_password_hash(string)
			
			# Open the database
			db = open_db()
			
			pics = [
				'golden.png','blue.png','jelly.png','crab.png',
				'turtle.png','globefish.png','egg.png','sub.png',
				'beta.png','penguin.png','sword.png','turtle.png',
				'sword.png'
				]
			
			# Create new user and add it to database
			new_user = User(username=request.form.get('username'),
							password=password,
							auth_token=auth_token,
							fallback_thumb=random.choice(pics))
			db.add(new_user)
			db.commit()
			
			db.refresh(new_user)
			
			# Set session
			session['auth_token'] = auth_token
			session['username'] = request.form.get('username')
			session['id'] = new_user.id
			
			send_notification(gettext(f'Thanks for registering.'),new_user.id)
			
			# Finally, end ;)
			db.close()
			
			return redirect(f'/user/view/{new_user.id}')
		else:
			return render_template('user/signup.html',u=u,signup_error='',title='Signup')
	except XaieconException as e:
		return render_template('user/signup.html',u=u,signup_error=e,title='Signup')
예제 #19
0
def image(u=None,pid=0):
	db = open_db()
	post = db.query(Post).filter_by(id=pid).first()
	if post is None:
		abort(404)
	if post.image_file is None:
		abort(404)
	db.close()
	return send_from_directory('../user_data',post.image_file)
예제 #20
0
def channels_of(data=None, u=None):
    if data is None:
        return '', 400

    db = open_db()
    channels = db.query(Channel).filter_by(server_id=data['server_id']).all()
    data = {'channels': [x.json for x in channels]}
    emit('channels_of', data)
    db.close()
예제 #21
0
def serverinfo_of(data=None, u=None):
    if data is None:
        return '', 400

    db = open_db()
    server = db.query(Server).filter_by(id=data['server_id']).first()
    data = {'server_uuid': server.uuid, 'server_name': server.name}
    emit('serverinfo_of', data)
    db.close()
예제 #22
0
def send_event(json):
    db = open_db()
    servers = db.query(Serverchain).all()
    for s in servers:
        headers = {'User-Agent': 'Xaiecon-Fediverse'}
        requests.post(url='https://{s.ip_addr}/fediverse/receive',
                      headers=headers,
                      json=json)
    db.close()
예제 #23
0
def view(u=None,pid=0):
	db = open_db()
	
	# Query post from database
	post = db.query(Post).filter_by(id=pid).options(joinedload('*')).first()
	if post is None:
		abort(404)
	# Dont let people see nsfw
	if post.is_nsfw == True and u.is_nsfw == False:
		abort(403)
	
	# Add one view
	if u is not None:
		if db.query(View).filter_by(user_id=u.id,post_id=pid).first() is None:
			view = View(user_id=u.id,post_id=pid)
			db.add(view)
			db.query(Post).filter_by(id=pid).update({'views':post.views+1})
			db.commit()

	comment = db.query(Comment).filter_by(post_id=post.id).options(joinedload('*')).order_by(desc(Comment.id)).all()
	
	# This is how we get replies, pardon for so many cringe
	comments = []

	# First add the top comment(s)
	for c in comment:
		c.depth_level = 1
		comments.append(c)

		# Obtain comments that reference the current comment (top)
		comms = db.query(Comment).filter_by(comment_id=c.id).options(joinedload('*')).all()
		if comms is not None:
			# Obtain the comments of comments
			for d in comms:
				d.depth_level = 2
				ecomms = db.query(Comment).filter_by(comment_id=d.id).options(joinedload('*')).all()
				
				comments.append(d)
				for l in ecomms:
					l.depth_level = 3

					# Deepest comments, check if they have even more children
					if db.query(Comment).filter_by(comment_id=l.id).options(joinedload('*')).first() is not None:
						l.more_children = True

					comments.append(l)
	
	ret = render_template('post/details.html',u=u,title=post.title,post=post,comment=comments)
	
	db.close()
	
	cache.delete_memoized(list_posts)
	cache.delete_memoized(list_nuked)
	cache.delete_memoized(list_feed)
	
	return ret
예제 #24
0
    def mods(self, bid: int) -> bool:
        from xaiecon.classes.board import Board

        db = open_db()
        ret = db.query(Board).filter_by(id=bid, user_id=self.id).first()
        db.close()

        if ret is None:
            return False
        return True
예제 #25
0
def send_admin_notification(msg: str):
    db = open_db()

    admins = db.query(User).filter_by(is_admin=True).all()
    for a in admins:
        notification = Notification(body=msg, body_html=md(msg), user_id=a.id)
        db.add(notification)
        db.commit()

    db.close()
예제 #26
0
def send_everyone_notification(msg: str):
    db = open_db()

    users = db.query(User).all()
    for u in users:
        notification = Notification(body=msg, body_html=md(msg), user_id=u.id)
        db.add(notification)
        db.commit()

    db.close()
예제 #27
0
def message_send(data=None, u=None):
    if data is None:
        return '', 400

    if data['channel_id'] == 0:
        return '', 400

    db = open_db()

    body_html = data['body']
    body_html = md(body_html)

    # Obtain embeds
    soup = BeautifulSoup(body_html, 'html.parser')
    for a in soup.find_all('a'):
        try:
            if a.get('href', None) is None:
                continue

            # Append embed html
            embed = obtain_embed_url(a['href'])
            if embed is None:
                continue

            embed_html = f'<iframe width="560" height="315" src="{embed}" allowfullscreen frameborder=\'0\'></iframe>'
            body_html += embed_html
        except requests.exceptions.ConnectionError:
            pass
        except requests.exceptions.MissingSchema:
            pass

    print(body_html)

    # Create new message
    message = Message(body=data['body'],
                      body_html=body_html,
                      user_id=u.id,
                      channel_id=data['channel_id'])
    db.add(message)
    db.commit()

    # Send everyone the message
    db.refresh(message)

    data = {
        'time_utc': message.creation_date,
        'username': u.username,
        'uid': u.id,
        'body': message.body_html,
        'msg_id': message.id,
        'channel_id': data['channel_id']
    }
    emit('make_message', data, broadcast=True)

    db.close()
예제 #28
0
    def is_banned_from_board(self, bid: int) -> bool:
        from xaiecon.classes.board import BoardBan

        db = open_db()
        ret = db.query(BoardBan).filter_by(board_id=bid,
                                           user_id=self.id).first()
        db.close()

        if ret is None:
            return False
        return True
예제 #29
0
def thumb(u=None,uid=0):
	db = open_db()
	user = db.query(User).filter_by(id=uid).first()
	if user is None:
		abort(404)
	
	db.close()
	
	if user.image_file is None or user.image_file == '':
		return send_from_directory('assets/public/pics',user.fallback_thumb)
	return send_from_directory('../user_data',user.image_file)
예제 #30
0
def view_by_username(u=None,username=None):
	db = open_db()
	user = db.query(User).filter(User.username.ilike(username)).all()
	if user is None or len(user) == 0:
		abort(404)
	db.close()
	
	if len(user) > 1:
		random.shuffle(user)
		return render_template('user/pick.html',u=u,title=username,username=username,user=user,len=len(user))
	return redirect(f'/user/view/{user[0].id}')