Example #1
0
def main():  # noqa: C901
    """Main entrypoint"""
    arguments = parse_arguments()
    loop = asyncio.get_event_loop()

    clients = []
    phones, authtoken = get_phones(arguments)
    telegram_api = get_telegram_api()

    if web_available:
        web = core.Web(telegram_api=telegram_api) if arguments.web else None
    else:
        if arguments.heroku_web_internal:
            raise RuntimeError("Web required but unavailable")
        web = None

    while telegram_api is None:
        if web:
            loop.run_until_complete(web.start())
            print("Web mode ready for configuration")  # noqa: T001
            if not arguments.heroku_web_internal:
                print("Please visit http://localhost:" +
                      str(web.port))  # noqa: T001
            loop.run_until_complete(web.wait_for_telegram_api_setup())
            telegram_api = web.telegram_api
        else:
            run_config({})
            importlib.invalidate_caches()
            telegram_api = get_telegram_api()

    if os.environ.get("authorization_strings", False):
        if os.environ.get(
                "DYNO", False
        ) or arguments.heroku_web_internal or arguments.heroku_deps_internal:
            app, config = heroku.get_app(os.environ["authorization_strings"],
                                         os.environ["heroku_api_key"],
                                         telegram_api, False, True)
        if arguments.heroku_web_internal:
            app.scale_formation_process("worker-never-touch", 0)
            signal.signal(signal.SIGTERM, functools.partial(sigterm, app))
        elif arguments.heroku_deps_internal:
            try:
                app.scale_formation_process("web", 0)
                app.scale_formation_process("worker-never-touch", 0)
            except requests.exceptions.HTTPError as e:
                if e.response.status_code != 404:
                    # The dynos don't exist on the very first deployment, so don't try to scale
                    raise
            else:
                atexit.register(
                    functools.partial(app.scale_formation_process,
                                      "restart-worker-never-touch", 1))
        elif arguments.heroku_restart_internal:
            signal.signal(signal.SIGTERM, functools.partial(sigterm, app))
            while True:
                time.sleep(60)
        elif os.environ.get("DYNO", False):
            signal.signal(signal.SIGTERM, functools.partial(sigterm, app))

    if authtoken:
        for phone, token in authtoken.items():
            try:
                clients += [
                    TelegramClient(StringSession(token),
                                   telegram_api.ID,
                                   telegram_api.HASH,
                                   connection_retries=None).start(phone)
                ]
            except ValueError:
                run_config({})
                return
            clients[-1].phone = phone  # for consistency
    if not clients and not phones:
        if web:
            if not web.running.is_set():
                loop.run_until_complete(web.start())
                print("Web mode ready for configuration")  # noqa: T001
                if not arguments.heroku_web_internal:
                    print("Please visit http://localhost:" +
                          str(web.port))  # noqa: T001
            loop.run_until_complete(web.wait_for_clients_setup())
            arguments.heroku = web.heroku_api_key
            clients = web.clients
            for client in clients:
                if arguments.heroku:
                    session = StringSession()
                else:
                    session = SQLiteSession(
                        os.path.join(os.path.dirname(utils.get_base_dir()),
                                     "t-userbot-" + client.phone))
                session.set_dc(client.session.dc_id,
                               client.session.server_address,
                               client.session.port)
                session.auth_key = client.session.auth_key
                if not arguments.heroku:
                    session.save()
                client.session = session
        else:
            try:
                phones = [input("Please enter your phone: ")]
            except EOFError:
                print()  # noqa: T001
                print("=" * 30)  # noqa: T001
                print()  # noqa: T001
                print(
                    "Hello. If you are seeing this, it means YOU ARE DOING SOMETHING WRONG!"
                )  # noqa: T001
                print()  # noqa: T001
                print(
                    "It is likely that you tried to deploy to heroku - "  # noqa: T001
                    "you cannot do this via the web interface.")
                print("To deploy to heroku, go to "  # noqa: T001
                      "https://BLIBWT.github.io/heroku to learn more")
                print()  # noqa: T001
                print(
                    "In addition, you seem to have forked the t-userbot repo. THIS IS WRONG!"
                )  # noqa: T001
                print(
                    "You should remove the forked repo, and read https://BLIBWT.github.io"
                )  # noqa: T001
                print()  # noqa: T001
                print(
                    "If you're not using heroku, then you are using a non-interactive prompt but "  # noqa: T001
                    "you have not got a session configured, meaning authentication to Telegram is "
                    "impossible.")  # noqa: T001
                print()  # noqa: T001
                print("THIS ERROR IS YOUR FAULT. DO NOT REPORT IT AS A BUG!"
                      )  # noqa: T001
                print("Goodbye.")  # noqa: T001
                sys.exit(1)
    for phone in phones:
        try:
            clients += [
                TelegramClient(
                    StringSession() if arguments.heroku else os.path.join(
                        os.path.dirname(utils.get_base_dir()), "t-userbot" +
                        (("-" + phone) if phone else "")),
                    telegram_api.ID,
                    telegram_api.HASH,
                    connection_retries=None).start(phone)
            ]
        except sqlite3.OperationalError as ex:
            print(
                "Error initialising phone " + (phone if phone else "unknown") +
                " " + ",".join(ex.args)  # noqa: T001
                +
                ": this is probably your fault. Try checking that this is the only instance running and "
                "that the session is not copied. If that doesn't help, delete the file named '"
                "t-userbot" + (("-" + phone) if phone else "") + ".session'")
            continue
        except (ValueError, ApiIdInvalidError):
            # Bad API hash/ID
            run_config({})
            return
        except PhoneNumberInvalidError:
            print(
                "Please check the phone number. Use international format (+XX...)"  # noqa: T001
                " and don't put spaces in it.")
            continue
        clients[
            -1].phone = phone  # so we can format stuff nicer in configurator

    if arguments.heroku:
        if isinstance(arguments.heroku, str):
            key = arguments.heroku
        else:
            key = input(
                "Please enter your Heroku API key (from https://dashboard.heroku.com/account): "
            ).strip()
        app = heroku.publish(clients, key, telegram_api)
        print(
            "Installed to heroku successfully! Type .help in Telegram for help."
        )  # noqa: T001
        if web:
            web.redirect_url = app.web_url
            web.ready.set()
            loop.run_until_complete(web.root_redirected.wait())
        return

    loops = [amain(client, clients, web, arguments) for client in clients]

    loop.set_exception_handler(lambda _, x: logging.error(
        "Exception on event loop! %s", x["message"], exc_info=x["exception"]))
    loop.run_until_complete(asyncio.gather(*loops))
Example #2
0
def main():  # noqa: C901
    """Main entrypoint"""
    arguments = parse_arguments()
    loop = asyncio.get_event_loop()

    clients = []
    phones, authtoken = get_phones(arguments)
    api_token = get_api_token(arguments)
    proxy, conn = get_proxy(arguments)

    if web_available:
        web = core.Web(data_root=arguments.data_root,
                       api_token=api_token,
                       test_dc=arguments.test_dc is not False,
                       proxy=proxy,
                       connection=conn) if arguments.web else None
    else:
        if arguments.heroku_web_internal:
            raise RuntimeError("Web required but unavailable")
        web = None

    while api_token is None:
        if arguments.no_auth:
            return
        if web:
            loop.run_until_complete(web.start())
            print("Web mode ready for configuration")  # noqa: T001
            if not arguments.heroku_web_internal:
                port = str(web.port)
                if platform.system(
                ) == "Linux" and not os.path.exists("/etc/os-release"):
                    print(f"Please visit http://localhost:{port}")
                else:
                    ipaddress = pymyip.get_ip()
                    print(
                        f"Please visit http://{ipaddress}:{port} or http://localhost:{port}"
                    )
            loop.run_until_complete(web.wait_for_api_token_setup())
            api_token = web.api_token
        else:
            run_config({}, arguments.data_root)
            importlib.invalidate_caches()
            api_token = get_api_token(arguments)

    if os.environ.get("authorization_strings", False):
        if os.environ.get(
                "DYNO", False
        ) or arguments.heroku_web_internal or arguments.heroku_deps_internal:
            app, config = heroku.get_app(os.environ["authorization_strings"],
                                         os.environ["heroku_api_token"],
                                         api_token, False, True)
        if arguments.heroku_web_internal:
            app.scale_formation_process(
                "worker-DO-NOT-TURN-ON-OR-THINGS-WILL-BREAK", 0)
            signal.signal(signal.SIGTERM, functools.partial(sigterm, app))
        elif arguments.heroku_deps_internal:
            try:
                app.scale_formation_process("web", 0)
                app.scale_formation_process(
                    "worker-DO-NOT-TURN-ON-OR-THINGS-WILL-BREAK", 0)
            except requests.exceptions.HTTPError as e:
                if e.response.status_code != 404:
                    # The dynos don't exist on the very first deployment, so don't try to scale
                    raise
            else:
                atexit.register(
                    functools.partial(
                        app.scale_formation_process,
                        "restarter-DO-NOT-TURN-ON-OR-THINGS-WILL-BREAK", 1))
        elif arguments.heroku_restart_internal:
            signal.signal(signal.SIGTERM, functools.partial(sigterm, app))
            while True:
                time.sleep(60)
        elif os.environ.get("DYNO", False):
            signal.signal(signal.SIGTERM, functools.partial(sigterm, app))

    if authtoken:
        for phone, token in authtoken.items():
            try:
                clients += [
                    TelegramClient(StringSession(token),
                                   api_token.ID,
                                   api_token.HASH,
                                   connection=conn,
                                   proxy=proxy,
                                   connection_retries=None).start()
                ]
            except ValueError:
                run_config({}, arguments.data_root)
                return
            clients[-1].phone = phone  # for consistency
    if not clients and not phones:
        if arguments.no_auth:
            return
        if web:
            if not web.running.is_set():
                loop.run_until_complete(web.start())
                print("Web mode ready for configuration")  # noqa: T001
                if not arguments.heroku_web_internal:
                    port = str(web.port)
                    if platform.system(
                    ) == "Linux" and not os.path.exists("/etc/os-release"):
                        print(f"Please visit http://localhost:{port}")
                    else:
                        ipaddress = pymyip.get_ip()
                        print(
                            f"Please visit http://{ipaddress}:{port} or http://localhost:{port}"
                        )
            loop.run_until_complete(web.wait_for_clients_setup())
            arguments.heroku = web.heroku_api_token
            clients = web.clients
            for client in clients:
                if arguments.heroku:
                    session = StringSession()
                else:
                    session = SQLiteSession(
                        os.path.join(
                            arguments.data_root
                            or os.path.dirname(utils.get_base_dir()),
                            "friendly-telegram-" + "+" + "X" *
                            (len(client.phone) - 5) + client.phone[-4:]))
                session.set_dc(client.session.dc_id,
                               client.session.server_address,
                               client.session.port)
                session.auth_key = client.session.auth_key
                if not arguments.heroku:
                    session.save()
                client.session = session
        else:
            try:
                phone = input("Please enter your phone or bot token: ")
                phones = {phone.split(":", maxsplit=1)[0]: phone}
            except EOFError:
                print()  # noqa: T001
                print("=" * 30)  # noqa: T001
                print()  # noqa: T001
                print(
                    "Hello. If you are seeing this, it means YOU ARE DOING SOMETHING WRONG!"
                )  # noqa: T001
                print()  # noqa: T001
                print(
                    "It is likely that you tried to deploy to heroku - "  # noqa: T001
                    "you cannot do this via the web interface.")
                print(
                    "To deploy to heroku, go to "  # noqa: T001
                    "https://friendly-telegram.gitlab.io/heroku to learn more")
                print()  # noqa: T001
                print(
                    "In addition, you seem to have forked the friendly-telegram repo. THIS IS WRONG!"
                )  # noqa: T001
                print(
                    "You should remove the forked repo, and read https://friendly-telegram.gitlab.io"
                )  # noqa: T001
                print()  # noqa: T001
                print(
                    "If you're not using Heroku, then you are using a non-interactive prompt but "  # noqa: T001
                    "you have not got a session configured, meaning authentication to Telegram is "
                    "impossible.")  # noqa: T001
                print()  # noqa: T001
                print("THIS ERROR IS YOUR FAULT. DO NOT REPORT IT AS A BUG!"
                      )  # noqa: T001
                print("Goodbye.")  # noqa: T001
                sys.exit(1)
    for phone_id, phone in phones.items():
        if arguments.heroku:
            session = StringSession()
        else:
            session = os.path.join(
                arguments.data_root or os.path.dirname(utils.get_base_dir()),
                "friendly-telegram" + (("-" + phone_id) if phone_id else ""))
        try:
            client = TelegramClient(session,
                                    api_token.ID,
                                    api_token.HASH,
                                    connection=conn,
                                    proxy=proxy,
                                    connection_retries=None)
            if arguments.test_dc is not False:
                client.session.set_dc(client.session.dc_id, "149.154.167.40",
                                      80)
            if ":" in phone:
                client.start(bot_token=phone)
                client.phone = None
                del phone
            else:
                if arguments.test_dc:
                    client.start(phone,
                                 code_callback=lambda: arguments.test_dc)
                else:
                    client.start(phone)
                client.phone = phone
            clients.append(client)
        except sqlite3.OperationalError as ex:
            print(
                "Error initialising phone " + (phone if phone else "unknown") +
                " " + ",".join(ex.args)  # noqa: T001
                +
                ": this is probably your fault. Try checking that this is the only instance running and "
                "that the session is not copied. If that doesn't help, delete the file named '"
                "friendly-telegram" + (("-" + phone) if phone else "") +
                ".session'")
            continue
        except (ValueError, ApiIdInvalidError):
            # Bad API hash/ID
            run_config({}, arguments.data_root)
            return
        except PhoneNumberInvalidError:
            print(
                "Please check the phone number. Use international format (+XX...)"  # noqa: T001
                " and don't put spaces in it.")
            continue
    del phones

    if arguments.heroku:
        if isinstance(arguments.heroku, str):
            key = arguments.heroku
        else:
            key = input(
                "Please enter your Heroku API key (from https://dashboard.heroku.com/account): "
            ).strip()
        app = heroku.publish(clients, key, api_token)
        print(
            "Installed to heroku successfully! Type .help in Telegram for help."
        )  # noqa: T001
        if web:
            web.redirect_url = app.web_url
            web.ready.set()
            loop.run_until_complete(web.root_redirected.wait())
        return

    loop.set_exception_handler(
        lambda _, x: logging.error("Exception on event loop! %s",
                                   x["message"],
                                   exc_info=x.get("exception", None)))

    loops = [
        amain_wrapper(client, clients, web, arguments) for client in clients
    ]
    loop.run_until_complete(asyncio.gather(*loops))
Example #3
0
def main():  # noqa: C901
    """Main entrypoint"""
    arguments = parse_arguments()
    loop = asyncio.get_event_loop()

    clients = []
    phones, authtoken = get_phones(arguments)
    api_token = get_api_token()

    if web_available:
        web = core.Web(api_token=api_token) if arguments.web else None
    else:
        if arguments.heroku_web_internal:
            raise RuntimeError("Web required but unavailable")
        web = None

    if api_token is None:
        if web:
            print("Web mode ready for configuration")  # noqa: T001
            loop.run_until_complete(web.start())
            loop.run_until_complete(web.wait_for_api_token_setup())
            api_token = web.api_token
        else:
            run_config({})

    if authtoken:
        for phone, token in authtoken.items():
            try:
                clients += [TelegramClient(StringSession(token), api_token.ID, api_token.HASH,
                                           connection_retries=None).start(phone)]
            except ValueError:
                run_config({})
                return
            clients[-1].phone = phone  # for consistency
    if not clients and not phones:
        if web:
            if not web.running.is_set():
                print("Web mode ready for configuration")  # noqa: T001
                loop.run_until_complete(web.start())
            loop.run_until_complete(web.wait_for_clients_setup())
            arguments.heroku = web.heroku_api_token
            clients = web.clients
            for client in clients:
                if arguments.heroku:
                    session = StringSession()
                else:
                    session = SQLiteSession(os.path.join(os.path.dirname(utils.get_base_dir()),
                                                         "friendly-telegram-" + client.phone))
                session.set_dc(client.session.dc_id, client.session.server_address, client.session.port)
                session.auth_key = client.session.auth_key
                if not arguments.heroku:
                    session.save()
                client.session = session
        else:
            try:
                phones = [input("Please enter your phone: ")]
            except EOFError:
                print()  # noqa: T001
                print("=" * 30)  # noqa: T001
                print()  # noqa: T001
                print("Hello. If you are seeing this, it means YOU ARE DOING SOMETHING WRONG!")  # noqa: T001
                print()  # noqa: T001
                print("It is likely that you tried to deploy to heroku - "  # noqa: T001
                      "you cannot do this via the web interface.")
                print("To deploy to heroku, go to "  # noqa: T001
                      "https://friendly-telegram.github.io/heroku to learn more")
                print()  # noqa: T001
                print("In addition, you seem to have forked the friendly-telegram repo. THIS IS WRONG!")  # noqa: T001
                print("You should remove the forked repo, and read https://friendly-telegram.github.io")  # noqa: T001
                print()  # noqa: T001
                print("If you're not using heroku, then you are using a non-interactive prompt but "  # noqa: T001
                      "you have not got a session configured, meaning authentication to Telegram is "
                      "impossible.")  # noqa: T001
                print()  # noqa: T001
                print("THIS ERROR IS YOUR FAULT. DO NOT REPORT IT AS A BUG!")  # noqa: T001
                print("Goodbye.")  # noqa: T001
                sys.exit(1)
    for phone in phones:
        try:
            clients += [TelegramClient(StringSession() if arguments.heroku else
                                       os.path.join(os.path.dirname(utils.get_base_dir()), "friendly-telegram"
                                                    + (("-" + phone) if phone else "")), api_token.ID,
                                       api_token.HASH, connection_retries=None).start(phone)]
        except sqlite3.OperationalError as ex:
            print("Error initialising phone " + (phone if phone else "unknown") + " " + ",".join(ex.args)  # noqa: T001
                  + ": this is probably your fault. Try checking that this is the only instance running and "
                  "that the session is not copied. If that doesn't help, delete the file named '"
                  "friendly-telegram" + (("-" + phone) if phone else "") + ".session'")
            continue
        except (ValueError, ApiIdInvalidError):
            # Bad API hash/ID
            run_config({})
            return
        except PhoneNumberInvalidError:
            print("Please check the phone number. Use international format (+XX...)"  # noqa: T001
                  " and don't put spaces in it.")
            continue
        clients[-1].phone = phone  # so we can format stuff nicer in configurator

    if arguments.heroku:
        if isinstance(arguments.heroku, str):
            key = arguments.heroku
        else:
            key = input("Please enter your Heroku API key (from https://dashboard.heroku.com/account): ").strip()
        from . import heroku
        app = heroku.publish(clients, key, api_token)
        print("Installed to heroku successfully! Type .help in Telegram for help.")  # noqa: T001
        if web:
            web.redirect_url = app.web_url
            web.ready.set()
            loop.run_until_complete(web.root_redirected.wait())
        return

    if arguments.heroku_web_internal:
        signal.signal(signal.SIGTERM, sigterm)

    loops = [amain(client, clients, web, arguments) for client in clients]

    loop.set_exception_handler(lambda _, x:
                               logging.error("Exception on event loop! %s", x["message"], exc_info=x["exception"]))
    loop.run_until_complete(asyncio.gather(*loops))