Ver Fonte

First finished version

JoostSijm há 5 anos atrás
pai
commit
8f529830d3
6 ficheiros alterados com 203 adições e 43 exclusões
  1. 4 4
      app/__init__.py
  2. 27 2
      app/api.py
  3. 7 5
      app/commands.py
  4. 105 15
      app/conversations/add_account.py
  5. 60 8
      app/database.py
  6. 0 9
      app/models.py

+ 4 - 4
app/__init__.py

@@ -15,17 +15,17 @@ load_dotenv()
 
 # get logger
 LOGGER = logging.getLogger(__name__)
-LOGGER.setLevel(logging.DEBUG)
+LOGGER.setLevel(logging.INFO)
 TELEGRAM_LOGGER = logging.getLogger('telegram')
-TELEGRAM_LOGGER.setLevel(logging.DEBUG)
+TELEGRAM_LOGGER.setLevel(logging.INFO)
 
 # create file handler
 FILE_HANDLER = logging.FileHandler('output.log')
-FILE_HANDLER.setLevel(logging.DEBUG)
+FILE_HANDLER.setLevel(logging.INFO)
 
 # create console handler
 STREAM_HANDLER = logging.StreamHandler()
-STREAM_HANDLER.setLevel(logging.DEBUG)
+STREAM_HANDLER.setLevel(logging.INFO)
 
 # create formatter and add it to the handlers
 FORMATTER = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

+ 27 - 2
app/api.py

@@ -26,7 +26,6 @@ def get_rr_account(account_id):
     name = soup.find('h1')
     if name:
         account['name'] = re.sub(r'.*:\s', '', name.text)
-        print(account['name'])
     for row in table.find_all('tr'):
         label = row.find('td').text.strip() 
         if label == 'Region:':
@@ -41,6 +40,32 @@ def get_rr_account(account_id):
             element = row.find('td', {'class': 'imp'})
             if element:
                 account['registation_date'] = parser.parse(element.text)
-    # print(region)
 
     return account
+
+def get_accounts_by_name(account_name):
+    """Get account list by name"""
+    response = requests.get(
+        '{}listed/region/0/{}/0'.format(BASE_URL, account_name),
+        headers=HEADERS,
+    )
+    soup = BeautifulSoup(response.text, 'html.parser')
+    accounts = []
+    account_items = soup.find_all('tr', {'class': 'list_link'})
+    for account_item in account_items:
+        accounts.append({
+            'id': int(account_item.get('user')),
+            'name': account_item.find('td', {'class': 'list_name'}).text.strip(),
+            'level': int(account_item.find('td', {'class': 'list_level'}).text),
+        })
+    return accounts
+
+def send_personal_message(user_id, message):
+    """Send personal message to player"""
+    requests.post(
+        '{}send_personal_message/{}'.format(BASE_URL, user_id),
+        headers=HEADERS,
+        data={
+            'message': message
+        }
+    )

+ 7 - 5
app/commands.py

@@ -2,15 +2,17 @@
 
 from telegram import ParseMode
 
-
-from app import database, functions
-from app.models import TelegramAccount
+from app import LOGGER, database, functions
 
 
 def cmd_start(update, context):
     """Start command"""
+    LOGGER.info('"@%s" start bot', update.message.from_user.username)
     update.message.reply_text(
-        'Hello {},\ntype /help for a list of commands'.format(update.message.from_user.first_name))
+        'Hello {}, use /add_account to add an account, use /help for a list of commands.'.format(
+            update.message.from_user.first_name
+        )
+    )
     telegram_account = database.get_telegram_account(update.message.from_user.id)
     if not telegram_account:
         database.add_telegram_account(update)
@@ -20,8 +22,8 @@ def cmd_help(update, context):
     """Help command"""
     message_list = [
         '**Command list**',
-        '/accounts - list of accounts',
         '/add\\_account - add account to list',
+        '/accounts - list of accounts',
     ]
     message = '\n'.join(message_list)
     update.message.reply_text(message, parse_mode=ParseMode.MARKDOWN)

+ 105 - 15
app/conversations/add_account.py

@@ -1,34 +1,75 @@
 """Add account conversation"""
 
+import random
+import string
+
 from telegram import ParseMode
 from telegram.ext import MessageHandler, CommandHandler, Filters, ConversationHandler
 
-from app import api, functions
+from app import api, functions, database, HEADERS, BASE_URL, LOGGER
+
 
-ACCOUNT_ID, CONFIRM, VERIFICATION = range(3)
+ACCOUNT_ID, CHOOSE, CONFIRM, VERIFICATION = range(4)
 
 def conv_ask_account_id(update, context):
     """Ask account id"""
-    update.message.reply_text('What\'s your Rival Regions acount ID?')
+    LOGGER.info('"@%s" start add account conversation', update.message.from_user.username)
+    update.message.reply_text('Send me your Rival Regions account name or ID.')
     return ACCOUNT_ID
 
-def conv_error_ask_account_id(update, context):
+def conv_account_choose(update, context):
     """Ask max resource"""
+    account_name = update.message.text
+    LOGGER.info(
+        '"@%s" searching for account name "%s"', 
+        update.message.from_user.username,
+        account_name
+    )
+    accounts = api.get_accounts_by_name(account_name)
+    if len(accounts) == 0:
+        update.message.reply_text('No accounts found witht that name, try again')
+        return ACCOUNT_ID
+    context.user_data['account_list'] = accounts
+    message = 'Chose from list:\n'
+    for num, account in enumerate(accounts, start=1):
+        message += '{}) {} ({})\n'.format(num, account['name'], account['level'])
+    update.message.reply_text(message)
+    return CHOOSE
+
+def conv_account_number_error(update, context):
+    """Wrong input error"""
     incorrect_input = update.message.text
+    LOGGER.info(
+        '"@%s" incorrect number number "%s"',
+        update.message.from_user.username,
+        incorrect_input
+    )
     update.message.reply_text(
-        '{}, I don\'t recognize that. What\'s your Rival Regions account ID?'.format(
+        '{}, I don\'t recognize that. What number?'.format(
             incorrect_input
-        ),
+        )
     )
-    return ACCOUNT_ID
+    return CHOOSE
 
 def conv_account_id_confirm(update, context):
-    """Sending announcement"""
+    """Confirm account """
+    account_id = int(update.message.text)
+    if account_id <= 25:
+        account_index = account_id-1
+        if account_index >= len(context.user_data['account_list']):
+            update.message.reply_text('{} is not an option, try again.'.format(account_id),)
+            return CHOOSE
+        account = context.user_data['account_list'][account_index]
+        account_id = account['id']
+    context.user_data['account_id'] = account_id
     update.message.reply_text(
         'Retreiving account from Rival Regions, this might take a couple seconds.'
     )
-    account_id = update.message.text
-    # account = api.get_rr_account(2000326045)
+    LOGGER.info(
+        '"@%s" RR account id "%s"',
+        update.message.from_user.username,
+        account_id
+    )
     account = api.get_rr_account(account_id)
 
     message_list = [
@@ -38,7 +79,7 @@ def conv_account_id_confirm(update, context):
         '*Region*: {}'.format(account['region']),
         '*Residency*: {}'.format(account['residency']),
         '*Registration date*: {}'.format(account['registation_date']),
-        '\nPlease confirm this is your account by typing \'confirm\'',
+        '\nPlease confirm this is your account by typing \'confirm\'.',
     ]
 
     update.message.reply_text(
@@ -50,18 +91,63 @@ def conv_account_id_confirm(update, context):
 def conv_verification(update, context):
     """Sending announcement"""
     update.message.reply_text(
-        'Verification code send to your Rival Region account ' + \
+        'Verification code will be send to your Rival Region account in a couple of secconds. ' + \
         'Check your personal messages for a verification code and send it here.',
         parse_mode=ParseMode.MARKDOWN
     )
+    letters = string.ascii_lowercase
+    verification_code = ''.join(random.choice(letters) for i in range(5))
+    LOGGER.info(
+        '"@%s" verification code "%s"',
+        update.message.from_user.username,
+        verification_code
+    )
+    message = 'Your verification code:\n{}\n\n'.format(verification_code) + \
+    'Please don\'t share this code except with @rr_verification_bot on Telegram.'
+    api.send_personal_message(context.user_data['account_id'], message)
+    context.user_data['verification_code'] = verification_code
     return VERIFICATION
 
 def conv_finish(update, context):
     """Sending announcement"""
+    verification_code = update.message.text
+    if verification_code != context.user_data['verification_code']:
+        LOGGER.info(
+            '"@%s" wrong verification code try "%s"',
+            update.message.from_user.username,
+            verification_code,
+        )
+        if 'tries' not in context.user_data:
+            context.user_data['tries'] = 0
+        context.user_data['tries'] += 1
+        if context.user_data['tries'] >= 3:
+            LOGGER.info(
+                '"@%s" too many wrong verification tries', 
+                update.message.from_user.username
+            )
+            update.message.reply_text(
+                'Failed verification to many times, canceled action.',
+                parse_mode=ParseMode.MARKDOWN
+            )
+            context.user_data.clear()
+            return ConversationHandler.END
+        update.message.reply_text(
+            'Verificated code doesn\'t match, try again.',
+            parse_mode=ParseMode.MARKDOWN
+        )
+        return VERIFICATION
+    account_id = context.user_data['account_id']
+    LOGGER.info(
+        '"@%s" succesfully verified RR account "%s"',
+        update.message.from_user.username,
+        account_id,
+    )
+    database.verify_rr_account(update.message.from_user.id, account_id)
     update.message.reply_text(
-        'Verificated your Rival Region account to Telegram',
+        'Verificated your Rival Region account to Telegram. Type /accounts to see your accounts',
         parse_mode=ParseMode.MARKDOWN
     )
+    context.user_data.clear()
     return ConversationHandler.END
 
 def conv_error_finish(update, context):
@@ -73,7 +159,7 @@ def conv_error_finish(update, context):
         ),
     )
     return VERIFICATION
-    
+
 def conv_cancel(update, context):
     """Cancel announcement"""
     update.message.reply_text('Canceled action.')
@@ -86,7 +172,11 @@ ADD_ACCOUNT_CONV = ConversationHandler(
     states={
         ACCOUNT_ID: [
             MessageHandler(Filters.regex(r'^\d*$'), conv_account_id_confirm),
-            MessageHandler(Filters.text, conv_error_ask_account_id),
+            MessageHandler(Filters.text, conv_account_choose),
+        ],
+        CHOOSE: [
+            MessageHandler(Filters.regex(r'^\d*$'), conv_account_id_confirm),
+            MessageHandler(Filters.text, conv_account_choose),
         ],
         CONFIRM: [
             MessageHandler(Filters.regex('confirm'), conv_verification),

+ 60 - 8
app/database.py

@@ -1,7 +1,9 @@
 """Database functons"""
 
-from app import SESSION
-from app.models import Player, TelegramAccount, TelegramHandle, PlayerTelegram, TelegramVerification
+from datetime import datetime
+
+from app import SESSION, LOGGER
+from app.models import Player, TelegramAccount, TelegramHandle, PlayerTelegram
 
 
 def add_telegram_account(update):
@@ -10,6 +12,7 @@ def add_telegram_account(update):
     telegram_account = TelegramAccount()
     telegram_account.id = update.message.from_user.id
     telegram_account.name = update.message.from_user.name
+    telegram_account.registration_date = datetime.now()
     session.add(telegram_account)
     session.commit()
     session.close()
@@ -22,16 +25,65 @@ def get_telegram_account(telegram_id):
     session.close()
     return telegram_account
 
+def get_rr_accounts(telegram_account):
+    """Get Rival Region accounts associated with Telegram account"""
+    LOGGER.info(
+        '"%s" get RR accounts',
+        telegram_account.id,
+    )
+    session = SESSION()
+    accounts = _get_rr_accounts(session, telegram_account.id)
+    session.close()
+    return accounts
+
+def verify_rr_account(telegram_id, account_id):
+    """Verify RR account in database"""
+    session = SESSION()
+    telegram_account = _get_telegram_account(session, telegram_id)
+    accounts = _get_rr_accounts(session, telegram_id)
+    for account in accounts:
+        if account.id == account_id:
+            LOGGER.info(
+                '"%s" account already connected "%s"',
+                telegram_id,
+                account_id
+            )
+            session.close()
+            return
+
+    active_player_telegrams = session.query(PlayerTelegram) \
+        .filter(PlayerTelegram.until_date_time != None) \
+        .all()
+    for active_player_telegram in active_player_telegrams:
+        LOGGER.info(
+            '"%s" unconnect account "%s"',
+            active_player_telegram.telegram_id,
+            account_id
+        )
+        active_player_telegram.until_date_time = datetime.now()
+
+    LOGGER.info(
+        '"%s" connecting account "%s"',
+        telegram_id,
+        account_id
+    )
+    player_telegram = PlayerTelegram()
+    player_telegram.telegram_id = telegram_account.id
+    player_telegram.player_id = account_id
+    player_telegram.from_date_time = datetime.now()
+    session.add(player_telegram)
+    session.commit()
+    session.close()
+
 def _get_telegram_account(session, telegram_id):
     """Return telegram_account"""
     return session.query(TelegramAccount).get(telegram_id)
 
-def get_rr_accounts(telegram_account):
+def _get_rr_accounts(session, telegram_account_id):
     """Get Rival Region accounts associated with Telegram account"""
-    session = SESSION()
-    rr_accounts = session.query(Player) \
+    return session.query(Player) \
         .join(Player.player_telegram) \
-        .filter(PlayerTelegram.telegram_id == telegram_account.id) \
+        .filter(PlayerTelegram.telegram_id == telegram_account_id) \
+        .filter(PlayerTelegram.until_date_time == None) \
         .all()
-    session.close()
-    return rr_accounts
+

+ 0 - 9
app/models.py

@@ -48,12 +48,3 @@ class PlayerTelegram(Base):
         'Player',
         backref=backref('player_telegram', lazy='dynamic')
     )
-
-class TelegramVerification(Base):
-    """Model for Telegram verification"""
-    __tablename__ = 'telegram_verification'
-    player_id = Column(BigInteger, ForeignKey('player.id'), primary_key=True)
-    telegram_id = Column(BigInteger, ForeignKey('telegram_account.id'), primary_key=True)
-    code = Column(String)
-    date_time = Column(DateTime)
-    confirmed = Column(Boolean, server_default='f', default=False)