Skip to content

Commit

Permalink
python-telegram-bot v7 compatability + more (#35)
Browse files Browse the repository at this point in the history
* Remove import of telegram.Emoji

* Using a list of filters in MessageHandler is getting deprecated

* Update requirements

Proudly upgrades to latest python-telegram-bot

* Refine readme

* Test kill command

* Another implement

* Add /kill command

* initial config support

* json config

* Add token into json

* Typo

* Add Admin list

* Refine admin & starter

* Fix an exception

* Fix typo

* refine readme

* Update help
  • Loading branch information
simonsmh authored and jh0ker committed Aug 18, 2017
1 parent 8be4bc6 commit 783e010
Show file tree
Hide file tree
Showing 12 changed files with 113 additions and 84 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Config file
config.json

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@

[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](./LICENSE)

Telegram Bot that allows you to play the popular card game UNO via inline queries. The bot currently runs as [@unobot](http://telegram.me/unobot)
Telegram Bot that allows you to play the popular card game UNO via inline queries. The bot currently runs as [@unobot](http://telegram.me/unobot).

To run the bot yourself, you will need:
- Python (tested with 3.4 and 3.5)
- The [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) module version 5.0.0
- Python (tested with 3.4+)
- The [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) module
- [Pony ORM](https://ponyorm.com/)

## Setup
- Get a bot token from [@BotFather](http://telegram.me/BotFather) and place it in `credentials.py`
- Convert all language files from .po to .mo using `msgfmt unobot.po -o unobot.mo`
- Use `/setinline` and `/setinlinefeedback` with BotFather for your bot
- Get a bot token from [@BotFather](http://telegram.me/BotFather) and change configurations in `config.json`.
- Convert all language files from `.po` files to `.mo` files using `msgfmt unobot.po -o unobot.mo`.
Also try `find . -maxdepth 2 -type d -name 'LC_MESSAGES' -exec bash -c 'msgfmt {}/unobot.po -o {}/unobot.mo' \;`.
- Use `/setinline` and `/setinlinefeedback` with BotFather for your bot.

Then run the bot with `python3 bot.py`
Then run the bot with `python3 bot.py`.

Code documentation is minimal but there
Code documentation is minimal but there.
71 changes: 55 additions & 16 deletions bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.


import logging
from datetime import datetime
from random import randint
Expand Down Expand Up @@ -45,13 +44,16 @@

from simple_commands import help

#import json
#with open("config.json","r") as f:
# config = json.loads(f.read())
#forbidden = config.get("black_list", None)

logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
logger = logging.getLogger(__name__)


@user_locale
def notify_me(bot, update):
"""Handler for /notify_me command, pm people for next game"""
Expand Down Expand Up @@ -88,14 +90,50 @@ def new_game(bot, update):
del gm.remind_dict[update.message.chat_id]

game = gm.new_game(update.message.chat)
game.owner = update.message.from_user
game.starter = update.message.from_user
game.owner.append(update.message.from_user.id)
send_async(bot, chat_id,
text=_("Created a new game! Join the game with /join "
"and start the game with /start"))

if botan:
botan.track(update.message, 'New games')

@user_locale
def kill_game(bot, update):
"""Handler for the /kill command"""
chat = update.message.chat
user = update.message.from_user
games = gm.chatid_games.get(chat.id)

if update.message.chat.type == 'private':
help(bot, update)
return

if not games:
send_async(bot, chat.id,
text=_("There is no running game in this chat."))
return

game = games[-1]

if user.id in game.owner:

try:
gm.end_game(chat, user)
send_async(bot, chat.id, text=__("Game ended!", multi=game.translate))

except NoGameInChatError:
send_async(bot, chat.id,
text=_("The game is not started yet. "
"Join the game with /join and start the game with /start"),
reply_to_message_id=update.message.message_id)

else:
send_async(bot, chat.id,
text=_("Only the game creator ({name}) and admin can do that.")
.format(name=game.starter.first_name),
reply_to_message_id=update.message.message_id)

@user_locale
def join_game(bot, update):
Expand Down Expand Up @@ -321,16 +359,16 @@ def close_game(bot, update):

game = games[-1]

if game.owner.id == user.id:
if user.id in game.owner:
game.open = False
send_async(bot, chat.id, text=_("Closed the lobby. "
"No more players can join this game."))
return

else:
send_async(bot, chat.id,
text=_("Only the game creator ({name}) can do that.")
.format(name=game.owner.first_name),
text=_("Only the game creator ({name}) and admin can do that.")
.format(name=game.starter.first_name),
reply_to_message_id=update.message.message_id)
return

Expand All @@ -349,15 +387,15 @@ def open_game(bot, update):

game = games[-1]

if game.owner.id == user.id:
if user.id in game.owner:
game.open = True
send_async(bot, chat.id, text=_("Opened the lobby. "
"New players may /join the game."))
return
else:
send_async(bot, chat.id,
text=_("Only the game creator ({name}) can do that")
.format(name=game.owner.first_name),
text=_("Only the game creator ({name}) and admin can do that.")
.format(name=game.starter.first_name),
reply_to_message_id=update.message.message_id)
return

Expand All @@ -376,16 +414,16 @@ def enable_translations(bot, update):

game = games[-1]

if game.owner.id == user.id:
if user.id in game.owner:
game.translate = True
send_async(bot, chat.id, text=_("Enabled multi-translations. "
"Disable with /disable_translations"))
return

else:
send_async(bot, chat.id,
text=_("Only the game creator ({name}) can do that")
.format(name=game.owner.first_name),
text=_("Only the game creator ({name}) and admin can do that.")
.format(name=game.starter.first_name),
reply_to_message_id=update.message.message_id)
return

Expand All @@ -404,7 +442,7 @@ def disable_translations(bot, update):

game = games[-1]

if game.owner.id == user.id:
if user.id in game.owner:
game.translate = False
send_async(bot, chat.id, text=_("Disabled multi-translations. "
"Enable them again with "
Expand All @@ -413,8 +451,8 @@ def disable_translations(bot, update):

else:
send_async(bot, chat.id,
text=_("Only the game creator ({name}) can do that")
.format(name=game.owner.first_name),
text=_("Only the game creator ({name}) and admin can do that.")
.format(name=game.starter.first_name),
reply_to_message_id=update.message.message_id)
return

Expand Down Expand Up @@ -728,6 +766,7 @@ def do_call_bluff(bot, player):
dispatcher.add_handler(CallbackQueryHandler(select_game))
dispatcher.add_handler(CommandHandler('start', start_game, pass_args=True))
dispatcher.add_handler(CommandHandler('new', new_game))
dispatcher.add_handler(CommandHandler('kill', kill_game))
dispatcher.add_handler(CommandHandler('join', join_game))
dispatcher.add_handler(CommandHandler('leave', leave_game))
dispatcher.add_handler(CommandHandler('open', open_game))
Expand All @@ -740,7 +779,7 @@ def do_call_bluff(bot, player):
dispatcher.add_handler(CommandHandler('notify_me', notify_me))
simple_commands.register()
settings.register()
dispatcher.add_handler(MessageHandler([Filters.status_update], status_update))
dispatcher.add_handler(MessageHandler(Filters.status_update, status_update))
dispatcher.add_error_handler(error)

start_bot(updater)
Expand Down
10 changes: 4 additions & 6 deletions card.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.


from telegram.emoji import Emoji

# Colors
RED = 'r'
BLUE = 'b'
Expand All @@ -30,10 +28,10 @@
COLORS = (RED, BLUE, GREEN, YELLOW)

COLOR_ICONS = {
RED: Emoji.HEAVY_BLACK_HEART,
BLUE: Emoji.BLUE_HEART,
GREEN: Emoji.GREEN_HEART,
YELLOW: Emoji.YELLOW_HEART,
RED: '❤️',
BLUE: '💙',
GREEN: '💚',
YELLOW: '💛',
BLACK: '⬛️'
}

Expand Down
8 changes: 8 additions & 0 deletions config.json.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"token": "token_here",
"botan_token": null,
"admin_list": [0],
"open_lobby": true,
"enable_translations": false,
"workers": 32
}
21 changes: 0 additions & 21 deletions credentials.py

This file was deleted.

14 changes: 8 additions & 6 deletions game.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,25 @@


import logging
import json
from datetime import datetime

from deck import Deck
import card as c


class Game(object):
""" This class represents a game of UNO """
current_player = None
reversed = False
draw_counter = 0
choosing_color = False
started = False
owner = None
open = True
translate = False
draw_counter = 0
players_won = 0
starter = None
with open("config.json","r") as f:
config = json.loads(f.read())
owner = config.get("admin_list", None)
open = config.get("open_lobby", True)
translate = config.get("enable_translations", False)

def __init__(self, chat):
self.chat = chat
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
python-telegram-bot==5
python-telegram-bot
pony
22 changes: 11 additions & 11 deletions settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.


from telegram import ReplyKeyboardMarkup, Emoji
from telegram import ReplyKeyboardMarkup
from telegram.ext import CommandHandler, RegexHandler

from utils import send_async
Expand All @@ -44,12 +44,12 @@ def show_settings(bot, update):
us = UserSetting(id=update.message.from_user.id)

if not us.stats:
stats = Emoji.BAR_CHART + ' ' + _("Enable statistics")
stats = '📊' + ' ' + _("Enable statistics")
else:
stats = Emoji.CROSS_MARK + ' ' + _("Delete all statistics")
stats = '❌' + ' ' + _("Delete all statistics")

kb = [[stats], [Emoji.EARTH_GLOBE_EUROPE_AFRICA + ' ' + _("Language")]]
send_async(bot, chat.id, text=Emoji.WRENCH + ' ' + _("Settings"),
kb = [[stats], ['🌍' + ' ' + _("Language")]]
send_async(bot, chat.id, text='🔧' + ' ' + _("Settings"),
reply_markup=ReplyKeyboardMarkup(keyboard=kb,
one_time_keyboard=True))

Expand All @@ -60,20 +60,20 @@ def kb_select(bot, update, groups):
user = update.message.from_user
option = groups[0]

if option == Emoji.BAR_CHART:
if option == '📊':
us = UserSetting.get(id=user.id)
us.stats = True
send_async(bot, chat.id, text=_("Enabled statistics!"))

elif option == Emoji.EARTH_GLOBE_EUROPE_AFRICA:
elif option == '🌍':
kb = [[locale + ' - ' + descr]
for locale, descr
in sorted(available_locales.items())]
send_async(bot, chat.id, text=_("Select locale"),
reply_markup=ReplyKeyboardMarkup(keyboard=kb,
one_time_keyboard=True))

elif option == Emoji.CROSS_MARK:
elif option == '❌':
us = UserSetting.get(id=user.id)
us.stats = False
us.first_places = 0
Expand All @@ -98,9 +98,9 @@ def locale_select(bot, update, groups):

def register():
dispatcher.add_handler(CommandHandler('settings', show_settings))
dispatcher.add_handler(RegexHandler('^([' + Emoji.BAR_CHART +
Emoji.EARTH_GLOBE_EUROPE_AFRICA +
Emoji.CROSS_MARK + ']) .+$',
dispatcher.add_handler(RegexHandler('^([' + '📊' +
'🌍' +
'❌' + ']) .+$',
kb_select, pass_groups=True))
dispatcher.add_handler(RegexHandler(r'^(\w\w_\w\w) - .*',
locale_select, pass_groups=True))
11 changes: 5 additions & 6 deletions shared_vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,20 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.


import json
from telegram.ext import Updater
from telegram.contrib.botan import Botan

from game_manager import GameManager
from database import db
from credentials import TOKEN, BOTAN_TOKEN

db.bind('sqlite', 'uno.sqlite3', create_db=True)
db.generate_mapping(create_tables=True)

gm = GameManager()
updater = Updater(token=TOKEN, workers=32)
with open("config.json","r") as f:
config = json.loads(f.read())
updater = Updater(token=config.get("token"), workers=config.get("workers", 32))
dispatcher = updater.dispatcher

botan = False
if BOTAN_TOKEN:
botan = Botan(BOTAN_TOKEN)
botan = Botan(config.get("botan_token", None))
1 change: 1 addition & 0 deletions simple_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"Other commands (only game creator):\n"
"/close - Close lobby\n"
"/open - Open lobby\n"
"/kill - Terminate the game\n"
"/enable_translations - Translate relevant texts into all "
"languages spoken in a game\n"
"/disable_translations - Use English for those texts\n\n"
Expand Down
Loading

0 comments on commit 783e010

Please sign in to comment.