def check_in(self): self.last_check_in_time = self.last_check_in_time or 0 old_time = self.last_check_in_time last_midnight = get_today_start_timestamp() # 今日未签到 if self.last_check_in_time < last_midnight: self.last_check_in_time = int(time.time()) # 三天内有签到,连击 if old_time > last_midnight - config.USER_CHECKIN_COUNTER_INTERVAL: self.check_in_his += 1 else: self.check_in_his = 1 self.save() # 签到加分 credit = self.credit exp = self.exp self.credit += 5 self.exp += 5 self.save() ManageLogModel.add_by_credit_changed_sys(get_bytes_from_blob(self.id), credit, self.credit, note='每日签到') ManageLogModel.add_by_exp_changed_sys(get_bytes_from_blob(self.id), exp, self.exp, note='每日签到') return { 'credit': 5, 'exp': 5, 'time': self.last_check_in_time, 'check_in_his': self.check_in_his }
def _auth_base(self, password_text): """ 已获取了用户对象,进行密码校验 :param password_text: :return: """ dk = hashlib.pbkdf2_hmac(config.PASSWORD_HASH_FUNC_NAME, password_text.encode('utf-8'), get_bytes_from_blob(self.salt), config.PASSWORD_HASH_ITERATIONS) if get_bytes_from_blob(self.password) == get_bytes_from_blob(dk): return self
def check_is_me(ability, user, action, record: DataRecord, available_columns: list): # 拒绝其他人写入自己的个人资料 if user: if record.get('id') != get_bytes_from_blob(user.id): available_columns.clear() return True
def __repr__(self): if isinstance(self.id, (bytes, memoryview)): return '<User id:%x nickname:%r>' % (int.from_bytes(get_bytes_from_blob(self.id), 'big'), self.nickname) elif isinstance(self.id, int): return '<User id:%d nickname:%r>' % (self.id, self.nickname) else: return '<User id:%s nickname:%r>' % (self.id, self.nickname)
def get_post_title_by_list(cls, *lst) -> Dict[bytes, str]: """ :param lst: [[related_type, related_id], ...] :return: """ ret = {} info = {} for related_type, related_id in lst: info.setdefault(related_type, []) info[related_type].append(related_id) for related_type, id_lst in info.items(): m = cls.get_model(related_type) fields = [ m._meta.primary_key, ] # 获取标题列 title_field = cls.TITLE_FIELD.get(related_type) if title_field: fields.append(getattr(m, title_field)) # 按分类分别执行查询 for i in m.select(*fields).where(m.id.in_(id_lst)): ret[get_bytes_from_blob(i.id)] = i.get_title() return ret
def get_main_page_article(cls): try: return cls.select().where(cls.flag == 2).get() except cls.DoesNotExist: a = cls.insert(time=int(time.time()), user_id=None, flag=2, title="主页面", content=DEFAULT_WIKI_CONTENT, ref=None).execute() post_stats_new(POST_TYPES.WIKI, get_bytes_from_blob(a)) return cls.get(cls.id == a)
def daily_access_reward(self): self.access_time = self.access_time or 0 old_time = self.access_time self.update_access_time() if old_time < get_today_start_timestamp(): exp = self.exp self.exp += 5 self.save() ManageLogModel.add_by_exp_changed_sys(get_bytes_from_blob(self.id), exp, self.exp, note='每日登录') return {'exp': 5}
def _to_dict(self): data = {} fields = self.val._meta.fields for name, v in model_to_dict(self.val, recurse=False).items(): if isinstance(fields[name], peewee.ForeignKeyField): name = name + '_id' elif isinstance(fields[name], peewee.BlobField): v = get_bytes_from_blob(v) if self.selected != ALL_COLUMNS and (self.selected and (name not in self.selected)): continue data[name] = v if self.available_columns != ALL_COLUMNS: return dict_filter(data, self.available_columns) return data
async def tick(self): """ 定时轮询 :return: """ data = {} now = int(time.time()) if self.current_user: user = self.current_user # 检查未读信息 r = Notification.refresh(user.id) c = Notification.count(user.id) data['notif_count'] = c # 更新在线时间 await redis.zadd(RK_USER_ACTIVE_TIME_ZSET, now, get_bytes_from_blob(user.id)) else: # TODO: 后面再给auid加几个随机数 auid = self.params.get('auid', None) if auid: try: auid = config.LONG_ID_GENERATOR(auid) if not await redis.zscore(RK_USER_ANON_ACTIVE_TIME_ZSET, auid.to_bin()): auid = None except TypeError: auid = None if not auid: new_id = config.LONG_ID_GENERATOR() await redis.zadd(RK_USER_ANON_ACTIVE_TIME_ZSET, now, new_id.to_bin()) data['auid'] = new_id.to_hex() else: await redis.zadd(RK_USER_ANON_ACTIVE_TIME_ZSET, now, auid.to_bin()) offset = 30 data['online'] = await redis.zcount(RK_USER_ACTIVE_TIME_ZSET, min=now - offset) + \ await redis.zcount(RK_USER_ANON_ACTIVE_TIME_ZSET, min=now - offset) self.finish(RETCODE.SUCCESS, data)
def ignore_hide_board(ability: Ability, user, query: 'SQLQueryInfo'): roles = {ability.role} if not user else set(user.roles) if roles & {'superuser', 'admin'}: return if roles & {'inactive_user', 'user', 'wiki_editor'}: visible_limit = POST_VISIBLE.ADMIN_ONLY else: visible_limit = POST_VISIBLE.USER_ONLY # TODO: 以后这种请求加cache ignored_board_ids = [ get_bytes_from_blob(x.id) for x in Board.select(Board.id).where(~( (Board.state > POST_STATE.APPLY) & (Board.visible > POST_VISIBLE.HIDE) & (Board.visible < visible_limit))) ] query.add_condition('board_id', SQL_OP.NOT_IN, ignored_board_ids)
async def after_insert(self, raw_post: Dict, values: SQLValuesToWrite, record: DataRecord): post_stats_do_comment(record['related_type'], record['related_id'], record['id']) post_number = Comment.select().where( Comment.related_id == record['related_id'], Comment.id <= record['id']).count() Comment.update(post_number=post_number).where( Comment.id == record['id']).execute() if self.do_mentions: # 创建提醒 loc = [record['related_type'], record['related_id']] # record['related_id']: memoryview loc_title = POST_TYPES.get_post_title_by_list(loc)[ get_bytes_from_blob(record['related_id'])] related = [POST_TYPES.COMMENT, record['id']] self.do_mentions(record['user_id'], loc_title, loc, related) if config.SEARCH_ENABLE: run_in_thread(esdb.es_update_comment, record['id'])
def fetch_notif_of_log(user_id, last_manage_log_id=b'\x00'): from model.manage_log import ManageLog, MOP if last_manage_log_id is None: last_manage_log_id = b'\x00' item_lst = ManageLog.select().where( ManageLog.related_user_id == user_id, ManageLog.id > last_manage_log_id, ManageLog.operation.in_( (MOP.POST_STATE_CHANGE, MOP.USER_PASSWORD_CHANGE, MOP.USER_PASSWORD_RESET, MOP.USER_KEY_RESET, MOP.USER_GROUP_CHANGE, MOP.USER_CREDIT_CHANGE, MOP.USER_REPUTE_CHANGE, MOP.USER_NICKNAME_CHANGE, MOP.TOPIC_BOARD_MOVE, MOP.TOPIC_AWESOME_CHANGE, MOP.TOPIC_STICKY_WEIGHT_CHANGE) ) ).order_by(ManageLog.id.desc()) moves = [] def wrap(item: ManageLog): # 总不能把MANAGE_OPERATION的内容换个号码,抄一遍写在上面。 # 因此选择过滤掉一些,其他全部归为一类。 if item.operation == MOP.USER_CREDIT_CHANGE: if item.note == '每日签到': # 签到得分忽略 return elif item.operation == MOP.USER_EXP_CHANGE: if item.note == '每日登录': # 签到得分忽略 return if item.operation == MOP.TOPIC_BOARD_MOVE: moves.append([POST_TYPES.BOARD, to_bin(item.value['change'][0])]) moves.append([POST_TYPES.BOARD, to_bin(item.value['change'][1])]) return { 'type': NOTIF_TYPE.MANAGE_INFO_ABOUT_ME, 'time': item.time, 'loc_post_type': item.related_type, 'loc_post_id': item.related_id, 'loc_post_title': None, 'sender_ids': (item.user_id,), 'receiver_id': user_id, 'from_post_type': None, # 来源为managelog,但并非post 'from_post_id': item.id, 'related_type': item.related_type, # 提醒类型较为特殊 'related_id': item.related_id, 'data': { 'op': item.operation, 'role': item.role, 'value': item.value, 'title': None # 进行二次填充 } } ret_items = list(filter(lambda x: x, map(wrap, item_lst))) info = POST_TYPES.get_post_title_by_list(*[[i['related_type'], i['related_id']] for i in ret_items]) info2 = POST_TYPES.get_post_title_by_list(*moves) for i in ret_items: t = info.get(get_bytes_from_blob(i['related_id']), None) if t: i['data']['title'] = t if i['related_type'] == POST_TYPES.COMMENT: # 这里不是批量,可能要付出较大代价 c: Comment = Comment.get_by_id(i['related_id']) if not c: continue p = POST_TYPES.get_post(c.related_type, c.related_id) if not p: continue i['loc_post_type'] = c.related_type i['loc_post_id'] = c.related_id i['loc_post_title'] = p.get_title() i['data']['comment'] = { 'related_type': c.related_type, 'related_id': c.related_id, 'related_title': p.get_title(), 'post_number': c.post_number, 'content': c.content } if i['data']['op'] == MOP.TOPIC_BOARD_MOVE: val = i['data']['value']['change'] i['data']['move_info'] = [ info2.get(to_bin(val[0]), None), info2.get(to_bin(val[1]), None) ] return ret_items
def check_is_users_post(ability, user, action, record: DataRecord, available_columns: Set): if user: if record.get('user_id') != get_bytes_from_blob(user.id): available_columns.clear() return True
def __repr__(self): return '<User id:%x nickname:%r>' % (int.from_bytes( get_bytes_from_blob(self.id), 'big'), self.nickname)
async def same_user(view: BaseView) -> Union[bytes, None]: if view.current_user: return get_bytes_from_blob(view.current_user.id) view.finish(RETCODE.PERMISSION_DENIED)
def get_token(self): return get_bytes_from_blob(self.id)
async def create_user(self, password, email=None, phone=None) -> User: values = {} nprefix = config.USER_NICKNAME_AUTO_PREFIX + '_' if config.POST_ID_GENERATOR != config.AutoGenerator: # 若不使用数据库生成id uid = User.gen_id() values['id'] = uid.to_bin() values['nickname'] = nprefix + uid.to_hex() values['is_new_user'] = True values['change_nickname_chance'] = 1 if email: values['email'] = email.lower() if phone: values['phone'] = phone # 密码 ret = User.gen_password_and_salt(password) values.update(ret) values['group'] = USER_GROUP.NORMAL values['state'] = POST_STATE.NORMAL # 注册IP地址 values['ip_registered'] = await get_fuzz_ip(self) # 生成 access_token values.update(User.gen_key()) values['time'] = int(time.time()) try: uid = User.insert(values).execute() u = User.get_by_pk(uid) except peewee.IntegrityError as e: db.rollback() if e.args[0].startswith('duplicate key'): return self.finish(RETCODE.ALREADY_EXISTS) return self.finish(RETCODE.FAILED) except peewee.DatabaseError: db.rollback() return self.finish(RETCODE.FAILED) times = 3 success = False u.nickname = nprefix + to_hex(get_bytes_from_blob(u.id)) # 尝试填充用户名 while times >= 0: try: if u.number == 1: u.group = USER_GROUP.ADMIN u.save() success = True break except peewee.DatabaseError: db.rollback() times -= 1 u.nickname = nprefix + to_hex(os.urandom(8)) if not success: return self.finish(RETCODE.FAILED) # 清理现场 if email: await User.reg_code_cleanup(email) # 添加统计记录 post_stats_new(POST_TYPES.USER, u.id) UserNotifLastInfo.new(u.id) return u
def func(ability: Ability, user, query: 'SQLQueryInfo'): for i in query.conditions.find('id'): if i[1] == SQL_OP.EQ and i[2] == get_bytes_from_blob(user.id): query.select.add('email') query.select.add('token_time')