Merge remote-tracking branch 'bot/master'
This commit is contained in:
commit
b057efd47d
111
bot.py
Executable file
111
bot.py
Executable 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()
|
|
@ -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())
|
||||||
|
|
6
setup.py
6
setup.py
|
@ -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)
|
||||||
|
|
|
@ -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
57
strings.py
Normal 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.'''
|
|
@ -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))
|
||||||
|
|
Loading…
Reference in a new issue