Search
Write a publication
Pull to refresh

Антиспам для Skype

Некоторое время назад случилось так, что пользоваться скайпом стало практически невозможно — спам-боты стучались один за другим. Неприятным фактом стало то, что в клиенте нет (до сих пор, впрочем) никакой предусмотренной функции антиспама, вроде контрольного вопроса или ещё чего-нибудь.

Нет — будет. На сайте обнаружился какой-никакой, а ассортимент wrapper'ов к API. Выбор пал на Python, ибо ничего масштабного не требовалось, а «import antigravity» только радовало. В процессе отладки скрипта было замечено несколько косяков в API. Оные были заботливо подпёрты костылями. Итак:

import Skype4Py
from time import sleep
skype = Skype4Py.Skype()
TRYING = 1
TEXT = {
¬'QUESTION':"Hello. It's antispam bot. Answer, 2+2=? One figure, please. You have %i trying." % (TRYING),
¬'ANSWER':"4",
¬'WIN':"Right. I'll write you soon.",
¬'AGAIN':"Try one more time.",
¬'FAIL':"Autoignoring.",
¬'INSTANT_BAN':"Autoignoring due to banned word in the authorization request or in the name."
}
BANNED = {
¬'WORDS':("http", "www"),
¬'NAMES':("")
}
HIDE_MESSAGES_AFTER_WRONG_ANSWER = True # True may cause loss of the new answers
REFRESH_DELAY = 30 # in seconds
GET_NAME_DELAY = 1.5
queue = {}

def answer_received(msg, status):
¬username = msg._GetSender()._GetHandle()
¬if username in queue.keys():
¬¬if status==Skype4Py.cmsReceived:
¬¬¬if msg._GetBody()!=TEXT['ANSWER']:
¬¬¬¬if HIDE_MESSAGES_AFTER_WRONG_ANSWER:
¬¬¬¬¬skype.UnregisterEventHandler('MessageStatus', answer_received)
¬¬¬¬¬for eachMsg in msg._GetChat()._GetRecentMessages():
¬¬¬¬¬¬try:
¬¬¬¬¬¬¬eachMsg.MarkAsSeen()
¬¬¬¬¬¬except:
¬¬¬¬¬¬¬continue
¬¬¬¬¬skype.RegisterEventHandler('MessageStatus', answer_received)
¬¬¬¬queue[username] = queue[username]-1
¬¬¬¬if queue[username]:
¬¬¬¬¬skype.SendMessage(username, TEXT['AGAIN'])
¬¬¬¬¬return
¬¬¬¬else:
¬¬¬¬¬del queue[username]
¬¬¬¬¬skype.SendMessage(username, TEXT['FAIL'])
¬¬¬¬¬msg._GetSender()._SetIsBlocked(True)
¬¬¬else:
¬¬¬¬del queue[username]
¬¬¬¬skype.SendMessage(username, TEXT['WIN'])
¬¬¬if len(queue)==0:
¬¬¬¬skype.UnregisterEventHandler('MessageStatus', answer_received)

def hasBanned(txtstr, target):
¬for word in BANNED[target]:
¬¬if word in txtstr:
¬¬¬return True
¬return False

def auth_received(from_user):
¬newUsers = skype._GetUsersWaitingAuthorization()
¬if not newUsers:
¬¬for key in queue.keys():
¬¬¬del queue[key]
¬¬return
¬for user in newUsers:
¬¬username = user._GetHandle()
¬¬if not (username in queue.keys()):
¬¬¬if TRYING < 1:
¬¬¬¬skype.SendMessage(username, TEXT['FAIL'])
¬¬¬¬user._SetIsBlocked(True)
¬¬¬¬continue
¬¬¬if hasBanned(user._GetReceivedAuthRequest(), 'WORDS'):
¬¬¬¬skype.SendMessage(username, TEXT['INSTANT_BAN'])
¬¬¬¬user._SetIsBlocked(True)
¬¬¬¬continue
¬¬¬skype.RegisterEventHandler('MessageStatus', answer_received)
¬¬¬skype.SendMessage(username, TEXT['QUESTION'])
¬¬¬queue[username] = TRYING
¬¬¬sleep(GET_NAME_DELAY)
¬¬¬if hasBanned(user._GetFullName(), 'NAMES'): # Skype's bug: full name is available only after message sending
¬¬¬¬del queue[username]
¬¬¬¬skype.SendMessage(username, TEXT['INSTANT_BAN'])
¬¬¬¬user._SetIsBlocked(True)
¬¬¬¬if len(queue)==0:
¬¬¬¬¬skype.UnregisterEventHandler('MessageStatus', answer_received)
¬¬¬¬continue

skype.RegisterEventHandler('UserAuthorizationRequestReceived', auth_received)
# В принципе следующий цикл не обязателен, но тогда при перезапуске скайпа придётся перезапускать и скрипт. И именно в такой последовательности.
while True:
¬skype.Attach()
¬auth_received(None)
¬sleep(REFRESH_DELAY)


¬ следует автозаменить на табуляцию, так вот глупо и неудобно определяется вложенность...
Затем сие сохраняется в файл с расширением .pyw и крутится в фоне.

P.S. К счастью, волна спама давно поутихла, но вдруг кому-то пригодится.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.