Skip to content

Commit 5101419

Browse files
authored
Merge pull request #53 from hardaker/cast-spells
Add functionality to cast spells from the CLI
2 parents 056bf79 + e9187a7 commit 5101419

File tree

2 files changed

+190
-4
lines changed

2 files changed

+190
-4
lines changed

habitipy/cli.py

Lines changed: 189 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ class ApplicationWithApi(ConfiguredApplication):
218218
"""Application with configured Habitica API"""
219219
api = None # type: Habitipy
220220

221-
def main(self):
221+
def main(self, *_args):
222222
super().main()
223223
self.api = Habitipy(self.config)
224224

@@ -556,15 +556,201 @@ def main(self):
556556
print(f'{food:<30}: {food_list[food]}')
557557

558558

559+
@HabiticaCli.subcommand('cast')
560+
class Cast(ApplicationWithApi):
561+
"""Casts spells"""
562+
DESCRIPTION=_("Cast a spell")
563+
564+
cast_count = cli.SwitchAttr(
565+
['-C', '--cast-times'], argtype=int, default=1,
566+
help=_("Number of times to cast the spell.")
567+
) # noqa: Q000
568+
sleep_time = cli.SwitchAttr(
569+
['-S', '--sleep-time'], argtype=int, default=1,
570+
help=_("Time to wait between each cast to avoid overloading the server")) # noqa: Q000
571+
572+
def main(self, *_arguments):
573+
super().main()
574+
575+
576+
class CastNoArguments(Cast):
577+
"""Cast a spell with no arguments."""
578+
def main(self, *arguments):
579+
super().main()
580+
spell = arguments[0]
581+
582+
for _i in range(self.cast_count):
583+
print(_(f"casting {spell}..."))
584+
_response = self.api.user["class"].cast[spell].post()
585+
time.sleep(self.sleep_time)
586+
587+
588+
class CastOnTask(Cast):
589+
"""Casts spells on a task"""
590+
def main(self, *arguments):
591+
super().main()
592+
if len(arguments) != 3 or arguments[1] not in ["todos", "habits", "dailies"]:
593+
self.log.error(_("usage: cast task (todos|habits|dailies) number"))
594+
return
595+
596+
(spell, domain, number) = arguments
597+
number = int(number)
598+
tasks = self.api.tasks.user.get(type=domain)
599+
600+
if number > len(tasks):
601+
self.log.error(_("selection number is too high"))
602+
return
603+
604+
for _i in range(self.cast_count):
605+
print(_(f"casting {spell}..."))
606+
self.api.user["class"].cast[spell].post(uri_params = {
607+
'targetId': tasks[number-1]['id'],
608+
})
609+
time.sleep(self.sleep_time)
610+
611+
612+
# Healer spells
613+
@Cast.subcommand('heal')
614+
class Heal(CastNoArguments):
615+
"""Cast heal."""
616+
DESCRIPTION=_("Cast Healer's Healing Light")
617+
def main(self, *args, **kwargs):
618+
super().main('heal', *args, **kwargs)
619+
620+
621+
@Cast.subcommand('brightness')
622+
class Brightness(CastNoArguments):
623+
"""Cast brightness."""
624+
DESCRIPTION=_("Cast Healer's Searing Brightness")
625+
def main(self, *args, **kwargs):
626+
super().main('brightness', *args, **kwargs)
627+
628+
629+
@Cast.subcommand('protectAura')
630+
class ProtectAura(CastNoArguments):
631+
"""Cast protectaura."""
632+
DESCRIPTION=_("Cast Healer's Protective Aura")
633+
def main(self, *args, **kwargs):
634+
super().main('protectAura', *args, **kwargs)
635+
636+
637+
@Cast.subcommand('healAll')
638+
class HealAll(CastNoArguments):
639+
"""Cast healall"""
640+
DESCRIPTION=_("Cast Healer's Blessing")
641+
def main(self, *args, **kwargs):
642+
super().main('healAll', *args, **kwargs)
643+
644+
645+
# Mage Spells
646+
@Cast.subcommand('fireball')
647+
class FireBall(CastOnTask):
648+
"""Cast fireball."""
649+
DESCRIPTION=_("Cast Mage's Burst of Flames on a task")
650+
def main(self, *args, **kwargs):
651+
super().main('fireball', *args, **kwargs)
652+
653+
654+
@Cast.subcommand('ethereal') # deliberately different
655+
class Ethereal(CastNoArguments):
656+
"""Cast ethereal."""
657+
DESCRIPTION=_("Cast Mage's Ethereal Surge")
658+
def main(self, *args, **kwargs):
659+
super().main('mpheal', *args, **kwargs)
660+
661+
662+
@Cast.subcommand('earth')
663+
class Earth(CastNoArguments):
664+
"""Cast earth."""
665+
DESCRIPTION=_("Cast Mage's Earthquake")
666+
def main(self, *args, **kwargs):
667+
super().main('earth', *args, **kwargs)
668+
669+
670+
@Cast.subcommand('frost')
671+
class Frost(CastNoArguments):
672+
"""Cast frost."""
673+
DESCRIPTION=_("Cast Mage's Chilling Frost")
674+
def main(self, *args, **kwargs):
675+
super().main('frost', *args, **kwargs)
676+
677+
678+
# Rogue spells
679+
680+
@Cast.subcommand('backstab')
681+
class Backstab(CastOnTask):
682+
"Cast backstab"
683+
DESCRIPTION=_("Cast Thief's Backstab on a task")
684+
def main(self, *args, **kwargs):
685+
super().main('backStab', *args, **kwargs)
686+
687+
688+
@Cast.subcommand('pickpocket')
689+
class PickPocket(CastOnTask):
690+
"Cast pickpocket"
691+
DESCRIPTION=_("Cast Thief's Pickpocket on a task")
692+
def main(self, *args, **kwargs):
693+
super().main('pickPocket', *args, **kwargs)
694+
695+
@Cast.subcommand('tools') # deliberately different
696+
class ToolsOfTrade(CastNoArguments):
697+
"""Cast tools of the trade."""
698+
DESCRIPTION=_("Cast Thief's Tools of the Trade")
699+
def main(self, *args, **kwargs):
700+
super().main('toolsOfTrade', *args, **kwargs)
701+
702+
703+
@Cast.subcommand('stealth')
704+
class Stealth(CastNoArguments):
705+
"""Cast stealth."""
706+
DESCRIPTION=_("Cast Thief's Stealth")
707+
def main(self, *args, **kwargs):
708+
super().main('stealth', *args, **kwargs)
709+
710+
711+
# Warrior spells
712+
713+
714+
@Cast.subcommand('smash')
715+
class Smash(CastOnTask):
716+
"""Cast smash."""
717+
DESCRIPTION=_("Cast Warrior's Brutal Smash on a task")
718+
def main(self, *args, **kwargs):
719+
super().main('smash', *args, **kwargs)
720+
721+
722+
@Cast.subcommand('defense') # deliberately different
723+
class DefensiveStance(CastNoArguments):
724+
"""Cast defense."""
725+
DESCRIPTION=_("Cast Warrior's Defensive Stance")
726+
def main(self, *args, **kwargs):
727+
super().main('defensiveStance', *args, **kwargs)
728+
729+
730+
@Cast.subcommand('intimidate')
731+
class Intimidate(CastNoArguments):
732+
"""Cast intimidate."""
733+
DESCRIPTION=_("Cast Warrior's Intimidating Gaze")
734+
def main(self, *args, **kwargs):
735+
super().main('intimidate', *args, **kwargs)
736+
737+
738+
@Cast.subcommand('presence')
739+
class ValorousPresence(CastNoArguments):
740+
"""Cast ValorousPresence"""
741+
DESCRIPTION=_("Cast Warrior's Valorous Presence")
742+
def main(self, *args, **kwargs):
743+
super().main('valorousPresence', *args, **kwargs)
744+
745+
559746
@HabiticaCli.subcommand('habits')
560-
class Habits(TasksPrint): # pylint: disable=missing-class-docstring
747+
class Habits(TasksPrint): # pylint: disable=missing-docstring
561748
DESCRIPTION = _("List, up and down habit tasks") # noqa: Q000
562749
domain = 'habits'
563750
def domain_format(self, habit): # pylint: disable=arguments-renamed
564751
score = ScoreInfo(self.config['show_style'], habit['value'])
565752
return _("{0} {text}").format(score, **habit) # noqa: Q000
566753

567-
568754
@HabiticaCli.subcommand('dailies')
569755
class Dailys(TasksPrint): # pylint: disable=missing-class-docstring
570756
DESCRIPTION = _("List, check, uncheck daily tasks") # noqa: Q000

pylintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ indent-string=' '
109109
max-line-length=100
110110

111111
# Maximum number of lines in a module
112-
max-module-lines=1000
112+
max-module-lines=2000
113113

114114
# List of optional constructs for which whitespace checking is disabled. `dict-
115115
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.

0 commit comments

Comments
 (0)