def info(login): try: user = User('login', login) except UserNotFound: raise NotFound try: data = users.info(user) except SubscribeError: raise Forbidden data['id'] = user.id data['login'] = user.login try: data['created'] = data['created'] except (KeyError, AttributeError): pass try: data['birthdate'] = data['birthdate'] except (KeyError, AttributeError): pass if env.user.id: data['subscribed'] = user.check_subscriber(env.user) data['rec_sub'] = user.check_rec_subscriber(env.user) if not data['subscribed']: data['bl'] = env.user.check_blacklist(user) if not data['bl']: data['wl'] = env.user.check_blacklist(user) return data
def usercss(login): try: u = User('login', login) except UserNotFound: raise NotFound css = u.get_profile('www.usercss') return Response(css, mimetype='text/css')
def info(login): try: user = User('login', login) except UserNotFound: raise NotFound try: data = users.info(user) except SubscribeError: raise Forbidden data['login'] = login try: data['created'] = timestamp(data['created']) except (KeyError, AttributeError): pass try: data['birthdate'] = timestamp(data['birthdate']) except (KeyError, AttributeError): pass if env.user.id: data['subscribed'] = user.check_subscriber(env.user) data['rec_sub'] = user.check_rec_subscriber(env.user) if not data['subscribed']: data['bl'] = env.user.check_blacklist(user) if not data['bl']: data['wl'] = env.user.check_blacklist(user) return Response(json.dumps(data), mimetype='application/json')
def info(login): try: user = User("login", login) except UserNotFound: raise NotFound try: data = users.info(user) except SubscribeError: raise Forbidden data["id"] = user.id data["login"] = user.login try: data["created"] = data["created"] except (KeyError, AttributeError): pass try: data["birthdate"] = data["birthdate"] except (KeyError, AttributeError): pass if env.user.id: data["subscribed"] = user.check_subscriber(env.user) data["rec_sub"] = user.check_rec_subscriber(env.user) if not data["subscribed"]: data["bl"] = env.user.check_blacklist(user) if not data["bl"]: data["wl"] = env.user.check_blacklist(user) return data
def __init__(self, field=None, value=None): if isinstance(field, (int, long)): User.__init__(self, field) return if field and value: User.__init__(self, field, value) return sess = Session() self.id = sess['id'] self.login = sess['login'] self.type = 'user' self.accounts = [] self.accounts_add = [] self.accounts_del = [] self.profile = {} self.profile_upd = {} self.info = {} self.info_upd = {} self.password = None self.redis = RedisPool(settings.storage_socket) if self.id: self._get_avatar()
def authenticate_ulogin(self, network, uid): res = db.fetchone("SELECT id FROM users.ulogin_accounts " "WHERE network=%s AND uid=%s;", [network, uid]) if not res: raise NotAuthorized User.__init__(self, int(res[0])) self.authenticate()
def unsubscribe_rec(login): if isinstance(login, User): user = login else: user = User('login', login) if not user.check_subscriber(env.user): return False user.del_rec_subscriber(env.user)
def info(user): """Get user info """ if isinstance(user, (str, unicode)): user = User('login', user) if env.user.id != user.id and user.get_profile('private') \ and not user.check_whitelist(env.user): raise SubscribeError return user.get_info()
def domain_owner(domain): if domain == settings.domain: return User.from_data(None, None) if domain.endswith(settings.domain): return User('login', domain[0:domain.find(settings.domain) - 1]) res = db.fetchone("SELECT id FROM users.domains WHERE domain=%s;", [domain]) #, _cache=600) if res: return User(res[0]) raise UserNotFound
def reset_password(code, password): redis = RedisPool(settings.storage_socket) key = 'reset-password:%s' % code print key id = redis.get(key) if not id: raise UserNotFound try: user = User(int(id)) except ValueError: raise UserNotFound user.set_password(password) user.save() redis.delete(key) return user
def subscribers_byid(uid): """Return user's subscribers by given user id""" uid = int(uid) env.owner = User(int(uid)) if not env.owner or not env.owner.id: raise NotFound return env.owner.subscribers()
def blog(login=None): if login: env.owner = User("login", login) elif env.user.is_authorized(): env.owner = env.user if not env.owner: raise UserNotFound before = env.request.args("before") if before: try: before = long(before) except (TypeError, ValueError): before = None try: plist = posts.recent_blog_posts(env.owner, settings.page_limit + 1, before=before) if len(plist) > settings.page_limit: plist = plist[:settings.page_limit] has_next = True else: has_next = False except PostAuthorError: raise Forbidden return {"posts": plist, "has_next": has_next}
def blog_by_id(uid=None): """Obtain user blog contents by given user id parameters: uid - user id """ if uid: env.owner = User(int(uid)) elif env.user.is_authorized(): env.owner = env.user if not env.owner: raise UserNotFound before = env.request.args("before") if before: try: before = long(before) except ValueError: before = None try: plist = posts.recent_blog_posts(env.owner, settings.page_limit + 1, before=before) if len(plist) > settings.page_limit: plist = plist[:settings.page_limit] has_next = True else: has_next = False except PostAuthorError: raise Forbidden return {"posts": plist, "has_next": has_next}
def subscribe_rec(login): """Subscribe to user's recommendations returns True if subscribed, and False if subscription request is sent """ if isinstance(login, User): user = login else: user = User('login', login) if env.user.id == user.id: raise SubscribeError if not user.check_subscriber(env.user): return subscribe(user) user.add_rec_subscriber(env.user) return True
def taglist(login): """Получение спика тегов пользователя по его user id или логину. Параметр login, переданный в URL может быть как числом, и тогда интерпретируется как id пользователя, так и строкой -- в этом случае он интерпретируется как login пользователя """ if login and login.isdigit(): env.owner = User(int(login)) else: env.owner = User("login", login) if not env.owner or not env.owner.id: raise UserNotFound return map(lambda t: { "tag": t["tag"], "count": t["cnt"] }, env.owner.tags(sort_by_name=True))
def userinfo(login): env.owner = User('login', login) if env.user.is_authorized() and env.user == env.owner: menu = 'blog' else: menu = '' return Response(template='/pages/userinfo.html', menu=menu, owner=env.owner)
def get_info(self, param=None): if self.id or self.info or self.info_upd: return User.get_info(self, param) if param: return None return {}
def register(login, **kwargs): """Register a new user """ if env.user.is_authorized(): raise AlreadyAuthorized(env.user.login) try: if User('login', login): raise UserExists(login) except UserNotFound: pass env.user = env.user.__class__.from_data(None, login, **kwargs) env.user.save() add_post('User @%s is registered' % login, author=User('login', 'welcome'), auto_subscribe=False)
def recipients(self): res = db.fetchall( "SELECT u.id, u.login FROM posts.recipients r " "JOIN users.logins u ON u.id=r.user_id " "WHERE r.post_id=%s;", [unb26(self.id)], ) return [User.from_data(r[0], r[1]) for r in res]
def recommended_users(self): res = db.fetchall( "SELECT u.id, u.login FROM posts.recommendations r " "JOIN users.logins u ON u.id=r.user_id " "WHERE post_id=%s AND comment_id=0;", [unb26(self.id)], ) return [User.from_data(r[0], r[1]) for r in res]
def __init__(self, post, id, to_comment_id=None, author=None, created=None, text=None, archive=False, files=None): if post and id: if isinstance(post, Post): self.post = post elif isinstance(post, (int, long)): self.post = Post.from_data(b26(post)) else: self.post = Post.from_data(post) self.id = int(id) res = db.fetchone( "SELECT c.author, u.login, i.name, i.avatar, " "c.to_comment_id, " "c.anon_login, " "c.created at time zone %s AS created, " "c.text, c.files, c.updated " "FROM posts.comments c " "JOIN users.logins u ON u.id=c.author " "JOIN users.info i ON u.id=i.id " "WHERE post_id=%s AND comment_id=%s;", [self.post.tz, unb26(self.post.id), self.id]) if not res: raise CommentNotFound(self.post.id, id) if author: self.author = author else: login = res['anon_login'] or res['login'] self.author = User.from_data(res['author'], login, info={ 'name': res['name'] or login, 'avatar': res['avatar'] }) self.to_comment_id = to_comment_id or res['to_comment_id'] self.created = created or res['created'] self.text = text or res['text'] self.recommendations = 0 self.recommended = False self.files = res['files'] self.updated = res['updated'] self.comments = [] self.archive = archive if isinstance(files, (list, tuple)): self.files = files
def _auth(self, sessid, ws): sess = Session(sessid.strip()) user = User(sess['id']) if user.id not in wss: wss[user.id] = [] wss[user.id].append(ws) return user
def tag_posts(login=None): """Выборка постов по тегам пользователя. Пользователь может быть идентифицирован по его user id или логину. Параметр login, переданный в URL может быть числом, и тогда интерпретируется как id пользователя, или строкой -- в этом случае он интерпретируется как login пользователя """ before = env.request.args("before") if before: try: before = long(before) except ValueError: before = None if login: if login and login.isdigit(): author = User(int(login)) else: author = User("login", login) else: author = None if author and author == env.user: private = None else: private = False tags = env.request.args("tag") if not isinstance(tags, (list, tuple)): tags = [tags] tags = [t.decode('utf-8').replace(u"\xa0", " ") for t in tags] plist = posts.select_posts(author=author, private=private, tags=tags, limit=settings.page_limit + 1, before=before) if len(plist) > settings.page_limit: plist = plist[:settings.page_limit] has_next = True else: has_next = False return {"posts": plist, "has_next": has_next}
def handleMatch(self, m): try: User('login', m.group('u')) except UserNotFound: return #'@'+m.group('u') a = etree.Element('a') a.set('href', '//%s.%s/' % (m.group('u'), settings.domain)) a.set('class', 'user') a.text = m.group('u') return a
def handleMatch(self, m): try: User('login', m.group('u')) except UserNotFound: return #'@'+m.group('u') a = etree.Element('a') a.set('href', userlink(m.group('u'))) a.set('class', 'user js-navigate') a.text = m.group('u') return a
def del_from_blacklist(login): if isinstance(login, User): user = login else: user = User('login', login) if env.user.id == user.id: return return env.user.del_from_blacklist(user)
def handleMatch(self, m): try: User('login', m.group('u')) except UserNotFound: return #m.group(0) a = etree.Element('a') a.set('href', link_template % '@' + m.group('u')) a.set('style', 'color:#4488ff;font-weight:bold;text-decoration:none;') a.text = '@' + m.group('u') return a
def save(self): is_new = not self.id if is_new and not self._url: raise InvalidFeedUrl("Cannot save feed without URL") if not self.login: self.login = self._generate_login() User.save(self) if is_new: db.perform("INSERT INTO users.feeds (id, url) VALUES (%s, %s);", [self.id, self._url]) self.fetch() for p in self.posts(): p.save() self.update_task()
def user_info_byid(uid): """Return user info by given user id""" if uid and uid.isdigit(): try: user = User(int(uid)) except (UserNotFound, ValueError): raise NotFound else: data = info(user.login) return json.loads(data.body) raise NotFound
def tag_posts(tag, login=None, show=None, offset=None, limit=None): if offset: offset = int(offset) if limit: limit = int(limit) else: limit = 10 try: author = User('login', login) if login else None except UserNotFound, e: return xmpp_template('user_not_found', login=e.message)
def domain_owner(domain): if domain == settings.domain: return User.from_data(None, None) if domain.endswith(settings.domain): return User("login", domain[0 : domain.find(settings.domain) - 1]) res = db.fetchone("SELECT id FROM users.domains WHERE domain=%s;", [domain]) # , _cache=600) if res: return User(res[0]) raise UserNotFound
def avatar(login, size): """To avoid code duplication, parameter ``login`` can be interpreted as a number if it is user id, and as a string if it is user login""" size = int(size) if size else 40 try: if login and login.isdigit(): user = User(int(login)) else: user = User('login', login) avatar = user.get_info('avatar') except UserNotFound: avatar = None if avatar: path = '%s%s/%s/%s' % \ (env.request.protocol, settings.avatars_root, size, avatar) else: path = '%s%s/av%s.png' % \ (env.request.protocol, settings.avatars_root, size) return Response(redirect=path)
def subscribe(login): """Subscribe to user returns True if subscribed, and False if subscription request is sent """ if isinstance(login, User): user = login else: user = User('login', login) if env.user.id == user.id: raise SubscribeError if user.add_subscription_request(env.user): publish('sub', {'to':user.id, 'a':'sub', 'from':env.user.login}) log.info('sub %d %s' % (user.id, env.user.login)) return True else: publish('sub', {'to':user.id, 'a':'req', 'from':env.user.login}) log.info('sub request %d %s' % (user.id, env.user.login)) return False
def subscribe(login): """Subscribe to user returns True if subscribed, and False if subscription request is sent """ if isinstance(login, User): user = login else: user = User('login', login) if env.user.id == user.id: raise SubscribeError if user.add_subscription_request(env.user): publish('sub', {'to': user.id, 'a': 'sub', 'from': env.user.login}) log.info('sub %d %s' % (user.id, env.user.login)) return True else: publish('sub', {'to': user.id, 'a': 'req', 'from': env.user.login}) log.info('sub request %d %s' % (user.id, env.user.login)) return False
def __init__(self, field, value=None): self._url = None if field == 'url': self._url = value elif isinstance(field, (str, unicode)): if field.startswith('http://') or field.startswith('https://'): self._url = field elif not value: raise InvalidFeedUrl if self._url: if not parse_url(self._url, exact=True): raise InvalidFeedUrl key = 'url_feed_id:%s' % self._url id = cache_get(key) if not id: res = db.fetchone("SELECT id FROM users.feeds WHERE url=%s;", [self._url]) if res: id = res['id'] cache_store(key, id) if not id: raise FeedNotFound try: User.__init__(self, long(id)) except UserNotFound: raise FeedNotFound else: try: User.__init__(self, field, value) except UserNotFound: raise FeedNotFound self._posts = []
def add_to_blacklist(login): if isinstance(login, User): user = login else: user = User('login', login) if env.user.id == user.id: raise SubscribeError res = env.user.add_to_blacklist(user) # TODO: send to pubsub return res
def info(login, show=False, offset=None, limit=None): """Get user info """ try: user = User('login', login) data = users.info(user) except UserNotFound: return xmpp_template('user_not_found', login=login) except SubscribeError: return xmpp_template('user_denied', login=login) data['realname'] = data['name'] del data['name'] #_posts = None if show: if offset: offset = int(offset) if limit: limit = int(limit) else: limit = 10 if env.user and env.user.id and env.user.id == user.id: private = None else: private = False #plist = posts.select_posts(author=user, private=private, # offset=offset, limit=limit) plist = posts.recent_blog_posts(author=user, offset=offset, limit=limit) plist.reverse() data['posts'] = plist else: data['posts_count'] = user.posts_count() return xmpp_template('user_info', login=login, **data)
def __init__(self, post, id, to_comment_id=None, author=None, created=None, text=None, archive=False, files=None): if post and id: if isinstance(post, Post): self.post = post elif isinstance(post, (int, long)): self.post = Post.from_data(b26(post)) else: self.post = Post.from_data(post) self.id = int(id) res = db.fetchone("SELECT c.author, u.login, i.name, i.avatar, " "c.to_comment_id, " "c.anon_login, " "c.created at time zone %s AS created, " "c.text, c.files, c.updated " "FROM posts.comments c " "JOIN users.logins u ON u.id=c.author " "JOIN users.info i ON u.id=i.id " "WHERE post_id=%s AND comment_id=%s;", [self.post.tz, unb26(self.post.id), self.id]) if not res: raise CommentNotFound(self.post.id, id) if author: self.author = author else: login = res['anon_login'] or res['login'] self.author = User.from_data(res['author'], login, info={'name': res['name'] or login, 'avatar': res['avatar']}) self.to_comment_id = to_comment_id or res['to_comment_id'] self.created = created or res['created'] self.text = text or res['text'] self.recommendations = 0 self.recommended = False self.files = res['files'] self.updated = res['updated'] self.comments = [] self.archive = archive if isinstance(files, (list, tuple)): self.files = files
def __init__(self, post_id, author=None, type=None, tags=None, private=None, created=None, title=None, link=None, text=None, edited=None, tz=settings.timezone, archive=None, files=None, pinned=None, tune=None): self._comments_count = None if post_id: if isinstance(post_id, (int, long)): if post_id == 0: raise PostNotFound(post_id) self.id = b26(post_id) else: self.id = post_id.lower() res = db.fetchone("SELECT p.author, u.login, p.type, p.private, " "p.created at time zone %s AS created, " "p.tags, p.title, p.link, p.text, p.files, " "p.edited, p.archive, p.pinned, p.tune " "FROM posts.posts p " "JOIN users.logins u ON p.author=u.id " "WHERE p.id=%s;", [tz, unb26(self.id)]) if not res: raise PostNotFound(post_id) self.author = User.from_data(res[0], res[1]) self.created = res['created'] if type is not None: self.type = type else: self.type = res['type'] if private is not None: self.private = private else: self.private = res['private'] if tags is not None: self.tags = [ t.decode('utf8').strip() if isinstance(t, str) else t for t in tags ] else: self.tags = res['tags'] if title is not None: if isinstance(title, str): self.title = title.decode('utf8').strip()[:128] elif isinstance(title, unicode): self.title = title.strip()[:128] else: self.title = res['title'] if link is not None: self.link = link else: self.link = res['link'] if text is not None: if isinstance(text, str): self.text = text.decode('utf8').strip()[:1048576] elif isinstance(text, unicode): self.text = text.strip()[:1048576] if len(self.text) < 3: raise PostTextError else: self.text = res['text'] if edited is not None: self.edited = edited else: self.edited = res['edited'] self.editable = not self.edited and \ self.created + \ timedelta(seconds=settings.edit_expire) >= \ datetime.now() # and \ #self.comments_count() == 0 if archive is not None: self.archive = archive else: self.archive = res['archive'] if pinned is not None: self.pinned = pinned else: self.pinned = res['pinned'] if tune is not None: self.tune = tune else: self.tune = res['tune'] if isinstance(files, (list, tuple)): self.files = files else: self.files = res['files'] #elif not author: # raise PostAuthorError #elif not text: # raise PostTextError else: self.id = None self.author = author self.type = type self.tags = tags self.private = private if isinstance(title, str): self.title = title.decode('utf-8').strip()[:128] elif isinstance(title, unicode): self.title = title.strip()[:128] else: self.title = title self.link = link if isinstance(text, str): try: self.text = text.decode('utf-8').strip()[:1048576] except UnicodeDecodeError: raise PostTextError elif isinstance(text, unicode): self.text = text.strip()[:1048576] else: self.text = text self.created = created self.edited = False self.editable = True self.archive = False if archive is None else archive self.pinned = False if pinned is None else pinned self.tune = tune self.tz = tz
def comments(self, last=False, all=False, offset=None, limit=None, cuser=None): if last: lim = " LIMIT %d" % limit if limit else '' offset = 0 order = ' DESC' elif all: lim = '' offset = 0 order = ' ASC' else: if not offset: offset = 0 lim = " LIMIT %d" % limit if limit else '' order = ' ASC' if isinstance(cuser, User) and cuser.id: res = db.fetchall("SELECT c.comment_id, c.to_comment_id," "c.author AS user_id, " "CASE WHEN c.anon_login IS NOT NULL " "THEN c.anon_login ELSE u1.login END AS login," "c.created at time zone %%s AS created, " "c.text, c.files, " "c.updated at time zone %%s AS updated, " "CASE WHEN rc.comment_id IS NOT NULL " "THEN true ELSE false END AS is_rec, " "ur.user_id AS recommended, " "ub.user_id AS bookmarked, " "ui1.name, ui1.avatar " "FROM posts.comments c " "JOIN users.logins u1 ON c.author=u1.id " "LEFT OUTER JOIN users.info ui1 " "ON ui1.id=c.author " "LEFT OUTER JOIN posts.recommendations rc " "ON rc.post_id=c.post_id " "AND rc.rcid=c.comment_id " "LEFT OUTER JOIN posts.recommendations ur " "ON ur.user_id=%%s " "AND ur.post_id=c.post_id " "AND ur.comment_id=c.comment_id " "LEFT OUTER JOIN posts.bookmarks ub " "ON ub.user_id=%%s " "AND ub.post_id=c.post_id " "AND ub.comment_id=c.comment_id " "WHERE c.post_id=%%s AND c.comment_id>=%%s " "ORDER BY c.created%s%s;" % (order, lim), [self.tz, self.tz, cuser.id, cuser.id, unb26(self.id), offset]) else: res = db.fetchall("SELECT c.comment_id, c.to_comment_id," "c.author AS user_id, ui1.name," "CASE WHEN c.anon_login IS NOT NULL " "THEN c.anon_login ELSE u1.login END AS login," "c.created at time zone %%s AS created, " "c.text, c.files, " "c.updated at time zone %%s AS updated, " "CASE WHEN rc.comment_id IS NOT NULL " "THEN true ELSE false END AS is_rec, " "false AS recommended, " "false AS bookmarked, " "ui1.avatar " "FROM posts.comments c " "JOIN users.logins u1 ON c.author=u1.id " "LEFT OUTER JOIN users.info ui1 " "ON ui1.id=c.author " "LEFT OUTER JOIN posts.recommendations rc " "ON rc.post_id=c.post_id " "AND rc.rcid=c.comment_id " "WHERE c.post_id=%%s AND c.comment_id>=%%s " "ORDER BY c.created%s%s;" % (order, lim), [self.tz, self.tz, unb26(self.id), offset]) if last: res.reverse() if cuser: unr = db.fetchall("SELECT comment_id FROM posts.unread_comments " "WHERE user_id=%s AND post_id=%s;", [cuser.id, unb26(self.id)]) unread = { r['comment_id']: 1 for r in unr } else: unread = {} comments = [] for c in res: author = User.from_data(c['user_id'], c['login'], info={'name': c['name'], 'avatar': c['avatar']}) unr = True if c['comment_id'] in unread else False comment = Comment.from_data(self, id=c['comment_id'], to_comment_id=c['to_comment_id'], author=author, created=c['created'], text=c['text'], recommended=c['recommended'], bookmarked=c['bookmarked'], is_rec=c['is_rec'], files=c['files'], updated=c['updated'], unread=unr) comments.append(comment) if not limit and not offset: redis = RedisPool(settings.storage_socket) redis.set('cmnt_cnt.%s' % unb26(self.id), len(comments)) return comments
def set_info(self, param, value): User.set_info(self, param, value) if param == 'avatar': self.avatar = value