From 9036a7bee78c9e0ca18dfec93901188e411d36fc Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Tue, 7 Feb 2017 22:36:31 +0100 Subject: [PATCH 01/31] Add dummy bot file --- bot.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 bot.py diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..066c83e --- /dev/null +++ b/bot.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + + From c4f0549d70d1ba622079c65f54cdd27a96fb37b1 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Tue, 7 Feb 2017 22:40:47 +0100 Subject: [PATCH 02/31] Copy over setuptools from twitools, add function for API token --- setuptools/__init__.py | 144 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 setuptools/__init__.py diff --git a/setuptools/__init__.py b/setuptools/__init__.py new file mode 100644 index 0000000..53674a4 --- /dev/null +++ b/setuptools/__init__.py @@ -0,0 +1,144 @@ +import configparser, csv, datetime, html.parser, itertools, os, sqlite3, sys, tweepy + +class SetupException(Exception): + def __str__(self): + 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"): + config = configparser.RawConfigParser() + config.read(path) + return config.get(section, setting) + +def dbtype(): + try: + return int(getSetting("Database", "type")) + except: + return 0 # for SQLite3 + +### Must only be called AFTER dbtype()! ### + +def dbhost(): + try: + return getSetting("Database", "host") + except: + raise SetupException() + +def dbuser(): + try: + return getSetting("Database", "user") + except: + raise SetupException() + +def dbpass(): + try: + return getSetting("Database", "pass") + except: + raise SetupException() + +def dbname(): + try: + return getSetting("Database", "name") + except: + raise SetupException() + +def dbpath(): + try: + return getSetting("Database", "path") + except: + return SetupException() + +### + +def token(): + try: + return getSetting("Telegram", "token") + except: + return SetupException() + +def cke(): + try: + return getSetting("Twitter", "cke") + except: + raise SetupException() + +def cse(): + try: + return getSetting("Twitter", "cse") + except: + raise SetupException() + +def ato(): + try: + return getSetting("Twitter", "ato") + except: + raise SetupException() + +def ase(): + try: + return getSetting("Twitter", "ase") + except: + raise SetupException() + +def dbCheck(db, create = False): + if (not create and dbInitialized(db)) or (create and not dbInitialized(db)): + return True + if create: + raise ValueError("Provided database file " + db.path + " is already initialized. Remove it manually before trying to recreate it.") + raise ValueError("Provided database file " + db.path + " is not initialized. Create it using makedb.py or csvdb.py") + + +def dbHelper(path, create = False): + db = dbObject(path) + dbCheck(db, create) + return db + + +def dbInitialized(db): + return db.isInitialized() + + +def fileExists(path): + return os.path.isfile(path) + + +def getDate(date): + try: + return datetime.datetime.strptime(date, '%Y-%m-%d') + except ValueError: + raise ValueError("Dates must be in YYYY-MM-DD format.") + + +def paginate(iterable, page_size): + while True: + i1, i2 = itertools.tee(iterable) + iterable, page = (itertools.islice(i1, page_size, None), list(itertools.islice(i2, page_size))) + if len(page) == 0: + break + yield page + + +def parseArgs(argv): + args = [] + path = None + nextpath = False + + for a in argv[1:]: + if nextpath: + path = a + nextpath = False + elif a == "-f": + if path != None: + raise ValueError("You can only pass one database file.") + nextpath = True + else: + args += [a] + + return args, path + +def printCSV(inlist): + writer = csv.writer(sys.stdout) + writer.writerows(inlist) + +def unescapeText(text): + return html.parser.HTMLParser().unescape(text).replace("'","''") + From 46449d800abe6199f87496788a48e7a411478171 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Tue, 7 Feb 2017 22:41:14 +0100 Subject: [PATCH 03/31] Add .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..56dc96b --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.swp +Database.db +__pycache__ +config.cfg From 33ade5451a5c99d921ecc627c0ba1efefd61422c Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Tue, 7 Feb 2017 22:54:22 +0100 Subject: [PATCH 04/31] First test bot --- bot.py | 9 +++++++++ 1 file changed, 9 insertions(+) mode change 100644 => 100755 bot.py diff --git a/bot.py b/bot.py old mode 100644 new mode 100755 index 066c83e..8ae7f4b --- a/bot.py +++ b/bot.py @@ -1,3 +1,12 @@ #!/usr/bin/env python3 +import logging, telegram.ext +updater = telegram.ext.Updater(token=setuptools.token) + +def start(bot, update): + bot.sendMessage(chat_id=update.message.chat_id, text="Heeeeeeey! :3") + +updater.dispatch.add_handler(telegram.ext.CommandHandler("start", start) + +updater.start_polling() From 67ef0e448dc52ba192464e82aa19de5297216749 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Tue, 7 Feb 2017 23:11:59 +0100 Subject: [PATCH 05/31] Fix some stuff --- bot.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/bot.py b/bot.py index 8ae7f4b..57c1fa1 100755 --- a/bot.py +++ b/bot.py @@ -1,12 +1,17 @@ #!/usr/bin/env python3 -import logging, telegram.ext +import logging, setuptools, telegram.ext -updater = telegram.ext.Updater(token=setuptools.token) +logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) + +updater = telegram.ext.Updater(token=setuptools.token()) def start(bot, update): - bot.sendMessage(chat_id=update.message.chat_id, text="Heeeeeeey! :3") + bot.sendMessage(chat_id=update.message.chat_id, text="Heeeeeeey! :3\n\nWelcome to the Boooooooooot!") -updater.dispatch.add_handler(telegram.ext.CommandHandler("start", start) +updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start)) -updater.start_polling() +try: + updater.start_polling() +except KeyboardInterrupt: + updater.stop() From e306b9fcc5085cd4e0f3d5d26165fdbc898ebabb Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 12:26:25 +0100 Subject: [PATCH 06/31] Move strings to strings.py --- bot.py | 8 ++++++-- strings.py | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 strings.py diff --git a/bot.py b/bot.py index 57c1fa1..896b859 100755 --- a/bot.py +++ b/bot.py @@ -1,15 +1,19 @@ #!/usr/bin/env python3 -import logging, setuptools, telegram.ext +import logging, setuptools, strings, telegram.ext logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) updater = telegram.ext.Updater(token=setuptools.token()) def start(bot, update): - bot.sendMessage(chat_id=update.message.chat_id, text="Heeeeeeey! :3\n\nWelcome to the Boooooooooot!") + bot.sendMessage(chat_id=update.message.chat_id, text=strings.start) + +def auth(bot, update): + bot.sendMessage(chat_id=update.message.chat_id, text="Ooops. Not implemented yet.") updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start)) +updater.dispatcher.add_handler(telegram.ext.CommandHandler("auth", auth)) try: updater.start_polling() diff --git a/strings.py b/strings.py new file mode 100644 index 0000000..024b1b3 --- /dev/null +++ b/strings.py @@ -0,0 +1,17 @@ +import setuptools + +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: + +* [Nothing yet. Sorry.] + +Have fun!''' From 1bbeeb3a0d568bbad4b16aa7ed8bb3207ce99f87 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 12:37:27 +0100 Subject: [PATCH 07/31] Copy over dbtools from twitools --- dbtools/__init__.py | 72 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 dbtools/__init__.py diff --git a/dbtools/__init__.py b/dbtools/__init__.py new file mode 100644 index 0000000..92f6699 --- /dev/null +++ b/dbtools/__init__.py @@ -0,0 +1,72 @@ +import setuptools +import sqlite3, pymysql, pymysql.cursors + +SQLITE = 0 +MYSQL = 1 +MARIADB = MYSQL + +MIN = 0 +MAX = 1 + +class dbObject: + +# --------------------------------------------- Initialization ------------------------------------------------- + + def initMySQL(self, host, port, user, pwd, db): + self.conn = pymysql.connect(host = host, port = port, user = user, password = pwd, db = db, charset = "utf8mb4", cursorclass = pymysql.cursors.DictCursor) + self.cur = self.conn.cursor() + self.dbtype = MYSQL + self.host = host + self.port = port + self.user = user + self.pwd = pwd + self.db = db + + def initSQLite(self, path): + self.conn = sqlite3.connect(path) + self.cur = self.conn.cursor() + self.dbtype = SQLITE + self.path = path + + def __init__(self, dbtype = SQLITE, path = None, host = None, port = None, user = None, pwd = None, db = None): + + if dbtype == SQLITE: + self.initSQLite(path or 'Database.db') + + elif dbtype == MYSQL: + self.initMySQL(host or 'localhost', port or 3306, user, pwd, db) + + else: + raise ValueError("Unknown database type %s." % str(dbtype)) + +# ---------------------------------------------- No more initialization ---------------------------------------- + + def closeConnection(self): + return self.conn.close() + + def commit(self): + return self.conn.commit() + + def executeQuery(self, query): + return self.cur.execute(query) + + def getAll(self): + return self.cur.fetchall() + + def getNext(self): + return self.cur.fetchone() + + def isInitialized(self): + try: + self.executeQuery("SELECT * FROM tokens") + return True + except: + return False + +def dbHelper(): + if setuptools.dbtype() == SQLITE: + return dbObject(dbtype=SQLITE, path=setuptools.dbpath()) + elif setuptools.dbtype() == MYSQL: + return dbObject(dbtype=MYSQL, host=setuptools.dbhost(), user=setuptools.dbuser(), pwd=setuptools.dbpass(), db=setuptools.dbname()) + else: + raise setuptools.SetupException() From 5c2c7d1a5e7a191a4c505f50823c8f8b88989180 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 12:39:53 +0100 Subject: [PATCH 08/31] ato/ase are not global variables --- setuptools/__init__.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 53674a4..47a1676 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -67,18 +67,6 @@ def cse(): except: raise SetupException() -def ato(): - try: - return getSetting("Twitter", "ato") - except: - raise SetupException() - -def ase(): - try: - return getSetting("Twitter", "ase") - except: - raise SetupException() - def dbCheck(db, create = False): if (not create and dbInitialized(db)) or (create and not dbInitialized(db)): return True From e2de6dac6a1923da2fdc918abba6fe02e3974bf8 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 12:49:05 +0100 Subject: [PATCH 09/31] Add functions to add/delete users and retrieve ato/ase from database --- dbtools/__init__.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/dbtools/__init__.py b/dbtools/__init__.py index 92f6699..4e6f3ad 100644 --- a/dbtools/__init__.py +++ b/dbtools/__init__.py @@ -63,6 +63,28 @@ class dbObject: except: 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("INSERT INTO tokens 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() + except: + return False + + def ase(self, cid): + try: + self.executeQuery("SELECT ase FROM tokens WHERE cid = %i;" % int(cid)) + return self.cur.fetchone() + except: + return False + def dbHelper(): if setuptools.dbtype() == SQLITE: return dbObject(dbtype=SQLITE, path=setuptools.dbpath()) From 8d56dc7ae3c7b728b77a9e8c3388f4629a36b770 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 13:06:17 +0100 Subject: [PATCH 10/31] Add unauth function --- bot.py | 8 ++++++-- setuptools/__init__.py | 12 ++++++++++++ strings.py | 12 +++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index 896b859..4f386e6 100755 --- a/bot.py +++ b/bot.py @@ -1,17 +1,21 @@ #!/usr/bin/env python3 -import logging, setuptools, strings, telegram.ext +import dbtools, logging, setuptools, strings, telegram.ext logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) updater = telegram.ext.Updater(token=setuptools.token()) def start(bot, update): - bot.sendMessage(chat_id=update.message.chat_id, text=strings.start) + bot.sendMessage(chat_id=update.message.chat_id, text=strings.start % (setuptools.botname, setuptools.botname)) def auth(bot, update): bot.sendMessage(chat_id=update.message.chat_id, text="Ooops. Not implemented yet.") +def unauth(bot, update): + dbtools.deleteUser(update.message.chat_id) + bot.sendMessage(chat_id=update.message.chat_id, text=strings.unauth % setuptools.url) + updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("auth", auth)) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 47a1676..e3ba12d 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -49,12 +49,24 @@ def dbpath(): ### +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 cke(): try: return getSetting("Twitter", "cke") diff --git a/strings.py b/strings.py index 024b1b3..d16c75f 100644 --- a/strings.py +++ b/strings.py @@ -12,6 +12,16 @@ After authentication, you will be able to tweet from your account. Just drop me Additionally, you will be able to use the following commands: -* [Nothing yet. Sorry.] +* /unauth - Revoke your authenticaton and stop using %s. Have fun!''' + +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!''' From 1900d516a947c26e2d7f1a6dacb4bcee53c5dc2f Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 13:06:58 +0100 Subject: [PATCH 11/31] Fix function calls --- bot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index 4f386e6..1b2c966 100755 --- a/bot.py +++ b/bot.py @@ -7,14 +7,14 @@ logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s updater = telegram.ext.Updater(token=setuptools.token()) def start(bot, update): - bot.sendMessage(chat_id=update.message.chat_id, text=strings.start % (setuptools.botname, setuptools.botname)) + bot.sendMessage(chat_id=update.message.chat_id, text=strings.start % (setuptools.botname(), setuptools.botname())) def auth(bot, update): bot.sendMessage(chat_id=update.message.chat_id, text="Ooops. Not implemented yet.") def unauth(bot, update): dbtools.deleteUser(update.message.chat_id) - bot.sendMessage(chat_id=update.message.chat_id, text=strings.unauth % setuptools.url) + bot.sendMessage(chat_id=update.message.chat_id, text=strings.unauth % setuptools.url()) updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("auth", auth)) From cfa2404bbb8cdce5f41fd927c1ef170d1c97ffbf Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 13:08:09 +0100 Subject: [PATCH 12/31] Add unauth handler --- bot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bot.py b/bot.py index 1b2c966..eeeee10 100755 --- a/bot.py +++ b/bot.py @@ -18,6 +18,7 @@ def unauth(bot, update): updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("auth", auth)) +updater.dispatcher.add_handler(telegram.ext.CommandHandler("unauth", unauth)) try: updater.start_polling() From 891eaf16276edac1c28e730e65e091b9d315a523 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 13:12:05 +0100 Subject: [PATCH 13/31] Fix function call --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index eeeee10..689f712 100755 --- a/bot.py +++ b/bot.py @@ -13,7 +13,7 @@ def auth(bot, update): bot.sendMessage(chat_id=update.message.chat_id, text="Ooops. Not implemented yet.") def unauth(bot, update): - dbtools.deleteUser(update.message.chat_id) + dbtools.dbHelper().deleteUser(update.message.chat_id) bot.sendMessage(chat_id=update.message.chat_id, text=strings.unauth % setuptools.url()) updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start)) From ca466277a5c573f862b1ad67dbb90499285a7ae8 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 13:17:14 +0100 Subject: [PATCH 14/31] Copy over setup.py from twitools --- setup.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100755 setup.py diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..a5e2df3 --- /dev/null +++ b/setup.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 + +import configparser, os.path, tweepy, dbtools, getpass + +if os.path.isfile("config.cfg"): + print("config.cfg already exists. Please remove it before running this script.") + exit(1) + +config = configparser.RawConfigParser() + +config.add_section('Database') + +print('''TweepBot will use a database for certain tasks. You can use a file or a MySQL database for this purpose. + +If you wish to use a MySQL database, you will need the credentials for it. If you don't know what any of that means, stick with the default value and just press Enter. +''') + +dbtype = input("Database type: %i (file), %i (MySQL) [%i]: " % (dbtools.SQLITE, dbtools.MYSQL, dbtools.SQLITE)) +print() + +try: + dbtype = int(dbtype) +except: + pass + +if dbtype == dbtools.MYSQL: + dbhost = input("MySQL host [localhost]: ") or "localhost" + dbuser = input("MySQL username [twitools]: ") or "twitools" + dbpass = getpass.getpass("MySQL password (not echoed!): ") + dbname = input("MySQL database name [twitools]: ") or "twitools" + print() + + config.set('Database', 'type', dbtype) + config.set('Database', 'host', dbhost) + config.set('Database', 'user', dbuser) + config.set('Database', 'pass', dbpass) + config.set('Database', 'name', dbname) + +else: + dbtype = dbtools.SQLITE + dbpath = input("Name of the database file [Database.db]: ") or "Database.db" + print() + + config.set('Database', 'type', dbtype) + config.set('Database', 'path', dbpath) + +if dbtype == dbtools.MYSQL: + db = dbtools.dbObject(dbtype=dbtype, host=dbhost, user=dbuser, pwd=dbpass, db=dbname) +else: + db = dbtools.dbObject(dbtype=dbtype, path=dbpath) +if not db.isInitialized(): + db.executeQuery("CREATE TABLE tokens(`cid` INT PRIMARY KEY, `ato` TEXT, `ase` TEXT, `fish` INT);") + db.commit() + +db.closeConnection() + +config.add_section("Twitter") + +cke = input("Your Twitter application's consumer key: ") +cse = input("Your Twitter application's consumer secret: ") + +config.set("Twitter", "cke", cke) +config.set("Twitter", "cse", cse) + +print("Seems like everything worked out fine. Let's write that config file...") + +with open('config.cfg', 'wt') as cfg: + config.write(cfg) + +print("We're all done. You can now use Twitools. Have fun!") From 4d5e5ac504f2a4636420fcc18a00a91e2ff9b42b Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 13:25:52 +0100 Subject: [PATCH 15/31] Add default value for fish --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a5e2df3..7a34ba0 100755 --- a/setup.py +++ b/setup.py @@ -49,7 +49,7 @@ if dbtype == dbtools.MYSQL: else: db = dbtools.dbObject(dbtype=dbtype, path=dbpath) if not db.isInitialized(): - db.executeQuery("CREATE TABLE tokens(`cid` INT PRIMARY KEY, `ato` TEXT, `ase` TEXT, `fish` INT);") + db.executeQuery("CREATE TABLE tokens(`cid` INT PRIMARY KEY, `ato` TEXT, `ase` TEXT, `fish` INT DEFAULT 0);") db.commit() db.closeConnection() From 33809c505d6f65feaa01e179ad2fe21962d0e9e5 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 14:09:00 +0100 Subject: [PATCH 16/31] Add /fish easter egg --- bot.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bot.py b/bot.py index 689f712..22e4dc2 100755 --- a/bot.py +++ b/bot.py @@ -16,9 +16,13 @@ def unauth(bot, update): dbtools.dbHelper().deleteUser(update.message.chat_id) bot.sendMessage(chat_id=update.message.chat_id, text=strings.unauth % setuptools.url()) +def fish(bot, update): + bot.sendMessage(chat_id=update.message.chat_id, text="Yummy! Thanks! :3") + updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("auth", auth)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("unauth", unauth)) +updater.dispatcher.add_handler(telegram.ext.CommandHandler("fish", fish)) try: updater.start_polling() From d8ea9a93a84d2dc78c5784905fc4aa5c1c0fb2f3 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 14:10:56 +0100 Subject: [PATCH 17/31] Copy over twitools from twitools --- twitools/__init__.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 twitools/__init__.py diff --git a/twitools/__init__.py b/twitools/__init__.py new file mode 100644 index 0000000..479e81d --- /dev/null +++ b/twitools/__init__.py @@ -0,0 +1,44 @@ +import tweepy, setuptools + +class twObject: + + def __init__(self, ato, ase, cke = setuptools.cke(), cse = setuptools.cse()): + self.auth = tweepy.OAuthHandler(cke, cse) + self.auth.set_access_token(ato, ase) + self.api = tweepy.API(self.auth) + + def retweet(self, id): + self.api.retweet(id) + + def delete(self, id): + self.api.destroy_status(id) + + def search(self, query, savepoint = 0): + tweets = list(tweepy.Cursor(self.api.search, q=query, since_id=savepoint).items()) + tweets.reverse() + return tweets + + def whoami(self): + return self.auth.get_username() + + def tweet(self, text, reply = 0): + return self.api.update_status(text, reply) + +def getFollowerIDs(two=twObject()): + ''' Returns 5,000 follower IDs at most ''' + for id in list(two.api.followers_ids(screen_name=twObject().whoami())): + yield int(id) + +def getFollowingIDs(two=twObject()): + for id in list(two.api.friends_ids(screen_name=twObject().whoami())): + yield int(id) + +def getNameByID(uid, two=twObject()): + return two.api.get_user(uid).screen_name + +def getNamesByIDs(fids=getFollowerIDs(), two=twObject()): + for page in setuptools.paginate(fids, 100): + followers = two.api.lookup_users(user_ids=page) + for follower in followers: + yield {"id": follower.id, "name": follower.screen_name} + From 955acb74b42ba0836f828d087d47a45393f6eba2 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 14:16:04 +0100 Subject: [PATCH 18/31] Improve signal handling --- bot.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bot.py b/bot.py index 22e4dc2..99975bd 100755 --- a/bot.py +++ b/bot.py @@ -24,7 +24,5 @@ updater.dispatcher.add_handler(telegram.ext.CommandHandler("auth", auth)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("unauth", unauth)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("fish", fish)) -try: - updater.start_polling() -except KeyboardInterrupt: - updater.stop() +updater.start_polling() +updater.idle() From 6beb8f61375b146b4ee8dcb3af580628ade33d8a Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 14:46:59 +0100 Subject: [PATCH 19/31] Implemented tweet handler, shorter reply call --- bot.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/bot.py b/bot.py index 99975bd..3511a7e 100755 --- a/bot.py +++ b/bot.py @@ -7,22 +7,26 @@ logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s updater = telegram.ext.Updater(token=setuptools.token()) def start(bot, update): - bot.sendMessage(chat_id=update.message.chat_id, text=strings.start % (setuptools.botname(), setuptools.botname())) + update.message.reply_text(strings.start % (setuptools.botname(), setuptools.botname())) def auth(bot, update): - bot.sendMessage(chat_id=update.message.chat_id, text="Ooops. Not implemented yet.") + update.message.reply_text("Ooops. Not implemented yet.") def unauth(bot, update): dbtools.dbHelper().deleteUser(update.message.chat_id) - bot.sendMessage(chat_id=update.message.chat_id, text=strings.unauth % setuptools.url()) + update.message.reply_text(strings.unauth % setuptools.url()) def fish(bot, update): - bot.sendMessage(chat_id=update.message.chat_id, text="Yummy! Thanks! :3") + update.message.reply_text("Yummy! Thanks! :3") + +def tweet(bot, update): + update.message.reply_text("Ooops. Not implemented yet.") updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("auth", auth)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("unauth", unauth)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("fish", fish)) +updater.dispatcher.add_handler(telegram.ext.MessageHandler(telegram.ext.Filters.text, tweet)) updater.start_polling() updater.idle() From cb3f9654da6027d150b18511ed0ad53ce1af4e26 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 14:58:09 +0100 Subject: [PATCH 20/31] Added database field for /toggletweet --- bot.py | 10 ++++++++++ setup.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 3511a7e..1b853ea 100755 --- a/bot.py +++ b/bot.py @@ -3,6 +3,10 @@ import dbtools, logging, setuptools, strings, telegram.ext 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()) @@ -22,11 +26,17 @@ def fish(bot, update): def tweet(bot, update): update.message.reply_text("Ooops. Not implemented yet.") +def unknown(bot, update): + update.message.reply_text("Sorry, I didn't understand that command.") + updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("auth", auth)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("unauth", unauth)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("fish", fish)) 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() diff --git a/setup.py b/setup.py index 7a34ba0..5854fa8 100755 --- a/setup.py +++ b/setup.py @@ -49,7 +49,7 @@ if dbtype == dbtools.MYSQL: else: db = dbtools.dbObject(dbtype=dbtype, path=dbpath) if not db.isInitialized(): - db.executeQuery("CREATE TABLE tokens(`cid` INT PRIMARY KEY, `ato` TEXT, `ase` TEXT, `fish` INT 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.closeConnection() From aa399adebd513bb0927c6e8ac56f448c55f72728 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 15:07:22 +0100 Subject: [PATCH 21/31] Fix INSERT statement --- dbtools/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbtools/__init__.py b/dbtools/__init__.py index 4e6f3ad..182be5b 100644 --- a/dbtools/__init__.py +++ b/dbtools/__init__.py @@ -68,7 +68,7 @@ class dbObject: self.commit() def storeUser(self, cid, ato, ase): - self.executeQuery("INSERT INTO tokens VALUES(%i, '%s', '%s');" % (int(cid), ato, ase)) + self.executeQuery("INSERT INTO tokens(cid, ato, ase) VALUES(%i, '%s', '%s');" % (int(cid), ato, ase)) self.commit() def ato(self, cid): From 6ea970e1e4b606f9f72ce1b8ebe133576d8eabfb Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 15:09:39 +0100 Subject: [PATCH 22/31] Fix ato/ase getters --- dbtools/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbtools/__init__.py b/dbtools/__init__.py index 182be5b..eeca06a 100644 --- a/dbtools/__init__.py +++ b/dbtools/__init__.py @@ -74,14 +74,14 @@ class dbObject: def ato(self, cid): try: self.executeQuery("SELECT ato FROM tokens WHERE cid = %i;" % int(cid)) - return self.cur.fetchone() + 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() + return self.cur.fetchone()[0] except: return False From 69159d93268991f0870a489ea8ac47309a9dcf09 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 15:14:03 +0100 Subject: [PATCH 23/31] Add automatic tweet toggling --- bot.py | 9 +++++++++ dbtools/__init__.py | 12 ++++++++++++ strings.py | 4 ++++ 3 files changed, 25 insertions(+) diff --git a/bot.py b/bot.py index 1b853ea..56b9e93 100755 --- a/bot.py +++ b/bot.py @@ -23,9 +23,15 @@ def unauth(bot, update): def fish(bot, update): update.message.reply_text("Yummy! Thanks! :3") +def explicitTweet(bot, update): + update.message.reply_text("Ooops. Not implemented yet.") + def tweet(bot, update): update.message.reply_text("Ooops. Not implemented yet.") +def toggleTweet(bot, update): + update.message.reply_text(strings.toggleTweet % ("on" if dbtools.dbHelper().toggleTweet(update.message.chat_id) else "off") + def unknown(bot, update): update.message.reply_text("Sorry, I didn't understand that command.") @@ -33,6 +39,9 @@ updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("auth", auth)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("unauth", unauth)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("fish", fish)) +updater.dispatcher.add_handler(telegram.ext.CommandHandler("toggletweet", toggleTweet)) +updater.dispatcher.add_handler(telegram.ext.CommandHandler("tweet", explicitTweet)) + updater.dispatcher.add_handler(telegram.ext.MessageHandler(telegram.ext.Filters.text, tweet)) updater.dispatcher.add_handler(telegram.ext.MessageHandler(telegram.ext.Filters.command, unknown)) diff --git a/dbtools/__init__.py b/dbtools/__init__.py index eeca06a..137ddc3 100644 --- a/dbtools/__init__.py +++ b/dbtools/__init__.py @@ -85,6 +85,18 @@ class dbObject: except: return False + def toggleTweet(self, cid): + try: + self.executeQuery("UPDATE tokens SET tweet = NOT tweet WHERE cid = %i;" % int(cid)) + self.commit() + + self.executeQuery("SELECT tweet FROM tokens WHERE cid = %i;" % int(cid)) + + return True if self.cur.fetchone()[0] == 1 else False + + except: + raise ValueError("No such user: %i" % int(cid)) + def dbHelper(): if setuptools.dbtype() == SQLITE: return dbObject(dbtype=SQLITE, path=setuptools.dbpath()) diff --git a/strings.py b/strings.py index d16c75f..3c40adc 100644 --- a/strings.py +++ b/strings.py @@ -16,6 +16,10 @@ Additionally, you will be able to use the following commands: 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: From 33380efd4f5c862ea937984b23c6fac19b55ea87 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 15:16:23 +0100 Subject: [PATCH 24/31] Add tweet toggling explanation --- strings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/strings.py b/strings.py index 3c40adc..b5c42db 100644 --- a/strings.py +++ b/strings.py @@ -12,6 +12,8 @@ After authentication, you will be able to tweet from your account. Just drop me 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!''' From 6fcedcceda05f39e86d50dd099ab893d67b90ba5 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 15:19:01 +0100 Subject: [PATCH 25/31] Add help handler, add noauth string --- bot.py | 10 +++++++--- strings.py | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index 56b9e93..0ff7782 100755 --- a/bot.py +++ b/bot.py @@ -30,17 +30,21 @@ def tweet(bot, update): update.message.reply_text("Ooops. Not implemented yet.") def toggleTweet(bot, update): - update.message.reply_text(strings.toggleTweet % ("on" if dbtools.dbHelper().toggleTweet(update.message.chat_id) else "off") + try: + update.message.reply_text(strings.toggleTweet % ("on" if dbtools.dbHelper().toggleTweet(update.message.chat_id) else "off") + except: + update.message.reply_text(strings.noauth) def unknown(bot, update): update.message.reply_text("Sorry, I didn't understand that command.") -updater.dispatcher.add_handler(telegram.ext.CommandHandler("start", start)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("auth", auth)) -updater.dispatcher.add_handler(telegram.ext.CommandHandler("unauth", unauth)) 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("toggletweet", toggleTweet)) updater.dispatcher.add_handler(telegram.ext.CommandHandler("tweet", explicitTweet)) +updater.dispatcher.add_handler(telegram.ext.CommandHandler("unauth", unauth)) updater.dispatcher.add_handler(telegram.ext.MessageHandler(telegram.ext.Filters.text, tweet)) updater.dispatcher.add_handler(telegram.ext.MessageHandler(telegram.ext.Filters.command, unknown)) diff --git a/strings.py b/strings.py index b5c42db..3de994b 100644 --- a/strings.py +++ b/strings.py @@ -1,5 +1,8 @@ import setuptools +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! From 7cbdeaaa825d2085dd651951efec9d693bf75703 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 15:19:55 +0100 Subject: [PATCH 26/31] Not using setuptools in strings.py --- strings.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/strings.py b/strings.py index 3de994b..324b8ab 100644 --- a/strings.py +++ b/strings.py @@ -1,5 +1,3 @@ -import setuptools - noauth = '''You are not authenticated. Please use /auth to sign in with Twitter.''' From 43850de7060df0b0c29e78ee6437af538d53296b Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 15:23:15 +0100 Subject: [PATCH 27/31] Actually count fish, add missing ')' --- bot.py | 3 ++- dbtools/__init__.py | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 0ff7782..f73ffa1 100755 --- a/bot.py +++ b/bot.py @@ -21,6 +21,7 @@ def unauth(bot, update): 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): @@ -31,7 +32,7 @@ def tweet(bot, update): def toggleTweet(bot, update): try: - update.message.reply_text(strings.toggleTweet % ("on" if dbtools.dbHelper().toggleTweet(update.message.chat_id) else "off") + update.message.reply_text(strings.toggleTweet % ("on" if dbtools.dbHelper().toggleTweet(update.message.chat_id) else "off")) except: update.message.reply_text(strings.noauth) diff --git a/dbtools/__init__.py b/dbtools/__init__.py index 137ddc3..4a6a514 100644 --- a/dbtools/__init__.py +++ b/dbtools/__init__.py @@ -97,6 +97,10 @@ class dbObject: except: raise ValueError("No such user: %i" % int(cid)) + def addFish(self, cid): + self.executeQuery("UPDATE tokens SET fish = fish + 1 WHERE cid = %i;" % int(cid)) + self.commit() + def dbHelper(): if setuptools.dbtype() == SQLITE: return dbObject(dbtype=SQLITE, path=setuptools.dbpath()) From 3cb5d8861c802c2be5ce75356ce043333ebe2124 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Wed, 8 Feb 2017 15:26:21 +0100 Subject: [PATCH 28/31] Separate toggler from checker --- dbtools/__init__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/dbtools/__init__.py b/dbtools/__init__.py index 4a6a514..434382c 100644 --- a/dbtools/__init__.py +++ b/dbtools/__init__.py @@ -85,11 +85,8 @@ class dbObject: except: return False - def toggleTweet(self, cid): + def getTStatus(self, cid): try: - self.executeQuery("UPDATE tokens SET tweet = NOT tweet WHERE cid = %i;" % int(cid)) - self.commit() - self.executeQuery("SELECT tweet FROM tokens WHERE cid = %i;" % int(cid)) return True if self.cur.fetchone()[0] == 1 else False @@ -97,6 +94,12 @@ class dbObject: 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 getTStatus + def addFish(self, cid): self.executeQuery("UPDATE tokens SET fish = fish + 1 WHERE cid = %i;" % int(cid)) self.commit() From 9457a83e02f9167bbdcbabe88875b4db97bf6d12 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Fri, 10 Feb 2017 18:41:28 +0100 Subject: [PATCH 29/31] Implement authentication and timeline retrieval --- bot.py | 66 ++++++++++++++++++++++++++++++++++++++++---- dbtools/__init__.py | 6 ++++ strings.py | 23 +++++++++++++++ twitools/__init__.py | 13 +++++---- 4 files changed, 97 insertions(+), 11 deletions(-) diff --git a/bot.py b/bot.py index f73ffa1..7d76f2d 100755 --- a/bot.py +++ b/bot.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -import dbtools, logging, setuptools, strings, telegram.ext +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__) @@ -10,12 +10,44 @@ def log(bot, update, error): 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): - update.message.reply_text("Ooops. Not implemented yet.") + 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()) @@ -24,28 +56,50 @@ def fish(bot, update): dbtools.dbHelper().addFish(update.message.chat_id) update.message.reply_text("Yummy! Thanks! :3") -def explicitTweet(bot, update): +def explicitTweet(bot, update, args): update.message.reply_text("Ooops. Not implemented yet.") def tweet(bot, update): - update.message.reply_text("Ooops. Not implemented yet.") + 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.twoHelper(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: - update.message.reply_text(strings.noauth) + 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)) +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)) diff --git a/dbtools/__init__.py b/dbtools/__init__.py index 434382c..5b006ef 100644 --- a/dbtools/__init__.py +++ b/dbtools/__init__.py @@ -68,6 +68,7 @@ class dbObject: 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() @@ -104,6 +105,11 @@ class dbObject: 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(): if setuptools.dbtype() == SQLITE: return dbObject(dbtype=SQLITE, path=setuptools.dbpath()) diff --git a/strings.py b/strings.py index 324b8ab..3a67aff 100644 --- a/strings.py +++ b/strings.py @@ -1,3 +1,17 @@ +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.''' @@ -32,3 +46,12 @@ I hope you had a good time with me. If there is anything you would like to tell 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.''' diff --git a/twitools/__init__.py b/twitools/__init__.py index 479e81d..26c0c9f 100644 --- a/twitools/__init__.py +++ b/twitools/__init__.py @@ -1,4 +1,4 @@ -import tweepy, setuptools +import dbtools, tweepy, setuptools class twObject: @@ -24,21 +24,24 @@ class twObject: def tweet(self, text, reply = 0): return self.api.update_status(text, reply) -def getFollowerIDs(two=twObject()): +def getFollowerIDs(two): ''' Returns 5,000 follower IDs at most ''' for id in list(two.api.followers_ids(screen_name=twObject().whoami())): yield int(id) -def getFollowingIDs(two=twObject()): +def getFollowingIDs(two): for id in list(two.api.friends_ids(screen_name=twObject().whoami())): yield int(id) -def getNameByID(uid, two=twObject()): +def getNameByID(uid, two): return two.api.get_user(uid).screen_name -def getNamesByIDs(fids=getFollowerIDs(), two=twObject()): +def getNamesByIDs(fids, two): for page in setuptools.paginate(fids, 100): followers = two.api.lookup_users(user_ids=page) for follower in followers: yield {"id": follower.id, "name": follower.screen_name} +def twoHelper(cid): + db = dbtools.dbHelper() + return twObject(db.ato(cid), db.ase(cid)) From 74239a16b8db500d3f68dcda41a5db40cac3dade Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Fri, 10 Feb 2017 18:54:30 +0100 Subject: [PATCH 30/31] Fix tweeting --- bot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index 7d76f2d..0f56a62 100755 --- a/bot.py +++ b/bot.py @@ -57,12 +57,13 @@ def fish(bot, update): update.message.reply_text("Yummy! Thanks! :3") def explicitTweet(bot, update, args): - update.message.reply_text("Ooops. Not implemented yet.") + two = twitools.twoHelper(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) + explicitTweet(bot, update, [update.message.text]) except: noauth(update) From eb45d2b0cd4115fdb217c1b5d2b00dee8c008ff9 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Fri, 10 Feb 2017 19:16:26 +0100 Subject: [PATCH 31/31] Fix tweet toggler --- dbtools/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbtools/__init__.py b/dbtools/__init__.py index 5b006ef..32027ee 100644 --- a/dbtools/__init__.py +++ b/dbtools/__init__.py @@ -90,7 +90,7 @@ class dbObject: try: self.executeQuery("SELECT tweet FROM tokens WHERE cid = %i;" % int(cid)) - return True if self.cur.fetchone()[0] == 1 else False + return True if int(self.cur.fetchone()[0]) == 1 else False except: raise ValueError("No such user: %i" % int(cid)) @@ -99,7 +99,7 @@ class dbObject: self.executeQuery("UPDATE tokens SET tweet = NOT tweet WHERE cid = %i;" % int(cid)) self.commit() - return getTStatus + return self.getTStatus(cid) def addFish(self, cid): self.executeQuery("UPDATE tokens SET fish = fish + 1 WHERE cid = %i;" % int(cid))