Merge remote-tracking branch 'bot/master'

This commit is contained in:
Klaus-Uwe Mitterer 2017-03-17 22:30:19 +01:00
commit b057efd47d
6 changed files with 241 additions and 5 deletions

111
bot.py Executable file
View file

@ -0,0 +1,111 @@
#!/usr/bin/env python3
import ast, dbtools, logging, setuptools, strings, telegram.ext, twitools, tweepy
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)
def log(bot, update, error):
logger.warn("Error %s caused by '%s'" % (error, update))
updater = telegram.ext.Updater(token=setuptools.token())
def noauth(update):
update.message.reply_text(strings.noauth)
def start(bot, update):
update.message.reply_text(strings.start % (setuptools.botname(), setuptools.botname()))
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(strings.auth % auth.get_authorization_url())
dbtools.dbHelper().storeToken(cid, auth.request_token)
else:
update.message.reply_text(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(strings.verify)
except Exception as e:
dbtools.dbHelper().deleteUser(update.message.chat_id)
update.message.reply_text(strings.verifyfail)
else:
update.message.reply_text(strings.verifyimp)
def unauth(bot, update):
dbtools.dbHelper().deleteUser(update.message.chat_id)
update.message.reply_text(strings.unauth % setuptools.url())
def fish(bot, update):
dbtools.dbHelper().addFish(update.message.chat_id)
update.message.reply_text("Yummy! Thanks! :3")
def explicitTweet(bot, update, args):
two = twitools.twoBotHelper(update.message.chat_id)
two.tweet(' '.join(args))
def tweet(bot, update):
try:
if dbtools.dbHelper().getTStatus(update.message.chat_id):
explicitTweet(bot, update, [update.message.text])
except:
noauth(update)
def timeline(bot, update, args = [10]):
try:
count = int(args[0])
except:
count = 10
two = twitools.twoBotHelper(update.message.chat_id)
for status in two.api.home_timeline(count=count):
update.message.reply_text("%s (%s) at %s: %s" % (status.author.name, status.author.screen_name, status.created_at, status.text))
def toggleTweet(bot, update):
try:
update.message.reply_text(strings.toggleTweet % ("on" if dbtools.dbHelper().toggleTweet(update.message.chat_id) else "off"))
except:
noauth(update)
def unknown(bot, update):
update.message.reply_text("Sorry, I didn't understand that command.")
def test(bot, update, args):
print(args)
unknown(bot, update)
updater.dispatcher.add_handler(telegram.ext.CommandHandler("auth", auth))
updater.dispatcher.add_handler(telegram.ext.CommandHandler("fish", fish))
updater.dispatcher.add_handler(telegram.ext.CommandHandler("help", start))
updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start))
updater.dispatcher.add_handler(telegram.ext.CommandHandler("test", test, pass_args=True))
updater.dispatcher.add_handler(telegram.ext.CommandHandler("timeline", timeline))
updater.dispatcher.add_handler(telegram.ext.CommandHandler("toggletweet", toggleTweet))
updater.dispatcher.add_handler(telegram.ext.CommandHandler("tweet", explicitTweet, pass_args=True))
updater.dispatcher.add_handler(telegram.ext.CommandHandler("unauth", unauth))
updater.dispatcher.add_handler(telegram.ext.CommandHandler("verify", verify, pass_args=True))
updater.dispatcher.add_handler(telegram.ext.MessageHandler(telegram.ext.Filters.text, tweet))
updater.dispatcher.add_handler(telegram.ext.MessageHandler(telegram.ext.Filters.command, unknown))
updater.dispatcher.add_error_handler(log)
updater.start_polling()
updater.idle()

View file

@ -108,6 +108,52 @@ class dbObject:
pass pass
return False return False
def deleteUser(self, cid):
self.executeQuery("DELETE FROM tokens WHERE cid = %i;" % int(cid))
self.commit()
def storeUser(self, cid, ato, ase):
self.executeQuery("DELETE FROM tokens WHERE cid = %i;" % int(cid))
self.executeQuery("INSERT INTO tokens(cid, ato, ase) VALUES(%i, '%s', '%s');" % (int(cid), ato, ase))
self.commit()
def ato(self, cid):
try:
self.executeQuery("SELECT ato FROM tokens WHERE cid = %i;" % int(cid))
return self.cur.fetchone()[0]
except:
return False
def ase(self, cid):
try:
self.executeQuery("SELECT ase FROM tokens WHERE cid = %i;" % int(cid))
return self.cur.fetchone()[0]
except:
return False
def getTStatus(self, cid):
try:
self.executeQuery("SELECT tweet FROM tokens WHERE cid = %i;" % int(cid))
return True if int(self.cur.fetchone()[0]) == 1 else False
except:
raise ValueError("No such user: %i" % int(cid))
def toggleTweet(self, cid):
self.executeQuery("UPDATE tokens SET tweet = NOT tweet WHERE cid = %i;" % int(cid))
self.commit()
return self.getTStatus(cid)
def addFish(self, cid):
self.executeQuery("UPDATE tokens SET fish = fish + 1 WHERE cid = %i;" % int(cid))
self.commit()
def storeToken(self, cid, ato):
self.executeQuery('INSERT INTO tokens(cid, ato) VALUES(%i, "%s");' % (int(cid), ato))
self.commit()
def dbHelper(): def dbHelper():
if setuptools.dbtype() == SQLITE: if setuptools.dbtype() == SQLITE:
return dbObject(dbtype=SQLITE, path=setuptools.dbpath()) return dbObject(dbtype=SQLITE, path=setuptools.dbpath())

View file

@ -64,7 +64,7 @@ if not db.isInitialized():
db.executeQuery("CREATE TABLE names(`id` TEXT NOT NULL, `name` TEXT NOT NULL, `since` INTEGER NOT NULL, `until` INTEGER, PRIMARY KEY(id, until));") db.executeQuery("CREATE TABLE names(`id` TEXT NOT NULL, `name` TEXT NOT NULL, `since` INTEGER NOT NULL, `until` INTEGER, PRIMARY KEY(id, until));")
db.executeQuery("CREATE TABLE retweets(id INT PRIMARY KEY, author VARCHAR(30), created_at VARCHAR(30), text TEXT);") db.executeQuery("CREATE TABLE retweets(id INT PRIMARY KEY, author VARCHAR(30), created_at VARCHAR(30), text TEXT);")
db.executeQuery("CREATE TABLE lyrics(id INTEGER PRIMARY KEY AUTOINCREMENT, text VARCHAR(140) NOT NULL, ref INT NOT NULL default '0', tweet_id INT, active BOOLEAN default '0');") db.executeQuery("CREATE TABLE lyrics(id INTEGER PRIMARY KEY AUTOINCREMENT, text VARCHAR(140) NOT NULL, ref INT NOT NULL default '0', tweet_id INT, active BOOLEAN default '0');")
db.executeQuery("CREATE TABLE tokens(`cid` INT PRIMARY KEY, `ato` TEXT, `ase` TEXT, `tweet` BOOLEAN DEFAULT 1, `fish` INT DEFAULT 0);")
db.commit() db.commit()
db.closeConnection() db.closeConnection()
@ -75,8 +75,8 @@ print('''We are going to need a consumer key and consumer secret for accessing T
If you don't have this yet, go to apps.twitter.com and create a new application. This If you don't have this yet, go to apps.twitter.com and create a new application. This
application will need read/write access as well as access to direct messages.''') application will need read/write access as well as access to direct messages.''')
cke = input("Consumer key: ") cke = input("Your Twitter application's consumer key: ")
cse = input("Consumer secret: ") cse = input("Your Twitter application's consumer secret: ")
config.set("Twitter", "cke", cke) config.set("Twitter", "cke", cke)
config.set("Twitter", "cse", cse) config.set("Twitter", "cse", cse)

View file

@ -8,7 +8,6 @@ class SetupException(Exception):
def __str__(self): def __str__(self):
return "Seems like config.cfg has not been created yet or contains serious errors. Run setup.py to create it." return "Seems like config.cfg has not been created yet or contains serious errors. Run setup.py to create it."
def getSetting(section, setting, path = "config.cfg"): def getSetting(section, setting, path = "config.cfg"):
config = configparser.RawConfigParser() config = configparser.RawConfigParser()
config.read(path) config.read(path)
@ -89,6 +88,25 @@ def ase(section = TWITTER):
except: except:
raise SetupException() raise SetupException()
def botname():
try:
return getSetting("Telegram", "botname")
except:
return SetupException()
def token():
try:
return getSetting("Telegram", "token")
except:
return SetupException()
def url():
try:
return getSetting("Bot", "url")
except:
return SetupExecption()
def dbCheck(db, create = False): def dbCheck(db, create = False):
if (not create and dbInitialized(db)) or (create and not dbInitialized(db)): if (not create and dbInitialized(db)) or (create and not dbInitialized(db)):
return True return True

57
strings.py Normal file
View file

@ -0,0 +1,57 @@
auth = '''To get authenticated with Twitter, please visit this URL and sign in:
* %s
You will receive a six-digit PIN. Please send it to me like this:
* /verify 123456'''
authimp = '''I can't currently start a new authentication process for you as you are either already authenticated or an authentication process has been started.
Please unauthenticate using /unauth first if you are sure you want to re-authenticate.'''
noauth = '''You are not authenticated. Please use /auth to sign in with Twitter.'''
start = '''Hey there!
I'm @%s, everybody's favorite Twitter bot on Telegram!
For me to help you, you will first have to authenticate with Twitter:
* /auth
After authentication, you will be able to tweet from your account. Just drop me a note!
Additionally, you will be able to use the following commands:
* /toggletweet - Turn automatic tweeting of messages on/off. Useful in groups.
* /tweet TEXT - Explicitly tweet TEXT even if automatic tweeting is off (/toggletweet).
* /unauth - Revoke your authenticaton and stop using %s.
Have fun!'''
toggleTweet = '''Automatic tweeting is now %s.'''
unauth = '''You're leaving already? :(
I hope you had a good time with me. If there is anything you would like to tell me or my developers, please drop us a note at:
* %s
Your data has been deleted. Of course, you can always just re-authenticate using /auth.
It was great having you here. So long, and thanks for all the /fish!'''
verify = '''Thanks for authenticating. You can now use all of my features!'''
verifyfail = '''Oops, something went wrong during the authentication. Please try again:
* /auth'''
verifyimp = '''There is not currently an authentication process running for you. You may already be logged in, or you have not yet sent me an /auth command.'''

View file

@ -1,4 +1,4 @@
import tweepy, setuptools import dbtools, tweepy, setuptools
class twObject: class twObject:
@ -69,3 +69,7 @@ def twoHelper(section = setuptools.TWITTER):
def tweet(text, ref = 0, section = setuptools.TWITTER): def tweet(text, ref = 0, section = setuptools.TWITTER):
return twoHelper(section).tweet(text, ref) return twoHelper(section).tweet(text, ref)
def twoBotHelper(cid):
db = dbtools.dbHelper()
return twObject(ato = db.ato(cid), ase = db.ase(cid))