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
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')
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)
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()
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
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)
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
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)
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)
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
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)
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)
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)
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()
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
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
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)
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')
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)
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()
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()
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()
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
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
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()
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()
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()
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
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)
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}')