-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from macisamuele/make-repository-installable-as…
…-python-package Update bot to support Python3, make it installable as python package
- Loading branch information
Showing
7 changed files
with
202 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
config.py | ||
__pycache__ | ||
*.egg | ||
*.egg-info/ | ||
*.pyc | ||
.idea/ | ||
.telegram.token | ||
.vscode/ | ||
__pycache__ | ||
venv/ | ||
.gitignore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
include LICENSE | ||
include README.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,22 @@ | ||
class Config(object): | ||
TOKEN = "" | ||
WAITING_TIMEOUT = 30.0 | ||
# -*- coding: utf-8 -*- | ||
import os | ||
|
||
|
||
class _Config(object): | ||
@property | ||
def TOKEN(self): | ||
try: | ||
with open('.telegram.token') as f: | ||
return ''.join(f.readlines()).strip() | ||
except: | ||
raise RuntimeError( | ||
'Telegram token not set. Please make sure that you followed the instructions on README and that you ' | ||
'have created the token file in `{}` and that is readable from the current user'.format( | ||
os.path.join(os.path.abspath('.'), '.telegram.token') | ||
), | ||
) | ||
|
||
WAITING_TIMEOUT = 30.0 | ||
|
||
|
||
Config = _Config() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,138 +1,191 @@ | ||
# -*- coding: utf-8 -*- | ||
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackQueryHandler, ConversationHandler | ||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode | ||
from config import Config | ||
import datetime | ||
import time | ||
import os | ||
import random | ||
import threading | ||
from __future__ import unicode_literals | ||
|
||
import logging | ||
import threading | ||
from sys import maxsize | ||
|
||
from telegram import InlineKeyboardButton | ||
from telegram import InlineKeyboardMarkup | ||
from telegram import ParseMode | ||
from telegram.error import NetworkError | ||
from telegram.ext import CallbackQueryHandler | ||
from telegram.ext import CommandHandler | ||
from telegram.ext import Filters | ||
from telegram.ext import MessageHandler | ||
from telegram.ext import Updater | ||
|
||
from config import Config | ||
|
||
logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', | ||
level=logging.INFO) | ||
|
||
logging.basicConfig( | ||
format='%(asctime)s - %(levelname)s - %(message)s', | ||
level=logging.INFO, | ||
) | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
new_users = [] | ||
|
||
|
||
def welcome(bot, update): | ||
for new_user_obj in update.message.new_chat_members: | ||
try: | ||
new_user = "@" + new_user_obj['username'] | ||
reply_text = "Benvenut*"+new_user+"! Premi <i>Confermo</i> per dimostrare di non essere un bot." \ | ||
.format(new_user_obj.username, new_user, update.message.chat.title) | ||
except Exception as _: | ||
new_user = new_user_obj['first_name'] | ||
reply_text = "Benvenut*"+new_user+"! Premi <i>Confermo</i> per dimostrare di non essere un bot." \ | ||
.format(new_user, update.message.chat.title) | ||
logger.info("Nuovo utente: {}".format(new_user)) | ||
""" | ||
:type bot: telegram.Bot | ||
:type update: telegram.Update | ||
""" | ||
for new_user_obj in update.message.new_chat_members: # new_user_obj has telegram.user.User type | ||
user_handle = new_user_obj.name | ||
user_id = new_user_obj.id | ||
chat_id = update.message.chat_id | ||
|
||
reply_text = "Benvenuto/a {}! Premi <i>Confermo</i> per dimostrare di non essere un bot.".format( | ||
user_handle, | ||
) | ||
|
||
new_users.append(new_user_obj.id) | ||
|
||
keyboard = [[InlineKeyboardButton("Confermo", callback_data=1)]] | ||
reply_markup = InlineKeyboardMarkup(keyboard) | ||
|
||
mexid = bot.send_message( | ||
update.message.chat_id, | ||
message = bot.send_message( | ||
chat_id=update.message.chat_id, | ||
text=reply_text, | ||
reply_markup=reply_markup, | ||
parse_mode=ParseMode.HTML | ||
parse_mode=ParseMode.HTML, | ||
) | ||
|
||
threading.Timer(Config.WAITING_TIMEOUT, timer, | ||
[bot, new_user_obj.id, update.message.chat_id, mexid.message_id]).start() | ||
return | ||
threading.Timer( | ||
interval=Config.WAITING_TIMEOUT, | ||
function=timer, | ||
args=[bot, user_id, chat_id, message.message_id], | ||
).start() # TODO: keep track of the timer to cancel it if the user confirmed it's identity | ||
|
||
logger.info("Nuovo utente: {}.".format(user_handle)) | ||
|
||
|
||
def button_pressed(bot, update): | ||
""" | ||
:type bot: telegram.Bot | ||
:type update: telegram.Update | ||
""" | ||
global new_users | ||
|
||
if update.callback_query.from_user.id in new_users: | ||
user_handle = update.callback_query.from_user.name | ||
chat_id = update.callback_query.message.chat_id | ||
message_id = update.callback_query.message.message_id | ||
|
||
new_users.remove(update.callback_query.from_user.id) | ||
bot.deleteMessage(update.callback_query.message.chat_id, update.callback_query.message.message_id) | ||
bot.delete_message(chat_id, message_id=message_id) | ||
|
||
try: | ||
user = "@" + update.callback_query.from_user.username | ||
except Exception as _: | ||
user = update.callback_query.from_user.first_name | ||
bot.send_message( | ||
chat_id, | ||
text="{}: grazie per aver completato la registrazione!".format(user_handle), | ||
) | ||
|
||
bot.send_message(update.callback_query.message.chat_id, | ||
text=user + ", grazie per aver completato la registrazione!") | ||
logger.info("Utente confermato: {}.".format(user_handle)) | ||
|
||
|
||
def check_activity(bot, update): | ||
""" | ||
:type bot: telegram.Bot | ||
:type update: telegram.Update | ||
""" | ||
bot.send_message( | ||
chat_id=update.message.chat_id, | ||
text="pong", | ||
reply_to_message_id=update.message.message_id) | ||
reply_to_message_id=update.message.message_id, | ||
) | ||
|
||
|
||
def is_admin(bot, userid, chatid): | ||
return userid in [admin.user.id for admin in bot.get_chat_administrators(chatid)] | ||
def is_admin(bot, user_id, chat_id): | ||
""" | ||
:type bot: telegram.Bot | ||
:type user_id: str or int | ||
:type chat_id: str or int | ||
""" | ||
try: | ||
return any(user_id == admin.user.id for admin in bot.get_chat_administrators(chat_id)) | ||
except NetworkError: | ||
return False | ||
|
||
|
||
def ban_user(bot, update): | ||
""" | ||
:type bot: telegram.Bot | ||
:type update: telegram.Update | ||
""" | ||
if update.message.reply_to_message is None: | ||
return | ||
|
||
if is_admin(bot, update.message.from_user.id, update.message.chat.id): | ||
if not is_admin(bot, update.message.reply_to_message.from_user.id, update.message.chat.id): | ||
reply_text = "{} è stato bannato con successo.".format(update.message.reply_to_message.from_user.username) | ||
bot.kickChatMember(update.message.chat.id, update.message.reply_to_message.from_user.id) | ||
bot.send_message(update.message.chat.id, text=reply_text) | ||
chat_id = update.message.chat.id | ||
|
||
try: | ||
user = "@" + update.message.reply_to_message.from_user.username | ||
except Exception as _: | ||
user = update.message.reply_to_message.from_user.first_name | ||
if is_admin(bot, user_id=update.message.from_user.id, chat_id=chat_id): | ||
user_id = update.message.reply_to_message.from_user.id | ||
user_handle = update.message.reply_to_message.from_user.name | ||
|
||
logger.info("The user {} was banned with success".format(user)) | ||
if not is_admin(bot, user_id, chat_id): | ||
bot.kick_chat_member(chat_id, user_id) | ||
bot.send_message( | ||
chat_id, | ||
text="{} è stato bannato con successo.".format(user_handle), | ||
) | ||
|
||
logger.info("Utente {} bannato con successo.".format(user_handle)) | ||
|
||
|
||
def kick_user(bot, update): | ||
""" | ||
:type bot: telegram.Bot | ||
:type update: telegram.Update | ||
""" | ||
# FIXME: not clear what is the difference with respect to ban_user | ||
|
||
if update.message.reply_to_message is None: | ||
return | ||
|
||
if is_admin(bot, update.message.from_user.id, update.message.chat.id): | ||
if not is_admin(bot, update.message.reply_to_message.from_user.id, update.message.chat.id): | ||
bot.kickChatMember(update.message.chat.id, update.message.reply_to_message.from_user.id) | ||
bot.unbanChatMember(update.message.chat.id, update.message.reply_to_message.from_user.id) | ||
chat_id = update.message.chat.id | ||
|
||
try: | ||
user = "@" + update.message.reply_to_message.from_user.username | ||
except Exception as _: | ||
user = update.message.reply_to_message.from_user.first_name | ||
if is_admin(bot, user_id=update.message.from_user.id, chat_id=chat_id): | ||
user_id = update.message.reply_to_message.from_user.id | ||
user_handle = update.message.reply_to_message.from_user.name | ||
|
||
logger.info("The user {} was kicked with success".format(user)) | ||
if is_admin(bot, user_id, chat_id): | ||
bot.kick_chat_member(chat_id, user_id) | ||
bot.unban_chat_member(chat_id, user_id) | ||
|
||
logger.info("The user {} was kicked with success.".format(user_handle)) | ||
|
||
|
||
def main(): | ||
updater = Updater(Config.TOKEN) | ||
dp = updater.dispatcher | ||
dp.add_handler(MessageHandler(Filters.status_update.new_chat_members, welcome)) | ||
dp.add_handler(MessageHandler(Filters.regex('^ping$'), check_activity)) | ||
dp.add_handler(CallbackQueryHandler(button_pressed)) | ||
dp.add_handler(CommandHandler('ban', ban_user)) | ||
dp.add_handler(CommandHandler('kick', kick_user)) | ||
updater.dispatcher.add_handler(MessageHandler(Filters.status_update.new_chat_members, welcome)) | ||
updater.dispatcher.add_handler(MessageHandler(Filters.regex('^ping$'), check_activity)) | ||
updater.dispatcher.add_handler(CallbackQueryHandler(button_pressed)) | ||
updater.dispatcher.add_handler(CommandHandler('ban', ban_user)) | ||
updater.dispatcher.add_handler(CommandHandler('kick', kick_user)) | ||
|
||
updater.start_polling() | ||
updater.idle() | ||
|
||
try: | ||
updater.idle() | ||
except KeyboardInterrupt: | ||
print("Chiusura programma") | ||
|
||
|
||
def timer(bot, userid, chatid, mexid): | ||
def timer(bot, user_id, chat_id, message_id): | ||
""" | ||
:type bot: telegram.Bot | ||
:type user_id: str or int | ||
:type chat_id: str or int | ||
:type message_id: str or int | ||
""" | ||
global new_users | ||
if userid in new_users: | ||
logger.info("User with id: {} auto-removed with success".format(userid)) | ||
bot.kickChatMember(chatid, userid, until_date=25) | ||
bot.deleteMessage(chatid, mexid) | ||
if user_id in new_users: | ||
logger.info("User with id: {} auto-removed with success".format(user_id)) | ||
bot.kick_chat_member(chat_id, user_id, until_date=maxsize) # Kicking a member for over 365 days is forever | ||
bot.delete_message(chat_id, message_id=message_id) | ||
return | ||
|
||
|
||
try: | ||
if __name__ == '__main__': | ||
main() | ||
except KeyboardInterrupt: | ||
print("Chiusura programma") | ||
if __name__ == '__main__': | ||
exit(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[metadata] | ||
description-file = README.md | ||
license_file = LICENSE | ||
|
||
[wheel] | ||
universal = True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
# Copyright (c) 2011-2018, Yelp, Inc. | ||
import os | ||
|
||
from setuptools import setup | ||
|
||
setup( | ||
name='gdg-pisa-user-manager', | ||
version='1.0.0', | ||
license='MIT License', | ||
description='Bot for managing the Telegram group of GDG Pisa', | ||
long_description=open(os.path.join(os.path.dirname(__file__), 'README.md')).read(), | ||
author='GDG Pise', | ||
author_email='TODO', | ||
url='https://github.com/gdgpisa/gdgpisausermanager/', | ||
py_modules=['gdgpisausermanager'], | ||
classifiers=[ | ||
'Development Status :: 5 - Production/Stable', | ||
'Intended Audience :: Developers', | ||
'Topic :: Communications :: Chat', | ||
'Topic :: Internet', | ||
'License :: OSI Approved :: MIT License', | ||
'Operating System :: OS Independent', | ||
'Programming Language :: Python :: 2', | ||
'Programming Language :: Python :: 2.7', | ||
'Programming Language :: Python :: 3', | ||
'Programming Language :: Python :: 3.5', | ||
'Programming Language :: Python :: 3.6', | ||
'Programming Language :: Python :: 3.7', | ||
], | ||
install_requires=['python-telegram-bot'], | ||
entry_points={'console_scripts': ['gdg-pisa-user-manager = gdgpisausermanager:main']}, | ||
) |