async def turnoff(shut): await shut.edit("`Sending information...`") exe = shut.pattern_match.group(1) if not exe: await shut.edit( f"`Heroku App not found.\nPlease run` `'.dyno off <your app name>'`" ) return else: HEROKU_APP_NAME = exe app = heroku.app(HEROKU_APP_NAME) """ Complete shutdown """ app.scale_formation_process("worker", 0) text = f"`Shutdown` ⬢**{HEROKU_APP_NAME}**" sleep = 1 dot = "." while (sleep <= 3): await shut.edit(text + f"`{dot}`") await asyncio.sleep(1) dot += "." sleep += 1 await shut.respond(f"⬢**{HEROKU_APP_NAME}** `turned off...`") await shut.delete() return True
async def restrt(dyno_restart): await dyno_restart.edit("`Sending information...`") exe = dyno_restart.pattern_match.group(1) if not exe: await dyno_restart.edit( f"`Heroku App not found.\nPlease run` `'.dyno restart <your app name>'`" ) return else: HEROKU_APP_NAME = exe app = heroku.app(HEROKU_APP_NAME) try: Dyno = app.dynos()[0] except IndexError: """ Tell user if main app dyno is not on """ await dyno_restart.respond(f"⬢**{HEROKU_APP_NAME}** `is not on...`" ) return False else: text = f"`Restarting` ⬢**{HEROKU_APP_NAME}**" Dyno.restart() sleep = 1 dot = "." await dyno_restart.edit(text) while (sleep <= 24): await dyno_restart.edit(text + f"`{dot}`") await asyncio.sleep(1) if len(dot) == 3: dot = "." else: dot += "." sleep += 1 state = Dyno.state if state == "up": await dyno_restart.respond( f"⬢**{HEROKU_APP_NAME}** `restarted...`") elif state == "crashed": await dyno_restart.respond( f"⬢**{HEROKU_APP_NAME}** `crashed...`") await dyno_restart.delete() return True
async def turnon(start): await start.edit("`Sending information...`") exe = start.pattern_match.group(1) if not exe: await start.edit( f"`Heroku App not found.\nPlease run` `'.dyno on <your app name>'`" ) return else: HEROKU_APP_NAME = exe app = heroku.app(HEROKU_APP_NAME) try: Dyno = app.dynos()[0] except IndexError: app.scale_formation_process("worker", 1) text = f"`Starting` ⬢**{HEROKU_APP_NAME}**" sleep = 1 dot = "." await start.edit(text) while (sleep <= 24): await start.edit(text + f"`{dot}`") await asyncio.sleep(1) if len(dot) == 3: dot = "." else: dot += "." sleep += 1 state = Dyno.state if state == "up": await start.respond(f"⬢**{HEROKU_APP_NAME}** `up...`") elif state == "crashed": await start.respond(f"⬢**{HEROKU_APP_NAME}** `crashed...`") await start.delete() return True else: await start.edit(f"⬢**{HEROKU_APP_NAME}** `already on...`") return False
async def dyno_manage(dyno): """ - Restart/Kill dyno - """ await dyno.edit("`Sending information...`") app = heroku.app(HEROKU_APP_NAME) exe = dyno.pattern_match.group(1) if exe == "on": try: Dyno = app.dynos()[0] except IndexError: app.scale_formation_process("worker", 1) text = f"`Starting` ⬢**{HEROKU_APP_NAME}**" sleep = 1 dot = "." await dyno.edit(text) while sleep <= 24: await dyno.edit(text + f"`{dot}`") await asyncio.sleep(1) if len(dot) == 3: dot = "." else: dot += "." sleep += 1 state = Dyno.state if state == "up": await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `up...`") elif state == "crashed": await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `crashed...`") return await dyno.delete() else: return await dyno.edit(f"⬢**{HEROKU_APP_NAME}** `already on...`") if exe == "restart": try: """ - Catch error if dyno not on - """ Dyno = app.dynos()[0] except IndexError: return await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `is not on...`") else: text = f"`Restarting` ⬢**{HEROKU_APP_NAME}**" Dyno.restart() sleep = 1 dot = "." await dyno.edit(text) while sleep <= 24: await dyno.edit(text + f"`{dot}`") await asyncio.sleep(1) if len(dot) == 3: dot = "." else: dot += "." sleep += 1 state = Dyno.state if state == "up": await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `restarted...`") elif state == "crashed": await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `crashed...`") return await dyno.delete() elif exe == "off": """ - Complete shutdown - """ app.scale_formation_process("worker", 0) text = f"`Shutdown` ⬢**{HEROKU_APP_NAME}**" sleep = 1 dot = "." while sleep <= 3: await dyno.edit(text + f"`{dot}`") await asyncio.sleep(1) dot += "." sleep += 1 await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `turned off...`") return await dyno.delete() elif exe == "usage": """ - Get your account Dyno Usage - """ await dyno.edit("`Getting information...`") headers = { "User-Agent": useragent, "Accept": "application/vnd.heroku+json; version=3.account-quotas", } user_id = [heroku.account().id] if fallback is not None: user_id.append(fallback.account().id) msg = "" for aydi in user_id: if fallback is not None and fallback.account().id == aydi: headers["Authorization"] = f"Bearer {HEROKU_API_KEY_FALLBACK}" else: headers["Authorization"] = f"Bearer {HEROKU_API_KEY}" path = "/accounts/" + aydi + "/actions/get-quota" r = requests.get(heroku_api + path, headers=headers) if r.status_code != 200: await dyno.edit("`Cannot get information...`") continue result = r.json() quota = result["account_quota"] quota_used = result["quota_used"] """ - Used - """ remaining_quota = quota - quota_used percentage = math.floor(remaining_quota / quota * 100) minutes_remaining = remaining_quota / 60 hours = math.floor(minutes_remaining / 60) minutes = math.floor(minutes_remaining % 60) """ - Used per/App Usage - """ Apps = result["apps"] """ - Sort from larger usage to lower usage - """ Apps = sorted(Apps, key=itemgetter("quota_used"), reverse=True) if fallback is not None and fallback.account().id == aydi: apps = fallback.apps() msg += "**Dyno Usage fallback-account**:\n\n" else: apps = heroku.apps() msg += "**Dyno Usage main-account**:\n\n" try: Apps[0] except IndexError: """ - If all apps usage are zero - """ for App in apps: msg += ( f" -> `Dyno usage for` **{App.name}**:\n" f" • `0`**h** `0`**m** " f"**|** [`0`**%**]\n\n" ) for App in Apps: AppName = "__~~Deleted or transferred app~~__" ID = App.get("app_uuid") try: AppQuota = App.get("quota_used") AppQuotaUsed = AppQuota / 60 AppPercentage = math.floor(AppQuota * 100 / quota) except IndexError: AppQuotaUsed = 0 AppPercentage = 0 finally: AppHours = math.floor(AppQuotaUsed / 60) AppMinutes = math.floor(AppQuotaUsed % 60) for names in apps: if ID == names.id: AppName = f"**{names.name}**" break msg += ( f" -> `Dyno usage for` {AppName}:\n" f" • `{AppHours}`**h** `{AppMinutes}`**m** " f"**|** [`{AppPercentage}`**%**]\n\n" ) msg = ( f"{msg}" " -> `Dyno hours quota remaining this month`:\n" f" • `{hours}`**h** `{minutes}`**m** " f"**|** [`{percentage}`**%**]\n\n" ) if msg: return await dyno.edit(msg) return elif exe in ["cancel deploy", "cancel build"]: """ - Only cancel 1 recent builds from activity - """ build_id = dyno.pattern_match.group(2) if build_id is None: build = app.builds(order_by="created_at", sort="desc")[0] else: build = app.builds().get(build_id) if build is None: return await dyno.edit(f"`There is no such build.id`: **{build_id}**") if build.status != "pending": return await dyno.edit("`Zero active builds to cancel...`") headers = { "User-Agent": useragent, "Authorization": f"Bearer {HEROKU_API_KEY}", "Accept": "application/vnd.heroku+json; version=3.cancel-build", } path = "/apps/" + build.app.id + "/builds/" + build.id r = requests.delete(heroku_api + path, headers=headers) text = f"`Stopping build` ⬢**{build.app.name}**" await dyno.edit(text) sleep = 1 dot = "." await asyncio.sleep(2) while sleep <= 3: await dyno.edit(text + f"`{dot}`") await asyncio.sleep(1) dot += "." sleep += 1 await dyno.respond("`[HEROKU]`\n" f"Build: ⬢**{build.app.name}** `Stopped...`") """ - Restart main if builds cancelled - """ try: app.dynos()[0].restart() except IndexError: await dyno.edit("`Your dyno main app is not on...`") await asyncio.sleep(2.5) return await dyno.delete() elif exe == "get log": await dyno.edit("`Getting information...`") with open("logs.txt", "w") as log: log.write(app.get_log()) await dyno.client.send_file( dyno.chat_id, "logs.txt", reply_to=dyno.id, caption="`Main dyno logs...`", ) await dyno.edit("`Information gets and sent back...`") await asyncio.sleep(5) await dyno.delete() return os.remove("logs.txt")
async def dyno_manage(dyno): await dyno.edit("`Sending information...`") exe = dyno.pattern_match.group(1) app = heroku.app(HEROKU_APP_NAME) if exe == "usage": """ Get your account Dyno Usage """ await dyno.edit("`Getting information...`") headers = { 'User-Agent': useragent, 'Accept': 'application/vnd.heroku+json; version=3.account-quotas', } user_id = [] user_id.append(heroku.account().id) if fallback is not None: user_id.append(fallback.account().id) msg = '' for aydi in user_id: if fallback is not None and fallback.account().id == aydi: headers['Authorization'] = f'Bearer {HEROKU_API_KEY_FALLBACK}' else: headers['Authorization'] = f'Bearer {HEROKU_API_KEY}' path = "/accounts/" + aydi + "/actions/get-quota" r = requests.get(heroku_api + path, headers=headers) if r.status_code != 200: msg += f"`Cannot get {aydi} information...`\n\n" continue result = r.json() quota = result['account_quota'] quota_used = result['quota_used'] """ Quota Limit Left and Used Quota """ remaining_quota = quota - quota_used percentage = math.floor(remaining_quota / quota * 100) minutes_remaining = remaining_quota / 60 hours = math.floor(minutes_remaining / 60) minutes = math.floor(minutes_remaining % 60) """ Used Quota per/App """ Apps = result['apps'] """Sort from larger usage to lower usage""" Apps = sorted(Apps, key=itemgetter('quota_used'), reverse=True) if fallback is not None and fallback.account().id == aydi: apps = fallback.apps() msg += "**Dyno Usage fallback-account**:\n\n" else: apps = heroku.apps() msg += "**Dyno Usage main-account**:\n\n" if len(Apps) == 0: for App in apps: msg += (f" -> `Dyno usage for` **{App.name}**:\n" f" • `0`**h** `0`**m** " f"**|** [`0`**%**]\n\n") else: for App in Apps: AppName = '__~~Deleted or transferred app~~__' ID = App.get('app_uuid') AppQuota = App.get('quota_used') AppQuotaUsed = AppQuota / 60 AppPercentage = math.floor(AppQuota * 100 / quota) AppHours = math.floor(AppQuotaUsed / 60) AppMinutes = math.floor(AppQuotaUsed % 60) for name in apps: if ID == name.id: AppName = f"**{name.name}**" break msg += (f" -> `Dyno usage for` {AppName}:\n" f" • `{AppHours}`**h** `{AppMinutes}`**m** " f"**|** [`{AppPercentage}`**%**]\n\n") msg = (f"{msg}" " -> `Dyno hours quota remaining this month`:\n" f" • `{hours}`**h** `{minutes}`**m** " f"**|** [`{percentage}`**%**]\n\n") await dyno.edit(msg) return if exe == "deploy": home = os.getcwd() if not os.path.isdir('deploy'): os.mkdir('deploy') txt = ("`Oops.. cannot continue deploy due to " "some problems occured.`\n\n**LOGTRACE:**\n") heroku_app = None apps = heroku.apps() for app in apps: if app.name == HEROKU_APP_NAME: heroku_app = app break if heroku_app is None: await dyno.edit( f"{txt}\n" "`Invalid Heroku credentials for deploying userbot dyno.`") return await dyno.edit('`[HEROKU - MAIN]`\n' '`ProjectDils deploy in progress, please wait...`') os.chdir('deploy') repo = Repo.init() origin = repo.create_remote('deploy', UPSTREAM_REPO_URL) try: origin.pull(MAIN_REPO_BRANCH) except GitCommandError: await dyno.edit(f"{txt}\n" f"`Invalid` **{MAIN_REPO_BRANCH}** `branch name.`" ) os.remove('deploy') return heroku_git_url = heroku_app.git_url.replace( "https://", "https://*****:*****@") remote = repo.create_remote("heroku", heroku_git_url) remote.push(refspec="HEAD:refs/heads/master", force=True) await dyno.edit('`Successfully deployed!\n' 'Restarting, please wait...`') os.chdir(home) shutil.rmtree('deploy') return elif exe == "cancel deploy" or exe == "cancel build": """ Only cancel 1 recent builds from activity if build.id not supplied """ build_id = dyno.pattern_match.group(2) if build_id is None: build = app.builds(order_by='created_at', sort='desc')[0] else: build = app.builds().get(build_id) if build is None: await dyno.edit(f"`There is no such build.id`:\n**{build_id}**" ) return False if build.status != "pending": await dyno.edit("`Zero active builds to cancel...`") return False headers = { 'User-Agent': useragent, 'Authorization': f'Bearer {HEROKU_API_KEY}', 'Accept': 'application/vnd.heroku+json; version=3.cancel-build', } path = "/apps/" + build.app.id + "/builds/" + build.id r = requests.delete(heroku_api + path, headers=headers) text = f"`Stopping build` ⬢**{build.app.name}**" await dyno.edit(text) sleep = 1 dot = "." await asyncio.sleep(2) while (sleep <= 3): await dyno.edit(text + f"`{dot}`") await asyncio.sleep(1) dot += "." sleep += 1 await dyno.respond("`[HEROKU]`\n" f"Build: ⬢**{build.app.name}** `Stopped...`") await dyno.delete() return True elif exe == "get log": await dyno.edit("`Getting information...`") with open('logs.txt', 'w') as log: log.write(app.get_log()) fd = codecs.open("logs.txt", "r", encoding="utf-8") data = fd.read() key = (requests.post("https://nekobin.com/api/documents", json={ "content": data }).json().get("result").get("key")) url = f"https://nekobin.com/raw/{key}" await dyno.edit( f"`Here the heroku logs:`\n\nPasted to: [Nekobin]({url})") os.remove('logs.txt') return True elif exe == "help": return await dyno.edit( "`.dyno usage`" "\nUsage: Check your heroku App usage dyno quota." "\nIf one of your app usage is empty, it won't be write in output." "\n\n`.dyno on <app name>`" "\nUsage: Turn on your your dyno application." "\n\n`.dyno restart <app name>`" "\nUsage: Restart your dyno application." "\n\n`.dyno off <app name>`" "\nUsage: Shutdown dyno completly." "\n\n`.dyno cancel deploy` or `.dyno cancel build`" "\nUsage: Cancel deploy from main app " "give build.id to specify build to cancel." "\n\n`.dyno deploy`" "\nUsage: Deploy your main userbot without checking update." "\n\n`.dyno get log`" "\nUsage: Get your main dyno recent logs." "\n\n`.dyno help`" "\nUsage: print this help.") elif exe == "update": return await dyno.edit( "`.updatef`" "\nUsage: Check fallback if there are any updates." "\n\n`.updatef deploy`" "\nUsage: If there are any updates, you can deploy fallback app." "\n\n`.updatef now`" "\nUsage: If there are any updates, you can update fallback app." "\n\n" "**FAQ**:\n" "`Q`: What's different `.updatef now` and `.updatef deploy`?\n" "`A`: `.updatef now` update your fallback without deploying, " "but the app will back to latest successfully deployed state if " "fallback restarted.\n" "`.updatef deploy` is more same but if fallback restarted it " "won't rollback.")
async def dyno_manage(dyno): """ - Restart/Kill dyno - """ await dyno.edit("`Sending information...`") app = heroku.app(HEROKU_APP_NAME) exe = dyno.pattern_match.group(1) if exe == "on": try: Dyno = app.dynos()[0] except IndexError: app.scale_formation_process("worker", 1) text = f"`Starting` ⬢**{HEROKU_APP_NAME}**" sleep = 1 dot = "." await dyno.edit(text) while (sleep <= 24): await dyno.edit(text + f"`{dot}`") await asyncio.sleep(1) if len(dot) == 3: dot = "." else: dot += "." sleep += 1 state = Dyno.state if state == "up": await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `up...`") elif state == "crashed": await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `crashed...`") return await dyno.delete() else: return await dyno.edit(f"⬢**{HEROKU_APP_NAME}** `already on...`") if exe == "restart": try: """ - Catch error if dyno not on - """ Dyno = app.dynos()[0] except IndexError: return await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `is not on...`") else: text = f"`Restarting` ⬢**{HEROKU_APP_NAME}**" Dyno.restart() sleep = 1 dot = "." await dyno.edit(text) while (sleep <= 24): await dyno.edit(text + f"`{dot}`") await asyncio.sleep(1) if len(dot) == 3: dot = "." else: dot += "." sleep += 1 state = Dyno.state if state == "up": await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `restarted...`") elif state == "crashed": await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `crashed...`") return await dyno.delete() elif exe == "off": """ - Complete shutdown - """ app.scale_formation_process("worker", 0) text = f"`Shutdown` ⬢**{HEROKU_APP_NAME}**" sleep = 1 dot = "." while (sleep <= 3): await dyno.edit(text + f"`{dot}`") await asyncio.sleep(1) dot += "." sleep += 1 await dyno.respond(f"⬢**{HEROKU_APP_NAME}** `turned off...`") return await dyno.delete() elif exe == "usage": """ - Get your account Dyno Usage - """ await dyno.edit("`Getting information...`") headers = { 'User-Agent': useragent, 'Accept': 'application/vnd.heroku+json; version=3.account-quotas', } user_id = [] user_id.append(heroku.account().id) if fallback is not None: user_id.append(fallback.account().id) msg = '' for aydi in user_id: if fallback is not None and fallback.account().id == aydi: headers['Authorization'] = f'Bearer {HEROKU_API_KEY_FALLBACK}' else: headers['Authorization'] = f'Bearer {HEROKU_API_KEY}' path = "/accounts/" + aydi + "/actions/get-quota" r = requests.get(heroku_api + path, headers=headers) if r.status_code != 200: await dyno.edit("`Cannot get information...`") continue result = r.json() quota = result['account_quota'] quota_used = result['quota_used'] """ - Used - """ remaining_quota = quota - quota_used percentage = math.floor(remaining_quota / quota * 100) minutes_remaining = remaining_quota / 60 hours = math.floor(minutes_remaining / 60) minutes = math.floor(minutes_remaining % 60) """ - Used per/App Usage - """ Apps = result['apps'] """ - Sort from larger usage to lower usage - """ Apps = sorted(Apps, key=itemgetter('quota_used'), reverse=True) if fallback is not None and fallback.account().id == aydi: apps = fallback.apps() msg += "**Dyno Usage fallback-account**:\n\n" else: apps = heroku.apps() msg += "**Dyno Usage main-account**:\n\n" try: Apps[0] except IndexError: """ - If all apps usage are zero - """ for App in apps: msg += ( f" -> `Dyno usage for` **{App.name}**:\n" f" • `0`**h** `0`**m** " f"**|** [`0`**%**]\n\n" ) for App in Apps: AppName = '__~~Deleted or transferred app~~__' ID = App.get('app_uuid') try: AppQuota = App.get('quota_used') AppQuotaUsed = AppQuota / 60 AppPercentage = math.floor(AppQuota * 100 / quota) except IndexError: AppQuotaUsed = 0 AppPercentage = 0 finally: AppHours = math.floor(AppQuotaUsed / 60) AppMinutes = math.floor(AppQuotaUsed % 60) for names in apps: if ID == names.id: AppName = f"**{names.name}**" break msg += ( f" -> `Dyno usage for` {AppName}:\n" f" • `{AppHours}`**h** `{AppMinutes}`**m** " f"**|** [`{AppPercentage}`**%**]\n\n" ) msg = ( f"{msg}" " -> `Dyno hours quota remaining this month`:\n" f" • `{hours}`**h** `{minutes}`**m** " f"**|** [`{percentage}`**%**]\n\n" ) if msg: return await dyno.edit(msg) else: return elif exe == "cancel deploy" or exe == "cancel build": """ - Only cancel 1 recent builds from activity - """ build_id = dyno.pattern_match.group(2) if build_id is None: build = app.builds(order_by='created_at', sort='desc')[0] else: build = app.builds().get(build_id) if build is None: return await dyno.edit( f"`There is no such build.id`: **{build_id}**") if build.status != "pending": return await dyno.edit("`Zero active builds to cancel...`") headers = { 'User-Agent': useragent, 'Authorization': f'Bearer {HEROKU_API_KEY}', 'Accept': 'application/vnd.heroku+json; version=3.cancel-build', } path = "/apps/" + build.app.id + "/builds/" + build.id r = requests.delete(heroku_api + path, headers=headers) text = f"`Stopping build` ⬢**{build.app.name}**" await dyno.edit(text) sleep = 1 dot = "." await asyncio.sleep(2) while (sleep <= 3): await dyno.edit(text + f"`{dot}`") await asyncio.sleep(1) dot += "." sleep += 1 await dyno.respond( "`[HEROKU]`\n" f"Build: ⬢**{build.app.name}** `Stopped...`") """ - Restart main if builds cancelled - """ try: app.dynos()[0].restart() except IndexError: await dyno.edit("`Your dyno main app is not on...`") await asyncio.sleep(2.5) return await dyno.delete() elif exe == "get log": await dyno.edit("`Getting information...`") with open('logs.txt', 'w') as log: log.write(app.get_log()) await dyno.client.send_file( dyno.chat_id, "logs.txt", reply_to=dyno.id, caption="`Main dyno logs...`", ) await dyno.edit("`Information gets and sent back...`") await asyncio.sleep(5) await dyno.delete() return os.remove('logs.txt') elif exe == "help": return await dyno.edit( ">`.dyno usage`" "\nUsage: Check your heroku App usage dyno quota." "\nIf one of your app usage is empty, it won't be write in output." "\n\n>`.dyno on`" "\nUsage: Turn on your main dyno application." "\n\n>`.dyno restart`" "\nUsage: Restart your dyno application." "\n\n>`.dyno off`" "\nUsage: Shutdown dyno completly." "\n\n>`.dyno cancel deploy` or >`.dyno cancel build`" "\nUsage: Cancel deploy from main app " "give build.id to specify build to cancel." "\n\n>`.dyno get log`" "\nUsage: Get your main dyno recent logs." "\n\n>`.dyno help`" "\nUsage: print this help." ) elif exe == "update": return await dyno.edit( ">`.updatef`" "\nUsage: Check fallback if there are any updates." "\n\n>`.updatef deploy`" "\nUsage: If there are any updates, you can deploy fallback app." "\n\n>`.updatef now`" "\nUsage: If there are any updates, you can update fallback app." "\n\n" "**FAQ**:\n" "`Q`: What's different >`.updatef now` and >`.updatef deploy`?\n" "`A`: >`.updatef now` update your fallback without deploying, " "but the app will back to latest successfully deployed state if " "fallback restarted.\n" ">`.updatef deploy` is more same but if fallback restarted it " "won't rollback." )