diff --git a/README.md b/README.md new file mode 100644 index 0000000..d9c0c2d --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# Telegram Group Chat Logger + +This is a bot that logs public Group Chats to an SQL Database. + +## Installation + + - Required: Python 3.X , PostgreSQL, Telegram Bot + - Clone this repo + - `pip install requirements.txt` + +## Bot/Group Setup + + - Create a group + - Add your bot to the group like so: https://stackoverflow.com/questions/37338101/how-to-add-a-bot-to-a-telegram-group + - your bot only sees commands. Use `/setprivacy` with `@BotFather` in order to allow it to see all messages in a group. + +## Running the bot + + - Create a Database, eg. `origindb` + - Store your Telegram Bot Token in an environment variable, eg. `echo $ORIGINTOKEN` + - Add your DB credentials to `model.py` eg. `engine = create_engine('postgresql://postgres:@localhost:5432/')` + - Run: `python model.py` to setup the DB tables, etc. + - Run: `python bot.py` to start logger \ No newline at end of file diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..8f17b1d --- /dev/null +++ b/bot.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- + +"""Group Chat Logger + +This bot is a modified version of the echo2 bot found here: +https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/echobot2.py + +This bot logs all messages sent in a Telegram Group to a database. + +""" + +from telegram.ext import Updater, CommandHandler, MessageHandler, Filters +import logging +import os +from model import User, Message, session + +# Enable logging +logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + level=logging.INFO) + +logger = logging.getLogger(__name__) + +# Define a few command handlers. These usually take the two arguments bot and +# update. Error handlers also receive the raised TelegramError object in error. + +def logger(bot, update): + """Primary Logger. Handles incoming bot messages and saves them to DB""" + + user = update.message.from_user + + if id_exists(user.id) == True: + log_message(user.id, update.message.text) + print("message logged") + + else: + add_user_success = add_user(user.id, user.first_name, user.last_name, user.username) + + if add_user_success == True: + log_message(user.id, update.message.text) + print("user added & message logged") + else: + print("Something went wrong adding the user!") + +# DB queries + +def id_exists(id_value): + s = session() + bool_set = False + for id1 in s.query(User.id).filter_by(id=id_value): + if id1: + bool_set = True + + s.close() + + return bool_set + +def log_message(user_id, user_message): + + try: + s = session() + msg1 = Message(user_id=user_id,message=user_message) + s.add(msg1) + s.commit() + s.close() + + except Exception as e: + print(e) + +def add_user(user_id, first_name, last_name, username): + try: + s = session() + bool_set = False + user = User(id=user_id, first_name = first_name, last_name = last_name, username = username) + s.add(user) + s.commit() + s.close() + + if id_exists(user_id) == True: + bool_set = True + + return bool_set + + except Exception as e: + print(e) + + +def error(bot, update, error): + """Log Errors caused by Updates.""" + logger.warning('Update "%s" caused error "%s"', update, error) + + +def main(): + """Start the bot.""" + # Create the EventHandler and pass it your bot's token. + updater = Updater(os.environ["ORIGINTOKEN"]) + + # Get the dispatcher to register handlers + dp = updater.dispatcher + + # on different commands - answer in Telegram + + # on noncommand i.e message - echo the message on Telegram + dp.add_handler(MessageHandler(Filters.text, logger)) + + # dp.add_handler(MessageHandler(Filters.status_update, status)) + + # log all errors + dp.add_error_handler(error) + + # Start the Bot + updater.start_polling() + + # Run the bot until you press Ctrl-C or the process receives SIGINT, + # SIGTERM or SIGABRT. This should be used most of the time, since + # start_polling() is non-blocking and will stop the bot gracefully. + updater.idle() + + +if __name__ == '__main__': + main() diff --git a/model.py b/model.py new file mode 100644 index 0000000..6508606 --- /dev/null +++ b/model.py @@ -0,0 +1,37 @@ +from sqlalchemy import Column, DateTime, String, Integer, ForeignKey, func +from sqlalchemy.orm import relationship, backref +from sqlalchemy.ext.declarative import declarative_base + +''' +This model has been referenced from: https://www.pythoncentral.io/sqlalchemy-orm-examples/ +''' + +Base = declarative_base() + + +class User(Base): + __tablename__ = 'users' + id = Column(Integer, primary_key=True) + first_name = Column(String) + last_name = Column(String) + username = Column(String) + + +class Message(Base): + __tablename__ = 'messages' + id = Column(Integer, primary_key=True) + user_id = Column(Integer, ForeignKey('users.id'), nullable=False) + message = Column(String) + # Use default=func.now() to set the default hiring time + # of an Employee to be the current time when an + # Employee record was created + time = Column(DateTime, default=func.now()) + + +from sqlalchemy import create_engine +engine = create_engine('postgresql://postgres:@localhost:5432/origindb') + +from sqlalchemy.orm import sessionmaker +session = sessionmaker() +session.configure(bind=engine) +Base.metadata.create_all(engine)