Exemplo n.º 1
0
    def __init__(self, constantJSON='data/constants.json'):
        with open(constantJSON, 'r', encoding='utf8') as file:
            constants = json.load(file)

        # set informations
        self.sets = constants['sets']
        self.setIds = {}
        for id, setDetails in self.sets.items():
            self.setIds[setDetails['name']] = id

        # classes
        self.classes = constants.get('classes', {})

        # special keywords to replace
        self.__specials = {}
        for key, values in constants['specials'].items():
            cards = [CardDB.cleanName(card) for card in values]
            self.__specials[CardDB.cleanName(key)] = cards

        self.specialNames = self.__specials.keys()

        # alternative card names
        self.__translations = {}
        for key, alts in constants['alternative_names'].items():
            org = CardDB.cleanName(key)

            if isinstance(alts, list):
                for alt in alts:
                    self.__translations[CardDB.cleanName(alt)] = org
            else:
                self.__translations[CardDB.cleanName(alts)] = org

        self.alternativeNames = self.__translations.keys()
Exemplo n.º 2
0
    def __getCards(self, text):
        """look for [[cardname]]s in text and collect them"""
        cards = []
        if len(text) < 6:
            return cards

        # regex for escaped (new reddit and some apps) and unescaped brackets
        for card in re.finditer(r'\\?\[\\?\[([^\]\\]{1,30})\\?\]\\?\]', text):
            card = card.group(1)
            log.debug("adding a card: %s", card)
            cleanCard = CardDB.cleanName(card)

            if cleanCard:
                log.debug("cleaned card name: %s", cleanCard)
                # slight spelling error?
                checkedCard = self.spellChecker.correct(cleanCard)
                if cleanCard != checkedCard:
                    log.info("spelling fixed: %s -> %s",
                        cleanCard, checkedCard)

                # is alternative name?
                checkedCard = self.constants.translateAlt(checkedCard)
                # add cardname
                if checkedCard not in cards:
                    cards.append(checkedCard)
                else:
                    log.info("duplicate card: %s", card)

            # sometimes cards are removed, get more to fill limit
            if len(cards) >= self.constants.CARD_LIMIT * 2:
                break

        return cards
Exemplo n.º 3
0
    def test_loadInfoTempl_simple(self):

        constantDict = {
            'sets' : { },
            'specials' : { 'dream' : ['no'] },
            'alternative_names' : { 'quickshot' : 'qs' }
        }

        try:
            if os.path.isfile('data/info_msg.templ'):
                os.rename('data/info_msg.templ', 'data/_info_msg.templ')

            with TempJson(constantDict) as constJson, \
                    TempJson({}) as emptyJson:

                with open('data/info_msg.templ', 'w', newline="\n") as f:
                    f.write('{user}-{alts}-{tokens}-{special}')

                c = Constants(constJson)
                db = CardDB(constants=c, cardJSON=emptyJson, tokenJSON=emptyJson, tempJSON=emptyJson)
                helper = HSHelper(db, c)

                info = helper.getInfoText('user')
                self.assertEqual(info, 'user-qs--dream')

        finally:
            removeFile('data/info_msg.templ')
            if os.path.isfile('data/_info_msg.templ'):
                os.rename('data/_info_msg.templ', 'data/info_msg.templ')
Exemplo n.º 4
0
    def test_CardDB(self):
        cardDict = {
            'Quick Shot': {
                'type': 'Spell',
                'hpwn': 14459,
                'cdn': 'https://media-Hearth.cursecdn.com/14459.png',
                'desc': 'Deal 3 damage. Draw a card.',
                'hp': 1,
                'class': 'Hunter',
                'subType': 'Mech',
                'set': 'Basic',
                'rarity': 'Common',
                'atk': 3,
                'head': 'quick-shot',
                'name': 'Quick Shot',
                'cost': 2
            }
        }

        constantDict = {
            'sets': {
                '01': {
                    'name': 'Basic'
                }
            },
            'specials': {},
            'alternative_names': {}
        }

        with TempJson(constantDict) as constJson, \
                TempJson(cardDict) as cardJson, \
                TempJson({}) as emptyJson:

            c = Constants(constJson)

            db = CardDB(constants=c,
                        cardJSON=cardJson,
                        tokenJSON=emptyJson,
                        tempJSON=emptyJson)

            self.assertEqual(db.cardNames(), ['quickshot'])
            self.assertEqual(db.tokens, [])
            self.assertTrue('quickshot' in db)
            self.assertFalse('slowshot' in db)
            self.assertTrue('Quick Shot' in db['quickshot'])
Exemplo n.º 5
0
    def test_RefreshCardDB(self):
        cardDict = {
            'Quick Shot': {
                'type': 'Spell',
                'hpwn': 14459,
                'cdn': 'https://media-Hearth.cursecdn.com/14459.png',
                'desc': 'Deal 3 damage. Draw a card.',
                'hp': 1,
                'class': 'Hunter',
                'subType': "Mech",
                'set': 'Basic',
                'rarity': 'Common',
                'atk': 3,
                'head': 'quick-shot',
                'name': 'Quick Shot',
                'cost': 2
            }
        }

        constantDict = {
            'sets' : { '01' : {'name' : 'Basic'} },
            'specials' : { },
            'alternative_names' : { }
        }

        with TempJson(constantDict) as constJson, \
                TempJson(cardDict) as cardJson, \
                TempJson({}) as emptyJson:

            c = Constants(constJson)
            db = CardDB(constants=c, cardJSON=emptyJson, tokenJSON=emptyJson, tempJSON='notexisting.json')

            self.assertEqual(db.cardNames(), [])
            self.assertFalse('quickshot' in db)

            db.tempJSON = cardJson
            db.refreshTemp()

            self.assertTrue('quickshot' in db)
            self.assertTrue('Quick Shot' in db['quickshot'])
Exemplo n.º 6
0
    def getCards(self, text):
        """look for [[cardname]]s in text and collect them securely"""
        cards = []
        if len(text) < 6:
            return cards

        open_bracket = False
        card = ''

        # could be regex, but I rather not parse everything evil users are sending
        for i in range(1, len(text)):
            c = text[i]

            if open_bracket and c != ']':
                card += c
            if c == '[' and text[i - 1] == '[':
                open_bracket = True
            if c == ']' and open_bracket:
                if len(card) > 0:
                    log.debug("adding a card: %s", card)
                    cleanCard = CardDB.cleanName(card)

                    if cleanCard:
                        log.debug("cleaned card name: %s", cleanCard)
                        # slight spelling error?
                        checkedCard = self.spellChecker.correct(cleanCard)
                        if cleanCard != checkedCard:
                            log.info("spelling fixed: %s -> %s", cleanCard,
                                     checkedCard)

                        # is alternative name?
                        checkedCard = self.constants.translateAlt(checkedCard)
                        # add cardname
                        if checkedCard not in cards:
                            cards.append(checkedCard)
                        else:
                            log.info("duplicate card: %s", card)

                card = ''
                open_bracket = False
                if len(cards) >= self.constants.CARD_LIMIT:
                    break

            if len(card) > 30:
                card = ''
                open_bracket = False

        return cards
Exemplo n.º 7
0
def main():
    log.debug('main() hearthscan-bot starting')

    # load constant values
    constants = Constants()
    # init answered comments sqlite DB
    answeredDB = commentDB.DB()
    # load card DB
    url = 'https://raw.githubusercontent.com/d-schmidt/hearthscan-bot/master/data/tempinfo.json'
    cardDB = CardDB(constants=constants, tempJSONUrl=url)
    # init hs helper for hearthstone stuff
    helper = HSHelper(cardDB, constants)
    # pm spam filter cache
    pmUserCache = {}

    def submissionListener(r, submission):
        answerSubmission(submission, helper)

    def commentListener(r, comment):
        answerComment(r, comment, answeredDB, helper)

    def mentionListener(r, comment):
        answerMention(r, comment, answeredDB, helper)

    def pmListener(r, message):
        answerPM(r, message, pmUserCache, helper)

    def postAction():
        cleanPMUserCache(pmUserCache)
        cardDB.refreshTemp()

    try:
        RedditBot(subreddits=credentials.subreddits,
                    newLimit=250,
                    connectAttempts=5,
                    userBlacklist=set(credentials.userBlacklist)) \
                .withSubmissionListener(submissionListener) \
                .withCommentListener(commentListener) \
                .withMentionListener(mentionListener) \
                .withPMListener(pmListener) \
                .run(postAction)
    except:
        log.exception('main() RedditBot failed unexpectedly')
    finally:
        log.warning('main() leaving hearthscan-bot')
        answeredDB.close()
Exemplo n.º 8
0
 def test_CleanName(self):
     self.assertEqual(CardDB.cleanName('Ab: 1c'), 'abc')
Exemplo n.º 9
0
    def test_getCardsFromComment(self):

        cardDict = {
            'Quick Shot': {
                'type': 'Spell',
                'hpwn': 14459,
                'cdn': 'https://media-Hearth.cursecdn.com/14459.png',
                'desc': 'Deal 3 damage. Draw a card.',
                'hp': 1,
                'class': 'Hunter',
                'subType': "Mech",
                'set': 'Basic',
                'rarity': 'Common',
                'atk': 3,
                'head': 'quick-shot',
                'name': 'Quick Shot',
                'cost': 2
            }
        }

        # we need more cards (Card AA - Card UU)
        for i in range(21):
            name = 'Card ' + chr(97 + i)
            cardDict[name] = cardDict['Quick Shot'].copy()
            cardDict[name]['name'] = name

        constantDict = {
            'sets': {
                '01': {
                    'name': 'Basic'
                }
            },
            'specials': {},
            'alternative_names': {
                "quickshot": "qs"
            }
        }

        with TempJson(constantDict) as constJson, \
                TempJson(cardDict) as cardJson, \
                TempJson({}) as emptyJson:

            c = Constants(constJson)
            db = CardDB(constants=c,
                        cardJSON=cardJson,
                        tokenJSON=emptyJson,
                        tempJSON=emptyJson)
            helper = HSHelper(db, c)

            # simple find
            text = '[[Quick Shot]]'
            cards, text = helper.parseText(text)
            self.assertEqual(cards, ['quickshot'], 'simple card')
            self.assertTrue('Quick Shot' in text)
            # escaped simple find
            text = '\\[\\[quickshot\\]\\]'
            cards, text = helper.parseText(text)
            self.assertEqual(cards, ['quickshot'], 'simple card')
            self.assertTrue('Quick Shot' in text)
            # two cards, cleanName
            text = ' [[card a]] world [[quickshot 42]] '
            cards, text = helper.parseText(text)
            self.assertEqual(cards, ['carda', 'quickshot'],
                             'multi cards, clean')
            self.assertTrue('Quick Shot' in text)
            self.assertTrue('Card a' in text)
            # spell check
            text = '[[Quic Shot]]'
            cards, text = helper.parseText(text)
            self.assertEqual(cards, ['quickshot'], 'simple card')
            self.assertTrue('Quick Shot' in text)
            # alternative name
            text = '[[QS]]'
            cards, text = helper.parseText(text)
            self.assertEqual(cards, ['quickshot'], 'alternative name')
            self.assertTrue('Quick Shot' in text)
            # test card limit always working
            cardsNames = [
                'card' + chr(97 + i) for i in range(c.CARD_LIMIT + 1)
            ]
            cardsNames = ['no card'] + cardsNames
            text = '[[' + ']][['.join(cardsNames) + ']]'
            cards, text = helper.parseText(text)
            self.assertEqual(cards, cardsNames[1:-1],
                             'CARD_LIMIT cards expected')
            self.assertTrue('no card' not in text, 'unknown should be skipped')
            for i in range(c.CARD_LIMIT):
                self.assertTrue('Card ' + chr(97 + i) in text)
            # test short text
            text = '[[a]]'
            cards, text = helper.parseText(text)
            self.assertEqual(len(cards), 0, 'no cards')
            self.assertEqual(len(text), 0, 'no cards')
            # test no valid text
            text = '[[123]] [abc]'
            cards, text = helper.parseText(text)
            self.assertEqual(len(cards), 0, 'no valid text')
            self.assertEqual(len(text), 0, 'no valid text')
            # card too long
            text = '[[123456789012345678901234567890abc]]'
            cards, text = helper.parseText(text)
            self.assertEqual(len(cards), 0, 'card too long')
            self.assertEqual(len(text), 0, 'card too long')
Exemplo n.º 10
0
 def test_CleanName(self):
     self.assertEqual(CardDB.cleanName('Ab: 1c'), 'abc')
Exemplo n.º 11
0
    def test_getCardsFromComment(self):

        cardDict = {
            'Quick Shot': {
                'type': 'Spell',
                'hpwn': 14459,
                'cdn': 'https://media-Hearth.cursecdn.com/14459.png',
                'desc': 'Deal 3 damage. Draw a card.',
                'hp': 1,
                'class': 'Hunter',
                'subType': "Mech",
                'set': 'Basic',
                'rarity': 'Common',
                'atk': 3,
                'head': 'quick-shot',
                'name': 'Quick Shot',
                'cost': 2
            }
        }

        constantDict = {
            'sets' : { '01' : {'name' : 'Basic'} },
            'specials' : { },
            'alternative_names' : { "quickshot" : "qs" }
        }

        with TempJson(constantDict) as constJson, \
                TempJson(cardDict) as cardJson, \
                TempJson({}) as emptyJson:

            c = Constants(constJson)
            db = CardDB(constants=c, cardJSON=cardJson, tokenJSON=emptyJson, tempJSON=emptyJson)
            helper = HSHelper(db, c)

            # simple find
            text = '[[test]]'
            cards, text = helper.parseText(text)
            self.assertEqual(cards, ['test'], 'simple card')
            self.assertEqual(len(text), 0, 'unknown card')
            # escaped simple find
            text = '\\[\\[test\\]\\]'
            cards, text = helper.parseText(text)
            self.assertEqual(cards, ['test'], 'simple card')
            self.assertEqual(len(text), 0, 'unknown card')
            # two cards, cleanName
            text = ' [[hello]] world [[Ab 123c]] '
            cards, text = helper.parseText(text)
            self.assertEqual(cards, ['hello', 'abc'], 'multi cards, clean')
            self.assertEqual(len(text), 0, 'unknown cards')
            # spell check
            text = '[[Quic Shot]]'
            cards, text = helper.parseText(text)
            self.assertEqual(cards, ['quickshot'], 'simple card')
            self.assertTrue('Quick Shot' in text)
            # alternative name
            text = '[[QS]]'
            cards, text = helper.parseText(text)
            self.assertEqual(cards, ['quickshot'], 'alternative name')
            self.assertTrue('Quick Shot' in text)
            # test card limit
            cardsNames = [chr(97 + i) * 2 for i in range(c.CARD_LIMIT + 1)]
            text = '[[' + ']][['.join(cardsNames) + ']]'
            cards, text = helper.parseText(text)
            self.assertEqual(cards, cardsNames[:-1], 'card limit')
            self.assertEqual(len(text), 0, 'unknown cards')
            # test short text
            text = '[[a]]'
            cards, text = helper.parseText(text)
            self.assertEqual(len(cards), 0, 'no cards')
            self.assertEqual(len(text), 0, 'no cards')
            # test no valid text
            text = '[[123]] [abc]'
            cards, text = helper.parseText(text)
            self.assertEqual(len(cards), 0, 'no valid text')
            self.assertEqual(len(text), 0, 'no valid text')
            # card too long
            text = '[[123456789012345678901234567890abc]]'
            cards, text = helper.parseText(text)
            self.assertEqual(len(cards), 0, 'card too long')
            self.assertEqual(len(text), 0, 'card too long')