twitools/bottools/methods.py

331 lines
10 KiB
Python
Raw Normal View History

import ast, dbtools, html, io, logging, moviepy.editor, os, PIL.Image, random, re, setuptools, string, bottools.strings, sys, telegram.ext, telegram, time, twitools, twitools.streaming, urllib.request, tweepy
2017-03-22 00:53:51 +00:00
def getTwo(message):
try:
return twitools.twoBotHelper(message.chat_id)
except ValueError:
message.reply_text(bottools.strings.noauth)
except tweepy.error.TweepError as e:
raise
def twoExceptions(e, message):
text = {
32: bottools.strings.badToken,
36: bottools.strings.selfSpam,
64: bottools.strings.accountSuspended,
88: bottools.strings.rateLimit,
89: bottools.strings.badToken,
99: bottools.strings.badToken,
130: bottools.strings.overload,
131: bottools.strings.twitterError,
161: bottools.strings.followLimit,
185: bottools.strings.tweetLimit,
186: bottools.strings.longTweet,
187: bottools.strings.dupTweet,
205: bottools.strings.rateLimit,
226: bottools.strings.automatedTweet,
271: bottools.strings.selfMute,
272: bottools.strings.notMuted,
323: bottools.strings.multipleGIFs,
326: bottools.strings.accountLocked,
354: bottools.strings.longTweet
}.get(e.api_code)
message.reply_text(text or bottools.strings.twoFail)
# Actual methods:
# ---------------
def start(bot, update):
update.message.reply_text(bottools.strings.start % {"name": setuptools.botname()})
2017-03-22 00:53:51 +00:00
def fish(bot, update):
dbtools.dbHelper().addFish(update.message.chat_id)
update.message.reply_text(bottools.strings.fishThanks)
def getTweetID(tlid, cid):
try:
db = dbtools.dbHelper()
db.executeQuery("SELECT tid FROM timelines WHERE nr = %i AND cid = %i;" % (int(tlid), int(cid)))
return db.getNext()[0]
except Exception:
raise ValueError("No such tweet in timeline")
def toggleTweet(bot, update):
try:
update.message.reply_text(bottools.strings.toggleTweet % (bottools.strings.toggleTweetOn if dbtools.dbHelper().toggleTweet(update.message.chat_id) else bottools.strings.toggleTweetOff))
except tweepy.error.TweepError as e:
bottools.methods.twoExceptions(e, update.message)
def unknown(bot, update):
update.message.reply_text(bottools.strings.unknownCommand)
def makeMenu(buttons, columns):
return [buttons[i:i + columns] for i in range(0, len(buttons), columns)]
2017-03-22 00:53:51 +00:00
# Authentication process
def auth(bot, update):
db = dbtools.dbHelper()
cid = update.message.chat_id
if not (db.ato(cid) or db.ase(cid)):
auth = tweepy.OAuthHandler(setuptools.cke(), setuptools.cse())
update.message.reply_text(bottools.strings.auth % auth.get_authorization_url())
dbtools.dbHelper().storeToken(cid, auth.request_token)
else:
update.message.reply_text(bottools.strings.authimp)
def verify(bot, update, args):
db = dbtools.dbHelper()
cid = update.message.chat_id
if db.ato(cid) and not db.ase(cid):
auth = tweepy.OAuthHandler(setuptools.cke(), setuptools.cse())
auth.request_token = ast.literal_eval(db.ato(cid))
try:
auth.get_access_token(args[0])
dbtools.dbHelper().storeUser(cid, auth.access_token, auth.access_token_secret)
update.message.reply_text(bottools.strings.verify)
except Exception as e:
dbtools.dbHelper().deleteUser(update.message.chat_id)
update.message.reply_text(bottools.strings.verifyfail)
else:
update.message.reply_text(bottools.strings.verifyimp)
def unauth(bot, update):
dbtools.dbHelper().deleteUser(update.message.chat_id)
update.message.reply_text(bottools.strings.unauth % setuptools.url())
# User methods
def follow(bot, update, args):
try:
two = bottools.methods.getTwo(update.message)
for user in args:
two.api.create_friendship(screen_name = user)
except tweepy.error.TweepError as e:
bottools.methods.twoExceptions(e, update.message)
def unfollow(bot, update, args):
try:
two = bottools.methods.getTwo(update.message)
for user in args:
two.api.destroy_friendship(screen_name = user)
except tweepy.error.TweepError as e:
bottools.methods.twoExceptions(e, update.message)
# Tweet methods
def explicitTweet(bot, update, args, reply = None):
try:
two = bottools.methods.getTwo(update.message)
if update.message.photo or update.message.document or update.message.video or update.message.sticker:
fid = update.message.document.file_id if update.message.document else update.message.sticker.file_id if update.message.sticker else update.message.video.file_id if update.message.video else update.message.photo[-1].file_id
path = bot.getFile(fid).file_path
media = urllib.request.urlopen(path)
mobj = io.BytesIO(media.read())
filename = path.split("/")[-1]
if filename.split(".")[-1].lower() == "webp":
out = io.BytesIO()
PIL.Image.open(mobj).convert('RGB').save(out, format="JPEG")
filename = "%s.jpg" % filename.split(".")[0]
if update.message.document and filename.split(".")[-1].lower() == "mp4":
temp = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(32))
with open("tmp/%s.%s" % (temp, filename.split(".")[-1]), "wb") as f:
f.write(mobj.getvalue())
moviepy.editor.VideoFileClip("tmp/%s.%s" % (temp, filename.split(".")[-1])).resize(0.3).write_gif("tmp/%s.gif" % temp)
filename = "%s.gif" % temp
out = open("tmp/%s.gif" % temp, "rb")
else:
out = mobj
two.api.update_with_media(filename, update.message.caption, reply, file=out)
out.close()
else:
two.tweet(' '.join(args), reply)
except tweepy.error.TweepError as e:
bottools.methods.twoExceptions(e, update.message)
def reply(bot, update, args):
try:
reply = bottools.methods.getTweetID(args[0], update.message.chat_id)
two = bottools.methods.getTwo(update.message)
otweet = twitools.getTweet(reply)
sender = otweet.user.screen_name
if not ("@%s" % sender.strip("@")) in [("@%s" % a.strip("@")) for a in args]:
mentions = []
for m in re.split('[^\w@]+', otweet.text):
try:
if m[0] == "@":
mentions += [m]
except:
pass
for m in mentions:
if m in args or m =="@%s" % two.whoami().strip("@") or m == "@%s" % sender.strip("@"):
mentions.remove(m)
else:
mentions = []
if "@%s" % sender.strip("@") != "@%s" % two.whoami().strip("@"):
first = ["@%s" % sender.strip("@")]
else:
try:
first = [mentions[0]]
mentions.remove(mentions[0])
except:
first = [""]
pargs = first + args[1:] + mentions
2017-03-22 00:53:51 +00:00
except:
update.message.reply_text(bottools.strings.cantfind % args[0])
raise
2017-03-22 00:53:51 +00:00
bottools.methods.explicitTweet(bot, update, pargs, reply)
2017-03-22 00:53:51 +00:00
def retweet(bot, update, args):
for tweet in args:
try:
tid = bottools.methods.getTweetID(tweet, update.message.chat_id)
bottools.methods.getTwo(update.message).api.retweet(tid)
except ValueError:
update.message.reply_text(bottools.strings.cantfind % tweet)
except tweepy.error.TweepError as e:
bottools.methods.twoExceptions(e, update.message)
def like(bot, update, args):
for tweet in args:
try:
tid = bottools.methods.getTweetID(tweet, update.message.chat_id)
bottools.methods.getTwo(update.message).api.create_favorite(tid)
except ValueError:
update.message.reply_text(bottools.strings.cantfind % tweet)
except tweepy.error.TweepError as e:
bottools.methods.twoExceptions(e, update.message)
def tweet(bot, update):
try:
if dbtools.dbHelper().getTStatus(update.message.chat_id):
bottools.methods.explicitTweet(bot, update, [update.message.text])
except twepy.error.TweepError as e:
bottools.methods.twoExceptions(e, update.message)
# Timelines
def timeline(bot, update, args = [10]):
try:
count = int(args[0])
except:
count = 10
db = dbtools.dbHelper()
db.executeQuery("DELETE FROM timelines WHERE cid = %i;" % int(update.message.chat_id))
try:
i = 1
two = bottools.methods.getTwo(update.message)
for status in two.api.home_timeline(count=count):
db.executeQuery("INSERT INTO timelines VALUES(%i, %i, %i);" % (update.message.chat_id, i, status.id))
update.message.reply_text("Tweet %i:\n%s (@%s) at %s:\n%s" % (i, status.author.name, status.author.screen_name, status.created_at, html.unescape(status.text)))
i += 1
except tweepy.error.TweepError as e:
bottools.methods.twoExceptions(e, update.message)
db.commit()
2017-03-23 13:18:52 +00:00
# Streaming
2017-03-23 16:32:06 +00:00
2017-03-23 13:18:52 +00:00
mentionstreams = {}
2017-03-23 16:01:05 +00:00
def makeStream(bot, cid):
two = twitools.twoBotHelper(cid)
stream = tweepy.Stream(auth = two.auth, listener = twitools.streaming.BotStreamListener(bot, cid))
stream.filter(track=[two.whoami()], async=True)
return stream
try:
for u in dbtools.dbHelper().mentionsOn():
mentionstreams[u] = makeStream(telegram.Bot(token=setuptools.token()), u)
except Exception as e:
print(e)
2017-03-23 13:18:52 +00:00
def mentionstream(bot, update):
global mentionstreams
2017-03-23 16:01:05 +00:00
try:
dbtools.dbHelper().toggleMentions(update.message.chat_id)
if update.message.chat_id in mentionstreams:
mentionstreams.pop(update.message.chat_id).disconnect()
update.message.reply_text(bottools.strings.toggleMentions % bottools.strings.toggleTweetOff)
else:
mentionstreams[update.message.chat_id] = makeStream(bot, update.message.chat_id)
update.message.reply_text(bottools.strings.toggleMentions % bottools.strings.toggleTweetOn)
except tweepy.error.TweepError as e:
bottools.methods.twoExceptions(e, update.message)
2017-03-23 13:18:52 +00:00
# Admin interaction
def togglebroadcasts(bot, update):
try:
update.message.reply_text(bottools.strings.toggleBroadcasts % (bottools.strings.toggleTweetOn if dbtools.dbHelper().toggleBroadcasts(update.message.chat_id) else bottools.strings.toggleTweetOff))
except tweepy.error.TweepError as e:
bottools.methods.twoExceptions(e, update.message)
2017-03-23 12:05:48 +00:00
# Administrator
def isadmin(message):
two = bottools.methods.getTwo(message)
if two.whoami().strip("@") == setuptools.admin().strip("@"):
return True
return False
def restart(bot, update):
if bottools.methods.isadmin(update.message):
update.message.reply_text(bottools.strings.restart)
time.sleep(0.5)
os.execl(sys.executable, sys.executable, *sys.argv)
else:
bottools.methods.unknown(bot, update)
2017-03-23 16:01:05 +00:00
2017-03-23 16:32:06 +00:00
def broadcast(bot, update, args):
if bottools.methods.isadmin(update.message):
for u in dbtools.dbHelper().broadcastUsers():
try:
bot.sendMessage(chat_id = u, text = ' '.join(args))
except:
logging.exception("Could not send broadcast.")
else:
bottools.methods.unknown(bot, update)
def emergency(bot, update, args):
2017-03-23 16:32:06 +00:00
if bottools.methods.isadmin(update.message):
for u in dbtools.dbHelper().allUsers():
try:
bot.sendMessage(chat_id = u, text = ' '.join(args))
except:
logging.exception("Could not send emergency broadcast.")
2017-03-23 16:32:06 +00:00
else:
bottools.methods.unknown(bot, update)