diff --git a/app/bot_cli.py b/app/bot_cli.py index 91c0dc0..8d725a9 100644 --- a/app/bot_cli.py +++ b/app/bot_cli.py @@ -23,6 +23,19 @@ def cmd_register(_args): _print_user(bot.get_user_api()) +def cmd_set_pin(args): + bot = CM_BOT_HAL() + if not bot.is_whatsapp_url(args.link): + print(f"ERROR: not a WhatsApp URL: {args.link}", file=sys.stderr) + sys.exit(2) + t_username, f_username = bot.get_whatsapp_link_username(args.link) + success = bot.set_security_pin_api(args.link) + if not success: + print("ERROR: set_security_pin_api returned a falsy result", file=sys.stderr) + sys.exit(1) + print(f"OK: f_username={f_username} t_username={t_username}") + + def build_parser() -> argparse.ArgumentParser: p = argparse.ArgumentParser( prog="bot_cli", @@ -33,6 +46,10 @@ def build_parser() -> argparse.ArgumentParser: sp = sub.add_parser("register", aliases=["get-acc"], help="Get next available account (Telegram /1).") sp.set_defaults(func=cmd_register) + sp = sub.add_parser("set-pin", help="Set security PIN from a WhatsApp link (Telegram /2).") + sp.add_argument("link") + sp.set_defaults(func=cmd_set_pin) + return p diff --git a/tests/test_bot_cli.py b/tests/test_bot_cli.py index 35f0d79..78377dd 100644 --- a/tests/test_bot_cli.py +++ b/tests/test_bot_cli.py @@ -65,5 +65,46 @@ class CmdRegisterTests(unittest.TestCase): self.assertIs(args.func, bot_cli.cmd_register) +class CmdSetPinTests(unittest.TestCase): + @mock.patch.object(bot_cli, "CM_BOT_HAL") + def test_rejects_invalid_whatsapp_url(self, mock_hal_class): + mock_hal = mock_hal_class.return_value + mock_hal.is_whatsapp_url.return_value = False + with self.assertRaises(SystemExit) as cm: + bot_cli.cmd_set_pin(argparse.Namespace(link="https://not-whatsapp.example/x")) + self.assertEqual(cm.exception.code, 2) + mock_hal.set_security_pin_api.assert_not_called() + + @mock.patch.object(bot_cli, "CM_BOT_HAL") + def test_extracts_names_locally_and_succeeds(self, mock_hal_class): + mock_hal = mock_hal_class.return_value + mock_hal.is_whatsapp_url.return_value = True + mock_hal.get_whatsapp_link_username.return_value = ("t_user_42", "f_user_42") + mock_hal.set_security_pin_api.return_value = True + out = io.StringIO() + with contextlib.redirect_stdout(out): + bot_cli.cmd_set_pin(argparse.Namespace(link="https://chat.whatsapp.com/abc")) + text = out.getvalue() + self.assertIn("f_username=f_user_42", text) + self.assertIn("t_username=t_user_42", text) + mock_hal.set_security_pin_api.assert_called_once_with("https://chat.whatsapp.com/abc") + + @mock.patch.object(bot_cli, "CM_BOT_HAL") + def test_falsy_set_security_pin_result_exits_nonzero(self, mock_hal_class): + mock_hal = mock_hal_class.return_value + mock_hal.is_whatsapp_url.return_value = True + mock_hal.get_whatsapp_link_username.return_value = ("t", "f") + mock_hal.set_security_pin_api.return_value = False + with self.assertRaises(SystemExit) as cm: + bot_cli.cmd_set_pin(argparse.Namespace(link="https://chat.whatsapp.com/abc")) + self.assertEqual(cm.exception.code, 1) + + def test_set_pin_subparser_dispatches(self): + parser = bot_cli.build_parser() + args = parser.parse_args(["set-pin", "https://chat.whatsapp.com/abc"]) + self.assertIs(args.func, bot_cli.cmd_set_pin) + self.assertEqual(args.link, "https://chat.whatsapp.com/abc") + + if __name__ == "__main__": unittest.main()