拉黑後端實現

此處輸入圖片的描述

社區妹子強烈須要拉黑功能,結果剛上線,妹子就被拉黑了…這是個悲傷的故事…html

初衷

對於種種緣由不想再理會的人,能夠刪除私信時選擇拉黑。拉黑後,拉黑者取消關注對方,刪除私信,不在接收對方私信。被拉黑者收到系統消息提示被拉黑,若是是惡意、不良信息則超過必定次數被禁號,可是保留被拉黑以前全部狀態,包括關注、私信,可是再次發送私信時提示私信被對方拒絕接收,再次關注提示對方拒絕被你加關注。惟一解除拉黑的手段,拉黑方再次關注對方則自動取消拉黑。前端

之因此保留狀態,是爲了儘可能減小用戶被拉黑的感知,可是又會收到系統提醒,相互矛盾。python

策略

  • 刪除私信時勾選拉黑:把對方加入本身blacklist列表中,統計數據,取消關注,刪除私信會話。json

  • 進入主頁:返回拉黑數據,點擊關注時則根據是否被拉黑進行提示。(更優方式:點擊關注時後臺判斷是否被拉黑,拉黑則拒絕該請求,不然正常關注)網絡

  • 被拉黑者發送私信:進入私信頁面返回拉黑數據,已被拉黑則發送消息時直接提示私信被對方拒絕接收,若是中途被拉黑後臺會主動判斷blacklist而提示私信被對方拒絕接收。(更優方式:開始不傳遞拉黑數據,發送私信時後臺判斷提示)session

上面也提到了更優辦法,其實能夠減小查詢次數,可是最終沒用,仍是考慮到體驗的問題,blacklist是使用kv存儲的,後臺查詢比客戶端請求快,kv費用消耗低。因此每次查詢數據附帶後傳到前端,絕大多數狀況用戶點擊就有提示,而不存在網絡延時。app

Coding Time

  • 刪除私信時勾選拉黑ui

# kvdb設置統計user被拉黑數量
def set_blacklist_count(user):
    blackcount_key = "blackcount_%s" % user.user_id
    blackcount = kv.get_value(blackcount_key)
    if blackcount is None:
        kv.set_value(blackcount_key, 1)
    else:
        kv.set_value(blackcount_key, blackcount+1)
        # 拉黑次數超過必定次數則發送郵件提醒
        if blackcount >= 5:
            print 'blacklist-email'
            # 建立一個假用戶
            null_user = User()
            null_user.nickname = user.nickname
            null_user.email = user.user_id
            null_user.password = blackcount
            content = u"您在社區的帳戶信息以下:"
            to_email = ['xxx@xxx.com']
            subject = u"xxx"
            html = render_template("login_info_email.html", user=null_user, content=content)
            sc_mail(to_email, subject, html)
    return 'sucesss'
# 添加user到to_user的黑名單list
def add_to_blacklist(user, to_user):
    # 禁止拉黑系統帳號
    if user.id == 1:
        return 'failed'
    key = 'blacklist_%s' % to_user.user_id
    blacklist = kv.get_list(key)
    # 名單爲空
    if blacklist is None:
        blacklist = []
        blacklist.append(user.user_id)
        kv.set_list(key, blacklist)
    # 追加list
    else:
        # 是否已經被拉黑
        if str(user.user_id) in blacklist:
            return 0
        else:
            blacklist.append(user.user_id)
            kv.set_list(key, blacklist)
    return 1
# 消息發送
@app.route('/message/<int:user_id>', methods=['GET', 'POST'])
@login_required
def message(user_id):
      ...
      # 刪除私信與拉黑處理
    if request.form.get('delete'):
        # 無私信對話直接返回
        if session is None:
            return 'error'
        # 選定拉黑名單
        if int(request.form.get('blacklist')) == 1:
            # 添加到本身黑名單中
            ret = add_to_blacklist(user, g.user)
            # 取消關注
            unfollow(user_id)
            # 發送系統私信
            sys_user = User.query.get(100)
            content = u"系統消息:你已經被拉黑!惡意使用且被拉黑超過限定次數的帳號將被禁用。"
            sys_msg(sys_user, user, content)
            content = u"系統消息:你已拉黑%s!惡意使用且被拉黑超過限定次數的帳號將被禁用。" % user.nickname
            sys_msg(sys_user, g.user, content)
            # 拉黑數據統計
            if ret:
                set_blacklist_count(user)
        # 刪除與其私信
        if g.user.id == session.from_id:
            session.from_delete_time = datetime.now()
        if g.user.id == session.to_id:
            session.to_delete_time = datetime.now()
        db.session.add(session)
        db.session.commit()
        return 'success'
    ...
    # 進入私信判斷是否在對方黑名單中
    blacklist_key = 'blacklist_%s' % user_id
    blacklist = kv.get_list(blacklist_key)
    inBlacklist = 1 if (blacklist is not None and str(g.user.user_id) in blacklist) else 0
    # 是不是系統帳號
    isSystem = 1 if user.id == 100 else 0
    return render_template("msg_content.html", title=u'私信', messages=messages, user=user, inBlacklist=inBlacklist, isSystem=isSystem)
  • 被拉黑者發送私信編碼

...
# 提交數據
if request.form.get('message'):
    # 判斷是否在blacklist中
    key = 'blacklist_%s' % user_id
    blacklist = kv.get_list(key)
    print blacklist
    if blacklist is not None and str(g.user.user_id) in blacklist:
        return 'blacklist'
...
  • 訪問主頁和取消拉黑url

# 在對方blacklist中則拒絕關注請求
blacklist_key = 'blacklist_%s' % user_id
blacklist = kv.get_list(blacklist_key)
if str(g.user.user_id) in blacklist:
      # flash(u'對方拒絕被你加好友!')
      return redirect(url_for('profile', user_id=user_id, list=1))
user = User.query.filter_by(user_id=user_id).first()
if user:
      if g.user.is_following(user):
        return redirect(url_for('profile', user_id=user_id))
      else:
          # 用戶是否在blacklist中
          blacklist_key = 'blacklist_%s' % g.user.user_id
          blacklist = kv.get_list(blacklist_key)
    # 取消拉黑
    if blacklist is not None and str(user_id) in blacklist:
          blacklist.remove(str(user_id))
          kv.set_list(blacklist_key, blacklist)
...
# -*- coding: utf-8 -*-
__author__ = 'SkyWay'

import sae
import json
import sae.kvdb

class KvdbStorage():
    # 初始化kvdb
    def __init__(self):
        self.kv = sae.kvdb.KVClient()

    # 獲取value
    def get_value(self, key):
        return self.kv.get(key)

    # 獲取dict_value
    def get(self, key):
        string_value = self.kv.get(key)
        if string_value is None:
            return None
        return decode_dict(string_value)

    # 設置value
    def set_value(self, key, value):
        self.kv.set(key, value)

    # 設置dict_value
    def set(self, key, dict_value):
        string_value = encode_dict(dict_value)
        self.kv.set(key, string_value)

    # 設置tuple_list
    def set_list(self, key, list_value):
        string_value = encode_list(list_value)
        self.kv.set(key, string_value)

    # 獲取list
    def get_list(self, key):
        string_value = self.kv.get(key)
        if string_value is None:
            return None
        return decode_list(string_value)

    # 批量獲取key
    def getkeys_by_prefix(self, prefix):
        return list(self.kv.getkeys_by_prefix(prefix, limit=100, marker=None))

    # 刪除key
    def delete(self, key):
        self.kv.delete(key)

# 編碼字典
def encode_dict(my_dict):
    return "\x1e".join("%s\x1f%s" % x for x in my_dict.iteritems())

# 解碼字典
def decode_dict(my_string):
    return dict(x.split("\x1f") for x in my_string.split("\x1e"))

# 編碼list
def encode_list(my_list):
    return "\x1e".join(str(x) for x in my_list)

# 解碼list
def decode_list(my_string):
    return list(my_string.split("\x1e"))

至於編碼、解碼爲何用\x1e\x1f和爲何最終鏈接成字符串,可參考SAE在kvdb保存數據的格式比較:json、pickle、string

Shutdown

策略其實已經差很少,固然,其實還應該不容許拉黑者給被拉黑者發送私信,可是好像也沒什麼必要,再說吧;還有拉黑超過次數發送郵件提醒管理員,其實不太科學,拉黑並不表明有不良信息或操做,因此要二次審覈。之因此沒有作舉報,一個是減小對用戶的迷惑性,而且常常經過系統帳號和用戶發消息,用戶也能夠經過私信來進行舉報。

實現方式可能還有改進的地方,之後慢慢改進,好比加入私信的等級,用戶對系統帳號的反饋級別較高會郵件提醒,在我的主頁增長舉報項等等。

Night!

相關文章
相關標籤/搜索