stampy/plugin/forward.py
#!/usr/bin/env python
# encoding: utf-8
#
# Description: Plugin for forwarding messages
# Author: Pablo Iranzo Gomez (Pablo.Iranzo@gmail.com)
import json
import logging
from time import sleep
import requests
from prettytable import from_db_cursor
import stampy.plugin.config
import stampy.stampy
from stampy.i18n import _
from stampy.i18n import _L
def init():
"""
Initializes module
:return: List of triggers for plugin
"""
triggers = ["^/forward"]
return triggers
def run(message): # do not edit this line
"""
Executes plugin
:param message: message to run against
:return:
"""
logger = logging.getLogger(__name__)
msgdetail = stampy.stampy.getmsgdetail(message)
text = msgdetail["text"]
if text:
if text.split()[0].lower()[0:8] == "/forward":
logger.debug(msg=_L("Processing forward commands"))
forwardcommands(message)
return
def help(message): # do not edit this line
"""
Returns help for plugin
:param message: message to process
:return: help text
"""
commandtext = ""
if stampy.stampy.is_owner(message):
commandtext = _("Use `/forward <source>=<target>` to assign a forwarder\n")
commandtext += _("Use `/forward list` to list forwards defined\n")
commandtext += _("Use `/forward delete <source>=<target>` to remove a forwarding\n\n")
return commandtext
def doforward(message, target):
"""
Forwards a message target chatid
:param message: Message to process (containing all details)
:param target: Target chat_id
:return:
"""
logger = logging.getLogger(__name__)
msgdetail = stampy.stampy.getmsgdetail(message)
chat_id = msgdetail["chat_id"]
message_id = msgdetail["message_id"]
url = "%s%s/forwardMessage" % (stampy.plugin.config.config(key="url"),
stampy.plugin.config.config(key='token'))
forwardmessageurl = "%s?chat_id=%s&from_chat_id=%s&message_id=%s" % (url, target, chat_id, message_id)
code = False
attempt = 0
exitcode = 0
while not code:
# It this is executed as per unit testing, skip sending message
UTdisable = not stampy.plugin.config.config(key='unittest', default=False)
if UTdisable:
output = json.loads(requests.get(forwardmessageurl).text)
result = {"message": output['result']}
code = output['ok']
else:
code = True
result = ""
logger.error(msg=_L("ERROR (%s) forwarding message: Code: %s : Text: %s") % (attempt, code, result))
if code == 'False' or not code:
if result['error_code'] == 403 and result['description'] == u'Forbidden: bot was blocked by the user':
# User hasn't initiated or has blocked direct messages from bot
attempt = 60
exitcode = 'blocked'
if result['error_code'] == 400 and result['description'] == u'Bad Request: message to forward not found':
# Message not found on chat
attempt = 60
exitcode = '0'
if result['error_code'] == 400 and result['description'] == u'Bad Request: chat not found':
# Message not found on chat
attempt = 60
exitcode = '0'
if result['error_code'] == 400 and result['description'] == u"Bad Request: message can't be forwarded":
# Message cannot be forwarded
attempt = 60
exitcode = '0'
attempt += 1
sleep(1)
# exit after 60 retries with 1 second delay each
if attempt > 60:
logger.error(msg=_L("PERM ERROR forwarding message: Code: %s : Text: %s") % (code, result))
code = True
logger.debug(msg=_L("forwarded message: Code: %s : message: %s") % (code, result))
return exitcode
def forwardmessage(message):
"""
Forwards a message based on id/chatid to target chatid
:param message: Message to process (contaning all details)
:return:
"""
logger = logging.getLogger(__name__)
# If forward plugin is enabled, process
forward = False
for i in stampy.stampy.plugs:
try:
if 'forward' in i.__name__:
forward = True
except:
continue
if forward:
msgdetail = stampy.stampy.getmsgdetail(message)
chat_id = msgdetail["chat_id"]
for target in getforward(source=chat_id):
doforward(message=message, target=target)
else:
logger.debug(msg=_L("Forward plugin not enabled, skipping"))
return
def forwardcommands(message):
"""
Processes forward commands in the message texts
:param message: Message to process
:return:
"""
msgdetail = stampy.stampy.getmsgdetail(message)
texto = msgdetail["text"]
chat_id = msgdetail["chat_id"]
message_id = msgdetail["message_id"]
who_un = msgdetail["who_un"]
logger = logging.getLogger(__name__)
logger.debug(msg=_L("Command: %s by %s") % (texto, who_un))
if stampy.stampy.is_owner(message):
logger.debug(msg=_L("Command: %s by Owner: %s") % (texto, who_un))
try:
command = texto.split(' ')[1]
except:
command = ""
try:
source = texto.split(' ')[2].lower()
except:
source = ""
for case in stampy.stampy.Switch(command):
if case('list'):
text = listforward(source)
stampy.stampy.sendmessage(chat_id=chat_id, text=text,
reply_to_message_id=message_id,
disable_web_page_preview=True,
parse_mode="Markdown")
break
if case('delete'):
word = texto.split(' ')[2]
if "=" in word:
source = word.split('=')[0]
target = texto.split('=')[1:][0]
text = _("Deleting forward for `%s -> %s`") % (source, target)
stampy.stampy.sendmessage(chat_id=chat_id, text=text,
reply_to_message_id=message_id,
disable_web_page_preview=True,
parse_mode="Markdown")
deleteforward(source=source, target=target)
break
if case():
word = command
if "=" in word:
source = word.split('=')[0]
target = texto.split('=')[1:][0]
text = _("Setting forward for `%s` to `%s`") % (source, target)
stampy.stampy.sendmessage(chat_id=chat_id, text=text,
reply_to_message_id=message_id,
disable_web_page_preview=True,
parse_mode="Markdown")
createforward(source=source, target=target)
return
def deleteforward(source, target):
"""
Deletes a pair from forward database
:param source: chat_id for source
:param target: chat_id for target
:return:
"""
logger = logging.getLogger(__name__)
sql = "DELETE FROM forward WHERE source='%s' AND target='%s';" % (source, target)
logger.debug(msg="rmforward: %s -> %s" % (source, target))
stampy.stampy.dbsql(sql)
return
def listforward(source=False):
"""
Lists the forwards defined for a source or all defined
:param source: chatid
:return: table with forwards defined
"""
logger = logging.getLogger(__name__)
if source:
# if source is provided, return the forwards for that source
string = (source,)
sql = "SELECT source,target FROM forward WHERE source='%s' ORDER by source ASC;" % string
cur = stampy.stampy.dbsql(sql)
target = cur.fetchone()
try:
# Get value from SQL query
target = target[1]
except:
# Value didn't exist before, return 0 value
target = ""
text = _("%s has a forward %s") % (source, target)
else:
sql = "SELECT source,target from forward ORDER BY source ASC;"
cur = stampy.stampy.dbsql(sql)
text = _("Defined forwards:\n")
table = from_db_cursor(cur)
text = "%s\n```%s```" % (text, table.get_string())
logger.debug(msg=text)
return text
def createforward(source, target):
"""
Creates a forward for specified source
:param source: chatid for source messages
:param target: chatid for destination messages
:return:
"""
logger = logging.getLogger(__name__)
if getforward(source) == target:
logger.error(msg=_L("createforward: circular reference %s=%s") % (source, target))
else:
sql = "INSERT INTO forward VALUES('%s','%s');" % (source, target)
logger.debug(msg=_L("createforward: %s=%s" % (source, target)))
stampy.stampy.dbsql(sql)
return
return False
def getforward(source):
"""
Get forwards for source if it's defined
:param source: chatid to search for
:return: target if existing or False if not
"""
logger = logging.getLogger(__name__)
string = (source,)
sql = "SELECT target FROM forward WHERE source='%s';" % string
cur = stampy.stampy.dbsql(sql)
rows = cur.fetchall()
for target in rows:
logger.debug(msg=_L("getforward: %s -> %s" % (source, target[0])))
yield target[0]