拉黑后端實(shí)現(xiàn)

此處輸入圖片的描述
此處輸入圖片的描述

社區(qū)妹子強(qiáng)烈需要拉黑功能芥玉,結(jié)果剛上線,妹子就被拉黑了…這是個(gè)悲傷的故事…

初衷

對于種種原因不想再理會的人急迂,可以刪除私信時(shí)選擇拉黑影所。拉黑后,拉黑者取消關(guān)注對方僚碎,刪除私信猴娩,不在接收對方私信。被拉黑者收到系統(tǒng)消息提示被拉黑勺阐,如果是惡意卷中、不良信息則超過一定次數(shù)被禁號,但是保留被拉黑之前所有狀態(tài)渊抽,包括關(guān)注蟆豫、私信,但是再次發(fā)送私信時(shí)提示私信被對方拒絕接收懒闷,再次關(guān)注提示對方拒絕被你加關(guān)注十减。唯一解除拉黑的手段,拉黑方再次關(guān)注對方則自動取消拉黑毛雇。

之所以保留狀態(tài)嫉称,是為了盡量減少用戶被拉黑的感知,但是又會收到系統(tǒng)提醒灵疮,相互矛盾织阅。

策略

  • 刪除私信時(shí)勾選拉黑:把對方加入自己blacklist列表中,統(tǒng)計(jì)數(shù)據(jù)震捣,取消關(guān)注荔棉,刪除私信會話。
  • 進(jìn)入主頁:返回拉黑數(shù)據(jù)蒿赢,點(diǎn)擊關(guān)注時(shí)則根據(jù)是否被拉黑進(jìn)行提示润樱。(更優(yōu)方式:點(diǎn)擊關(guān)注時(shí)后臺判斷是否被拉黑,拉黑則拒絕該請求羡棵,否則正常關(guān)注)
  • 被拉黑者發(fā)送私信:進(jìn)入私信頁面返回拉黑數(shù)據(jù)壹若,已被拉黑則發(fā)送消息時(shí)直接提示私信被對方拒絕接收,如果中途被拉黑后臺會主動判斷blacklist而提示私信被對方拒絕接收皂冰。(更優(yōu)方式:開始不傳遞拉黑數(shù)據(jù)店展,發(fā)送私信時(shí)后臺判斷提示)

上面也提到了更優(yōu)辦法,其實(shí)可以減少查詢次數(shù)秃流,但是最終沒用赂蕴,還是考慮到體驗(yàn)的問題,blacklist是使用kv存儲的舶胀,后臺查詢比客戶端請求快概说,kv費(fèi)用消耗低碧注。所以每次查詢數(shù)據(jù)附帶后傳到前端,絕大多數(shù)情況用戶點(diǎn)擊就有提示糖赔,而不存在網(wǎng)絡(luò)延時(shí)萍丐。

Coding Time

  • 刪除私信時(shí)勾選拉黑
# kvdb設(shè)置統(tǒng)計(jì)user被拉黑數(shù)量
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)
        # 拉黑次數(shù)超過一定次數(shù)則發(fā)送郵件提醒
        if blackcount >= 5:
            print 'blacklist-email'
            # 創(chuàng)建一個(gè)假用戶
            null_user = User()
            null_user.nickname = user.nickname
            null_user.email = user.user_id
            null_user.password = blackcount
            content = u"您在社區(qū)的賬戶信息如下:"
            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):
    # 禁止拉黑系統(tǒng)賬號
    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:
        # 是否已經(jīng)被拉黑
        if str(user.user_id) in blacklist:
            return 0
        else:
            blacklist.append(user.user_id)
            kv.set_list(key, blacklist)
    return 1
# 消息發(fā)送
@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)
            # 取消關(guān)注
            unfollow(user_id)
            # 發(fā)送系統(tǒng)私信
            sys_user = User.query.get(100)
            content = u"系統(tǒng)消息:你已經(jīng)被拉黑!惡意使用且被拉黑超過限定次數(shù)的賬號將被禁用放典。"
            sys_msg(sys_user, user, content)
            content = u"系統(tǒng)消息:你已拉黑%s碉纺!惡意使用且被拉黑超過限定次數(shù)的賬號將被禁用。" % user.nickname
            sys_msg(sys_user, g.user, content)
            # 拉黑數(shù)據(jù)統(tǒng)計(jì)
            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'
    ...
    # 進(jìn)入私信判斷是否在對方黑名單中
    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
    # 是否是系統(tǒng)賬號
    isSystem = 1 if user.id == 100 else 0
    return render_template("msg_content.html", title=u'私信', messages=messages, user=user, inBlacklist=inBlacklist, isSystem=isSystem)
  • 被拉黑者發(fā)送私信
...
# 提交數(shù)據(jù)
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'
...
  • 訪問主頁和取消拉黑
# 在對方blacklist中則拒絕關(guān)注請求
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)

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

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

    # 設(shè)置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保存數(shù)據(jù)的格式比較:json舱呻、pickle醋火、string

Shutdown

策略其實(shí)已經(jīng)差不多,當(dāng)然箱吕,其實(shí)還應(yīng)該不允許拉黑者給被拉黑者發(fā)送私信芥驳,但是好像也沒什么必要,再說吧茬高;還有拉黑超過次數(shù)發(fā)送郵件提醒管理員兆旬,其實(shí)不太科學(xué),拉黑并不代表有不良信息或操作怎栽,所以要二次審核丽猬。之所以沒有做舉報(bào),一個(gè)是減少對用戶的迷惑性熏瞄,并且經(jīng)常通過系統(tǒng)賬號和用戶發(fā)消息脚祟,用戶也可以通過私信來進(jìn)行舉報(bào)。

實(shí)現(xiàn)方式可能還有改進(jìn)的地方强饮,以后慢慢改進(jìn)由桌,比如加入私信的等級,用戶對系統(tǒng)賬號的反饋級別較高會郵件提醒邮丰,在個(gè)人主頁增加舉報(bào)項(xiàng)等等行您。

Night!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市柠座,隨后出現(xiàn)的幾起案子邑雅,更是在濱河造成了極大的恐慌,老刑警劉巖妈经,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淮野,死亡現(xiàn)場離奇詭異捧书,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)骤星,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門经瓷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人洞难,你說我怎么就攤上這事舆吮。” “怎么了队贱?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵色冀,是天一觀的道長。 經(jīng)常有香客問我柱嫌,道長锋恬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任编丘,我火速辦了婚禮与学,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嘉抓。我一直安慰自己索守,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布抑片。 她就那樣靜靜地躺著卵佛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蓝丙。 梳的紋絲不亂的頭發(fā)上级遭,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音渺尘,去河邊找鬼挫鸽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鸥跟,可吹牛的內(nèi)容都是我干的丢郊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼医咨,長吁一口氣:“原來是場噩夢啊……” “哼枫匾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拟淮,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤干茉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后很泊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體角虫,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沾谓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了戳鹅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片均驶。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖枫虏,靈堂內(nèi)的尸體忽然破棺而出妇穴,到底是詐尸還是另有隱情,我是刑警寧澤隶债,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布腾它,位于F島的核電站,受9級特大地震影響死讹,放射性物質(zhì)發(fā)生泄漏携狭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一回俐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧稀并,春花似錦仅颇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至引颈,卻和暖如春耕皮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蝙场。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工凌停, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人售滤。 一個(gè)月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓罚拟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親完箩。 傳聞我的和親對象是個(gè)殘疾皇子赐俗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 點(diǎn)擊查看原文 Web SDK 開發(fā)手冊 SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個(gè)完善的 IM 系統(tǒng)...
    layjoy閱讀 13,768評論 0 15
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)弊知,斷路器阻逮,智...
    卡卡羅2017閱讀 134,660評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件秩彤、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,105評論 4 62
  • 今天狀態(tài)似乎不是很好叔扼,工作中容易出錯(cuò)事哭。 下班回到家里感覺很累很困,想要休息币励。 索性在床上睡了會慷蠕,迷迷糊糊過了半小時(shí)...
    雪碧君阿歐尼醬閱讀 366評論 0 0