# Copyright (C) 2018-2019 The Authors # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. """Handles heroku uploads""" import logging import json import os from git import Repo from git.exc import InvalidGitRepositoryError from telethon.sessions import StringSession import heroku3 import requests from . import utils def publish(clients, key, api_token=None): """Push to heroku""" logging.debug("Configuring heroku...") data = json.dumps({getattr(client, "phone", ""): StringSession.save(client.session) for client in clients}) app, config = get_app(clients, key, api_token) try: 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: raise config["authorization_strings"] = data config["heroku_api_token"] = key if api_token is not None: config["api_id"] = api_token.ID config["api_hash"] = api_token.HASH repo = get_repo() url = app.git_url.replace("https://", "https://api:" + key + "@") if "heroku" in repo.remotes: remote = repo.remote("heroku") remote.set_url(url) else: remote = repo.create_remote("heroku", url) remote.push(refspec="HEAD:refs/heads/master") logging.debug("We are still alive. Enabling dyno.") app.scale_formation_process("web", 1) return app def get_app(clients, key, api_token=None, create_new=True, full_match=False): heroku = heroku3.from_key(key) app = None for poss_app in heroku.apps(): config = poss_app.config() if "authorization_strings" not in config: continue if (api_token is None or (config["api_id"] == api_token.ID and config["api_hash"] == api_token.HASH)): if full_match and config["authorization_strings"] != os.environ["authorization_strings"]: continue app = poss_app break if app is None: if api_token is None or not create_new: logging.error("%r", {app: repr(app.config) for app in heroku.apps()}) raise RuntimeError("Could not identify app!") app = heroku.create_app(stack_id_or_name="heroku-18", region_id_or_name="us") config = app.config() return app, config def get_repo(): """Helper to get the repo, making it if not found""" try: repo = Repo(os.path.dirname(utils.get_base_dir())) except InvalidGitRepositoryError: repo = Repo.init(os.path.dirname(utils.get_base_dir())) origin = repo.create_remote("origin", "https://gitlab.com/friendly-telegram/friendly-telegram") origin.fetch() repo.create_head("master", origin.refs.master) repo.heads.master.set_tracking_branch(origin.refs.master) repo.heads.master.checkout(True) return repo