Esempio n. 1
0
 def __init__(self):
     """Initialize weather instance."""
     self.api_key = get_config("libweather.api_key")
     if self.api_key is None:
         raise AssertionError("An API key is needed")
     self.base_unit = get_config("libweather.temp_unit", "metric")
     self.temp_unit = TEMP_UNITS.get(self.base_unit, "K")
     self.wind_unit = WIND_UNITS.get(self.base_unit, "km/h")
Esempio n. 2
0
def user_is_admin(user_id):
    """
	Check if the given user ID is in the list
	of the approved user IDs.
	"""
    if user_id not in get_config("libadmin.approved_user_ids", []):
        LOGI(f"Access denied to user {user_id}")
        return False

    LOGI(f"Access granted to user {user_id}")
    return True
Esempio n. 3
0
def ci(update: Update, context: CallbackContext):
	if not user_is_approved(update.message.from_user.id):
		update.message.reply_text("Error: You are not authorized to use CI function of this bot.\n"
								  "Ask to who host this bot to add you to the authorized people list")
		return

	if get_config("ci.channel_id") is None:
		update.message.reply_text("Error: CI channel or user ID not defined")
		LOGE("CI channel or user ID not defined")
		return

	parser = CIParser(prog="/ci")
	parser.set_output(update.message.reply_text)
	parser.add_argument('project', help='CI project',
						nargs='?', default=None,)
	parser.add_argument('-s', '--status',
						action='store_true', help='show queue status')

	args, project_args = parser.parse_known_args(context.args)

	if args.status:
		update.message.reply_text(queue_manager.get_formatted_queue_list())
		return

	if args.project is None:
		parser.error("Please specify a project")

	try:
		project_class = import_module(f"homebot.modules.ci.projects.{args.project}", package="Project").Project
	except (ModuleNotFoundError, AttributeError):
		update.message.reply_text("Error: Project script not found")
		return
	except Exception as e:
		text = "Error: Error while importing project:"
		text += format_exception(e)
		update.message.reply_text(text)
		LOGE(text)
		return

	try:
		project = project_class(update, context, project_args)
	except Exception as e:
		text = "Error: Project class initialization failed:\n"
		text += format_exception(e)
		update.message.reply_text(text)
		LOGE(text)
		return

	workflow = Workflow(project)
	queue_manager.put(workflow)
	update.message.reply_text("Workflow added to the queue")
	LOGI("Workflow added to the queue")
Esempio n. 4
0
    def __init__(self):
        """Initialize the uploader variables."""
        self.method = get_config("libupload.method")
        self.destination_path_base = Path(get_config("libupload.base_dir"))
        self.host = get_config("libupload.host")
        self.port = get_config("libupload.port")
        self.server = self.host if self.port is None else f"{self.host}:{self.port}"
        self.username = get_config("libupload.username")
        self.password = get_config("libupload.password")

        if self.method not in ALLOWED_METHODS:
            raise NotImplementedError("Upload method not valid")
Esempio n. 5
0
def main():
	updater = HomeBot(get_config("bot.api_token"))
	LOGI(f"HomeBot started, version {__version__}")
	LOGI(f"Bot username: @{updater.bot.get_me().username}")
	updater.start_polling()
Esempio n. 6
0
from homebot.core.config import get_config
from homebot.modules.ci.artifacts import Artifacts
from telegram.error import TimedOut, RetryAfter
from time import sleep

chat_id = get_config("ci.channel_id")


class PostManager:
    def __init__(self, project, device: str, artifacts: Artifacts):
        """Initialize PostManager class."""
        self.project = project
        self.device = device
        self.artifacts = artifacts
        self.base_message_text = self.get_base_message_text()
        self.message = self.project.context.bot.send_message(
            chat_id, self.base_message_text)

    def get_base_message_text(self):
        text = f"🛠 CI | {self.project.name} {self.project.version} ({self.project.android_version})\n"
        text += f"Device: {self.device}\n"
        text += f"Lunch flavor: {self.project.lunch_prefix}_{self.device}-{self.project.lunch_suffix}\n"
        text += "\n"
        return text

    def update(self, status: str):
        text = self.base_message_text
        text += f"Status: {status}\n"
        text += "\n"
        if self.artifacts.artifacts:
            text += self.artifacts.get_readable_artifacts_list()
Esempio n. 7
0
	def build(self):
		status_message = self.update.message.reply_text("Downloading file...")

		# Download file
		tempdir = TemporaryDirectory()
		path = Path(tempdir.name)
		url = self.parsed_args.url
		file = path / "recovery.img"
		open(file, 'wb').write(requests.get(url, allow_redirects=True).content)

		# Generate device tree
		status_message.edit_text("Generating device tree...")
		try:
			devicetree = DeviceTree(path / "working", recovery_image=file)
		except Exception as e:
			status_message.edit_text("Device tree generation failed\n"
									f"Error: {e}")
			return

		try:
			build_description = devicetree.build_prop_reader.get_prop(BUILD_DESCRIPTION, "build description")
			branch = build_description.replace(" ", "-")
		except AssertionError:
			status_message.edit_text("Failed to get build description prop, using date as a branch")
			today = date.today()
			build_description = None
			branch = f"{today.year}-{today.month}-{today.day}"

		# Upload to GitHub
		status_message.edit_text("Pushing to GitHub...")
		gh_username = get_config("ci.github_username")
		gh_token = get_config("ci.github_token")
		gh_org_name = get_config("ci.twrpdtgen.github_org")
		repo_name = f"android_device_{devicetree.manufacturer}_{devicetree.codename}"
		git_repo_url = f"https://{gh_username}:{gh_token}@github.com/{gh_org_name}/{repo_name}"

		# Get organization
		try:
			gh = Github(gh_token)
			gh_org = gh.get_organization(gh_org_name)
		except GithubException as error:
			status_message.edit_text(f"Failed to get organization\n"
									 f"Error: {error}")
			return

		# Create repo if needed
		status_message.edit_text("Creating repo if needed...")
		try:
			devicetree_repo = gh_org.create_repo(name=repo_name, private=False, auto_init=False)
		except GithubException as error:
			if error.status != 422:
				status_message.edit_text("Repo creation failed\n"
										 f"Error: {error.status} {error}")
				return
			devicetree_repo = gh_org.get_repo(name=repo_name)

		status_message.edit_text("Pushing...")
		try:
			devicetree.git_repo.git.push(git_repo_url, f"HEAD:refs/heads/{branch}")
			devicetree_repo.edit(default_branch=branch)
		except GitCommandError:
			status_message.edit_text("Error: Push to remote failed!")
			return

		status_message.edit_text("Done")

		channel_id = get_config("ci.twrpdtgen.channel_id")
		self.context.bot.send_message(channel_id,
									  "TWRP device tree generated\n"
									  f"Codename: {devicetree.codename}\n"
									  f"Manufacturer: {devicetree.manufacturer}\n"
									  f"Build description: {build_description}\n"
									  f"Device tree: {devicetree_repo.html_url}/tree/{branch}",
									  disable_web_page_preview=True)
Esempio n. 8
0
    def build(self):
        project_dir = Path(
            f"{get_config('ci.main_dir', '')}/{self.name}-{self.version}")
        device_out_dir = project_dir / "out" / "target" / "product" / self.parsed_args.device

        artifacts = Artifacts(device_out_dir, self.artifacts)
        post_manager = PostManager(self, self.parsed_args.device, artifacts)

        if self.parsed_args.clean is True:
            clean_type = "clean"
        elif self.parsed_args.installclean is True:
            clean_type = "installclean"
        else:
            clean_type = "none"

        post_manager.update("Building")

        command = [
            bot_path / "modules" / "ci" / "projects" / "aosp" / "tools" /
            "building.sh", "--sources", project_dir, "--lunch_prefix",
            self.lunch_prefix, "--lunch_suffix", self.lunch_suffix,
            "--build_target", self.build_target, "--clean", clean_type,
            "--device", self.parsed_args.device
        ]

        last_edit = datetime.now()
        process = subprocess.Popen(command,
                                   encoding="UTF-8",
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.STDOUT)
        while True:
            output = process.stdout.readline()
            if output == '' and process.poll() is not None:
                break
            if not output:
                continue

            now = datetime.now()
            if (now - last_edit).seconds < 150:
                continue

            result = re.search(r"\[ +([0-9]+% [0-9]+/[0-9]+)\]",
                               output.strip())
            if result is None:
                continue
            result_split = str(result.group(1)).split()
            if len(result_split) != 2:
                continue

            percentage, targets = re.split(" +", result.group(1))
            post_manager.update(f"Building: {percentage} ({targets})")

            last_edit = now

        returncode = process.poll()

        # Process return code
        build_result = ERROR_CODES.get(returncode,
                                       "Build failed: Unknown error")

        post_manager.update(build_result)

        needs_logs_upload = NEEDS_LOGS_UPLOAD.get(returncode, False)
        if needs_logs_upload != False:
            log_file = open(project_dir / needs_logs_upload, "rb")
            self.context.bot.send_document(get_config("ci.channel_id"),
                                           log_file)
            log_file.close()

        if returncode != SUCCESS or get_config("ci.upload_artifacts",
                                               False) is not True:
            return

        # Upload artifacts
        try:
            uploader = Uploader()
        except Exception as e:
            post_manager.update(f"{build_result}\n"
                                f"Upload failed: {type(e)}: {e}")
            return

        artifacts.update()

        post_manager.update(build_result)

        for artifact in artifacts.artifacts:
            artifact.status = STATUS_UPLOADING
            post_manager.update(build_result)

            try:
                uploader.upload(
                    artifact.path,
                    Path(self.category) / self.parsed_args.device / self.name /
                    self.android_version)
            except Exception as e:
                artifact.status = f"{STATUS_NOT_UPLOADED}: {type(e)}: {e}"
                LOGE(f"Error while uploading artifact {artifact.name}:\n"
                     f"{format_exception(e)}")
            else:
                artifact.status = STATUS_UPLOADED

            post_manager.update(build_result)