Beispiel #1
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)
Beispiel #2
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()
Beispiel #3
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()
Beispiel #4
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()
Beispiel #5
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()
Beispiel #6
0
def write(u=None):
	db = open_db()
	try:
		if request.method == 'POST':
			body = request.form.get('body','')
			title = request.form.get('title')
			keywords = request.form.get('keywords')
			link = request.form.get('link','')
			bid = request.form.get('bid')
			category = int(request.values.get('category','0'))
			show_votes = strtobool(request.form.get('show_votes','False'))
			is_nsfw = strtobool(request.form.get('is_nsfw','False'))

			if len(title) > 255:
				raise XaieconException('Too long title')
			if len(body) > 16000:
				raise XaieconException('Too long body')
			
			category = db.query(Category).filter_by(id=category).first()
			if category is None:
				raise XaieconException('Not a valid category')
			board = db.query(Board).filter_by(id=bid).first()
			if board is None:
				raise XaieconException('Invalid board')
			bid = board.id

			if u.is_banned_from_board(bid) == True:
				raise XaieconException(f'You\'re banned from /b/{board.name}')
			
			is_link = False
			embed_html = ''
			if link != '':
				is_link = True

				embed = obtain_embed_url(link)
				if embed is not None:
					embed_html = f'<iframe width="560" height="315" src="{embed}" allowfullscreen frameborder=\'0\'></iframe>'

			if body == '' and is_link == False:
				raise XaieconException('Empty body')
			if title is None or title == '':
				raise XaieconException('Empty title')
			
			body_html = md(body)
			
			post = Post(keywords=keywords,
						title=title,
						body=body,
						link_url=link,
						is_link=is_link,
						user_id=u.id,
						is_nsfw=is_nsfw,
						downvote_count=0,
						upvote_count=0,
						total_vote_count=0,
						category_id=category.id,
						board_id=bid,
						embed_html=embed_html,
						body_html=body_html,
						show_votes=show_votes)
			
			file = request.files['image']
			if file:
				try:
					# Build paths and filenames
					image_filename = secure_filename(f'{secrets.token_hex(12)}.jpeg')
					image_filepath = os.path.join('user_data',image_filename)
	
					thumb_filename = secure_filename(f'thumb_{image_filename}')
					thumb_filepath = os.path.join('user_data',thumb_filename)
	
					# Save full image file
					file.save(image_filepath)
	
					# Create thumbnail for image
					image = PIL.Image.open(image_filepath)
					image = image.convert('RGB')
					image.thumbnail((128,128))
					image.save(thumb_filepath)
	
					post.image_file = image_filename
					post.thumb_file = thumb_filename
	
					post.is_image = True
					post.is_thumb = True
				except PIL.UnidentifiedImageError:
					pass
			else:
				post.is_image = False
				if is_link == True:
					img = obtain_post_thumb(link)
					if img is not None:
						thumb_filename = secure_filename(f'thumb_{secrets.token_hex(12)}.jpeg')
						thumb_filepath = os.path.join('user_data',thumb_filename)
						
						timg = img.convert('RGB')
						timg.resize((128,128))
						timg.save(thumb_filepath)
						
						post.thumb_file = thumb_filename
						post.is_thumb = True
			
			db.add(post)
			db.commit()
			
			db.refresh(post)
			
			csam_thread = threading.Thread(target=csam_check_post, args=(u.id,post.id,))
			csam_thread.start()
			
			notif_msg = f'# {post.title}\n\rBy [/u/{u.username}](/user/view/{u.id}) on [/b/{board.name}](/board/view/{board.id})\n\r{post.body}'
			
			# Alert boardmaster of the posts in the guild
			if board.user_id != u.id:
				send_notification(notif_msg,board.user_id)
			
			# Notify followers
			follows = db.query(UserFollow).filter_by(target_id=u.id,notify=True).all()
			for f in follows:
				if f.user_id != u.id:
					send_notification(notif_msg,f.user_id)
			
			ping = body.find('@everyone')
			if ping != -1 and u.is_admin == True:
				users = db.query(User).all()
				for us in users:
					if us.id != u.id:
						send_notification(notif_msg,us.id)
			
			ping = body.find('@here')
			if ping != -1 and u.mods(post.board_id):
				subs = db.query(BoardSub).filter_by(board_id=post.board_id).all()
				for s in subs:
					if s.user_id != u.id:
						send_notification(notif_msg,s.user_id)
			
			for m in re.finditer(r'([u][\/]|[@])([a-zA-Z0-9#][^ ,.;:\n\r\t<>\/\'])*\w+',body):
				m = m.group(0)
				try:
					name = re.split(r'([u][\/]|[@])',m)[2]
					tag = name.split('#')
					
					# direct mention
					if len(tag) > 1:
						uid = int(tag[1])
						user = db.query(User).filter_by(id=uid).first()
						if user is None:
							raise IndexError
						send_notification(notif_msg,user.id)
					else:
						users = db.query(User).filter_by(username=name).all()
						if users is None:
							raise IndexError
						for user in users:
							send_notification(notif_msg,user.id)
				except IndexError:
					pass
			
			db.close()
			
			# Mess with everyone's feed
			cache.delete_memoized(list_posts)
			cache.delete_memoized(list_nuked)
			cache.delete_memoized(list_feed)
			
			return redirect(f'/post/view/{post.id}')
		else:
			board = db.query(Board).filter_by(is_banned=False).options(joinedload('user_info')).all()
			categories = db.query(Category).all()
			db.close()
			return render_template('post/write.html',u=u,title='New post',boards=board,categories=categories)
	except XaieconException as e:
		db.rollback()
		db.close()
		return render_template('user_error.html',u=u,title = 'Whoops!',err=e)
Beispiel #7
0
def edit(u=None,pid=0):
	db = open_db()
	try:
		post = db.query(Post).filter_by(id=pid).first()
		if post is None:
			abort(404)
		
		if u.id != post.user_id and u.is_admin == False:
			raise XaieconException('User is not authorized')
		
		if request.method == 'POST':
			body = request.form.get('body')
			title = request.form.get('title')
			keywords = request.form.get('keywords')
			link = request.form.get('link','')
			category = int(request.form.get('category','0'))
			is_nsfw = strtobool(request.form.get('is_nsfw','False'))

			if len(title) > 255:
				raise XaieconException('Too long title')

			category = db.query(Category).filter_by(id=category).first()
			if category is None:
				raise XaieconException('Not a valid category')
			
			is_link = False
			embed_html = ''
			if link != '':
				is_link = True

				embed = obtain_embed_url(link)
				if embed is not None:
					embed_html = f'<iframe width="560" height="315" src="{embed}" allowfullscreen frameborder=\'0\'></iframe>'
			
			if body == None or body == '':
				raise XaieconException('Empty body')
			if title == None or title == '':
				raise XaieconException('Empty title')

			body_html = ''
			
			# Remove old image
			try:
				if post.is_image == True:
					os.remove(os.path.join('user_data',post.image_file))
					os.remove(os.path.join('user_data',post.thumb_file))
			except FileNotFoundError:
				pass
			
			file = request.files['image']
			if file:
				try:
					# Build paths and filenames
					image_filename = secure_filename(f'{secrets.token_hex(12)}.jpeg')
					image_filepath = os.path.join('user_data',image_filename)

					thumb_filename = secure_filename(f'thumb_{image_filename}')
					thumb_filepath = os.path.join('user_data',thumb_filename)

					# Save full image file
					file.save(image_filepath)

					# Create thumbnail for image
					image = PIL.Image.open(image_filepath)
					image = image.convert('RGB')
					image.resize((128,128))
					image.save(thumb_filepath)

					db.query(Post).filter_by(id=pid).update({
						'image_file':image_filename,
						'thumb_file':thumb_filename,
						'is_image':True,
						'is_thumb':True})
				except PIL.UnidentifiedImageError:
					# Failure creating image!
					db.query(Post).filter_by(id=pid).update({
						'is_image':False,
						'is_thumb':False})
			else:
				db.query(Post).filter_by(id=pid).update({
					'is_image':False,
					'is_thumb':False})
				if is_link == True:
					img = obtain_post_thumb(link)
					if img is not None:
						thumb_filename = secure_filename(f'thumb_{secrets.token_hex(12)}.jpeg')
						thumb_filepath = os.path.join('user_data',thumb_filename)
						
						img = img.convert('RGB')
						img.thumbnail((128,128))
						img.save(thumb_filepath)
						
						db.query(Post).filter_by(id=pid).update({
							'is_thumb':True,
							'thumb_file':thumb_filename})
			
			body_html = md(body)
			
			# Update post entry on database
			db.query(Post).filter_by(id=pid).update({
						'keywords':keywords,
						'body':body,
						'body_html':body_html,
						'is_link':is_link,
						'is_nsfw':is_nsfw,
						'title':title,
						'link_url':link,
						'category_id':category.id,
						'body_html':body_html,
						'embed_html':embed_html})
			db.commit()

			csam_thread = threading.Thread(target=csam_check_post, args=(u.id,post.id,))
			csam_thread.start()
			
			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}')
		else:
			categories = db.query(Category).all()
			db.close()
			return render_template('post/edit.html',u=u,title='Edit',post=post,categories=categories)
	except XaieconException as e:
		db.rollback()
		db.close()
		return render_template('user_error.html',u=u,title = 'Whoops!',err=e)
Beispiel #8
0
def create(u=None,pid=0):
	try:
		db = open_db()
		
		body = request.form.get('body')
		
		if len(body) == 0:
			raise XaieconException('Body too short')
		
		# Post exists in first place?
		post = db.query(Post).filter_by(id=pid).options(joinedload('*')).first()
		if post is None:
			abort(404)
		
		# Add comment
		comment = Comment(body=body,body_html=md(body),user_id=u.id,post_id=pid)
		db.add(comment)
		
		# Increment number of comments
		db.query(Post).filter_by(id=pid).update({'number_comments':post.number_comments+1})
		db.commit()
		
		notif_msg = f'Comment by [/u/{comment.user_info.username}](/user/view/{post.user_info.id}) on [/b/{post.board_info.name}](/board/view/{post.board_info.id}) in post ***{post.title}*** [View](/comment/view/{comment.id})\n\r{comment.body}'
		
		idlist = []
		if post.user_id != u.id and post.user_id not in idlist:
				idlist.append(post.user_id)
		
		# Notify followers
		follows = db.query(UserFollow).filter_by(target_id=u.id,notify=True).all()
		for f in follows:
			if f.user_id != u.id and f.user_id not in idlist:
				idlist.append(f.user_id)
		
		# Notify post poster
		if post.user_id != u.id and post.user_id not in idlist:
				idlist.append(post.user_id)
		
		# Notify commenter
		if comment.user_id != u.id and comment.user_id not in idlist:
				idlist.append(comment.user_id)

		for id in idlist:
			send_notification(notif_msg,id)

		ping = body.find('@everyone')
		if ping != -1 and u.is_admin == True:
			users = db.query(User).all()
			for us in users:
				if us.id != u.id:
					send_notification(notif_msg,us.id)
		
		ping = body.find('@here')
		if ping != -1 and u.mods(post.board_id):
			subs = db.query(BoardSub).filter_by(board_id=post.board_id).all()
			for s in subs:
				if s.user_id != u.id:
					send_notification(notif_msg,s.user_id)
		
		for m in re.finditer(r'([u][\/]|[@])([a-zA-Z0-9#][^ ,.;:\n\r\t<>\/\'])*\w+',body):
			m = m.group(0)
			print(m)
			try:
				name = re.split(r'([u][\/]|[@])',m)[2]
				tag = name.split('#')
				
				# direct mention
				if len(tag) > 1:
					uid = int(tag[1])
					user = db.query(User).filter_by(id=uid).first()
					if user is None:
						raise IndexError
					send_notification(notif_msg,user.id)
				else:
					users = db.query(User).filter_by(username=name).all()
					if users is None:
						raise IndexError
					for user in users:
						send_notification(notif_msg,user.id)
			except IndexError:
				pass
		
		db.close()
		
		cache.delete_memoized(view_p)
		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:
		return render_template('user_error.html',u=u,title = 'Whoops!',err=e)