<commit_before>#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import configparser
import re
import tempfile
import textwrap
import time
import tweepy

import chem_bot
from chem_bot import SmilesEncoder


def oauth(auth):
    if auth.access_token == '':
        try:
            redirect_url = auth.get_authorization_url()
            print('Get authorized PIN code from url.')
            print(redirect_url)
            pin = input('PIN:')
            auth.get_access_token(pin)
            print('access_token:', auth.access_token)
            print('access_token_secret:', auth.access_token_secret)
            return auth
        except tweepy.TweepError:
            raise Exception(textwrap.dedent("""\
                Error: Failed to get request token.
                Please check [twitter.config].\
                """))
    else:
        return auth


def _tweet_test(api, smiles, screen_name):
    return api.update_status('tes')


def get_config():
    config = configparser.ConfigParser()
    config.read('twitter.config')
    auth = tweepy.OAuthHandler(
        config.get('tokens', 'consumer_key'),
        config.get('tokens', 'consumer_secret'))
    auth.set_access_token(
        config.get('tokens', 'access_token'),
        config.get('tokens', 'access_token_secret'))
    return tweepy.API(auth), config


class Listner(tweepy.StreamListener):
    """Streaming time-line."""
    def __init__(self, api=None):
        super().__init__(api)
        self.iupac_prefix = config.get('general', 'iupac_prefix')
        self.smiles_prefix = config.get('general', 'smiles_prefix')
        self.opsin = config.get('general', 'opsin')

    def on_status(self, status):
        if str(status.text).startswith(self.iupac_prefix):
            print(
                '[CATCH] @{0} >>> {1}'
                .format(status.author.screen_name, status.text))
            iupac = status.text.split(self.iupac_prefix)[1].lstrip(' ')
            if self.check_ascii(iupac):
                smiles, error = chem_bot.util.converter.iupac_to_smiles(
                    iupac, self.opsin)
            else:
                smiles = ''
                error = iupac

            if smiles == '':
                self.reply_iupac_convert_error(error, status.id)
                print('[BOT] Error: {0}'.format(error))
            else:
                self.reply_with_png(
                    api,
                    smiles,
                    status.id,
                    status.author.screen_name,
                    descriptor_type='IUPAC名')
            print('[BOT] continue streaming...')

        if str(status.text).startswith(self.smiles_prefix):
            print(
                '[CATCH] @{0} >>> {1}'
                .format(status.author.screen_name, status.text))
            command = status.text.split(self.smiles_prefix)[1].lstrip(' ')
            smiles, option_d = self.parse_tweet_command(command)
            self.reply_with_png(
                api,
                smiles,
                status.id,
                status.author.screen_name,
                option_d=option_d)
            print('[BOT] continue streaming...')

        return True

    def parse_tweet_command(self, command):
        """Parse command into SMILES/IUPAC and options.

        If command not has any options, return (smile/iupac, None)
        """
        try:
            discriptor, trail_line = re.split(r',[ ]*| +', command, maxsplit=1)
        except ValueError:
            return command, None

        options = re.split(r', *', trail_line)
        option_d = dict([re.split(r': *', x) for x in options])
        return discriptor, option_d

    def reply_iupac_convert_error(self, error, s_id):
        """Tweet for reply about iupac convert error."""
        print('[BOT] IUPAC conversion error')
        return self.tweet_error_message(
            'すまない。私の化学目録に「{0}」という文字は無かった。'
            .format(error), s_id)

    def reply_with_png(self, api, smiles,
                       s_id, screen_name, option_d=None,
                       descriptor_type='SMILES'):
        """Tweet chem graph to user"""
        print('[SMILES]: {0}'.format(smiles))
        tweet = '@{0}'.format(screen_name)

        if smiles == '':
            tweet += (
                '{0}を入力し忘れていないか確認してもらえないだろうか。'
                .format(descriptor_type))
            return self.tweet_error_message(tweet, s_id)

        if self.check_ascii(smiles):
            encoder = SmilesEncoder(smiles)
        else:
            tweet += ' おや、SMILESに使えない文字が入っているようだ。'
            return self.tweet_error_message(tweet, s_id)

        if encoder.mol is None:
            print('Encoding error for [ {0} ]'.format(smiles))<commit_msg>:bug: Fix reply error<commit_after>#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import configparser
import re
import tempfile
import textwrap
import time
import tweepy

import chem_bot
from chem_bot import SmilesEncoder


def oauth(auth):
    if auth.access_token == '':
        try:
            redirect_url = auth.get_authorization_url()
            print('Get authorized PIN code from url.')
            print(redirect_url)
            pin = input('PIN:')
            auth.get_access_token(pin)
            print('access_token:', auth.access_token)
            print('access_token_secret:', auth.access_token_secret)
            return auth
        except tweepy.TweepError:
            raise Exception(textwrap.dedent("""\
                Error: Failed to get request token.
                Please check [twitter.config].\
                """))
    else:
        return auth


def _tweet_test(api, smiles, screen_name):
    return api.update_status('tes')


def get_config():
    config = configparser.ConfigParser()
    config.read('twitter.config')
    auth = tweepy.OAuthHandler(
        config.get('tokens', 'consumer_key'),
        config.get('tokens', 'consumer_secret'))
    auth.set_access_token(
        config.get('tokens', 'access_token'),
        config.get('tokens', 'access_token_secret'))
    return tweepy.API(auth), config


class Listner(tweepy.StreamListener):
    """Streaming time-line."""
    def __init__(self, api=None):
        super().__init__(api)
        self.iupac_prefix = config.get('general', 'iupac_prefix')
        self.smiles_prefix = config.get('general', 'smiles_prefix')
        self.opsin = config.get('general', 'opsin')

    def on_status(self, status):
        if str(status.text).startswith(self.iupac_prefix):
            print(
                '[CATCH] @{0} >>> {1}'
                .format(status.author.screen_name, status.text))
            iupac = status.text.split(self.iupac_prefix)[1].lstrip(' ')
            if self.check_ascii(iupac):
                smiles, error = chem_bot.util.converter.iupac_to_smiles(
                    iupac, self.opsin)
            else:
                smiles = ''
                error = iupac

            if smiles == '':
                self.reply_iupac_convert_error(
                    error, status.id, status.author.screen_name)
                print('[BOT] Error: {0}'.format(error))
            else:
                self.reply_with_png(
                    api,
                    smiles,
                    status.id,
                    status.author.screen_name,
                    descriptor_type='IUPAC名')
            print('[BOT] continue streaming...')

        if str(status.text).startswith(self.smiles_prefix):
            print(
                '[CATCH] @{0} >>> {1}'
                .format(status.author.screen_name, status.text))
            command = status.text.split(self.smiles_prefix)[1].lstrip(' ')
            smiles, option_d = self.parse_tweet_command(command)
            self.reply_with_png(
                api,
                smiles,
                status.id,
                status.author.screen_name,
                option_d=option_d)
            print('[BOT] continue streaming...')

        return True

    def parse_tweet_command(self, command):
        """Parse command into SMILES/IUPAC and options.

        If command not has any options, return (smile/iupac, None)
        """
        try:
            discriptor, trail_line = re.split(r',[ ]*| +', command, maxsplit=1)
        except ValueError:
            return command, None

        options = re.split(r', *', trail_line)
        option_d = dict([re.split(r': *', x) for x in options])
        return discriptor, option_d

    def reply_iupac_convert_error(self, error, s_id, screen_name):
        """Tweet for reply about iupac convert error."""
        print('[BOT] IUPAC conversion error')
        tweet = '@{0} '.format(screen_name)
        return self.tweet_error_message(
            tweet + 'すまない。私の化学目録に「{0}」という文字は無かった。'
            .format(error), s_id)

    def reply_with_png(self, api, smiles,
                       s_id, screen_name, option_d=None,
                       descriptor_type='SMILES'):
        """Tweet chem graph to user"""
        print('[SMILES]: {0}'.format(smiles))
        tweet = '@{0}'.format(screen_name)

        if smiles == '':
            tweet += (
                '{0}を入力し忘れていないか確認してもらえないだろうか。'
                .format(descriptor_type))
            return self.tweet_error_message(tweet, s_id)

        if self.check_ascii(smiles):
            encoder = SmilesEncoder(smiles)
        else:
            tweet += ' おや、SMILESに使えない文字が入っているようだ。'
            return self.tweet_error_message(tweet, s_id)

        if encoder.mol is None:
            print('Encoding error for [ {0} ]'.format(smiles))
{'fraction_non_alphanumeric': 0.11956863155690503, 'fraction_numerical': 0.00324573343105434, 'mean_word_length': 1.9228886168910648, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4859805', 'n_tokens_mistral': 2979, 'n_tokens_neox': 2871, 'n_words': 557}