diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..d813d41a7
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,413 @@
+#editorconfig
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202103251804-git
+# @Author : Jason Hempstead
+# @Contact : jason@casjaysdev.pro
+# @License : LICENSE.md
+# @ReadME : editorconfig
+# @Copyright : Copyright: (c) 2021 Jason Hempstead, CasjaysDev
+# @Created : Thursday, Mar 25, 2021 18:52 EDT
+# @File : editorconfig
+# @Description : Default file for editorconfig
+# @TODO :
+# @Other :
+# @Resource : http://editorconfig.org
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# This file is the top-most EditorConfig file
+root = true
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# All Files
+[*]
+charset = utf-8
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Visual Studio Solution Files
+[*.sln]
+indent_style = tab
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Visual Studio XML Project Files
+[*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}]
+indent_size = 2
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# XML Configuration Files
+[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}]
+indent_size = 2
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# JSON Files
+[*.{json,json5,webmanifest}]
+indent_size = 2
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# YAML Files
+[*.{yml,yaml}]
+indent_size = 2
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Markdown Files
+[*.md]
+trim_trailing_whitespace = false
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Web Files
+[*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,svg,vue}]
+indent_size = 2
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Batch Files
+[*.{cmd,bat}]
+end_of_line = crlf
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Bash Files
+[*.{sh,zsh,bash,fish}]
+end_of_line = lf
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Makefiles
+[Makefile]
+indent_style = tab
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+##########################################
+# File Header (Uncomment to support file headers)
+# https://docs.microsoft.com/en-us/visualstudio/ide/reference/add-file-header
+##########################################
+
+# [*.{cs,csx,cake,vb,vbx}]
+# file_header_template = \nCopyright (©) PROJECT-AUTHOR. All Rights Reserved\n
+
+# SA1636: File header copyright text should match
+# Justification: .editorconfig supports file headers, so specifying a stylecop.json file with the file header is not needed.
+# dotnet_diagnostic.SA1636.severity = none
+
+##########################################
+# .NET Language Conventions
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions
+##########################################
+
+# .NET Code Style Settings
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#net-code-style-settings
+[*.{cs,csx,cake,vb,vbx}]
+# "this." and "Me." qualifiers
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#this-and-me
+dotnet_style_qualification_for_field = true:warning
+dotnet_style_qualification_for_property = true:warning
+dotnet_style_qualification_for_method = true:warning
+dotnet_style_qualification_for_event = true:warning
+# Language keywords instead of framework type names for type references
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#language-keywords
+dotnet_style_predefined_type_for_locals_parameters_members = true:warning
+dotnet_style_predefined_type_for_member_access = true:warning
+# Modifier preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#normalize-modifiers
+dotnet_style_require_accessibility_modifiers = always:warning
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
+visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async
+dotnet_style_readonly_field = true:warning
+# Parentheses preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parentheses-preferences
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion
+# Expression-level preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences
+dotnet_style_object_initializer = true:warning
+dotnet_style_collection_initializer = true:warning
+dotnet_style_explicit_tuple_names = true:warning
+dotnet_style_prefer_inferred_tuple_names = true:warning
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
+dotnet_style_prefer_auto_properties = true:warning
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
+dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion
+dotnet_style_prefer_conditional_expression_over_return = false:suggestion
+dotnet_style_prefer_compound_assignment = true:warning
+# Null-checking preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#null-checking-preferences
+dotnet_style_coalesce_expression = true:warning
+dotnet_style_null_propagation = true:warning
+# Parameter preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parameter-preferences
+dotnet_code_quality_unused_parameters = all:warning
+# More style options (Undocumented)
+# https://github.com/MicrosoftDocs/visualstudio-docs/issues/3641
+dotnet_style_operator_placement_when_wrapping = end_of_line
+# https://github.com/dotnet/roslyn/pull/40070
+dotnet_style_prefer_simplified_interpolation = true:warning
+
+# C# Code Style Settings
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-code-style-settings
+[*.{cs,csx,cake}]
+# Implicit and explicit types
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#implicit-and-explicit-types
+csharp_style_var_for_built_in_types = true:warning
+csharp_style_var_when_type_is_apparent = true:warning
+csharp_style_var_elsewhere = true:warning
+# Expression-bodied members
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-bodied-members
+csharp_style_expression_bodied_methods = true:warning
+csharp_style_expression_bodied_constructors = true:warning
+csharp_style_expression_bodied_operators = true:warning
+csharp_style_expression_bodied_properties = true:warning
+csharp_style_expression_bodied_indexers = true:warning
+csharp_style_expression_bodied_accessors = true:warning
+csharp_style_expression_bodied_lambdas = true:warning
+csharp_style_expression_bodied_local_functions = true:warning
+# Pattern matching
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#pattern-matching
+csharp_style_pattern_matching_over_is_with_cast_check = true:warning
+csharp_style_pattern_matching_over_as_with_null_check = true:warning
+# Inlined variable declarations
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#inlined-variable-declarations
+csharp_style_inlined_variable_declaration = true:warning
+# Expression-level preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences
+csharp_prefer_simple_default_expression = true:warning
+# "Null" checking preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-null-checking-preferences
+csharp_style_throw_expression = true:warning
+csharp_style_conditional_delegate_call = true:warning
+# Code block preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#code-block-preferences
+csharp_prefer_braces = true:warning
+# Unused value preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#unused-value-preferences
+csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
+csharp_style_unused_value_assignment_preference = discard_variable:suggestion
+# Index and range preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#index-and-range-preferences
+csharp_style_prefer_index_operator = true:warning
+csharp_style_prefer_range_operator = true:warning
+# Miscellaneous preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#miscellaneous-preferences
+csharp_style_deconstructed_variable_declaration = true:warning
+csharp_style_pattern_local_over_anonymous_function = true:warning
+csharp_using_directive_placement = inside_namespace:warning
+csharp_prefer_static_local_function = true:warning
+csharp_prefer_simple_using_statement = true:suggestion
+
+##########################################
+# .NET Formatting Conventions
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-code-style-settings-reference#formatting-conventions
+##########################################
+
+# Organize usings
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#organize-using-directives
+dotnet_sort_system_directives_first = true
+# Newline options
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#new-line-options
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+# Indentation options
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#indentation-options
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = no_change
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents_when_block = false
+# Spacing options
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#spacing-options
+csharp_space_after_cast = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_between_parentheses = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_after_comma = true
+csharp_space_before_comma = false
+csharp_space_after_dot = false
+csharp_space_before_dot = false
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_around_declaration_statements = false
+csharp_space_before_open_square_brackets = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_square_brackets = false
+# Wrapping options
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#wrap-options
+csharp_preserve_single_line_statements = false
+csharp_preserve_single_line_blocks = true
+
+##########################################
+# .NET Naming Conventions
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-naming-conventions
+##########################################
+
+[*.{cs,csx,cake,vb,vbx}]
+
+##########################################
+# Styles
+##########################################
+
+# camel_case_style - Define the camelCase style
+dotnet_naming_style.camel_case_style.capitalization = camel_case
+# pascal_case_style - Define the PascalCase style
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+# first_upper_style - The first character must start with an upper-case character
+dotnet_naming_style.first_upper_style.capitalization = first_word_upper
+# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I'
+dotnet_naming_style.prefix_interface_with_i_style.capitalization = pascal_case
+dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I
+# prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T'
+dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_case
+dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T
+# disallowed_style - Anything that has this style applied is marked as disallowed
+dotnet_naming_style.disallowed_style.capitalization = pascal_case
+dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____
+dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____
+# internal_error_style - This style should never occur... if it does, it indicates a bug in file or in the parser using the file
+dotnet_naming_style.internal_error_style.capitalization = pascal_case
+dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____
+dotnet_naming_style.internal_error_style.required_suffix = ____INTERNAL_ERROR____
+
+##########################################
+# .NET Design Guideline Field Naming Rules
+# Naming rules for fields follow the .NET Framework design guidelines
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/index
+##########################################
+
+# All public/protected/protected_internal constant fields must be PascalCase
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
+dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities = public, protected, protected_internal
+dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers = const
+dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds = field
+dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols = public_protected_constant_fields_group
+dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style = pascal_case_style
+dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity = warning
+
+# All public/protected/protected_internal static readonly fields must be PascalCase
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
+dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities = public, protected, protected_internal
+dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers = static, readonly
+dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds = field
+dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols = public_protected_static_readonly_fields_group
+dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style
+dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity = warning
+
+# No other public/protected/protected_internal fields are allowed
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
+dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities = public, protected, protected_internal
+dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field
+dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group
+dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style
+dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error
+
+##########################################
+# StyleCop Field Naming Rules
+# Naming rules for fields follow the StyleCop analyzers
+# This does not override any rules using disallowed_style above
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers
+##########################################
+
+# All constant fields must be PascalCase
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md
+dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
+dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const
+dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field
+dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group
+dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = pascal_case_style
+dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning
+
+# All static readonly fields must be PascalCase
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md
+dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
+dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly
+dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field
+dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group
+dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style
+dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning
+
+# No non-private instance fields are allowed
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md
+dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
+dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field
+dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group
+dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style
+dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity = error
+
+# Private fields must be camelCase
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md
+dotnet_naming_symbols.stylecop_private_fields_group.applicable_accessibilities = private
+dotnet_naming_symbols.stylecop_private_fields_group.applicable_kinds = field
+dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols = stylecop_private_fields_group
+dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.style = camel_case_style
+dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.severity = warning
+
+# Local variables must be camelCase
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md
+dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local
+dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local
+dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group
+dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style
+dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity = silent
+
+# This rule should never fire. However, it's included for at least two purposes:
+# First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers.
+# Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#).
+dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_accessibilities = *
+dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_kinds = field
+dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_check_uncovered_field_case_group
+dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style
+dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error
+
+##########################################
+# Other Naming Rules
+##########################################
+
+# All of the following must be PascalCase:
+# - Namespaces
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-namespaces
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
+# - Classes and Enumerations
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
+# - Delegates
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types
+# - Constructors, Properties, Events, Methods
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-type-members
+dotnet_naming_symbols.element_group.applicable_kinds = namespace, class, enum, struct, delegate, event, method, property
+dotnet_naming_rule.element_rule.symbols = element_group
+dotnet_naming_rule.element_rule.style = pascal_case_style
+dotnet_naming_rule.element_rule.severity = warning
+
+# Interfaces use PascalCase and are prefixed with uppercase 'I'
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
+dotnet_naming_symbols.interface_group.applicable_kinds = interface
+dotnet_naming_rule.interface_rule.symbols = interface_group
+dotnet_naming_rule.interface_rule.style = prefix_interface_with_i_style
+dotnet_naming_rule.interface_rule.severity = warning
+
+# Generics Type Parameters use PascalCase and are prefixed with uppercase 'T'
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
+dotnet_naming_symbols.type_parameter_group.applicable_kinds = type_parameter
+dotnet_naming_rule.type_parameter_rule.symbols = type_parameter_group
+dotnet_naming_rule.type_parameter_rule.style = prefix_type_parameters_with_t_style
+dotnet_naming_rule.type_parameter_rule.severity = warning
+
+# Function parameters use camelCase
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/naming-parameters
+dotnet_naming_symbols.parameters_group.applicable_kinds = parameter
+dotnet_naming_rule.parameters_rule.symbols = parameters_group
+dotnet_naming_rule.parameters_rule.style = camel_case_style
+dotnet_naming_rule.parameters_rule.severity = warning
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 000000000..5cc0ab6dc
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,13 @@
+{
+ "extends": ["airbnb", "prettier", "plugin:node/recommended"],
+ "plugins": ["prettier"],
+ "rules": {
+ "prettier/prettier": "error",
+ "no-unused-vars": "warn",
+ "no-console": "off",
+ "func-names": "off",
+ "no-process-exit": "off",
+ "object-shorthand": "off",
+ "class-methods-use-this": "off"
+ }
+}
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..e69de29bb
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..9fb9eb495
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,99 @@
+# gitignore created on 02/24/23 at 00:39
+# Disable reminder in prompt
+ignoredirmessage
+
+# Disable reminder in prompt
+ignoredirmessage
+
+# OS generated files
+### Linux ###
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+### macOS ###
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### macOS Patch ###
+# iCloud generated files
+*.icloud
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# Other
+**/.installed
+
+# ignore commit message
+**/.gitcommit
+
+# ignore .build_failed files
+**/.build_failed*
+
+# ignore .bak files
+**/*.bak
+
+# ignore .no_push files
+**/.no_push
+
+# ignore .no_git files
+**/.no_git
+
+# ignore work in progress files
+**/*.rewrite.sh
+**/*.refactor.sh
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 000000000..14ad1d80e
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,8 @@
+{
+ "useTabs": false,
+ "printWidth": 120,
+ "tabWidth": 2,
+ "singleQuote": true,
+ "trailingComma": "all",
+ "noSemi": true
+}
diff --git a/.shellcheckrc b/.shellcheckrc
new file mode 100644
index 000000000..8f824e0a9
--- /dev/null
+++ b/.shellcheckrc
@@ -0,0 +1,55 @@
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202103251804-git
+# @Author : Jason Hempstead
+# @Contact : jason@casjaysdev.pro
+# @License : LICENSE.md
+# @ReadME : shellcheck --help
+# @Copyright : Copyright: (c) 2021 Jason Hempstead, CasjaysDev
+# @Created : Thursday, Mar 25, 2021 18:52 EDT
+# @File : shellcheckrc
+# @DeSCription : My default shellcheckrc file
+# @TODO :
+# @Other :
+# @Resource :
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+shell=/bin/bash
+#disable=SC
+disable=SC1004
+disable=SC1017
+disable=SC1090
+disable=SC1091
+disable=SC1117
+disable=SC2002
+disable=SC2004
+disable=SC2005
+disable=SC2009
+disable=SC2010
+disable=SC2012
+disable=SC2015
+disable=SC2016
+disable=SC2021
+disable=SC2030
+disable=SC2031
+disable=SC2034
+disable=SC2039
+disable=SC2045
+disable=SC2046
+disable=SC2062
+disable=SC2086
+disable=SC2089
+disable=SC2116
+disable=SC2120
+disable=SC2129
+disable=SC2148
+disable=SC2153
+disable=SC2154
+disable=SC2155
+disable=SC2162
+disable=SC2181
+disable=SC2207
+disable=SC2231
+disable=SC2236
+disable=SC2242
+disable=SC2294
+disable=SC2126
+disable=SC2317
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..48343db53
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,44 @@
+# travis-ci test main source and push to mirrors
+
+language: bash
+sudo: enabled
+
+jobs:
+ include:
+ - os: linux
+ dist: focal
+ before_install: sudo apt-get update
+ arch:
+ - amd64
+ - arm64
+# - armhf
+# - os: osx
+# osx_image: xcode12.1
+# before_install: brew update -f
+
+install:
+ - sudo git clone https://github.com/casjay-dotfiles/scripts "/usr/local/share/CasjaysDev/scripts"; sudo rm -Rf /usr/local/share/CasjaysDev/scripts/.git
+ - sudo /usr/local/share/CasjaysDev/scripts/install.sh
+ - sudo ./tests/travis-ci.sh
+
+#services:
+# - docker
+
+#before_install:
+# - docker pull archlinux
+# - docker pull centos
+# - docker pull debian
+# - docker pull fedora
+# - docker pull ubuntu
+
+#script:
+# - docker run --rm -v $(pwd):/scripts -it archlinux /bin/bash -c /scripts/tests/docker-pacman.sh
+# - docker run --rm -v $(pwd):/scripts -it centos /bin/bash -c /scripts/tests/docker-yum.sh
+# - docker run --rm -v $(pwd):/scripts -it fedora /bin/bash -c /scripts/tests/docker-dnf.sh
+# - docker run --rm -v $(pwd):/scripts -it debian /bin/bash -c /scripts/tests/docker-apt.sh
+# - docker run --rm -v $(pwd):/scripts -it ubuntu /bin/bash -c /scripts/tests/docker-apt.sh
+
+notifications:
+ email:
+ on_failure: never
+ on_success: never
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..af4920b70
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,10 @@
+{
+ "shellcheck.enable": true,
+ "shellcheck.enableQuickFix": true,
+ "shellcheck.run": "onSave",
+ "shellcheck.executablePath": "shellcheck",
+ "shellcheck.customArgs": [],
+ "shellcheck.ignorePatterns": {},
+ "compile-hero.disable-compile-files-on-did-save-code": false,
+ "python.formatting.provider": "yapf"
+}
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 000000000..b87453c7a
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,13 @@
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ Version 2, December 2004
+
+ Copyright (C) 2021 Jason Hempstead
+
+Everyone is permitted to copy and distribute verbatim or modified copies of
+this license document, and changing it is allowed as long as the name is changed.
+
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+1. You just DO WHAT THE FUCK YOU WANT TO.
+2. End of the What The Fuck Public License
diff --git a/README.md b/README.md
new file mode 100644
index 000000000..9d6d4a66f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,71 @@
+# My custom scripts
+
+## Automatic install
+
+```shell
+sudo git clone https://github.com/casjay-dotfiles/scripts "/usr/local/share/CasjaysDev/scripts" && \
+sudo /usr/local/share/CasjaysDev/scripts/install.sh
+```
+
+## Automatic update
+
+```shell
+sudo systemmgr update scripts
+```
+
+## Manual install
+
+requires:
+
+```shell
+sudo apt install git bash zsh fish python3-pip python3-setuptools net-tools fontconfig jq tf xclip curl wget dialog qalc rsync links html2text dict sudo ruby expect nethogs iftop iotop iperf locate pass python
+```
+
+```shell
+sudo yum install git bash zsh fish python3-pip python3-setuptools net-tools fontconfig jq tinyfugue xclip curl wget dialog qalc sudo
+```
+
+```shell
+sudo pacman -S git bash zsh fish python-pip python-setuptools net-tools fontconfig jq xclip curl wget dialog qalculate-gtk sudo
+yay -S tinyfugue
+```
+
+```shell
+apk add ncurses util-linux pciutils usbutils coreutils binutils findutils grep iproute2 sudo
+```
+
+```shell
+export PATH="$PATH:/usr/local/share/CasjaysDev/scripts/bin"
+sudo git clone https://github.com/systemmgr/installer "/usr/local/share/CasjaysDev/scripts"
+echo 'for f in /usr/local/share/CasjaysDev/scripts/completions/*; do source "$f" >/dev/null 2>&1; done' | sudo tee -p "/etc/bash_completion.d/_my_scripts_completions" >/dev/null
+sudo ln -sf /usr/local/share/CasjaysDev/scripts /usr/local/share/CasjaysDev/installer
+for f in $(ls /usr/local/share/CasjaysDev/scripts/bin/); do
+ sudo ln -sf /usr/local/share/CasjaysDev/scripts/bin/$f /usr/local/bin/$f
+done
+```
+
+Manual update:
+
+```shell
+sudo git -C /usr/local/share/CasjaysDev/scripts pull
+```
+
+
+
+ dotfiles |
+ fonts |
+ icons |
+ themes |
+ wallpapers
+ devenvmgr |
+ dockermgr |
+ pkmgr |
+ systemmgr
+
+
+
+
+ scripts site
+ 
+ 
+
diff --git a/applications/My_BackupApp.desktop b/applications/My_BackupApp.desktop
new file mode 100644
index 000000000..ae49a869a
--- /dev/null
+++ b/applications/My_BackupApp.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Backups
+GenericName=Backup
+Comment=Backup Files.
+Icon=back
+Exec=backupapp
+Terminal=false
+Actions=
+Categories=System;Utility;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=backup;my;
+StartupNotify=false
diff --git a/applications/My_Calc.desktop b/applications/My_Calc.desktop
new file mode 100644
index 000000000..2b8f594e0
--- /dev/null
+++ b/applications/My_Calc.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Calc
+GenericName=Calculator
+Comment=Calculator.
+Icon=calc
+Exec=calc
+Terminal=false
+Actions=
+Categories=Utility;Calculator;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=calc;my;
+StartupNotify=false
diff --git a/applications/My_Editor.desktop b/applications/My_Editor.desktop
new file mode 100644
index 000000000..405185aa4
--- /dev/null
+++ b/applications/My_Editor.desktop
@@ -0,0 +1,16 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Editor
+GenericName=TextEditor
+Comment=Edit Files.
+Icon=accessories-text-editor
+TryExec=myeditor
+Exec=myeditor
+Terminal=false
+Actions=
+Categories=GTK;Development;IDE;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=editor;files;my;
+StartupNotify=false
diff --git a/applications/My_Email.desktop b/applications/My_Email.desktop
new file mode 100644
index 000000000..436e82b1c
--- /dev/null
+++ b/applications/My_Email.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Email
+GenericName=E-Mail
+Comment=Manage E-mail.
+Icon=thunderbird
+Exec=myemail
+Terminal=false
+Actions=
+Categories=Application;Network;Email;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=mail;e-mail;my;
+StartupNotify=false
diff --git a/applications/My_FileManager.desktop b/applications/My_FileManager.desktop
new file mode 100644
index 000000000..3b25eee84
--- /dev/null
+++ b/applications/My_FileManager.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Files
+GenericName=File Manager
+Comment=Manage Files.
+Icon=system-file-manager
+Exec=myfilemanager
+Terminal=false
+Actions=
+Categories=FileManager;System;Utility;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=files;manager;my;
+StartupNotify=false
diff --git a/applications/My_Images.desktop b/applications/My_Images.desktop
new file mode 100644
index 000000000..0f5d30b78
--- /dev/null
+++ b/applications/My_Images.desktop
@@ -0,0 +1,16 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Images
+GenericName=Images
+Comment=Manage Photos.
+Icon=image-viewer
+TryExec=images
+Exec=images
+Terminal=false
+Actions=
+Categories=Graphics;Viewer;Photography;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=images;photo;player;my;
+StartupNotify=false
diff --git a/applications/My_Multimedia.desktop b/applications/My_Multimedia.desktop
new file mode 100644
index 000000000..e50c49f33
--- /dev/null
+++ b/applications/My_Multimedia.desktop
@@ -0,0 +1,16 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Media
+GenericName=Media
+Comment=Manage Media.
+Icon=multimedia
+TryExec=multimedia
+Exec=multimedia
+Terminal=false
+Actions=
+Categories=AudioVideo;Player;Recorder;Graphics;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=music;videos;images;photo;player;my;
+StartupNotify=false
diff --git a/applications/My_Music.desktop b/applications/My_Music.desktop
new file mode 100644
index 000000000..e92492211
--- /dev/null
+++ b/applications/My_Music.desktop
@@ -0,0 +1,16 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Music
+GenericName=Music
+Comment=Play Music.
+Icon=multimedia
+TryExec=music
+Exec=music
+Terminal=false
+Actions=
+Categories=Audio;Player;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=music;player;my;
+StartupNotify=false
diff --git a/applications/My_Notes.desktop b/applications/My_Notes.desktop
new file mode 100644
index 000000000..de9fcc98d
--- /dev/null
+++ b/applications/My_Notes.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Notes
+GenericName=Notes
+Comment=Manage Notes.
+Icon=geany
+Exec=notes
+Terminal=false
+Actions=
+Categories=GTK;Development;IDE;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=notes;text;my;
+StartupNotify=false
diff --git a/applications/My_SSH.desktop b/applications/My_SSH.desktop
new file mode 100644
index 000000000..2d002134e
--- /dev/null
+++ b/applications/My_SSH.desktop
@@ -0,0 +1,16 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My SSH
+GenericName=SSH Client
+Comment=Open a ssh conection.
+Icon=folder-remote-ssh
+TryExec=myssh
+Exec=myssh
+Terminal=false
+Actions=
+Categories=GTK;System;Network;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=system;internet;my;
+StartupNotify=false
diff --git a/applications/My_Terminal.desktop b/applications/My_Terminal.desktop
new file mode 100644
index 000000000..3a8dde5d7
--- /dev/null
+++ b/applications/My_Terminal.desktop
@@ -0,0 +1,16 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Terminal
+GenericName=Terminal Emulator
+Comment=Open Terminal.
+Icon=utilities-terminal
+Exec=myterminal
+Path=
+Terminal=false
+Actions=
+Categories=System;GTK;Utility;TerminalEmulator;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=terminal;my;
+StartupNotify=false
diff --git a/applications/My_Todo.desktop b/applications/My_Todo.desktop
new file mode 100644
index 000000000..a7f3a56a8
--- /dev/null
+++ b/applications/My_Todo.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Todo
+GenericName=Todo
+Comment=Manage TODOs.
+Icon=geany
+Exec=todo
+Terminal=false
+Actions=
+Categories=GTK;Development;IDE;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=notes;text;my;
+StartupNotify=false
diff --git a/applications/My_Torrent.desktop b/applications/My_Torrent.desktop
new file mode 100644
index 000000000..f4c0ae9ef
--- /dev/null
+++ b/applications/My_Torrent.desktop
@@ -0,0 +1,16 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Torrents
+GenericName=BitTorrent Client
+Comment=Manage Torrents.
+Icon=transmission
+TryExec=mytorrent
+Exec=mytorrent
+Terminal=false
+Actions=
+Categories=Network;FileTransfer;P2P;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=torrents;my;
+StartupNotify=false
diff --git a/applications/My_Videos.desktop b/applications/My_Videos.desktop
new file mode 100644
index 000000000..468a68696
--- /dev/null
+++ b/applications/My_Videos.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Videos
+GenericName=Multimedia player
+Comment=Watch videos.
+Icon=vlc
+Exec=videos
+Terminal=false
+Actions=
+Categories=Video;Player;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=Videos;my;
+StartupNotify=false
diff --git a/applications/My_Vmmanager.desktop b/applications/My_Vmmanager.desktop
new file mode 100644
index 000000000..8334499dd
--- /dev/null
+++ b/applications/My_Vmmanager.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My VMManager
+GenericName=VM Manager
+Comment=Manager VMs.
+Icon=virtualbox
+Exec=myvmmanager
+Terminal=false
+Actions=
+Categories=System;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=virtual;machine;my;
+StartupNotify=false
diff --git a/applications/My_browser.desktop b/applications/My_browser.desktop
new file mode 100644
index 000000000..906835346
--- /dev/null
+++ b/applications/My_browser.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=My Browser
+GenericName=Browser
+Comment=Browse the web.
+Icon=web-browser
+Exec=mybrowser
+Terminal=false
+Actions=
+Categories=Network;WebBrowser;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=web;browser;my;
+StartupNotify=true
diff --git a/applications/Notify_Daemon.desktop b/applications/Notify_Daemon.desktop
new file mode 100644
index 000000000..021067cdf
--- /dev/null
+++ b/applications/Notify_Daemon.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=Notification Daemon
+GenericName=NotificationDaemon
+Comment=Start Notification Daemon.
+Icon=preferences-desktop-notification
+Exec=notify-daemon
+Terminal=false
+Actions=
+Categories=System;GTK;X-XFCE;GNOME;
+Keywords=xfce4-notify;notify;music;player;my;MyScripts;
+StartupNotify=false
diff --git a/applications/config-editor.desktop b/applications/config-editor.desktop
new file mode 100644
index 000000000..37e873370
--- /dev/null
+++ b/applications/config-editor.desktop
@@ -0,0 +1,16 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=Config Editor
+GenericName=EditConf
+Comment=List Config files to edit.
+Icon=preferences-gtk-config
+Exec=config-editor
+Path=~
+Terminal=false
+Actions=
+Categories=System;GTK;Utility;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=edit;config;my;
+StartupNotify=false
diff --git a/applications/define.desktop b/applications/define.desktop
new file mode 100644
index 000000000..69acfabe5
--- /dev/null
+++ b/applications/define.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=Define
+GenericName=Define
+Comment=Define word.
+Icon=org.xfce.Dictionary
+Exec=define --gtk
+Terminal=false
+Actions=
+Categories=Office;GTK;X-XFCE;GNOME;MyScripts
+Keywords=emojis;my;
+StartupNotify=false
diff --git a/applications/emojis.desktop b/applications/emojis.desktop
new file mode 100644
index 000000000..2f70e4275
--- /dev/null
+++ b/applications/emojis.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=Emoji Menu
+GenericName=Emojis
+Comment=Choose emojis.
+Icon=image-viewer
+Exec=emojis dmenu
+Terminal=false
+Actions=
+Categories=System;GTK;X-XFCE;GNOME;MyScripts
+Keywords=emojis;my;
+StartupNotify=false
diff --git a/applications/mpd-notify.desktop b/applications/mpd-notify.desktop
new file mode 100644
index 000000000..3bde6625d
--- /dev/null
+++ b/applications/mpd-notify.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=MPD Notify
+GenericName=MPDNotify
+Comment=Get MPD Notifications.
+Icon=multimedia
+Exec=mpd-notify
+Terminal=false
+Actions=
+Categories=Audio;Player;System;GTK;X-XFCE;GNOME;MyScripts
+Keywords=mpd;music;player;my;
+StartupNotify=false
diff --git a/applications/mpdclient.desktop b/applications/mpdclient.desktop
new file mode 100644
index 000000000..df12945d7
--- /dev/null
+++ b/applications/mpdclient.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=MPD Client
+GenericName=MPDCLient
+Comment=Manage MPD.
+Icon=multimedia
+Exec=mpdclient
+Terminal=false
+Actions=
+Categories=Audio;Player;GTK;X-XFCE;GNOME;MyScripts;
+Keywords=mpd;music;player;my;
+StartupNotify=false
diff --git a/applications/randomwallpapers.desktop b/applications/randomwallpapers.desktop
new file mode 100644
index 000000000..a5da54484
--- /dev/null
+++ b/applications/randomwallpapers.desktop
@@ -0,0 +1,29 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.1
+Type=Application
+Name=Random Wallpaper
+GenericName=Random Wallpaper
+Comment=Change the wallpaper.
+Icon=wallpaper
+Exec=randomwallpaper
+Actions=New;Status;start;Stop;
+Categories=GNOME;GTK;GTK;MyScripts;System;TerminalEmulator;Utility;X-XFCE;
+Keywords=wallpaper;my;
+
+[Desktop Action New]
+Name=New
+Exec=randomwallpaper bg new
+
+[Desktop Action Status]
+Name=Status
+Exec=randomwallpaper bg status
+
+[Desktop Action start]
+Name=Start
+Exec=randomwallpaper bg start
+
+[Desktop Action Stop]
+Name=Stop
+Exec=randomwallpaper bg stop
diff --git a/applications/search-menu.desktop b/applications/search-menu.desktop
new file mode 100644
index 000000000..ee64b7310
--- /dev/null
+++ b/applications/search-menu.desktop
@@ -0,0 +1,16 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=Search Menu
+GenericName=Search Menu
+Comment=A menu to search on websites
+Icon=catfish
+TryExec=search-menu
+Exec=search-menu
+Terminal=false
+Actions=
+Categories=Accessories;X-XFCE;GNOME;MyScripts;
+Keywords=search;my;
+StartupNotify=false
diff --git a/applications/spellcheck.desktop b/applications/spellcheck.desktop
new file mode 100644
index 000000000..b54ccc767
--- /dev/null
+++ b/applications/spellcheck.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=SpellCheck
+GenericName=SpellCheck
+Comment=Check Spelling.
+Icon=org.xfce.Dictionary
+Exec=spellcheck --gtk
+Terminal=false
+Actions=
+Categories=Office;GTK;X-XFCE;GNOME;MyScripts
+Keywords=emojis;my;
+StartupNotify=false
diff --git a/bin/acme-cli b/bin/acme-cli
new file mode 100755
index 000000000..723c75266
--- /dev/null
+++ b/bin/acme-cli
@@ -0,0 +1,1051 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202408240859-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : acme-cli --help
+# @@Copyright : Copyright: (c) 2024 Jason Hempstead, Casjays Developments
+# @@Created : Saturday, Aug 24, 2024 08:59 EDT
+# @@File : acme-cli
+# @@Description :
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202408240859-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+ACME_CLI_REQUIRE_SUDO="${ACME_CLI_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && ACME_CLI_EXIT_STATUS=0 || ACME_CLI_EXIT_STATUS=1
+ return ${ACME_CLI_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && ACME_CLI_EXIT_STATUS=0 || ACME_CLI_EXIT_STATUS=1
+ return ${ACME_CLI_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ ACME_CLI_EXIT_STATUS=0
+ [ -n "$1" ] && local ACME_CLI_EXIT_STATUS="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && ACME_CLI_EXIT_STATUS+=$(($ACME_CLI_EXIT_STATUS + 0)) || ACME_CLI_EXIT_STATUS+=$(($ACME_CLI_EXIT_STATUS + 1))
+ done
+ [ $ACME_CLI_EXIT_STATUS -eq 0 ] || ACME_CLI_EXIT_STATUS=3
+ return ${ACME_CLI_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local ACME_CLI_EXIT_STATUS=0
+ curl -q -LSsfI --max-time 1 --retry 0 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || ACME_CLI_EXIT_STATUS=4
+ return ${ACME_CLI_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$ACME_CLI_CONFIG_DIR/$ACME_CLI_CONFIG_FILE"
+ fi
+ [ -d "$ACME_CLI_CONFIG_DIR" ] || mkdir -p "$ACME_CLI_CONFIG_DIR"
+ [ -d "$ACME_CLI_CONFIG_BACKUP_DIR" ] || mkdir -p "$ACME_CLI_CONFIG_BACKUP_DIR"
+ [ -f "$ACME_CLI_CONFIG_DIR/$ACME_CLI_CONFIG_FILE" ] &&
+ cp -Rf "$ACME_CLI_CONFIG_DIR/$ACME_CLI_CONFIG_FILE" "$ACME_CLI_CONFIG_BACKUP_DIR/$ACME_CLI_CONFIG_FILE.$$"
+ cat <"$ACME_CLI_CONFIG_DIR/$ACME_CLI_CONFIG_FILE"
+# Settings for acme-cli
+ACME_CLI_CERT_DIR="${ACME_CLI_CERT_DIR:-domain}"
+ACME_CLI_RYSNC="${ACME_CLI_RYSNC:-}"
+ACME_CLI_EMAIL="${ACME_CLI_EMAIL:-}"
+ACME_CLI_TEST="${ACME_CLI_TEST:-yes}"
+ACME_CLI_HOSTNAME="${ACME_CLI_HOSTNAME:-}"
+ACME_CLI_DNS_KEY="${ACME_CLI_DNS_KEY:-}"
+ACME_CLI_SHORT_HOST="${ACME_CLI_SHORT_HOST:-}"
+ACME_CLI_PRIMARY_DNS_IP="${ACME_CLI_PRIMARY_DNS_IP:-}"
+ACME_CLI_UPDATE_CERTS_IPS="${ACME_CLI_UPDATE_CERTS_IPS:-}"
+ACME_CLI_SERVICE_RESTART="${ACME_CLI_SERVICE_RESTART:-}"
+ACME_CLI_OPTIONS="${ACME_CLI_OPTIONS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ACME_CLI_DOMAIN_PRIMARY="${ACME_CLI_DOMAIN_PRIMARY:-}"
+ACME_CLI_DOMAIN_LIST="${ACME_CLI_DOMAIN_LIST:-}"
+ACME_CLI_SUB_LIST="${ACME_CLI_SUB_LIST:-}"
+ACME_CLI_WILD_LIST="${ACME_CLI_WILD_LIST:-}"
+ACME_CLI_ADD_DOMAINS="${ACME_CLI_ADD_DOMAINS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ACME_CLI_CONF_FILE="${ACME_CLI_CONF_FILE:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ACME_CLI_OUTPUT_COLOR_1="${ACME_CLI_OUTPUT_COLOR_1:-}"
+ACME_CLI_OUTPUT_COLOR_2="${ACME_CLI_OUTPUT_COLOR_2:-}"
+ACME_CLI_OUTPUT_COLOR_GOOD="${ACME_CLI_OUTPUT_COLOR_GOOD:-}"
+ACME_CLI_OUTPUT_COLOR_ERROR="${ACME_CLI_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ACME_CLI_NOTIFY_ENABLED="${ACME_CLI_NOTIFY_ENABLED:-}"
+ACME_CLI_GOOD_NAME="${ACME_CLI_GOOD_NAME:-}"
+ACME_CLI_ERROR_NAME="${ACME_CLI_ERROR_NAME:-}"
+ACME_CLI_GOOD_MESSAGE="${ACME_CLI_GOOD_MESSAGE:-}"
+ACME_CLI_ERROR_MESSAGE="${ACME_CLI_ERROR_MESSAGE:-}"
+ACME_CLI_NOTIFY_CLIENT_NAME="${ACME_CLI_NOTIFY_CLIENT_NAME:-}"
+ACME_CLI_NOTIFY_CLIENT_ICON="${ACME_CLI_NOTIFY_CLIENT_ICON:-}"
+ACME_CLI_NOTIFY_CLIENT_URGENCY="${ACME_CLI_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$ACME_CLI_CONFIG_DIR/$ACME_CLI_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$ACME_CLI_CONFIG_DIR/$ACME_CLI_CONFIG_FILE"
+ ACME_CLI_EXIT_STATUS=0
+ else
+ printf_red "Failed to create the config file"
+ ACME_CLI_EXIT_STATUS=1
+ fi
+ return ${ACME_CLI_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "acme-cli: - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: acme-cli [options] [commands]"
+ __printf_line "--key - Specify dns server key"
+ __printf_line "--server - Specify dns server ip"
+ __printf_line "--domains - Specify domains"
+ __printf_line "--add - Specify domains to add [hostname.domain]"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_line "--no - No options"
+ __printf_line "--yes - Yes options"
+ __printf_line ""
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__grep() { grep "$@" 2>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$ACME_CLI_REQUIRE_SUDO" = "yes" ] && [ -z "$ACME_CLI_REQUIRE_SUDO_RUN" ]; then
+ export ACME_CLI_REQUIRE_SUDO="no"
+ export ACME_CLI_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ ACME_CLI_EXIT_STATUS=$?
+ else
+ printf '%s\n' "This requires root to run"
+ ACME_CLI_EXIT_STATUS=1
+ fi
+ return ${ACME_CLI_EXIT_STATUS:-0}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__how_long_did_it_take() {
+ local retprev=$?
+ local retval=${1:-$retprev}
+ __cmd_exists bc || return $retval
+ [ -n "$ACME_CLI_START_TIMER" ] || return 0
+ local stop_time="$(date +%s.%N)"
+ local dt=$(echo "$stop_time - $ACME_CLI_START_TIMER" | bc)
+ local dd=$(echo "$dt/86400" | bc)
+ local dt2=$(echo "$dt-86400*$dd" | bc)
+ local dh=$(echo "$dt2/3600" | bc)
+ local dt3=$(echo "$dt2-3600*$dh" | bc)
+ local dm=$(echo "$dt3/60" | bc)
+ local ds=$(echo "$dt3-60*$dm" | bc)
+ printf_purple "$(LC_NUMERIC=C printf "Total runtime: %d Days, %02d Hours, %02d Minutes, %02.4f Seconds\n" $dd $dh $dm $ds)"
+ return $retval
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ ACME_CLI_EXIT_STATUS=${ACME_CLI_EXIT_STATUS:-0}
+ [ -f "$ACME_CLI_TEMP_FILE" ] && rm -Rf "$ACME_CLI_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $ACME_CLI_EXIT_STATUS
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a --no-* options function
+__options_function_no() {
+ local options="${1//=*/}" options="${1//-*/}"
+ local argument="${1//*=/}" argument="${1//*-/}"
+ case "$options" in
+ *test) printf_yellow "Disabling test" && ACME_CLI_TEST=no && shift ;;
+ *) echo "${argument:-No argument provided}" && shift ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a --yes-* options function
+__options_function_yes() {
+ local options="${1//=*/}"
+ local argument="${1//*=/}"
+ case "$options" in
+ *) echo "${argument:-No argument provided}" && shift ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__if_hostname_is_not() { if [ "$1" = "$2" ]; then return 1; else return 0; fi; }
+__printf_added() { [ "$ACME_CLI_SILENT" = "true" ] || { printf_color "Adding $1" "$2" && printf '\n'; }; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__cert_dir_exists() {
+ le_cert_dir="${1:-/etc/letsencrypt/live/$ACME_CLI_CERT_DIR}"
+ if [ -d "$le_cert_dir" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__certbot_test() {
+ local exitCode=1
+ local type="${1:-certonly}"
+ __cert_dir_exists && return 0
+ [ "$ACME_CLI_TEST" = "yes" ] || return 0
+ printf_yellow "Testing if we can get certificates"
+ if [ "$type" = "renew" ]; then
+ certbot $type $ACME_CLI_SERVER_OPTIONS -vv -n --dry-run --agree-tos $ACME_CLI_SET_EMAIL_OPTIONS --expand $ACME_CLI_OPTIONS --dns-rfc2136 --dns-rfc2136-credentials $ACME_CLI_CONF_FILE 2>"$ACME_CLI_LOG_ERROR_FILE" >/dev/null
+ exitCode=$?
+ else
+ certbot $type $ACME_CLI_SERVER_OPTIONS -vv -n --dry-run --agree-tos $ACME_CLI_SET_EMAIL_OPTIONS --expand $ACME_CLI_OPTIONS --dns-rfc2136 --dns-rfc2136-credentials $ACME_CLI_CONF_FILE $ACME_CLI_DOMAIN_LIST 2>"$ACME_CLI_LOG_ERROR_FILE" >/dev/null
+ exitCode=$?
+ fi
+ [ "$ACME_CLI_FIRST_RUN" != "yes" ] || \rm -Rf "/etc/letsencrypt"
+ [ "$ACME_CLI_INIT" != "yes" ] || \rm -Rf "/etc/letsencrypt/live"/*
+ [ $exitCode = 0 ] && printf_cyan "Testing has passed"
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__certbot_renew() {
+ __cert_dir_exists || [ -f "/etc/letsencrypt/renewal/$ACME_CLI_CERT_DIR.conf" ] || [ -f "/etc/letsencrypt/renewal/domain.conf" ] || return 1
+ __certbot_test renew || printf_exit "certbot test has failed"
+ printf_purple "Attempting to renew certificates"
+ certbot renew $ACME_CLI_SERVER_OPTIONS -n --agree-tos --expand $ACME_CLI_OPTIONS --dns-rfc2136 --dns-rfc2136-credentials $ACME_CLI_CONF_FILE 2>"$ACME_CLI_LOG_ERROR_FILE" >/dev/null
+ __certbot_finalize $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__certbot_create() {
+ __cert_dir_exists && return 0
+ [ "$ACME_CLI_INIT" = "yes" ] && rm -Rf "/etc/letsencrypt/live"/*
+ __certbot_test certonly || printf_exit "certbot test has failed"
+ printf_purple "Attempting to create certificates"
+ certbot certonly $ACME_CLI_SERVER_OPTIONS -n --agree-tos $ACME_CLI_SET_EMAIL_OPTIONS --expand $ACME_CLI_OPTIONS --dns-rfc2136 --dns-rfc2136-credentials $ACME_CLI_CONF_FILE $ACME_CLI_DOMAIN_LIST 2>"$ACME_CLI_LOG_ERROR_FILE" >/dev/null
+ __certbot_finalize $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__certbot_finalize() {
+ local retVal="${1:-$?}"
+ if [ $retVal -eq 0 ]; then
+ __symlink $retVal
+ __update_configs $retVal
+ __reload_services $retVal
+ __update_certs $retVal
+ rm -Rf "$ACME_CLI_LE_LOG_FILE" "$ACME_CLI_LOG_ERROR_FILE"
+ else
+ if grep -qs 'Certificate not yet due for renewal' "$ACME_CLI_LE_LOG_FILE" "$ACME_CLI_LOG_ERROR_FILE"; then
+ printf_green "No certificates are due for renewal"
+ rm -Rf "$ACME_CLI_LE_LOG_FILE" "$ACME_CLI_LOG_ERROR_FILE"
+ return 0
+ else
+ printf_red "Error log saved to $ACME_CLI_LOG_ERROR_FILE"
+ exit $retVal
+ fi
+ fi
+ return $retVal
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__generate_domain_list() {
+ printf_cyan "Generating the domain list"
+ local gen_domains
+ local colorize=122
+ local all_acme_domains=()
+ local name_full="$(hostname -f | grep '^' || true)"
+ local name_short="$(hostname -s | grep '^' || true)"
+ local name_domain="$(hostname -d | grep '^' || true)"
+ local hostname="$ACME_CLI_SHORT_HOST"
+ local add_host_domain="$(echo "${ACME_CLI_ADD_DOMAINS//,/ }" | tr ' ' '\n' | sort -u | grep -v '^$' | tr '\n' ' ' | grep '^' || false)"
+ local set_domains="$(echo "${ACME_CLI_DOMAIN_LIST//,/ }" | tr ' ' '\n' | sort -u | grep -Ev "^$|^$ACME_CLI_DOMAIN_PRIMARY$" 2>/dev/null | grep -Fv '*.' | tr '\n' ' ')"
+ [ "$ACME_CLI_FIRST_RUN" != "yes" ] || \rm -Rf '/etc/letsencrypt'
+ [ "$ACME_CLI_INIT" != "yes" ] || \rm -Rf "/etc/letsencrypt/live"/*
+ if __cert_dir_exists; then
+ printf_yellow "The Certificate folder already exists: /etc/letsencrypt/live/$ACME_CLI_CERT_DIR"
+ return 0
+ fi
+ [ -n "$ACME_CLI_DOMAIN_PRIMARY" ] && set_domains="$ACME_CLI_DOMAIN_PRIMARY *.$ACME_CLI_DOMAIN_PRIMARY $set_domains"
+ if [ -n "$set_domains" ] && [ "$set_domains" != " " ]; then
+ for domain in $set_domains; do
+ if ! echo "$domain" | grep -qF '*.'; then
+ if __if_hostname_is_not "$name_short.$name_domain" "$name_short.$domain"; then
+ gen_domains+="$domain,*.$domain,*.$name_short.$domain,"
+ __printf_added "domain: $domain,*.$domain,*.$name_short.$domain" "120"
+ else
+ gen_domains+="$domain,*.$domain,"
+ __printf_added "domain: $domain,*.$domain" "120"
+ fi
+ if [ -n "$ACME_CLI_SUB_LIST" ]; then
+ for sub_domain in $ACME_CLI_SUB_LIST; do
+ if __if_hostname_is_not "$name_short.$domain" "$sub_domain.$domain"; then
+ gen_domains+="*.$sub_domain.$domain,"
+ __printf_added "subdomain: *.$sub_domain.$domain" "121"
+ fi
+ done
+ fi
+ fi
+ done
+ if [ -n "$ACME_CLI_WILD_LIST" ]; then
+ for wild_domain in $ACME_CLI_WILD_LIST; do
+ if echo "$wild_domain" | grep -qF '*.'; then
+ gen_domains+="$wild_domain,"
+ __printf_added "wildcard: $wild_domain" "122"
+ elif __if_hostname_is_not "$name_short.$name_domain" "$wild_domain" || __if_hostname_is_not "$wild_domain" "$HOSTNAME"; then
+ gen_domains+="*.$wild_domain,$wild_domain,"
+ __printf_added "wildcard: *.$wild_domain,$wild_domain" "122"
+ else
+ gen_domains+="*.$wild_domain,"
+ __printf_added "wildcard: *.$wild_domain" "122"
+ fi
+ if [ -n "$ACME_CLI_SUB_LIST" ]; then
+ for sub_domain in $ACME_CLI_SUB_LIST; do
+ if __if_hostname_is_not "$name_short.$wild_domain" "$sub_domain.$wild_domain"; then
+ gen_domains+="*.$sub_domain.$wild_domain,"
+ __printf_added "subdomain: *.$sub_domain.$wild_domain" "121"
+ fi
+ done
+ fi
+ done
+ fi
+ if [ -n "$add_host_domain" ]; then
+ for host_domain in $add_host_domain; do
+ colorize=$((colorize + 1))
+ if [ "$host_domain" != "$ACME_CLI_DOMAIN_PRIMARY" ] || [ "$name_full" != "$ACME_CLI_DOMAIN_PRIMARY" ]; then
+ if __if_hostname_is_not "$HOSTNAME" "$name_short.$host_domain"; then
+ gen_domains+="*.$host_domain,*.$name_short.$host_domain,"
+ __printf_added "domains: $name_short.$host_domain,*.$name_short.$host_domain" "$colorize"
+ else
+ gen_domains+="*.$name_short.$host_domain,"
+ __printf_added "domains: *.$name_short.$host_domain" "$colorize"
+ fi
+ fi
+ if [ -n "$ACME_CLI_SUB_LIST" ]; then
+ for sub_domain in $ACME_CLI_SUB_LIST; do
+ if __if_hostname_is_not "$name_short.$host_domain" "$sub_domain.$host_domain"; then
+ gen_domains+="*.$sub_domain.$host_domain,"
+ __printf_added "subdomain: *.$sub_domain.$host_domain" "121"
+ fi
+ done
+ fi
+ done
+ fi
+ set_acme_domains="$(echo "$gen_domains" | tr ',' '\n' | sort -u | grep -Ev "^$|^$ACME_CLI_DOMAIN_PRIMARY$" 2>/dev/null | tr '\n' ' ' | grep '^')"
+ for domains in $ACME_CLI_DOMAIN_PRIMARY $set_acme_domains; do
+ all_acme_domains+=("-d $domains")
+ done
+ else
+ unset ACME_CLI_DOMAIN_LIST
+ printf '%s\n' "The variable ACME_CLI_DOMAIN_PRIMARY is not set"
+ return 1
+ fi
+ export ACME_CLI_DOMAIN_LIST="${all_acme_domains[*]}"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__symlink() {
+ local statusCode=${1:-$?}
+ local LE_DOMAIN="/etc/letsencrypt/live/$ACME_CLI_CERT_DIR"
+ local LE_LINK="$(\find /etc/letsencrypt/live/ -mindepth 1 -maxdepth 1 -type d 2>/dev/null | \grep -V '/domain$' | \wc -l)"
+ local LE_FOLDER="$(\find /etc/letsencrypt/live/ -mindepth 1 -maxdepth 1 -type d 2>/dev/null | \grep -V '/domain$' | \head -n1 | \grep '^')"
+ if [ -d "/etc/letsencrypt/live/domain" ] || [ -L "/etc/letsencrypt/live/domain" ]; then
+ return 0
+ elif [ -d "/etc/letsencrypt/live/domain" ] && [ -d "/etc/letsencrypt/live/$ACME_CLI_CERT_DIR" ]; then
+ return 0
+ else
+ if [ $statusCode -eq 0 ] && [ ! -L "/etc/letsencrypt/live/domain" ]; then
+ if [ -d "/etc/letsencrypt/live/domain" ]; then
+ \rm -Rf "/etc/letsencrypt/live/domain"
+ fi
+ if [ -d "$LE_DOMAIN" ]; then
+ \ln -sf "$LE_DOMAIN" "/etc/letsencrypt/live/domain"
+ elif [ "$LE_LINK" -eq 1 ]; then
+ \ln -sf "$LE_FOLDER" "/etc/letsencrypt/live/domain"
+ fi
+ else
+ \unlink "/etc/letsencrypt/live/domain"
+ fi
+ [ -e "/etc/letsencrypt/live/domain" ] && return 0 || return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__update_configs() {
+ local retVal=${1:-$?}
+ local files_with_ca files_with_cert files_with_key
+ files_with_ca="$(grep -Rs '/etc/ssl/CA/CasjaysDev/certs/ca.crt' /etc 2>/dev/null | awk -F ':' '{print $1}' | sort -u | grep '^' || false)"
+ files_with_cert="$(grep -Rs '/etc/ssl/CA/CasjaysDev/certs/localhost.crt' /etc 2>/dev/null | awk -F ':' '{print $1}' | sort -u | grep '^' || false)"
+ files_with_key="$(grep -Rs '/etc/ssl/CA/CasjaysDev/private/localhost.key' /etc 2>/dev/null | awk -F ':' '{print $1}' | sort -u | grep '^' || false)"
+ if [ $retVal = 0 ]; then
+ if [ -n "$files_with_ca" ]; then
+ for file_ca in $files_with_ca; do
+ \sed -i '\/etc\/ssl\/CA\/CasjaysDev\/certs\/ca.crt/d' "$file_ca" 2>/dev/null
+ done
+ fi
+ if [ -n "$files_with_key" ]; then
+ for file_key in $files_with_key; do
+ \sed -i 's|/etc/ssl/CA/CasjaysDev/private/localhost.key|/etc/letsencrypt/live/domain/privkey.pem|g' "$file_key" 2>/dev/null
+ done
+ fi
+ if [ -n "$files_with_cert" ]; then
+ for file_cert in $files_with_cert; do
+ \sed -i 's|/etc/ssl/CA/CasjaysDev/certs/localhost.crt|/etc/letsencrypt/live/domain/fullchain.pem|g' "$file_cert" 2>/dev/null
+ done
+ fi
+ fi
+ return $retVal
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__service_exists() {
+ service_status="$(\systemctl is-enabled "$1" 2>/dev/null || false)"
+ [ -n "$service_status" ] && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__reload_services() {
+ local prevExit="${1:-$?}"
+ if [ "$prevExit" -eq 0 ]; then
+ for service in $ACME_CLI_SERVICE_RESTART; do
+ __service_exists "$service" && \systemctl reload "$service" >/dev/null 2>&1
+ done
+ return 0
+ else
+ return $prevExit
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__update_certs() {
+ local prevExit=${1:-$?}
+ local retVal=0
+ local preVal=0
+ local ip
+ if [ $prevExit -ne 0 ]; then
+ ACME_CLI_EXIT_STATUS=$prevExit
+ return $ACME_CLI_EXIT_STATUS
+ fi
+ [ "$ACME_CLI_RYSNC" = "false" ] && printf_red "rsync is disabled" >&2 && return ${prevExit:-2}
+ [ -z "$ACME_CLI_UPDATE_CERTS_IPS" ] && printf_red "ACME_CLI_UPDATE_CERTS_IPS var is unset\n" >&2 && return 1
+ printf_blue "Attempting to copy the certs to your other servers via rsync"
+ for ip in $ACME_CLI_UPDATE_CERTS_IPS; do
+ ip="${ip/:*/}"
+ echo "$ip" | grep -q '[0-9]:[0-9]' && port="${ip/*:/}" || port=22
+ if [ -n "$ip" ]; then
+ if [ "$ip" != "$ACME_CLI_PRIMARY_DNS_IP" ]; then
+ ssh -q -l root -p $port $ip 'exit' && echo "connection to $ip successfully made..."
+ printf '%s%s' "Sending files to $ip:$port" " "
+ timeout 30 ssh -t root@$ip -p $port "mkdir -p /etc/letsencrypt" && timeout 30 rsync -qavhP -e "ssh -p $port" /etc/letsencrypt/* root@$ip:/etc/letsencrypt/ --delete &>/dev/null
+ preVal=$?
+ if [ $preVal -eq 0 ]; then
+ printf '%s\n' "has completed" || printf '%s\n' "has failed" >&2
+ for service in $ACME_CLI_SERVICE_RESTART; do
+ printf '%s' "Restarting $service on $ip"
+ \ssh -t -q root@$ip -p $port "systemctl restart $service" >/dev/null
+ retVal=$?
+ prevExit=$((prevExit + retVal))
+ [ $retVal = 0 ] && printf ': %s\n' 'OK' || printf ': %s\n' "Failed"
+ done
+ fi
+ else
+ printf '%s\n' "The IP matches dns server"
+ fi
+ fi
+ done
+ return $prevExit
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__gen_dns_conf() {
+ [ -n "$ACME_CLI_DNS_KEY" ] || return 0
+ [ -n "$ACME_CLI_PRIMARY_DNS_IP" ] || return 0
+ cat <"/etc/certbot/dns.conf"
+#Certbot DNS
+# Target DNS server
+dns_rfc2136_server = $ACME_CLI_PRIMARY_DNS_IP
+# TSIG key name
+dns_rfc2136_name = certbot.
+# TSIG key secret
+dns_rfc2136_secret = $ACME_CLI_DNS_KEY
+# TSIG key algorithm
+dns_rfc2136_algorithm = HMAC-SHA512
+
+EOF
+ if [ -f "$ACME_CLI_CONF_FILE" ]; then
+ chmod -f 600 "$ACME_CLI_CONF_FILE" 2>/dev/null
+ else
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__gen_config_local() {
+ __gen_dns_conf
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+ACME_CLI_START_TIMER="${ACME_CLI_START_TIMER:-$(date +%s.%N)}"
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Default exit code
+ACME_CLI_EXIT_STATUS=0
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+ACME_CLI_CONFIG_DIR="${ACME_CLI_CONFIG_DIR:-$HOME/.config/myscripts/acme-cli}"
+ACME_CLI_CONFIG_BACKUP_DIR="${ACME_CLI_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/acme-cli/backups}"
+ACME_CLI_LOG_DIR="${ACME_CLI_LOG_DIR:-$HOME/.local/log/acme-cli}"
+ACME_CLI_RUN_DIR="${ACME_CLI_RUN_DIR:-$HOME/.local/run/system_scripts/$ACME_CLI_SCRIPTS_PREFIX}"
+ACME_CLI_TEMP_DIR="${ACME_CLI_TEMP_DIR:-$HOME/.local/tmp/system_scripts/acme-cli}"
+ACME_CLI_CACHE_DIR="${ACME_CLI_CACHE_DIR:-$HOME/.cache/acme-cli}"
+ACME_CLI_LE_LOG_FILE="${ACME_CLI_LE_LOG_FILE:-$ACME_CLI_LOG_DIR/acme-cli.log}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# File settings
+ACME_CLI_CONFIG_FILE="${ACME_CLI_CONFIG_FILE:-settings.conf}"
+ACME_CLI_LOG_ERROR_FILE="${ACME_CLI_LOG_ERROR_FILE:-$ACME_CLI_LOG_DIR/acme-cli.err}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ACME_CLI_OUTPUT_COLOR_1="${ACME_CLI_OUTPUT_COLOR_1:-33}"
+ACME_CLI_OUTPUT_COLOR_2="${ACME_CLI_OUTPUT_COLOR_2:-5}"
+ACME_CLI_OUTPUT_COLOR_GOOD="${ACME_CLI_OUTPUT_COLOR_GOOD:-2}"
+ACME_CLI_OUTPUT_COLOR_ERROR="${ACME_CLI_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ACME_CLI_NOTIFY_ENABLED="${ACME_CLI_NOTIFY_ENABLED:-yes}"
+ACME_CLI_GOOD_NAME="${ACME_CLI_GOOD_NAME:-Great:}"
+ACME_CLI_ERROR_NAME="${ACME_CLI_ERROR_NAME:-Error:}"
+ACME_CLI_GOOD_MESSAGE="${ACME_CLI_GOOD_MESSAGE:-No errors reported}"
+ACME_CLI_ERROR_MESSAGE="${ACME_CLI_ERROR_MESSAGE:-Errors were reported}"
+ACME_CLI_NOTIFY_CLIENT_NAME="${ACME_CLI_NOTIFY_CLIENT_NAME:-$APPNAME}"
+ACME_CLI_NOTIFY_CLIENT_ICON="${ACME_CLI_NOTIFY_CLIENT_ICON:-notification-new}"
+ACME_CLI_NOTIFY_CLIENT_URGENCY="${ACME_CLI_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+ACME_CLI_SHORT_HOST="${ACME_CLI_SHORT_HOST:-$(hostname -s)}"
+ACME_CLI_HOSTNAME="${ACME_CLI_HOSTNAME:-$(hostname -f | grep '^' || echo "$HOSTNAME")}"
+ACME_CLI_DOMAIN_PRIMARY="${ACME_CLI_DOMAIN_PRIMARY:-$(hostname -d | grep '^' || echo "$ACME_CLI_HOSTNAME")}"
+ACME_CLI_DOMAIN_LIST="${ACME_CLI_DOMAIN_LIST:-}"
+ACME_CLI_SUB_LIST="${ACME_CLI_SUB_LIST:-}"
+ACME_CLI_WILD_LIST="${ACME_CLI_WILD_LIST:-$ACME_CLI_HOSTNAME} *.$ACME_CLI_DOMAIN_PRIMARY"
+ACME_CLI_ADD_DOMAINS="${ACME_CLI_ADD_DOMAINS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ACME_CLI_TEST="${ACME_CLI_TEST:-yes}"
+ACME_CLI_RYSNC="${ACME_CLI_RYSNC:-false}"
+ACME_CLI_CERT_DIR="${ACME_CLI_CERT_DIR:-domain}"
+ACME_CLI_CONF_FILE="${ACME_CLI_CONF_FILE:-/etc/certbot/dns.conf}"
+ACME_CLI_EMAIL="${ACME_CLI_EMAIL:-$CERTBOT_REGISTERED_EMAIL}"
+ACME_CLI_PRIMARY_DNS_IP="${ACME_CLI_PRIMARY_DNS_IP:-$(grep -sh 'dns_rfc2136_server.*=' "$ACME_CLI_CONF_FILE" | sed 's|^dns_rfc2136_server =.* ||g' | grep '^')}"
+ACME_CLI_DNS_KEY="${ACME_CLI_DNS_KEY:-$(grep -sh 'dns_rfc2136_secret.*=' "$ACME_CLI_CONF_FILE" | sed 's|^dns_rfc2136_secret =.* ||g' | grep '^')}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ACME_CLI_UPDATE_CERTS_IPS="${ACME_CLI_UPDATE_CERTS_IPS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ACME_CLI_SERVICE_RESTART="${ACME_CLI_SERVICE_RESTART:-httpd,nginx,postfix,dovecot,proftpd,cockpit }"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ACME_CLI_OPTION_ADD=""
+ACME_CLI_DOMAINS_NEW=()
+ACME_CLI_SUB_LIST="${ACME_CLI_SUB_LIST//,/ }"
+ACME_CLI_WILD_LIST="${ACME_CLI_WILD_LIST//,/ }"
+ACME_CLI_DOMAIN_LIST="${ACME_CLI_DOMAIN_LIST//,/ }"
+ACME_CLI_SERVICE_RESTART="${ACME_CLI_SERVICE_RESTART//,/ }"
+ACME_CLI_UPDATE_CERTS_IPS="${ACME_CLI_UPDATE_CERTS_IPS//,/ }"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ACME_CLI_OPTION_ADD+="--reinstall,--staple-ocsp,--cert-name \$ACME_CLI_CERT_DIR "
+ACME_CLI_OPTION_ADD+="--key-path /etc/letsencrypt/live/\$ACME_CLI_CERT_DIR/privkey.pem "
+ACME_CLI_OPTION_ADD+="--chain-path /etc/letsencrypt/live/\$ACME_CLI_CERT_DIR/cert.pem "
+ACME_CLI_OPTION_ADD+="--fullchain-path /etc/letsencrypt/live/\$ACME_CLI_CERT_DIR/fullchain.pem "
+ACME_CLI_OPTIONS="${ACME_CLI_OPTIONS:-$ACME_CLI_OPTION_ADD,--dns-rfc2136-propagation-seconds 90,}"
+ACME_CLI_DEFAULT_DOMAINS="amd64.us,apmpproject.org,arm64.us,casjay.app,casjay.casa,casjay.cc,casjay.coffee,casjay.dev,casjay.email,casjay.gdn,"
+ACME_CLI_DEFAULT_DOMAINS+="casjay.info,casjay.link,casjay.nl,casjay.org,casjay.pro,casjay.social,casjay.us,casjay.work,casjay.xyz,casjaydns.com,"
+ACME_CLI_DEFAULT_DOMAINS+="casjaydns.fyi,casjaysdev.pro,csj.lol,dockersrc.us,malaks.us,onhealth.xyz,pste.us,redxt.us,sqldb.us"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$ACME_CLI_CONFIG_DIR/$ACME_CLI_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$ACME_CLI_CONFIG_DIR/$ACME_CLI_CONFIG_FILE" ] && . "$ACME_CLI_CONFIG_DIR/$ACME_CLI_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$ACME_CLI_RUN_DIR" ] || mkdir -p "$ACME_CLI_RUN_DIR" |& __devnull
+[ -d "$ACME_CLI_LOG_DIR" ] || mkdir -p "$ACME_CLI_LOG_DIR" |& __devnull
+[ -d "$ACME_CLI_TEMP_DIR" ] || mkdir -p "$ACME_CLI_TEMP_DIR" |& __devnull
+[ -d "$ACME_CLI_CACHE_DIR" ] || mkdir -p "$ACME_CLI_CACHE_DIR" |& __devnull
+[ -f "$ACME_CLI_LE_LOG_FILE" ] && rm -Rf "$ACME_CLI_LE_LOG_FILE" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ACME_CLI_TEMP_FILE="${ACME_CLI_TEMP_FILE:-$(mktemp $ACME_CLI_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$ACME_CLI_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$ACME_CLI_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$ACME_CLI_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$ACME_CLI_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$ACME_CLI_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$ACME_CLI_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent,force,no-*,yes-*,"
+LONGOPTS+="default,init,domains:,primary:,add:,folder:,dev,prod,acme:,create:"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="remove init rsync renew modify fix"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ ACME_CLI_SILENT="true"
+ ;;
+ --force)
+ shift 1
+ export FORCE_INSTALL="true"
+ ACME_CLI_FORCE_INSTALL="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ ACME_CLI_CWD="$2"
+ [ -d "$ACME_CLI_CWD" ] || mkdir -p "$ACME_CLI_CWD" |& __devnull
+ shift 2
+ ;;
+ --no-*)
+ __options_function_no "$@"
+ ;;
+ --yes-*)
+ __options_function_yes "$@"
+ ;;
+ --default)
+ shift 1
+ ACME_CLI_DOMAIN_LIST="$ACME_CLI_DEFAULT_DOMAINS"
+ ;;
+ --key)
+ ACME_CLI_DNS_KEY="$2"
+ shift 2
+ ;;
+ --server)
+ ACME_CLI_PRIMARY_DNS_IP="$2"
+ shift 2
+ ;;
+ --domains)
+ ACME_CLI_DOMAINS_NEW+=("$2")
+ ACME_CLI_DOMAIN_LIST="${ACME_CLI_DOMAIN_LIST//$2/}"
+ shift 2
+ ;;
+ --primary)
+ ACME_CLI_DOMAIN_PRIMARY="$2"
+ shift 2
+ ;;
+ --add)
+ ACME_CLI_ADD_DOMAINS="$ACME_CLI_ADD_DOMAINS,$2"
+ ACME_CLI_ADD_DOMAINS="$(echo "$ACME_CLI_ADD_DOMAINS" | sort -u | grep -V '^$')"
+ unset ACME_CLI_DOMAIN_LIST ACME_CLI_WILD_LIST
+ shift 2
+ ;;
+ --folder)
+ ACME_CLI_CERT_DIR="$2"
+ shift 2
+ ;;
+ --acme)
+ ACME_CLI_SERVER_OPTIONS="--server $2"
+ shift 2
+ ;;
+ --dev)
+ shift 1
+ ACME_CLI_SERVER_OPTIONS="--server https://acme-staging-v02.api.letsencrypt.org/directory"
+ ;;
+ --prod)
+ shift 1
+ ACME_CLI_SERVER_OPTIONS="--server https://acme-v02.api.letsencrypt.org/directory"
+ ;;
+ --create)
+ ACME_CLI_CERT_DIR="$2" ACME_CLI_DOMAIN_PRIMARY="$2" ACME_CLI_CONFIG_FILE="$2.conf"
+ unset ACME_CLI_DOMAIN_LIST ACME_CLI_SUB_LIST ACME_CLI_WILD_LIST ACME_CLI_ADD_DOMAINS
+ shift 2
+ ;;
+ --init)
+ shift 1
+ ACME_CLI_FIRST_RUN="yes"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# ACME_CLI_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# ACME_CLI_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && ACME_CLI_CWD="$1" && shift 1 || ACME_CLI_CWD="${ACME_CLI_CWD:-$PWD}"
+ACME_CLI_CWD="$(realpath "${ACME_CLI_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$ACME_CLI_CWD" ] && cd "$ACME_CLI_CWD"; then
+# if [ "$ACME_CLI_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $ACME_CLI_CWD"
+# fi
+# else
+# printf_exit "💔 $ACME_CLI_CWD does not exist 💔"
+# fi
+export ACME_CLI_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask certbot || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+[ -d "/etc/letsencrypt/live" ] || ACME_CLI_INIT="yes"
+[ -n "$ACME_CLI_DNS_KEY" ] || ACME_CLI_DNS_KEY="$(grep -sh 'dns_rfc2136_secret.*=' "$ACME_CLI_CONF_FILE" | sed 's|^dns_rfc2136_secret.* ||g' | grep '^')"
+[ -n "$ACME_CLI_PRIMARY_DNS_IP" ] || ACME_CLI_PRIMARY_DNS_IP="$(grep -sh 'dns_rfc2136_server.*=' "$ACME_CLI_CONF_FILE" | sed 's|^dns_rfc2136_server =.* ||g' | grep '^')"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+if [ "$ACME_CLI_CONFIG_FILE" != "settings.conf" ]; then
+ __gen_config >/dev/null && [ -f "$ACME_CLI_CONFIG_DIR/$ACME_CLI_CONFIG_FILE" ] && . "$ACME_CLI_CONFIG_DIR/$ACME_CLI_CONFIG_FILE"
+fi
+[ -n "${ACME_CLI_DOMAINS_NEW[*]}" ] && ACME_CLI_DOMAIN_LIST="${ACME_CLI_DOMAINS_NEW[*]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -n "$ACME_CLI_DNS_KEY" ] || printf_exit "Please set variable ACME_CLI_DNS_KEY with your DNS auth key"
+[ -n "$ACME_CLI_PRIMARY_DNS_IP" ] || printf_exit "Please set variable ACME_CLI_PRIMARY_DNS_IP with your primary dns server IP address"
+[ -n "$ACME_CLI_EMAIL" ] && ACME_CLI_SET_EMAIL_OPTIONS="-m \"$ACME_CLI_EMAIL\"" || ACME_CLI_SET_EMAIL_OPTIONS="--register-unsafely-without-email"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Export variables
+ACME_CLI_OPTIONS="${ACME_CLI_OPTIONS//,/ }"
+ACME_CLI_OPTIONS="${ACME_CLI_OPTIONS// / }"
+ACME_CLI_CERT_DIR="${ACME_CLI_CERT_DIR:-$ACME_CLI_DOMAIN_PRIMARY}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+if grep -Rqs ' http://ca.casjay.pro' '/etc/letsencrypt/live/domain'; then
+ \rm -Rf '/etc/letsencrypt/live/domain'
+fi
+[ "$ACME_CLI_FIRST_RUN" != "yes" ] || \rm -Rf '/etc/letsencrypt'
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case $1 in
+remove)
+ shift 1
+ for d in rmd --yes "/etc/letsencrypt" "/var/letsencrypt" "/var/log/letsencrypt" "$ACME_CLI_CONFIG_DIR"; do
+ if [ -e "$d" ]; then
+ printf_yellow "Removing all files in $d"
+ \rm -Rf "${d:?Failed to determine $d}"/*
+ fi
+ done
+ exit
+ ;;
+init)
+ shift 1
+ __symlink
+ exit $?
+ ;;
+rsync)
+ shift 1
+ ACME_CLI_RYSNC="true"
+ __update_certs
+ exit $?
+ ;;
+renew)
+ shift 1
+ __certbot_renew
+ exit $?
+ ;;
+fix)
+ shift 1
+ __update_configs
+ __reload_services
+ exit $?
+ ;;
+modify)
+ shift 1
+ __symlink
+ __update_configs
+ __reload_services
+ exit $?
+ ;;
+*)
+ [ "$1" = "new" ] && shift 1
+ [ "$1" = "create" ] && shift 1
+ ACME_CLI_DOMAIN_LIST="${*:-$ACME_CLI_DOMAIN_LIST}"
+ [ -n "$ACME_CLI_DOMAINS_NEW" ] || __gen_config &>/dev/null
+ if [ -d "/etc/letsencrypt/live/$ACME_CLI_CERT_DIR" ] && [ -f "/etc/letsencrypt/renewal/$ACME_CLI_CERT_DIR" ]; then
+ __certbot_renew
+ else
+ __certbot_create
+ fi
+ exit $?
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+ACME_CLI_EXIT_STATUS="${ACME_CLI_EXIT_STATUS:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${ACME_CLI_EXIT_STATUS:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/am_i_online b/bin/am_i_online
new file mode 100755
index 000000000..c7a44f459
--- /dev/null
+++ b/bin/am_i_online
@@ -0,0 +1,740 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208041705-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : am_i_online --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 17:05 EDT
+# @@File : am_i_online
+# @@Description : Check for internet connection
+# @@Changelog : Refactor the code
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208041705-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+AM_I_ONLINE_REQUIRE_SUDO="${AM_I_ONLINE_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -ISsf --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+__printf_good() { printf '\r\b%b%s %s %b %c' "$GREEN" "${1}" "${2}" "$NC" " "; }
+__printf_error() { printf '\r\b%b%s %s %b %c' "$RED" "${1}" "${2}" "$NC" " "; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$AM_I_ONLINE_CONFIG_DIR/$AM_I_ONLINE_CONFIG_FILE"
+ fi
+ [ -d "$AM_I_ONLINE_CONFIG_DIR" ] || mkdir -p "$AM_I_ONLINE_CONFIG_DIR"
+ [ -d "$AM_I_ONLINE_CONFIG_BACKUP_DIR" ] || mkdir -p "$AM_I_ONLINE_CONFIG_BACKUP_DIR"
+ [ -f "$AM_I_ONLINE_CONFIG_DIR/$AM_I_ONLINE_CONFIG_FILE" ] &&
+ cp -Rf "$AM_I_ONLINE_CONFIG_DIR/$AM_I_ONLINE_CONFIG_FILE" "$AM_I_ONLINE_CONFIG_BACKUP_DIR/$AM_I_ONLINE_CONFIG_FILE.$$"
+ cat <"$AM_I_ONLINE_CONFIG_DIR/$AM_I_ONLINE_CONFIG_FILE"
+# Settings for am_i_online
+AM_I_ONLINE_TIMEOUT="${AM_I_ONLINE_TIMEOUT:-}"
+AM_I_ONLINE_PING_COUNT="${AM_I_ONLINE_PING_COUNT:-}"
+AM_I_ONLINE_TEST_SITE_URL="${AM_I_ONLINE_TEST_SITE_URL:-}"
+AM_I_ONLINE_TEST_SITE_PING="${AM_I_ONLINE_TEST_SITE_PING:-}"
+AM_I_ONLINE_TEST_SITE_HTTP="${AM_I_ONLINE_TEST_SITE_HTTP:-}"
+AM_I_ONLINE_TEST_SITE_HTTP_STATUS="${AM_I_ONLINE_TEST_SITE_HTTP_STATUS:-}"
+AM_I_ONLINE_LOOP_INTERVAL="${AM_I_ONLINE_LOOP_INTERVAL:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+AM_I_ONLINE_OUTPUT_COLOR_1="${AM_I_ONLINE_OUTPUT_COLOR_1:-}"
+AM_I_ONLINE_OUTPUT_COLOR_2="${AM_I_ONLINE_OUTPUT_COLOR_2:-}"
+AM_I_ONLINE_OUTPUT_COLOR_GOOD="${AM_I_ONLINE_OUTPUT_COLOR_GOOD:-}"
+AM_I_ONLINE_OUTPUT_COLOR_ERROR="${AM_I_ONLINE_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+AM_I_ONLINE_NOTIFY_ENABLED="${AM_I_ONLINE_NOTIFY_ENABLED:-}"
+AM_I_ONLINE_GOOD_NAME="${AM_I_ONLINE_GOOD_NAME:-}"
+AM_I_ONLINE_ERROR_NAME="${AM_I_ONLINE_ERROR_NAME:-}"
+AM_I_ONLINE_GOOD_MESSAGE="${AM_I_ONLINE_GOOD_MESSAGE:-}"
+AM_I_ONLINE_ERROR_MESSAGE="${AM_I_ONLINE_ERROR_MESSAGE:-}"
+AM_I_ONLINE_NOTIFY_CLIENT_NAME="${AM_I_ONLINE_NOTIFY_CLIENT_NAME:-}"
+AM_I_ONLINE_NOTIFY_CLIENT_ICON="${AM_I_ONLINE_NOTIFY_CLIENT_ICON:-}"
+AM_I_ONLINE_NOTIFY_CLIENT_URGENCY="${AM_I_ONLINE_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$AM_I_ONLINE_CONFIG_DIR/$AM_I_ONLINE_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$AM_I_ONLINE_CONFIG_DIR/$AM_I_ONLINE_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "am_i_online: Check for internet connection - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: am_i_online [options] [commands]"
+ __printf_line "--message myMessage - Set custom message"
+ __printf_line "--site 1.1.1.1 - Specify site"
+ __printf_line "--code 200 - Custom http status code"
+ __printf_line "--force - Force true"
+ __printf_line "--error - Show only errors"
+ __printf_line "--console - Show output messages"
+ __printf_line "--loop - Keeps running on a 15 second loop"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$AM_I_ONLINE_REQUIRE_SUDO" = "yes" ] && [ -z "$AM_I_ONLINE_REQUIRE_SUDO_RUN" ]; then
+ export AM_I_ONLINE_REQUIRE_SUDO="no"
+ export AM_I_ONLINE_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$AM_I_ONLINE_TEMP_FILE" ] && rm -Rf "$AM_I_ONLINE_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__simple_loop() {
+ clear
+ while :; do
+ for i in 1.1.1.1 google.com; do
+ printf '\r%s' " Pinging $i " &&
+ ping -c 1 $i &>/dev/null && printf '\r %s' "Online " ||
+ printf '\r%s' "Offline "
+ sleep 1
+ done
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__local_network() {
+ [ "$AM_I_ONLINE_RUN_LOOP" = "yes" ] && return 1
+ local hostname="" domainname="" domain=""
+ domainname="$(hostname -f 2>/dev/null)"
+ hostname="$(hostname -s 2>/dev/null)"
+ domain="$(hostname -d 2>/dev/null)"
+ if [[ "$1" = "localhost" ]] || [[ "$1" = "$hostname" ]] || [[ "$1" = "$domainname" ]] || [[ "$1" = *."$hostname.$domain" ]] ||
+ [[ "$1" = "$domainname" ]] || [[ "$1" =~ 10.*.*.* ]] || [[ "$1" =~ 192.168.*.* ]] || [[ "$1" =~ 172.16.*.* ]] ||
+ [[ "$1" =~ 127.*.*.* ]] || [[ "$1" = *.local ]] || [[ "$1" = *.localdomain ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+test_site() {
+ siteExit=1
+ curl -q --connect-timeout 1 --max-time 2 --fail --retry 0 -LSsfI https://1.1.1.1 2>/dev/null | grep -q 'server:.*cloudflare'
+ siteExit="$?"
+ export siteExit
+ return $siteExit
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+test_ping() {
+ [ -z "$no_ping" ] || return
+ local definesite="${site:-$AM_I_ONLINE_TEST_SITE_PING}"
+ local site="${definesite:-$AM_I_ONLINE_TEST_SITE_URL}"
+ local timeout="${AM_I_ONLINE_TIMEOUT:-1}"
+ local count="${AM_I_ONLINE_PING_COUNT:-0}"
+ timeout $timeout ping -c$count "$site" &>/dev/null && true || false
+ pingExit="$?"
+ export pingExit
+ return $pingExit
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+test_http() {
+ [ -z "$no_http" ] || return
+ local timeout="${AM_I_ONLINE_TIMEOUT:-1}"
+ local site="${site:-$AM_I_ONLINE_TEST_SITE_URL}"
+ local definestatus="${status:-200}"
+ local definesite="${site:-$AM_I_ONLINE_TEST_SITE_HTTP}"
+ local status="${definestatus:-$AM_I_ONLINE_TEST_SITE_HTTP_STATUS}"
+ timeout $timeout curl --disable -ISsf --insecure --max-time ${timeout} "$site" 2>/dev/null |
+ grep -e "HTTP/[0123456789]" | grep -qE "${status}|301" -n1 &>/dev/null && true || false
+ httpExit="$?"
+ export httpExit
+ return $httpExit
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_main() {
+ exitCode="0"
+ pingExit=""
+ httpExit=""
+ if [ -n "$AM_I_ONLINE_FORCE_CONNECTION" ] || __local_network "$site"; then
+ httpExit=0
+ pingExit=0
+ AM_I_ONLINE_RUN=no
+ fi
+ if [ -z "$AM_I_ONLINE_RUN" ]; then
+ if test_ping; then
+ exitCode=0
+ elif test_site; then
+ exitCode=0
+ elif test_http; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ fi
+ [ "$AM_I_ONLINE_RUN_LOOP" = "yes" ] && return $exitCode
+ options_used_message="PingSite:${site:-$AM_I_ONLINE_TEST_SITE_PING}|HTTPSite:${site:-$AM_I_ONLINE_TEST_SITE_HTTP}|StatusCode:$AM_I_ONLINE_TEST_SITE_HTTP_STATUS"
+ if [ "$pingExit" = 0 ] || [ "$httpExit" = 0 ] || [ "$exitCode" = 0 ]; then
+ exitCode=0
+ export AM_I_ONLINE_NOTIFY_CLIENT_ICON="connect_established"
+ if [ "$AM_I_ONLINE_SHOW_MESSAGE" = "yes" ]; then
+ if [ "$AM_I_ONLINE_ERROR" != "true" ] && [ "$AM_I_ONLINE_SHOW_ERROR" != "yes" ]; then
+ printf_green "$AM_I_ONLINE_GOOD_MESSAGE"
+ __notifications "$AM_I_ONLINE_GOOD_NAME ${AM_I_ONLINE_GOOD_MESSAGE}"
+ fi
+ fi
+ if [ "$AM_I_ONLINE_SHOW_CONSOLE" = "yes" ]; then
+ printf_green "Options Used - $options_used_message"
+ printf_green "$AM_I_ONLINE_GOOD_MESSAGE"
+ fi
+ else
+ if [ "$AM_I_ONLINE_SHOW_CONSOLE" = "yes" ]; then
+ AM_I_ONLINE_SHOW_ERROR="no"
+ printf_green "Options Used - $options_used_message"
+ printf_red exitCode:$exitCode httpExit:$httpExit pingExit:$pingExit
+ printf_red "$AM_I_ONLINE_MESSAGE" >&2
+ fi
+ if [ "$AM_I_ONLINE_SHOW_ERROR" = "yes" ]; then
+ printf_return 1 1 "${AM_I_ONLINE_MESSAGE:-$AM_I_ONLINE_ERROR_MESSAGE}" >&2
+ __notifications "$AM_I_ONLINE_ERROR_NAME ${AM_I_ONLINE_MESSAGE:-$AM_I_ONLINE_ERROR_MESSAGE}"
+ fi
+ exitCode=1
+ fi
+ return "${exitCode:-0}"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_loop() {
+ trap 'exitCode=$?;[ -n "$AM_I_ONLINE_CACHE_DIR" ] && [ -f "$AM_I_ONLINE_CACHE_DIR/am_i_online_no" ] && rm -f "$AM_I_ONLINE_CACHE_DIR/am_i_online_no" &>/dev/null;echo;exit ${exitCode:-0}' SIGINT SIGQUIT SIGTSTP EXIT
+ [ -n "$1" ] && __validate_ip "$1" && AM_I_ONLINE_TEST_SITE_URL="$1" || printf_red "$1 seems to be invalid... Using default"
+ local date onmess="" ofmess="" onmessorig="" ofmessorig=""
+ local send_notify_status="" exitCode="" interval="" site=""
+ clear
+ exitCode="1"
+ interval="$AM_I_ONLINE_LOOP_INTERVAL"
+ site="$AM_I_ONLINE_TEST_SITE_URL"
+ date="$(date +'%H:%M:%S')"
+ onmessorig="You appear to be online at"
+ ofmessorig="You appear to be offline at"
+ printf_yellow "To exit the loop press control+c"
+ printf_blue "Starting loop on $date to site: $site"
+ printf_cyan "And checking the site every $interval seconds"
+ send_notify="false"
+ AM_I_ONLINE_MESSAGE=""
+ while :; do
+ __execute_main
+ if [ ${exitCode:-0} -eq 0 ]; then
+ [ -n "$onmess" ] && onmess="You still appear to be online at" || onmess="$onmessorig"
+ [ "$send_notify_status" = "offline" ] && send_notify=""
+ __printf_good "${onmess}" "$date"
+ [ "$send_notify" = "true" ] || __notifications "${onmess} $date"
+ rm -f "$AM_I_ONLINE_CACHE_DIR/am_i_online_no"
+ send_notify="true"
+ send_notify_status="online"
+ else
+ [ -n "$ofmess" ] && ofmess="You still appear to be offline at" || ofmess="$ofmessorig"
+ [ "$send_notify_status" = "online" ] && send_notify=""
+ __printf_error "${ofmess}" "$date"
+ [ "$send_notify" = "true" ] || __notifications "${ofmess} $date"
+ touch "$AM_I_ONLINE_CACHE_DIR/am_i_online_no"
+ send_notify="true"
+ send_notify_status="offline"
+ fi
+ sleep $interval
+ date="$(date +'%H:%M:%S')"
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_ip() {
+ getent ahostsv4 "$1" | grep 'RAW' | awk '{print $1}' | head -n 1 || echo "$1"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__validate_ip() {
+ ip="$(__get_ip "$1")"
+ echo "$ip" | grep -q -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+AM_I_ONLINE_CONFIG_FILE="${AM_I_ONLINE_CONFIG_FILE:-settings.conf}"
+AM_I_ONLINE_CONFIG_DIR="${AM_I_ONLINE_CONFIG_DIR:-$HOME/.config/myscripts/am_i_online}"
+AM_I_ONLINE_CONFIG_BACKUP_DIR="${AM_I_ONLINE_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/am_i_online/backups}"
+AM_I_ONLINE_LOG_DIR="${AM_I_ONLINE_LOG_DIR:-$HOME/.local/log/am_i_online}"
+AM_I_ONLINE_TEMP_DIR="${AM_I_ONLINE_TEMP_DIR:-$HOME/.local/tmp/system_scripts/am_i_online}"
+AM_I_ONLINE_CACHE_DIR="${AM_I_ONLINE_CACHE_DIR:-$HOME/.cache/am_i_online}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+AM_I_ONLINE_OUTPUT_COLOR_1="${AM_I_ONLINE_OUTPUT_COLOR_1:-33}"
+AM_I_ONLINE_OUTPUT_COLOR_2="${AM_I_ONLINE_OUTPUT_COLOR_2:-5}"
+AM_I_ONLINE_OUTPUT_COLOR_GOOD="${AM_I_ONLINE_OUTPUT_COLOR_GOOD:-2}"
+AM_I_ONLINE_OUTPUT_COLOR_ERROR="${AM_I_ONLINE_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+AM_I_ONLINE_NOTIFY_ENABLED="${AM_I_ONLINE_NOTIFY_ENABLED:-yes}"
+AM_I_ONLINE_GOOD_NAME="${AM_I_ONLINE_GOOD_NAME:-Great:}"
+AM_I_ONLINE_ERROR_NAME="${AM_I_ONLINE_ERROR_NAME:-Error:}"
+AM_I_ONLINE_GOOD_MESSAGE="${AM_I_ONLINE_GOOD_MESSAGE:-🆗 you seem to be connected to the internet 🆗}"
+AM_I_ONLINE_ERROR_MESSAGE="${AM_I_ONLINE_ERROR_MESSAGE:-🚫 No internet connection 🚫}"
+AM_I_ONLINE_NOTIFY_CLIENT_NAME="${AM_I_ONLINE_NOTIFY_CLIENT_NAME:-$APPNAME}"
+AM_I_ONLINE_NOTIFY_CLIENT_ICON="${AM_I_ONLINE_NOTIFY_CLIENT_ICON:-network}"
+AM_I_ONLINE_NOTIFY_CLIENT_URGENCY="${AM_I_ONLINE_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+AM_I_ONLINE_TIMEOUT="${AM_I_ONLINE_TIMEOUT:-1}"
+AM_I_ONLINE_PING_COUNT="${AM_I_ONLINE_PING_COUNT:-1}"
+AM_I_ONLINE_TEST_SITE_URL="${AM_I_ONLINE_TEST_SITE_URL:-1.1.1.1}"
+AM_I_ONLINE_TEST_SITE_PING="${AM_I_ONLINE_TEST_SITE_PING:-1.1.1.1}"
+AM_I_ONLINE_TEST_SITE_HTTP="${AM_I_ONLINE_TEST_SITE_HTTP:-1.1.1.1}"
+AM_I_ONLINE_TEST_SITE_HTTP_STATUS="${AM_I_ONLINE_TEST_SITE_HTTP_STATUS:-[200|301]}"
+AM_I_ONLINE_LOOP_INTERVAL="${AM_I_ONLINE_LOOP_INTERVAL:-15}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$AM_I_ONLINE_CONFIG_DIR/$AM_I_ONLINE_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$AM_I_ONLINE_CONFIG_DIR/$AM_I_ONLINE_CONFIG_FILE" ] && . "$AM_I_ONLINE_CONFIG_DIR/$AM_I_ONLINE_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$AM_I_ONLINE_LOG_DIR" ] || mkdir -p "$AM_I_ONLINE_LOG_DIR" |& __devnull
+[ -d "$AM_I_ONLINE_TEMP_DIR" ] || mkdir -p "$AM_I_ONLINE_TEMP_DIR" |& __devnull
+[ -d "$AM_I_ONLINE_CACHE_DIR" ] || mkdir -p "$AM_I_ONLINE_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+AM_I_ONLINE_TEMP_FILE="${AM_I_ONLINE_TEMP_FILE:-$(mktemp $AM_I_ONLINE_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$AM_I_ONLINE_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$AM_I_ONLINE_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$AM_I_ONLINE_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$AM_I_ONLINE_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$AM_I_ONLINE_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$AM_I_ONLINE_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS="f,l,m:,s:"
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=",error,show,console,force,message:,site:,code:,loop"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ __printf_good() { printf '\r\b%s %s %c' "${1}" "${2}" " "; }
+ __printf_error() { printf '\r\b%s %s %c' "${1}" "${2}" " "; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ AM_I_ONLINE_SILENT="true"
+ ;;
+ --error)
+ shift 1
+ AM_I_ONLINE_ERROR="true"
+ AM_I_ONLINE_SHOW_ERROR="yes"
+ ;;
+ --show)
+ shift 1
+ AM_I_ONLINE_SHOW_MESSAGE="yes"
+ AM_I_ONLINE_SHOW_ERROR=""
+ ;;
+ --console)
+ shift 1
+ AM_I_ONLINE_SHOW_CONSOLE="yes"
+ ;;
+ --code)
+ status="$2"
+ no_ping="true"
+ shift 2
+ ;;
+ -f | --force)
+ shift 1
+ AM_I_ONLINE_FORCE_CONNECTION="true"
+ ;;
+ -l | --loop)
+ shift 1
+ AM_I_ONLINE_RUN_LOOP="yes"
+ ;;
+ -m | --message)
+ AM_I_ONLINE_SHOW_MESSAGE="yes"
+ AM_I_ONLINE_SHOW_ERROR="yes"
+ AM_I_ONLINE_MESSAGE="$2"
+ shift 2
+ ;;
+ -s | --site)
+ site="$2"
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# AM_I_ONLINE_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# AM_I_ONLINE_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && AM_I_ONLINE_CWD="$1" && shift 1 || AM_I_ONLINE_CWD="${AM_I_ONLINE_CWD:-$PWD}"
+AM_I_ONLINE_CWD="$(realpath "${AM_I_ONLINE_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$AM_I_ONLINE_CWD" ] && cd "$AM_I_ONLINE_CWD"; then
+# if [ "$AM_I_ONLINE_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $AM_I_ONLINE_CWD"
+# fi
+# else
+# printf_exit "💔 $AM_I_ONLINE_CWD does not exist 💔"
+# fi
+export AM_I_ONLINE_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask curl || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+AM_I_ONLINE_ERROR="${AM_I_ONLINE_ERROR:-}"
+AM_I_ONLINE_MESSAGE="${AM_I_ONLINE_MESSAGE:-}"
+AM_I_ONLINE_SHOW_ERROR="${AM_I_ONLINE_SHOW_ERROR:-}"
+AM_I_ONLINE_SHOW_MESSAGE="${AM_I_ONLINE_SHOW_MESSAGE:-}"
+AM_I_ONLINE_SHOW_CONSOLE="${AM_I_ONLINE_SHOW_CONSOLE:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+if [ "$AM_I_ONLINE_RUN_LOOP" = "yes" ]; then
+ __run_loop "$@"
+ exit $?
+else
+ __execute_main "$@"
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/anime-dl b/bin/anime-dl
new file mode 100755
index 000000000..72d488b82
--- /dev/null
+++ b/bin/anime-dl
@@ -0,0 +1,635 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208041729-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : anime-dl --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 17:29 EDT
+# @@File : anime-dl
+# @@Description : Search for anime to watch or download
+# @@Changelog : Updated to include axel
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource : https://github.com/pystardust/ani-cli
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208041729-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+ANIME_DL_REQUIRE_SUDO="${ANIME_DL_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$ANIME_DL_CONFIG_DIR/$ANIME_DL_CONFIG_FILE"
+ fi
+ [ -d "$ANIME_DL_CONFIG_DIR" ] || mkdir -p "$ANIME_DL_CONFIG_DIR"
+ [ -d "$ANIME_DL_CONFIG_BACKUP_DIR" ] || mkdir -p "$ANIME_DL_CONFIG_BACKUP_DIR"
+ [ -f "$ANIME_DL_CONFIG_DIR/$ANIME_DL_CONFIG_FILE" ] &&
+ cp -Rf "$ANIME_DL_CONFIG_DIR/$ANIME_DL_CONFIG_FILE" "$ANIME_DL_CONFIG_BACKUP_DIR/$ANIME_DL_CONFIG_FILE.$$"
+ cat <"$ANIME_DL_CONFIG_DIR/$ANIME_DL_CONFIG_FILE"
+# Settings for anime-dl
+ANIME_DL_SAVE_DIR="${ANIME_DL_SAVE_DIR:-}"
+ANIME_DL_SOURCE_FILE="${ANIME_DL_SOURCE_FILE:-}"
+ANIME_DL_UPDATE_URL="${ANIME_DL_UPDATE_URL:-}"
+ANIME_DL_UPDATE_FILE="${ANIME_DL_UPDATE_FILE:-}"
+ANIME_DL_DEFAULT_OPTS="${ANIME_DL_DEFAULT_OPTS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ANIME_DL_OUTPUT_COLOR_1="${ANIME_DL_OUTPUT_COLOR_1:-}"
+ANIME_DL_OUTPUT_COLOR_2="${ANIME_DL_OUTPUT_COLOR_2:-}"
+ANIME_DL_OUTPUT_COLOR_GOOD="${ANIME_DL_OUTPUT_COLOR_GOOD:-}"
+ANIME_DL_OUTPUT_COLOR_ERROR="${ANIME_DL_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ANIME_DL_NOTIFY_ENABLED="${ANIME_DL_NOTIFY_ENABLED:-}"
+ANIME_DL_GOOD_NAME="${ANIME_DL_GOOD_NAME:-}"
+ANIME_DL_ERROR_NAME="${ANIME_DL_ERROR_NAME:-}"
+ANIME_DL_GOOD_MESSAGE="${ANIME_DL_GOOD_MESSAGE:-}"
+ANIME_DL_ERROR_MESSAGE="${ANIME_DL_ERROR_MESSAGE:-}"
+ANIME_DL_NOTIFY_CLIENT_NAME="${ANIME_DL_NOTIFY_CLIENT_NAME:-}"
+ANIME_DL_NOTIFY_CLIENT_ICON="${ANIME_DL_NOTIFY_CLIENT_ICON:-}"
+ANIME_DL_NOTIFY_CLIENT_URGENCY="${ANIME_DL_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$ANIME_DL_CONFIG_DIR/$ANIME_DL_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$ANIME_DL_CONFIG_DIR/$ANIME_DL_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "anime-dl: Search for anime to download or watch - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: anime-dl [options] [query]"
+ __printf_line "-q best|worst|360|480|720|1080 - Set video quality"
+ __printf_line "-p /path/to/dir - Download episode to specified directory"
+ __printf_line "-r [1-7] - Select provider to scrape first "
+ __printf_line "--dir [/path/to/dir] - Sets the working directory"
+ __printf_line "-c - Continue watching anime from history"
+ __printf_line "-v - Use VLC as the media player"
+ __printf_line "-s - Watch anime together with friends, using Syncplay (mpv only)"
+ __printf_line "-f - Use fzf for anime selection"
+ __printf_line "-a - Specify episode to watch"
+ __printf_line "-d - Download episode"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$ANIME_DL_REQUIRE_SUDO" = "yes" ] && [ -z "$ANIME_DL_REQUIRE_SUDO_RUN" ]; then
+ export ANIME_DL_REQUIRE_SUDO="no"
+ export ANIME_DL_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$ANIME_DL_TEMP_FILE" ] && rm -Rf "$ANIME_DL_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__update() {
+ printf_green "Updating $APPNAME"
+ curl -q -LSsf "$ANIME_DL_UPDATE_URL" -o '/tmp/anime-cli' 2>/dev/null
+ if [[ -f "/tmp/anime-cli" ]]; then
+ if echo "$ANIME_DL_SOURCE_FILE" | grep -q "$HOME/"; then
+ mv -f "/tmp/anime-cli" "$ANIME_DL_SOURCE_FILE"
+ exitCode=0
+ elif __sudoif; then
+ sudo mv -f "/tmp/anime-cli" "$ANIME_DL_SOURCE_FILE"
+ exitCode=0
+ else
+ printf_red "Updating $APPNAME requires sudo privileges"
+ exitCode=1
+ fi
+ else
+ printf_yellow "Failed to download the anime client from:"
+ printf_red "$ANIME_DL_UPDATE_URL"
+ exitCode=1
+ fi
+ if [ -f "$ANIME_DL_SOURCE_FILE" ] && [ $exitCode = 0 ]; then
+ sudo chmod +x "$ANIME_DL_SOURCE_FILE"
+ printf_green "Updated $APPNAME"
+ else
+ printf_red "Failed to update $APPNAME"
+ exitCode=1
+ fi
+ rm -Rf "/tmp/anime-cli" &>/dev/null
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__download() {
+ local query="$*"
+ local src="$ANIME_DL_SOURCE_FILE"
+ local get_opts="${CLI_OPTS:--d}"
+ local opts="${get_opts:-$ANIME_DL_DEFAULT_OPTS}"
+ local dir="${ANIME_DL_NEW_SAVE_DIR:-$ANIME_DL_SAVE_DIR}"
+ [ -d "$dir" ] || __mkd "$dir"
+ printf_cyan "Setting download dir to $dir"
+ if [ ${#query} -eq 0 ] || [ "$query" = "" ]; then
+ if cd "$dir" &>/dev/null; then
+ eval $src $opts -p "$dir" 2>/dev/null
+ exitCode=$?
+ [ "$exitCode" = 0 ] && __notifications
+ else
+ printf_exit "Failed to create $dir"
+ fi
+ else
+ dir="$dir/$(basename ${query// /_})"
+ [ -d "$dir" ] || __mkd "$dir"
+ if cd "$dir" &>/dev/null; then
+ eval $src $opts -p "$dir" "$query" 2>/dev/null || { exitCode=1 && false; }
+ [ "$?" = 0 ] && exitCode=0 && __notifications "Download of $query has finished"
+ else
+ printf_exit "Failed to create $dir"
+ fi
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__aria2c() {
+ local exitCode=0
+ local pkg_list="aria2 axel"
+ local pkg_list_pretty="aria2,axel"
+ if __cmd_exists $pkg_list; then
+ return 0
+ elif __cmd_exists aria2c axel; then
+ return 0
+ else
+ printf_green "Installing ${pkg_list_pretty}"
+ pkmgr silent install ${pkg_list} || pkmgr silent install axel aria2c || exitCode=1
+ [ "$exitCode" = 0 ] && printf_cyan "${pkg_list_pretty} has been installed" ||
+ printf_red "${pkg_list_pretty} failed to install"
+ { __cmd_exists axel; } || { __cmd_exists aria2 || __cmd_exists aria2c; } || exit 1
+ return $exitCode
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_ani_cli() {
+ [ -f "$ANIME_DL_SOURCE_FILE" ] || __update
+ __aria2c && __download "$@" && exitCode=0 || exitCode=1
+ echo
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+ANIME_DL_CONFIG_FILE="${ANIME_DL_CONFIG_FILE:-settings.conf}"
+ANIME_DL_CONFIG_DIR="${ANIME_DL_CONFIG_DIR:-$HOME/.config/myscripts/anime-dl}"
+ANIME_DL_CONFIG_BACKUP_DIR="${ANIME_DL_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/anime-dl/backups}"
+ANIME_DL_LOG_DIR="${ANIME_DL_LOG_DIR:-$HOME/.local/log/anime-dl}"
+ANIME_DL_TEMP_DIR="${ANIME_DL_TEMP_DIR:-$HOME/.local/tmp/system_scripts/anime-dl}"
+ANIME_DL_CACHE_DIR="${ANIME_DL_CACHE_DIR:-$HOME/.cache/anime-dl}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ANIME_DL_OUTPUT_COLOR_1="${ANIME_DL_OUTPUT_COLOR_1:-33}"
+ANIME_DL_OUTPUT_COLOR_2="${ANIME_DL_OUTPUT_COLOR_2:-5}"
+ANIME_DL_OUTPUT_COLOR_GOOD="${ANIME_DL_OUTPUT_COLOR_GOOD:-2}"
+ANIME_DL_OUTPUT_COLOR_ERROR="${ANIME_DL_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ANIME_DL_NOTIFY_ENABLED="${ANIME_DL_NOTIFY_ENABLED:-yes}"
+ANIME_DL_GOOD_NAME="${ANIME_DL_GOOD_NAME:-Great:}"
+ANIME_DL_ERROR_NAME="${ANIME_DL_ERROR_NAME:-Error:}"
+ANIME_DL_GOOD_MESSAGE="${ANIME_DL_GOOD_MESSAGE:-No errors reported}"
+ANIME_DL_ERROR_MESSAGE="${ANIME_DL_ERROR_MESSAGE:-Errors were reported}"
+ANIME_DL_NOTIFY_CLIENT_NAME="${ANIME_DL_NOTIFY_CLIENT_NAME:-$APPNAME}"
+ANIME_DL_NOTIFY_CLIENT_ICON="${ANIME_DL_NOTIFY_CLIENT_ICON:-notification-new}"
+ANIME_DL_NOTIFY_CLIENT_URGENCY="${ANIME_DL_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+ANIME_DL_SAVE_DIR="${ANIME_DL_SAVE_DIR:-$HOME/Videos/Anime}"
+ANIME_DL_SOURCE_FILE="${ANIME_DL_SOURCE_FILE:-$CASJAYSDEVDIR/sources/ani-cli}"
+ANIME_DL_UPDATE_URL="${ANIME_DL_UPDATE_URL:-https://github.com/pystardust/ani-cli/raw/master/ani-cli}"
+ANIME_DL_UPDATE_FILE="${ANIME_DL_UPDATE_FILE:-ani-cli}"
+ANIME_DL_DEFAULT_OPTS="${ANIME_DL_DEFAULT_OPTS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$ANIME_DL_CONFIG_DIR/$ANIME_DL_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$ANIME_DL_CONFIG_DIR/$ANIME_DL_CONFIG_FILE" ] && . "$ANIME_DL_CONFIG_DIR/$ANIME_DL_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$ANIME_DL_LOG_DIR" ] || mkdir -p "$ANIME_DL_LOG_DIR" |& __devnull
+[ -d "$ANIME_DL_TEMP_DIR" ] || mkdir -p "$ANIME_DL_TEMP_DIR" |& __devnull
+[ -d "$ANIME_DL_CACHE_DIR" ] || mkdir -p "$ANIME_DL_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ANIME_DL_TEMP_FILE="${ANIME_DL_TEMP_FILE:-$(mktemp $ANIME_DL_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$ANIME_DL_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$ANIME_DL_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$ANIME_DL_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$ANIME_DL_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$ANIME_DL_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$ANIME_DL_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS="v,s,d,c,f,q:,a:,p:,r:"
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=",update"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ ANIME_DL_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ ANIME_DL_CWD="$2"
+ [ -d "$ANIME_DL_CWD" ] || mkdir -p "$ANIME_DL_CWD" |& __devnull
+ shift 2
+ ;;
+ --update)
+ shift 1
+ __update
+ exit $?
+ ;;
+ -v | -s | -d | -c | -f)
+ [[ -z "$CLI_OPTS" ]] && CLI_OPTS="$1 " || CLI_OPTS+="$1 "
+ shift 1
+ ;;
+ -p)
+ ANIME_DL_NEW_SAVE_DIR="$2"
+ shift 2
+ ;;
+ -q | -a | -r)
+ [[ -z "$CLI_OPTS" ]] && CLI_OPTS="$1 $2 " || CLI_OPTS+="$1 $2 "
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# ANIME_DL_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# ANIME_DL_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && ANIME_DL_CWD="$1" && shift 1 || ANIME_DL_CWD="${ANIME_DL_CWD:-$PWD}"
+#ANIME_DL_CWD="$(realpath "${ANIME_DL_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$ANIME_DL_CWD" ] && cd "$ANIME_DL_CWD"; then
+# if [ "$ANIME_DL_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $ANIME_DL_CWD"
+# fi
+# else
+# printf_exit "💔 $ANIME_DL_CWD does not exist 💔"
+# fi
+export ANIME_DL_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -d "$ANIME_DL_SAVE_DIR" ] || mkdir -p "$ANIME_DL_SAVE_DIR"
+[ $# -eq 0 ] || printf_yellow "Sending $* to: $ANIME_DL_SOURCE_FILE"
+cd "$ANIME_DL_SAVE_DIR" || printf_exit "Failed to cd into $ANIME_DL_SAVE_DIR"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__execute_ani_cli "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/anonymize b/bin/anonymize
new file mode 100755
index 000000000..af311f94d
--- /dev/null
+++ b/bin/anonymize
@@ -0,0 +1,754 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208041729-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : anonymize --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 17:29 EDT
+# @@File : anonymize
+# @@Description : Anonymous web access
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208041729-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+ANONYMIZE_REQUIRE_SUDO="${ANONYMIZE_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$ANONYMIZE_CONFIG_DIR/$ANONYMIZE_CONFIG_FILE"
+ fi
+ [ -d "$ANONYMIZE_CONFIG_DIR" ] || mkdir -p "$ANONYMIZE_CONFIG_DIR"
+ [ -d "$ANONYMIZE_CONFIG_BACKUP_DIR" ] || mkdir -p "$ANONYMIZE_CONFIG_BACKUP_DIR"
+ [ -f "$ANONYMIZE_CONFIG_DIR/$ANONYMIZE_CONFIG_FILE" ] &&
+ cp -Rf "$ANONYMIZE_CONFIG_DIR/$ANONYMIZE_CONFIG_FILE" "$ANONYMIZE_CONFIG_BACKUP_DIR/$ANONYMIZE_CONFIG_FILE.$$"
+ cat <"$ANONYMIZE_CONFIG_DIR/$ANONYMIZE_CONFIG_FILE"
+# Settings for anonymize
+ANONYMIZE_HOME="${ANONYMIZE_HOME:-}"
+ANONYMIZE_TOR_VERSION="${ANONYMIZE_TOR_VERSION:-}"
+ANONYMIZE_I2P_VERSION="${ANONYMIZE_I2P_JAR_VERSION:-}"
+ANONYMIZE_FREENET_VERSION="${ANONYMIZE_FREENET_VERSION:-}"
+ANONYMIZE_I2P_JAR="${ANONYMIZE_I2P_JAR:-}"
+ANONYMIZE_FREENET_JAR="${ANONYMIZE_FREENET_JAR:-}"
+ANONYMIZE_TOR_ARM64="${ANONYMIZE_TOR_ARM64:-}"
+ANONYMIZE_TOR_HOME="${ANONYMIZE_TOR_HOME:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ANONYMIZE_OUTPUT_COLOR_1="${ANONYMIZE_OUTPUT_COLOR_1:-}"
+ANONYMIZE_OUTPUT_COLOR_2="${ANONYMIZE_OUTPUT_COLOR_2:-}"
+ANONYMIZE_OUTPUT_COLOR_GOOD="${ANONYMIZE_OUTPUT_COLOR_GOOD:-}"
+ANONYMIZE_OUTPUT_COLOR_ERROR="${ANONYMIZE_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ANONYMIZE_NOTIFY_ENABLED="${ANONYMIZE_NOTIFY_ENABLED:-}"
+ANONYMIZE_GOOD_NAME="${ANONYMIZE_GOOD_NAME:-}"
+ANONYMIZE_ERROR_NAME="${ANONYMIZE_ERROR_NAME:-}"
+ANONYMIZE_GOOD_MESSAGE="${ANONYMIZE_GOOD_MESSAGE:-}"
+ANONYMIZE_ERROR_MESSAGE="${ANONYMIZE_ERROR_MESSAGE:-}"
+ANONYMIZE_NOTIFY_CLIENT_NAME="${ANONYMIZE_NOTIFY_CLIENT_NAME:-}"
+ANONYMIZE_NOTIFY_CLIENT_ICON="${ANONYMIZE_NOTIFY_CLIENT_ICON:-}"
+ANONYMIZE_NOTIFY_CLIENT_URGENCY="${ANONYMIZE_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$ANONYMIZE_CONFIG_DIR/$ANONYMIZE_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$ANONYMIZE_CONFIG_DIR/$ANONYMIZE_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "anonymize: Anonymous web access - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: anonymize [options] [command]"
+ __printf_line "init - Installs tor browser if it isn't installed"
+ __printf_line "proxy - Set proxy"
+ __printf_line "wireguard - Configure NetworkManager wireguard config"
+ __printf_line "tor - Launch tor browser"
+ __printf_line "i2p - Launch i2p server"
+ __printf_line "freenet - Launch freenet server"
+ __printf_line "zerotier - Initialize zerotier"
+ __printf_line "--download - Update/re-download server"
+ __printf_line "--console - Output to console"
+ __printf_line "--dir [path/to/dir] - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$ANONYMIZE_REQUIRE_SUDO" = "yes" ] && [ -z "$ANONYMIZE_REQUIRE_SUDO_RUN" ]; then
+ export ANONYMIZE_REQUIRE_SUDO="no"
+ export ANONYMIZE_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$ANONYMIZE_TEMP_FILE" ] && rm -Rf "$ANONYMIZE_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__cd() { mkdir -p "$1" && builtin cd "$1" || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__proxy_setup() {
+ local progname proxy port browser
+ progname="${1:-tor}"
+ proxy="${2:-http://localhost:9080}"
+ browser="${3:-https://check.torproject.org}"
+ port="$(echo "$proxy" | sed -e 's|.*://||g' | awk -F: '{print $2}' || echo "$proxy")"
+ if netstatg "$port" | grep -q "$progname"; then
+ SET_PROXY="$proxy"
+ SET_PROXY_NONE="127.0.0.1,localhost,.localdomain.com,.local"
+ export http_proxy="$SET_PROXY"
+ export https_proxy="$SET_PROXY"
+ export ftp_proxy="$SET_PROXY"
+ export rsync_proxy="$SET_PROXY"
+ export no_proxy="${SET_PROXY_NONE:-}"
+ export all_proxy="$SET_PROXY"
+ export HTTP_PROXY="$SET_PROXY"
+ export HTTPS_PROXY="$SET_PROXY"
+ export FTP_PROXY="$SET_PROXY"
+ export RSYNC_PROXY="$SET_PROXY"
+ export ALL_PROXY="$SET_PROXY"
+ export NO_PROXY="${SET_PROXY_NONE:-}"
+ printf_cyan "Proxy is set to $SET_PROXY"
+ mybrowser "$browser"
+ curl -q -LSsf "https://check.torproject.org" |
+ grep -q 'Congratulations. This browser is configured to use Tor' &&
+ printf_yellow "Torifing your shell - exit to quit"
+ exec bash || printf_return "Proxy seems to have failed"
+ else
+ printf_red "Can not set http proxy due to tor not running"
+ fi
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__curl_dl() { curl -q -LSsf --retry 1 "$1" -o "$2" 2>/dev/null || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_versions() { return; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__install_tor() {
+ local tor_bin=""
+ if [ "$(uname -m)" = "aarch64" ]; then
+ #printf_exit "Unsupported architecture "
+ local tor_home="$HOME/.local/share/tor/browser"
+ printf_cyan "Grabbing tor-browser from $ANONYMIZE_TOR_ARM64"
+ rm -Rf "$tor_home"
+ mkdir -p "$tor_home"
+ if __curl_dl "$ANONYMIZE_TOR_ARM64" "$ANONYMIZE_TEMP_FILE"; then
+ tar xf "$ANONYMIZE_TEMP_FILE" -C "$tor_home" --strip-components=1 && rm -Rf "$ANONYMIZE_TEMP_FILE" || exitCode=1
+ else
+ printf_exit "Failed to download torbrowser from $ANONYMIZE_TOR_ARM64"
+ fi
+ if [ -f "$tor_home/start-tor-browser.desktop" ]; then
+ cd "$tor_home" && eval "$tor_home/start-tor-browser.desktop" --register-app | printf_readline
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ fi
+ if __cmd_exists torbrowser; then
+ exitCode=0
+ elif __cmd_exists tor-browser; then
+ exitCode=0
+ elif __cmd_exists torbrowser-launcher; then
+ exitCode=0
+ elif [ -f "$tor_home/start-tor-browser" ]; then
+ tor_bin="$tor_home/start-tor-browser"
+ exitCode=0
+ elif [ -f $(find "$HOME/.local/share/torbrowser"/*/* -name 'start-tor-browser' 2>/dev/null) ]; then
+ tor_bin="$(find "$HOME/.local/share/torbrowser"/*/* -name 'start-tor-browser' 2>/dev/null)"
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ if [ "$exitCode" -ne 0 ]; then
+ printf_green "Attempting to install tor browser"
+ if pkmgr silent install tor-browser || pkmgr silent install torbrowser || pkmgr silent install tor-browser || pkmgr silent install torbrowser-launcher || false; then
+ exitCode=0
+ else
+ printf_red "Failed to install the tor browser"
+ exitCode=1
+ fi
+ fi
+ tor_bin="${tor_bin:-$(builtin type -P "$HOME/.local/share/tor/browser/Browser/start-tor-browser" || type -P "$HOME/.local/share/torbrowser/tbb"/*/*/Browser/start-tor-browser || builtin type -P torbrowser || builtin type -P tor-browser || false)}"
+ if [ -n "$tor_bin" ]; then
+ printf_green "torbrowser has been installed to $tor_bin"
+ if [ ! -e "$HOME/.local/bin/torbrowser" ]; then
+ printf '#!/usr/bin/env sh\n\n%s\n%s %s\n' "cd $(dirname $tor_bin)" "exec $tor_bin" \"\$@\" >"$HOME/.local/bin/torbrowser"
+ chmod -Rf 755 "$HOME/.local/bin/torbrowser"
+ fi
+ exitCode=0
+ else
+ printf_red "Can not find the tor browser binary"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__zerotier() {
+ if __cmd_exists yum || __cmd_exists dnf || __cmd_exists apt; then
+ __cmd_exists zerotier-cli || curl -s https://install.zerotier.com | sudo bash &>/dev/null
+ fi
+ if [ ! -f "$ANONYMIZE_CONFIG_DIR/zerotier.conf" ] && [ -n "$ZEROTIER_NETWORK_KEY" ]; then
+ zerotier-cli join $ZEROTIER_NETWORK_KEY &>/dev/null
+ echo $ZEROTIER_NETWORK_KEY >"$ANONYMIZE_CONFIG_DIR/zerotier.conf"
+ fi
+ __cmd_exists zerotier-cli || __cmd_exists zerotier-one || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+ANONYMIZE_CONFIG_FILE="${ANONYMIZE_CONFIG_FILE:-settings.conf}"
+ANONYMIZE_CONFIG_DIR="${ANONYMIZE_CONFIG_DIR:-$HOME/.config/myscripts/anonymize}"
+ANONYMIZE_CONFIG_BACKUP_DIR="${ANONYMIZE_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/anonymize/backups}"
+ANONYMIZE_LOG_DIR="${ANONYMIZE_LOG_DIR:-$HOME/.local/log/anonymize}"
+ANONYMIZE_TEMP_DIR="${ANONYMIZE_TEMP_DIR:-$HOME/.local/tmp/system_scripts/anonymize}"
+ANONYMIZE_CACHE_DIR="${ANONYMIZE_CACHE_DIR:-$HOME/.cache/anonymize}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ANONYMIZE_OUTPUT_COLOR_1="${ANONYMIZE_OUTPUT_COLOR_1:-33}"
+ANONYMIZE_OUTPUT_COLOR_2="${ANONYMIZE_OUTPUT_COLOR_2:-5}"
+ANONYMIZE_OUTPUT_COLOR_GOOD="${ANONYMIZE_OUTPUT_COLOR_GOOD:-2}"
+ANONYMIZE_OUTPUT_COLOR_ERROR="${ANONYMIZE_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ANONYMIZE_NOTIFY_ENABLED="${ANONYMIZE_NOTIFY_ENABLED:-yes}"
+ANONYMIZE_GOOD_NAME="${ANONYMIZE_GOOD_NAME:-Great:}"
+ANONYMIZE_ERROR_NAME="${ANONYMIZE_ERROR_NAME:-Error:}"
+ANONYMIZE_GOOD_MESSAGE="${ANONYMIZE_GOOD_MESSAGE:-No errors reported}"
+ANONYMIZE_ERROR_MESSAGE="${ANONYMIZE_ERROR_MESSAGE:-Errors were reported}"
+ANONYMIZE_NOTIFY_CLIENT_NAME="${ANONYMIZE_NOTIFY_CLIENT_NAME:-$APPNAME}"
+ANONYMIZE_NOTIFY_CLIENT_ICON="${ANONYMIZE_NOTIFY_CLIENT_ICON:-notification-new}"
+ANONYMIZE_NOTIFY_CLIENT_URGENCY="${ANONYMIZE_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+ANONYMIZE_TOR_VERSION="${ANONYMIZE_TOR_VERSION:-12.5.1}"
+ANONYMIZE_I2P_VERSION="${ANONYMIZE_I2P_JAR_VERSION:-2.2.1}"
+ANONYMIZE_FREENET_VERSION="${ANONYMIZE_FREENET_VERSION:-1497}"
+ANONYMIZE_HOME="${ANONYMIZE_HOME:-$HOME/.local/share/anonymize}"
+ANONYMIZE_I2P_JAR="${ANONYMIZE_I2P_JAR:-https://download.i2p2.no/releases/${ANONYMIZE_I2P_VERSION}/i2pinstall_${ANONYMIZE_I2P_VERSION}.jar}"
+ANONYMIZE_FREENET_JAR="${ANONYMIZE_FREENET_JAR:-https://github.com/freenet/fred/releases/download/build0${ANONYMIZE_FREENET_VERSION}/new_installer_offline_${ANONYMIZE_FREENET_VERSION}.jar}"
+ANONYMIZE_TOR_ARM64="${ANONYMIZE_TOR_ARM64:-https://sourceforge.net/projects/tor-browser-ports/files/${ANONYMIZE_TOR_VERSION}-alsa/tor-browser-linux-arm64-${ANONYMIZE_TOR_VERSION}_ALL.tar.xz}"
+ANONYMIZE_TOR_HOME="${ANONYMIZE_TOR_HOME:-http://imtulbcjer7mohs62lpycyod2c3pnil2x6xjirrojedbluh4d7z2g6ad.onion}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$ANONYMIZE_CONFIG_DIR/$ANONYMIZE_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$ANONYMIZE_CONFIG_DIR/$ANONYMIZE_CONFIG_FILE" ] && . "$ANONYMIZE_CONFIG_DIR/$ANONYMIZE_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$ANONYMIZE_LOG_DIR" ] || mkdir -p "$ANONYMIZE_LOG_DIR" |& __devnull
+[ -d "$ANONYMIZE_TEMP_DIR" ] || mkdir -p "$ANONYMIZE_TEMP_DIR" |& __devnull
+[ -d "$ANONYMIZE_CACHE_DIR" ] || mkdir -p "$ANONYMIZE_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ANONYMIZE_TEMP_FILE="${ANONYMIZE_TEMP_FILE:-$(mktemp $ANONYMIZE_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$ANONYMIZE_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$ANONYMIZE_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$ANONYMIZE_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$ANONYMIZE_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$ANONYMIZE_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$ANONYMIZE_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=",download,console"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="init wireguard i2p freenet tor proxy zerotier"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ ANONYMIZE_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ ANONYMIZE_CWD="$2"
+ [ -d "$ANONYMIZE_CWD" ] || mkdir -p "$ANONYMIZE_CWD" |& __devnull
+ shift 2
+ ;;
+ --download)
+ shift 1
+ ANONYMIZE_DOWNLOAD="true"
+ ;;
+ --console)
+ shift 1
+ CONSOLE="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# ANONYMIZE_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# ANONYMIZE_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && ANONYMIZE_CWD="$1" && shift 1 || ANONYMIZE_CWD="${ANONYMIZE_CWD:-$PWD}"
+ANONYMIZE_CWD="$(realpath "${ANONYMIZE_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$ANONYMIZE_CWD" ] && cd "$ANONYMIZE_CWD"; then
+# if [ "$ANONYMIZE_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $ANONYMIZE_CWD"
+# fi
+# else
+# printf_exit "💔 $ANONYMIZE_CWD does not exist 💔"
+# fi
+export ANONYMIZE_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -d "$ANONYMIZE_CWD" ] || mkdir -p "$ANONYMIZE_CWD"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+init)
+ shift 1
+ __create_versions
+ __install_tor
+ exit $?
+ ;;
+
+zerotier)
+ shift 1
+ __zerotier
+ exit $?
+ ;;
+
+wireguard)
+ shift 1
+ [ -f "$1" ] || printf_exit "$APPNAME wireguard path_2_wireguard_config"
+ file="$1"
+ sudo nmcli connection import type wireguard file "$file"
+ exit $?
+ ;;
+
+proxy)
+ shift 1
+ __proxy_setup "$@"
+ exit $?
+ ;;
+
+tor)
+ shift 1
+ __install_tor
+ if [ $? -ne 0 ]; then printf_red "Tor browser does not seem to be installed" && __notifications "Please install Tor Browser"; fi
+ if __cmd_exists tor-browser; then
+ __notifications "Launching tor-browser -new-tab --allow-remote"
+ tor-browser -new-tab --allow-remote "$ANONYMIZE_TOR_HOME" &>/dev/null &
+ elif __cmd_exists torbrowser; then
+ __notifications "Launching torbrowser -new-tab --allow-remote"
+ torbrowser -new-tab --allow-remote "$ANONYMIZE_TOR_HOME" &>/dev/null &
+ elif __cmd_exists systemmgr; then
+ sudo -n true
+ systemmgr install tor &>/dev/null
+ sleep 10
+ __proxy_setup "tor" "http://localhost:9080"
+ fi
+ exit $?
+ ;;
+
+i2p)
+ shift 1
+ __cmd_exists java || printf_exit "Please install the openjdk runtime"
+ if [ "$ANONYMIZE_DOWNLOAD" = "true" ] || [ ! -f "$ANONYMIZE_HOME/i2p/i2p-install.jar" ]; then
+ __cd "$ANONYMIZE_HOME/i2p"
+ __curl_dl "$ANONYMIZE_I2P_JAR" "$ANONYMIZE_HOME/i2p/i2p-install.jar"
+ [ -f "$ANONYMIZE_HOME/i2p/i2p-install.jar" ] || printf_exit "failed to download $ANONYMIZE_I2P_JAR"
+ printf_yellow "Install to $ANONYMIZE_HOME/i2p"
+ if [ "$CONSOLE" = "true" ]; then
+ java -jar "$ANONYMIZE_HOME/i2p/i2p-install.jar" -console
+ else
+ java -jar "$ANONYMIZE_HOME/i2p/i2p-install.jar"
+ fi
+ fi
+ if [ -f "$ANONYMIZE_HOME/i2p/i2prouter" ]; then
+ eval "$ANONYMIZE_HOME/i2p/i2prouter" start &
+ sleep 10
+ fi
+ netstatg 7657 2>&1 | grep -q java || printf_exit "i2p does not seem to be running"
+ [ -z "$BROWSER" ] || eval $BROWSER "http://localhost:7657"
+ exit $?
+ ;;
+
+freenet)
+ shift 1
+ __cmd_exists java || printf_exit "Please install the openjdk runtime"
+ if [ -f "$ANONYMIZE_HOME/Freenet/run.sh" ]; then
+ eval "$ANONYMIZE_HOME/Freenet/run.sh" start &
+ sleep 10
+ else
+ if [ "$ANONYMIZE_DOWNLOAD" = "true" ]; then
+ __cd "$ANONYMIZE_HOME/freenet"
+ if [ -f "$ANONYMIZE_HOME/freenet/freenet-install.jar" ]; then
+ __curl_dl "$ANONYMIZE_FREENET_JAR" "$ANONYMIZE_HOME/freenet/freenet-install.jar"
+ [ -f "$ANONYMIZE_HOME/freenet/freenet-install.jar" ] || printf_exit "failed to download $ANONYMIZE_FREENET_JAR"
+ fi
+ printf_yellow "Install to $ANONYMIZE_HOME/Freenet"
+ if [ "$CONSOLE" = "true" ]; then
+ java -jar "$ANONYMIZE_HOME/freenet/freenet-install.jar" -console
+ else
+ java -jar "$ANONYMIZE_HOME/freenet/freenet-install.jar"
+ fi
+ fi
+ fi
+ netstatg 8888 2>&1 | grep -q java || printf_exit "Freenet does not seem to be running"
+ [ -z "$BROWSER" ] || eval $BROWSER "http://localhost:8888"
+ exit $?
+ ;;
+
+*)
+ __help
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/append_path b/bin/append_path
new file mode 100755
index 000000000..3d5149231
--- /dev/null
+++ b/bin/append_path
@@ -0,0 +1,554 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208041957-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : append_path --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 19:57 EDT
+# @@File : append_path
+# @@Description : Append a folder to the system/user PATH
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208041957-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+APPEND_PATH_REQUIRE_SUDO="${APPEND_PATH_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$APPEND_PATH_CONFIG_DIR/$APPEND_PATH_CONFIG_FILE"
+ fi
+ [ -d "$APPEND_PATH_CONFIG_DIR" ] || mkdir -p "$APPEND_PATH_CONFIG_DIR"
+ [ -d "$APPEND_PATH_CONFIG_BACKUP_DIR" ] || mkdir -p "$APPEND_PATH_CONFIG_BACKUP_DIR"
+ [ -f "$APPEND_PATH_CONFIG_DIR/$APPEND_PATH_CONFIG_FILE" ] &&
+ cp -Rf "$APPEND_PATH_CONFIG_DIR/$APPEND_PATH_CONFIG_FILE" "$APPEND_PATH_CONFIG_BACKUP_DIR/$APPEND_PATH_CONFIG_FILE.$$"
+ cat <"$APPEND_PATH_CONFIG_DIR/$APPEND_PATH_CONFIG_FILE"
+# Settings for append_path
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+APPEND_PATH_OUTPUT_COLOR_1="${APPEND_PATH_OUTPUT_COLOR_1:-}"
+APPEND_PATH_OUTPUT_COLOR_2="${APPEND_PATH_OUTPUT_COLOR_2:-}"
+APPEND_PATH_OUTPUT_COLOR_GOOD="${APPEND_PATH_OUTPUT_COLOR_GOOD:-}"
+APPEND_PATH_OUTPUT_COLOR_ERROR="${APPEND_PATH_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+APPEND_PATH_NOTIFY_ENABLED="${APPEND_PATH_NOTIFY_ENABLED:-}"
+APPEND_PATH_GOOD_NAME="${APPEND_PATH_GOOD_NAME:-}"
+APPEND_PATH_ERROR_NAME="${APPEND_PATH_ERROR_NAME:-}"
+APPEND_PATH_GOOD_MESSAGE="${APPEND_PATH_GOOD_MESSAGE:-}"
+APPEND_PATH_ERROR_MESSAGE="${APPEND_PATH_ERROR_MESSAGE:-}"
+APPEND_PATH_NOTIFY_CLIENT_NAME="${APPEND_PATH_NOTIFY_CLIENT_NAME:-}"
+APPEND_PATH_NOTIFY_CLIENT_ICON="${APPEND_PATH_NOTIFY_CLIENT_ICON:-}"
+APPEND_PATH_NOTIFY_CLIENT_URGENCY="${APPEND_PATH_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$APPEND_PATH_CONFIG_DIR/$APPEND_PATH_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$APPEND_PATH_CONFIG_DIR/$APPEND_PATH_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "append_path: Append a folder to the system/user PATH - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: append_path [options] [/path/to/dir]"
+ __printf_line "/path/to/dirs - Add Directories to path"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$APPEND_PATH_REQUIRE_SUDO" = "yes" ] && [ -z "$APPEND_PATH_REQUIRE_SUDO_RUN" ]; then
+ export APPEND_PATH_REQUIRE_SUDO="no"
+ export APPEND_PATH_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$APPEND_PATH_TEMP_FILE" ] && rm -Rf "$APPEND_PATH_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__add2path_function() {
+ builtin type add2path 2>/dev/null | grep -q 'add2path is a function' &>/dev/null && export -f add2path || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__clean_path() {
+ tr ':' '\n' | grep "$@" | grep -Ev "$CASJAYSDEVDIR|$HOME/.local/bin" | grep -v '^$' | tr '\n' ':' | sed 's|:\.||g;s|::||g;s|:$||g' | uniq
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_append() {
+ if __add2path_function; then
+ add2path "$@"
+ elif [ $# -ne 0 ]; then
+ local PATH_NEW PATH_ADD PATH_CREATE PATH_ORIG
+ PATH_ADD="$*"
+ PATH_NEW=""
+ PATH_CREATE=""
+ PATH_ORIG_RUN="$(echo "$PATH" | __clean_path "run/user/$UID")"
+ PATH_ORIG_USER="$(echo "$PATH" | __clean_path "$HOME")"
+ PATH_ORIG_SYTEM="$(echo "$PATH" | __clean_path -vE "$HOME|run/user/$UID")"
+ PATH_ORIG="$HOME/.local/bin:$PATH_ORIG_RUN:$PATH_ORIG_USER:$CASJAYSDEVDIR:$PATH_ORIG_SYTEM"
+ for paths in $PATH_ADD; do
+ { [ -d "$paths" ] && PATH_NEW="$(realpath "$paths" 2>/dev/null)"; } ||
+ { [ -f "$paths" ] && PATH_NEW="$(dirname "$(realpath "$paths" 2>/dev/null)" 2>/dev/null)"; }
+ if echo "$PATH_NEW:$PATH:$PATH_ORIG" | tr ':' '\n' | grep -qv "$PATH_NEW"; then
+ [[ -e "$PATH_NEW" ]] && PATH_CREATE+="$PATH_NEW:"
+ fi
+ done
+ printf_yellow "Current Paths in path order:"
+ echo "${PATH_ORIG}" | tr ':' '\n' | uniq | grep -v '^$' | printf_column "5"
+ printf_blue 'New path parameters: '
+ printf_cyan 'export PATH='$PATH_CREATE'$PATH:.'
+ printf_green "source $APPEND_PATH_TEMP_DIR/append_path.path"
+ echo 'PATH="'$PATH_CREATE$PATH_ORIG:.'"' >"$APPEND_PATH_TEMP_DIR/append_path.path"
+ else
+ printf_red "Usage: $APPNAME /path/to/dir /path/to/dir2 /path/to/file"
+ exitCode=1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+APPEND_PATH_CONFIG_FILE="${APPEND_PATH_CONFIG_FILE:-settings.conf}"
+APPEND_PATH_CONFIG_DIR="${APPEND_PATH_CONFIG_DIR:-$HOME/.config/myscripts/append_path}"
+APPEND_PATH_CONFIG_BACKUP_DIR="${APPEND_PATH_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/append_path/backups}"
+APPEND_PATH_LOG_DIR="${APPEND_PATH_LOG_DIR:-$HOME/.local/log/append_path}"
+APPEND_PATH_TEMP_DIR="${APPEND_PATH_TEMP_DIR:-$HOME/.local/tmp/system_scripts/append_path}"
+APPEND_PATH_CACHE_DIR="${APPEND_PATH_CACHE_DIR:-$HOME/.cache/append_path}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+APPEND_PATH_OUTPUT_COLOR_1="${APPEND_PATH_OUTPUT_COLOR_1:-33}"
+APPEND_PATH_OUTPUT_COLOR_2="${APPEND_PATH_OUTPUT_COLOR_2:-5}"
+APPEND_PATH_OUTPUT_COLOR_GOOD="${APPEND_PATH_OUTPUT_COLOR_GOOD:-2}"
+APPEND_PATH_OUTPUT_COLOR_ERROR="${APPEND_PATH_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+APPEND_PATH_NOTIFY_ENABLED="${APPEND_PATH_NOTIFY_ENABLED:-yes}"
+APPEND_PATH_GOOD_NAME="${APPEND_PATH_GOOD_NAME:-Great:}"
+APPEND_PATH_ERROR_NAME="${APPEND_PATH_ERROR_NAME:-Error:}"
+APPEND_PATH_GOOD_MESSAGE="${APPEND_PATH_GOOD_MESSAGE:-No errors reported}"
+APPEND_PATH_ERROR_MESSAGE="${APPEND_PATH_ERROR_MESSAGE:-Errors were reported}"
+APPEND_PATH_NOTIFY_CLIENT_NAME="${APPEND_PATH_NOTIFY_CLIENT_NAME:-$APPNAME}"
+APPEND_PATH_NOTIFY_CLIENT_ICON="${APPEND_PATH_NOTIFY_CLIENT_ICON:-notification-new}"
+APPEND_PATH_NOTIFY_CLIENT_URGENCY="${APPEND_PATH_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$APPEND_PATH_CONFIG_DIR/$APPEND_PATH_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$APPEND_PATH_CONFIG_DIR/$APPEND_PATH_CONFIG_FILE" ] && . "$APPEND_PATH_CONFIG_DIR/$APPEND_PATH_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$APPEND_PATH_LOG_DIR" ] || mkdir -p "$APPEND_PATH_LOG_DIR" |& __devnull
+[ -d "$APPEND_PATH_TEMP_DIR" ] || mkdir -p "$APPEND_PATH_TEMP_DIR" |& __devnull
+[ -d "$APPEND_PATH_CACHE_DIR" ] || mkdir -p "$APPEND_PATH_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPEND_PATH_TEMP_FILE="${APPEND_PATH_TEMP_FILE:-$(mktemp $APPEND_PATH_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$APPEND_PATH_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$APPEND_PATH_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$APPEND_PATH_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$APPEND_PATH_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$APPEND_PATH_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$APPEND_PATH_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ APPEND_PATH_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ APPEND_PATH_CWD="$2"
+ [ -d "$APPEND_PATH_CWD" ] || mkdir -p "$APPEND_PATH_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# APPEND_PATH_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# APPEND_PATH_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && APPEND_PATH_CWD="$1" && shift 1 || APPEND_PATH_CWD="${APPEND_PATH_CWD:-$PWD}"
+APPEND_PATH_CWD="$(realpath "${APPEND_PATH_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$APPEND_PATH_CWD" ] && cd "$APPEND_PATH_CWD"; then
+# if [ "$APPEND_PATH_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $APPEND_PATH_CWD"
+# fi
+# else
+# printf_exit "💔 $APPEND_PATH_CWD does not exist 💔"
+# fi
+export APPEND_PATH_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__execute_append "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/ask_for_input b/bin/ask_for_input
new file mode 100755
index 000000000..869325235
--- /dev/null
+++ b/bin/ask_for_input
@@ -0,0 +1,537 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042001-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : ask_for_input --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 20:01 EDT
+# @@File : ask_for_input
+# @@Description : A simple script to ask a user for input
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042001-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+ASK_FOR_INPUT_REQUIRE_SUDO="${ASK_FOR_INPUT_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$ASK_FOR_INPUT_CONFIG_DIR/$ASK_FOR_INPUT_CONFIG_FILE"
+ fi
+ [ -d "$ASK_FOR_INPUT_CONFIG_DIR" ] || mkdir -p "$ASK_FOR_INPUT_CONFIG_DIR"
+ [ -d "$ASK_FOR_INPUT_CONFIG_BACKUP_DIR" ] || mkdir -p "$ASK_FOR_INPUT_CONFIG_BACKUP_DIR"
+ [ -f "$ASK_FOR_INPUT_CONFIG_DIR/$ASK_FOR_INPUT_CONFIG_FILE" ] &&
+ cp -Rf "$ASK_FOR_INPUT_CONFIG_DIR/$ASK_FOR_INPUT_CONFIG_FILE" "$ASK_FOR_INPUT_CONFIG_BACKUP_DIR/$ASK_FOR_INPUT_CONFIG_FILE.$$"
+ cat <"$ASK_FOR_INPUT_CONFIG_DIR/$ASK_FOR_INPUT_CONFIG_FILE"
+# Settings for ask_for_input
+ASK_FOR_INPUT_NAME="${ASK_FOR_INPUT_NAME:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ASK_FOR_INPUT_OUTPUT_COLOR_1="${ASK_FOR_INPUT_OUTPUT_COLOR_1:-}"
+ASK_FOR_INPUT_OUTPUT_COLOR_2="${ASK_FOR_INPUT_OUTPUT_COLOR_2:-}"
+ASK_FOR_INPUT_OUTPUT_COLOR_GOOD="${ASK_FOR_INPUT_OUTPUT_COLOR_GOOD:-}"
+ASK_FOR_INPUT_OUTPUT_COLOR_ERROR="${ASK_FOR_INPUT_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ASK_FOR_INPUT_NOTIFY_ENABLED="${ASK_FOR_INPUT_NOTIFY_ENABLED:-}"
+ASK_FOR_INPUT_GOOD_NAME="${ASK_FOR_INPUT_GOOD_NAME:-}"
+ASK_FOR_INPUT_ERROR_NAME="${ASK_FOR_INPUT_ERROR_NAME:-}"
+ASK_FOR_INPUT_GOOD_MESSAGE="${ASK_FOR_INPUT_GOOD_MESSAGE:-}"
+ASK_FOR_INPUT_ERROR_MESSAGE="${ASK_FOR_INPUT_ERROR_MESSAGE:-}"
+ASK_FOR_INPUT_NOTIFY_CLIENT_NAME="${ASK_FOR_INPUT_NOTIFY_CLIENT_NAME:-}"
+ASK_FOR_INPUT_NOTIFY_CLIENT_ICON="${ASK_FOR_INPUT_NOTIFY_CLIENT_ICON:-}"
+ASK_FOR_INPUT_NOTIFY_CLIENT_URGENCY="${ASK_FOR_INPUT_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$ASK_FOR_INPUT_CONFIG_DIR/$ASK_FOR_INPUT_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$ASK_FOR_INPUT_CONFIG_DIR/$ASK_FOR_INPUT_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "ask_for_input: A simple script to ask a user for input - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: ask_for_input [options] [title]"
+ __printf_line "[title] - Title to show to user"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Variables"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "MESSAGE - Message to user"
+ __printf_line "TITLE - Set title"
+ __printf_line "OPTIONS - Additional arguments"
+ __printf_line "CUSTOM - TODO : Create your own"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$ASK_FOR_INPUT_REQUIRE_SUDO" = "yes" ] && [ -z "$ASK_FOR_INPUT_REQUIRE_SUDO_RUN" ]; then
+ export ASK_FOR_INPUT_REQUIRE_SUDO="no"
+ export ASK_FOR_INPUT_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$ASK_FOR_INPUT_TEMP_FILE" ] && rm -Rf "$ASK_FOR_INPUT_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+ASK_FOR_INPUT_CONFIG_FILE="${ASK_FOR_INPUT_CONFIG_FILE:-settings.conf}"
+ASK_FOR_INPUT_CONFIG_DIR="${ASK_FOR_INPUT_CONFIG_DIR:-$HOME/.config/myscripts/ask_for_input}"
+ASK_FOR_INPUT_CONFIG_BACKUP_DIR="${ASK_FOR_INPUT_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/ask_for_input/backups}"
+ASK_FOR_INPUT_LOG_DIR="${ASK_FOR_INPUT_LOG_DIR:-$HOME/.local/log/ask_for_input}"
+ASK_FOR_INPUT_TEMP_DIR="${ASK_FOR_INPUT_TEMP_DIR:-$HOME/.local/tmp/system_scripts/ask_for_input}"
+ASK_FOR_INPUT_CACHE_DIR="${ASK_FOR_INPUT_CACHE_DIR:-$HOME/.cache/ask_for_input}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ASK_FOR_INPUT_OUTPUT_COLOR_1="${ASK_FOR_INPUT_OUTPUT_COLOR_1:-33}"
+ASK_FOR_INPUT_OUTPUT_COLOR_2="${ASK_FOR_INPUT_OUTPUT_COLOR_2:-5}"
+ASK_FOR_INPUT_OUTPUT_COLOR_GOOD="${ASK_FOR_INPUT_OUTPUT_COLOR_GOOD:-2}"
+ASK_FOR_INPUT_OUTPUT_COLOR_ERROR="${ASK_FOR_INPUT_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ASK_FOR_INPUT_NOTIFY_ENABLED="${ASK_FOR_INPUT_NOTIFY_ENABLED:-yes}"
+ASK_FOR_INPUT_GOOD_NAME="${ASK_FOR_INPUT_GOOD_NAME:-Great:}"
+ASK_FOR_INPUT_ERROR_NAME="${ASK_FOR_INPUT_ERROR_NAME:-Error:}"
+ASK_FOR_INPUT_GOOD_MESSAGE="${ASK_FOR_INPUT_GOOD_MESSAGE:-No errors reported}"
+ASK_FOR_INPUT_ERROR_MESSAGE="${ASK_FOR_INPUT_ERROR_MESSAGE:-Errors were reported}"
+ASK_FOR_INPUT_NOTIFY_CLIENT_NAME="${ASK_FOR_INPUT_NOTIFY_CLIENT_NAME:-$APPNAME}"
+ASK_FOR_INPUT_NOTIFY_CLIENT_ICON="${ASK_FOR_INPUT_NOTIFY_CLIENT_ICON:-notification-new}"
+ASK_FOR_INPUT_NOTIFY_CLIENT_URGENCY="${ASK_FOR_INPUT_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+ASK_FOR_INPUT_NAME="${ASK_FOR_INPUT_NAME:-Please fill out the form}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$ASK_FOR_INPUT_CONFIG_DIR/$ASK_FOR_INPUT_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$ASK_FOR_INPUT_CONFIG_DIR/$ASK_FOR_INPUT_CONFIG_FILE" ] && . "$ASK_FOR_INPUT_CONFIG_DIR/$ASK_FOR_INPUT_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$ASK_FOR_INPUT_LOG_DIR" ] || mkdir -p "$ASK_FOR_INPUT_LOG_DIR" |& __devnull
+[ -d "$ASK_FOR_INPUT_TEMP_DIR" ] || mkdir -p "$ASK_FOR_INPUT_TEMP_DIR" |& __devnull
+[ -d "$ASK_FOR_INPUT_CACHE_DIR" ] || mkdir -p "$ASK_FOR_INPUT_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ASK_FOR_INPUT_TEMP_FILE="${ASK_FOR_INPUT_TEMP_FILE:-$(mktemp $ASK_FOR_INPUT_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$ASK_FOR_INPUT_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$ASK_FOR_INPUT_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$ASK_FOR_INPUT_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$ASK_FOR_INPUT_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$ASK_FOR_INPUT_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$ASK_FOR_INPUT_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ ASK_FOR_INPUT_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# ASK_FOR_INPUT_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# ASK_FOR_INPUT_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && ASK_FOR_INPUT_CWD="$1" && shift 1 || ASK_FOR_INPUT_CWD="${ASK_FOR_INPUT_CWD:-$PWD}"
+ASK_FOR_INPUT_CWD="$(realpath "${ASK_FOR_INPUT_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$ASK_FOR_INPUT_CWD" ] && cd "$ASK_FOR_INPUT_CWD"; then
+# if [ "$ASK_FOR_INPUT_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $ASK_FOR_INPUT_CWD"
+# fi
+# else
+# printf_exit "💔 $ASK_FOR_INPUT_CWD does not exist 💔"
+# fi
+export ASK_FOR_INPUT_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+MESSAGE="${1:-$MESSAGE}"
+TITLE="${2:-$TITLE}"
+OPTIONS="${3:-$OPTIONS}"
+CUSTOM="${CUSTOM:-}"
+ASK_FOR_INPUT_NAME="${MESSAGE:-$ASK_FOR_INPUT_NAME}"
+ASK_FOR_INPUT_TITLE="${TITLE:-$ASK_FOR_INPUT_TITLE}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -n "$ASK_FOR_INPUT_TITLE" ] || ASK_FOR_INPUT_TITLE="Input needed!"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+if __cmd_exists yad; then
+ REPLY="$(yad --width=400 --title "$ASK_FOR_INPUT_TITLE" --entry --text "$ASK_FOR_INPUT_NAME" $OPTIONS 2>/dev/null || echo '')"
+elif __cmd_exists zenity; then
+ REPLY="$(zenity --width=400 --title "$ASK_FOR_INPUT_TITLE" --entry --text "$ASK_FOR_INPUT_NAME" $OPTIONS 2>/dev/null || echo '')"
+elif __cmd_exists gdialog; then
+ REPLY="$(gdialog --title "$ASK_FOR_INPUT_TITLE" --erase-on-exit --stdout --inputbox "$ASK_FOR_INPUT_NAME" 400x100 2>/dev/null || echo '')"
+elif __cmd_exists Xdialog; then
+ REPLY="$(Xdialog --title "$ASK_FOR_INPUT_TITLE" --editable --inputbox /tmp/tempfile 400x100 2>/dev/null || echo '')"
+elif __cmd_exists dialog; then
+ dialog --clear --title "$ASK_FOR_INPUT_TITLE" --inputbox "$ASK_FOR_INPUT_NAME" 8 40 3>"$ASK_FOR_INPUT_TEMP_FILE" 2>&3
+ REPLY="$(<"$ASK_FOR_INPUT_TEMP_FILE")"
+else
+ printf_read_input "4" "$ASK_FOR_INPUT_NAME" "180" "REPLY" "-e"
+fi
+[ -n "$REPLY" ] && echo "$REPLY" || exitCode=1
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/ask_for_password b/bin/ask_for_password
new file mode 100755
index 000000000..e98257f47
--- /dev/null
+++ b/bin/ask_for_password
@@ -0,0 +1,646 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042020-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : ask_for_password --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 20:20 EDT
+# @@File : ask_for_password
+# @@Description : Ask for password script
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042020-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+ASK_FOR_PASSWORD_REQUIRE_SUDO="${ASK_FOR_PASSWORD_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$ASK_FOR_PASSWORD_CONFIG_DIR/$ASK_FOR_PASSWORD_CONFIG_FILE"
+ fi
+ [ -d "$ASK_FOR_PASSWORD_CONFIG_DIR" ] || mkdir -p "$ASK_FOR_PASSWORD_CONFIG_DIR"
+ [ -d "$ASK_FOR_PASSWORD_CONFIG_BACKUP_DIR" ] || mkdir -p "$ASK_FOR_PASSWORD_CONFIG_BACKUP_DIR"
+ [ -f "$ASK_FOR_PASSWORD_CONFIG_DIR/$ASK_FOR_PASSWORD_CONFIG_FILE" ] &&
+ cp -Rf "$ASK_FOR_PASSWORD_CONFIG_DIR/$ASK_FOR_PASSWORD_CONFIG_FILE" "$ASK_FOR_PASSWORD_CONFIG_BACKUP_DIR/$ASK_FOR_PASSWORD_CONFIG_FILE.$$"
+ cat <"$ASK_FOR_PASSWORD_CONFIG_DIR/$ASK_FOR_PASSWORD_CONFIG_FILE"
+# Settings for ask_for_password
+ASK_FOR_PASSWORD_INPUT_NAME="${ASK_FOR_PASSWORD_INPUT_NAME:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ASK_FOR_PASSWORD_OUTPUT_COLOR_1="${ASK_FOR_PASSWORD_OUTPUT_COLOR_1:-}"
+ASK_FOR_PASSWORD_OUTPUT_COLOR_2="${ASK_FOR_PASSWORD_OUTPUT_COLOR_2:-}"
+ASK_FOR_PASSWORD_OUTPUT_COLOR_GOOD="${ASK_FOR_PASSWORD_OUTPUT_COLOR_GOOD:-}"
+ASK_FOR_PASSWORD_OUTPUT_COLOR_ERROR="${ASK_FOR_PASSWORD_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ASK_FOR_PASSWORD_NOTIFY_ENABLED="${ASK_FOR_PASSWORD_NOTIFY_ENABLED:-}"
+ASK_FOR_PASSWORD_GOOD_NAME="${ASK_FOR_PASSWORD_GOOD_NAME:-}"
+ASK_FOR_PASSWORD_ERROR_NAME="${ASK_FOR_PASSWORD_ERROR_NAME:-}"
+ASK_FOR_PASSWORD_GOOD_MESSAGE="${ASK_FOR_PASSWORD_GOOD_MESSAGE:-}"
+ASK_FOR_PASSWORD_ERROR_MESSAGE="${ASK_FOR_PASSWORD_ERROR_MESSAGE:-}"
+ASK_FOR_PASSWORD_NOTIFY_CLIENT_NAME="${ASK_FOR_PASSWORD_NOTIFY_CLIENT_NAME:-}"
+ASK_FOR_PASSWORD_NOTIFY_CLIENT_ICON="${ASK_FOR_PASSWORD_NOTIFY_CLIENT_ICON:-}"
+ASK_FOR_PASSWORD_NOTIFY_CLIENT_URGENCY="${ASK_FOR_PASSWORD_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$ASK_FOR_PASSWORD_CONFIG_DIR/$ASK_FOR_PASSWORD_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$ASK_FOR_PASSWORD_CONFIG_DIR/$ASK_FOR_PASSWORD_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "ask_for_password: Ask for password script - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: ask_for_password [options] [title]"
+ __printf_line "[title] - Set the title"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$ASK_FOR_PASSWORD_REQUIRE_SUDO" = "yes" ] && [ -z "$ASK_FOR_PASSWORD_REQUIRE_SUDO_RUN" ]; then
+ export ASK_FOR_PASSWORD_REQUIRE_SUDO="no"
+ export ASK_FOR_PASSWORD_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$ASK_FOR_PASSWORD_TEMP_FILE" ] && rm -Rf "$ASK_FOR_PASSWORD_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__set_pass() {
+ __ask_pass
+ if [ -z "$PASS_WORD" ]; then
+ PASS_WORD_STATUS="failed"
+ return 1
+ else
+ if sudo -Sp '' true <<<$PASS_WORD 2>&1 | grep -vq 'try again' &>/dev/null; then
+ if echo -e "$PASS_WORD" | sudo -S true &>/dev/null && export PASS_WORD_STATUS="completed"; then
+ return 0
+ else
+ export sudoError=1
+ export PASS_WORD_STATUS="failed"
+ return 1
+ fi
+ else
+ export PASS_WORD_STATUS="completed"
+ return 0
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_pass() {
+ local retries=0
+ local exitCode=1
+ local sudoError=0
+ local maxRetries=3
+ local PASS_WORD=""
+ local SHELL="/bin/bash"
+ local PASS_APP="sudo"
+ local INPUT_NAME="${INPUT_NAME:-$ASK_FOR_PASSWORD_INPUT_NAME}"
+ export SUDO_PROMPT="$(printf "\033[1;31m")[sudo]$(printf "\033[1;36m") password for $(printf "\033[1;32m")%p: $(printf "\033[0m")"
+ __cmd_exists sudo || return 0
+ # Check if password is needed
+ if ! builtin command sudo -n true &>/dev/null; then
+ # Check for displays
+ if [ "$(uname -s)" = "Linux" ]; then
+ if [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECT" ]; then
+ # command check and set ask_pass
+ if __cmd_exists yad; then
+ PASS_APP="yad"
+ __ask_pass() { PASS_WORD="$(yad --class="GSu" --title="${INPUT_NAME:-$APPNAME}" --text="Enter password for user $USER:" --image="dialog-password" --entry --hide-text 2>/dev/null || echo '')"; }
+ elif __cmd_exists zenity; then
+ PASS_APP="zenity"
+ __ask_pass() { PASS_WORD="$(zenity --class="GSu" --title="${INPUT_NAME:-$APPNAME}" --text="Enter password for user $USER:" --entry --hide-text 2>/dev/null || echo '')"; }
+ elif __cmd_exists rofi; then
+ PASS_APP="rofi"
+ __ask_pass() { PASS_WORD="$(rofi -theme ${ROFI_THEME:-purple} -dmenu -password -i -no-fixed-num-lines -p "Please enter your password: " 2>/dev/null || echo '')"; }
+ elif __cmd_exists dmenu; then
+ PASS_APP="dmenu"
+ __ask_pass() { PASS_WORD="$(dmenu -fn Monospace-18 -P -p "Please enter your password: " <&- 2>/dev/null && echo || echo '')"; }
+ elif __cmd_exists kdialog; then
+ PASS_APP="kdialog"
+ __ask_pass() { PASS_WORD="$(kdialog --password "Please enter your password: " 2>/dev/null || echo '')"; }
+ elif __cmd_exists gksudo; then
+ PASS_APP="gksudo"
+ __ask_pass() { PASS_WORD="$(gksudo --print-pass --message "Please enter your password: " 2>/dev/null || echo '')"; }
+ elif __cmd_exists dialog; then
+ PASS_APP="dialog"
+ dialog --clear --title "$ASK_FOR_INPUT_TITLE" --passwordbox "$ASK_FOR_INPUT_NAME" 8 40 3>"$ASK_FOR_INPUT_TEMP_FILE" 2>&3
+ REPLY="$(<"$ASK_FOR_INPUT_TEMP_FILE")"
+ else
+ PASS_APP="sudo"
+ fi
+ # If no display
+ else
+ PASS_APP="sudo"
+ fi
+ elif [ "$(uname -s)" = "Darwin" ]; then
+ PASS_APP="osascript"
+ __ask_pass() { PASS_WORD="$(osascript -e 'Tell application "System Events" to display dialog "Please enter your password: " default answer ""' -e 'text returned of result' 2>/dev/null || echo '')"; }
+ else
+ PASS_APP="sudo"
+ fi
+ # try to get the password
+ # Sanity check
+ if [ "$PASS_APP" = "sudo" ]; then
+ __notifications "Attempting to get password from sudo"
+ sudo true && export PASS_WORD_STATUS="completed" || export PASS_WORD_STATUS="failed"
+ elif [ -n "$PASS_APP" ]; then
+ # Debugger
+ if [ -n "${DEBUGGER:-$_DEBUG}" ]; then
+ __notifications "Retrieved password for $SUDO_USER"
+ printf_green "With password helper being $PASS_APP"
+ fi
+ # If password fails retry 2 more times
+ __notifications "Attempting to get password from $PASS_APP"
+ while [[ $retries -lt $maxRetries ]]; do
+ if __set_pass; then
+ sudoError=0
+ export PASS_WORD
+ export PASS_WORD_STATUS="completed"
+ break
+ else
+ __notifications "Sorry sudo said try again"
+ sudoError=1
+ export PASS_WORD_STATUS="failed"
+ fi
+ ((retries++))
+ done
+ exitCode="$sudoError"
+ # Error was encountered
+ else
+ if [ "$PASS_WORD_STATUS" = "failed" ]; then
+ message="No password seems to be present. Did you cancel?"
+ printf_red "No password seems to be present. Did you cancel?"
+ exitCode=1
+ fi
+ fi
+ # sudo says no password needed
+ else
+ message="Your password seems to be cached"
+ exitCode=0
+ export PASS_WORD_STATUS="completed"
+ fi
+ # Only show password once
+ export ASK_FOR_PASSWORD_NOTIFY_ENABLED="no"
+ # Clean up
+ sleep .5
+ unset PASS_APP PASS_WORD
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+ASK_FOR_PASSWORD_CONFIG_FILE="${ASK_FOR_PASSWORD_CONFIG_FILE:-settings.conf}"
+ASK_FOR_PASSWORD_CONFIG_DIR="${ASK_FOR_PASSWORD_CONFIG_DIR:-$HOME/.config/myscripts/ask_for_password}"
+ASK_FOR_PASSWORD_CONFIG_BACKUP_DIR="${ASK_FOR_PASSWORD_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/ask_for_password/backups}"
+ASK_FOR_PASSWORD_LOG_DIR="${ASK_FOR_PASSWORD_LOG_DIR:-$HOME/.local/log/ask_for_password}"
+ASK_FOR_PASSWORD_TEMP_DIR="${ASK_FOR_PASSWORD_TEMP_DIR:-$HOME/.local/tmp/system_scripts/ask_for_password}"
+ASK_FOR_PASSWORD_CACHE_DIR="${ASK_FOR_PASSWORD_CACHE_DIR:-$HOME/.cache/ask_for_password}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ASK_FOR_PASSWORD_OUTPUT_COLOR_1="${ASK_FOR_PASSWORD_OUTPUT_COLOR_1:-33}"
+ASK_FOR_PASSWORD_OUTPUT_COLOR_2="${ASK_FOR_PASSWORD_OUTPUT_COLOR_2:-5}"
+ASK_FOR_PASSWORD_OUTPUT_COLOR_GOOD="${ASK_FOR_PASSWORD_OUTPUT_COLOR_GOOD:-2}"
+ASK_FOR_PASSWORD_OUTPUT_COLOR_ERROR="${ASK_FOR_PASSWORD_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ASK_FOR_PASSWORD_NOTIFY_ENABLED="${ASK_FOR_PASSWORD_NOTIFY_ENABLED:-yes}"
+ASK_FOR_PASSWORD_GOOD_NAME="${ASK_FOR_PASSWORD_GOOD_NAME:-Great:}"
+ASK_FOR_PASSWORD_ERROR_NAME="${ASK_FOR_PASSWORD_ERROR_NAME:-Error:}"
+ASK_FOR_PASSWORD_GOOD_MESSAGE="${ASK_FOR_PASSWORD_GOOD_MESSAGE:-No errors reported}"
+ASK_FOR_PASSWORD_ERROR_MESSAGE="${ASK_FOR_PASSWORD_ERROR_MESSAGE:-Errors were reported}"
+ASK_FOR_PASSWORD_NOTIFY_CLIENT_NAME="${ASK_FOR_PASSWORD_NOTIFY_CLIENT_NAME:-Ask For Password}"
+ASK_FOR_PASSWORD_NOTIFY_CLIENT_ICON="${ASK_FOR_PASSWORD_NOTIFY_CLIENT_ICON:-notification-new}"
+ASK_FOR_PASSWORD_NOTIFY_CLIENT_URGENCY="${ASK_FOR_PASSWORD_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+ASK_FOR_PASSWORD_INPUT_NAME="${ASK_FOR_PASSWORD_INPUT_NAME:-Please enter your password!}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$ASK_FOR_PASSWORD_CONFIG_DIR/$ASK_FOR_PASSWORD_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$ASK_FOR_PASSWORD_CONFIG_DIR/$ASK_FOR_PASSWORD_CONFIG_FILE" ] && . "$ASK_FOR_PASSWORD_CONFIG_DIR/$ASK_FOR_PASSWORD_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$ASK_FOR_PASSWORD_LOG_DIR" ] || mkdir -p "$ASK_FOR_PASSWORD_LOG_DIR" |& __devnull
+[ -d "$ASK_FOR_PASSWORD_TEMP_DIR" ] || mkdir -p "$ASK_FOR_PASSWORD_TEMP_DIR" |& __devnull
+[ -d "$ASK_FOR_PASSWORD_CACHE_DIR" ] || mkdir -p "$ASK_FOR_PASSWORD_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ASK_FOR_PASSWORD_TEMP_FILE="${ASK_FOR_PASSWORD_TEMP_FILE:-$(mktemp $ASK_FOR_PASSWORD_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$ASK_FOR_PASSWORD_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$ASK_FOR_PASSWORD_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$ASK_FOR_PASSWORD_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$ASK_FOR_PASSWORD_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$ASK_FOR_PASSWORD_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$ASK_FOR_PASSWORD_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ ASK_FOR_PASSWORD_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ ASK_FOR_PASSWORD_CWD="$2"
+ [ -d "$ASK_FOR_PASSWORD_CWD" ] || mkdir -p "$ASK_FOR_PASSWORD_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# ASK_FOR_PASSWORD_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# ASK_FOR_PASSWORD_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && ASK_FOR_PASSWORD_CWD="$1" && shift 1 || ASK_FOR_PASSWORD_CWD="${ASK_FOR_PASSWORD_CWD:-$PWD}"
+ASK_FOR_PASSWORD_CWD="$(realpath "${ASK_FOR_PASSWORD_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$ASK_FOR_PASSWORD_CWD" ] && cd "$ASK_FOR_PASSWORD_CWD"; then
+# if [ "$ASK_FOR_PASSWORD_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $ASK_FOR_PASSWORD_CWD"
+# fi
+# else
+# printf_exit "💔 $ASK_FOR_PASSWORD_CWD does not exist 💔"
+# fi
+export ASK_FOR_PASSWORD_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+[ "$1" = "sudo" ] && shift 1
+SUDO_COMMAND="${SUDO_COMMAND:-$1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ "$#" = 0 ] && SUDO_COMMAND="true"
+[ "$PASS_WORD_STATUS" = "completed" ] && __notifications() { true; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__get_pass
+if [ "$PASS_WORD_STATUS" = "completed" ]; then
+ __notifications "${message:-Password obtained for ${SUDO_USER:-$USER}}"
+ sudo -HE $SUDO_COMMAND && exitCode=0 || exitCode=1
+else
+ exitCode=1
+fi
+[ "$exitCode" -eq 0 ] && export PASS_WORD_STATUS
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/ask_yes_no_question b/bin/ask_yes_no_question
new file mode 100755
index 000000000..a5996af46
--- /dev/null
+++ b/bin/ask_yes_no_question
@@ -0,0 +1,657 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042029-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : ask_yes_no_question --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 20:29 EDT
+# @@File : ask_yes_no_question
+# @@Description : ask user a question and execute command
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042029-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+ASK_YES_NO_QUESTION_REQUIRE_SUDO="${ASK_YES_NO_QUESTION_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$ASK_YES_NO_QUESTION_CONFIG_DIR/$ASK_YES_NO_QUESTION_CONFIG_FILE"
+ fi
+ [ -d "$ASK_YES_NO_QUESTION_CONFIG_DIR" ] || mkdir -p "$ASK_YES_NO_QUESTION_CONFIG_DIR"
+ [ -d "$ASK_YES_NO_QUESTION_CONFIG_BACKUP_DIR" ] || mkdir -p "$ASK_YES_NO_QUESTION_CONFIG_BACKUP_DIR"
+ [ -f "$ASK_YES_NO_QUESTION_CONFIG_DIR/$ASK_YES_NO_QUESTION_CONFIG_FILE" ] &&
+ cp -Rf "$ASK_YES_NO_QUESTION_CONFIG_DIR/$ASK_YES_NO_QUESTION_CONFIG_FILE" "$ASK_YES_NO_QUESTION_CONFIG_BACKUP_DIR/$ASK_YES_NO_QUESTION_CONFIG_FILE.$$"
+ cat <"$ASK_YES_NO_QUESTION_CONFIG_DIR/$ASK_YES_NO_QUESTION_CONFIG_FILE"
+# Settings for ask_yes_no_question
+ASK_YES_NO_QUESTION_DEFAULT_COMMAND="${ASK_YES_NO_QUESTION_DEFAULT_COMMAND:-}"
+ASK_YES_NO_QUESTION_INPUT_NAME="${ASK_YES_NO_QUESTION_INPUT_NAME:-}"
+ASK_YES_NO_QUESTION_ROFI_THEME="${ASK_YES_NO_QUESTION_ROFI_THEME:-}"
+ASK_YES_NO_QUESTION_NO_ERROR_MESSAGE="${ASK_YES_NO_QUESTION_NO_ERROR_MESSAGE:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ASK_YES_NO_QUESTION_OUTPUT_COLOR_1="${ASK_YES_NO_QUESTION_OUTPUT_COLOR_1:-}"
+ASK_YES_NO_QUESTION_OUTPUT_COLOR_2="${ASK_YES_NO_QUESTION_OUTPUT_COLOR_2:-}"
+ASK_YES_NO_QUESTION_OUTPUT_COLOR_GOOD="${ASK_YES_NO_QUESTION_OUTPUT_COLOR_GOOD:-}"
+ASK_YES_NO_QUESTION_OUTPUT_COLOR_ERROR="${ASK_YES_NO_QUESTION_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ASK_YES_NO_QUESTION_NOTIFY_ENABLED="${ASK_YES_NO_QUESTION_NOTIFY_ENABLED:-}"
+ASK_YES_NO_QUESTION_GOOD_NAME="${ASK_YES_NO_QUESTION_GOOD_NAME:-}"
+ASK_YES_NO_QUESTION_ERROR_NAME="${ASK_YES_NO_QUESTION_ERROR_NAME:-}"
+ASK_YES_NO_QUESTION_GOOD_MESSAGE="${ASK_YES_NO_QUESTION_GOOD_MESSAGE:-}"
+ASK_YES_NO_QUESTION_ERROR_MESSAGE="${ASK_YES_NO_QUESTION_ERROR_MESSAGE:-}"
+ASK_YES_NO_QUESTION_NOTIFY_CLIENT_NAME="${ASK_YES_NO_QUESTION_NOTIFY_CLIENT_NAME:-}"
+ASK_YES_NO_QUESTION_NOTIFY_CLIENT_ICON="${ASK_YES_NO_QUESTION_NOTIFY_CLIENT_ICON:-}"
+ASK_YES_NO_QUESTION_NOTIFY_CLIENT_URGENCY="${ASK_YES_NO_QUESTION_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$ASK_YES_NO_QUESTION_CONFIG_DIR/$ASK_YES_NO_QUESTION_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$ASK_YES_NO_QUESTION_CONFIG_DIR/$ASK_YES_NO_QUESTION_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "ask_yes_no_question: ask user a question and execute command - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: ask_yes_no_question [options] [command] [name] [title]"
+ __printf_line "sudo true MYAPP - Get sudo pass to run true with MYAPP as name"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$ASK_YES_NO_QUESTION_REQUIRE_SUDO" = "yes" ] && [ -z "$ASK_YES_NO_QUESTION_REQUIRE_SUDO_RUN" ]; then
+ export ASK_YES_NO_QUESTION_REQUIRE_SUDO="no"
+ export ASK_YES_NO_QUESTION_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$ASK_YES_NO_QUESTION_TEMP_FILE" ] && rm -Rf "$ASK_YES_NO_QUESTION_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+notify_good() {
+ local prog="$name"
+ local name="${1:-$prog}"
+ local message="${command:-Command} $ASK_YES_NO_QUESTION_GOOD_MESSAGE"
+ [ "$name" = "sudo" ] && prog="sudo" && message="Got root privileges"
+ [ "$name" = "true" ] && prog="true" && message="$name was successful"
+ export good_message="${message:-$NOTIFY_GOOD_MESSAGE}"
+ if [ -z "$SEND_NOTIFY" ]; then
+ __notifications "${prog:-$name}:" "$good_message" || printf_green "${prog:-$name}: $good_message"
+ export ASK_YES_NO_QUESTION_NOTIFY_ENABLED="${ASK_YES_NO_QUESTION_NOTIFY_ENABLED:-yes}"
+ fi
+ return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+notify_error() {
+ local prog="$name"
+ local name="${1:-$prog}"
+ local message="${command:-Command} $ASK_YES_NO_QUESTION_ERROR_MESSAGE"
+ [ "$name" = "sudo" ] && prog="sudo" && message="Failed to get root privileges"
+ [ "$name" = "true" ] && prog="true" && message="$name has failed"
+ export error_message="${message:-$NOTIFY_ERROR_MESSAGE}"
+ if [ -z "$SEND_NOTIFY" ] && [ "$ASK_YES_NO_QUESTION_NO_ERROR_MESSAGE" != "true" ]; then
+ __notifications "${prog:-$name}:" "$error_message" || printf_red "${prog:-$name}: $error_message"
+ export ASK_YES_NO_QUESTION_NOTIFY_ENABLED="${ASK_YES_NO_QUESTION_NOTIFY_ENABLED:-yes}"
+ fi
+ exitCode=1
+ return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+printf_question_term() {
+ local REPLY=""
+ printf "\n"
+ printf_read_question "5" "$1" "1" "REPLY"
+ printf "\n"
+ if printf_answer_yes "$REPLY"; then
+ eval "${2:-true}"
+ return $?
+ else
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__term() {
+ printf_question_term "$1" "$2" 2>/dev/null || return 1
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__yad() {
+ yad --question --title="${TITLE:-$APPNAME}" --width=400 --text="$1" --ellipsize --default-cancel 2>/dev/null && eval "${2:-true}"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__zenity() {
+ zenity --question --title="${TITLE:-$APPNAME}" --width=400 --text="$1" --ellipsize --default-cancel 2>/dev/null && eval "${2:-true}" || return 1
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__dmenu() {
+ [ "$(printf "No\\nYes" | dmenu -i -p "$1" -nb purple -sb white -sf black -nf gray 2>/dev/null)" = "Yes" ] && eval "${2:-true}" || return 1
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__rofi() {
+ [ "$(printf "No\\nYes" | rofi -theme ${ROFI_THEME:-$ASK_YES_NO_QUESTION_ROFI_THEME} -dmenu -i -p "$1" 2>/dev/null)" = "Yes" ] && eval "${2:-true}" || return 1
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__dialog() {
+ dialog --clear --title "${TITLE:-$APPNAME}" --yesno "Would you like to run the command:\n$2" 8 40 3>&1 2>&3 && eval "${2:-true}" || return 1
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__resend() {
+ ASK_YES_NO_QUESTION_QUESTION="$question"
+ ASK_YES_NO_QUESTION_COMMAND="$command"
+ export ASK_YES_NO_QUESTION_QUESTION ASK_YES_NO_QUESTION_COMMAND
+ ${TERMINAL:-myterminal} -e "$APPNAME --term"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+ASK_YES_NO_QUESTION_CONFIG_FILE="${ASK_YES_NO_QUESTION_CONFIG_FILE:-settings.conf}"
+ASK_YES_NO_QUESTION_CONFIG_DIR="${ASK_YES_NO_QUESTION_CONFIG_DIR:-$HOME/.config/myscripts/ask_yes_no_question}"
+ASK_YES_NO_QUESTION_CONFIG_BACKUP_DIR="${ASK_YES_NO_QUESTION_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/ask_yes_no_question/backups}"
+ASK_YES_NO_QUESTION_LOG_DIR="${ASK_YES_NO_QUESTION_LOG_DIR:-$HOME/.local/log/ask_yes_no_question}"
+ASK_YES_NO_QUESTION_TEMP_DIR="${ASK_YES_NO_QUESTION_TEMP_DIR:-$HOME/.local/tmp/system_scripts/ask_yes_no_question}"
+ASK_YES_NO_QUESTION_CACHE_DIR="${ASK_YES_NO_QUESTION_CACHE_DIR:-$HOME/.cache/ask_yes_no_question}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ASK_YES_NO_QUESTION_OUTPUT_COLOR_1="${ASK_YES_NO_QUESTION_OUTPUT_COLOR_1:-33}"
+ASK_YES_NO_QUESTION_OUTPUT_COLOR_2="${ASK_YES_NO_QUESTION_OUTPUT_COLOR_2:-5}"
+ASK_YES_NO_QUESTION_OUTPUT_COLOR_GOOD="${ASK_YES_NO_QUESTION_OUTPUT_COLOR_GOOD:-2}"
+ASK_YES_NO_QUESTION_OUTPUT_COLOR_ERROR="${ASK_YES_NO_QUESTION_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ASK_YES_NO_QUESTION_NOTIFY_ENABLED="${ASK_YES_NO_QUESTION_NOTIFY_ENABLED:-yes}"
+ASK_YES_NO_QUESTION_GOOD_NAME="${ASK_YES_NO_QUESTION_GOOD_NAME:-Great:}"
+ASK_YES_NO_QUESTION_ERROR_NAME="${ASK_YES_NO_QUESTION_ERROR_NAME:-Error:}"
+ASK_YES_NO_QUESTION_GOOD_MESSAGE="${ASK_YES_NO_QUESTION_GOOD_MESSAGE:-No errors reported}"
+ASK_YES_NO_QUESTION_ERROR_MESSAGE="${ASK_YES_NO_QUESTION_ERROR_MESSAGE:-Errors were reported}"
+ASK_YES_NO_QUESTION_NOTIFY_CLIENT_NAME="${ASK_YES_NO_QUESTION_NOTIFY_CLIENT_NAME:-$APPNAME}"
+ASK_YES_NO_QUESTION_NOTIFY_CLIENT_ICON="${ASK_YES_NO_QUESTION_NOTIFY_CLIENT_ICON:-notification-new}"
+ASK_YES_NO_QUESTION_NOTIFY_CLIENT_URGENCY="${ASK_YES_NO_QUESTION_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+ASK_YES_NO_QUESTION_NO_ERROR_MESSAGE="${ASK_YES_NO_QUESTION_NO_ERROR_MESSAGE:-true}"
+ASK_YES_NO_QUESTION_ROFI_THEME="${ASK_YES_NO_QUESTION_ROFI_THEME:-purple}"
+ASK_YES_NO_QUESTION_DEFAULT_COMMAND="${ASK_YES_NO_QUESTION_DEFAULT_COMMAND:-true}"
+ASK_YES_NO_QUESTION_INPUT_NAME="${ASK_YES_NO_QUESTION_INPUT_NAME:-Would you like to continue?}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$ASK_YES_NO_QUESTION_CONFIG_DIR/$ASK_YES_NO_QUESTION_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$ASK_YES_NO_QUESTION_CONFIG_DIR/$ASK_YES_NO_QUESTION_CONFIG_FILE" ] && . "$ASK_YES_NO_QUESTION_CONFIG_DIR/$ASK_YES_NO_QUESTION_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$ASK_YES_NO_QUESTION_LOG_DIR" ] || mkdir -p "$ASK_YES_NO_QUESTION_LOG_DIR" |& __devnull
+[ -d "$ASK_YES_NO_QUESTION_TEMP_DIR" ] || mkdir -p "$ASK_YES_NO_QUESTION_TEMP_DIR" |& __devnull
+[ -d "$ASK_YES_NO_QUESTION_CACHE_DIR" ] || mkdir -p "$ASK_YES_NO_QUESTION_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ASK_YES_NO_QUESTION_TEMP_FILE="${ASK_YES_NO_QUESTION_TEMP_FILE:-$(mktemp $ASK_YES_NO_QUESTION_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$ASK_YES_NO_QUESTION_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ ASK_YES_NO_QUESTION_GOOD_MESSAGE="${good_message:-$ASK_YES_NO_QUESTION_GOOD_MESSAGE}"
+ ASK_YES_NO_QUESTION_ERROR_MESSAGE="${error_message:-$ASK_YES_NO_QUESTION_ERROR_MESSAGE}"
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$ASK_YES_NO_QUESTION_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$ASK_YES_NO_QUESTION_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$ASK_YES_NO_QUESTION_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$ASK_YES_NO_QUESTION_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$ASK_YES_NO_QUESTION_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=",terminal,silent,off"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ ASK_YES_NO_QUESTION_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ ASK_YES_NO_QUESTION_CWD="$2"
+ [ -d "$ASK_YES_NO_QUESTION_CWD" ] || mkdir -p "$ASK_YES_NO_QUESTION_CWD" |& __devnull
+ shift 2
+ ;;
+ --term)
+ shift 1
+ launch_term="true"
+ PRESENT_QUESTION="$ASK_YES_NO_QUESTION_QUESTION"
+ PRESENT_COMMAND="$ASK_YES_NO_QUESTION_COMMAND"
+ ;;
+ --off)
+ shift 1
+ ASK_YES_NO_QUESTION_NOTIFY_ENABLED="no"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# ASK_YES_NO_QUESTION_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# ASK_YES_NO_QUESTION_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && ASK_YES_NO_QUESTION_CWD="$1" && shift 1 || ASK_YES_NO_QUESTION_CWD="${ASK_YES_NO_QUESTION_CWD:-$PWD}"
+ASK_YES_NO_QUESTION_CWD="$(realpath "${ASK_YES_NO_QUESTION_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$ASK_YES_NO_QUESTION_CWD" ] && cd "$ASK_YES_NO_QUESTION_CWD"; then
+# if [ "$ASK_YES_NO_QUESTION_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $ASK_YES_NO_QUESTION_CWD"
+# fi
+# else
+# printf_exit "💔 $ASK_YES_NO_QUESTION_CWD does not exist 💔"
+# fi
+export ASK_YES_NO_QUESTION_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+INPUT_NAME="${INPUT_NAME:-$TITLE}"
+TITLE="${INPUT_NAME:-$ASK_YES_NO_QUESTION_INPUT_NAME}"
+ASK_YES_NO_QUESTION_DEFAULT_COMMAND="${ASK_YES_NO_QUESTION_DEFAULT_COMMAND:-true}"
+ASK_YES_NO_QUESTION_QUESTION="${ASK_YES_NO_QUESTION_QUESTION:-$TITLE}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ "$1" = "sudo" ] && ask_for_password "sudo true" "sudo" "Get password for sudo"
+appname="${NOTIFY_CLIENT_NAME:-$ASK_YES_NO_QUESTION_NOTIFY_CLIENT_NAME}"
+if [ $# -ge 3 ]; then
+ question="${1:-$ASK_YES_NO_QUESTION_INPUT_NAME}"
+ command="${2:-$ASK_YES_NO_QUESTION_DEFAULT_COMMAND}"
+ name="${3:-$appname}"
+elif [ $# -eq 2 ]; then
+ name="${1:-$appname}" && shift 1
+ command="${*:-$ASK_YES_NO_QUESTION_DEFAULT_COMMAND}"
+else
+ command="${*:-$appname}"
+fi
+question="${question:-$name}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+if [ "$launch_term" = "true" ]; then
+ printf_newline '\n\n\n\n'
+ question="${PRESENT_QUESTION:-$ASK_YES_NO_QUESTION_QUESTION}"
+ command="${PRESENT_COMMAND:-$ASK_YES_NO_QUESTION_COMMAND}"
+ __term "$question" "$command" || notify_error "$name"
+else
+ if [ -n "$DISPLAY" ]; then
+ if __cmd_exists yad; then
+ __yad "$question" "$command" 2>/dev/null && notify_good "${name}" || notify_error "${name}"
+ elif __cmd_exists zenity; then
+ __zenity "$question" "$command" 2>/dev/null && notify_good "${name}" || notify_error "${name}"
+ elif __cmd_exists rofi1; then
+ __rofi "$question" "$command" 2>/dev/null && notify_good "${name}" || notify_error "${name}"
+ elif __cmd_exists dmenu1; then
+ __dmenu "$question" "$command" 2>/dev/null && notify_good "${name}" || notify_error "${name}"
+ elif __cmd_exists dialog; then
+ __dialog "$question" "$command" && notify_good "${name}" || notify_error "${name}"
+ elif [ -t 0 ]; then
+ __term "$question" "$command" || notify_error
+ else
+ __term "$question" "$command" || notify_error
+ fi
+ else
+ if [ -t 0 ]; then
+ __term "$question" "$command" || notify_error
+ else
+ __term "$question" "$command" || notify_error
+ fi
+ fi
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/auto_tail b/bin/auto_tail
new file mode 100755
index 000000000..ee00c1223
--- /dev/null
+++ b/bin/auto_tail
@@ -0,0 +1,602 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202309011234-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : auto_tail --help
+# @@Copyright : Copyright: (c) 2023 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Sep 01, 2023 12:34 EDT
+# @@File : auto_tail
+# @@Description :
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202309011234-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+AUTO_TAIL_REQUIRE_SUDO="${AUTO_TAIL_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && AUTO_TAIL_EXIT_STATUS=0 || AUTO_TAIL_EXIT_STATUS=1
+ return ${AUTO_TAIL_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && AUTO_TAIL_EXIT_STATUS=0 || AUTO_TAIL_EXIT_STATUS=1
+ return ${AUTO_TAIL_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ AUTO_TAIL_EXIT_STATUS=0
+ [ -n "$1" ] && local AUTO_TAIL_EXIT_STATUS="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && AUTO_TAIL_EXIT_STATUS+=$(($AUTO_TAIL_EXIT_STATUS + 0)) || AUTO_TAIL_EXIT_STATUS+=$(($AUTO_TAIL_EXIT_STATUS + 1))
+ done
+ [ $AUTO_TAIL_EXIT_STATUS -eq 0 ] || AUTO_TAIL_EXIT_STATUS=3
+ return ${AUTO_TAIL_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local AUTO_TAIL_EXIT_STATUS=0
+ curl -q -LSsfI --max-time 1 --retry 0 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || AUTO_TAIL_EXIT_STATUS=4
+ return ${AUTO_TAIL_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$AUTO_TAIL_CONFIG_DIR/$AUTO_TAIL_CONFIG_FILE"
+ fi
+ [ -d "$AUTO_TAIL_CONFIG_DIR" ] || mkdir -p "$AUTO_TAIL_CONFIG_DIR"
+ [ -d "$AUTO_TAIL_CONFIG_BACKUP_DIR" ] || mkdir -p "$AUTO_TAIL_CONFIG_BACKUP_DIR"
+ [ -f "$AUTO_TAIL_CONFIG_DIR/$AUTO_TAIL_CONFIG_FILE" ] &&
+ cp -Rf "$AUTO_TAIL_CONFIG_DIR/$AUTO_TAIL_CONFIG_FILE" "$AUTO_TAIL_CONFIG_BACKUP_DIR/$AUTO_TAIL_CONFIG_FILE.$$"
+ cat <"$AUTO_TAIL_CONFIG_DIR/$AUTO_TAIL_CONFIG_FILE"
+# Settings for auto_tail
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+AUTO_TAIL_OUTPUT_COLOR_1="${AUTO_TAIL_OUTPUT_COLOR_1:-}"
+AUTO_TAIL_OUTPUT_COLOR_2="${AUTO_TAIL_OUTPUT_COLOR_2:-}"
+AUTO_TAIL_OUTPUT_COLOR_GOOD="${AUTO_TAIL_OUTPUT_COLOR_GOOD:-}"
+AUTO_TAIL_OUTPUT_COLOR_ERROR="${AUTO_TAIL_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+AUTO_TAIL_NOTIFY_ENABLED="${AUTO_TAIL_NOTIFY_ENABLED:-}"
+AUTO_TAIL_GOOD_NAME="${AUTO_TAIL_GOOD_NAME:-}"
+AUTO_TAIL_ERROR_NAME="${AUTO_TAIL_ERROR_NAME:-}"
+AUTO_TAIL_GOOD_MESSAGE="${AUTO_TAIL_GOOD_MESSAGE:-}"
+AUTO_TAIL_ERROR_MESSAGE="${AUTO_TAIL_ERROR_MESSAGE:-}"
+AUTO_TAIL_NOTIFY_CLIENT_NAME="${AUTO_TAIL_NOTIFY_CLIENT_NAME:-}"
+AUTO_TAIL_NOTIFY_CLIENT_ICON="${AUTO_TAIL_NOTIFY_CLIENT_ICON:-}"
+AUTO_TAIL_NOTIFY_CLIENT_URGENCY="${AUTO_TAIL_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$AUTO_TAIL_CONFIG_DIR/$AUTO_TAIL_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$AUTO_TAIL_CONFIG_DIR/$AUTO_TAIL_CONFIG_FILE"
+ AUTO_TAIL_EXIT_STATUS=0
+ else
+ printf_red "Failed to create the config file"
+ AUTO_TAIL_EXIT_STATUS=1
+ fi
+ return ${AUTO_TAIL_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "auto_tail: - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: auto_tail [options] [commands]"
+ __printf_line " - "
+ __printf_line " - "
+ __printf_line "--dir - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__grep() { grep "$@" 2>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$AUTO_TAIL_REQUIRE_SUDO" = "yes" ] && [ -z "$AUTO_TAIL_REQUIRE_SUDO_RUN" ]; then
+ export AUTO_TAIL_REQUIRE_SUDO="no"
+ export AUTO_TAIL_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ AUTO_TAIL_EXIT_STATUS=$?
+ else
+ printf '%s\n' "This requires root to run"
+ AUTO_TAIL_EXIT_STATUS=1
+ fi
+ return ${AUTO_TAIL_EXIT_STATUS:-0}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__how_long_did_it_take() {
+ local retprev=$?
+ local retval=${1:-$retprev}
+ __cmd_exists bc || return $retval
+ [ -n "$AUTO_TAIL_START_TIMER" ] || return 0
+ local stop_time="$(date +%s.%N)"
+ local dt=$(echo "$stop_time - $AUTO_TAIL_START_TIMER" | bc)
+ local dd=$(echo "$dt/86400" | bc)
+ local dt2=$(echo "$dt-86400*$dd" | bc)
+ local dh=$(echo "$dt2/3600" | bc)
+ local dt3=$(echo "$dt2-3600*$dh" | bc)
+ local dm=$(echo "$dt3/60" | bc)
+ local ds=$(echo "$dt3-60*$dm" | bc)
+ printf_purple "$(LC_NUMERIC=C printf "Total runtime: %d Days, %02d Hours, %02d Minutes, %02.4f Seconds\n" $dd $dh $dm $ds)"
+ return $retval
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ AUTO_TAIL_EXIT_STATUS=${AUTO_TAIL_EXIT_STATUS:-0}
+ [ -f "$AUTO_TAIL_TEMP_FILE" ] && rm -Rf "$AUTO_TAIL_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $AUTO_TAIL_EXIT_STATUS
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a --no-* options function
+__no_options_function() {
+ case $1 in
+ *) ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__get_files() { find $AUTO_TAIL_BASE_DIR -maxdepth 3 -type f 2>/dev/null; }
+__get_count() { find $AUTO_TAIL_BASE_DIR -maxdepth 3 -type f 2>/dev/null | wc -l; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_thread() {
+ printf_cyan "Following logs in $AUTO_TAIL_NAME" && sleep 1
+ local files="$(__get_files)"
+ tail --follow=name --retry $files &
+ THREAD_PID=$!
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit_local() {
+ pgrep -P $$ | xargs -I kill {} 2>/dev/null
+ exit
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+AUTO_TAIL_START_TIMER="${AUTO_TAIL_START_TIMER:-$(date +%s.%N)}"
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Default exit code
+AUTO_TAIL_EXIT_STATUS=0
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+AUTO_TAIL_CONFIG_DIR="${AUTO_TAIL_CONFIG_DIR:-$HOME/.config/myscripts/auto_tail}"
+AUTO_TAIL_CONFIG_BACKUP_DIR="${AUTO_TAIL_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/auto_tail/backups}"
+AUTO_TAIL_LOG_DIR="${AUTO_TAIL_LOG_DIR:-$HOME/.local/log/auto_tail}"
+AUTO_TAIL_RUN_DIR="${AUTO_TAIL_RUN_DIR:-$HOME/.local/run/system_scripts/$AUTO_TAIL_SCRIPTS_PREFIX}"
+AUTO_TAIL_TEMP_DIR="${AUTO_TAIL_TEMP_DIR:-$HOME/.local/tmp/system_scripts/auto_tail}"
+AUTO_TAIL_CACHE_DIR="${AUTO_TAIL_CACHE_DIR:-$HOME/.cache/auto_tail}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# File settings
+AUTO_TAIL_CONFIG_FILE="${AUTO_TAIL_CONFIG_FILE:-settings.conf}"
+AUTO_TAIL_LOG_ERROR_FILE="${AUTO_TAIL_LOG_ERROR_FILE:-$AUTO_TAIL_LOG_DIR/error.log}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+AUTO_TAIL_OUTPUT_COLOR_1="${AUTO_TAIL_OUTPUT_COLOR_1:-33}"
+AUTO_TAIL_OUTPUT_COLOR_2="${AUTO_TAIL_OUTPUT_COLOR_2:-5}"
+AUTO_TAIL_OUTPUT_COLOR_GOOD="${AUTO_TAIL_OUTPUT_COLOR_GOOD:-2}"
+AUTO_TAIL_OUTPUT_COLOR_ERROR="${AUTO_TAIL_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+AUTO_TAIL_NOTIFY_ENABLED="${AUTO_TAIL_NOTIFY_ENABLED:-yes}"
+AUTO_TAIL_GOOD_NAME="${AUTO_TAIL_GOOD_NAME:-Great:}"
+AUTO_TAIL_ERROR_NAME="${AUTO_TAIL_ERROR_NAME:-Error:}"
+AUTO_TAIL_GOOD_MESSAGE="${AUTO_TAIL_GOOD_MESSAGE:-No errors reported}"
+AUTO_TAIL_ERROR_MESSAGE="${AUTO_TAIL_ERROR_MESSAGE:-Errors were reported}"
+AUTO_TAIL_NOTIFY_CLIENT_NAME="${AUTO_TAIL_NOTIFY_CLIENT_NAME:-$APPNAME}"
+AUTO_TAIL_NOTIFY_CLIENT_ICON="${AUTO_TAIL_NOTIFY_CLIENT_ICON:-notification-new}"
+AUTO_TAIL_NOTIFY_CLIENT_URGENCY="${AUTO_TAIL_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+AUTO_TAIL_DEFAULT_LOG_DIR="${AUTO_TAIL_DEFAULT_LOG_DIR:-$HOME/.local/log/buildx}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$AUTO_TAIL_CONFIG_DIR/$AUTO_TAIL_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$AUTO_TAIL_CONFIG_DIR/$AUTO_TAIL_CONFIG_FILE" ] && . "$AUTO_TAIL_CONFIG_DIR/$AUTO_TAIL_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$AUTO_TAIL_RUN_DIR" ] || mkdir -p "$AUTO_TAIL_RUN_DIR" |& __devnull
+[ -d "$AUTO_TAIL_LOG_DIR" ] || mkdir -p "$AUTO_TAIL_LOG_DIR" |& __devnull
+[ -d "$AUTO_TAIL_TEMP_DIR" ] || mkdir -p "$AUTO_TAIL_TEMP_DIR" |& __devnull
+[ -d "$AUTO_TAIL_CACHE_DIR" ] || mkdir -p "$AUTO_TAIL_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+AUTO_TAIL_TEMP_FILE="${AUTO_TAIL_TEMP_FILE:-$(mktemp $AUTO_TAIL_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$AUTO_TAIL_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$AUTO_TAIL_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$AUTO_TAIL_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$AUTO_TAIL_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$AUTO_TAIL_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$AUTO_TAIL_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent,force,no-*"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ AUTO_TAIL_SILENT="true"
+ ;;
+ --force)
+ shift 1
+ AUTO_TAIL_FORCE="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ AUTO_TAIL_CWD="$2"
+ [ -d "$AUTO_TAIL_CWD" ] || mkdir -p "$AUTO_TAIL_CWD" |& __devnull
+ shift 2
+ ;;
+ --no-*)
+ shift 1
+ __no_options_function "$@"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# AUTO_TAIL_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# AUTO_TAIL_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && AUTO_TAIL_CWD="$1" && shift 1 || AUTO_TAIL_CWD="${AUTO_TAIL_CWD:-$PWD}"
+AUTO_TAIL_CWD="$(realpath "${AUTO_TAIL_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$AUTO_TAIL_CWD" ] && cd "$AUTO_TAIL_CWD"; then
+# if [ "$AUTO_TAIL_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $AUTO_TAIL_CWD"
+# fi
+# else
+# printf_exit "💔 $AUTO_TAIL_CWD does not exist 💔"
+# fi
+export AUTO_TAIL_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+for dir in "$@"; do
+ AUTO_TAIL_GET_PATTERN+=("$dir")
+ AUTO_TAIL_NAME+=("$(dirname $dir* | head -1)")
+ if [ ! -d $AUTO_TAIL_BASE_DIR ]; then
+ echo DIR $AUTO_TAIL_BASE_DIR does not exist, waiting for it...
+ while [ ! -d "$AUTO_TAIL_BASE_DIR" ]; do
+ sleep 2
+ done
+ echo DIR $AUTO_TAIL_BASE_DIR is now online
+ fi
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+AUTO_TAIL_NAME=("$(printf '%s\n' "${AUTO_TAIL_NAME[@]}" | sort -u | tr '\n' ' ')")
+AUTO_TAIL_BASE_DIR="\"${AUTO_TAIL_GET_PATTERN[*]}\""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Export variables
+OLD_NUM_OF_FILES=$(__get_count)
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__run_thread
+while true; do
+ # If files are added - retail
+ NUM_FILES=$(__get_count)
+ if [ $NUM_FILES -ne $OLD_NUM_OF_FILES ]; then
+ OLD_NUM_OF_FILES=$NUM_FILES
+ kill $THREAD_PID
+ __run_thread
+ fi
+ sleep 1
+done
+AUTO_TAIL_EXIT_STATUS=$?
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+AUTO_TAIL_EXIT_STATUS="${AUTO_TAIL_EXIT_STATUS:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${AUTO_TAIL_EXIT_STATUS:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/automate b/bin/automate
new file mode 100755
index 000000000..8998d3ec2
--- /dev/null
+++ b/bin/automate
@@ -0,0 +1,582 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042043-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : automate --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 20:43 EDT
+# @@File : automate
+# @@Description : Script to control roku and hue devices
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042043-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+AUTOMATE_REQUIRE_SUDO="${AUTOMATE_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$AUTOMATE_CONFIG_DIR/$AUTOMATE_CONFIG_FILE"
+ fi
+ [ -d "$AUTOMATE_CONFIG_DIR" ] || mkdir -p "$AUTOMATE_CONFIG_DIR"
+ [ -d "$AUTOMATE_CONFIG_BACKUP_DIR" ] || mkdir -p "$AUTOMATE_CONFIG_BACKUP_DIR"
+ [ -f "$AUTOMATE_CONFIG_DIR/$AUTOMATE_CONFIG_FILE" ] &&
+ cp -Rf "$AUTOMATE_CONFIG_DIR/$AUTOMATE_CONFIG_FILE" "$AUTOMATE_CONFIG_BACKUP_DIR/$AUTOMATE_CONFIG_FILE.$$"
+ cat <"$AUTOMATE_CONFIG_DIR/$AUTOMATE_CONFIG_FILE"
+# Settings for automate
+AUTOMATE_CACHE_DIR="${AUTOMATE_CACHE_DIR:-}"
+AUTOMATE_STATE_FILE="${AUTOMATE_STATE_FILE:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+AUTOMATE_OUTPUT_COLOR_1="${AUTOMATE_OUTPUT_COLOR_1:-}"
+AUTOMATE_OUTPUT_COLOR_2="${AUTOMATE_OUTPUT_COLOR_2:-}"
+AUTOMATE_OUTPUT_COLOR_GOOD="${AUTOMATE_OUTPUT_COLOR_GOOD:-}"
+AUTOMATE_OUTPUT_COLOR_ERROR="${AUTOMATE_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+AUTOMATE_NOTIFY_ENABLED="${AUTOMATE_NOTIFY_ENABLED:-}"
+AUTOMATE_GOOD_NAME="${AUTOMATE_GOOD_NAME:-}"
+AUTOMATE_ERROR_NAME="${AUTOMATE_ERROR_NAME:-}"
+AUTOMATE_GOOD_MESSAGE="${AUTOMATE_GOOD_MESSAGE:-}"
+AUTOMATE_ERROR_MESSAGE="${AUTOMATE_ERROR_MESSAGE:-}"
+AUTOMATE_NOTIFY_CLIENT_NAME="${AUTOMATE_NOTIFY_CLIENT_NAME:-}"
+AUTOMATE_NOTIFY_CLIENT_ICON="${AUTOMATE_NOTIFY_CLIENT_ICON:-}"
+AUTOMATE_NOTIFY_CLIENT_URGENCY="${AUTOMATE_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$AUTOMATE_CONFIG_DIR/$AUTOMATE_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$AUTOMATE_CONFIG_DIR/$AUTOMATE_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "automate: Script to control roku and hue devices - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: automate [options] [commands]"
+ __printf_line "play - Turn off lights and play video"
+ __printf_line "stop - Turn on lights and stop video"
+ __printf_line "pause - Turn on/off lights and stop/start video"
+ __printf_line "toggle - Same as pause"
+ __printf_line "state [json,txt] - Output state"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$AUTOMATE_REQUIRE_SUDO" = "yes" ] && [ -z "$AUTOMATE_REQUIRE_SUDO_RUN" ]; then
+ export AUTOMATE_REQUIRE_SUDO="no"
+ export AUTOMATE_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$AUTOMATE_TEMP_FILE" ] && rm -Rf "$AUTOMATE_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+roku_play() { roku play; }
+roku_stop() { roku stop; }
+roku_pause() { roku pause; }
+hue_play() { hue play; }
+hue_stop() { hue stop; }
+automate_play() { roku_play && hue_play && echo play >"$AUTOMATE_STATE_FILE" || return 1; }
+automate_stop() { roku_stop && hue_stop && echo stop >"$AUTOMATE_STATE_FILE" || return 1; }
+automate_pause() { roku pause && hue toggle && echo pause >"$AUTOMATE_STATE_FILE" || return 1; }
+getstate() { [[ -f "$AUTOMATE_STATE_FILE" ]] && cat "$AUTOMATE_STATE_FILE" || echo 'pause'; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+automate_toggle() {
+ if [ "$(getstate)" = play ]; then
+ automate_stop || exitCode=1
+ elif [ "$(getstate)" = stop ]; then
+ automate_play || exitCode=1
+ elif [ "$(getstate)" = pause ] || [ "$(getstate)" = "toggle" ]; then
+ automate_pause || exitCode=1
+ else
+ printf_exit "Can not get state from $AUTOMATE_STATE_FILE"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+AUTOMATE_CONFIG_FILE="${AUTOMATE_CONFIG_FILE:-settings.conf}"
+AUTOMATE_CONFIG_DIR="${AUTOMATE_CONFIG_DIR:-$HOME/.config/myscripts/automate}"
+AUTOMATE_CONFIG_BACKUP_DIR="${AUTOMATE_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/automate/backups}"
+AUTOMATE_LOG_DIR="${AUTOMATE_LOG_DIR:-$HOME/.local/log/automate}"
+AUTOMATE_TEMP_DIR="${AUTOMATE_TEMP_DIR:-$HOME/.local/tmp/system_scripts/automate}"
+AUTOMATE_CACHE_DIR="${AUTOMATE_CACHE_DIR:-$HOME/.cache/automate}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+AUTOMATE_OUTPUT_COLOR_1="${AUTOMATE_OUTPUT_COLOR_1:-33}"
+AUTOMATE_OUTPUT_COLOR_2="${AUTOMATE_OUTPUT_COLOR_2:-5}"
+AUTOMATE_OUTPUT_COLOR_GOOD="${AUTOMATE_OUTPUT_COLOR_GOOD:-2}"
+AUTOMATE_OUTPUT_COLOR_ERROR="${AUTOMATE_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+AUTOMATE_NOTIFY_ENABLED="${AUTOMATE_NOTIFY_ENABLED:-yes}"
+AUTOMATE_GOOD_NAME="${AUTOMATE_GOOD_NAME:-Great:}"
+AUTOMATE_ERROR_NAME="${AUTOMATE_ERROR_NAME:-Error:}"
+AUTOMATE_GOOD_MESSAGE="${AUTOMATE_GOOD_MESSAGE:-No errors reported}"
+AUTOMATE_ERROR_MESSAGE="${AUTOMATE_ERROR_MESSAGE:-Errors were reported}"
+AUTOMATE_NOTIFY_CLIENT_NAME="${AUTOMATE_NOTIFY_CLIENT_NAME:-$APPNAME}"
+AUTOMATE_NOTIFY_CLIENT_ICON="${AUTOMATE_NOTIFY_CLIENT_ICON:-notification-new}"
+AUTOMATE_NOTIFY_CLIENT_URGENCY="${AUTOMATE_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+AUTOMATE_STATE_FILE="${AUTOMATE_STATE_FILE:-$AUTOMATE_CACHE_DIR/state}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$AUTOMATE_CONFIG_DIR/$AUTOMATE_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$AUTOMATE_CONFIG_DIR/$AUTOMATE_CONFIG_FILE" ] && . "$AUTOMATE_CONFIG_DIR/$AUTOMATE_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$AUTOMATE_LOG_DIR" ] || mkdir -p "$AUTOMATE_LOG_DIR" |& __devnull
+[ -d "$AUTOMATE_TEMP_DIR" ] || mkdir -p "$AUTOMATE_TEMP_DIR" |& __devnull
+[ -d "$AUTOMATE_CACHE_DIR" ] || mkdir -p "$AUTOMATE_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+AUTOMATE_TEMP_FILE="${AUTOMATE_TEMP_FILE:-$(mktemp $AUTOMATE_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$AUTOMATE_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$AUTOMATE_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$AUTOMATE_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$AUTOMATE_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$AUTOMATE_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$AUTOMATE_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="play stop pause toggle state"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ AUTOMATE_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ AUTOMATE_CWD="$2"
+ [ -d "$AUTOMATE_CWD" ] || mkdir -p "$AUTOMATE_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# AUTOMATE_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# AUTOMATE_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && AUTOMATE_CWD="$1" && shift 1 || AUTOMATE_CWD="${AUTOMATE_CWD:-$PWD}"
+AUTOMATE_CWD="$(realpath "${AUTOMATE_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$AUTOMATE_CWD" ] && cd "$AUTOMATE_CWD"; then
+# if [ "$AUTOMATE_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $AUTOMATE_CWD"
+# fi
+# else
+# printf_exit "💔 $AUTOMATE_CWD does not exist 💔"
+# fi
+export AUTOMATE_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -s "$AUTOMATE_STATE_FILE" ] || echo "toggle" >"$AUTOMATE_STATE_FILE"
+[ -f "$HOME/.cache/automate" ] && mv -f "$HOME/.cache/automate" "$AUTOMATE_STATE_FILE" || touch "$AUTOMATE_STATE_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+play)
+ shift 1
+ state="play"
+ automate_play
+ ;;
+stop)
+ shift 1
+ state="stop"
+ automate_stop
+ ;;
+pause)
+ shift 1
+ state="pause"
+ automate_pause
+ ;;
+toggle)
+ shift 1
+ state="$(getstate)"
+ automate_toggle && echo "toggle" >"$AUTOMATE_STATE_FILE"
+ ;;
+state)
+ case "$2" in
+ text)
+ shift 2
+ printf '%s\n' "$(getstate)"
+ exit $?
+ ;;
+ json | *)
+ shift 2
+ printf '%s\n' '{"status":"'$(getstate)'"}'
+ exit $?
+ ;;
+ esac
+ ;;
+*)
+ automate_toggle
+ ;;
+esac
+[ -z "$state" ] || __notifications "$AUTOMATE_GOOD_MESSAGE" "$state"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/backupapp b/bin/backupapp
new file mode 100755
index 000000000..1e0dec3a1
--- /dev/null
+++ b/bin/backupapp
@@ -0,0 +1,970 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042048-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : backupapp --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 20:48 EDT
+# @@File : backupapp
+# @@Description : Backup files and folders
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042048-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+BACKUPAPP_REQUIRE_SUDO="${BACKUPAPP_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE"
+ fi
+ [ -d "$BACKUPAPP_CONFIG_DIR" ] || mkdir -p "$BACKUPAPP_CONFIG_DIR"
+ [ -d "$BACKUPAPP_CONFIG_BACKUP_DIR" ] || mkdir -p "$BACKUPAPP_CONFIG_BACKUP_DIR"
+ [ -f "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE" ] &&
+ cp -Rf "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE" "$BACKUPAPP_CONFIG_BACKUP_DIR/$BACKUPAPP_CONFIG_FILE.$$"
+ cat <"$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE"
+# Settings for backupapp
+BACKUPAPP_BACKUP_DIR="${BACKUPAPP_BACKUP_DIR:-}"
+BACKUPAPP_KEEP_AMOUNT="${BACKUPAPP_KEEP_AMOUNT:-}"
+BACKUPAPP_LOGFILE_EXTENSION="${BACKUPAPP_LOGFILE_EXTENSION:-}"
+BACKUPAPP_DATE_FORMAT="${BACKUPAPP_DATE_FORMAT:-}"
+BACKUPAPP_BICON_GOOD="${BACKUPAPP_BICON_GOOD:-}"
+BACKUPAPP_BICON_WARN="${BACKUPAPP_BICON_WARN:-}"
+BACKUPAPP_BICON_ERROR="${BACKUPAPP_BICON_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+BACKUPAPP_OUTPUT_COLOR_1="${BACKUPAPP_OUTPUT_COLOR_1:-}"
+BACKUPAPP_OUTPUT_COLOR_2="${BACKUPAPP_OUTPUT_COLOR_2:-}"
+BACKUPAPP_OUTPUT_COLOR_GOOD="${BACKUPAPP_OUTPUT_COLOR_GOOD:-}"
+BACKUPAPP_OUTPUT_COLOR_ERROR="${BACKUPAPP_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+BACKUPAPP_NOTIFY_ENABLED="${BACKUPAPP_NOTIFY_ENABLED:-}"
+BACKUPAPP_GOOD_NAME="${BACKUPAPP_GOOD_NAME:-}"
+BACKUPAPP_ERROR_NAME="${BACKUPAPP_ERROR_NAME:-}"
+BACKUPAPP_GOOD_MESSAGE="${BACKUPAPP_GOOD_MESSAGE:-}"
+BACKUPAPP_ERROR_MESSAGE="${BACKUPAPP_ERROR_MESSAGE:-}"
+BACKUPAPP_NOTIFY_CLIENT_NAME="${BACKUPAPP_NOTIFY_CLIENT_NAME:-}"
+BACKUPAPP_NOTIFY_CLIENT_ICON="${BACKUPAPP_NOTIFY_CLIENT_ICON:-}"
+BACKUPAPP_NOTIFY_CLIENT_URGENCY="${BACKUPAPP_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "backupapp: Backup files and folders - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: backupapp [options] [name] [directory]"
+ __printf_line "--term - Start in a new terminal"
+ __printf_line "[--]cron - options to run via cron"
+ __printf_line "[--]cron all - Back up all via cron"
+ __printf_line "[--]cron list - List current cron jobs"
+ __printf_line "[--]cron add - Add a new backup via cron"
+ __printf_line "[--]cron del - Delete a cron backup schedule"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$BACKUPAPP_REQUIRE_SUDO" = "yes" ] && [ -z "$BACKUPAPP_REQUIRE_SUDO_RUN" ]; then
+ export BACKUPAPP_REQUIRE_SUDO="no"
+ export BACKUPAPP_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$BACKUPAPP_TEMP_FILE" ] && rm -Rf "$BACKUPAPP_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__gen_backup_config() {
+ local _APPNAME="${1:-settings}"
+ local _APPDIRS="${_APPDIRS:-$HOME}"
+ local _CONFIG_NAME="${_APPNAME}.conf"
+ if [ "$INIT_CONFIG" = "TRUE" ]; then
+ local BACKUPAPP_CONFIG_FILE="$_CONFIG_NAME"
+ local NAME="${_APPNAME:-$BACKUPAPP_CONFIG_FILE%.*}"
+ else
+ local BACKUPAPP_CONFIG_FILE="${2:-$_CONFIG_NAME}"
+ local NAME="${_APPNAME:-$BACKUPAPP_CONFIG_FILE%.*}"
+ fi
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Generating the config file in"
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE"
+ [ -d "$BACKUPAPP_CONFIG_DIR" ] || mkdir -p "$BACKUPAPP_CONFIG_DIR"
+ [ -d "$BACKUPAPP_CONFIG_BACKUP_DIR" ] || mkdir -p "$BACKUPAPP_CONFIG_BACKUP_DIR"
+ if [ -f "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE" ]; then
+ cp -Rf "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE" "$BACKUPAPP_CONFIG_BACKUP_DIR/$BACKUPAPP_CONFIG_FILE.$$"
+ fi
+ local _APPDIRS="${_APPDIRS//~/$HOME}"
+ local BACKUPAPP_PROJECTDIRS="${BACKUPAPP_PROJECTDIRS//~/$HOME}"
+ [ "$_APPNAME" = "settings" ] && TITLE="default" || TITLE="$_APPNAME"
+ cat </dev/null
+# Settings for backupapp - $TITLE
+BACKUPAPP_CONFIGNAME="$NAME"
+BACKUPAPP_PROJECTNAME="$NAME"
+BACKUPAPP_PROJECTDIRS="${BACKUPAPP_PROJECTDIRS:-$_APPDIRS}"
+BACKUPAPP_CONFIG_FILE="$BACKUPAPP_CONFIG_FILE"
+BACKUPAPP_LOG_DIR="\$HOME/.local/log/backups/apps"
+BACKUPAPP_BACKUP_DIR="\$HOME/.local/backups/apps"
+BACKUPAPP_KEEP_AMOUNT="14"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification settings
+BACKUPAPP_GOOD_MESSAGE="${BACKUPAPP_GOOD_MESSAGE:-}"
+BACKUPAPP_ERROR_MESSAGE="${BACKUPAPP_ERROR_MESSAGE:-}"
+BACKUPAPP_NOTIFY_ENABLED="${BACKUPAPP_NOTIFY_ENABLED:-}"
+BACKUPAPP_NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$APPNAME}"
+BACKUPAPP_NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$BACKUPAPP_NOTIFY_CLIENT_ICON}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Colorization settings
+BACKUPAPP_OUTPUT_COLOR="${BACKUPAPP_OUTPUT_COLOR:-5}"
+BACKUPAPP_OUTPUT_COLOR_GOOD="${BACKUPAPP_OUTPUT_COLOR_GOOD:-2}"
+BACKUPAPP_OUTPUT_COLOR_ERROR="${BACKUPAPP_OUTPUT_COLOR_ERROR:-1}"
+
+EOF
+
+ if [ -f "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_name() {
+ _APPNAME="${1:-$_APPNAME}"
+ _APPNAME="${_APPNAME:-$BACKUPAPP_PROJECTNAME}"
+ _APPDIRS="${_APPDIRS:-$BACKUPAPP_PROJECTDIRS}"
+ _BACKUPDIR="${_BACKUPDIR:-$BACKUPAPP_BACKUP_DIR}"
+ _APPDIRS="${_APPDIRS//~/$HOME}"
+ printf_blue "Current saved projects in $BACKUPAPP_CONFIG_DIR"
+ find "$BACKUPAPP_CONFIG_DIR/" -type f,l | sed "s|$BACKUPAPP_CONFIG_DIR/||g" | grep -v 'settings.conf' | sed 's|.conf||g' | printf_column "6"
+ printf_read_input "2" "Enter backupname or existing project name: " "120" "_APPNAME" "-e "
+ if [ -f "$BACKUPAPP_CONFIG_DIR/$_APPNAME.conf" ]; then
+ . "$BACKUPAPP_CONFIG_DIR/$_APPNAME.conf"
+ fi
+ _APPNAME="${_APPNAME:-}"
+ BACKUPAPP_CONFIG_FILE="$_APPNAME.conf"
+ export _APPNAME _APPDIRS _BACKUPDIR BACKUPAPP_PROJECTNAME BACKUPAPP_BACKUP_DIR BACKUPAPP_CONFIG_FILE
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__save_config() {
+ BACKUPAPP_PROJECTNAME="${1:-$_APPNAME}"
+ BACKUPAPP_CONFIGNAME="${1:-$_APPNAME}"
+ BACKUPAPP_PROJECTDIRS="$(realpath "${2:-$_APPDIRS}")"
+ [ "$BACKUPAPP_NO_CONFIG" != "no" ] || return
+ if [ -f "$BACKUPAPP_CONFIG_DIR/${_APPNAME:-$BACKUPAPP_PROJECTNAME}.conf" ]; then
+ . "$BACKUPAPP_CONFIG_DIR/${_APPNAME:-$BACKUPAPP_PROJECTNAME}.conf"
+ printf_red "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_PROJECTNAME.conf already exists"
+ printf_read_question_nt "57" "Do you want to overwrite existing config" "1" "OVERWRITE"
+ printf_answer_yes "$OVERWRITE" || return
+ fi
+ _APPDIRS="${_APPDIRS//~/$HOME}"
+ BACKUPAPP_PROJECTDIRS="${BACKUPAPP_PROJECTDIRS//~/$HOME}"
+ if [ -z "$BACKUPAPP_AUTOMATE" ]; then
+ printf_read_input "2" "Enter project name: " "120" "_APPNAME" "-e -i ${BACKUPAPP_PROJECTNAME:-$_APPNAME} "
+ printf_read_input "2" "Enter directories:" "140" "_APPDIRS" "-e -i ${BACKUPAPP_PROJECTDIRS:-$HOME} "
+ printf_read_input "2" "Enter config Name: " "120" "_CONFIGNAME" "-e -i ${BACKUPAPP_CONFIGNAME:-$_APPNAME} "
+ fi
+ _APPDIRS="${_APPDIRS//~/$HOME}"
+ BACKUPAPP_PROJECTDIRS="${_APPDIRS//~/$HOME}"
+ BACKUPAPP_CONFIGNAME="$_CONFIGNAME"
+ BACKUPAPP_PROJECTNAME="$_APPNAME"
+ __gen_backup_config "$_APPNAME"
+ if [ -f "$BACKUPAPP_CONFIG_DIR/$_APPNAME.conf" ]; then
+ printf_blue "Your configuration for $_APPNAME has been created in"
+ printf_cyan "$BACKUPAPP_CONFIG_DIR/$_APPNAME.conf"
+ . "$BACKUPAPP_CONFIG_DIR/$_APPNAME.conf"
+ else
+ printf_error "Failed to save $BACKUPAPP_CONFIG_DIR/$_APPNAME.conf" 1>&2
+ fi
+ printf_pause "Press any key to continue"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__term() {
+ trap '$APPNAME --console' SIGINT
+ trap '' SIGQUIT SIGTSTP
+ local cont="" save="" main=""
+ _APPNAME="${_APPNAME:-}"
+ _APPDIRS="${_APPDIRS:-}"
+ clear
+ printf_newline '\n\n\n\n\n'
+ __get_name "$_APPNAME"
+ while :; do
+ clear
+ printf_newline "\n\n\n\n"
+ printf_head "Backup Menu for ${_APPNAME:-default}"
+ printf_custom "6" "Welcome to the backup menu: type quit to exit"
+ printf_green "c. import config"
+ printf_green "s. save config"
+ printf_green "e. Show config"
+ printf_green "b. Backup files"
+ printf_green "r. Restore files"
+ printf_green "z. Exit"
+ printf_read_question_nt "6" "Enter your choice [c,e,r,s,z] : " "1" "main"
+ clear
+ printf_newline "\n\n\n"
+
+ case $main in
+ c) __get_name "$_APPNAME" ;;
+ e)
+ if [ -f "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE" ]; then
+ printf_yellow "Showing $BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE"
+ printf_readline "6" <"$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE"
+ else
+ printf_red "No configuration was found. Try creating one"
+ fi
+ printf_pause
+ ;;
+ r) __restore ;;
+ s) __save_config "$_APPNAME" ;;
+ z)
+ shift 1
+ clear
+ break
+ ;;
+ *)
+ [ -n "$BACKUPAPP_PROJECTNAME" ] || printf_read_input "2" "Enter directories:" "140" "_APPDIRS" "-e -i $HOME/"
+ printf_newline
+ if [ -n "${_APPNAME:-$BACKUPAPP_PROJECTNAME}" ] && [ -n "${_APPDIRS:-$BACKUPAPP_PROJECTDIRS}" ]; then
+ __backup "${_APPNAME:-$BACKUPAPP_PROJECTNAME}" "${_APPDIRS:-$BACKUPAPP_PROJECTDIRS}" || printf_pause
+ else
+ [ -n "${_APPNAME:-$BACKUPAPP_PROJECTNAME}" ] || printf_pause "Needs an name"
+ [ -n "${_APPDIRS:-$BACKUPAPP_PROJECTDIRS}" ] || printf_pause "Needs a directory"
+ fi
+ printf_newline
+ if [ -z "$BACKUPAPP_PROJECTNAME" ]; then
+ printf_read_question_nt "6" "Should I save this for future use? [y/N]" "1" save
+ if printf_answer_yes "$save"; then
+ __save_config "$BACKUPAPP_PROJECTNAME"
+ fi
+ fi
+ printf_newline
+ if [ "$main" != "s" ]; then
+ printf_read_question_nt "6" "Would you like to keep this window open? [y/N]" "1" cont
+ printf_answer_yes "$cont" && continue || break
+ printf_counter "5" "3" "Re-loading menu in"
+ fi
+ ;;
+ esac
+ done
+ clear
+ printf_newline "\n\n"
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__restore() {
+ #__get_name
+ local restore=""
+ local _APPNAME="$BACKUPAPP_PROJECTNAME"
+ local _APPDIRS="$(realpath "$BACKUPAPP_PROJECTDIRS")"
+ local _BACKUPDIR="$BACKUPAPP_BACKUP_DIR"
+ local _APPDIRS="${_APPDIRS//~/$HOME}"
+ local logdir="${BACKUPAPP_LOG_DIR:-$HOME/.local/log/backups/apps}"
+ local datefmt="%Y-%m-%d-%H-%M_%S"
+ local curdate="$(date +"${BACKUPAPP_DATE_FORMAT:-$datefmt}")"
+ local logfilenameformat="${BACKUPAPP_LOGNAME_FORMAT:-$curdate}"
+ local logfilenameextension="${BACKUPAPP_LOGFILE_EXTENSION:-log}"
+ local logname="$appname-$logfilenameformat.restore.$logfilenameextension"
+ local latest_backup="$(__find "$_BACKUPDIR" "$_APPNAME*")"
+ local latest_backup_short="${latest_backup/$_BACKUPDIR\//}"
+ if [ -f "$latest_backup" ]; then
+ printf_read_question_nt "6" "Found $latest_backup_short should i restore that [y/N]" "1" "restore"
+ if printf_answer_yes "$restore"; then
+ if __restorecmd; then
+ printf_pause 2 "Restore of $latest_backup_short was successful"
+ else
+ printf_pause 1 "Failed to restore $latest_backup_short"
+ false
+ fi
+ else
+ printf_blue "Found the folowing files:"
+ __find "$_BACKUPDIR" "$_APPNAME*" "head -n100" | printf_readline "2"
+ printf_read_question_nt "6" "Would you like to restore one of those [y/N]" "1" "restore"
+ if printf_answer_yes "$restore"; then
+ printf_read_input "2" "Enter backupname:" "200" "latest_backup" "-e "
+ latest_backup_short="${latest_backup/$_BACKUPDIR\//}"
+ if __restorecmd; then
+ printf_pause 2 "Restore of $latest_backup_short was successful"
+ else
+ printf_pause 1 "Failed to restore $latest_backup_short"
+ false
+ fi
+ fi
+ fi
+ else
+ printf_pause "Couldn't find any backups in $_BACKUPDIR/$_APPNAME"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__backup() {
+ local e err appname appdir
+ local _APPNAME="${_APPNAME:-$BACKUPAPP_PROJECTNAME}"
+ local _APPDIRS="${_APPDIRS:-$BACKUPAPP_PROJECTDIRS}"
+ local appname="${1:-$_APPNAME}"
+ shift 1
+ local appdir="$(realpath "${*:-$_APPDIRS}")"
+ shift $#
+ local _APPDIRS="${_APPDIRS//~/$HOME}"
+ local logdir="${BACKUPAPP_LOG_DIR:-$HOME/.local/log/backups/apps}"
+ local datefmt="%Y-%m-%d-%H-%M_%S"
+ local curdate="$(date +"${BACKUPAPP_DATE_FORMAT:-$datefmt}")"
+ local filenameformate="${BACKUPAPP_FILENAME_FORMAT:-$curdate}"
+ local logfilenameformat="${BACKUPAPP_LOGNAME_FORMAT:-$curdate}"
+ local logfilenameextension="${BACKUPAPP_LOGFILE_EXTENSION:-log}"
+ local backupdir="${BACKUPAPP_BACKUP_DIR:-$HOME/.local/backups/apps}"
+ local notifyEnabled="${BACKUPAPP_NOTIFY_ENABLED:-yes}"
+ local leaveCount="${BACKUPAPP_KEEP_AMOUNT:-14}"
+ local icon_good="${BACKUPAPP_BICON_GOOD:-🆗}"
+ local icon_warn="${BACKUPAPP_BICON_WARN:-⚠️}"
+ local icon_error="${BACKUPAPP_BICON_ERROR:-✖}"
+ local filename="$appname-$filenameformate.tar.gz"
+ local logname="$appname-$logfilenameformat.$logfilenameextension"
+ local logname_err="$appname-$logfilenameformat.err"
+ [ "$notifyEnabled" = "yes" ] && __notifications "$icon_warn" "Initializing the backup of $appname"
+ __execute "sleep 3" "Initializing the backup of $appname"
+ __mkd "$backupdir" "$logdir"
+ for e in $appdir; do [ -e "$e" ] || err="$e"; done
+ if [ -n "$err" ]; then
+ [ "$notifyEnabled" = "yes" ] && __notifications "$icon_error" "Can't back up: $err doesn't exists"
+ printf_error "Can't back up: $err doesn't exists"
+ return 1
+ fi
+ shift
+ printf_header " # Started on $(date +'%A, %B %d, %Y %H:%M:%S')" "# Backing up $appdir" >>"$logdir/$logname"
+ if [ -t 0 ]; then
+ __execute "__backupcmd" "Backing up $appname to $backupdir"
+ exitCode=$?
+ else
+ __backupcmd
+ exitCode=$?
+ fi
+ printf_header " #Ended on $(date +'%A, %B %d, %Y %H:%M:%S')" >>"$logdir/$logname"
+ printf_newline "\n\n" >>"$logdir/$logname"
+ if [ "$exitCode" = 0 ]; then
+ printf_green "$icon_good The backup has completed successfully and Saved to:"
+ printf_green "$icon_good $backupdir/$filename"
+ [ "$notifyEnabled" = "yes" ] && __notifications "$icon_good" "Backup of $appname has completed"
+ else
+ printf_red "$icon_error The backup has failed to complete."
+ printf_red "$icon_error More information can be found in the log file:"
+ printf_exit "$icon_warn $logdir/$logname"
+ [ "$notifyEnabled" = "yes" ] && __notifications "$icon_error" "Backup of $appname has failed"
+ fi
+ logfileCount=$(ls $logdir/$appname*.$logfilenameextension 2>/dev/null | wc -l 2>/dev/null)
+ logremoveoldbackups=$(ls $logdir/$appname*.$logfilenameextension 2>/dev/null)
+ fileCount=$(ls $backupdir/$appname*.tar.gz 2>/dev/null | wc -l 2>/dev/null)
+ removeoldbackups=$(ls $backupdir/$appname*.tar.gz 2>/dev/null)
+ tailCount=$((fileCount - leaveCount))
+ if [ "$fileCount" -gt "$leaveCount" ] && [ $leaveCount -ne 0 ]; then
+ [ -z "$leaveCount" ] || ls -t $removeoldbackups | tail -$tailCount 2>/dev/null | xargs rm -f
+ [ -z "$leaveCount" ] || ls -t $logremoveoldbackups | tail -$tailCount 2>/dev/null | xargs rm -f
+ fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__find() {
+ find "${1:-$_BACKUPDIR}" -iname "${2:-_APPNAME}*" 2>/dev/null | ${3:-tail -n1} | grep '^' || false
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__restorecmd() {
+ tar xfvz $latest_backup -C $_APPDIRS >>"$logdir/$logname" 2>>"$logdir/$logname.err" || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__backupcmd() {
+ tar cfzv "$backupdir/$filename" $appdir >>"$logdir/$logname" 2>>"$logdir/$logname_err" || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__local_cron_add() {
+ __setupcrontab "${3:-0 0 * * *}" "backupapp --yes $1 $2 >/dev/null 2>&1"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__local_cron_del() {
+ __removecrontab "backupapp --yes $1 "
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+BACKUPAPP_CONFIG_FILE="${BACKUPAPP_CONFIG_FILE:-settings.conf}"
+BACKUPAPP_CONFIG_DIR="${BACKUPAPP_CONFIG_DIR:-$HOME/.config/myscripts/backupapp}"
+BACKUPAPP_CONFIG_BACKUP_DIR="${BACKUPAPP_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/backupapp/backups}"
+BACKUPAPP_LOG_DIR="${BACKUPAPP_LOG_DIR:-$HOME/.local/log/backupapp}"
+BACKUPAPP_TEMP_DIR="${BACKUPAPP_TEMP_DIR:-$HOME/.local/tmp/system_scripts/backupapp}"
+BACKUPAPP_CACHE_DIR="${BACKUPAPP_CACHE_DIR:-$HOME/.cache/backupapp}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+BACKUPAPP_OUTPUT_COLOR_1="${BACKUPAPP_OUTPUT_COLOR_1:-33}"
+BACKUPAPP_OUTPUT_COLOR_2="${BACKUPAPP_OUTPUT_COLOR_2:-5}"
+BACKUPAPP_OUTPUT_COLOR_GOOD="${BACKUPAPP_OUTPUT_COLOR_GOOD:-2}"
+BACKUPAPP_OUTPUT_COLOR_ERROR="${BACKUPAPP_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+BACKUPAPP_NOTIFY_ENABLED="${BACKUPAPP_NOTIFY_ENABLED:-yes}"
+BACKUPAPP_GOOD_NAME="${BACKUPAPP_GOOD_NAME:-Great:}"
+BACKUPAPP_ERROR_NAME="${BACKUPAPP_ERROR_NAME:-Error:}"
+BACKUPAPP_GOOD_MESSAGE="${BACKUPAPP_GOOD_MESSAGE:-No errors reported}"
+BACKUPAPP_ERROR_MESSAGE="${BACKUPAPP_ERROR_MESSAGE:-Errors were reported}"
+BACKUPAPP_NOTIFY_CLIENT_NAME="${BACKUPAPP_NOTIFY_CLIENT_NAME:-$APPNAME}"
+BACKUPAPP_NOTIFY_CLIENT_ICON="${BACKUPAPP_NOTIFY_CLIENT_ICON:-notification-new}"
+BACKUPAPP_NOTIFY_CLIENT_URGENCY="${BACKUPAPP_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+BACKUPAPP_BACKUP_DIR="${BACKUPAPP_BACKUP_DIR:-$HOME/.local/backups/apps}"
+BACKUPAPP_KEEP_AMOUNT="${BACKUPAPP_KEEP_AMOUNT:-14}"
+BACKUPAPP_LOGFILE_EXTENSION="${BACKUPAPP_LOGFILE_EXTENSION:-log}"
+BACKUPAPP_DATE_FORMAT="${BACKUPAPP_DATE_FORMAT:-%Y-%m-%d-%H-%M_%S}"
+BACKUPAPP_FILENAME_FORMAT="${BACKUPAPP_FILENAME_FORMAT:-$(date +"$DATEFORMAT")}"
+BACKUPAPP_LOGNAME_FORMAT="${BACKUPAPP_LOGNAME_FORMAT:-$(date +"$DATEFORMAT")}"
+BACKUPAPP_BICON_GOOD="${BACKUPAPP_BICON_GOOD:-🆗}"
+BACKUPAPP_BICON_WARN="${BACKUPAPP_BICON_WARN:-⚠️}"
+BACKUPAPP_BICON_ERROR="${BACKUPAPP_BICON_ERROR:-✖}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE" ] && . "$BACKUPAPP_CONFIG_DIR/$BACKUPAPP_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$BACKUPAPP_LOG_DIR" ] || mkdir -p "$BACKUPAPP_LOG_DIR" |& __devnull
+[ -d "$BACKUPAPP_TEMP_DIR" ] || mkdir -p "$BACKUPAPP_TEMP_DIR" |& __devnull
+[ -d "$BACKUPAPP_CACHE_DIR" ] || mkdir -p "$BACKUPAPP_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+BACKUPAPP_TEMP_FILE="${BACKUPAPP_TEMP_FILE:-$(mktemp $BACKUPAPP_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$BACKUPAPP_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$BACKUPAPP_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$BACKUPAPP_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$BACKUPAPP_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$BACKUPAPP_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$BACKUPAPP_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=",term,cron:,once,console"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="cron run new"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ BACKUPAPP_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ BACKUPAPP_CWD="$2"
+ [ -d "$BACKUPAPP_CWD" ] || mkdir -p "$BACKUPAPP_CWD" |& __devnull
+ shift 2
+ ;;
+ --term)
+ shift 1
+ TERMINAL_APP="TRUE"
+ ;;
+ --cron)
+ shift 1
+ CRON_OPTS="$1"
+ shift 1
+ ;;
+ --once)
+ shift 1
+ BACKUPAPP_NO_CONFIG="true"
+ ;;
+ --console)
+ shift 1
+ __term
+ exit $?
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# BACKUPAPP_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# BACKUPAPP_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && BACKUPAPP_CWD="$1" && shift 1 || BACKUPAPP_CWD="${BACKUPAPP_CWD:-$PWD}"
+BACKUPAPP_CWD="$(realpath "${BACKUPAPP_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$BACKUPAPP_CWD" ] && cd "$BACKUPAPP_CWD"; then
+# if [ "$BACKUPAPP_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $BACKUPAPP_CWD"
+# fi
+# else
+# printf_exit "💔 $BACKUPAPP_CWD does not exist 💔"
+# fi
+export BACKUPAPP_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+cron)
+ __mkd "$BACKUPAPP_CONFIG_DIR/cron"
+ #cron case 2
+ case "${2:-$CRON_OPTS}" in
+ all)
+ shift 1
+ if [ "$(__count_files "$BACKUPAPP_CONFIG_DIR/cron/")" -ne 0 ]; then
+ for cronjob in $(ls "$BACKUPAPP_CONFIG_DIR/cron/"); do
+ . "$BACKUPAPP_CONFIG_DIR/cron/$cronjob"
+ if [ -n "${_APPNAME:-$BACKUPAPP_PROJECTNAME}" ] && [ -n "${_APPNAME:-$BACKUPAPP_PROJECTNAME}" ]; then
+ echo "Backup up $cronjob"
+ __backup "${_APPNAME:-$BACKUPAPP_PROJECTNAME}" "${_APPDIRS:-$BACKUPAPP_PROJECTDIRS}" >/dev/null 2>&1
+ exitCode=$?
+ sleep 3
+ if [ "$exitCode" = 0 ]; then echo "Backup up of $cronjob has completed"; else echo "Backup up of $cronjob has failed"; fi
+ fi
+ unset _APPNAME _APPDIRS BACKUPAPP_PROJECTNAME BACKUPAPP_PROJECTDIRS
+ done
+ else
+ printf_exit 0 1 "No files were found"
+ fi
+ ;;
+ list)
+ shift 1
+ if crontab -l | grep -qF "backupapp "; then
+ printf_red "You don't have any jobs enabled"
+ else
+ printf_green "current cron jobs for backupapp"
+ crontab -l | grep -F "backupapp " | printf_readline "4"
+ fi
+ exit
+ ;;
+ add)
+ shift 1
+ if [ $# -gt 1 ]; then
+ __local_cron_add "$1" "$2" "$3"
+ #if [ "$(crontab -l | grep -q "$*" 2>/dev/null)" ]; then
+ printf_green "$1 $2 has been added to your cron jobs"
+ #else
+ # printf_red "failed to add $1 $2"
+ #fi
+ else
+ printf_custom "4" 'Usage: backupapp cron add "Backupname" "BackupDir" "Frequency" | default nightly at midnight'
+ printf_custom "4" 'Example: backupapp cron add "Documents" "$HOME/Documents" "0 0 * * *"'
+ fi
+ exit $?
+ ;;
+ del)
+ shift 1
+ if [ $# -lt 2 ]; then
+ __local_cron_del "$1" "$2"
+ #if [ "$(crontab -l | grep -qv "$*" 2>/dev/null)" ]; then
+ printf_green "$1 $2 has been removed from your cron jobs"
+ #else
+ # printf_red "failed to delete $1 $2"
+ #fi
+ else
+ printf_help 'Usage: backupapp cron del "Backupname" "BackupDir"'
+ fi
+ exit $?
+ ;;
+ *)
+ printf_custom "4" 'Usage: backupapp cron add "Backupname" "BackupDir"'
+ printf_custom "4" 'Usage: backupapp cron del "Backupname" "BackupDir"'
+ exit
+ ;;
+ esac
+ ;;
+ # end cron
+create)
+ args="$#"
+ [ -n "$1" ] && name="$1" && shift 1
+ [ "$args" -ne 0 ] && dirs="$*" && shift $#
+ [ "$args" -eq 2 ] || print_exit "Usage: $APPNAME create [name] [/path/to/dirs /path/to/files]"
+ [ ! -f "$BACKUPAPP_CONFIG_DIR/$1.conf" ] && [ -d "$2" ] && BACKUPAPP_AUTOMATE="true" __save_config "$name" "$dirs"
+ ;;
+*)
+ [ "$1" = "new" ] && shift 1
+ [ "$1" = "run" ] && shift 1
+ args="$#"
+ [ -n "$1" ] && name="$1" && shift 1
+ [ $# -ne 0 ] && dirs="$*" && shift $#
+ [ -n "$1" ] && BACKUPAPP_CONFIG_FILE="$BACKUPAPP_CONFIG_DIR/$1.conf" || BACKUPAPP_CONFIG_FILE=""
+ [ $# -eq 2 ] && [ ! -f "$BACKUPAPP_CONFIG_DIR/$1.conf" ] && [ -d "$2" ] && BACKUPAPP_AUTOMATE="true" __save_config "$name" "$dirs"
+ if [ -f "$BACKUPAPP_CONFIG_FILE" ] && [ "$#" -lt 2 ] && [ "$BACKUPAPP_CONFIG_FILE" != "$BACKUPAPP_DEFAULT_CONFIG_FILE" ]; then
+ [ "$YN" = "Y" ] || printf_read_question_nt "6" "I found a settings file for $BACKUPAPP_CONFIG_FILE: Should I use that?" "1" YN
+ if printf_answer_yes "$YN"; then
+ . "$BACKUPAPP_CONFIG_FILE"
+ if [ -n "${_APPNAME:-$BACKUPAPP_PROJECTNAME}" ] && [ -n "${_APPDIRS:-$BACKUPAPP_PROJECTDIRS}" ]; then
+ __backup "${_APPNAME:-$BACKUPAPP_PROJECTNAME}" "${_APPDIRS:-$BACKUPAPP_PROJECTDIRS}"
+ else
+ [ -n "${_APPNAME:-$BACKUPAPP_PROJECTNAME}" ] || printf_return 1 1 "Could get the settings for _APPNAME/PROJECTNAME"
+ [ -n "${_APPDIRS:-$BACKUPAPP_PROJECTNAME}" ] || printf_return 1 1 "Could get the settings for _APPDIRS/PROJECTDIRS"
+ exit $?
+ fi
+ elif [ "$args" -gt 1 ]; then
+ _APPNAME="$name"
+ _APPDIRS="$dirs"
+ __backup "${_APPNAME:-$BACKUPAPP_PROJECTNAME}" "${_APPDIRS:-$BACKUPAPP_PROJECTDIRS}"
+ else
+ __term
+ fi
+ elif [ "$args" -gt 1 ]; then
+ _APPNAME="$name"
+ _APPDIRS="$dirs"
+ __backup "${_APPNAME:-$BACKUPAPP_PROJECTNAME}" "${_APPDIRS:-$BACKUPAPP_PROJECTDIRS}"
+ else
+ __term
+ fi
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/bashtop b/bin/bashtop
new file mode 100755
index 000000000..b4b65e656
--- /dev/null
+++ b/bin/bashtop
@@ -0,0 +1,545 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042105-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : bashtop --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 21:05 EDT
+# @@File : bashtop
+# @@Description : System monitor written in bash
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042105-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+BASHTOP_REQUIRE_SUDO="${BASHTOP_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$BASHTOP_CONFIG_DIR/$BASHTOP_CONFIG_FILE"
+ fi
+ [ -d "$BASHTOP_CONFIG_DIR" ] || mkdir -p "$BASHTOP_CONFIG_DIR"
+ [ -d "$BASHTOP_CONFIG_BACKUP_DIR" ] || mkdir -p "$BASHTOP_CONFIG_BACKUP_DIR"
+ [ -f "$BASHTOP_CONFIG_DIR/$BASHTOP_CONFIG_FILE" ] &&
+ cp -Rf "$BASHTOP_CONFIG_DIR/$BASHTOP_CONFIG_FILE" "$BASHTOP_CONFIG_BACKUP_DIR/$BASHTOP_CONFIG_FILE.$$"
+ cat <"$BASHTOP_CONFIG_DIR/$BASHTOP_CONFIG_FILE"
+# Settings for bashtop
+BASHTOP_BIN_DIR="${BASHTOP_BIN_DIR:-}"
+BASHTOP_UPDATE_URL="${BASHTOP_UPDATE_URL:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+BASHTOP_OUTPUT_COLOR_1="${BASHTOP_OUTPUT_COLOR_1:-}"
+BASHTOP_OUTPUT_COLOR_2="${BASHTOP_OUTPUT_COLOR_2:-}"
+BASHTOP_OUTPUT_COLOR_GOOD="${BASHTOP_OUTPUT_COLOR_GOOD:-}"
+BASHTOP_OUTPUT_COLOR_ERROR="${BASHTOP_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+BASHTOP_NOTIFY_ENABLED="${BASHTOP_NOTIFY_ENABLED:-}"
+BASHTOP_GOOD_NAME="${BASHTOP_GOOD_NAME:-}"
+BASHTOP_ERROR_NAME="${BASHTOP_ERROR_NAME:-}"
+BASHTOP_GOOD_MESSAGE="${BASHTOP_GOOD_MESSAGE:-}"
+BASHTOP_ERROR_MESSAGE="${BASHTOP_ERROR_MESSAGE:-}"
+BASHTOP_NOTIFY_CLIENT_NAME="${BASHTOP_NOTIFY_CLIENT_NAME:-}"
+BASHTOP_NOTIFY_CLIENT_ICON="${BASHTOP_NOTIFY_CLIENT_ICON:-}"
+BASHTOP_NOTIFY_CLIENT_URGENCY="${BASHTOP_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$BASHTOP_CONFIG_DIR/$BASHTOP_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$BASHTOP_CONFIG_DIR/$BASHTOP_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "bashtop: System monitor written in bash - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: bashtop [options]"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$BASHTOP_REQUIRE_SUDO" = "yes" ] && [ -z "$BASHTOP_REQUIRE_SUDO_RUN" ]; then
+ export BASHTOP_REQUIRE_SUDO="no"
+ export BASHTOP_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$BASHTOP_TEMP_FILE" ] && rm -Rf "$BASHTOP_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__update() {
+ printf_cyan "Attempting to update bashtop"
+ [ -n "$BASHTOP_UPDATE_URL" ] && curl -q -LSsf "$BASHTOP_UPDATE_URL" -o "$BASHTOP_TEMP_FILE" ||
+ printf_exit "Failed to download"
+ if [ -f "$HOME/.local/bin/bashtop" ]; then
+ binFile="$HOME/.local/bin/bashtop"
+ mv -f "$BASHTOP_TEMP_FILE" "$binFile" &>/dev/null
+ elif [ -f "$BASHTOP_BIN_DIR/bashtop" ]; then
+ binFile="$BASHTOP_BIN_DIR/bashtop"
+ if ! mv -f "$BASHTOP_TEMP_FILE" "$binFile" &>/dev/null; then
+ sudo -n true
+ binFile="$CASJAYSDEVDIR/sources/bashtop"
+ sudo mv -f "$BASHTOP_TEMP_FILE" "$binFile" &>/dev/null
+ fi
+ fi
+ [ -f "$binFile" ] && chmod -Rf 755 "$binFile" && printf_green "$binFile has been updated" ||
+ { printf_red "Failed to update $binFile" && false || false; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_bashtop() {
+ if [ -f "$HOME/.local/bin/bashtop" ]; then
+ bash "$HOME/.local/bin/bashtop"
+ elif [ -f "$BASHTOP_BIN_DIR/bashtop" ]; then
+ bash "$BASHTOP_BIN_DIR/bashtop"
+ else
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+BASHTOP_CONFIG_FILE="${BASHTOP_CONFIG_FILE:-settings.conf}"
+BASHTOP_CONFIG_DIR="${BASHTOP_CONFIG_DIR:-$HOME/.config/myscripts/bashtop}"
+BASHTOP_CONFIG_BACKUP_DIR="${BASHTOP_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/bashtop/backups}"
+BASHTOP_LOG_DIR="${BASHTOP_LOG_DIR:-$HOME/.local/log/bashtop}"
+BASHTOP_TEMP_DIR="${BASHTOP_TEMP_DIR:-$HOME/.local/tmp/system_scripts/bashtop}"
+BASHTOP_CACHE_DIR="${BASHTOP_CACHE_DIR:-$HOME/.cache/bashtop}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+BASHTOP_OUTPUT_COLOR_1="${BASHTOP_OUTPUT_COLOR_1:-33}"
+BASHTOP_OUTPUT_COLOR_2="${BASHTOP_OUTPUT_COLOR_2:-5}"
+BASHTOP_OUTPUT_COLOR_GOOD="${BASHTOP_OUTPUT_COLOR_GOOD:-2}"
+BASHTOP_OUTPUT_COLOR_ERROR="${BASHTOP_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+BASHTOP_NOTIFY_ENABLED="${BASHTOP_NOTIFY_ENABLED:-yes}"
+BASHTOP_GOOD_NAME="${BASHTOP_GOOD_NAME:-Great:}"
+BASHTOP_ERROR_NAME="${BASHTOP_ERROR_NAME:-Error:}"
+BASHTOP_GOOD_MESSAGE="${BASHTOP_GOOD_MESSAGE:-No errors reported}"
+BASHTOP_ERROR_MESSAGE="${BASHTOP_ERROR_MESSAGE:-Errors were reported}"
+BASHTOP_NOTIFY_CLIENT_NAME="${BASHTOP_NOTIFY_CLIENT_NAME:-$APPNAME}"
+BASHTOP_NOTIFY_CLIENT_ICON="${BASHTOP_NOTIFY_CLIENT_ICON:-notification-new}"
+BASHTOP_NOTIFY_CLIENT_URGENCY="${BASHTOP_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+BASHTOP_BIN_DIR="${BASHTOP_BIN_DIR:-$CASJAYSDEVDIR/sources}"
+BASHTOP_UPDATE_URL="${BASHTOP_UPDATE_URL:-https://github.com/aristocratos/bashtop/raw/master/bashtop}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$BASHTOP_CONFIG_DIR/$BASHTOP_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$BASHTOP_CONFIG_DIR/$BASHTOP_CONFIG_FILE" ] && . "$BASHTOP_CONFIG_DIR/$BASHTOP_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$BASHTOP_LOG_DIR" ] || mkdir -p "$BASHTOP_LOG_DIR" |& __devnull
+[ -d "$BASHTOP_TEMP_DIR" ] || mkdir -p "$BASHTOP_TEMP_DIR" |& __devnull
+[ -d "$BASHTOP_CACHE_DIR" ] || mkdir -p "$BASHTOP_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+BASHTOP_TEMP_FILE="${BASHTOP_TEMP_FILE:-$(mktemp $BASHTOP_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$BASHTOP_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$BASHTOP_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$BASHTOP_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$BASHTOP_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$BASHTOP_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$BASHTOP_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=",update"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ BASHTOP_SILENT="true"
+ ;;
+ --update)
+ shift 1
+ __update
+ exit $?
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# BASHTOP_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# BASHTOP_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && BASHTOP_CWD="$1" && shift 1 || BASHTOP_CWD="${BASHTOP_CWD:-$PWD}"
+BASHTOP_CWD="$(realpath "${BASHTOP_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$BASHTOP_CWD" ] && cd "$BASHTOP_CWD"; then
+# if [ "$BASHTOP_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $BASHTOP_CWD"
+# fi
+# else
+# printf_exit "💔 $BASHTOP_CWD does not exist 💔"
+# fi
+export BASHTOP_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__execute_bashtop "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/blog b/bin/blog
new file mode 100755
index 000000000..cf6d1a333
--- /dev/null
+++ b/bin/blog
@@ -0,0 +1,898 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042114-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : blog --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 21:14 EDT
+# @@File : blog
+# @@Description : Blogging script using github pages
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042114-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+BLOG_REQUIRE_SUDO="${BLOG_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE"
+ fi
+ [ -d "$BLOG_CONFIG_DIR" ] || mkdir -p "$BLOG_CONFIG_DIR"
+ [ -d "$BLOG_CONFIG_BACKUP_DIR" ] || mkdir -p "$BLOG_CONFIG_BACKUP_DIR"
+ [ -f "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" ] &&
+ cp -Rf "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" "$BLOG_CONFIG_BACKUP_DIR/$BLOG_CONFIG_FILE.$$"
+ cat <"$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE"
+# Settings for blog
+BLOG_NAME="${BLOG_NAME:-}"
+BLOG_AUTHOR=${BLOG_AUTHOR:-}
+BLOG_AUTHOR_EMAIL=${BLOG_AUTHOR_EMAIL:-}
+BLOG_BASE_URL="${BLOG_BASE_URL:-}"
+BLOG_PAGE_BASE_URL="${BLOG_BASE_URL:-}"
+BLOG_POST_BASE_URL="${BLOG_POST_BASE_URL:-}"
+BLOG_DEFAULT_EXT="${BLOG_DEFAULT_EXT:-}"
+BLOG_GIT_ENABLED="${BLOG_GIT_ENABLED:-}"
+BLOG_DIR="${BLOG_DIR:-}"
+BLOG_TEMPLATE_DIR="${BLOG_TEMPLATE_DIR:-}"
+BLOG_EDITOR="${EDITOR:-}"
+BLOG_OPTIONS_VIM="${BLOG_OPTIONS_EDITOR:-}"
+BLOG_GITHUB_AUTH_TOKEN="${BLOG_GITHUB_AUTH_TOKEN:-}"
+BLOG_PAGE_COUNT="${BLOG_PAGE_COUNT:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+BLOG_OUTPUT_COLOR_1="${BLOG_OUTPUT_COLOR_1:-}"
+BLOG_OUTPUT_COLOR_2="${BLOG_OUTPUT_COLOR_2:-}"
+BLOG_OUTPUT_COLOR_GOOD="${BLOG_OUTPUT_COLOR_GOOD:-}"
+BLOG_OUTPUT_COLOR_ERROR="${BLOG_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+BLOG_NOTIFY_ENABLED="${BLOG_NOTIFY_ENABLED:-}"
+BLOG_GOOD_NAME="${BLOG_GOOD_NAME:-}"
+BLOG_ERROR_NAME="${BLOG_ERROR_NAME:-}"
+BLOG_GOOD_MESSAGE="${BLOG_GOOD_MESSAGE:-}"
+BLOG_ERROR_MESSAGE="${BLOG_ERROR_MESSAGE:-}"
+BLOG_NOTIFY_CLIENT_NAME="${BLOG_NOTIFY_CLIENT_NAME:-}"
+BLOG_NOTIFY_CLIENT_ICON="${BLOG_NOTIFY_CLIENT_ICON:-}"
+BLOG_NOTIFY_CLIENT_URGENCY="${BLOG_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "blog: Blogging script using github pages - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: blog [options] [commands]"
+ __printf_line "config - Generate config file for site"
+ __printf_line "copy - Copy templates files to config directory"
+ __printf_line "page - Create a new blog page"
+ __printf_line "post - Create a new blog post"
+ __printf_line "new - Create and edit new blog post"
+ __printf_line "edit [/path/to/file] - Edit an existing file"
+ __printf_line "-f,--file - Create a new file"
+ __printf_line "--dir - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$BLOG_REQUIRE_SUDO" = "yes" ] && [ -z "$BLOG_REQUIRE_SUDO_RUN" ]; then
+ export BLOG_REQUIRE_SUDO="no"
+ export BLOG_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$BLOG_TEMP_FILE" ] && rm -Rf "$BLOG_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__retrieve_variable() { awk -F'=' '{print $2}' | sed 's|"||g;s|^ ||g' | grep -v '^$' | grep '^' || echo "0"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__git_enabled() {
+ BLOG_GIT_ENABLED="${1:-$BLOG_GIT_ENABLED}"
+ if [ -f "${BLOG_CONFIG_DIR}/$BLOG_NAME.nogit" ] || [ "$BLOG_GIT_ENABLED" = "" ]; then
+ BLOG_GIT_ENABLED=""
+ return 1
+ else
+ BLOG_GIT_ENABLED="ENABLED"
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__replace() {
+ sed -i 's|'"$1"'|'"$2"'|g' "$3" 2>/dev/null
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__findcmd() {
+ find "${1:-$BLOG_CONFIG_DIR}" -type f ${1} -not -path "*/.git/*" 2>/dev/null |
+ __sed 's|'${1:-$BLOG_CONFIG_DIR}/'||g' | sort -u
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_count() {
+ count=0
+ if [ -f "$BLOG_CONFIG_DIR/$BLOG_NAME.cont" ]; then
+ count=$(grep -sh "BLOG_PAGE_COUNT" "$BLOG_CONFIG_DIR/$BLOG_NAME.cont" | __retrieve_variable)
+ elif [ -f "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" ]; then
+ count=$(grep -sh "BLOG_PAGE_COUNT" "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" | __retrieve_variable)
+ else
+ count=0
+ fi
+ [ $count -gt 0 ] && cont=$((count + 1)) || count=0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__git_message() {
+ shift 1
+ if [ "$BLOG_GIT_ENABLED" = "ENABLED" ]; then
+ if [ -f "$1" ]; then
+ message="🐜📓❇📓 Modified: ${file/$BLOG_DIR\//} 📓❇📓🐜"
+ else
+ message=" 🐜📓❇📓Added: ${file/$BLOG_DIR\//} 📓❇📓🐜"
+ fi
+ BLOG_COMMIT_MESSAGE="${message:-New blog post} ${args:-}"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__setup() {
+ local ARGS="$*"
+ local exitStatus=0
+ BLOG_NAME="$(basename -- "${BLOG_DIR}")"
+ if __blog_init "$BLOG_DIR"; then
+ if [ -f "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" ]; then
+ ln -sf "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" "$BLOG_CONFIG_DIR/$BLOG_NAME.conf"
+ else
+ printf_red "The file $BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE doesn't exist"
+ exitStatus=1
+ fi
+ else
+ exitStatus=1
+ fi
+ if [ $exitStatus = 0 ]; then
+ __mkd "$BLOG_DIR/_posts" "$BLOG_DIR/_pages"
+ __newpage_template "index" "Welcome to your new site"
+ $APPNAME $ARGS
+ exit $?
+ else
+ exitStatus=1
+ fi
+ return ${exitStatus:-$?}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__blog_init() {
+ local YesNo=""
+ local BLOG_URL=""
+ local BLOG_DIR="${1:-$BLOG_DIR}"
+ if [ -f "$BLOG_CONFIG_DIR/$BLOG_NAME.nogit" ] || [ "$BLOG_GIT_ENABLED" = "" ]; then
+ return 0
+ fi
+ printf_read_question "2" "Would you like to keep this in a git repo?" "1" "BLOG_GIT_ENABLED"
+ if printf_answer_yes "$BLOG_GIT_ENABLED"; then
+ BLOG_GIT_ENABLED="ENABLED"
+ printf_read_question "3" "Do you already have a blog repo you would like to import: [y/N] " "1" "YES"
+ if printf_answer_yes "$YES"; then
+ printf_read_input "3" "Enter the url: " "120" "BLOG_URL" "-e"
+ printf_blue "Cloning $BLOG_URL to"
+ printf_blue "$BLOG_DIR"
+ git clone "$BLOG_URL" "$BLOG_DIR" -q &>/dev/null || printf_exit "Failed to clone the repo"
+ else
+ __git_init "$BLOG_DIR"
+ fi
+ fi
+ if [ ! -d "$BLOG_DIR/.git" ]; then
+ printf '%s\n' "Git is disabled for $BLOG_NAME" >"$BLOG_CONFIG_DIR/$BLOG_NAME.nogit"
+ BLOG_GIT_ENABLED="no"
+ fi
+ if [ -f "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" ]; then
+ if [ -d "$BLOG_DIR" ] && [ -d "$BLOG_DIR/_posts" ] && [ -d "$BLOG_DIR/_pages" ]; then
+ printf_green "Your new blogging site has been setup"
+ else
+ printf_red "Not enabling git for $BLOG_DIR"
+ fi
+ export BLOG_INIT_SETUP="true"
+ fi
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__git_init() {
+ if [ ! -d "${BLOG_DIR}/.git" ] && [ "$BLOG_GIT_ENABLED" = "ENABLED" ]; then
+ if [ "$(__count_dir ${BLOG_DIR})" = 0 ]; then
+ __mkd "$BLOG_DIR/_posts" "$BLOG_DIR/_pages"
+ touch "${BLOG_DIR}/.gitignore"
+ git -C "${BLOG_DIR}" init &>/dev/null
+ git -C "${BLOG_DIR}" add . &>/dev/null
+ git -C "${BLOG_DIR}" commit -q -m " 🦈🏠🐜❗ Initial Commit ❗🐜🦈🏠 " 2>/dev/null
+ [ -d "${BLOG_DIR}/.git" ] || printf_exit "Failed to initialize the the blog"
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__blog_site() {
+ git -C "$BLOG_DIR" remote -v 2>/dev/null | grep push |
+ head -n 1 | awk '{print $2}' 2>/dev/null | grep '^'
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__blog_dir() {
+ if [ -d "$BLOG_DIR" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__blog_publish() {
+ local message="$1"
+ if [ "$BLOG_GIT_ENABLED" = "ENABLED" ]; then
+ __git_message "$message"
+ if git -C "${BLOG_DIR}" add . &&
+ git -C "${BLOG_DIR}" commit -q -m "${BLOG_COMMIT_MESSAGE:-$message}"; then
+ printf_blue "Your changes have been commited to git"
+ fi
+ else
+ printf_red "Git is disabled for blog: $BLOG_NAME"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__edit() {
+ # Possible completion fix
+ if [ -f "$1" ]; then
+ file="$1"
+ elif [ -f "$BLOG_DIR/$1" ]; then
+ file="$BLOG_DIR/$1"
+ elif [ -f "$HOME/.local/share/blogs/$1" ]; then
+ file="$HOME/.local/share/blogs/$1"
+ else file="$1"; fi
+ printf_yellow "Launching $BLOG_EDITOR $file"
+ eval ${BLOG_EDITOR:-$EDITOR} "$file"
+ printf_pause "Press any key when done"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__make_file() {
+ file="$1" && shift 1
+ title="${1:-$BLOG_NEW_FILE_TITLE}"
+ dir="$(dirname "${file/$BLOG_DIR/}" | __sed 's|^/||g;s|/$||g;s| |_|g')"
+ date="$(date +"$BLOG_DATE_FORMAT")"
+ if [ "$MAKE_DATE" = "no" ] || [[ "$dir" = _pages/** ]]; then
+ newtitle="$(basename -- "${title:-$file}")"
+ newedit="$(echo "$newtitle" | __sed 's| |_|g')"
+ newfilename="$newedit.$BLOG_DEFAULT_EXT"
+ else
+ newtitle="$(basename -- "${title:-$file}")"
+ newedit="$(echo "$date-$newtitle" | __sed 's| |_|g')"
+ newfilename="$newedit.$BLOG_DEFAULT_EXT"
+ fi
+ export dir="$dir"
+ export title="$newtitle"
+ export rawfile="$dir/$newedit"
+ export linkurl="${newtitle// /-}"
+ export edit="$newfilename"
+ export file="$BLOG_DIR/$dir/$edit"
+ [ -d "$BLOG_DIR/$dir" ] || __mkd "$BLOG_DIR/$dir"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__blog_post_header() {
+ local url=$(echo "${rawfile//$BLOG_DIR/}" | sed 's|_posts||g;s|_pages||g')
+ local index="$(basename $rawfile)"
+ local get_title="${title:-$BLOG_NEW_FILE_TITLE}"
+ if [ "$index" = index ]; then
+ linkurl="$(dirname $url)/"
+ else
+ linkurl="$(dirname $url).html"
+ fi
+ cat "$BLOG_TEMPLATE_DIR/blog/post.$BLOG_DEFAULT_EXT" |
+ __sed "s|AuthorName|$BLOG_AUTHOR|g" |
+ __sed "s|DATE|$(date +"$BLOG_DATE_FORMAT $BLOG_TIME_FORMAT")|g" |
+ __sed "s|TITLE|$get_title|g" |
+ __sed "s|/myurl|$BLOG_POST_BASE_URL/$url|g" | sed 's|//|/|'
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__blog_page_header() {
+ local url=$(echo "${rawfile//$BLOG_DIR/}" | sed 's|_posts||g;s|_pages||g')
+ local get_title="${title:-$BLOG_NEW_FILE_TITLE}"
+ local index="$(basename $rawfile)"
+ if [ "$index" = index ]; then
+ linkurl="$(dirname $url)/"
+ else
+ linkurl="$(dirname $url).html"
+ fi
+ cat "$BLOG_TEMPLATE_DIR/blog/page.$BLOG_DEFAULT_EXT" |
+ __sed "s|AuthorName|$BLOG_AUTHOR|g" |
+ __sed "s|DATE|$(date +"$BLOG_DATE_FORMAT $BLOG_TIME_FORMAT")|g" |
+ __sed "s|TITLE|$get_title|g" |
+ __sed "s|/myurl|$BLOG_PAGE_BASE_URL/$linkurl|g" |
+ __sed "s|weight:.*|weight: $count|g" |
+ __sed "s|BLOG_PAGE_COUNT=.*|BLOG_PAGE_COUNT=$count|g" |
+ __sed "s|/myurl|$BLOG_POST_BASE_URL/$url|g" | sed 's|//|/|'
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__newpost_template() {
+ if __blog_dir; then
+ __make_file "_posts/$1"
+ __blog_post_header >"$file"
+ __edit "$file"
+ __blog_publish "$file"
+ else
+ printf_red "There is no blog directory"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__newpage_template() {
+ MAKE_DATE="no"
+ __make_file "_pages/$1"
+ BLOG_NEW_FILE_TITLE="$2"
+ __get_count
+ if [ ! -f "$file" ]; then
+ __blog_page_header >"$file"
+ fi
+ sed -i 's|permalink: //|permalink: /|g' "$file"
+ __edit "$file"
+ __blog_publish
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__copy_templates() {
+ if [ -d "$BLOG_CONFIG_DIR/files/.git" ]; then
+ printf_green "Updating the template files"
+ git -C "$BLOG_CONFIG_DIR/files" pull -q
+ elif [ -d "${CASJAYSDEVDIR}/templates/blog" ]; then
+ printf_green "Copying $APPNAME templates $CASJAYSDEVDIR/templates/blog"
+ mkdir -p "$BLOG_CONFIG_DIR/files $CASJAYSDEVDIR/templates/blog"
+ __cp_rf "$CASJAYSDEVDIR/templates/blog/." "$BLOG_CONFIG_DIR/files/"
+ else
+ printf_error "Can not get template files"
+ exit 1
+ fi
+ if [ "$(__count_files $BLOG_CONFIG_DIR/files)" -ne 0 ]; then
+ printf_green "Copying has succeeded > $BLOG_CONFIG_DIR/files"
+ exitCodeT=0
+ else
+ printf_error "Copying of files has failed < $BLOG_CONFIG_DIR/files"
+ exitCodeT=1
+ fi
+ echo ""
+ return $exitCodeT
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+BLOG_CONFIG_FILE="${BLOG_CONFIG_FILE:-settings.conf}"
+BLOG_CONFIG_DIR="${BLOG_CONFIG_DIR:-$HOME/.config/myscripts/blog}"
+BLOG_CONFIG_BACKUP_DIR="${BLOG_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/blog/backups}"
+BLOG_LOG_DIR="${BLOG_LOG_DIR:-$HOME/.local/log/blog}"
+BLOG_TEMP_DIR="${BLOG_TEMP_DIR:-$HOME/.local/tmp/system_scripts/blog}"
+BLOG_CACHE_DIR="${BLOG_CACHE_DIR:-$HOME/.cache/blog}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+BLOG_OUTPUT_COLOR_1="${BLOG_OUTPUT_COLOR_1:-33}"
+BLOG_OUTPUT_COLOR_2="${BLOG_OUTPUT_COLOR_2:-5}"
+BLOG_OUTPUT_COLOR_GOOD="${BLOG_OUTPUT_COLOR_GOOD:-2}"
+BLOG_OUTPUT_COLOR_ERROR="${BLOG_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+BLOG_NOTIFY_ENABLED="${BLOG_NOTIFY_ENABLED:-yes}"
+BLOG_GOOD_NAME="${BLOG_GOOD_NAME:-Great:}"
+BLOG_ERROR_NAME="${BLOG_ERROR_NAME:-Error:}"
+BLOG_GOOD_MESSAGE="${BLOG_GOOD_MESSAGE:-No errors reported}"
+BLOG_ERROR_MESSAGE="${BLOG_ERROR_MESSAGE:-Errors were reported}"
+BLOG_NOTIFY_CLIENT_NAME="${BLOG_NOTIFY_CLIENT_NAME:-$APPNAME}"
+BLOG_NOTIFY_CLIENT_ICON="${BLOG_NOTIFY_CLIENT_ICON:-notification-new}"
+BLOG_NOTIFY_CLIENT_URGENCY="${BLOG_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+BLOG_EDITOR="${EDITOR:-myeditor}"
+BLOG_NAME="${BLOG_NAME:-default}"
+BLOG_AUTHOR=${BLOG_AUTHOR:-$USER}
+BLOG_AUTHOR_EMAIL=${BLOG_AUTHOR_EMAIL:-$USER@$(hostname -f)}
+BLOG_BASE_URL="${BLOG_BASE_URL:-}"
+BLOG_PAGE_BASE_URL="${BLOG_BASE_URL:-}"
+BLOG_POST_BASE_URL="${BLOG_POST_BASE_URL:-$BLOG_BASE_URL/blog}"
+BLOG_DEFAULT_EXT="${BLOG_DEFAULT_EXT:-md}"
+BLOG_GIT_ENABLED="${BLOG_GIT_ENABLED:-yes}"
+BLOG_DIR="${BLOG_DIR:-$HOME/.local/share/blogs/$BLOG_NAME}"
+BLOG_TEMPLATE_DIR="${BLOG_TEMPLATE_DIR:-$CASJAYSDEVDIR/templates}"
+BLOG_OPTIONS_VIM="${BLOG_OPTIONS_EDITOR:-"vim -c ':setlocal ft=notes syntax=markdown'"}"
+BLOG_GITHUB_AUTH_TOKEN="${BLOG_GITHUB_AUTH_TOKEN:-$GITHUB_ACCESS_TOKEN}"
+BLOG_PAGE_COUNT=0
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" ] && . "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$BLOG_LOG_DIR" ] || mkdir -p "$BLOG_LOG_DIR" |& __devnull
+[ -d "$BLOG_TEMP_DIR" ] || mkdir -p "$BLOG_TEMP_DIR" |& __devnull
+[ -d "$BLOG_CACHE_DIR" ] || mkdir -p "$BLOG_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+BLOG_TEMP_FILE="${BLOG_TEMP_FILE:-$(mktemp $BLOG_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$BLOG_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$BLOG_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$BLOG_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$BLOG_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$BLOG_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$BLOG_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS="f"
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=",file:"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="config copy edit page post new"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ BLOG_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ BLOG_CWD="$2"
+ [ -d "$BLOG_CWD" ] || mkdir -p "$BLOG_CWD" |& __devnull
+ shift 2
+ ;;
+ -f | --file)
+ shift 1
+ OLD_BLOG_CONFIG_FILE="$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE"
+ BLOG_CONFIG_FILE="$BLOG_CONFIG_DIR/$1"
+ BLOG_NAME="$(basename -- "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE")"
+ shift 1
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# BLOG_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# BLOG_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && BLOG_CWD="$1" && shift 1 || BLOG_CWD="${BLOG_CWD:-$PWD}"
+BLOG_CWD="$(realpath "${BLOG_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$BLOG_CWD" ] && cd "$BLOG_CWD"; then
+# if [ "$BLOG_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $BLOG_CWD"
+# fi
+# else
+# printf_exit "💔 $BLOG_CWD does not exist 💔"
+# fi
+export BLOG_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+[ -n "$BLOG_DIR" ] || printf_exit 1 1 "Failed to load $BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE"
+[ -f "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" ] && . "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE"
+[ -d "$BLOG_DIR" ] || __setup "$*"
+__git_enabled "$BLOG_GIT_ENABLED"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+config)
+ shift 1
+ BLOG_DIR="${1:-$BLOG_DIR}"
+ BLOG_NAME="$(basename -- "${BLOG_DIR}")"
+ BLOG_CONFIG_NEW=""$BLOG_NAME.conf""
+ if [ "$BLOG_CONFIG_FILE" != "default.conf" ] || [ "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" != "$BLOG_CONFIG_DIR/$BLOG_CONFIG_FILE" ]; then
+ printf_read_input "4" "Where would you like to store your blog files" "120" "BLOG_DIR" "-e -i $HOME/.local/share/blogs/$BLOG_NAME"
+ fi
+ __blog_init "$BLOG_DIR"
+ __gen_config
+ exit $?
+ ;;
+
+copy)
+ shift 1
+ __copy_templates
+ exit $?
+ ;;
+
+edit)
+ shift 1
+ [ -z "${1}" ] && printf_red "Usage: $APPNAME edit 'filename'" && exit 1
+ __edit "$1"
+ __blog_publish "$file"
+ exit $?
+ ;;
+
+page)
+ shift 1
+ [ -z "${1}" ] && printf_red "Usage: $APPNAME page 'filename' 'title'" && exit 1
+ __newpage_template "${1:-index}" "${2:-Welcome to your new site}"
+ exit $?
+ ;;
+
+post)
+ shift 1
+ [ -z "${1}" ] && printf_red "Usage: $APPNAME post subdir/filename" && exit 1
+ __newpost_template "$1"
+ exit $?
+ ;;
+
+new)
+ shift 1
+ [ -z "${1}" ] && printf_red "Usage: $APPNAME new filename title" && exit 1
+ BLOG_NEW_FILE_TITLE="${2:-New file}"
+ __make_file "$1"
+ if [ "$dir" = "$BLOG_DIR" ] || [ "$dir" = "." ]; then
+ file="$BLOG_DIR/_posts/$edit"
+ [ -d "$BLOG_DIR/_posts" ] || __mkd "$BLOG_DIR/_posts"
+ else
+ file="${file:?}"
+ [ -d "$dir" ] || __mkd "$dir"
+ fi
+ __blog_post_header >"$file"
+ __edit "$file"
+ __blog_publish "$file"
+ exit $?
+ ;;
+
+*)
+ [ -n "${1}" ] || printf_exit "Usage: $APPNAME filename title"
+ BLOG_NEW_FILE_TITLE="${2:-New file}"
+ __make_file "$1"
+ if [ "$dir" = "$BLOG_DIR" ] || [ "$dir" = "." ]; then
+ file="$BLOG_DIR/_posts/$edit"
+ [ -d "$BLOG_DIR/_posts" ] || __mkd "$BLOG_DIR/_posts"
+ else
+ file="${file:?}"
+ [ -d "$dir" ] || __mkd "$dir"
+ fi
+ __blog_post_header >"$file"
+ __edit "$file"
+ __blog_publish "$file"
+ exit $?
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/buildx b/bin/buildx
new file mode 100755
index 000000000..fd4eae0b6
--- /dev/null
+++ b/bin/buildx
@@ -0,0 +1,2017 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042122-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : buildx --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 21:22 EDT
+# @@File : buildx
+# @@Description : Docker buildx wrapper
+# @@Changelog : Replacing variables with functions
+# @@TODO : Refactor code: clean up arguments and variables
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shell check options
+# shellcheck disable=SC2016
+# shellcheck disable=SC2031
+# shellcheck disable=SC2120
+# shellcheck disable=SC2155
+# shellcheck disable=SC2199
+# shellcheck disable=SC2317
+# shellcheck disable=SC2001
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename "$0" 2>/dev/null)"
+VERSION="202208042122-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+BUILDX_REQUIRE_SUDO="${BUILDX_REQUIRE_SUDO:-no}"
+export BUILDX_START_TIMER="${BUILDX_START_TIMER:-$(date +%s.%N)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+[ -z "$CASJAYSDEV_TITLE_SET" ] && echo -ne '\033]2;'${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME'\007' && export CASJAYSDEV_TITLE_SET="$APPNAME"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$BUILDX_CONFIG_DIR/$BUILDX_CONFIG_FILE"
+ fi
+ [ -d "$BUILDX_CONFIG_DIR" ] || mkdir -p "$BUILDX_CONFIG_DIR"
+ [ -d "$BUILDX_CONFIG_BACKUP_DIR" ] || mkdir -p "$BUILDX_CONFIG_BACKUP_DIR"
+ [ -f "$BUILDX_CONFIG_DIR/$BUILDX_CONFIG_FILE" ] &&
+ cp -Rf "$BUILDX_CONFIG_DIR/$BUILDX_CONFIG_FILE" "$BUILDX_CONFIG_BACKUP_DIR/$BUILDX_CONFIG_FILE.$$"
+ cat <"$BUILDX_CONFIG_DIR/$BUILDX_CONFIG_FILE"
+# Settings for buildx
+BUILDX_ADD_REPO="${BUILDX_ADD_REPO:-}"
+BUILDX_ADD_REGISTRY="${BUILDX_ADD_REGISTRY:-}"
+BUILDX_DOCKER_CMD="${BUILDX_DOCKER_CMD:-}"
+BUILDX_BUILDER_NAME="${BUILDX_BUILDER_NAME:-}"
+BUILDX_DEFAULT_REPO="${BUILDX_DEFAULT_REPO:-}"
+BUILDX_DEFAULT_REGISTRY="${BUILDX_DEFAULT_REGISTRY:-}"
+BUILDX_DEFAULT_VERSION="${BUILDX_DEFAULT_VERSION:-}"
+BUILDX_REMOVE_BUILD="${BUILDX_REMOVE_BUILD:-}"
+BUILDX_GIT_REPO_USER="${BUILDX_GIT_REPO_USER:-}"
+BUILDX_GIT_REPO_PROVIDER="${BUILDX_GIT_REPO_PROVIDER:-}"
+BUILDX_DOCKER_PLATFORMS="${BUILDX_DOCKER_PLATFORMS:-}"
+BUILDX_PROJECT_DIR="${BUILDX_PROJECT_DIR:-}"
+BUILDX_BUILD_DATE_TAG_FORMAT="${BUILDX_BUILD_DATE_TAG_FORMAT:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+BUILDX_OUTPUT_COLOR_1="${BUILDX_OUTPUT_COLOR_1:-}"
+BUILDX_OUTPUT_COLOR_2="${BUILDX_OUTPUT_COLOR_2:-}"
+BUILDX_OUTPUT_COLOR_GOOD="${BUILDX_OUTPUT_COLOR_GOOD:-}"
+BUILDX_OUTPUT_COLOR_ERROR="${BUILDX_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+BUILDX_NOTIFY_ENABLED="${BUILDX_NOTIFY_ENABLED:-}"
+BUILDX_GOOD_NAME="${BUILDX_GOOD_NAME:-}"
+BUILDX_ERROR_NAME="${BUILDX_ERROR_NAME:-}"
+BUILDX_GOOD_MESSAGE="${BUILDX_GOOD_MESSAGE:-}"
+BUILDX_ERROR_MESSAGE="${BUILDX_ERROR_MESSAGE:-}"
+BUILDX_NOTIFY_CLIENT_NAME="${BUILDX_NOTIFY_CLIENT_NAME:-}"
+BUILDX_NOTIFY_CLIENT_ICON="${BUILDX_NOTIFY_CLIENT_ICON:-}"
+BUILDX_NOTIFY_CLIENT_URGENCY="${BUILDX_NOTIFY_CLIENT_URGENCY:-}"
+BUILDX_REMOTE_NOTIFY_ENABLED="${BUILDX_REMOTE_NOTIFY_ENABLED:-yes}"
+BUILDX_REMOTE_NOTIFY_COMMAND="${BUILDX_REMOTE_NOTIFY_COMMAND:-web-notify telegram}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$BUILDX_CONFIG_DIR/$BUILDX_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$BUILDX_CONFIG_DIR/$BUILDX_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "buildx: Docker buildx wrapper - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: buildx [options] [commands]"
+ __printf_line "init - Setup docker to use buildx"
+ __printf_line "status - Get Status info"
+ __printf_line "version - Get version info"
+ __printf_line "api - API functions"
+ __printf_line "api list - List all available images"
+ __printf_line "api search [query] - Search for an image"
+ __printf_line "api sources [query] - Lookup sources used to build image"
+ __printf_line "api clone [repo] - Clone the source repository"
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ # __printf_line " - "
+ __printf_line "--dir - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$BUILDX_REQUIRE_SUDO" = "yes" ] && [ -z "$BUILDX_REQUIRE_SUDO_RUN" ]; then
+ export BUILDX_REQUIRE_SUDO="no"
+ export BUILDX_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ local exitCode=$?
+ [ -f "$BUILDX_TEMP_FILE" ] && rm -Rf "$BUILDX_TEMP_FILE" &>/dev/null
+ unset CASJAYSDEV_TITLE_SET && echo -ne '\033]2;'${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}'\007'
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__trap_exit_local() {
+ exitCode=$?
+ [ "$_DEBUG" != "on" ] || { [ -n "$exitCode" ] && echo $exitCode; }
+ __buildx_cleanup && exitCode=0
+ __remove_pid
+ [ -f "$BUILDX_FAILED_LOG" ] && [ "$exitCode" -ne 0 ] || exitCode=0
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_timer() {
+ local retval=$?
+ __cmd_exists bc || return $retval
+ local stop_timer="$(date +%s.%N)"
+ local dt=$(echo "$stop_timer - $BUILDX_START_TIMER" | bc)
+ local dd=$(echo "$dt/86400" | bc)
+ local dt2=$(echo "$dt-86400*$dd" | bc)
+ local dh=$(echo "$dt2/3600" | bc)
+ local dt3=$(echo "$dt2-3600*$dh" | bc)
+ local dm=$(echo "$dt3/60" | bc)
+ local ds=$(echo "$dt3-60*$dm" | bc)
+ printf_purple "$(LC_NUMERIC=C printf "Total runtime: %d Days, %02d Hours, %02d Minutes, %02.4f Seconds\n" $dd $dh $dm $ds)"
+ return $retval
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__grep_exclude_version() { grep -v 'USE_DATE'; }
+__get_version() { awk -F '=' '{print $2}' | sed 's|"||g;s|,| |g' | tr ' ' '\n' | grep -Ev '\${.*_.*}' | grep -v '^$' | sort -Vu | tr '\n' ' ' | grep '^' || false; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__set_variables() {
+ export DOCKER_BUILDKIT=1
+ export BUILDX_PID_NUMBER="$$"
+ export name="$(basename "$BUILDX_CWD")"
+ export org_name="$(basename $(dirname "$BUILDX_CWD"))"
+ export DOCKER_PLATFORMS="$BUILDX_DOCKER_PLATFORMS"
+ export BUILDX_EXPERIMENTAL="$BUILDX_DOCKER_BUILD_EXPERIMENTAL"
+ export DOCKER_CLI_EXPERIMENTAL="$BUILDX_DOCKER_CLI_EXPERIMENTAL"
+ BUILDX_SET_REPO="${ENV_ORG_NAME:-$BUILDX_SET_REPO}"
+ BUILDX_SET_IMAGE="${ENV_IMAGE_PUSH:-$BUILDX_SET_IMAGE}"
+ BUILDX_VERSION_TAG="${ENV_ADD_TAGS:-$BUILDX_VERSION_TAG}"
+ BUILDX_DOCKER_PLATFORMS="${BUILDX_DOCKER_PLATFORMS// /,}"
+ BUILDX_DEFAULT_REPO="${BUILDX_SET_REPO:-$(basename "$BUILDX_CWD")}"
+ BUILDX_DEFAULT_REGISTRY="${BUILDX_SET_REGISTRY:-$BUILDX_DEFAULT_REGISTRY}"
+ BUILDX_GIT_REPO_USER="${BUILDX_SET_GIT_USER:-$BUILDX_GIT_REPO_USER}"
+ BUILDX_PROJECT_DIR="${BUILDX_PROJECT_DIR:-$HOME/Projects/github/$BUILDX_DEFAULT_REPO}"
+ BUILDX_DEFAULT_VERSION="$(echo "${BUILDX_SET_VERSION:-$BUILDX_DEFAULT_VERSION}" | awk -F ' ' '{print $1}' | sed 's|"||g')"
+ [ -n "$BUILDX_VERSION_TAG" ] && export BUILDX_ADD_TAG="true"
+ [ -n "$BUILDX_SET_REPO" ] && export BUILDX_SET_REPO
+ [ -n "$BUILDX_SET_IMAGE" ] && export BUILDX_SET_IMAGE
+ [ -n "$BUILDX_SET_VERSION" ] && export BUILDX_SET_VERSION
+ [ -n "$BUILDX_SET_REGISTRY" ] && export BUILDX_SET_REGISTRY
+ [ -n "$BUILDX_SET_GIT_USER" ] && export BUILDX_SET_GIT_USER
+ [ -n "$ENV_IMAGE_TAG" ] && export BUILDX_SET_VERSION="$(basename "${ENV_IMAGE_TAG//*:/}")"
+ BUILDX_SET_DEFAULT_VER="${BUILDX_SET_DEFAULT_VER:-$BUILDX_SET_VERSION}"
+ export BUILDX_CUSTOM_LOG_DIR="$BUILDX_LOG_DIR/$BUILDX_DEFAULT_REGISTRY/$BUILDX_DEFAULT_LOG_ORG/$BUILDX_DEFAULT_LOG_REPO"
+ export BUILDX_CUSTOM_LOG_FILE="$BUILDX_CUSTOM_LOG_DIR/${BUILDX_SET_DEFAULT_VER:-$name}.log"
+ export BUILDX_PID_FILE="$HOME/.local/run/$APPNAME/${BUILDX_BUILDER_NAME_CUSTOM:-$BUILDX_BUILDER_NAME}.pid"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_log_files() {
+ return
+ local directory="" file=""
+ local dir_name="" file_name=""
+ local project_dir="${ENV_BUILDX_PROJECT_DIR:-$BUILDX_PROJECT_DIR}"
+ for directory in $project_dir; do
+ dir_name="$(basename $directory)"
+ file_name="$(basename "$dir_name").log"
+ if [ -n "$directory" ] && [ ! -d "$BUILDX_LOG_DIR/$dir_name" ]; then
+ mkdir -p "$BUILDX_LOG_DIR/$dir_name"
+ fi
+ for dir in $directory/*; do
+ [ -n "$dir" ] && [ -d "$dir" ] && touch "$BUILDX_LOG_DIR/$dir_name/$file_name"
+ done
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_update_docker_daemon_config() {
+ if __can_i_sudo; then
+ __sudo true
+ sudo mkdir -p "/etc/docker"
+ if [ ! -f "/etc/docker/daemon.json" ]; then
+ printf '{\n %s\n}' "\"experimental\": true" | sudo tee -p -a "/etc/docker/daemon.json" &>/dev/null
+ elif grep -shq "experimental" "/etc/docker/daemon.json"; then
+ sudo sed -i 's|experimental.*e|experimental": true|g' "/etc/docker/daemon.json"
+ else
+ echo "{\"experimental\": true}," | sudo tee -p -a "/etc/docker/daemon.json" &>/dev/null
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__last_build_check() {
+ local errlog="$BUILDX_FAILED_LOG"
+ if [ -f "$errlog" ]; then
+ printf_red "Please note the last build had failed!!"
+ printf_red "Please check the error log and fix all problems"
+ printf_yellow "To remove this warning delete $errlog"
+ return 20
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__orgs_api_delete() {
+ if echo "$1" | grep -q '/'; then
+ user="${1//\/*/}"
+ image="${1//*\//}"
+ elif [ $# -eq 1 ]; then
+ user="$BUILDX_DEFAULT_REPO"
+ image="$1"
+ else
+ user="$1"
+ image="$2"
+ fi
+ [ -n "$user" ] || printf_exit "Please provide a organization name"
+ [ -n "$image" ] || printf_exit "Please provide a repository name"
+ repo="$user/$image"
+ if [ -f "$BUILDX_CACHE_DIR/token" ]; then
+ local TOKEN="$(<"$BUILDX_CACHE_DIR/token")"
+ printf_cyan "Attempting to delete $image from: $BUILDX_REGISTRY_URL/v2/repositories/$repo"
+ curl -q -LSsfi -H "Authorization: Bearer $TOKEN" -X DELETE "$BUILDX_REGISTRY_URL/v2/repositories/$repo" &>"$BUILDX_CACHE_DIR/delete.log"
+ if grep -qis '405 Not Allowed' "$BUILDX_CACHE_DIR/delete.log"; then
+ __api_auth_error
+ elif grep -qis '404.*Not.*Found' "$BUILDX_CACHE_DIR/delete.log"; then
+ printf_green "Repository does not exist"
+ elif grep -qis 'HTTP.*404.NO.*Content' "$BUILDX_CACHE_DIR/delete.log"; then
+ printf_green "Repository does not exist"
+ elif grep -qis 'HTTP.*204.NO.*Content' "$BUILDX_CACHE_DIR/delete.log"; then
+ printf_green "Repository does not exist"
+ elif grep -qis 'HTTP.*202.*Accepted' "$BUILDX_CACHE_DIR/delete.log"; then
+ printf_green "Successfully deleted the repository"
+ else
+ printf_exit "Failed to delete the repository"
+ grep -i 'HTTP/.*' "$BUILDX_CACHE_DIR/delete.log" | printf_readline 1
+ grep -i 'URL returned error' "$BUILDX_CACHE_DIR/delete.log" | sed 's|*.The requested URL returned error: ||g' | printf_readline 1
+ fi
+ else
+ printf_exit 1 1 "token not set: $APPNAME api auth [username] [password]"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__orgs_api_update() {
+ # TODO figure out how to make this work
+ printf_exit "This is not working for me!"
+ if echo "$1" | grep -q '/'; then
+ user="${1//\/*/}"
+ image="${1//*\//}"
+ elif [ $# -eq 1 ]; then
+ user="$BUILDX_DEFAULT_REPO"
+ image="$1"
+ else
+ user="$1"
+ image="$2"
+ fi
+ repo="$user/$image"
+ [ -n "$user" ] || printf_exit "Please provide a organization name"
+ [ -n "$image" ] || printf_exit "Please provide a repository name"
+ [ -n "$3" ] && field="$3" || printf_exit "Please provide a field to update [description,full_description,is_private]"
+ [ -n "$4" ] && field_value="$4" || printf_exit "Please provide a value to field"
+ # [ -n "$4" ] && full_description="$4" || printf_exit "Please provide full description"
+ # [ -n "$5" ] && is_private="$5" || printf_exit "private repo true/false"
+ # [ -n "$6" ] && can_edit="$6" || printf_exit "can edit true/false"
+ #-d "{\"description\": \"$description\", \"is_private\": \"$is_private\", \"can_edit\": \"$can_edit\", \"full_description\": \"$full_description\"}" \
+ if [ -f "$BUILDX_CACHE_DIR/token" ]; then
+ local TOKEN="$(<"$BUILDX_CACHE_DIR/token")"
+ printf_cyan "Attempting to update $image from:"
+ printf_cyan "$BUILDX_REGISTRY_URL/v2/repositories/$repo"
+ curl -q -LSsfi -H "Content-Type: application/json" \
+ -H "Authorization: Bearer $TOKEN" -X PATCH \
+ -d "{\"$field\": \"$field_value\"}" \
+ "$BUILDX_REGISTRY_URL/v2/repositories/$repo/" &>"$BUILDX_CACHE_DIR/update.log"
+ if grep -qis '405 Not Allowed' "$BUILDX_CACHE_DIR/update.log"; then
+ __api_auth_error
+ elif grep -qis '404.*Not.*Found' "$BUILDX_CACHE_DIR/update.log"; then
+ printf_green "Repository does not exist"
+ elif grep -qis '403.*FORBIDDEN' "$BUILDX_CACHE_DIR/update.log"; then
+ printf_green "You are not authorized to make this request"
+ elif grep -qis 'HTTP.*404.NO.*Content' "$BUILDX_CACHE_DIR/update.log"; then
+ printf_green "Repository does not exist"
+ elif grep -qis 'HTTP.*204.NO.*Content' "$BUILDX_CACHE_DIR/update.log"; then
+ printf_green "Repository does not exist"
+ elif grep -qis 'HTTP.*202.*Accepted' "$BUILDX_CACHE_DIR/update.log"; then
+ printf_green "Successfully updated the repository"
+ else
+ printf_exit "Failed to update the repository"
+ grep -i 'HTTP/.*' "$BUILDX_CACHE_DIR/update.log" | printf_readline 1
+ grep -i 'URL returned error' "$BUILDX_CACHE_DIR/update.log" | sed 's|*.The requested URL returned error: ||g' | printf_readline 1
+ fi
+ else
+ printf_exit 1 1 "Well something went terribly wrong"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_auth_error() {
+ printf_exit "Please authenticate with the command:"
+ printf_yellow "dockermgr api auth username password/key"
+ exit 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__curl_docker_api_tags() {
+ [ -n "$DEBUGGER" ] && set -x
+ local tags="" latest="" words="" numbers=""
+ [ $# -eq 3 ] || return 1
+ tags="$(curl -q -LSsf "$1/$2/$3/tags?page_size=1000" | jq -r ".results[].name" | grep '^' | grep -v '^$')"
+ latest="$(printf '%s' "$tags" | grep -E 'latest|edge|rolling' | grep '^')"
+ words="$(printf '%s' "$tags" | grep -Ev 'latest|edge|rolling|[0-9]' | grep '^')"
+ numbers="$(printf '%s' "$tags" | grep -E '[0-9]' | grep -Evi '[a-z]' | sort --reverse -u --version-sort | grep '^')"
+ [ -n "$latest" ] && printf '%s\n' "$latest" || latest="na"
+ [ -n "$words" ] && printf '%s\n' "$words" || word="na"
+ [ -n "$numbers" ] && printf '%s\n' "$numbers" || numbers="na"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_tags() {
+ [ -n "$DEBUGGER" ] && set -x
+ local results=""
+ local repo="${1:-}"
+ local image="${2:-}"
+ local registry="${3:-$2}"
+ local api_url="${4:-v2/repositories}"
+ local registry="https://registry.hub.docker.com/$api_url"
+ echo "$image" | grep -q '/' && repo="${repo//\/*/}" && image="${repo//*\//}"
+ [ -n "$image" ] || repo="library" image="$1"
+ [ -n "$image" ] && [ -n "$image" ] || printf_exit "Usage: $APPNAME api tags [repo] [image]"
+ results="$(__curl_docker_api_tags "$registry" "$repo" "$image" | grep '^')"
+ if [ -n "$results" ]; then
+ printf_cyan "found the following tags for $repo/$image"
+ printf '%s\n' "$results" | printf_column "$BUILDX_OUTPUT_COLOR_1" | grep -v '^$'
+ return 0
+ else
+ printf_exit "Failed to get tags from $registry/$repo/$image"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_dockerfile_ver() {
+ # TODO: rewrite this function
+ [ -n "$DEBUGGER" ] && set -x
+ local fileloc=""
+ local buildx_enable_tag="$BUILDX_ADD_TAG"
+ fileloc="$(realpath "${1:-$Dockerfile}" 2>/dev/null)"
+ [ -f "$fileloc" ] || return 1
+ #
+ local date_tag=""
+ local run_add_tags="yes"
+ local set_ver_tag="" iver="" cver="" version="" exitC="0"
+ #
+ new_tag="${set_newtag:-$new_tag}"
+ new_tag="${new_tag:-latest}"
+ iver="$(basename "$fileloc" 2>/dev/null | sed 's/^[^\.]*\./rel:/' | awk -F ':' '{print $2}' | sed 's| ||g' | __grep_exclude_version || echo '')"
+ cver="$(grep -sh 'ARG.*CONTAINER_VERSION=' "$fileloc" | __get_version | __grep_exclude_version || grep -sh 'ARG.*IMAGE_VERSION=' "$fileloc" | __get_version | __grep_exclude_version || echo '')"
+ #
+ date_tag="$(grep -sh 'ARG.*CONTAINER_VERSION=' "$fileloc" | __get_version | grep 'USE_DATE' || grep -sh '^ARG.*IMAGE_VERSION=' "$fileloc" | __get_version | grep 'USE_DATE' || echo '')"
+ #
+ [ -f "$BUILDX_CWD/.env.scripts.$iver" ] && . "$BUILDX_CWD/.env.scripts.$iver"
+ [ -f "$BUILDX_CWD/.env.scripts.$cver" ] && . "$BUILDX_CWD/.env.scripts.$cver"
+ #
+ [ -n "$ENV_IMAGE_TAG" ] && cver="$cver $ENV_ADD_TAGS $ENV_IMAGE_TAG"
+ #
+ set_default_tag="$(echo "$iver" "$cver" | __grep_exclude_version | tr ' ' '\n' | grep -v '^$' | sort -uVr | head -n1 | grep '^' || echo "$new_tag")"
+ #
+ { [ -z "$iver" ] || [ "$iver" = " " ]; } && iver=""
+ { [ -z "$cver" ] || [ "$cver" = " " ]; } && cver=""
+ #
+ [ "$cver" = "$iver" ] && run_add_tags="no"
+ [ -z "$iver" ] && [ -z "$cver" ] && [ -z "$date_tag" ] && run_add_tags="no"
+ current_versions="${set_default_tag:-$new_tag} $(echo $iver $cver $ENV_ADD_TAGS $ENV_IMAGE_TAG | tr ' ' '\n' | sort -urV | grep -vE "${set_default_tag:-$new_tag}|USE_DATE" | tr '\n' ' ')"
+ current_versions="${current_versions//USE_DATE/}"
+ #
+ if [ "$run_add_tags" != "no" ]; then
+ for version in $current_versions $date_tag; do
+ if [ "$version" != "$set_default_tag" ]; then
+ if [ -n "$version" ] && [ "$version" != " " ]; then
+ if echo "$version" | grep -qw '^USE_DATE'; then
+ set_ver_tag+="$(date +"$BUILDX_BUILD_DATE_TAG_FORMAT"),"
+ elif echo "$version" | grep -qw '^[0-9]'; then
+ set_ver_tag+="$version,"
+ elif echo "$version" | grep -Eqw '^edge'; then
+ set_ver_tag+="edge,"
+ elif echo "$version" | grep -Eqw '^rolling'; then
+ set_ver_tag+="rolling,"
+ elif echo "$version" | grep -Eqw '^dev|^devel'; then
+ set_ver_tag+="devel,"
+ elif echo "$version" | grep -qw '^latest'; then
+ set_ver_tag+="latest,"
+ elif echo "$version" | grep -Eqw '^next|^beta|^alpha|^test|^testing'; then
+ set_ver_tag+="next,"
+ else
+ set_ver_tag+="$version,"
+ fi
+ else
+ exitC=1
+ fi
+ fi
+ done
+ fi
+ set_ver_tag="${set_ver_tag//USE_DATE/}"
+ #
+ new_tag="$(echo "${set_default_tag}" | grep '^' || echo "latest")"
+ set_ver_tag="$(echo "$set_ver_tag" | sed 's| |,|g' | tr ',' '\n' | sort -u | grep -v "$new_tag" | grep -v '^$' | tr '\n' ' ' | sed 's|,$||g;s|,| |g;s| $||g;s|^ *||g;s| *| |g' | grep '^' || false)"
+ set_ver_tag="${set_ver_tag//$new_tag/}"
+ [ "$set_ver_tag" = " " ] && set_ver_tag=""
+ tag_count="$(echo "${set_ver_tag[@]}" | grep -v '^$' | wc -l)"
+ #
+ #
+ set_ver_tag="${set_ver_tag// /,}"
+ if [ "$tag_count" -eq 0 ]; then
+ BUILDX_ADD_TAG="${buildx_enable_tag:-}"
+ else
+ BUILDX_ADD_TAG="true"
+ BUILDX_VERSION_TAG="$set_ver_tag"
+ fi
+ #
+ if [ -f "$BUILDX_CWD/.env.scripts.$new_tag" ]; then
+ . "$BUILDX_CWD/.env.scripts.$new_tag"
+ ENV_ADD_TAGS="${ENV_ADD_TAGS//USE_DATE/}"
+ fi
+ BUILDX_GET_VERSION_MESSAGE="$(printf '%s\n%s\n%s\n' "Image version is: $new_tag" "setting tag to $new_tag" "Added tags: ${BUILDX_VERSION_TAG:-none}")"
+ #
+ return $exitC
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_all() {
+ trap 'exit' SIGINT
+ local exitCode=0
+ export BUILDX_ADD_TAG=""
+ export ENV_IMAGE_TAG=""
+ export BUILDX_RUN_COUNT_OF="${BUILDX_RUN_COUNT_OF:-1}"
+ export BUILDX_BUILD_ALL="${BUILDX_BUILD_ALL:-true}"
+ export BUILDX_GIT_COMMIT_ID="${BUILDX_GIT_COMMIT_ID:-}"
+ export ENV_BUILDX_PROJECT_DIR="$(dirname "$BUILDX_CWD")"
+ export BUILDX_CUSTOM_LOG_RUNALL_DIR="${BUILDX_CUSTOM_LOG_DIR:-$BUILDX_LOG_DIR}"
+ export BUILDX_CUSTOM_LOG_RUNALL_FILE="$BUILDX_CUSTOM_LOG_DIR/build_all.log"
+ #
+ local errormess="Can not find a Dockerfile in $BUILDX_CWD"
+ #
+ if [ $BUILDX_RUN_COUNT_OF -eq 1 ]; then
+ printf_purple "Log file is being written to $BUILDX_CUSTOM_LOG_RUNALL_FILE"
+ [ -d "$BUILDX_CUSTOM_LOG_DIR" ] || mkdir -p "$BUILDX_CUSTOM_LOG_RUNALL_DIR"
+ __wait_for_previous_build
+ __create_log_files
+ __reinit_buildx
+ else
+ __wait_for_previous_build &>/dev/null
+ __create_log_files &>/dev/null
+ __reinit_buildx &>/dev/null
+ fi
+ if [ -f "$1" ]; then
+ echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ printf_purple "Building Dockerfile $BUILDX_RUN_COUNT_OF of $BUILDX_RUN_COUNT_TOTAL"
+ __execute_buildx "$1"
+ exitCode=$?
+ else
+ printf_red "$errormess"
+ exitCode=10
+ fi
+ if [ "$BUILDX_RUN_CRON" = "true" ]; then
+ if [ -f "/var/log/buildx-os" ]; then
+ cat "$BUILDX_CUSTOM_LOG_FILE" >>"/var/log/buildx-os"
+ if [ -n "$errormess" ] && [ "$exitCode" = "10" ]; then
+ printf '%s\n' "$errormess" >>"/var/log/buildx-os"
+ fi
+ printf '%s\n\n' "buildx has completed with status $exitCode" >>"/var/log/buildx-os"
+ fi
+ fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__buildx_run() {
+ trap 'exit' SIGINT
+ local exitCode=0
+ __wait_for_previous_build
+ __create_log_files
+ __reinit_buildx
+ __run_git_pull "$BUILDX_CWD"
+ if [ $# -ne 0 ]; then
+ __execute_buildx "$@"
+ exitCode=$?
+ elif [ -f "$BUILDX_CWD/$1" ]; then
+ __execute_buildx "$BUILDX_CWD/$1"
+ exitCode=$?
+ elif [ -f "$BUILDX_CWD/Dockerfile" ]; then
+ __execute_buildx "$BUILDX_CWD/Dockerfile"
+ exitCode=$?
+ else
+ printf_red "Can not find a Dockerfile in $BUILDX_CWD"
+ exitCode=10
+ fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__wait_for_previous_build() {
+ local sleep=60 count=20 pid_number=""
+ if [ -f "$BUILDX_PID_FILE" ]; then
+ pid="$(<"$BUILDX_PID_FILE")"
+ pid_number="$(ps aux | grep "$pid" | grep -v 'grep ')"
+ [ -n "$pid_number" ] && printf_green "Pid exists: $BUILDX_PID_FILE"
+ while [ -n "$pid_number" ] && [ -f "$BUILDX_PID_FILE" ]; do
+ if [ $count -eq 0 ]; then
+ echo " "
+ printf_exit "Timeout waiting for previous build to complete "
+ else
+ [ -f "$BUILDX_PID_FILE" ] && pid="$(<"$BUILDX_PID_FILE")" || break
+ printf '\r%s' "waiting for previous build to complete: $((count * $sleep / 60)) minutes"
+ pid_number="$(ps aux | grep "$pid" | grep -v 'grep ')"
+ count=$((count - 1))
+ sleep $sleep
+ fi
+ done
+ [ -f "$BUILDX_PID_FILE" ] && rm -Rf "$BUILDX_PID_FILE"
+ buildx init &>/dev/null
+ #BUILDX_CLEANUP="false"
+ sleep 60
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__remove_pid() {
+ if [ "$BUILDX_IS_RUNNING" = "true" ] && [ -f "$BUILDX_PID_FILE" ]; then
+ rm -Rf "$BUILDX_PID_FILE"
+ fi
+ return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__is_buildx_installed() {
+ local buildx_installed=""
+ buildx_installed="$(__docker_init buildx version 2>&1 | grep 'buildx.*v[0-9].*[0-9]' && __docker_init buildx ls 2>&1 | grep -A3 'NAME/NODE' | grep 'running.*[0-9] ' || false)"
+ if [ -n "$buildx_installed" ] && [ -d "$HOME/.docker/buildx" ]; then
+ exitCode=0
+ else
+ __install_buildx && __buildx_init && BUILDX_INSTALLED="yes" && return 0
+ export BUILDX_INSTALLED="no"
+ exitCode=0
+ fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__is_docker_installed() {
+ if ! type -p docker &>/dev/null; then
+ printf_red "Docker is not installed either run dockermgr init"
+ printf_exit "or refer to docker documentation for installation"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__is_initialized() {
+ local exitCode=0
+ local init_name="${1:-$BUILDX_BUILDER_NAME}"
+ if { [ -e "/root/.docker/buildx/instances/$init_name" ] || [ -e "$HOME/.docker/buildx/instances/$init_name" ]; }; then
+ { [ -n "$builder_id" ] && [ -n "$qemu_id" ] && [ -n "$binfmt_id" ] && BUILDX_INIT_RAN="true"; } && __is_buildx_installed || exitCode=1
+ else
+ exitCode=1
+ fi
+ [ "$BUILDX_BUILD_ALL" = "true" ] && return 0 || return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__jq() { jq "${@:--r}" 2>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__curl() { curl -q -LSsf --max-time 2 --retry 0 "$*" 2>/dev/null || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__usage() { printf_exit 1 2 "Usage: $APPNAME [Dir] [Dockerfile] [name] [tag]" 1>&2; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker() {
+ eval "$BUILDX_DOCKER_CMD" "$@" 2>/dev/null && true
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_init() {
+ eval "$BUILDX_DOCKER_CMD" "$@" 2>&1 && true
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_push() {
+ __docker push "$tagged_name" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null ||
+ __docker push "$tagged_name" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null ||
+ __docker push "$tagged_name" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null && true
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__qemu_version() {
+ if grep -shq 'enabled' "/proc/sys/fs/binfmt_misc/status"; then
+ if __cmd_exists qemu-aarch64-static; then
+ version="$(qemu-aarch64-static --version | head -n1 | cut -d' ' -f3 | tr -cd '0-9.')"
+ printf_blue "QEMU aarch64 version: $version"
+ fi
+ if __cmd_exists qemu-x86_64-static; then
+ version="$(qemu-x86_64-static --version | head -n1 | cut -d' ' -f3 | tr -cd '0-9.')"
+ printf_blue "QEMU x86_64 version: $version"
+ fi
+ if __cmd_exists qemu-arm-static; then
+ version="$(qemu-arm-static --version | head -n1 | cut -d' ' -f3 | tr -cd '0-9.')"
+ printf_blue "QEMU arm version: $version"
+ fi
+ else
+ printf_red "Missing qemu-user-static package."
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_version() {
+ version="$(__docker --version | cut -d' ' -f3 | tr -cd '0-9.' | sed -e 's/ 0*/ /g')"
+ [ -n "$version" ] && printf_blue "Docker version: $version"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__binfmt_version() {
+ if __cmd_exists update-binfmts; then
+ version="$(update-binfmts --version | awk '{print $NF}')"
+ [ -n "$version" ] && printf_blue "update-binfmts version: $version"
+ else
+ printf_return "Please install update-binfmts"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__buildx_vars() {
+ local get_name="${1:-$BUILDX_BUILDER_NAME}"
+ local set_name="${get_name:-mybuilder}"
+ export qemu_imagename="buildx-qemu"
+ export binfmt_imagename="buildx-binfmt"
+ export qemu_id="$(__docker_init ps -a | awk '{print $NF}' | grep "$qemu_imagename" || echo '')"
+ export binfmt_id="$(__docker_init ps -a | awk '{print $NF}' | grep "$binfmt_imagename" || echo '')"
+ export builder_id="$(__docker_init ps -a | awk '{print $NF}' | grep "$set_name" | grep "buildkit" || __docker_init buildx ls | grep "$set_name" | awk -F ' ' '{print $1}' | head -n1 || echo '')"
+ export BUILDX_BUILDER_NAME="$set_name"
+ [ -n "$qemu_id" ] && [ -n "$binfmt_id" ] && [ -n "$builder_id" ] && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__buildx_version() {
+ features="$(__docker version | awk '/^ *Experimental:/ {print $2 ; exit}')"
+ [ "$features" == "true" ] && printf_blue "Experimental Features: yes" ||
+ printf_red "Experimental Features: no"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__reinit_buildx() {
+ name="${name:-init}"
+ local force_install="${BUILDX_FORCE:-$BUILDX_FORCE_REINSTALL}"
+ __buildx_vars "${BUILDX_BUILDER_NAME:-}"
+ [ "$BUILDX_INIT_RAN" != "true" ] || return 0
+ [ "$force_install" = "yes" ] || [ -z "$builder_id" ] || [ -z "$binfmt_id" ] || [ -z "$qemu_id" ] || return 0
+ printf_cyan "Reinitializing buildx: $BUILDX_BUILDER_NAME on: $(date)"
+ echo "Reinitializing buildx: $BUILDX_BUILDER_NAME on: $(date)" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ local force="${force_install:-$BUILDX_CLEAN_FORCE}"
+ [ -z "$builder_id" ] || __docker_init rm -f --volumes $builder_id |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ [ -z "$binfmt_id" ] || __docker_init rm -f --volumes "$qemu_imagename" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ [ -z "$qemu_id" ] || __docker_init rm -f --volumes "$binfmt_imagename" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __docker_init run -d --name "$qemu_imagename" --privileged multiarch/qemu-user-static --reset -p yes --credential yes |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __docker_init run -d --name "$binfmt_imagename" --privileged tonistiigi/binfmt --install all |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __docker_init buildx create --driver docker-container --driver-opt network=host --driver-opt image=moby/buildkit:master --name ${BUILDX_BUILDER_NAME:-mybuilder} --use |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __docker_init buildx use "$BUILDX_BUILDER_NAME" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __docker_init buildx inspect --bootstrap |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __buildx_vars "${BUILDX_BUILDER_NAME:-}"
+ __create_update_docker_daemon_config
+ if [ -n "$builder_id" ] && __is_buildx_installed; then
+ BUILDX_FORCE=""
+ BUILDX_INIT_RAN="true"
+ BUILDX_FORCE_REINSTALL=""
+ printf_cyan "Building for platforms: $BUILDX_DOCKER_PLATFORMS"
+ printf '%s\n' " # Building for platforms: $BUILDX_DOCKER_PLATFORMS" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ return 0
+ else
+ echo "Initializing of buildx failed" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ printf_yellow "Initializing of buildx failed"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__buildx_cleanup() {
+ local prevExit=$?
+ local exitCodeClean=""
+ if [ "$BUILDX_CLEANUP" = "true" ] && [ "$BUILDX_IS_RUNNING" = "true" ]; then
+ if [ "$BUILDX_BUILD_ALL" != "true" ] && [ "$BUILDX_RAN_CLEANUP" != "true" ]; then
+ printf_yellow "Cleaning up containers"
+ fi
+ __docker rm -f --volumes $builder_id $qemu_imagename $binfmt_imagename &>/dev/null
+ BUILDX_RAN_CLEANUP="true"
+ if __is_initialized; then exitCodeClean=1; else exitCodeClean=0; fi
+ fi
+ if [ "$BUILDX_BUILD_ALL" != "true" ]; then
+ __trap_timer
+ unset BUILDX_START_TIMER BUILDX_STOP_TIMER
+ exitCodeClean=$prevExit
+ else
+ echo ""
+ fi
+ return $exitCodeClean
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__install_buildx() {
+ local arch=""
+ local release=""
+ local exitCode=0
+ local buildx_install_dir="$HOME/.docker/cli-plugins"
+ local buildx_install_path="$buildx_install_dir/docker-buildx"
+ local arch="$(uname -m | tr '[:upper:]' '[:lower:]')"
+ local api="https://api.github.com/repos/docker/buildx/releases/latest"
+ [ -x "$buildx_install_path" ] && [ "$BUILDX_FORCE" != "yes" ] && return 0
+ case "$arch" in
+ x86_64) arch="amd64" ;;
+ aarch64) arch="arm64" ;;
+ esac
+ [ -d "$buildx_install_dir" ] || mkdir -p "$buildx_install_dir"
+ release="$(curl -q -LSsf "$api" 2>/dev/null | jq -r '.' | grep 'browser_download_url' | awk -F '":' '{print $2}' | sed 's|"||g;s| *||g' | grep "linux-$arch$")"
+ if [ -n "$release" ]; then
+ printf_cyan "Installing buildx for $arch "
+ curl -q -LSsf "$release" -o "$buildx_install_path" || exitCode=1
+ if [ $exitCode = 0 ] && [ -f "$buildx_install_path" ]; then
+ chmod -Rf +x "$buildx_install_path"
+ if [ "$USER" != "root" ]; then
+ __can_i_sudo && sudo mkdir -p "/root/.docker/cli-plugins" && sudo cp -Rf "$buildx_install_path" "/root/.docker/cli-plugins"
+ fi
+ printf_green "Installed buildx to $buildx_install_path"
+ fi
+ fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__buildx_init() {
+ __buildx_vars "$BUILDX_BUILDER_NAME"
+ local buildx_log_file="$BUILDX_CUSTOM_LOG_FILE"
+ __is_buildx_installed && BUILDX_INIT_RAN="true" || BUILDX_FORCE="true"
+ if [ "$BUILDX_FORCE" = "true" ]; then
+ [ -d "$HOME/.docker/buildx" ] && rm -Rf "$HOME/.docker/buildx"
+ [ -d "/root/.docker/buildx" ] && __sudo rm -Rf "$HOME/.docker/buildx"
+ BUILDX_FORCE="yes"
+ BUILDX_CLEAN_FORCE="yes"
+ BUILDX_FORCE_REINSTALL="yes"
+ __reinit_buildx
+ fi
+ if [ "$BUILDX_FORCE_REINSTALL" = "yes" ] || [ "$BUILDX_CLEAN_FORCE" = "yes" ]; then
+ __reinit_buildx
+ elif __is_initialized && [ "$BUILDX_FORCE" != "yes" ]; then
+ printf_cyan "buildx seems to be already setup"
+ return 0
+ else
+ echo "Starting buildx init for $name on $(date)" |& tee -p "$BUILDX_CUSTOM_LOG_FILE"
+ printf_yellow "Initializing docker build"
+ printf_cyan "Setting logfile to: $buildx_log_file"
+ if [ "$BUILDX_CLEANUP" = "true" ] || { [ -n "$binfmt" ] && [ -n "$qemu" ]; }; then
+ printf_yellow "Removing old containers: $qemu_imagename,$binfmt_imagename"
+ __docker_init rm -f --volumes "$qemu_imagename" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __docker_init rm -f --volumes "$binfmt_imagename" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ fi
+ __install_buildx
+ if [ "$(uname -m)" = "x86_64" ]; then
+ # Setup qemu
+ # sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes --credential yes
+ printf_yellow "Setting up the qemu image - multiarch/qemu-user-static as $qemu_imagename"
+ __docker_init run -d --name "$qemu_imagename" --privileged multiarch/qemu-user-static --reset -p yes --credential yes |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ # Setup binfmt
+ printf_yellow "Setting up the binfmt image - tonistiigi/binfmt as $binfmt_imagename"
+ __docker_init run -d --name "$binfmt_imagename" --privileged tonistiigi/binfmt --install all |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ # setup buildx
+ printf_blue "Setting up docker build to use buildx"
+ #__docker_init buildx create --buildkitd-flags '--allow-insecure-entitlement security.insecure' --name "$name" --use |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __docker_init buildx create --driver docker-container --driver-opt network=host --driver-opt image=moby/buildkit:master --name ${name:-mybuilder} --use |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __docker_init buildx use "$name" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __docker_init buildx inspect --bootstrap |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ fi
+ if [ "$BUILDX_INIT_RAN" != "yes" ]; then
+ # create docker daemon file
+ __create_update_docker_daemon_config
+ # setup service
+ printf_blue "Making sure docker service is running"
+ sudo systemctl daemon-reload
+ if ! systemctl status systemd-binfmt.service | grep -iq 'running'; then
+ sudo systemctl enable -now systemd-binfmt.service &>/dev/null
+ sudo systemctl restart systemd-binfmt.service &>/dev/null
+ fi
+ if ! systemctl status docker*.service | grep -iq 'running'; then
+ sudo systemctl enable --now docker &>/dev/null
+ sudo systemctl restart docker &>/dev/null
+ fi
+ # login to docker hub
+ printf_yellow "Making sure user is signed into to docker hub"
+ __is_logged_in || __docker_init login || exit 2
+ # clean up
+ printf_purple "Finishing up"
+ [ -d "$HOME/.docker/buildx" ] || mkdir -p "$HOME/.docker/buildx"
+ sudo bash -c '[ -d "/root/.docker/buildx" ] && [ "/root/.docker/buildx" != "'$HOME/.docker/buildx'" ] && cp -Rf /root/.docker/buildx/. "'$HOME/.docker/buildx/'"'
+ sudo chown -Rf "$SUDO_USER":"$SUDO_USER" "$HOME/.docker"
+ [ -e "$HOME/.docker/buildx/current" ] && printf_green "buildx has been setup"
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__tag_versions() {
+ local add_new_host="" add_image_name="" add_full_host=""
+ local ADD_IMAGE_PUSH="${ENV_ADD_IMAGE_PUSH//,/ }"
+ host="${host:-$BUILDX_DEFAULT_REGISTRY}"
+ add_image_name="${image_name//:*/}"
+ add_tags="${BUILDX_VERSION_TAG//,/ }"
+ namespace="${namespace:-$BUILDX_DEFAULT_REPO}"
+ add_full_host="${1:-$host/$namespace/$add_image_name}"
+ add_tags="${add_tags//USE_DATE/}"
+ if [ "$BUILDX_ADD_TAG" = "true" ]; then
+ for tag in $add_tags; do
+ [ "$tag" = "$BUILDX_DEFAULT_VERSION" ] || SET_ADD_HOST+=("-t $add_full_host:$tag ")
+ if [ -n "$ADD_IMAGE_PUSH" ]; then
+ for vtag in $ADD_IMAGE_PUSH; do
+ SET_ADD_HOST+=("-t $vtag:$tag ")
+ done
+ fi
+ done
+ else
+ add_new_host="$add_full_host:$tag_version"
+ [ -n "$ADD_IMAGE_PUSH" ] && SET_ADD_HOST+=("-t $ADD_IMAGE_PUSH:$tag_version ")
+ fi
+ image_name="$add_new_host"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__buildx_status() {
+ local a="" e="" c="" r="" s=""
+ e=0
+ a="$*"
+ c="$(__docker buildx inspect ${1:-$BUILDX_BUILDER_NAME} || false)"
+ r="$(__docker buildx ls | grep ${1:-$BUILDX_BUILDER_NAME} | grep -qi 'running' && echo 'running' || false)"
+ s="$(echo "$c" | grep -i 'Status:' | grep -qi 'running' && echo 'Running' || false)"
+ if [ ${#a} = 0 ]; then
+ [ -n "$s" ] && e=0 || e=1
+ else
+ if [ -n "$s" ]; then
+ printf '%s\n' "$c"
+ e=0
+ else
+ printf '%s\n' "buildx is not running"
+ e=1
+ fi
+ fi
+ return ${e:-$?}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_docker_script() {
+ set_build_command="$(<"$BUILDX_CWD/build.sh")"
+ set_build_command="${set_build_command// / }"
+ build_command="$(echo "$set_build_command" | grep '^' | grep -v '^$' | sed 's|,,| \\\n|g')"
+ set_build_command="${set_build_command//,,/}"
+ printf '%b%s: %b%s%b\n' "$GREEN" "Saving the build command to" "$CYAN" "$logscript_file" "$NC"
+ printf 'Saving the build command to: %s\n' "$logscript_file" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __save_build_script
+ printf_blue "Setting default tag to: $set_tag"
+ if [ -n "$ADDITIONAL_PRETTY" ]; then
+ for reg in $ADDITIONAL_PRETTY; do
+ printf_cyan "Added tag: $reg"
+ done
+ fi
+ echo "$BUILDX_GET_VERSION_MESSAGE" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ if [ "$BUILDX_ADD_TAG" = "true" ] || [ -n "$REGISTRY_TAG" ] && [ -n "$ADDITIONAL_PRETTY" ]; then
+ printf_blue "Adding tags: $ADDITIONAL_PRETTY"
+ printf '%s\n' "# Adding tags: $ADDITIONAL_PRETTY" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ fi
+ sleep 2
+ printf 'Executing: %s\n' "$set_build_command" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ eval "$set_build_command" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null || false
+ return $?
+
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_dockermgr_script() {
+ local dir="/tmp/builder"
+ local build_tags="-t $tagged_name $ADDITIONAL_TAGS"
+ local build_name="$(basename "${tagged_name//:*/}")"
+ local buildfile="$(basename "${Dockerfile:-Dockerfile}")"
+ set_build_command='dockermgr --name '$build_name',, -- builder buildx_script "'$BUILDX_DOCKER_PLATFORMS'",, "'$build_tags'",, "'$dir'",, "'$dir/$buildfile'"'
+ set_build_command="${set_build_command// / }"
+ build_command="$(echo "$set_build_command" | grep '^' | grep -v '^$' | sed 's|,,| \\\n|g')"
+ set_build_command="${set_build_command//,,/}"
+ printf '%b%s: %b%s%b\n' "$GREEN" "Saving the build command to" "$CYAN" "$logscript_file" "$NC"
+ printf 'Saving the build command to: %s\n' "$logscript_file" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __save_build_script
+ printf_blue "Setting default tag to: $set_tag"
+ if [ "$BUILDX_ADD_TAG" = "true" ] || [ -n "$REGISTRY_TAG" ] && [ -n "$ADDITIONAL_PRETTY" ]; then
+ printf_blue "Adding tags: $ADDITIONAL_PRETTY"
+ printf '%s\n' "# Adding tags: $ADDITIONAL_PRETTY" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ fi
+ sleep 2
+ printf 'Executing: %s\n' "$build_command" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ eval "$set_build_command" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null || false
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_buildx_script() {
+ set_build_command="$BUILDX_DOCKER_CMD buildx build ${BUILDX_REMOVE_BUILD:-},, --platform $BUILDX_DOCKER_PLATFORMS,, --rm --pull --push,, --no-cache --progress auto --output=type=registry,, -t $tagged_name $ADDITIONAL_TAGS,, ${dir:-$PWD},, -f ${Dockerfile:-Dockerfile}"
+ set_build_command="${set_build_command// / }"
+ build_command="$(echo "$set_build_command" | grep '^' | grep -v '^$' | sed 's|,,| \\\n|g')"
+ set_build_command="${set_build_command//,,/}"
+ printf '%b%s: %b%s%b\n' "$GREEN" "Saving the build command to" "$CYAN" "$logscript_file" "$NC"
+ printf 'Saving the build command to: %s\n' "$logscript_file" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __save_build_script
+ printf_blue "Setting default tag to: $set_tag"
+ if [ "$BUILDX_ADD_TAG" = "true" ] || [ -n "$REGISTRY_TAG" ] && [ -n "$ADDITIONAL_PRETTY" ]; then
+ printf_blue "Adding tags: $ADDITIONAL_PRETTY"
+ printf '%s\n' "# Adding tags: $ADDITIONAL_PRETTY" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ fi
+ sleep 2
+ printf 'Executing: %s\n' "$set_build_command" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ eval "$set_build_command" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null || false
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_build_script() {
+ set_build_command="$BUILDX_DOCKER_CMD build,, --pull --force-rm --no-cache,, -t $tagged_name $ADDITIONAL_TAGS,, ${dir:-$PWD},, -f ${Dockerfile:-Dockerfile}"
+ set_build_command="${set_build_command// / }"
+ build_command="$(echo "$set_build_command" | grep '^' | grep -v '^$' | sed 's|,,| \\\n|g')"
+ set_build_command="${set_build_command//,,/}"
+ printf '%b%s: %b%s%b\n' "$GREEN" "Saving the build command to" "$CYAN" "$logscript_file" "$NC"
+ printf 'Saving the build command to: %s\n' "$logscript_file" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __save_build_script
+ printf_blue "Setting default tag to: $set_tag"
+ if [ "$BUILDX_ADD_TAG" = "true" ] || [ -n "$REGISTRY_TAG" ] && [ -n "$ADDITIONAL_PRETTY" ]; then
+ printf_blue "Adding tags: $ADDITIONAL_PRETTY"
+ printf '%s\n' "# Adding tags: $ADDITIONAL_PRETTY" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ fi
+ sleep 2
+ printf 'Executing: %s\n' "$set_build_command" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ eval "$set_build_command" |& tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null || false
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__save_build_script() {
+ [ -d "$logscript_dir" ] || mkdir -p "$logscript_dir"
+ echo "command: $build_command" |& tee -p "$logscript_file" &>/dev/null
+ cat </dev/null
+#!/usr/bin/env bash
+# Build command for $tagged_name
+
+${build_command}
+exit \$?
+
+EOF
+ chmod -Rf 755 "$logscript_file"
+ if [ "$BUILDX_GEN_SCRIPT" = "true" ]; then
+ if [ -x "$logscript_file" ]; then
+ printf_yellow "Your script has been saved: exiting"
+ echo "Your script has been saved: exiting" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ exit 0
+ else
+ printf_red "Your script failed to save: exiting" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ exit 1
+ fi
+ else
+ [ -x "$logscript_file" ] && return 0 || return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_docker_build() {
+ set -e -o pipefail
+ cd "$BUILDX_CWD" || return 1
+ buildx_status="0"
+ SET_ADD_HOST=("")
+ registry="${BUILDX_ADD_REGISTRY//,/ }"
+ image_name="${tagged_name//$BUILDX_DEFAULT_REPO\//}"
+ if [ -n "$BUILDX_ADD_REGISTRY" ] && [ "$BUILDX_ENABLE_REGISTRY" = "true" ]; then
+ for host in $registry; do
+ if [ -n "$BUILDX_ADD_REPO" ]; then
+ namespace="$BUILDX_ADD_REPO"
+ [ "$namespace" = "" ] && namespace="library"
+ [ "$namespace" = "_" ] && namespace="library"
+ if echo "$image_name" | grep -q ":"; then
+ full_host="$host/$namespace/$image_name"
+ __tag_versions "$full_host"
+ SET_ADD_HOST+=("-t $full_host ")
+ else
+ __tag_versions "$host/$namespace/$image_name"
+ SET_ADD_HOST+=("-t $host/$namespace/$image_name ")
+ fi
+ else
+ namespace="$(echo $(basename $(dirname "$BUILDX_CWD")))"
+ __tag_versions "$host/$namespace/$image_name"
+ SET_ADD_HOST+=("-t $host/$namespace/$image_name ")
+ fi
+ done
+ fi
+ __tag_versions "$tagged_name"
+ ADD_HOST="$(printf '%s\n' "${SET_ADD_HOST[@]}" | sort -u | tr '\n' ' ' | sed 's| *| |g')"
+ ADDITIONAL_TAGS="$REGISTRY_TAG ${ADD_HOST[*]}"
+ ADDITIONAL_PRETTY="$(echo "$ADDITIONAL_TAGS" | sed 's|--tag||g;s|-t||g' | tr ' ' '\n' | grep -v '^$' | tr '\n' ' ')"
+ [ -n "$image_name" ] && tagged_name="$image_name" || tagged_name="$push_tag"
+ if [ "$BUILDX_RUN_SCRIPT" = "true" ] && [ -f "$BUILDX_CWD/build.sh" ]; then
+ printf_blue "Using $BUILDX_CWD/build.sh to build $tagged_name"
+ printf '%s\n' "# Using Using $BUILDX_CWD/build.sh to build $tagged_name" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __run_docker_script
+ buildx_status=$?
+ elif __is_buildx_installed; then
+ printf_blue "Using docker buildx to build $tagged_name"
+ printf '%s\n' "# Using docker buildx to build $tagged_name" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __run_buildx_script
+ buildx_status=$?
+ else
+ printf_blue "Using docker build to build $tagged_name"
+ printf '%s\n' "# Using docker build to build $tagged_name" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __run_build_script
+ buildx_status=$?
+ if [ "$buildx_status" = 0 ]; then
+ if __docker_push; then
+ printf '%s\n' "# Pushing of $tagged_name completed on : $(date +'%Y-%m-%d at %H:%M')" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ else
+ printf '%s\n' "# Pushing of $tagged_name failed on : $(date +'%Y-%m-%d at %H:%M')" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ fi
+ fi
+ fi
+ if [ $buildx_status = 0 ]; then
+ printf '%s\n' "# Finished building $tagged_name $ADDITIONAL_PRETTY" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ buildx_status=0
+ else
+ printf '%s\n' "# Building of $tagged_name has failed" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ buildx_status="${buildx_status:-10}"
+ fi
+ printf '\n%s\n' "buildx has Finished on: $(date +'%Y-%m-%d at %H:%M')" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __remove_pid
+ return $buildx_status
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__build_cmd() {
+ local exitCodeS="1"
+ local dir="${1:-$FULL_DIR_PATH}"
+ local errlog="$BUILDX_FAILED_LOG"
+ __last_build_check "$dir"
+ if ! __is_buildx_installed; then
+ printf_yellow "💔 buildx is not installed - Using 'docker build' instead. 💔"
+ fi
+ __run_docker_build
+ exitCodeS=$?
+ if [ "$exitCodeS" -ne 0 ]; then
+ printf_red "Building of $tagged_name has failed"
+ echo "build started on $BUILDX_FAILED_LOG" >"$errlog"
+ printf_yellow "The last 75 lines of the log are in:${CYAN} $errlog"
+ printf_blue "Full log is in the logfile"
+ echo "build failed on $(date +'%Y-%m-%d at %H:%M')" >>"$errlog"
+ tail -n75 "$BUILDX_CUSTOM_LOG_FILE" >>"$errlog"
+ fi
+ return ${exitCodeS:-$?}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_buildx() {
+ local exitCode=0
+ local buildxexitCode=1
+ BUILDX_DATE="$(date +'%Y-%m-%d at %H:%M')"
+ FULL_DIR_PATH="$(realpath "$BUILDX_CWD")"
+ if [ -f "$BUILDX_PID_FILE" ]; then
+ printf_exit "$APPNAME is already running"
+ else
+ BUILDX_IS_RUNNING="true"
+ echo "$BUILDX_PID_NUMBER" >"$BUILDX_PID_FILE"
+ fi
+ echo "$*" | grep -q '.*.:.*.' && __usage
+ [ $# -ne 0 ] || __usage
+ notify_message=""
+ set_name="${BUILDX_SET_IMAGE:-$BUILDX_SET_NAME}"
+ if [ -f "$1" ]; then
+ Dockerfile="$(realpath "$1")"
+ FULL_DIR_PATH="$(dirname "$Dockerfile")"
+ SET_DIR_NAME="$(basename "$FULL_DIR_PATH")"
+ shift 1
+ elif [ -d "$1" ]; then
+ Dockerfile="$(realpath "${1//$PWD\//}/Dockerfile")"
+ FULL_DIR_PATH="$(dirname "$Dockerfile")"
+ SET_DIR_NAME="$(basename "$FULL_DIR_PATH")"
+ shift 1
+ elif [ -f "$PWD/$1" ]; then
+ Dockerfile="$(realpath "${1//$PWD\//}")"
+ FULL_DIR_PATH="$(dirname "$Dockerfile")"
+ SET_DIR_NAME="$(basename "$(dirname "$(realpath "$Dockerfile")")")"
+ shift 1
+ elif [ -f "$BUILDX_CWD/Dockerfile.latest" ]; then
+ Dockerfile="$(realpath "$BUILDX_CWD/Dockerfile.latest")"
+ FULL_DIR_PATH="$(dirname "$Dockerfile")"
+ SET_DIR_NAME="$(basename "$(dirname "$(realpath "$Dockerfile")")")"
+ elif [ -f "$BUILDX_CWD/Dockerfile.next" ]; then
+ Dockerfile="$(realpath "$BUILDX_CWD/Dockerfile.next")"
+ FULL_DIR_PATH="$(dirname "$Dockerfile")"
+ SET_DIR_NAME="$(basename "$(dirname "$(realpath "$Dockerfile")")")"
+ elif [ -f "$BUILDX_CWD/Dockerfile" ]; then
+ Dockerfile="$(realpath "$BUILDX_CWD/Dockerfile")"
+ FULL_DIR_PATH="$(dirname "$Dockerfile")"
+ SET_DIR_NAME="$(basename "$(dirname "$(realpath "$Dockerfile")")")"
+ fi
+ if [ -n "$FULL_DIR_PATH" ] && [ -f "$Dockerfile" ]; then
+ builtin cd "$FULL_DIR_PATH" || exit 15
+ else
+ printf_red "Well something went wrong while looking for a Dockerfile in $FULL_DIR_PATH"
+ echo "" && exit 1
+ fi
+ [ -e "$1" ] && shift
+ default_name="$(basename "$FULL_DIR_PATH")"
+ DockerfileName="$(basename "$Dockerfile")"
+ BUILDX_CWD="$(dirname "$(realpath "$Dockerfile")")"
+ #BUILDX_DEFAULT_REPO="$(basename "$(realpath "$BUILDX_CWD")")"
+ FULL_DIR_PATH="${FULL_DIR_PATH:-$(dirname "$(realpath "$BUILDX_CWD/Dockerfile")")}"
+ if [ ! -f "$Dockerfile" ] || [ -z "$(ls -A "$Dockerfile" 2>/dev/null)" ]; then
+ printf_red "Can not find a Dockerfile in $FULL_DIR_PATH"
+ echo "" && exit 1
+ fi
+ #
+ image_name="$(grep -sh 'ARG.*IMAGE_NAME=' "$Dockerfile" | awk -F'=' '{print $2}' | sed 's|"||g' | grep '^' || echo "$default_name")"
+ #
+ name="${set_name:-$image_name}"
+ set_newtag="${set_newtag//*:/}"
+ name="$(echo "$name" | tr '[:upper:]' '[:lower:]')"
+ SET_DIR_NAME="$(echo "$SET_DIR_NAME" | tr '[:upper:]' '[:lower:]')"
+ #
+ __get_dockerfile_ver "$Dockerfile"
+ [ -n "$ENV_IMAGE_PUSH" ] && name="$(basename "${ENV_IMAGE_PUSH//:*/}")"
+ tag_version="${new_tag:-$set_newtag}"
+ tag_version="${tag_version,,}"
+ BUILDX_DEFAULT_VERSION="$tag_version"
+ #
+ if echo "$DockerfileName" | grep -q '[0-9]-dev'; then
+ BUILDX_DOCKERFILE_VERSION="$(echo "${DockerfileName//Dockerfile./}" | sed 's| ||g')"
+ else
+ BUILDX_DOCKERFILE_VERSION="$(echo "$DockerfileName" | sed 's|[a-zA-Z]||g;s| ||g' | grep '[0-9]')"
+ fi
+ if [ -z "$BUILDX_DOCKERFILE_VERSION" ]; then
+ BUILDX_FAILED_LOG="${BUILDX_FAILED_LOG:-$BUILDX_CWD/.build_failed}"
+ else
+ BUILDX_FAILED_LOG="${BUILDX_FAILED_LOG:-$BUILDX_CWD/.build_failed$BUILDX_DOCKERFILE_VERSION}"
+ fi
+ if [ "$(basename "$Dockerfile" 2>/dev/null)" = "Dockerfile" ] && [ "$tag_version" != "latest" ]; then
+ BUILDX_ADD_TAG="true"
+ BUILDX_VERSION_TAG="${BUILDX_VERSION_TAG},latest"
+ fi
+ if [ "$BUILDX_DEFAULT_REGISTRY" = "docker.io" ]; then
+ tagged_name="$BUILDX_DEFAULT_REPO/$name"
+ else
+ tagged_name="$BUILDX_DEFAULT_REGISTRY/$BUILDX_DEFAULT_REPO/$name"
+ fi
+ tagged_name="${tagged_name//\/dockerfile/}"
+ push_tag="$tagged_name:$tag_version"
+ set_tag="${push_tag//$BUILDX_DEFAULT_REGISTRY\//}"
+ logfolder="${BUILDX_CUSTOM_LOG_DIR:-/$BUILDX_DEFAULT_REGISTRY/$BUILDX_DEFAULT_LOG_ORG/$BUILDX_DEFAULT_LOG_REPO}"
+ logfile="${BUILDX_CUSTOM_LOG_FILE:-$BUILDX_CUSTOM_LOG_DIR/$(echo "$tagged_name" | awk -F':' '{print $1}').log}"
+ logscript_dir="$BUILDX_CONFIG_DIR/scripts/$(echo "$tagged_name" | awk -F '/' '{print $1}')"
+ logscript_file="$logscript_dir/$(echo "$tagged_name" | awk -F '/' '{print $2}')-${tag_version}.sh"
+ pretty_name="${set_tag/:*/}"
+ log_file_tag_name="$(echo "$push_tag" | awk -F ':' '{print $2}' | grep '^' || echo '')"
+ if [ -n "$log_file_tag_name" ]; then
+ logfile="$logfolder/$log_file_tag_name.log"
+ fi
+ if [ -n "$BUILDX_CUSTOM_LOG_RUNALL_DIR" ] && [ -n "$BUILDX_CUSTOM_LOG_RUNALL_FILE" ]; then
+ logfile="$BUILDX_CUSTOM_LOG_RUNALL_FILE"
+ logfolder="$BUILDX_CUSTOM_LOG_RUNALL_DIR"
+ fi
+ BUILDX_CUSTOM_LOG_FILE="$logfile"
+ BUILDX_CUSTOM_LOG_DIR="$logfolder"
+ if [ "$BUILDX_BUILD_ALL" != "true" ]; then
+ printf_blue "Log is being written to: ${logfile//$HOME/~}"
+ fi
+ [ -n "$Dockerfile" ] && printf_cyan "Setting Dockerfile to: ${Dockerfile//$PWD\//./}"
+ if [ -f "$Dockerfile" ]; then
+ [ -d "$FULL_DIR_PATH/rootfs" ] || mkdir -p "$FULL_DIR_PATH/rootfs"
+ fi
+ [ -d "$BUILDX_LOG_DIR/$logfolder" ] || mkdir -p "$BUILDX_LOG_DIR/$logfolder"
+ if __build_cmd "$FULL_DIR_PATH"; then
+ notify_message+="Successfully built $set_tag $ADDITIONAL_PRETTY|"
+ printf_green "Successfully built container: $set_tag $ADDITIONAL_PRETTY"
+ [ -f "$BUILDX_FAILED_LOG" ] && rm -Rf "$BUILDX_FAILED_LOG"
+ if [ "$BUILDX_NO_PULL" != "no" ]; then
+ printf '%b: ' "$(printf_green "Pulling the updated image")"
+ if __docker pull "$push_tag" &>/dev/null; then
+ printf_green "Successfully pulled $push_tag"
+ notify_message+="Successfully pulled $push_tag|"
+ printf '\n%s\n' "# Successfully pulled $push_tag on : $(date +'%Y-%m-%d at %H:%M')" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ __docker rmi "$push_tag" &>/dev/null
+ __docker rmi "$pretty_name" &>/dev/null
+ buildxexitCode=0
+ else
+ printf_red "Failed to pull $push_tag" >&2
+ notify_message+="Failed to pull $push_tag|"
+ printf '\n%s\n' "# Failed to pull $push_tag on : $(date +'%Y-%m-%d at %H:%M')" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ buildxexitCode=2
+ fi
+ fi
+ else
+ printf_red "Failed to build $push_tag" >&2
+ notify_message+="Failed to build $push_tag|"
+ buildxexitCode=10
+ fi
+ notify_message="$(echo "$notify_message" | tr '|' '\n')"
+ __notifications "${notify_message[@]}" &>/dev/null &
+ [ "$BUILDX_REMOTE_NOTIFY_ENABLED" = "yes" ] && [ -n "$BUILDX_REMOTE_NOTIFY_COMMAND" ] && eval $BUILDX_REMOTE_NOTIFY_COMMAND "${notify_message[@]}" &>/dev/null &
+ printf "# Exit status: %s\n" "$buildxexitCode" | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ printf '###############################################################################\n\n' | tee -p -a "$BUILDX_CUSTOM_LOG_FILE" &>/dev/null
+ [ -f "$BUILDX_PID_FILE" ] && rm -Rf "$BUILDX_PID_FILE"
+ [ "$buildxexitCode" = "1" ] && exitCode=0 || exitCode=$buildxexitCode
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__is_logged_in() {
+ __docker system info 2>&1 | grep -E 'Username|Registry' | grep -i "Username" | awk '{print $2}' | grep -q '^' &&
+ return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api() {
+ local repo
+ repo="$(__curl "https://hub.docker.com/v2/repositories/$BUILDX_DEFAULT_REPO/?page_size=1000" | __jq -r '.results|.[]|.name' | grep '^')"
+ [ -n "$repo" ] && echo "$repo" | grep -vE 'tools|templates|.docker' | grep '^' || exit 2
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_search() {
+ [ $# -eq 1 ] || return 1
+ local repo
+ repo="$(__curl "https://hub.docker.com/v2/repositories/$1/?page_size=1000" | __jq -r '.results|.[]|.name' | grep '^')"
+ [ -n "$repo" ] && echo "$repo" | grep -vE 'tools|templates|.docker' | grep '^' || exit 2
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_source() {
+ local list
+ list="$(__curl "https://api.github.com/orgs/${1:-$BUILDX_GIT_REPO_USER}/repos?per_page=1000" | __jq -r '.[].name' | grep '^')"
+ [ -n "$list" ] || list="$(__curl -q -LSsf "https://api.github.com/users/${1:-BUILDX_GIT_REPO_USER}/repos?per_page=1000" | __jq -r '.[].name' | grep '^')"
+ [ -n "$list" ] && echo "$list" | grep -vE 'tools|templates|.github' | grep '^' || exit 2
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_clone() {
+ local repos git_url
+ [ "$1" = "all" ] && repos="$(__api_source "$BUILDX_GIT_REPO_USER")" || repos="$(__api_source "$BUILDX_GIT_REPO_USER" | grep "$1" | head -n1)"
+ git_url="${2:-$BUILDX_GIT_REPO_PROVIDER/$BUILDX_GIT_REPO_USER}"
+ [ -n "$repo" ] || exit 2
+ [ -n "$git_url" ] || exit 2
+ for repo in $repos; do
+ gitadmin clone "$git_url/$repo"
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__buildx_all() {
+ local statusCode=0
+ local dockerfiles=""
+ BUILDX_RUN_COUNT_OF="0"
+ BUILDX_RUN_COUNT_TOTAL="$(ls -A "$BUILDX_CWD/Dockerfile"* 2>/dev/null | wc -l)"
+ BUILDX_FAILED_EXISTS="$(ls -A "$BUILDX_CWD/.build_failed"* 2>/dev/null | wc -l)"
+ [ "$BUILDX_FAILED_EXISTS" -eq 0 ] && export BUILDX_FAILED_EXISTS="false" || BUILDX_FAILED_EXISTS="true"
+ export BUILDX_GIT_COMMIT_ID="${BUILDX_GIT_COMMIT_ID:-}"
+ if [ ! -d "$BUILDX_CWD" ]; then
+ printf_exit "Usage: $APPNAME [dir] all"
+ elif [ "$BUILDX_RUN_COUNT_TOTAL" -eq 0 ]; then
+ printf_exit "The doesn't seem to be any Dockerfiles in $BUILDX_CWD"
+ fi
+ __run_git_pull "$BUILDX_CWD"
+ printf_cyan "Building all Dockerfiles in $BUILDX_CWD"
+ for file in $(ls -Avr "$BUILDX_CWD/Dockerfile"* 2>/dev/null); do
+ buildCode=0
+ file="$(realpath "$file" 2>/dev/null | grep '^' || echo '')"
+ [ -n "$file" ] && [ -f "$file" ] || buildCode=1
+ if [ $buildCode -eq 0 ]; then
+ export BUILDX_RUN_COUNT_TOTAL="${BUILDX_RUN_COUNT_TOTAL:-1}" BUILDX_GIT_COMMIT_ID="$BUILDX_GIT_COMMIT_ID"
+ export BUILDX_RUN_COUNT_OF=$((BUILDX_RUN_COUNT_OF + 1)) BUILDX_BUILD_ALL="true" BUILDX_GEN_SCRIPT="${BUILDX_GEN_SCRIPT:-}"
+ $0 --dir "$BUILDX_CWD" run "$file" || statusCode=$((statusCode + 1))
+ else
+ printf_return "Can not find Dockerfile in $BUILDX_CWD"
+ fi
+ done
+ BUILDX_FAILED_EXISTS="$(ls -A "$BUILDX_CWD/.build_failed"* 2>/dev/null | wc -l)"
+ [ "$BUILDX_FAILED_EXISTS" -eq 0 ] && export BUILDX_FAILED_EXISTS="false" || export BUILDX_FAILED_EXISTS="true"
+ [ "$BUILDX_GEN_SCRIPT" = "true" ] && exit_message_good="Finished generating the build scripts" || exit_message_good="Finished building all Dockerfile in"
+ [ "$BUILDX_GEN_SCRIPT" = "true" ] && exit_message_error="Finished generating the build scripts with errors" || exit_message_error="Building has failed with errors"
+ if [ $statusCode -eq 0 ] || [ "$BUILDX_FAILED_EXISTS" = "false" ]; then
+ printf_blue "$exit_message_good $BUILDX_CWD"
+ statusCode=0
+ else
+ printf_red "$exit_message_error"
+ fi
+ __trap_timer
+ printf_yellow "Cleaning up containers"
+ printf_blue '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+ printf '\n'
+ return $statusCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__automate() {
+ local BUILDX_AUTOMATE_CWD="$(realpath "$1" 2>/dev/null)"
+ BUILDX_CWD="$BUILDX_AUTOMATE_CWD"
+ [ -f "$BUILDX_AUTOMATE_CWD" ] && BUILDX_AUTOMATE_CWD="$(dirname "$BUILDX_AUTOMATE_CWD" 2>/dev/null)"
+ [ -d "$BUILDX_AUTOMATE_CWD" ] && BUILDX_AUTOMATE_CWD="${BUILDX_AUTOMATE_CWD:-$PWD}" || { printf_red "Usage: $APPNAME cron [dir]" && return 1; }
+ __buildx_all "$BUILDX_AUTOMATE_CWD"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_git_pull() {
+ local commit_cur="" commit_new="" dir=""
+ [ -z "$BUILDX_GIT_COMMIT_ID" ] || return 0
+ dir="$(realpath "${1:-$BUILDX_CWD}" 2>/dev/null || echo "${1:-$BUILDX_CWD}")"
+ [ -d "$dir/.git" ] || return 1
+ commit_cur="$(git -C "$dir" log 2>/dev/null | head -n1 | tr ' ' '\n' | grep '[0-9].*[0-9].*[a-z]' || false)"
+ printf_cyan "Attempting to update repo in $dir"
+ git -C "$dir" pull -q &>/dev/null
+ commit_new="$(git -C "$dir" log 2>/dev/null | head -n1 | tr ' ' '\n' | grep '[0-9].*[0-9].*[a-z]' || false)"
+ [ -n "$commit_cur" ] && [ -n "$commit_new" ] || { printf_red "Failed to get the git commit history" && return 1; }
+ if [ "$commit_cur" = "$commit_new" ]; then
+ printf_cyan "No commit changes detected! commit id: $commit_cur"
+ else
+ printf_cyan "Updated to commit: $commit_new"
+ fi
+ export BUILDX_GIT_COMMIT_ID="${commit_new:-$commit_cur}"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+BUILDX_FORCE="${BUILDX_FORCE:-}"
+BUILDX_REMOVE_BUILD="${BUILDX_REMOVE_BUILD:-}"
+BUILDX_DEFAULT_REPO="${BUILDX_DEFAULT_REPO:-}"
+BUILDX_GIT_REPO_USER="${BUILDX_GIT_REPO_USER:-}"
+BUILDX_DEFAULT_VERSION="${BUILDX_DEFAULT_VERSION:-latest}"
+BUILDX_DEFAULT_REGISTRY="${BUILDX_DEFAULT_REGISTRY:-docker.io}"
+BUILDX_BUILDER_NAME="${BUILDX_BUILDER_NAME:-mybuilder}"
+BUILDX_GIT_REPO_PROVIDER="${BUILDX_GIT_REPO_PROVIDER:-http://github.com}"
+BUILDX_PROJECT_DIR="${BUILDX_PROJECT_DIR:-$HOME/Projects/github}"
+BUILDX_DOCKER_PLATFORMS="${DOCKER_PLATFORMS:-}"
+BUILDX_DOCKER_BUILD_EXPERIMENTAL="${BUILDX_EXPERIMENTAL:-1}"
+BUILDX_DOCKER_CLI_EXPERIMENTAL="${DOCKER_CLI_EXPERIMENTAL:-enabled}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+BUILDX_CONFIG_FILE="${BUILDX_CONFIG_FILE:-settings.conf}"
+BUILDX_CONFIG_DIR="${BUILDX_CONFIG_DIR:-$HOME/.config/myscripts/buildx}"
+BUILDX_CONFIG_BACKUP_DIR="${BUILDX_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/buildx/backups}"
+BUILDX_LOG_DIR="${BUILDX_LOG_DIR:-$HOME/.local/log/buildx}"
+BUILDX_TEMP_DIR="${BUILDX_TEMP_DIR:-$HOME/.local/tmp/system_scripts/buildx}"
+BUILDX_CACHE_DIR="${BUILDX_CACHE_DIR:-$HOME/.cache/buildx}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+BUILDX_OUTPUT_COLOR_1="${BUILDX_OUTPUT_COLOR_1:-33}"
+BUILDX_OUTPUT_COLOR_2="${BUILDX_OUTPUT_COLOR_2:-5}"
+BUILDX_OUTPUT_COLOR_GOOD="${BUILDX_OUTPUT_COLOR_GOOD:-2}"
+BUILDX_OUTPUT_COLOR_ERROR="${BUILDX_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+BUILDX_NOTIFY_ENABLED="${BUILDX_NOTIFY_ENABLED:-yes}"
+BUILDX_GOOD_NAME="${BUILDX_GOOD_NAME:-Great:}"
+BUILDX_ERROR_NAME="${BUILDX_ERROR_NAME:-Error:}"
+BUILDX_GOOD_MESSAGE="${BUILDX_GOOD_MESSAGE:-No errors reported}"
+BUILDX_ERROR_MESSAGE="${BUILDX_ERROR_MESSAGE:-Errors were reported}"
+BUILDX_NOTIFY_CLIENT_NAME="${BUILDX_NOTIFY_CLIENT_NAME:-$APPNAME}"
+BUILDX_NOTIFY_CLIENT_ICON="${BUILDX_NOTIFY_CLIENT_ICON:-notification-new}"
+BUILDX_NOTIFY_CLIENT_URGENCY="${BUILDX_NOTIFY_CLIENT_URGENCY:-normal}"
+BUILDX_REMOTE_NOTIFY_ENABLED="${BUILDX_REMOTE_NOTIFY_ENABLED:-yes}"
+BUILDX_REMOTE_NOTIFY_COMMAND="${BUILDX_REMOTE_NOTIFY_COMMAND:-web-notify telegram}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+REGISTRY_TAG=""
+BUILDX_ADD_REPO=""
+BUILDX_IS_RUNNING=""
+BUILDX_CLEANUP="true"
+BUILDX_AUTO_VERSION=""
+BUILDX_ADD_REGISTRY=""
+BUILDX_SET_PLATFORM=""
+BUILDX_RUN_SCRIPT="false"
+BUILDX_ENABLE_REGISTRY="false"
+BUILDX_DOCKER_CMD="${BUILDX_DOCKER_CMD:-docker}"
+BUILDX_BUILD_DATE_TAG_FORMAT="${BUILDX_BUILD_DATE_TAG_FORMAT:-%y%m}"
+BUILDX_DOCKER_PLATFORMS="${BUILDX_DOCKER_PLATFORMS:-linux/amd64,linux/arm64}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$BUILDX_CONFIG_DIR/$BUILDX_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$BUILDX_CONFIG_DIR/$BUILDX_CONFIG_FILE" ] && . "$BUILDX_CONFIG_DIR/$BUILDX_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$BUILDX_LOG_DIR" ] || mkdir -p "$BUILDX_LOG_DIR" |& __devnull
+[ -d "$BUILDX_TEMP_DIR" ] || mkdir -p "$BUILDX_TEMP_DIR" |& __devnull
+[ -d "$BUILDX_CACHE_DIR" ] || mkdir -p "$BUILDX_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+BUILDX_TEMP_FILE="${BUILDX_TEMP_FILE:-$(mktemp $BUILDX_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit;exit $?' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$BUILDX_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$BUILDX_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$BUILDX_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$BUILDX_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$BUILDX_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$BUILDX_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ retval=$?
+ return $retval
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent,no-pull"
+LONGOPTS+=",force,cleanup,add-registry:,repo:,no-registry,no-repo,cron,platform:"
+LONGOPTS+=",gen-script,tag:,add-tag:,all,build,url:,script,init,user:,image:,registry:"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="all run[Dockerfile] init status version api[tags,list,search,sources,clone,delete,update] "
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ BUILDX_SILENT="true"
+ ;;
+ --dir)
+ export CWD_IS_SET="TRUE"
+ export BUILDX_CWD="$2"
+ [ -d "$BUILDX_CWD" ] || mkdir -p "$BUILDX_CWD" |& __devnull
+ shift 2
+ ;;
+ --force)
+ shift 1
+ export BUILDX_FORCE="true"
+ ;;
+ --script)
+ shift 1
+ export BUILDX_RUN_SCRIPT="true"
+ ;;
+ --build)
+ shift 1
+ export BUILDX_ENABLED="no"
+ ;;
+ --init)
+ shift 1
+ export BUILDX_FORCE_REINSTALL="yes"
+ ;;
+ --no-registry)
+ shift 1
+ export BUILDX_ENABLE_REGISTRY="false"
+ export BUILDX_ADD_REGISTRY=""
+ ;;
+ --no-repo)
+ shift 1
+ export BUILDX_ADD_REPO=""
+ ;;
+ --cron)
+ shift 1
+ BUILDX_RUN_CRON="true"
+ ;;
+ --all)
+ shift 1
+ export BUILDX_ALL="true"
+ ;;
+ --gen-script)
+ shift 1
+ BUILDX_GEN_SCRIPT="true"
+ ;;
+ --cleanup)
+ shift 1
+ export BUILDX_CLEANUP="true"
+ ;;
+ --add-registry)
+ export BUILDX_ENABLE_REGISTRY="true"
+ export BUILDX_ADD_REGISTRY+="$2"
+ shift 2
+ ;;
+ --repo)
+ export BUILDX_ADD_TAG="true"
+ export BUILDX_ADD_REPO="$2"
+ shift 2
+ ;;
+ --platform)
+ [ "$2" = "x64" ] && BUILDX_SET_PLATFORM="linux/amd64" && shift 2
+ [ "$2" = "arm" ] && BUILDX_SET_PLATFORM="linux/arm/v7" && shift 2
+ [ "$2" = "arm64" ] && BUILDX_SET_PLATFORM="linux/arm64" && shift 2
+ export BUILDX_DOCKER_PLATFORMS="${BUILDX_SET_PLATFORM:-$2}"
+ printf_yellow "Setting platform to $BUILDX_DOCKER_PLATFORMS"
+ BUILDX_SET_PLATFORM=""
+ shift 2
+ ;;
+ --tag)
+ export BUILDX_AUTO_VERSION="false"
+ if echo "$2" | grep -q ':'; then
+ export BUILDX_SET_NAME="${2//:*/}"
+ export BUILDX_SET_VERSION="${2//*:/}"
+ else
+ export BUILDX_SET_VERSION="$2"
+ fi
+ export BUILDX_SET_VERSION="${2//,/ }"
+ shift 2
+ ;;
+ --image)
+ export BUILDX_SET_IMAGE="$2"
+ shift 2
+ ;;
+ --add-tag)
+ export BUILDX_VERSION_TAG="${2//,/ }"
+ shift 2
+ ;;
+ --url)
+ urls="${2//,/ }"
+ for url in $urls; do
+ if [ -n "$url" ]; then
+ export REGISTRY_TAG+="-t $url "
+ fi
+ done
+ unset url urls
+ shift 2
+ ;;
+ --user)
+ export BUILDX_SET_REPO="$2"
+ export BUILDX_SET_GIT_USER="$2"
+ shift 2
+ ;;
+ --registry)
+ BUILDX_SET_REGISTRY="$2"
+ shift 2
+ ;;
+ --no-pull)
+ shift 1
+ BUILDX_NO_PULL="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# BUILDX_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# BUILDX_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+[ -d "$1" ] && __is_an_option "$1" && BUILDX_CWD="$1" && shift 1 || BUILDX_CWD="${BUILDX_CWD:-$PWD}"
+BUILDX_CWD="$(realpath "${BUILDX_CWD:-$PWD}" 2>/dev/null)"
+if [ -d "$BUILDX_CWD" ] && cd "$BUILDX_CWD"; then
+ if [ "$BUILDX_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+ true
+ #printf_cyan "Setting working dir to $BUILDX_CWD"
+ fi
+else
+ printf_exit "💔 $BUILDX_CWD does not exist 💔"
+fi
+export BUILDX_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+if [ -f "${2:-$1}" ]; then
+ BUILDX_CWD="$(realpath "$(dirname "${2:-$1}")")"
+ BUILDX_SET_DEFAULT_VER="$(basename ${2:-$1} | sed 's|Dockerfile.||g' | grep '^' || echo '')"
+fi
+BUILDX_BUILDER_NAME_CUSTOM="$(basename "$BUILDX_CWD")"
+BUILDX_DEFAULT_LOG_ORG="$(basename "$(dirname "$(realpath "$BUILDX_CWD")")")"
+BUILDX_DEFAULT_LOG_REPO="$(basename "$(realpath "$BUILDX_CWD")" | sed 's|^docker-||g')"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+[ -f "$BUILDX_CWD/.env.scripts" ] && . "$BUILDX_CWD/.env.scripts"
+[ -n "$BUILDX_SET_DEFAULT_VER" ] && [ -f "$BUILDX_CWD/.env.scripts.$BUILDX_SET_DEFAULT_VER" ] && . "$BUILDX_CWD/.env.scripts.$BUILDX_SET_DEFAULT_VER"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+__set_variables
+__buildx_vars ${BUILDX_BUILDER_NAME_CUSTOM:-$BUILDX_BUILDER_NAME}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Export variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -d "$BUILDX_CUSTOM_LOG_DIR" ] || mkdir -p "$BUILDX_CUSTOM_LOG_DIR"
+[ -d "$HOME/.local/run/$APPNAME" ] || mkdir -p "$HOME/.local/run/$APPNAME"
+[ -d "$BUILDX_CONFIG_DIR/scripts" ] || mkdir -p "$BUILDX_CONFIG_DIR/scripts"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+init)
+ shift
+ __buildx_init "$@"
+ exit $?
+ ;;
+
+status)
+ shift 1
+ if [ $# -eq 0 ]; then
+ __buildx_status && printf_blue "BuildX is running" || printf_red "buildx is not running"
+ else
+ __buildx_status "$@" | printf_readline "4"
+ fi
+ exit $?
+ ;;
+
+version)
+ __qemu_version
+ __docker_version
+ __binfmt_version
+ __buildx_version
+ exit 0
+ ;;
+
+api)
+ shift 1
+ case "$1" in
+ tags)
+ shift 1
+ [ "$1" = "help" ] && printf_help "usage: $APPNAME api tags [repo/image] [registry]"
+ __get_tags "$@"
+ exit $?
+ ;;
+ list)
+ shift 1
+ [ "$1" = "help" ] && printf_help "usage: $APPNAME api list repo"
+ __api | grep "${1:-^}"
+ exit $?
+ ;;
+ search)
+ shift 1
+ [ "$1" = "help" ] && printf_help "usage: $APPNAME api search repo"
+ __api_search "${1:-docker}"
+ exit $?
+ ;;
+ sources)
+ shift 1
+ [ "$1" = "help" ] && printf_help "usage: $APPNAME api sources repo"
+ __api_source | grep "${1:-^}"
+ exit $?
+ ;;
+ clone)
+ shift 1
+ [ "$1" = "help" ] && printf_help "usage: $APPNAME api clone repo [Base user repo]"
+ __api_clone "${@:-all}"
+ exit $?
+ ;;
+ delete)
+ shift 1
+ __orgs_api_delete "$@"
+ exit $?
+ ;;
+ update)
+ shift 1
+ __orgs_api_update "$@"
+ ;;
+ *)
+ printf_help "usage: $APPNAME api [tags|list|search|sources|clone|delete|update] [help]"
+ exit 1
+ ;;
+ esac
+ ;;
+
+automated | cron)
+ shift 1
+ exitCode=0
+ if [ $# -eq 0 ] && [ -d "$BUILDX_PROJECT_DIR" ]; then
+ for projectDir in $BUILDX_PROJECT_DIR/*; do
+ if [ -d "$projectDir" ]; then
+ __automate "$projectDir"
+ exitCode=$((1 + exitCode))
+ else
+ printf '%s\n' "$projectDir is not a directory"
+ exitCode=$((1 + exitCode))
+ fi
+ done
+ elif [ $# -ne 0 ]; then
+ for projectDir in "$@"; do
+ if [ -d "$projectDir" ]; then
+ __automate "$projectDir"
+ exitCode=$((1 + exitCode))
+ else
+ printf '%s\n' "$projectDir is not a directory"
+ exitCode=$((1 + exitCode))
+ fi
+ done
+ fi
+ exit $exitCode
+ ;;
+
+all)
+ shift 1
+ __buildx_all "$@"
+ exit $?
+ ;;
+
+run)
+ shift 1
+ __run_all "$@"
+ ;;
+
+build)
+ shift 1
+ runAllCode=0
+ BUILDX_BUILD_FILES="$*"
+ for i in ${BUILDX_BUILD_FILES:-BUILDX_CWD}; do
+ __buildx_run "$i"
+ ec=$?
+ runAllCode=$(($ec + $runAllCode))
+ done
+ exitCode="$runAllCode"
+ ;;
+*)
+ runAllCode=0
+ BUILDX_BUILD_FILES="$*"
+ for i in ${BUILDX_BUILD_FILES:-BUILDX_CWD}; do
+ __buildx_run "$i"
+ ec=$?
+ runAllCode=$(($ec + $runAllCode))
+ done
+ exitCode="$runAllCode"
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/calc b/bin/calc
new file mode 100755
index 000000000..ae21fda48
--- /dev/null
+++ b/bin/calc
@@ -0,0 +1,571 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042133-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : calc --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 21:33 EDT
+# @@File : calc
+# @@Description : wrapper for qalc/bc
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042133-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CALC_REQUIRE_SUDO="${CALC_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CALC_CONFIG_DIR/$CALC_CONFIG_FILE"
+ fi
+ [ -d "$CALC_CONFIG_DIR" ] || mkdir -p "$CALC_CONFIG_DIR"
+ [ -d "$CALC_CONFIG_BACKUP_DIR" ] || mkdir -p "$CALC_CONFIG_BACKUP_DIR"
+ [ -f "$CALC_CONFIG_DIR/$CALC_CONFIG_FILE" ] &&
+ cp -Rf "$CALC_CONFIG_DIR/$CALC_CONFIG_FILE" "$CALC_CONFIG_BACKUP_DIR/$CALC_CONFIG_FILE.$$"
+ cat <"$CALC_CONFIG_DIR/$CALC_CONFIG_FILE"
+# Settings for calc
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CALC_OUTPUT_COLOR_1="${CALC_OUTPUT_COLOR_1:-}"
+CALC_OUTPUT_COLOR_2="${CALC_OUTPUT_COLOR_2:-}"
+CALC_OUTPUT_COLOR_GOOD="${CALC_OUTPUT_COLOR_GOOD:-}"
+CALC_OUTPUT_COLOR_ERROR="${CALC_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CALC_NOTIFY_ENABLED="${CALC_NOTIFY_ENABLED:-}"
+CALC_GOOD_NAME="${CALC_GOOD_NAME:-}"
+CALC_ERROR_NAME="${CALC_ERROR_NAME:-}"
+CALC_GOOD_MESSAGE="${CALC_GOOD_MESSAGE:-}"
+CALC_ERROR_MESSAGE="${CALC_ERROR_MESSAGE:-}"
+CALC_NOTIFY_CLIENT_NAME="${CALC_NOTIFY_CLIENT_NAME:-}"
+CALC_NOTIFY_CLIENT_ICON="${CALC_NOTIFY_CLIENT_ICON:-}"
+CALC_NOTIFY_CLIENT_URGENCY="${CALC_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CALC_CONFIG_DIR/$CALC_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CALC_CONFIG_DIR/$CALC_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "calc: wrapper for qalc/bc - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: calc [options] [arithmetic]"
+ __printf_line "[8x8+4-1/3] - Preform calculation"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CALC_REQUIRE_SUDO" = "yes" ] && [ -z "$CALC_REQUIRE_SUDO_RUN" ]; then
+ export CALC_REQUIRE_SUDO="no"
+ export CALC_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CALC_TEMP_FILE" ] && rm -Rf "$CALC_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__usage() {
+ printf_cyan 'Usage: "20 * 4/2 + 23 - 14"'
+ printf_red "press q to exit"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_calc() {
+ local answer=
+ if [[ ${#CALC_OUTPUT} -ne 0 ]]; then
+ if cmd_exists bc; then
+ answer="$(echo "$CALC_INPUT = $(echo "$CALC_OUTPUT" | bc -q 2>/dev/null)")"
+ elif cmd_exists qalc; then
+ answer="$(qalc "$CALC_OUTPUT" 2>/dev/null)"
+ else
+ printf_exit "Can't find a calculator app!"
+ fi
+ fi
+ [ -z "$answer" ] && exitCode=1 || echo "$answer"
+ if [ "$CALC_NOTIFY_ENABLED" = yes ]; then __notifications "Calc" "Answer to: $answer"; fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__term() {
+ trap '$APPNAME --term' SIGINT
+ clear
+ printf_newline "\n\n"
+ __usage
+ while :; do
+ printf_read_input "2" "What is it you would like to solve?" "200" "CALC_INPUT" "-e"
+ if [ "$CALC_INPUT" = "q" ] || [ -z "$CALC_INPUT" ]; then
+ printf_newline "\n"
+ break
+ else
+ clear
+ printf_newline "\n\n\n"
+ if [ "$CALC_INPUT" = "h" ] || [ "$CALC_INPUT" = "?" ]; then
+ __usage
+ else
+ CALC_OUTPUT="$(echo "$CALC_INPUT" | sed '/^$/d;s/[[:blank:]]//g')"
+ __execute_calc "$CALC_OUTPUT" | printf_readline "5"
+ fi
+ printf_newline
+ fi
+ done
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CALC_CONFIG_FILE="${CALC_CONFIG_FILE:-settings.conf}"
+CALC_CONFIG_DIR="${CALC_CONFIG_DIR:-$HOME/.config/myscripts/calc}"
+CALC_CONFIG_BACKUP_DIR="${CALC_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/calc/backups}"
+CALC_LOG_DIR="${CALC_LOG_DIR:-$HOME/.local/log/calc}"
+CALC_TEMP_DIR="${CALC_TEMP_DIR:-$HOME/.local/tmp/system_scripts/calc}"
+CALC_CACHE_DIR="${CALC_CACHE_DIR:-$HOME/.cache/calc}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CALC_OUTPUT_COLOR_1="${CALC_OUTPUT_COLOR_1:-33}"
+CALC_OUTPUT_COLOR_2="${CALC_OUTPUT_COLOR_2:-5}"
+CALC_OUTPUT_COLOR_GOOD="${CALC_OUTPUT_COLOR_GOOD:-2}"
+CALC_OUTPUT_COLOR_ERROR="${CALC_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CALC_NOTIFY_ENABLED="${CALC_NOTIFY_ENABLED:-yes}"
+CALC_GOOD_NAME="${CALC_GOOD_NAME:-Great:}"
+CALC_ERROR_NAME="${CALC_ERROR_NAME:-Error:}"
+CALC_GOOD_MESSAGE="${CALC_GOOD_MESSAGE:-No errors reported}"
+CALC_ERROR_MESSAGE="${CALC_ERROR_MESSAGE:-Errors were reported}"
+CALC_NOTIFY_CLIENT_NAME="${CALC_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CALC_NOTIFY_CLIENT_ICON="${CALC_NOTIFY_CLIENT_ICON:-notification-new}"
+CALC_NOTIFY_CLIENT_URGENCY="${CALC_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CALC_CONFIG_DIR/$CALC_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CALC_CONFIG_DIR/$CALC_CONFIG_FILE" ] && . "$CALC_CONFIG_DIR/$CALC_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CALC_LOG_DIR" ] || mkdir -p "$CALC_LOG_DIR" |& __devnull
+[ -d "$CALC_TEMP_DIR" ] || mkdir -p "$CALC_TEMP_DIR" |& __devnull
+[ -d "$CALC_CACHE_DIR" ] || mkdir -p "$CALC_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CALC_TEMP_FILE="${CALC_TEMP_FILE:-$(mktemp $CALC_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CALC_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CALC_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CALC_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CALC_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CALC_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CALC_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=",term"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CALC_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ CALC_CWD="$2"
+ [ -d "$CALC_CWD" ] || mkdir -p "$CALC_CWD" |& __devnull
+ shift 2
+ ;;
+ --term)
+ shift 1
+ TERMINAL_APP="yes"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CALC_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CALC_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CALC_CWD="$1" && shift 1 || CALC_CWD="${CALC_CWD:-$PWD}"
+CALC_CWD="$(realpath "${CALC_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CALC_CWD" ] && cd "$CALC_CWD"; then
+# if [ "$CALC_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CALC_CWD"
+# fi
+# else
+# printf_exit "💔 $CALC_CWD does not exist 💔"
+# fi
+export CALC_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+CALC_INPUT="$*"
+CALC_OUTPUT="$(echo "$CALC_INPUT" | sed '/^$/d;s/[[:blank:]]//g' 2>/dev/null)"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+if [ -n "$TERMINAL_APP" ]; then
+ __term
+elif [ $# = 0 ]; then
+ $APPNAME --term
+else
+ __execute_calc | printf_readline "2"
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/calendar b/bin/calendar
new file mode 100755
index 000000000..86f32aa36
--- /dev/null
+++ b/bin/calendar
@@ -0,0 +1,939 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042138-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : calendar --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 21:38 EDT
+# @@File : calendar
+# @@Description : Bash calendar script
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource : https://github.com/coreymwamba/estonta
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042138-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CALENDAR_REQUIRE_SUDO="${CALENDAR_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CALENDAR_CONFIG_DIR/$CALENDAR_CONFIG_FILE"
+ fi
+ [ -d "$CALENDAR_CONFIG_DIR" ] || mkdir -p "$CALENDAR_CONFIG_DIR"
+ [ -d "$CALENDAR_CONFIG_BACKUP_DIR" ] || mkdir -p "$CALENDAR_CONFIG_BACKUP_DIR"
+ [ -f "$CALENDAR_CONFIG_DIR/$CALENDAR_CONFIG_FILE" ] &&
+ cp -Rf "$CALENDAR_CONFIG_DIR/$CALENDAR_CONFIG_FILE" "$CALENDAR_CONFIG_BACKUP_DIR/$CALENDAR_CONFIG_FILE.$$"
+ cat <"$CALENDAR_CONFIG_DIR/$CALENDAR_CONFIG_FILE"
+# Settings for calendar
+CALENDER_EVENT_DIR="${CALENDER_EVENT_DIR:-}"
+CALENDER_HOMETOWN="${CALENDER_HOMETOWN:-}"
+CALENDER_HOMECOUNTRY="${CALENDER_HOMECOUNTRY:-}"
+CALENDER_DATEFORMAT="${CALENDER_DATEFORMAT:-}"
+CALENDER_TAGS=${CALENDER_TAGS:-}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CALENDAR_OUTPUT_COLOR_1="${CALENDAR_OUTPUT_COLOR_1:-}"
+CALENDAR_OUTPUT_COLOR_2="${CALENDAR_OUTPUT_COLOR_2:-}"
+CALENDAR_OUTPUT_COLOR_GOOD="${CALENDAR_OUTPUT_COLOR_GOOD:-}"
+CALENDAR_OUTPUT_COLOR_ERROR="${CALENDAR_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CALENDAR_NOTIFY_ENABLED="${CALENDAR_NOTIFY_ENABLED:-}"
+CALENDAR_GOOD_NAME="${CALENDAR_GOOD_NAME:-}"
+CALENDAR_ERROR_NAME="${CALENDAR_ERROR_NAME:-}"
+CALENDAR_GOOD_MESSAGE="${CALENDAR_GOOD_MESSAGE:-}"
+CALENDAR_ERROR_MESSAGE="${CALENDAR_ERROR_MESSAGE:-}"
+CALENDAR_NOTIFY_CLIENT_NAME="${CALENDAR_NOTIFY_CLIENT_NAME:-}"
+CALENDAR_NOTIFY_CLIENT_ICON="${CALENDAR_NOTIFY_CLIENT_ICON:-}"
+CALENDAR_NOTIFY_CLIENT_URGENCY="${CALENDAR_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CALENDAR_CONFIG_DIR/$CALENDAR_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CALENDAR_CONFIG_DIR/$CALENDAR_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "calendar: Bash calendar script - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: calendar [options] [commands]"
+ __printf_line "add - Add an event"
+ __printf_line "category - Search by categories"
+ __printf_line "summary - Search by summery"
+ __printf_line "date - Search by date"
+ __printf_line "find - Search for an event"
+ __printf_line "list - List events"
+ __printf_line "gui - GUI interface to add events"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CALENDAR_REQUIRE_SUDO" = "yes" ] && [ -z "$CALENDAR_REQUIRE_SUDO_RUN" ]; then
+ export CALENDAR_REQUIRE_SUDO="no"
+ export CALENDAR_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CALENDAR_TEMP_FILE" ] && rm -Rf "$CALENDAR_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__welcome() {
+ __show_date
+ if [ $# = 0 ]; then
+ printf_cyan "list - Show all events"
+ printf_cyan "add - Add event in console."
+ printf_cyan "gui - Graphical calendar display of events (can also add events)."
+ printf_cyan "category=TEXT - List all saved events filtered by category."
+ printf_cyan "summary=TEXT - List all saved events filtered by summary."
+ printf_cyan "date=DATE_STRING - Find events matching the date string."
+ printf_cyan "find START_DATE_STRING END_DATE_STRING - Find events within a date range."
+ printf_blue "You can type exit or q to exit"
+ printf_read_cal "5" "What would you like to do? " "main"
+ { [ "$main" = "q" ] || [ "$main" = "exit" ] || [ "$main" = "!q" ]; } && exit
+ printf_newline
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+initialize() {
+ [ -f "$CALENDER_EVENT_DIR" ] && __rm_rf "$CALENDER_EVENT_DIR"
+ if [ ! -d "$CALENDER_EVENT_DIR" ]; then
+ mkdir -p "$CALENDER_EVENT_DIR" &>/dev/null
+ printf_green "New directory created at $CALENDER_EVENT_DIR."
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+printf_read_cal() {
+ test -n "$1" && test -z "${1//[0-9]/}" && local color="$1" && shift 1 || local color="1"
+ local msg="$1" && shift 1
+ local reply="${1:-REPLY}" && shift 1
+ printf_color "$msg " "${PRINTF_COLOR:-$color}"
+ read ${reply:-} || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+containsElement() {
+ local e
+ for e in "${@:2}"; do [ "$e" == "$1" ] && return 0; done
+ return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+generate_fields() {
+ files="$(find "${1:-$CALENDER_EVENT_DIR}" -name '*.ics' 2>/dev/null | grep '^' || echo '')"
+ icalarray=("DTSTART" "SUMMARY" "LOCATION" "DESCRIPTION" "CATEGORIES")
+ while read line; do
+ IFS=':' read -r calname string <<<"$line"
+ containsElement "${calname}" "${icalarray[@]}"
+ [ $? -eq 0 ] && printf -v '%s %s' "$calname" "$string"
+ done <"$LERTA"
+ #iCalendar date format -> something that `date` can read. Sure there is an easier way, but I don't know it
+ DTSTART="$(echo ${DTSTART%Z} | sed -e 's/.\{4\}/&-/' | sed -e 's/.\{7\}/&-/' | sed -e 's/.\{13\}/&:/' | sed -e 's/.\{16\}/&:/' 2>/dev/null)"
+ THEDATE="$(date -d $DTSTART +"$CALENDER_DATEFORMAT" 2>/dev/null)"
+ #possibly inefficient, but bulletproof
+ desc="$(cat "$LERTA" | grep -v "DTSTART" | grep -v "CATEGORIES" | grep -v "SUMMARY" | grep -v "END" | grep -v "LOCATION" | grep -v "DTEND" | sed -r 's/\\n/\n/g' | sed -r 's/(\\)//g' 2>/dev/null)"
+ desc="${desc/DESCRIPTION:/}"
+ startdate="$THEDATE"
+ title="$SUMMARY"
+ location="$LOCATION"
+ category="$CATEGORIES"
+ # Format output
+ [ -n "$startdate" ] && DATETIME="$startdate"
+ [ -n "$title" ] && TITLE=" - $title"
+ [ -n "$desc" ] && DESC=" - $desc"
+ [ -n "$location" ] && LOC=" - $location"
+ [ -n "$category" ] && CATEG=" - ($category)"
+ #CALENDER_TERSE="$startdate - $title"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+find_appointments() {
+ local files=""
+ files="$(find "$CALENDER_EVENT_DIR" -name '*.ics' 2>/dev/null | grep '^' || echo '')"
+ if [ -z "$files" ]; then
+ printf_red "No events found"
+ exit 1
+ else
+ needle="$(date -I -d "$DATEFILE" 2>/dev/null)"
+ for found in $(grep -lr --include '*.ics' $needle $CALENDER_EVENT_DIR); do
+ list_appointment
+ done
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+date_range() {
+ # SO - http://stackoverflow.com/questions/28226229/bash-looping-through-dates
+ sdr="$(date -I -d "$sdr" 2>/dev/null)" || exit 1
+ edr="$(date -I -d "$edr" 2>/dev/null)" || exit 1
+ DATEFILE="$sdr"
+ while [ "$(date -d "$DATEFILE" +%Y%m%d 2>/dev/null)" -le "$(date -d "$edr" +%Y%m%d 2>/dev/null)" ]; do
+ find_appointments
+ DATEFILE="$(date -I -d "$DATEFILE + 1 day" 2>/dev/null)"
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+list_appointment() {
+ local files=""
+ files="$(find "$CALENDER_EVENT_DIR" -name '*.ics' 2>/dev/null | grep '^' || echo '')"
+ if [ -z "$files" ]; then
+ printf_red "No events found"
+ exit 1
+ else
+ for file in $files; do
+ tail -n +7 "$files" >"$LERTA"
+ generate_fields "$file"
+ printf '%s %s %s %s' "${DATETIME:-$startdate}" "${TITLE:-$title}" "${DESC:-$desc}" "${LOC:-$location}"
+ done
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+list_all() {
+ initialize
+ local files=""
+ files="$(find "$CALENDER_EVENT_DIR" -name '*.ics' 2>/dev/null | sort | grep '^' || echo '')"
+ if [ -z "$files" ]; then
+ printf_red "No events found"
+ exit 1
+ else
+ for file in $files; do
+ tail -n +7 "$file" >$LERTA
+ generate_fields "$file"
+ printf '%s %s %s %s\n' "${DATETIME:-$startdate}" "${TITLE:-$title}" "${DESC:-$desc}" "${LOC:-$location}"
+ done
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+tagordo() {
+ local files=""
+ files="$(find "$CALENDER_EVENT_DIR" -name '*.ics' 2>/dev/null | grep '^' || echo '')"
+ if [ -z "$files" ]; then
+ printf_red "No events found"
+ exit 1
+ else
+ for file in $files; do
+ tail -n +7 $file >$LERTA
+ generate_fields "$file"
+ printf_green "$(date -d $DTSTART +"%Y-%m-%d" 2>/dev/null) $SUMMARY ($(date -d $DTSTART +"%-l:%M%P" 2>/dev/null))"
+ done
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+list_by_cat() {
+ local files=""
+ files="$(find "$CALENDER_EVENT_DIR" -name '*.ics' 2>/dev/null | grep '^' || echo '')"
+ if [ -z "$files" ]; then
+ printf_red "No events found"
+ exit 1
+ else
+ for file in $files; do
+ tail -n +7 $file >$LERTA
+ generate_fields "$file"
+ if [ "$CATEGORIES" == "$FILTER" ]; then
+ printf '%s %s %s %s\n' "${DATETIME:-$startdate}" "${TITLE:-$title}" "${DESC:-$desc}" "${LOC:-$location}"
+ fi
+ done
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+list_by_text() {
+ local files=""
+ files="$(find "$CALENDER_EVENT_DIR" -name '*.ics' 2>/dev/null | grep '^' || echo '')"
+ if [ -z "$files" ]; then
+ printf_red "No events found"
+ exit 1
+ else
+ for file in $files; do
+ tail -n +5 $file >$LERTA
+ generate_fields "$file"
+ if [[ "$SUMMARY" =~ ${FILTER} ]]; then
+ printf '%s %s %s %s\n' "${DATETIME:-$startdate}" "${TITLE:-$title}" "${DESC:-$desc}" "${LOC:-$location}"
+ fi
+ done
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+join_strings() {
+ local d=$1
+ shift
+ echo -n "$1"
+ shift
+ printf "%s" "${@/#/$d}"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+shell_generate_ical() {
+ newfile="$CALENDER_EVENT_DIR/$(date -Iminutes -d "$sdt" 2>/dev/null | tr -d ':').ics"
+ # simple anti-clash mechanism
+ if [ -f $newfile ]; then
+ printf_red "You have something on this day at that time already..."
+ estonta
+ exit 1
+ fi
+ touch "$newfile"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+populate_ical() {
+ vcst="BEGIN:VCALENDAR"
+ vcv="VERSION:2.0"
+ vcp="PRODID:-//Estonta/ical//NONSGML v1.0//EN"
+ vcuid="UID:$(date -Iminutes -d "$sdt" 2>/dev/null | tr -d ':')@$(hostname)"
+ dtstamp="DTSTAMP:$(date +"%Y%m%dT%H%M%SZ" 2>/dev/null)"
+ vevst="BEGIN:VEVENT"
+ veven="END:VEVENT"
+ echo $vcst >>$newfile
+ echo $vcv >>$newfile
+ echo $vcp >>$newfile
+ echo $vevst >>$newfile
+ echo $vcuid >>$newfile
+ echo $dtstamp >>$newfile
+ echo "DTSTART:$dtstart" >>$newfile
+ [ -n "$location" ] && echo "LOCATION:${location}" >>$newfile
+ [ -n "$summary" ] && echo "SUMMARY:$summary" >>$newfile
+ [ -n "$category" ] && echo "CATEGORIES:$category" >>$newfile
+ [ -n "$desc" ] && echo "DESCRIPTION:$desc" | tr '\n' '\t' | awk '{gsub(/\,/,"\\,",$0)} {gsub(/\;/, "\\;",$0)} {gsub(/\t/,"\\n",$0) } {print $0}' | fold -b -s -w 75 >>$newfile 2>/dev/null
+ echo -e $veven >>$newfile
+ echo "END:VCALENDAR" >>$newfile
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+text_add_event() {
+ initialize
+ printf_read_cal "4" "[Format: YYYYMMDD] What date is the event: $(date +"%Y%m%d" 2>/dev/null)" dat
+ dtd=$(date -d "$dat" +"%Y-%m-%d" 2>/dev/null) && [ -n "$dtd" ] || exit 1
+ printf_read_cal "4" "[Format: HHMM] Enter the start time: " dtt
+ sdt="$dtd $dtt" && [ -n "$sdt" ] || exit 1
+ dtstart=$(date -d "$sdt" +"%Y%m%dT%H%M%SZ" 2>/dev/null)
+ printf_read_cal "4" "Where is it (press Enter to skip)? " location
+ location=${location//,/\,}
+ printf_read_cal "4" "Please give the event a title (press Enter to skip): " summary
+ printf_read_cal "4" "any CALENDER_TAGS (press Enter to skip)? " category
+ CALENDER_TAGS=${category//,/\,}
+ printf_read_cal "4" "Write a short description (press Enter to skip): " desc
+ shell_generate_ical
+ populate_ical
+ printf_green "Event saved."
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__show_date() {
+ clear
+ printf_newline '\n\n\n'
+ if [ -z "$CALENDER_MESSAGE" ]; then
+ CALENDER_MESSAGE="$(date +'Today is: %A %B %d, %Y and the time is: %H:%M' 2>/dev/null)"
+ fi
+ printf_custom "$CALENDAR_OUTPUT_COLOR" "$CALENDER_MESSAGE"
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+gui_add_event() {
+ __cmd_exists yad || printf_exit "This feature required yad to be installed"
+ [ ! -s $CALENDER_EVENT_DIR ] && {
+ mkdir -p "$CALENDER_EVENT_DIR" 2>/dev/null
+ yad --text="Events directory created at $CALENDER_EVENT_DIR" 2>/dev/null
+ }
+ tmpfile=$(mktemp)
+ tagordo >$tmpfile
+ dtd=$(yad --title="start date" --text="When is it?" --calendar --date-format="%Y-%m-%d" --details=$tmpfile) || exit 1
+ [ -z "$dtd" ] && exit 0
+ dtt=$(yad --title="start time" --text="enter the start time" --entry) || exit 1
+ sdt="$dtd $dtt"
+ dtstart=$(date -d "$sdt" +"%Y%m%dT%H%M%SZ" 2>/dev/null)
+ loc=$(yad --title="location" --text="where is it?" --form --field="Name" --field="Address" --field="City" --field="Postcode" --field="Country") || exit 1
+ loc_array=()
+ place=$(echo $loc | awk -F '|' '{print $1}' 2>/dev/null)
+ [ -n "$place" ] && loc_array+=("$place")
+ street=$(echo $loc | awk -F '|' '{print $2}' 2>/dev/null)
+ [ -n "$street" ] && loc_array+=("$street")
+ city=$(echo $loc | awk -F '|' '{print $3}' 2>/dev/null)
+ [ -z "$city" ] && city=$CALENDER_HOMETOWN
+ [ -n "$city" ] && loc_array+=("$city")
+ postc=$(echo $loc | awk -F '|' '{print $4}' 2>/dev/null)
+ [ -n "$postc" ] && loc_array+=("$postc")
+ country=$(echo $loc | awk -F '|' '{print $5}' 2>/dev/null)
+ [ -z "$country" ] && country=$CALENDER_HOMECOUNTRY
+ [ -n "$country" ] && loc_array+=("$country")
+ location=$(printf "%s\, " "${loc_array[@]}" | sed -e 's/\(.*\)\\,/\1/' 2>/dev/null)
+ group="--field tag?:CBE"
+ title="--field title"
+ gp=$(join_strings '!' "${CALENDER_TAGS[@]}")
+ main=$(yad --form $group $title $gp) || exit 1
+ summary=$(echo $main | awk -F '|' '{print $2}' 2>/dev/null)
+ category=$(echo $main | awk -F '|' '{print $1}' 2>/dev/null)
+ desc=$(yad --text="Write a description or more information" --text-info --editable --wrap) || exit 1
+ yad_generate_ical
+ populate_ical
+ thanks=$(yad --text="Event saved")
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+yad_generate_ical() {
+ __cmd_exists yad || printf_exit "This feature required yad to be installed"
+ newfile="$CALENDER_EVENT_DIR/$(date -Iminutes -d "$sdt" 2>/dev/null | tr -d ':').ics"
+ # simple anti-clash mechanism
+ if [ -f $newfile ]; then
+ uhoh=$(yad --text="You have something on this day at that time already...")
+ exit 1
+ fi
+ touch "$newfile"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CALENDAR_CONFIG_FILE="${CALENDAR_CONFIG_FILE:-settings.conf}"
+CALENDAR_CONFIG_DIR="${CALENDAR_CONFIG_DIR:-$HOME/.config/myscripts/calendar}"
+CALENDAR_CONFIG_BACKUP_DIR="${CALENDAR_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/calendar/backups}"
+CALENDAR_LOG_DIR="${CALENDAR_LOG_DIR:-$HOME/.local/log/calendar}"
+CALENDAR_TEMP_DIR="${CALENDAR_TEMP_DIR:-$HOME/.local/tmp/system_scripts/calendar}"
+CALENDAR_CACHE_DIR="${CALENDAR_CACHE_DIR:-$HOME/.cache/calendar}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CALENDAR_OUTPUT_COLOR_1="${CALENDAR_OUTPUT_COLOR_1:-33}"
+CALENDAR_OUTPUT_COLOR_2="${CALENDAR_OUTPUT_COLOR_2:-5}"
+CALENDAR_OUTPUT_COLOR_GOOD="${CALENDAR_OUTPUT_COLOR_GOOD:-2}"
+CALENDAR_OUTPUT_COLOR_ERROR="${CALENDAR_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CALENDAR_NOTIFY_ENABLED="${CALENDAR_NOTIFY_ENABLED:-yes}"
+CALENDAR_GOOD_NAME="${CALENDAR_GOOD_NAME:-Great:}"
+CALENDAR_ERROR_NAME="${CALENDAR_ERROR_NAME:-Error:}"
+CALENDAR_GOOD_MESSAGE="${CALENDAR_GOOD_MESSAGE:-No errors reported}"
+CALENDAR_ERROR_MESSAGE="${CALENDAR_ERROR_MESSAGE:-Errors were reported}"
+CALENDAR_NOTIFY_CLIENT_NAME="${CALENDAR_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CALENDAR_NOTIFY_CLIENT_ICON="${CALENDAR_NOTIFY_CLIENT_ICON:-notification-new}"
+CALENDAR_NOTIFY_CLIENT_URGENCY="${CALENDAR_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CALENDER_EVENT_DIR="${CALENDER_EVENT_DIR:-$HOME/.local/share/ics}"
+CALENDER_HOMETOWN="${CALENDER_HOMETOWN:-$MYLOCATIONCITY}"
+CALENDER_HOMECOUNTRY="${CALENDER_HOMECOUNTRY:-$MYLOCATION_COUNTRY}"
+CALENDER_DATEFORMAT="${CALENDER_DATEFORMAT:-%a %b %d, %Y %H:%M}"
+CALENDER_TAGS=${CALENDER_TAGS:-(work,meeting,study,party)}
+CALENDER_MESSAGE="${CALENDER_MESSAGE:-$(date +"Today is: %A %B %d, %Y and the time is: %H:%M" 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CALENDAR_CONFIG_DIR/$CALENDAR_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CALENDAR_CONFIG_DIR/$CALENDAR_CONFIG_FILE" ] && . "$CALENDAR_CONFIG_DIR/$CALENDAR_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CALENDAR_LOG_DIR" ] || mkdir -p "$CALENDAR_LOG_DIR" |& __devnull
+[ -d "$CALENDAR_TEMP_DIR" ] || mkdir -p "$CALENDAR_TEMP_DIR" |& __devnull
+[ -d "$CALENDAR_CACHE_DIR" ] || mkdir -p "$CALENDAR_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CALENDAR_TEMP_FILE="${CALENDAR_TEMP_FILE:-$(mktemp $CALENDAR_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CALENDAR_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CALENDAR_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CALENDAR_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CALENDAR_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CALENDAR_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CALENDAR_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="add category summary date find list gui"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CALENDAR_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ CALENDAR_CWD="$2"
+ [ -d "$CALENDAR_CWD" ] || mkdir -p "$CALENDAR_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CALENDAR_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CALENDAR_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CALENDAR_CWD="$1" && shift 1 || CALENDAR_CWD="${CALENDAR_CWD:-$PWD}"
+CALENDAR_CWD="$(realpath "${CALENDAR_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CALENDAR_CWD" ] && cd "$CALENDAR_CWD"; then
+# if [ "$CALENDAR_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CALENDAR_CWD"
+# fi
+# else
+# printf_exit "💔 $CALENDAR_CWD does not exist 💔"
+# fi
+export CALENDAR_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+__welcome "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case ${1:-$main} in
+list)
+ shift 1
+ list="$(list_all | grep -v '^$' | tr -s '[:space:]' | grep '^' || false)"
+ if [ -n "$list" ]; then
+ printf_yellow "Your events are:"
+ printf '%s\n' "${list}" | printf_readline "$CALENDAR_OUTPUT_COLOR_2"
+ else
+ printf_red "You don't currently have any events"
+ fi
+ ;;
+
+category)
+ FILTER="$2"
+ [ -n "$FILTER" ] || printf_exit 'ERROR: you need to enter a category.' >&2
+ list="$(list_by_cat | grep -v '^$' | tr -s '[:space:]' | grep '^' || false)"
+ if [ -n "$list" ]; then
+ printf_yellow "Current categories are:"
+ printf '%s\n' "${list}" | printf_readline "$CALENDAR_OUTPUT_COLOR_2"
+ else
+ printf_red "You don't currently have any events"
+ fi
+ exit $?
+ ;;
+
+category=?*)
+ FILTER=${1#*=}
+ [ -n "$FILTER" ] || printf_exit 'ERROR: you need to enter a category file.' >&2
+ list="$(list_by_cat | grep -v '^$' | tr -s '[:space:]' | grep '^' || false)"
+ if [ -n "$list" ]; then
+ printf_yellow "Current categories are:"
+ printf '%s\n' "${list}" | printf_readline "$CALENDAR_OUTPUT_COLOR_2"
+ else
+ printf_red "You don't currently have any events"
+ fi
+ exit $?
+ ;;
+
+summary)
+ FILTER="$2"
+ [ -n "$FILTER" ] || printf_exit 'ERROR: you need to enter a summary.' >&2
+ list="$(list_by_text | grep -v '^$' | tr -s '[:space:]' | grep '^' || false)"
+ if [ -n "$list" ]; then
+ printf_yellow "Current summaries are:"
+ printf '%s\n' "${list}" | printf_readline "$CALENDAR_OUTPUT_COLOR_2"
+ else
+ printf_red "You don't currently have any events"
+ fi
+ exit $?
+ ;;
+
+summary=?*)
+ FILTER=${1#*=}
+ [ -n "$FILTER" ] || printf_exit 'ERROR: you need to enter a summary file.' >&2
+ list="$(list_by_text | grep -v '^$' | tr -s '[:space:]' | grep '^' || false)"
+ if [ -n "$list" ]; then
+ printf_yellow "Current summaries are:"
+ printf '%s\n' "${list}" | printf_readline "$CALENDAR_OUTPUT_COLOR_2"
+ else
+ printf_red "You don't currently have any events"
+ fi
+ exit $?
+ ;;
+
+date)
+ DATEFILE=$2
+ [ -n "$DATEFILE" ] || printf_exit 'ERROR: you need to enter a date.' >&2
+ list="$(find_appointments | grep -v '^$' | tr -s '[:space:]' | grep '^' || false)"
+ if [ -n "$list" ]; then
+ printf_yellow "Current summaries are:"
+ printf '%s\n' "${list}" | printf_readline "$CALENDAR_OUTPUT_COLOR_2"
+ else
+ printf_red "You don't currently have any events"
+ fi
+ exit $?
+ ;;
+
+date=?*)
+ DATEFILE=${1#*=}
+ [ -n "$DATEFILE" ] || printf_exit 'ERROR: you need to enter a date file.' >&2
+ list="$(find_appointments | grep -v '^$' | tr -s '[:space:]' | grep '^' || false)"
+ if [ -n "$list" ]; then
+ printf_yellow "Current summaries are:"
+ printf '%s\n' "${list}" | printf_readline "$CALENDAR_OUTPUT_COLOR_2"
+ else
+ printf_red "You don't currently have any events"
+ fi
+ exit $?
+ ;;
+
+find)
+ shift
+ [ $# -eq 2 ] || printf_exit "Usage: $APPNAME find [startdate] [enddate]"
+ sdr="$1"
+ edr="$2"
+ [ -n "$DATEFILE" ] || printf_exit 'ERROR: you need to enter a summary.' >&2
+ list="$(date_range | grep -v '^$' | tr -s '[:space:]' | grep '^' || false)"
+ if [ -n "$list" ]; then
+ printf_yellow "Current summaries are:"
+ printf '%s\n' "${list}" | printf_readline "$CALENDAR_OUTPUT_COLOR_2"
+ else
+ printf_red "You don't currently have any events"
+ fi
+ exit $?
+ ;;
+
+add)
+ shift 1
+ text_add_event
+ exit 0
+ ;;
+
+gui)
+ tmpfile="$CALENDAR_TEMP_FILE"
+ tagordo >"$tmpfile"
+ gui_add_event 2>/dev/null
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/cdd b/bin/cdd
new file mode 100755
index 000000000..3805c9350
--- /dev/null
+++ b/bin/cdd
@@ -0,0 +1,866 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208201626-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : cdd --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Saturday, Aug 20, 2022 16:26 EDT
+# @@File : cdd
+# @@Description : cd into directories using shortcuts
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208201626-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CDD_REQUIRE_SUDO="${CDD_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CDD_CONFIG_DIR/$CDD_CONFIG_FILE"
+ fi
+ [ -d "$CDD_CONFIG_DIR" ] || mkdir -p "$CDD_CONFIG_DIR"
+ [ -d "$CDD_CONFIG_BACKUP_DIR" ] || mkdir -p "$CDD_CONFIG_BACKUP_DIR"
+ [ -f "$CDD_CONFIG_DIR/$CDD_CONFIG_FILE" ] &&
+ cp -Rf "$CDD_CONFIG_DIR/$CDD_CONFIG_FILE" "$CDD_CONFIG_BACKUP_DIR/$CDD_CONFIG_FILE.$$"
+ cat <"$CDD_CONFIG_DIR/$CDD_CONFIG_FILE"
+# Settings for cdd
+CDD_OPTIONS_DEFAULT_PROJECT_NAME="${CDD_OPTIONS_DEFAULT_PROJECT_NAME:-default}"
+CDD_OPTIONS_PROJECT_DIR="${CDD_OPTIONS_PROJECT_DIR:-$HOME/.local/share/cdd/projects}"
+CDD_GREP_COLORS="${CDD_GREP_COLORS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CDD_OUTPUT_COLOR_1="${CDD_OUTPUT_COLOR_1:-}"
+CDD_OUTPUT_COLOR_2="${CDD_OUTPUT_COLOR_2:-}"
+CDD_OUTPUT_COLOR_GOOD="${CDD_OUTPUT_COLOR_GOOD:-}"
+CDD_OUTPUT_COLOR_ERROR="${CDD_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CDD_NOTIFY_ENABLED="${CDD_NOTIFY_ENABLED:-}"
+CDD_GOOD_NAME="${CDD_GOOD_NAME:-}"
+CDD_ERROR_NAME="${CDD_ERROR_NAME:-}"
+CDD_GOOD_MESSAGE="${CDD_GOOD_MESSAGE:-}"
+CDD_ERROR_MESSAGE="${CDD_ERROR_MESSAGE:-}"
+CDD_NOTIFY_CLIENT_NAME="${CDD_NOTIFY_CLIENT_NAME:-}"
+CDD_NOTIFY_CLIENT_ICON="${CDD_NOTIFY_CLIENT_ICON:-}"
+CDD_NOTIFY_CLIENT_URGENCY="${CDD_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CDD_CONFIG_DIR/$CDD_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CDD_CONFIG_DIR/$CDD_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "cdd: cd into directories using shortcuts - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: cdd [options] [commands] [projectName]"
+ __printf_line "--root [dir] - Enable system browsing"
+ __printf_line "-s, --shell [shell] - change shell "
+ __printf_line "-a, --add [alias] [dir] - Add an alias"
+ __printf_line "-m, --modify [alias] [dir] - Modify an alias"
+ __printf_line "-d, --delete [file,dir] - Delete all files in dir"
+ __printf_line "-r, --remove [alias] - remove an alias"
+ __printf_line "-l, --list - List aliases"
+ __printf_line "--edit - Open alias file in editor"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ # --edit
+ __printf_line "--silent - Don't show messages"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CDD_REQUIRE_SUDO" = "yes" ] && [ -z "$CDD_REQUIRE_SUDO_RUN" ]; then
+ export CDD_REQUIRE_SUDO="no"
+ export CDD_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CDD_TEMP_FILE" ] && rm -Rf "$CDD_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__gen_config_local() {
+ __gen_alias &>/dev/null
+ [ -f "$CDD_CONFIG_BACKUP_DIR/$CDD_ALIAS_FILE.$$" ] && rm -Rf "$CDD_CONFIG_BACKUP_DIR/$CDD_ALIAS_FILE.$$" || true
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__open_editor() {
+ local editor="$(type -P "$EDITOR" 2>/dev/null || type -P "vim" 2>/dev/null || type -P "nano" 2>/dev/null || type -P "nvim" 2>/dev/null || type -P "vi" 2>/dev/null || type -P "vi" 2>/dev/null || false)"
+ if [ -n "$editor" ]; then
+ eval $editor "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE"
+ else
+ __notifications "No editors found"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__gen_alias() {
+ if [ -f "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" ]; then
+ cdd_update=true
+ printf_green "Updating the aliases file in"
+ else
+ printf_green "Generating the aliases file in"
+ fi
+ printf_green "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE"
+ tempfile="$CDD_CONFIG_DIR/$CDD_ALIAS_FILE.bak"
+ [ -d "$CDD_CONFIG_DIR" ] || mkdir -p "$CDD_CONFIG_DIR"
+ [ -d "$CDD_CONFIG_BACKUP_DIR" ] || mkdir -p "$CDD_CONFIG_BACKUP_DIR"
+ [ -f "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" ] && cp -Rf "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" "$tempfile"
+ cat <"$CDD_CONFIG_DIR/$CDD_ALIAS_FILE"
+# Alias settings for cdd - format: name = "/mydir"
+default = "$CDD_OPTIONS_PROJECT_DIR/${CDD_OPTIONS_DEFAULT_PROJECT_NAME}"
+screen = "$CDD_OPTIONS_PROJECT_DIR/dev-screen"
+tmux = "$CDD_OPTIONS_PROJECT_DIR/dev-tmux"
+testing = "${TMPDIR:-/tmp}/testing"
+projects = "$HOME/Projects"
+pictures = "$HOME/Pictures"
+music = "$HOME/Music"
+share = "$HOME/.local/share"
+
+EOF
+
+ if [ -f "$tempfile" ] && [ "$(<"$tempfile")" != "$(<"$CDD_CONFIG_DIR/$CDD_ALIAS_FILE")" ]; then
+ cp -Rf "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" "$CDD_CONFIG_BACKUP_DIR/$CDD_ALIAS_FILE.$$"
+ printf '# Settings for %s\n' "$APPNAME" >"$CDD_CONFIG_DIR/$CDD_ALIAS_FILE"
+ cat "$HOME/.config/myscripts/cdd/aliases.conf"* | sed 's|.*:||g' | grep -v '#' | sort -u | grep -v '^$' >>"$CDD_CONFIG_DIR/$CDD_ALIAS_FILE"
+ printf '\n' >>"$CDD_CONFIG_DIR/$CDD_ALIAS_FILE"
+ fi
+ if [ -f "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" ] && [ -f "$CDD_CONFIG_DIR/$CDD_CONFIG_FILE" ]; then
+ printf_green "Your config file for cdd has been created"
+ true
+ else
+ printf_red "Failed to create the config file"
+ false
+ fi
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+quit() {
+ local exitCode=$?
+ printf_red "Exiting the cdd enviroment" && sleep 3 && builtin exit $exitCode &>/dev/null
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+_cd() {
+ _find() { find ${1:-$PWD/} -maxdepth 1 -type d 2>/dev/null | sed 's|'"$CDD_CWD_DIR/"'||g' | grep -shv '^$'; }
+ prev=
+ COMPREPLY=($(compgen -W '$(_find ${cur})' -- "${cur}"))
+} && complete -F _cd cd
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+cd() {
+ local realdir=""
+ realdir="$(realpath "$1")"
+ cd_cdd "$realdir" || return 1
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+cd_cdd() {
+ local exitCode=0 realpath=""
+ local ORIG_PATH="$PATH"
+ local local_remote_repo="local repo"
+ local local_remote_icon="🤷"
+ local remote_icon="🚀"
+ local CDD_REPO_UPDATED="${CDD_REPO_UPDATED:-}"
+ local CD_INTO_DIR="$(realpath "${1:-$CDD_CWD_DIR}")"
+ if [ -z "$CDD_CWD_DIR" ]; then
+ builtin cd "$CD_INTO_DIR" || return 1
+ else
+ unalias cd &>/dev/null
+ if [ "$CDD_ALLOW_ROOT" = "true" ]; then
+ CDD_INTO_CUR="$CD_INTO_DIR"
+ else
+ CDD_INTO_CUR="$CDD_CWD_DIR/${CD_INTO_DIR//$CDD_CWD_DIR/}"
+ fi
+ CDD_TOP_DIR="$(__git_top_dir "${CDD_INTO_CUR:-$PWD}")"
+ [ -f "$CDD_TOP_DIR/.env" ] && . "$CDD_TOP_DIR/.env"
+ [ -n "$OLDPATH" ] && PATH="${OLDPATH//::/:}" || OLDPATH="${PATH//::/:}"
+ [ -d "$CDD_TOP_DIR/bin" ] && PATH="$CDD_TOP_DIR/bin:${OLDPATH:$PATH}" || OLDPATH="$PATH"
+ [ -d "$CDD_TOP_DIR/node_modules/.bin" ] && PATH="$CDD_TOP_DIR/node_modules/.bin:${OLDPATH:$PATH}" || PATH="$OLDPATH"
+ if [ -d "$CDD_TOP_DIR/.git" ] && [ -z "$CDD_REPO_UPDATED" ]; then
+ [ -f "${CDD_TOP_DIR:-$PWD}/.git/config" ] && remote_repo="$(grep -sh 'url = ' "${CDD_TOP_DIR:-$PWD}/.git/config" | awk -F'= ' '{print $2}' | grep '^')"
+ [ -z "$remote_repo" ] && remote_icon="$local_remote_icon" && remote_repo="$local_remote_repo"
+ { printf_green "🎆 Updating the git repo from: $remote_repo $remote_icon" && git -C "$CD_INTO_DIR" pull -q &>/dev/null; } &&
+ export CDD_REPO_UPDATED="yes" || CDD_REPO_UPDATED=""
+ fi
+ if echo "$PATH" | grep -qv "$HOME/.local/bin"; then
+ export PATH="$HOME/.local/bin:$PATH"
+ fi
+ if [ $# == 0 ] || [ "$CD_INTO_DIR" = "/" ]; then
+ if ! builtin cd "$CDD_CWD_DIR" &>/dev/null; then
+ exitCode=12
+ fi
+ else
+ if ! builtin cd "$CDD_INTO_CUR" &>/dev/null; then
+ exitCode=12
+ fi
+ fi
+ export -f cd
+ fi
+ export PATH CDD_REPO_UPDATED
+ [ "$exitCode" = "12" ] && printf_red "Changing into $CD_INTO_DIR is not allowed"
+ exitCode=${exitCode:-0}
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+cd_goto() {
+ local dir="" folder="" message="" message_add="" name="" exitCode=""
+ [ "$CDD_STATUS" = "running" ] && [[ "$1" = ./* ]] && cd "$1" && return
+ [ -f "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" ] || __gen_config "$@"
+ if [ -n "$CDD_STATUS" ]; then
+ printf_pause "cdd already appears to be active "
+ return 1
+ fi
+ if [ "$CDD_STATUS" != "running" ] && [ "$CDD_ALLOW_ROOT" = "true" ]; then
+ dir="$1"
+ CDD_NO_ALIAS="true"
+ folder="$(basename $(dirname "$1/."))"
+ message="Entering into $dir"
+ elif [ "$CDD_STATUS" != "running" ] && { [ "$1" = "current_project" ] || [ "$1" = "." ] || [ "$1" = "$PWD" ]; }; then
+ dir="$PWD"
+ CDD_NO_ALIAS="true"
+ folder="$(basename $(dirname "$PWD/."))"
+ message="Entering into $dir with alias $folder"
+ elif [ -n "$(list_aliases "folder" "$1")" ]; then
+ dir="$(list_aliases "folder" "$1")"
+ folder="$(list_aliases alias "$1")"
+ message="entering into $dir"
+ elif [ -z "$dir" ]; then
+ name="${1:-$CDD_OPTIONS_DEFAULT_PROJECT_NAME}"
+ dir="$CDD_OPTIONS_PROJECT_DIR/$name"
+ folder="$(basename -- "$dir/")"
+ message="Entering $name"
+ message_add="see $APPNAME -l or add alias: $APPNAME -a [name] [directory]"
+ fi
+ exitCode=0
+ STATUS="running"
+ SHELL="${SHELL:-bash}"
+ PS1_ADD_CDD="$PS1_ADD cdd: ${folder:-$dir}"
+ GREP_COLORS="$GREP_COLORS;$CDD_GREP_COLORS"
+ clear
+ printf '\n'
+ AUTO="true" add_alias "${name:-$folder}" "$dir"
+ [ -d "$dir" ] || mkdir -p "$dir"
+ [ -d "$dir" ] && builtin cd "$dir" || printf_exit "Failed to enter $dir"
+ if [ "$CDD_JUST_CD" = "true" ]; then
+ printf_cyan "Setting working directory to: $dir"
+ unset -f cd_cdd &>/dev/null
+ cd_cdd() { [ $# -eq 0 ] && { builtin cd "$CDD_CWD_DIR" || return 1; } || { [ -d "$1" ] && builtin cd "$1" || { echo "$1 is not a directory" && return 1; }; }; }
+ export SHELL GREP_COLORS CDD_CWD_DIR="$PWD" CDD_STATUS="" CDD_JUST_CD="" CDD_CWD=""
+ unset CDD_CWD_DIR CDD_STATUS CDD_JUST_CD CDD_CWD
+ else
+ [ -n "$message" ] && printf_green "$message using $(basename -- "$SHELL" 2>/dev/null)"
+ [ -n "$message_add" ] && printf_blue "$message_add"
+ printf_yellow "cd out of $dir is not"
+ printf_yellow "allowed while using cdd which will cause issues with applications"
+ printf_cyan "Type quit to return to your previous directory/shell"
+ export SHELL GREP_COLORS CDD_CWD_DIR="$PWD" PS1_ADD="$PS1_ADD_CDD" CDD_STATUS="$STATUS"
+ fi
+ export -f _cd cd_cdd quit __git_top_dir printf_red
+ export PATH="$HOME/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:."
+ printf '\n'
+ eval "$SHELL"
+ exitCode=$?
+ sleep .5
+ export PATH="${ORIG_PATH:-$PATH}" CDD_CWD_DIR="" PS1_ADD="" CDD_STATUS=""
+ [ "$exitCode" = 0 ] && clear
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+add_alias() {
+ [ $# = 2 ] || printf_exit "Usage: $APPNAME add name Directory"
+ [ -z "$CDD_NO_ALIAS" ] || return 0
+ if ! list_aliases alias "$1" | grep -qx "$1"; then
+ printf_green "Adding the alias $1 to config"
+ grep -shv '^$' "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" >"$CDD_CONFIG_DIR/$CDD_ALIAS_FILE.tmp"
+ printf "%s = %s\n\n" "$1" "$2" >>"$CDD_CONFIG_DIR/$CDD_ALIAS_FILE.tmp"
+ mv -f "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE.tmp" "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE"
+ else
+ [ -n "$AUTO" ] || printf_red "It appears that $1 has already been added"
+ fi
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+rm_alias() {
+ local folder
+ [ $# = 1 ] || printf_exit "Usage: $APPNAME delete alias"
+ folder="$(list_aliases 'alias' "$1")"
+ list_aliases 'alias' "$1"
+ exit
+ if list_aliases 'alias' '*' | grep -qx "$folder"; then
+ printf_green "Removing the alias $folder from config"
+ grep -shxv ^"$folder = .*" "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" >"$CDD_CONFIG_DIR/$CDD_ALIAS_FILE.tmp" &&
+ mv -f "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE.tmp" "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" || return 1
+ else
+ printf_red "The alias $1 doesn't exist"
+ fi
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+list_aliases() {
+ if [ ! -f "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" ]; then __gen_config &>/dev/null; fi
+ __grep() { grep -shE '^'$1' =*..*$' "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" 2>/dev/null | sed 's|"||g' 2>/dev/null; }
+ if [ "$1" = "folder" ]; then
+ shift 1
+ __grep "$1" | awk -F'= ' '{print $2}' | sed -e 's#" ##g' 2>/dev/null | grep -Ev '^$|^#' | grep '^'
+ elif [ "$1" = "alias" ]; then
+ shift 1
+ __grep "$1" | awk -F' =' '{print $1}' | sed -e 's#"##g' 2>/dev/null | grep -Ev '^$|^#' | grep '^'
+ else
+ __grep "$1" | awk -F' =' '{print $1,$2}' | sed -e 's#"##g' 2>/dev/null | grep -Ev '^$|^#' | grep '^'
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+delete_files() {
+ if [ -n "$CDD_CWD_DIR" ] && [ "$CDD_STATUS" = "running" ]; then
+ FILES_TO_DELETE="$(find "$CDD_CWD_DIR/" -maxdepth 1 2>/dev/null | grep -v "^$CDD_CWD_DIR/$1")"
+ if [ -n "$FILES_TO_DELETE" ]; then
+ printf_blue "Deleting all files in $CDD_CWD_DIR"
+ for file in ${FILES_TO_DELETE}; do
+ if [ -d "$file" ]; then
+ printf_yellow "Deleting folder: $file" && rm -Rf "${file}" &>/dev/null
+ elif [ -f "$file" ]; then
+ printf_yellow "Deleting file: $file" && rm -Rf "${file}" &>/dev/null
+ elif [ -e "$file" ]; then
+ printf_yellow "Deleting: $file" && rm -Rf "${file}" &>/dev/null
+ fi
+ done
+ exitCode=0
+ else
+ printf_red "There are no files to delete"
+ exitCode=1
+ fi
+ else
+ printf_red "cdd is not active refusing to delete files"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+CDD_OPTIONS_DEFAULT_PROJECT_NAME="${CDD_OPTIONS_DEFAULT_PROJECT_NAME:-}"
+CDD_OPTIONS_PROJECT_DIR="${CDD_OPTIONS_PROJECT_DIR:-}"
+CDD_OPTIONS_TMP_DIR="${CDD_OPTIONS_TMP_DIR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CDD_CONFIG_FILE="${CDD_CONFIG_FILE:-settings.conf}"
+CDD_CONFIG_DIR="${CDD_CONFIG_DIR:-$HOME/.config/myscripts/cdd}"
+CDD_CONFIG_BACKUP_DIR="${CDD_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/cdd/backups}"
+CDD_LOG_DIR="${CDD_LOG_DIR:-$HOME/.local/log/cdd}"
+CDD_TEMP_DIR="${CDD_TEMP_DIR:-$HOME/.local/tmp/system_scripts/cdd}"
+CDD_CACHE_DIR="${CDD_CACHE_DIR:-$HOME/.cache/cdd}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CDD_OUTPUT_COLOR_1="${CDD_OUTPUT_COLOR_1:-33}"
+CDD_OUTPUT_COLOR_2="${CDD_OUTPUT_COLOR_2:-5}"
+CDD_OUTPUT_COLOR_GOOD="${CDD_OUTPUT_COLOR_GOOD:-2}"
+CDD_OUTPUT_COLOR_ERROR="${CDD_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CDD_NOTIFY_ENABLED="${CDD_NOTIFY_ENABLED:-yes}"
+CDD_GOOD_NAME="${CDD_GOOD_NAME:-Great:}"
+CDD_ERROR_NAME="${CDD_ERROR_NAME:-Error:}"
+CDD_GOOD_MESSAGE="${CDD_GOOD_MESSAGE:-No errors reported}"
+CDD_ERROR_MESSAGE="${CDD_ERROR_MESSAGE:-Errors were reported}"
+CDD_NOTIFY_CLIENT_NAME="${CDD_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CDD_NOTIFY_CLIENT_ICON="${CDD_NOTIFY_CLIENT_ICON:-notification-new}"
+CDD_NOTIFY_CLIENT_URGENCY="${CDD_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CDD_ALIAS_FILE="${CDD_ALIAS_FILE:-aliases.conf}"
+CDD_GREP_COLORS="${CDD_GREP_COLORS:-mt=38;5;220;1}"
+CDD_OPTIONS_DEFAULT_PROJECT_NAME="${CDD_OPTIONS_DEFAULT_PROJECT_NAME:-default}"
+CDD_OPTIONS_PROJECT_DIR="${CDD_OPTIONS_PROJECT_DIR:-$HOME/.local/share/cdd/projects}"
+CDD_OPTIONS_TMP_DIR="${CDD_OPTIONS_TMP_DIR:-$HOME/.local/tmp/cdd}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CDD_CONFIG_DIR/$CDD_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CDD_CONFIG_DIR/$CDD_CONFIG_FILE" ] && . "$CDD_CONFIG_DIR/$CDD_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CDD_LOG_DIR" ] || mkdir -p "$CDD_LOG_DIR" |& __devnull
+[ -d "$CDD_TEMP_DIR" ] || mkdir -p "$CDD_TEMP_DIR" |& __devnull
+[ -d "$CDD_CACHE_DIR" ] || mkdir -p "$CDD_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CDD_TEMP_FILE="${CDD_TEMP_FILE:-$(mktemp $CDD_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CDD_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CDD_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CDD_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CDD_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CDD_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CDD_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS="c,v,h,m::,r:,l,s:,a::,d:"
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=",modify::,remove:,list,shell:,add::,delete:,root,edit,cd,enter"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="$(list_aliases '*' | awk '{print $1}')"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CDD_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ CDD_CWD="$2"
+ [ -d "$CDD_CWD" ] || mkdir -p "$CDD_CWD" |& __devnull
+ shift 2
+ ;;
+ --root)
+ shift 1
+ CDD_ALLOW_ROOT="true"
+ ;;
+ --edit)
+ shift 1
+ __open_editor
+ exit $?
+ ;;
+ -a | --add)
+ add_alias "$2" "$3"
+ shift 3
+ exit $?
+ ;;
+ -m | --modify)
+ [ -z "$2" ] && [ -z "$3" ] && [ -n "$EDITOR" ] && $EDITOR "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE"
+ add_alias "$2" "$3"
+ shift 2
+ exit $?
+ ;;
+ -r | --remove)
+ rm_alias "$2"
+ shift 2
+ exit $?
+ ;;
+ -d | --delete)
+ delete_files "$2" || false
+ shift 2
+ exit $?
+ ;;
+ -l | --list)
+ shift 1
+ list_aliases alias '*'
+ exit $?
+ ;;
+ -s | --shell)
+ if [ -f "$2" ] || cmd_exists "$2"; then
+ SHELL="$2"
+ else
+ printf_exit "$2 seems to be an invalid shell"
+ fi
+ shift 1
+ ;;
+ --cd | --enter)
+ shift 1
+ CDD_JUST_CD="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CDD_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CDD_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CDD_CWD="$1" && shift 1 || CDD_CWD="${CDD_CWD:-$PWD}"
+CDD_CWD="$(realpath "${CDD_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CDD_CWD" ] && cd "$CDD_CWD"; then
+# if [ "$CDD_SILENT" != true ]; then
+# printf_cyan "Setting working dir to $CDD_CWD"
+# fi
+# else
+# printf_exit "💔 $CDD_CWD does not exist 💔"
+# fi
+export CDD_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+if [ "$TERMINAL_APP" = "TRUE" ]; then
+ printf '\n\n'
+ find "$CDD_OPTIONS_PROJECT_DIR"/ -maxdepth 1 | sed 's|'$CDD_OPTIONS_PROJECT_DIR/'||g' | printf_column $CDD_OUTPUT_COLOR_2
+ printf_read_input "4" "What project would you like to work on? " "120" CDD_PROJECT
+ [ -n "$CDD_PROJECT" ] || { printf_newline && printf_pause "No project selected. Exiting" && exit 1; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+list)
+ shift 1
+ list_aliases alias '*'
+ ;;
+
+add)
+ shift 1
+ add_alias "$1" "$2"
+ ;;
+
+modify)
+ shift 1
+ [ -z "$1" ] && [ -z "$2" ] && [ -n "$EDITOR" ] &&
+ $EDITOR "$CDD_CONFIG_DIR/$CDD_ALIAS_FILE" || printf_exit "Usage: modify alias directory"
+ add_alias "$1" "$2"
+ ;;
+
+remove)
+ shift 1
+ rm_alias "$@"
+ ;;
+
+*)
+ [ $# -le 1 ] || printf_exit "Usage: [alias]"
+ cd_goto "${CDD_PROJECT:-$1}"
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/changeip b/bin/changeip
new file mode 100755
index 000000000..154fa3e56
--- /dev/null
+++ b/bin/changeip
@@ -0,0 +1,709 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042152-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : changeip --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 21:52 EDT
+# @@File : changeip
+# @@Description : change ip script
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : yes
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042152-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CHANGEIP_REQUIRE_SUDO="${CHANGEIP_REQUIRE_SUDO:-yes}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ printf_color() { printf '%b' "$1" | tr -d '\t' | $CHANGEIP_SED '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | $CHANGEIP_SED 's|:||g;s/'$3'/ '$4'/g'
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CHANGEIP_CONFIG_DIR/$CHANGEIP_CONFIG_FILE"
+ fi
+ [ -d "$CHANGEIP_CONFIG_DIR" ] || mkdir -p "$CHANGEIP_CONFIG_DIR"
+ [ -d "$CHANGEIP_CONFIG_BACKUP_DIR" ] || mkdir -p "$CHANGEIP_CONFIG_BACKUP_DIR"
+ [ -f "$CHANGEIP_CONFIG_DIR/$CHANGEIP_CONFIG_FILE" ] &&
+ cp -Rf "$CHANGEIP_CONFIG_DIR/$CHANGEIP_CONFIG_FILE" "$CHANGEIP_CONFIG_BACKUP_DIR/$CHANGEIP_CONFIG_FILE.$$"
+ cat <"$CHANGEIP_CONFIG_DIR/$CHANGEIP_CONFIG_FILE"
+# Settings for changeip
+CHANGE_IP_VAR_DIR="${CHANGE_IP_VAR_DIR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CHANGEIP_OUTPUT_COLOR_1="${CHANGEIP_OUTPUT_COLOR_1:-}"
+CHANGEIP_OUTPUT_COLOR_2="${CHANGEIP_OUTPUT_COLOR_2:-}"
+CHANGEIP_OUTPUT_COLOR_GOOD="${CHANGEIP_OUTPUT_COLOR_GOOD:-}"
+CHANGEIP_OUTPUT_COLOR_ERROR="${CHANGEIP_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CHANGEIP_NOTIFY_ENABLED="${CHANGEIP_NOTIFY_ENABLED:-}"
+CHANGEIP_GOOD_NAME="${CHANGEIP_GOOD_NAME:-}"
+CHANGEIP_ERROR_NAME="${CHANGEIP_ERROR_NAME:-}"
+CHANGEIP_GOOD_MESSAGE="${CHANGEIP_GOOD_MESSAGE:-}"
+CHANGEIP_ERROR_MESSAGE="${CHANGEIP_ERROR_MESSAGE:-}"
+CHANGEIP_NOTIFY_CLIENT_NAME="${CHANGEIP_NOTIFY_CLIENT_NAME:-}"
+CHANGEIP_NOTIFY_CLIENT_ICON="${CHANGEIP_NOTIFY_CLIENT_ICON:-}"
+CHANGEIP_NOTIFY_CLIENT_URGENCY="${CHANGEIP_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CHANGEIP_CONFIG_DIR/$CHANGEIP_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CHANGEIP_CONFIG_DIR/$CHANGEIP_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "changeip: change ip script - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: changeip [options]"
+ __printf_line "* - Changes the IP address and hostname"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CHANGEIP_REQUIRE_SUDO" = "yes" ] && [ -z "$CHANGEIP_REQUIRE_SUDO_RUN" ]; then
+ export CHANGEIP_REQUIRE_SUDO="no"
+ export CHANGEIP_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CHANGEIP_TEMP_FILE" ] && rm -Rf "$CHANGEIP_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__getlipaddr() {
+ local CHANGE_IP_VAR_DIR="" IFCONFIG=""
+ CHANGE_IP_VAR_DIR="${CHANGE_IP_VAR_DIR:-/var/lib/system-scripts/checkip}"
+ [ -d "$CHANGE_IP_VAR_DIR" ] || sudo mkdir -p "$CHANGE_IP_VAR_DIR"
+ if [[ "$OSTYPE" =~ ^darwin ]]; then
+ NETDEV="$(route get default 2>/dev/null | grep interface | awk '{print $2}')"
+ else
+ NETDEV="$(ip route 2>/dev/null | grep default | sed -e "s/^.*dev.//" -e "s/.proto.*//" | awk '{print $1}' | grep '^' || echo 'eth0')"
+ fi
+ IFCONFIG="$(builtin type -P /sbin/ifconfig || builtin type -P ifconfig)"
+ if [ -f "$IFCONFIG" ]; then
+ # net-tools package
+ CURRENT_IP_4="$(/sbin/ifconfig $NETDEV 2>/dev/null | grep -E "venet|inet" | grep -v "127.0.0." | grep 'inet' | grep -v inet6 | awk '{print $2}' | sed s/addr://g | head -n1 | grep '^')"
+ CURRENT_IP_6="$(/sbin/ifconfig $NETDEV 2>/dev/null | grep -E "venet|inet" | grep 'inet6' | grep -i global | awk '{print $2}' | head -n1 | grep '^')"
+ else
+ CURRENT_IP_4="$(ip -o -f inet address show $NETDEV | awk -F'/' '{print $1}' | awk '{print $NF}' | head -n 1 | grep '^')"
+ CURRENT_IP_6="$(ip -o -f inet6 address show $NETDEV | awk -F'/' '{print $1}' | awk '{print $NF}' | head -n 1 | grep '^')"
+ fi
+ [ -n "$NETDEV" ] || NETDEV="lo"
+ [ -n "$CURRENT_IP_4" ] || CURRENT_IP_4="127.0.0.1"
+ [ -n "$CURRENT_IP_6" ] || CURRENT_IP_6="::1"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CHANGEIP_CONFIG_FILE="${CHANGEIP_CONFIG_FILE:-settings.conf}"
+CHANGEIP_CONFIG_DIR="${CHANGEIP_CONFIG_DIR:-$HOME/.config/myscripts/changeip}"
+CHANGEIP_CONFIG_BACKUP_DIR="${CHANGEIP_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/changeip/backups}"
+CHANGEIP_LOG_DIR="${CHANGEIP_LOG_DIR:-$HOME/.local/log/changeip}"
+CHANGEIP_TEMP_DIR="${CHANGEIP_TEMP_DIR:-$HOME/.local/tmp/system_scripts/changeip}"
+CHANGEIP_CACHE_DIR="${CHANGEIP_CACHE_DIR:-$HOME/.cache/changeip}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CHANGEIP_OUTPUT_COLOR_1="${CHANGEIP_OUTPUT_COLOR_1:-33}"
+CHANGEIP_OUTPUT_COLOR_2="${CHANGEIP_OUTPUT_COLOR_2:-5}"
+CHANGEIP_OUTPUT_COLOR_GOOD="${CHANGEIP_OUTPUT_COLOR_GOOD:-2}"
+CHANGEIP_OUTPUT_COLOR_ERROR="${CHANGEIP_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CHANGEIP_NOTIFY_ENABLED="${CHANGEIP_NOTIFY_ENABLED:-yes}"
+CHANGEIP_GOOD_NAME="${CHANGEIP_GOOD_NAME:-Great:}"
+CHANGEIP_ERROR_NAME="${CHANGEIP_ERROR_NAME:-Error:}"
+CHANGEIP_GOOD_MESSAGE="${CHANGEIP_GOOD_MESSAGE:-No errors reported}"
+CHANGEIP_ERROR_MESSAGE="${CHANGEIP_ERROR_MESSAGE:-Errors were reported}"
+CHANGEIP_NOTIFY_CLIENT_NAME="${CHANGEIP_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CHANGEIP_NOTIFY_CLIENT_ICON="${CHANGEIP_NOTIFY_CLIENT_ICON:-notification-new}"
+CHANGEIP_NOTIFY_CLIENT_URGENCY="${CHANGEIP_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CHANGE_IP_VAR_DIR="${CHANGE_IP_VAR_DIR:-/var/lib/system-scripts/checkip}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CHANGEIP_CONFIG_DIR/$CHANGEIP_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CHANGEIP_CONFIG_DIR/$CHANGEIP_CONFIG_FILE" ] && . "$CHANGEIP_CONFIG_DIR/$CHANGEIP_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CHANGEIP_LOG_DIR" ] || mkdir -p "$CHANGEIP_LOG_DIR" |& __devnull
+[ -d "$CHANGEIP_TEMP_DIR" ] || mkdir -p "$CHANGEIP_TEMP_DIR" |& __devnull
+[ -d "$CHANGEIP_CACHE_DIR" ] || mkdir -p "$CHANGEIP_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CHANGEIP_TEMP_FILE="${CHANGEIP_TEMP_FILE:-$(mktemp $CHANGEIP_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CHANGEIP_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CHANGEIP_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CHANGEIP_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CHANGEIP_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CHANGEIP_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CHANGEIP_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="clean"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | $CHANGEIP_SED 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | $CHANGEIP_SED 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | $CHANGEIP_SED 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | $CHANGEIP_SED 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CHANGEIP_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CHANGEIP_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CHANGEIP_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CHANGEIP_CWD="$1" && shift 1 || CHANGEIP_CWD="${CHANGEIP_CWD:-$PWD}"
+CHANGEIP_CWD="$(realpath "${CHANGEIP_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CHANGEIP_CWD" ] && cd "$CHANGEIP_CWD"; then
+# if [ "$CHANGEIP_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CHANGEIP_CWD"
+# fi
+# else
+# printf_exit "💔 $CHANGEIP_CWD does not exist 💔"
+# fi
+export CHANGEIP_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+__getlipaddr
+NEWIP4="$(echo "${CURRENT_IP_4:-}" | grep '^')"
+NEWIP6="$(echo "${CURRENT_IP_6:-}" | grep '^')"
+NEWDOM="$(hostname -d 2>/dev/null | grep '^' || echo 'local')"
+NEWSHORT="$(hostname -s 2>/dev/null | grep '^')"
+CHANGEIP_SED="$(builtin command -v gsed 2>/dev/null || builtin command -v sed 2>/dev/null)"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+if [ -f "$CHANGE_IP_VAR_DIR/olddomain.txt" ] && [ -s "$CHANGE_IP_VAR_DIR/olddomain.txt" ]; then
+ OLDDOM="$(<"$CHANGE_IP_VAR_DIR/olddomain.txt")"
+else
+ OLDDOM="myserverdomainname"
+fi
+if [ -f "$CHANGE_IP_VAR_DIR/oldshort.txt" ] && [ -s "$CHANGE_IP_VAR_DIR/oldshort.txt" ]; then
+ OLDSHORT="$(<"$CHANGE_IP_VAR_DIR/oldshort.txt")"
+else
+ OLDSHORT="myserverhostname"
+fi
+if [ -f "$CHANGE_IP_VAR_DIR/oldipv4.txt" ] && [ -s "$CHANGE_IP_VAR_DIR/oldipv4.txt" ]; then
+ OLDIP4="$(<"$CHANGE_IP_VAR_DIR/oldipv4.txt")"
+else
+ OLDIP4="10.0.20.1"
+fi
+if [ -f "$CHANGE_IP_VAR_DIR/oldipv6.txt" ] && [ -s "$CHANGE_IP_VAR_DIR/oldipv6.txt" ]; then
+ OLDIP6="$(<"$CHANGE_IP_VAR_DIR/oldipv6.txt")"
+else
+ OLDIP6="2001:db8:edfa:1234:5678::e1a2"
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+echo "$OLDIP4" | grep '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/oldipv4.txt"
+echo "$OLDIP6" | grep '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/oldipv6.txt"
+echo "$OLDDOM" | grep '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/olddomain.txt"
+echo "$OLDSHORT" | grep '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/oldshort.txt"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+clean)
+ printf_cyan "Deleting the files in $CHANGE_IP_VAR_DIR"
+ rm -Rf "${CHANGE_IP_VAR_DIR:?printf_exit "The variable CHANGE_IP_VAR_DIR is not set"}"
+ mkdir -p "$CHANGE_IP_VAR_DIR"
+ exit $?
+ ;;
+*)
+ if [ -z "$NEWIP4" ]; then
+ printf_red "no ipv4"
+ rm -Rf "$CHANGE_IP_VAR_DIR/myip4.txt" "$CHANGE_IP_VAR_DIR/oldipv4.txt"
+ [ -e "/etc/httpd" ] && find /etc/httpd -name 'conf*' -type f -exec $CHANGEIP_SED -i "s#$OLDIP4:443##g" {} \; &>/var/log/changeip
+ [ -e "/etc/nginx" ] && find /etc/nginx -name 'conf*' -type f -exec $CHANGEIP_SED -i "s#$OLDIP4:443##g" {} \; &>/var/log/changeip
+ [ -e "/etc/apache2" ] && find /etc/apache2 -name 'conf*' -type f -exec $CHANGEIP_SED -i "s#$OLDIP4:443##g" {} \; &>/var/log/changeip
+ else
+ printf_green "ipv4 works so continuing with IPV4 changes: $NEWIP4"
+ echo "$NEWIP4" | grep -v '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/myip4.txt"
+ echo "$NEWIP4" | grep -v '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/oldipv4.txt"
+ [ -e "/root/.local/bin" ] && find /root/.local/bin -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/hosts" ] && find /etc/hosts* -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/issue" ] && find /etc/issue* -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/proftpd.conf" ] && find /etc/proftpd* -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/apache2" ] && find /etc/apache2 -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/httpd" ] && find /etc/httpd -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/nginx" ] && find /etc/nginx -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/postfix" ] && find /etc/postfix -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/motd" ] && find /etc/motd* -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/named" ] && find /etc/named -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/var/www" ] && find /var/www -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/var/named" ] && find /var/named -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/webmin" ] && find /etc/webmin -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/usermin" ] && find /etc/usermin -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/var/lib/system-scripts" ] && find /var/lib/system-scripts -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/sysconfig/network-scripts" ] && find /etc/sysconfig/network-scripts/ifcfg-* -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "$CHANGE_IP_VAR_DIR" ] && find "$CHANGE_IP_VAR_DIR" -type f -exec $CHANGEIP_SED -i "s#$OLDIP4#$NEWIP4#g" {} \; &>/var/log/changeip
+ if [ "$OLDIP4" != "10.0.20.1" ]; then
+ [ -e "/root/.local/bin" ] && find /root/.local/bin -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/hosts" ] && find /etc/hosts* -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/issue" ] && find /etc/issue* -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/proftpd.conf" ] && find /etc/proftpd* -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/apache2" ] && find /etc/apache2 -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/httpd" ] && find /etc/httpd -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/nginx" ] && find /etc/nginx -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/postfix" ] && find /etc/postfix -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/motd" ] && find /etc/motd* -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/named" ] && find /etc/named -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/var/www" ] && find /var/www -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/var/named" ] && find /var/named -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/webmin" ] && find /etc/webmin -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/usermin" ] && find /etc/usermin -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ [ -e "/etc/sysconfig/network-scripts" ] && find /etc/sysconfig/network-scripts/ifcfg-* -type f -exec $CHANGEIP_SED -i "s#10.0.20.1#$NEWIP4#g" {} \; &>/var/log/changeip
+ fi
+ fi
+ # Change IPV6
+ if [ -z "$NEWIP6" ]; then
+ printf_red "no ipv6"
+ rm -Rf "$CHANGE_IP_VAR_DIR/myip6.txt" "$CHANGE_IP_VAR_DIR/oldipv6.txt"
+ [ -e "/etc/httpd" ] && find /etc/httpd -name 'conf*' -type f -exec $CHANGEIP_SED -i "s#\[$OLDIP6\]:443##g" {} \; &>/var/log/changeip
+ [ -e "/etc/nginx" ] && find /etc/nginx -name 'conf*' -type f -exec $CHANGEIP_SED -i "s#\[$OLDIP6\]:443##g" {} \; &>/var/log/changeip
+ [ -e "/etc/apache2" ] && find /etc/apache2 -name 'conf*' -type f -exec $CHANGEIP_SED -i "s#\[$OLDIP6\]:443##g" {} \; &>/var/log/changeip
+ else
+ printf_green "ipv6 works so continuing with IPV6 changes: $NEWIP6"
+ echo "$NEWIP6" | grep -v '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/myip6.txt"
+ echo "$NEWIP6" | grep -v '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/oldipv6.txt"
+ [ -e "/root/.local/bin" ] && find /root/.local/bin -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/postfix" ] && find /etc/postfix -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/apache2" ] && find /etc/apache2 -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/httpd" ] && find /etc/httpd -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/nginx" ] && find /etc/nginx -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/proftpd.conf" ] && find /etc/proftpd* -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/named" ] && find /etc/named -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/var/named" ] && find /var/named -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/var/www" ] && find /var/www -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; >/dev/null 2>&1
+ [ -e "/etc/hosts" ] && find /etc/hosts* -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/issue" ] && find /etc/issue* -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/motd" ] && find /etc/motd* -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/webmin" ] && find /etc/webmin -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/casjaysdev" ] && find /etc/casjaysdev -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/sysconfig/network-scripts" ] && find /etc/sysconfig/network-scripts/ifcfg-* -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "$CHANGE_IP_VAR_DIR" ] && find "$CHANGE_IP_VAR_DIR" -type f -exec $CHANGEIP_SED -i "s#$OLDIP6#$NEWIP6#g" {} \; &>/var/log/changeip
+ if [ "$NEWIP6" != "2001:db8:edfa:1234:5678::e1a2" ]; then
+ [ -e "/root/.local/bin" ] && find /root/.local/bin -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/postfix" ] && find /etc/postfix -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/apache2" ] && find /etc/apache2 -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/httpd" ] && find /etc/httpd -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/nginx" ] && find /etc/nginx -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/proftpd.conf" ] && find /etc/proftpd* -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/named" ] && find /etc/named -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/var/named" ] && find /var/named -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/var/www" ] && find /var/www -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; >/dev/null 2>&1
+ [ -e "/etc/hosts" ] && find /etc/hosts* -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/issue" ] && find /etc/issue* -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/motd" ] && find /etc/motd* -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/webmin" ] && find /etc/webmin -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/casjaysdev" ] && find /etc/casjaysdev -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ [ -e "/etc/sysconfig/network-scripts" ] && find /etc/sysconfig/network-scripts/ifcfg-* -type f -exec $CHANGEIP_SED -i "s#2001:db8:edfa:1234:5678::e1a2#$NEWIP6#g" {} \; &>/var/log/changeip
+ fi
+ fi
+ # Change Domain
+ printf_green "Changing the domain to: $NEWDOM"
+ echo "$NEWDOM" | grep -v '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/mydomain.txt"
+ echo "$NEWDOM" | grep -v '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/olddomain.txt"
+ [ -e "/root/.local/bin" ] && find /root/.local/bin -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/postfix" ] && find /etc/postfix -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/apache2" ] && find /etc/httpd -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/httpd" ] && find /etc/httpd -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/nginx" ] && find /etc/nginx -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/proftpd.conf" ] && find /etc/proftpd* -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/named" ] && find /etc/named -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/var/named" ] && find /var/named -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/var/www" ] && find /var/www -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; >/dev/null 2>&1
+ [ -e "/etc/hosts" ] && find /etc/hosts* -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/issue" ] && find /etc/issue* -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/motd" ] && find /etc/motd* -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/munin" ] && find /etc/munin -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/rc.d/rc.local" ] && find /etc/rc.d/rc.local -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/cron.d" ] && find /etc/cron* -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/casjaysdev" ] && find /etc/casjaysdev -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/webmin" ] && find /etc/webmin -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/webalizer" ] && find /etc/webalizer* -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/uptimed.conf" ] && find /etc/uptimed.conf -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "$CHANGE_IP_VAR_DIR" ] && find "$CHANGE_IP_VAR_DIR" -type f -exec $CHANGEIP_SED -i "s#$OLDDOM#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/root/.local/bin" ] && find /root/.local/bin -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ if [ "$NEWDOM" != "myserverdomainname" ]; then
+ [ -e "/etc/postfix" ] && find /etc/postfix -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/apache2" ] && find /etc/httpd -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/httpd" ] && find /etc/httpd -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/nginx" ] && find /etc/nginx -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/proftpd.conf" ] && find /etc/proftpd* -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/named" ] && find /etc/named -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/var/named" ] && find /var/named -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/var/www" ] && find /var/www -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; >/dev/null 2>&1
+ [ -e "/etc/hosts" ] && find /etc/hosts* -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/issue" ] && find /etc/issue* -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/motd" ] && find /etc/motd* -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/munin" ] && find /etc/munin -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/rc.d/rc.local" ] && find /etc/rc.d/rc.local -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/cron.d" ] && find /etc/cron* -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/casjaysdev" ] && find /etc/casjaysdev -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/webmin" ] && find /etc/webmin -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/webalizer" ] && find /etc/webalizer* -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ [ -e "/etc/uptimed.conf" ] && find /etc/uptimed.conf -type f -exec $CHANGEIP_SED -i "s#myserverdomainname#$NEWDOM#g" {} \; &>/var/log/changeip
+ fi
+ # Change Short HostName
+ printf_green "Setting the hostname to: $NEWSHORT"
+ echo "$NEWSHORT" | grep -v '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/myshort.txt"
+ echo "$NEWSHORT" | grep -v '^$' | head -n1 | grep '^' >"$CHANGE_IP_VAR_DIR/oldshort.txt"
+ [ -e "/root/.local/bin" ] && find /root/.local/bin -type f -exec $CHANGEIP_SED -i "s#$OLDSHORT#$NEWSHORT#g" {} \; &>/var/log/changeip
+ [ -e "/etc/casjaysdev" ] && find /etc/casjaysdev -type f -exec $CHANGEIP_SED -i "s#$OLDSHORT#$NEWSHORT#g" {} \; &>/var/log/changeip
+ [ -e "/etc/apache2" ] && find /etc/apache2 -type f -exec $CHANGEIP_SED -i "s#$OLDSHORT#$NEWSHORT#g" {} \; &>/var/log/changeip
+ [ -e "/etc/httpd" ] && find /etc/httpd -type f -exec $CHANGEIP_SED -i "s#$OLDSHORT#$NEWSHORT#g" {} \; &>/var/log/changeip
+ [ -e "/etc/nginx" ] && find /etc/nginx -type f -exec $CHANGEIP_SED -i "s#$OLDSHORT#$NEWSHORT#g" {} \; &>/var/log/changeip
+ [ -e "$CHANGE_IP_VAR_DIR" ] && find "$CHANGE_IP_VAR_DIR" -type f -exec $CHANGEIP_SED -i "s#$OLDSHORT#$NEWSHORT#g" {} \; &>/var/log/changeip
+ if [ "$NEWSHORT" != "myserverhostname" ]; then
+ [ -e "/root/.local/bin" ] && find /root/.local/bin -type f -exec $CHANGEIP_SED -i "s#myserverhostname#$NEWSHORT#g" {} \; &>/var/log/changeip
+ [ -e "/etc/casjaysdev" ] && find /etc/casjaysdev -type f -exec $CHANGEIP_SED -i "s#myserverhostname#$NEWSHORT#g" {} \; &>/var/log/changeip
+ [ -e "/etc/apache2" ] && find /etc/apache2 -type f -exec $CHANGEIP_SED -i "s#myserverhostname#$NEWSHORT#g" {} \; &>/var/log/changeip
+ [ -e "/etc/httpd" ] && find /etc/httpd -type f -exec $CHANGEIP_SED -i "s#myserverhostname#$NEWSHORT#g" {} \; &>/var/log/changeip
+ [ -e "/etc/nginx" ] && find /etc/nginx -type f -exec $CHANGEIP_SED -i "s#myserverhostname#$NEWSHORT#g" {} \; &>/var/log/changeip
+ fi
+ # Print status
+ FULL_HOSTNAME="$(hostname -f | grep '^' || echo '')"
+ [ -z "$FULL_HOSTNAME" ] || printf_cyan "The full hostname is $FULL_HOSTNAME"
+ [ -z "$NEWSHORT" ] || [ "$OLDSHORT" = "$NEWSHORT" ] || printf_cyan "Changed the HOSTNAME from $OLDSHORT to $NEWSHORT"
+ [ -z "$NEWDOM" ] || [ "$OLDDOM" = "$NEWDOM" ] || printf_cyan "Changed the DOMAIN from $OLDDOM to $NEWDOM"
+ [ -z "$NEWIP4" ] || [ "$OLDIP4" = "$NEWIP4" ] || printf_cyan "Changed the IP4 from $OLDIP4 to $NEWIP4"
+ [ -z "$NEWIP6" ] || [ "$OLDIP6" = "$NEWIP6" ] || printf_cyan "Changed the IP6 from $OLDIP6 to $NEWIP6"
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/cheat.sh b/bin/cheat.sh
new file mode 100755
index 000000000..6251003e7
--- /dev/null
+++ b/bin/cheat.sh
@@ -0,0 +1,598 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042200-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : cheat.sh --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 22:00 EDT
+# @@File : cheat.sh
+# @@Description : Get help with commands
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042200-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CHEAT_SH_REQUIRE_SUDO="${CHEAT_SH_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CHEAT_SH_CONFIG_DIR/$CHEAT_SH_CONFIG_FILE"
+ fi
+ [ -d "$CHEAT_SH_CONFIG_DIR" ] || mkdir -p "$CHEAT_SH_CONFIG_DIR"
+ [ -d "$CHEAT_SH_CONFIG_BACKUP_DIR" ] || mkdir -p "$CHEAT_SH_CONFIG_BACKUP_DIR"
+ [ -f "$CHEAT_SH_CONFIG_DIR/$CHEAT_SH_CONFIG_FILE" ] &&
+ cp -Rf "$CHEAT_SH_CONFIG_DIR/$CHEAT_SH_CONFIG_FILE" "$CHEAT_SH_CONFIG_BACKUP_DIR/$CHEAT_SH_CONFIG_FILE.$$"
+ cat <"$CHEAT_SH_CONFIG_DIR/$CHEAT_SH_CONFIG_FILE"
+# Settings for cheat.sh
+CHEAT_SH_URL="${CHEAT_SH_URL:-}"
+CHEAT_SH_UPDATE_URL="${CHEAT_SH_UPDATE_URL:-}"
+CHEAT_SH_HOME="${CHEAT_SH_HOME:-}"
+CHEAT_SH_BIN_DIR="${CHEAT_SH_BIN_DIR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CHEAT_SH_OUTPUT_COLOR_1="${CHEAT_SH_OUTPUT_COLOR_1:-}"
+CHEAT_SH_OUTPUT_COLOR_2="${CHEAT_SH_OUTPUT_COLOR_2:-}"
+CHEAT_SH_OUTPUT_COLOR_GOOD="${CHEAT_SH_OUTPUT_COLOR_GOOD:-}"
+CHEAT_SH_OUTPUT_COLOR_ERROR="${CHEAT_SH_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CHEAT_SH_NOTIFY_ENABLED="${CHEAT_SH_NOTIFY_ENABLED:-}"
+CHEAT_SH_GOOD_NAME="${CHEAT_SH_GOOD_NAME:-}"
+CHEAT_SH_ERROR_NAME="${CHEAT_SH_ERROR_NAME:-}"
+CHEAT_SH_GOOD_MESSAGE="${CHEAT_SH_GOOD_MESSAGE:-}"
+CHEAT_SH_ERROR_MESSAGE="${CHEAT_SH_ERROR_MESSAGE:-}"
+CHEAT_SH_NOTIFY_CLIENT_NAME="${CHEAT_SH_NOTIFY_CLIENT_NAME:-}"
+CHEAT_SH_NOTIFY_CLIENT_ICON="${CHEAT_SH_NOTIFY_CLIENT_ICON:-}"
+CHEAT_SH_NOTIFY_CLIENT_URGENCY="${CHEAT_SH_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CHEAT_SH_CONFIG_DIR/$CHEAT_SH_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CHEAT_SH_CONFIG_DIR/$CHEAT_SH_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "cheat.sh: Get help with commands - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: cheat.sh [options] [commands]"
+ __printf_line "TOPIC - show cheat sheet on the TOPIC"
+ __printf_line "TOPIC/SUB - show cheat sheet on the SUB topic in TOPIC"
+ __printf_line "~KEYWORD - search cheat sheets for KEYWORD"
+ __printf_line ":list - list all cheat sheets"
+ __printf_line ":post - how to post new cheat sheet"
+ __printf_line ":styles - list of color styles"
+ __printf_line ":styles-demo - show color styles usage examples"
+ __printf_line ":random - fetches a random cheat sheet"
+ __printf_line ":help - this page"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CHEAT_SH_REQUIRE_SUDO" = "yes" ] && [ -z "$CHEAT_SH_REQUIRE_SUDO_RUN" ]; then
+ export CHEAT_SH_REQUIRE_SUDO="no"
+ export CHEAT_SH_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CHEAT_SH_TEMP_FILE" ] && rm -Rf "$CHEAT_SH_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__curl() { curl -q -LSSf --max-time 2 "$*"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__update() {
+ local UPDATE_FILE=""
+ __user_is_root &&
+ UPDATE_FILE="$CHEAT_SH_BIN_DIR/cheat.sh" ||
+ UPDATE_FILE="$HOME/.local/bin/cheat.sh"
+ printf_blue "Grabbing update from: $CHEAT_SH_UPDATE_URL"
+ __curl "$CHEAT_SH_UPDATE_URL" -o "$UPDATE_FILE" 2>/dev/null && true || false
+ if [ $? -eq 0 ]; then
+ printf_cyan "Successfully updated: $UPDATE_FILE"
+ return 0
+ else
+ printf_exit "Failed to update: $UPDATE_FILE"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_completion() {
+ type _cheat.sh_completion 2>&1 | grep -iq 'is a function' && return
+ [ -z "$CHEAT_SH_FORCE" ] && [ -f "$CHEAT_SH_CONFIG_DIR/completion.txt" ] && return
+ cat </dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CHEAT_SH_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CHEAT_SH_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CHEAT_SH_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CHEAT_SH_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CHEAT_SH_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CHEAT_SH_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=",shell:,standalone-install:,mode,update"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CHEAT_SH_SILENT="true"
+ ;;
+ --shell | --standalone-install | --mode)
+ [ -n "$CHEAT_SH_VARS" ] && CHEAT_SH_VARS="$1 "$2 || CHEAT_SH_VARS+="$1 $2"
+ shift 2
+ ;;
+ --update)
+ shift 1
+ __update
+ exit $?
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CHEAT_SH_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CHEAT_SH_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CHEAT_SH_CWD="$1" && shift 1 || CHEAT_SH_CWD="${CHEAT_SH_CWD:-$PWD}"
+CHEAT_SH_CWD="$(realpath "${CHEAT_SH_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CHEAT_SH_CWD" ] && cd "$CHEAT_SH_CWD"; then
+# if [ "$CHEAT_SH_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CHEAT_SH_CWD"
+# fi
+# else
+# printf_exit "💔 $CHEAT_SH_CWD does not exist 💔"
+# fi
+export CHEAT_SH_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+export CHTSH="${CHTSH:-$CHEAT_SH_HOME}"
+export CHEAT_SH_URL="${CHEAT_SH_URL}"
+export CHEATSH_CACHE_TYPE="${CHEATSH_CACHE_TYPE:-none}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ $# -ne 0 ] || [ -n "$CHEAT_SH_VARS" ] || printf_exit "Usage: $APPNAME [options] [query]"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__create_completion
+__execute_cheatsh "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/check-for-updates b/bin/check-for-updates
new file mode 100755
index 000000000..b755cf197
--- /dev/null
+++ b/bin/check-for-updates
@@ -0,0 +1,615 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042218-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : check-for-updates --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 22:18 EDT
+# @@File : check-for-updates
+# @@Description : check for package updates
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042218-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CHECK_FOR_UPDATES_REQUIRE_SUDO="${CHECK_FOR_UPDATES_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CHECK_FOR_UPDATES_CONFIG_DIR/$CHECK_FOR_UPDATES_CONFIG_FILE"
+ fi
+ [ -d "$CHECK_FOR_UPDATES_CONFIG_DIR" ] || mkdir -p "$CHECK_FOR_UPDATES_CONFIG_DIR"
+ [ -d "$CHECK_FOR_UPDATES_CONFIG_BACKUP_DIR" ] || mkdir -p "$CHECK_FOR_UPDATES_CONFIG_BACKUP_DIR"
+ [ -f "$CHECK_FOR_UPDATES_CONFIG_DIR/$CHECK_FOR_UPDATES_CONFIG_FILE" ] &&
+ cp -Rf "$CHECK_FOR_UPDATES_CONFIG_DIR/$CHECK_FOR_UPDATES_CONFIG_FILE" "$CHECK_FOR_UPDATES_CONFIG_BACKUP_DIR/$CHECK_FOR_UPDATES_CONFIG_FILE.$$"
+ cat <"$CHECK_FOR_UPDATES_CONFIG_DIR/$CHECK_FOR_UPDATES_CONFIG_FILE"
+# Settings for check-for-updates
+CHECK_FOR_UPDATES_ENABLE_UPDATE_NAG="${CHECK_FOR_UPDATES_ENABLE_UPDATE_NAG:-}"
+CHECK_FOR_UPDATES_SUDO_ASKPASS="${SUDO_ASKPASS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CHECK_FOR_UPDATES_OUTPUT_COLOR_1="${CHECK_FOR_UPDATES_OUTPUT_COLOR_1:-}"
+CHECK_FOR_UPDATES_OUTPUT_COLOR_2="${CHECK_FOR_UPDATES_OUTPUT_COLOR_2:-}"
+CHECK_FOR_UPDATES_OUTPUT_COLOR_GOOD="${CHECK_FOR_UPDATES_OUTPUT_COLOR_GOOD:-}"
+CHECK_FOR_UPDATES_OUTPUT_COLOR_ERROR="${CHECK_FOR_UPDATES_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CHECK_FOR_UPDATES_NOTIFY_ENABLED="${CHECK_FOR_UPDATES_NOTIFY_ENABLED:-}"
+CHECK_FOR_UPDATES_GOOD_NAME="${CHECK_FOR_UPDATES_GOOD_NAME:-}"
+CHECK_FOR_UPDATES_ERROR_NAME="${CHECK_FOR_UPDATES_ERROR_NAME:-}"
+CHECK_FOR_UPDATES_GOOD_MESSAGE="${CHECK_FOR_UPDATES_GOOD_MESSAGE:-}"
+CHECK_FOR_UPDATES_ERROR_MESSAGE="${CHECK_FOR_UPDATES_ERROR_MESSAGE:-}"
+CHECK_FOR_UPDATES_NOTIFY_CLIENT_NAME="${CHECK_FOR_UPDATES_NOTIFY_CLIENT_NAME:-}"
+CHECK_FOR_UPDATES_NOTIFY_CLIENT_ICON="${CHECK_FOR_UPDATES_NOTIFY_CLIENT_ICON:-}"
+CHECK_FOR_UPDATES_NOTIFY_CLIENT_URGENCY="${CHECK_FOR_UPDATES_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CHECK_FOR_UPDATES_CONFIG_DIR/$CHECK_FOR_UPDATES_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CHECK_FOR_UPDATES_CONFIG_DIR/$CHECK_FOR_UPDATES_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "check-for-updates: check for package updates - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: check-for-updates [options]"
+ __printf_line " - Check if there are any update available"
+ __printf_line "--ask - Ask to update"
+ __printf_line "--force - Force a check"
+ __printf_line "--show - Show how many package to update"
+ __printf_line "--notify - Send a notification"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CHECK_FOR_UPDATES_REQUIRE_SUDO" = "yes" ] && [ -z "$CHECK_FOR_UPDATES_REQUIRE_SUDO_RUN" ]; then
+ export CHECK_FOR_UPDATES_REQUIRE_SUDO="no"
+ export CHECK_FOR_UPDATES_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CHECK_FOR_UPDATES_TEMP_FILE" ] && rm -Rf "$CHECK_FOR_UPDATES_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__update_count() {
+ local update_count=""
+ if __cmd_exists pkmgr; then
+ update_count=$(pkmgr check 2>/dev/null | head -n1 | grep '^')
+ else
+ # Brew update check
+ if __cmd_exists brew; then
+ update_count=$(brew outdated 2>/dev/null | grep -v Security | wc -l | grep '^')
+ # Arch update check
+ elif __cmd_exists pacman; then
+ update_count=$(pacman -Qu 2>/dev/null | wc -l | grep '^')
+ # yay doesn't do sudo
+ __cmd_exists yay && updates_aur=$(yay -Qum 2>/dev/null | wc -l | grep '^')
+ # add yay and pacman for total count
+ [ -n "$updates_aur" ] && update_count="$(($updates_aur + $updates))"
+ # Debian update check
+ elif __cmd_exists apt; then
+ update_count=$(apt -q -y --ignore-hold --allow-change-held-packages --allow-unauthenticated -s dist-upgrade 2>/dev/null | grep '^Inst' | wc -l | grep '^')
+ # Fedora update check
+ elif __cmd_exists dnf; then
+ update_count=$(dnf -q check-update 2>/dev/null | grep -v 'Security' | wc -l | grep '^')
+ # CentOS update check
+ elif __cmd_exists yum; then
+ update_count=$(yum -q check-update 2>/dev/null | grep -v 'Security' | wc -l | grep '^')
+ # Alpinelinux
+ elif __cmd_exists apk; then
+ update_count="$(apk -u list | wc -l)"
+ fi
+ fi
+ [ -n "$update_count" ] || update_count="0"
+ printf '%s\n' "$update_count"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_update_check() {
+ updates="$(__update_count)"
+ if [ "$updates" -eq 0 ]; then
+ __rm_rf "$CHECK_FOR_UPDATES_CACHE_DIR/update_check"
+ else
+ echo "$updates" >"$CHECK_FOR_UPDATES_CACHE_DIR/update_check"
+ fi
+
+ if [ "$CHECK_FOR_UPDATES_SHOW" = "true" ]; then
+ echo "$updates"
+ return
+ fi
+
+ if [ "$CHECK_FOR_UPDATES_NOTIFY_ENABLED" = "yes" ]; then
+ if [ "$updates" -ne 0 ]; then
+ if [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ]; then
+ __notifications "System Updates:" "You have $updates update[s] available"
+ else
+ echo "$updates"
+ fi
+ else
+ __notifications "System Updates:" "No updates available"
+ fi
+ fi
+
+ if [ "$CHECK_FOR_UPDATES_ENABLE_UPDATE_NAG" = "yes" ]; then
+ [ "$updates" -eq 0 ] || __ask_me_to_update "$updates"
+ return $?
+ fi
+
+ if [ "$CHECK_FOR_UPDATES_ASK" = "true" ]; then
+ __ask_me_to_update "$updates"
+ return $?
+ fi
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__ask_me_to_update() {
+ local show_updates="${1:-$updates}"
+ if [ "$1" -eq 0 ]; then
+ __notifications "Update Check" "You don't have any updates"
+ return 0
+ else
+ CHECK_FOR_UPDATES_ENABLE_UPDATE_NAG="no"
+ local mess="You have $show_updates available updates\nWould you like to update the package[s]?"
+ local command="pkmgr silent upgrade"
+ ask_yes_no_question "$mess" "$command"
+ return $?
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CHECK_FOR_UPDATES_CONFIG_FILE="${CHECK_FOR_UPDATES_CONFIG_FILE:-settings.conf}"
+CHECK_FOR_UPDATES_CONFIG_DIR="${CHECK_FOR_UPDATES_CONFIG_DIR:-$HOME/.config/myscripts/check-for-updates}"
+CHECK_FOR_UPDATES_CONFIG_BACKUP_DIR="${CHECK_FOR_UPDATES_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/check-for-updates/backups}"
+CHECK_FOR_UPDATES_LOG_DIR="${CHECK_FOR_UPDATES_LOG_DIR:-$HOME/.local/log/check-for-updates}"
+CHECK_FOR_UPDATES_TEMP_DIR="${CHECK_FOR_UPDATES_TEMP_DIR:-$HOME/.local/tmp/system_scripts/check-for-updates}"
+CHECK_FOR_UPDATES_CACHE_DIR="${CHECK_FOR_UPDATES_CACHE_DIR:-$HOME/.cache/check-for-updates}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CHECK_FOR_UPDATES_OUTPUT_COLOR_1="${CHECK_FOR_UPDATES_OUTPUT_COLOR_1:-33}"
+CHECK_FOR_UPDATES_OUTPUT_COLOR_2="${CHECK_FOR_UPDATES_OUTPUT_COLOR_2:-5}"
+CHECK_FOR_UPDATES_OUTPUT_COLOR_GOOD="${CHECK_FOR_UPDATES_OUTPUT_COLOR_GOOD:-2}"
+CHECK_FOR_UPDATES_OUTPUT_COLOR_ERROR="${CHECK_FOR_UPDATES_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CHECK_FOR_UPDATES_NOTIFY_ENABLED="${CHECK_FOR_UPDATES_NOTIFY_ENABLED:-yes}"
+CHECK_FOR_UPDATES_GOOD_NAME="${CHECK_FOR_UPDATES_GOOD_NAME:-Great:}"
+CHECK_FOR_UPDATES_ERROR_NAME="${CHECK_FOR_UPDATES_ERROR_NAME:-Error:}"
+CHECK_FOR_UPDATES_GOOD_MESSAGE="${CHECK_FOR_UPDATES_GOOD_MESSAGE:-Update successful}"
+CHECK_FOR_UPDATES_ERROR_MESSAGE="${CHECK_FOR_UPDATES_ERROR_MESSAGE:-Update has failed}"
+CHECK_FOR_UPDATES_NOTIFY_CLIENT_NAME="${CHECK_FOR_UPDATES_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CHECK_FOR_UPDATES_NOTIFY_CLIENT_ICON="${CHECK_FOR_UPDATES_NOTIFY_CLIENT_ICON:-software}"
+CHECK_FOR_UPDATES_NOTIFY_CLIENT_URGENCY="${CHECK_FOR_UPDATES_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CHECK_FOR_UPDATES_ENABLE_UPDATE_NAG="${CHECK_FOR_UPDATES_ENABLE_UPDATE_NAG:-yes}"
+CHECK_FOR_UPDATES_SUDO_ASKPASS="${SUDO_ASKPASS:-/usr/local/bin/ask_for_password}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CHECK_FOR_UPDATES_CONFIG_DIR/$CHECK_FOR_UPDATES_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CHECK_FOR_UPDATES_CONFIG_DIR/$CHECK_FOR_UPDATES_CONFIG_FILE" ] && . "$CHECK_FOR_UPDATES_CONFIG_DIR/$CHECK_FOR_UPDATES_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CHECK_FOR_UPDATES_LOG_DIR" ] || mkdir -p "$CHECK_FOR_UPDATES_LOG_DIR" |& __devnull
+[ -d "$CHECK_FOR_UPDATES_TEMP_DIR" ] || mkdir -p "$CHECK_FOR_UPDATES_TEMP_DIR" |& __devnull
+[ -d "$CHECK_FOR_UPDATES_CACHE_DIR" ] || mkdir -p "$CHECK_FOR_UPDATES_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CHECK_FOR_UPDATES_TEMP_FILE="${CHECK_FOR_UPDATES_TEMP_FILE:-$(mktemp $CHECK_FOR_UPDATES_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CHECK_FOR_UPDATES_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CHECK_FOR_UPDATES_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CHECK_FOR_UPDATES_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CHECK_FOR_UPDATES_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CHECK_FOR_UPDATES_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CHECK_FOR_UPDATES_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=",force,ask,show,notify"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CHECK_FOR_UPDATES_SILENT="true"
+ ;;
+ --force)
+ __rm_rf "$CHECK_FOR_UPDATES_CACHE_DIR/update_check"
+ ;;
+ --ask)
+ shift 1
+ CHECK_FOR_UPDATES_ASK="true"
+ ;;
+ --show)
+ shift 1
+ CHECK_FOR_UPDATES_SHOW="true"
+ ;;
+ --notify)
+ shift 1
+ CHECK_FOR_UPDATES_NOTIFY_ENABLED="yes"
+ CHECK_FOR_UPDATES_ENABLE_UPDATE_NAG="no"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CHECK_FOR_UPDATES_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CHECK_FOR_UPDATES_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CHECK_FOR_UPDATES_CWD="$1" && shift 1 || CHECK_FOR_UPDATES_CWD="${CHECK_FOR_UPDATES_CWD:-$PWD}"
+CHECK_FOR_UPDATES_CWD="$(realpath "${CHECK_FOR_UPDATES_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CHECK_FOR_UPDATES_CWD" ] && cd "$CHECK_FOR_UPDATES_CWD"; then
+# if [ "$CHECK_FOR_UPDATES_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CHECK_FOR_UPDATES_CWD"
+# fi
+# else
+# printf_exit "💔 $CHECK_FOR_UPDATES_CWD does not exist 💔"
+# fi
+export CHECK_FOR_UPDATES_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+export SUDO_ASKPASS="${CHECK_FOR_UPDATES_SUDO_ASKPASS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+shift $#
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__execute_update_check
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/check_app b/bin/check_app
new file mode 100755
index 000000000..e73c4e88e
--- /dev/null
+++ b/bin/check_app
@@ -0,0 +1,539 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042208-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : check_app --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 22:08 EDT
+# @@File : check_app
+# @@Description : check for app and install if missing
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042208-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CHECK_APP_REQUIRE_SUDO="${CHECK_APP_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CHECK_APP_CONFIG_DIR/$CHECK_APP_CONFIG_FILE"
+ fi
+ [ -d "$CHECK_APP_CONFIG_DIR" ] || mkdir -p "$CHECK_APP_CONFIG_DIR"
+ [ -d "$CHECK_APP_CONFIG_BACKUP_DIR" ] || mkdir -p "$CHECK_APP_CONFIG_BACKUP_DIR"
+ [ -f "$CHECK_APP_CONFIG_DIR/$CHECK_APP_CONFIG_FILE" ] &&
+ cp -Rf "$CHECK_APP_CONFIG_DIR/$CHECK_APP_CONFIG_FILE" "$CHECK_APP_CONFIG_BACKUP_DIR/$CHECK_APP_CONFIG_FILE.$$"
+ cat <"$CHECK_APP_CONFIG_DIR/$CHECK_APP_CONFIG_FILE"
+# Settings for check_app
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CHECK_APP_OUTPUT_COLOR_1="${CHECK_APP_OUTPUT_COLOR_1:-}"
+CHECK_APP_OUTPUT_COLOR_2="${CHECK_APP_OUTPUT_COLOR_2:-}"
+CHECK_APP_OUTPUT_COLOR_GOOD="${CHECK_APP_OUTPUT_COLOR_GOOD:-}"
+CHECK_APP_OUTPUT_COLOR_ERROR="${CHECK_APP_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CHECK_APP_NOTIFY_ENABLED="${CHECK_APP_NOTIFY_ENABLED:-}"
+CHECK_APP_GOOD_NAME="${CHECK_APP_GOOD_NAME:-}"
+CHECK_APP_ERROR_NAME="${CHECK_APP_ERROR_NAME:-}"
+CHECK_APP_GOOD_MESSAGE="${CHECK_APP_GOOD_MESSAGE:-}"
+CHECK_APP_ERROR_MESSAGE="${CHECK_APP_ERROR_MESSAGE:-}"
+CHECK_APP_NOTIFY_CLIENT_NAME="${CHECK_APP_NOTIFY_CLIENT_NAME:-}"
+CHECK_APP_NOTIFY_CLIENT_ICON="${CHECK_APP_NOTIFY_CLIENT_ICON:-}"
+CHECK_APP_NOTIFY_CLIENT_URGENCY="${CHECK_APP_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CHECK_APP_CONFIG_DIR/$CHECK_APP_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CHECK_APP_CONFIG_DIR/$CHECK_APP_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "check_app: check for app and install if missing - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: check_app [options] [programName]"
+ __printf_line "[options] bash - Check for bash and prompt to install if missing"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CHECK_APP_REQUIRE_SUDO" = "yes" ] && [ -z "$CHECK_APP_REQUIRE_SUDO_RUN" ]; then
+ export CHECK_APP_REQUIRE_SUDO="no"
+ export CHECK_APP_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CHECK_APP_TEMP_FILE" ] && rm -Rf "$CHECK_APP_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__check_app() {
+ local cmd=""
+ local choice=""
+ local MISSING=()
+ local exitCode=0
+ export NOTIFY_CLIENT_ICON="software"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$APPNAME}"
+ for cmd in "${@}"; do
+ __cmd_exists "$cmd" || MISSING+=("$cmd")
+ done
+ if [ -n "${MISSING[*]}" ]; then
+ __notifications "${NOTIFY_CLIENT_NAME:-$APPNAME}" "Missing ${MISSING[*]}"
+ if [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ]; then
+ ask_yes_no_question "Would you like install ${MISSING[*]}" "pkmgr silent install ${MISSING[*]}" && exitCode=0 || exitCode=1
+ else
+ printf_red "The following apps are missing: ${MISSING[*]}"
+ printf_read_question "2" "Would you like install the missing packages? [y/N]" "1" "choice" "-s"
+ if printf_answer_yes "$choice"; then
+ for miss in $MISSING; do
+ __execute "pkmgr silent install ${MISSING[*]}" "Installing ${MISSING[*]}" && true || false
+ exitCode=$(($? + exitCode))
+ done
+ else
+ exitCode=$((exitCode + 1))
+ fi
+ fi
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CHECK_APP_CONFIG_FILE="${CHECK_APP_CONFIG_FILE:-settings.conf}"
+CHECK_APP_CONFIG_DIR="${CHECK_APP_CONFIG_DIR:-$HOME/.config/myscripts/check_app}"
+CHECK_APP_CONFIG_BACKUP_DIR="${CHECK_APP_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/check_app/backups}"
+CHECK_APP_LOG_DIR="${CHECK_APP_LOG_DIR:-$HOME/.local/log/check_app}"
+CHECK_APP_TEMP_DIR="${CHECK_APP_TEMP_DIR:-$HOME/.local/tmp/system_scripts/check_app}"
+CHECK_APP_CACHE_DIR="${CHECK_APP_CACHE_DIR:-$HOME/.cache/check_app}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CHECK_APP_OUTPUT_COLOR_1="${CHECK_APP_OUTPUT_COLOR_1:-33}"
+CHECK_APP_OUTPUT_COLOR_2="${CHECK_APP_OUTPUT_COLOR_2:-5}"
+CHECK_APP_OUTPUT_COLOR_GOOD="${CHECK_APP_OUTPUT_COLOR_GOOD:-2}"
+CHECK_APP_OUTPUT_COLOR_ERROR="${CHECK_APP_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CHECK_APP_NOTIFY_ENABLED="${CHECK_APP_NOTIFY_ENABLED:-yes}"
+CHECK_APP_GOOD_NAME="${CHECK_APP_GOOD_NAME:-Great:}"
+CHECK_APP_ERROR_NAME="${CHECK_APP_ERROR_NAME:-Error:}"
+CHECK_APP_GOOD_MESSAGE="${CHECK_APP_GOOD_MESSAGE:-No errors reported}"
+CHECK_APP_ERROR_MESSAGE="${CHECK_APP_ERROR_MESSAGE:-Failed to install}"
+CHECK_APP_NOTIFY_CLIENT_NAME="${CHECK_APP_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CHECK_APP_NOTIFY_CLIENT_ICON="${CHECK_APP_NOTIFY_CLIENT_ICON:-notification-new}"
+CHECK_APP_NOTIFY_CLIENT_URGENCY="${CHECK_APP_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CHECK_APP_CONFIG_DIR/$CHECK_APP_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CHECK_APP_CONFIG_DIR/$CHECK_APP_CONFIG_FILE" ] && . "$CHECK_APP_CONFIG_DIR/$CHECK_APP_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CHECK_APP_LOG_DIR" ] || mkdir -p "$CHECK_APP_LOG_DIR" |& __devnull
+[ -d "$CHECK_APP_TEMP_DIR" ] || mkdir -p "$CHECK_APP_TEMP_DIR" |& __devnull
+[ -d "$CHECK_APP_CACHE_DIR" ] || mkdir -p "$CHECK_APP_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CHECK_APP_TEMP_FILE="${CHECK_APP_TEMP_FILE:-$(mktemp $CHECK_APP_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CHECK_APP_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CHECK_APP_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CHECK_APP_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CHECK_APP_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CHECK_APP_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CHECK_APP_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CHECK_APP_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CHECK_APP_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CHECK_APP_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CHECK_APP_CWD="$1" && shift 1 || CHECK_APP_CWD="${CHECK_APP_CWD:-$PWD}"
+CHECK_APP_CWD="$(realpath "${CHECK_APP_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CHECK_APP_CWD" ] && cd "$CHECK_APP_CWD"; then
+# if [ "$CHECK_APP_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CHECK_APP_CWD"
+# fi
+# else
+# printf_exit "💔 $CHECK_APP_CWD does not exist 💔"
+# fi
+export CHECK_APP_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+CMD=()
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+[ "$#" -eq 0 ] && true || __check_app "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/clean-system b/bin/clean-system
new file mode 100755
index 000000000..6cbb319ab
--- /dev/null
+++ b/bin/clean-system
@@ -0,0 +1,570 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042230-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : clean-system --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 22:30 EDT
+# @@File : clean-system
+# @@Description : remove old logs
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : yes
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042230-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CLEAN_SYSTEM_REQUIRE_SUDO="${CLEAN_SYSTEM_REQUIRE_SUDO:-yes}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail braceexpand glob
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CLEAN_SYSTEM_CONFIG_DIR/$CLEAN_SYSTEM_CONFIG_FILE"
+ fi
+ [ -d "$CLEAN_SYSTEM_CONFIG_DIR" ] || mkdir -p "$CLEAN_SYSTEM_CONFIG_DIR"
+ [ -d "$CLEAN_SYSTEM_CONFIG_BACKUP_DIR" ] || mkdir -p "$CLEAN_SYSTEM_CONFIG_BACKUP_DIR"
+ [ -f "$CLEAN_SYSTEM_CONFIG_DIR/$CLEAN_SYSTEM_CONFIG_FILE" ] &&
+ cp -Rf "$CLEAN_SYSTEM_CONFIG_DIR/$CLEAN_SYSTEM_CONFIG_FILE" "$CLEAN_SYSTEM_CONFIG_BACKUP_DIR/$CLEAN_SYSTEM_CONFIG_FILE.$$"
+ cat <"$CLEAN_SYSTEM_CONFIG_DIR/$CLEAN_SYSTEM_CONFIG_FILE"
+# Settings for clean-system
+CLEAN_SYSTEM_DEFAULT_DAYS="${CLEAN_SYSTEM_DEFAULT_DAYS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CLEAN_SYSTEM_OUTPUT_COLOR_1="${CLEAN_SYSTEM_OUTPUT_COLOR_1:-}"
+CLEAN_SYSTEM_OUTPUT_COLOR_2="${CLEAN_SYSTEM_OUTPUT_COLOR_2:-}"
+CLEAN_SYSTEM_OUTPUT_COLOR_GOOD="${CLEAN_SYSTEM_OUTPUT_COLOR_GOOD:-}"
+CLEAN_SYSTEM_OUTPUT_COLOR_ERROR="${CLEAN_SYSTEM_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CLEAN_SYSTEM_NOTIFY_ENABLED="${CLEAN_SYSTEM_NOTIFY_ENABLED:-}"
+CLEAN_SYSTEM_GOOD_NAME="${CLEAN_SYSTEM_GOOD_NAME:-}"
+CLEAN_SYSTEM_ERROR_NAME="${CLEAN_SYSTEM_ERROR_NAME:-}"
+CLEAN_SYSTEM_GOOD_MESSAGE="${CLEAN_SYSTEM_GOOD_MESSAGE:-}"
+CLEAN_SYSTEM_ERROR_MESSAGE="${CLEAN_SYSTEM_ERROR_MESSAGE:-}"
+CLEAN_SYSTEM_NOTIFY_CLIENT_NAME="${CLEAN_SYSTEM_NOTIFY_CLIENT_NAME:-}"
+CLEAN_SYSTEM_NOTIFY_CLIENT_ICON="${CLEAN_SYSTEM_NOTIFY_CLIENT_ICON:-}"
+CLEAN_SYSTEM_NOTIFY_CLIENT_URGENCY="${CLEAN_SYSTEM_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CLEAN_SYSTEM_CONFIG_DIR/$CLEAN_SYSTEM_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CLEAN_SYSTEM_CONFIG_DIR/$CLEAN_SYSTEM_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "clean-system: remove old logs - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: clean-system [options]"
+ __printf_line "* - Clean all old log files and temp files"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ __user_is_root && return 0
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CLEAN_SYSTEM_REQUIRE_SUDO" = "yes" ] && [ -z "$CLEAN_SYSTEM_REQUIRE_SUDO_RUN" ]; then
+ export CLEAN_SYSTEM_REQUIRE_SUDO="no"
+ export CLEAN_SYSTEM_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CLEAN_SYSTEM_TEMP_FILE" ] && rm -Rf "$CLEAN_SYSTEM_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__rm_now() {
+ for file in "$@"; do
+ [ -e "$file" ] && rm -Rfv "$file" |& __devnull
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__rm_after() {
+ local time="-ctime +$1" && shift 1
+ for file in "$@"; do
+ [ -e "$file" ] && find -L "$file" $time -exec rm -Rfv {} \; |& __devnull
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__logrotate() {
+ __cmd_exists logrotate || return 2
+ rm -Rf /etc/cron.*/*logrotate* &>/dev/null
+ logrotate "$@" |& __devnull
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CLEAN_SYSTEM_CONFIG_FILE="${CLEAN_SYSTEM_CONFIG_FILE:-settings.conf}"
+CLEAN_SYSTEM_CONFIG_DIR="${CLEAN_SYSTEM_CONFIG_DIR:-$HOME/.config/myscripts/clean-system}"
+CLEAN_SYSTEM_CONFIG_BACKUP_DIR="${CLEAN_SYSTEM_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/clean-system/backups}"
+CLEAN_SYSTEM_LOG_DIR="${CLEAN_SYSTEM_LOG_DIR:-$HOME/.local/log/clean-system}"
+CLEAN_SYSTEM_TEMP_DIR="${CLEAN_SYSTEM_TEMP_DIR:-$HOME/.local/tmp/system_scripts/clean-system}"
+CLEAN_SYSTEM_CACHE_DIR="${CLEAN_SYSTEM_CACHE_DIR:-$HOME/.cache/clean-system}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CLEAN_SYSTEM_OUTPUT_COLOR_1="${CLEAN_SYSTEM_OUTPUT_COLOR_1:-33}"
+CLEAN_SYSTEM_OUTPUT_COLOR_2="${CLEAN_SYSTEM_OUTPUT_COLOR_2:-5}"
+CLEAN_SYSTEM_OUTPUT_COLOR_GOOD="${CLEAN_SYSTEM_OUTPUT_COLOR_GOOD:-2}"
+CLEAN_SYSTEM_OUTPUT_COLOR_ERROR="${CLEAN_SYSTEM_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CLEAN_SYSTEM_NOTIFY_ENABLED="${CLEAN_SYSTEM_NOTIFY_ENABLED:-yes}"
+CLEAN_SYSTEM_GOOD_NAME="${CLEAN_SYSTEM_GOOD_NAME:-Great:}"
+CLEAN_SYSTEM_ERROR_NAME="${CLEAN_SYSTEM_ERROR_NAME:-Error:}"
+CLEAN_SYSTEM_GOOD_MESSAGE="${CLEAN_SYSTEM_GOOD_MESSAGE:-No errors reported}"
+CLEAN_SYSTEM_ERROR_MESSAGE="${CLEAN_SYSTEM_ERROR_MESSAGE:-Errors were reported}"
+CLEAN_SYSTEM_NOTIFY_CLIENT_NAME="${CLEAN_SYSTEM_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CLEAN_SYSTEM_NOTIFY_CLIENT_ICON="${CLEAN_SYSTEM_NOTIFY_CLIENT_ICON:-notification-new}"
+CLEAN_SYSTEM_NOTIFY_CLIENT_URGENCY="${CLEAN_SYSTEM_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CLEAN_SYSTEM_DEFAULT_DAYS="${CLEAN_SYSTEM_DEFAULT_DAYS:-1}"
+CLEAN_SYSTEM_CURRENT_YEAR="${CLEAN_SYSTEM_CURRENT_YEAR:-$(date +"%Y")}"
+CLEAN_SYSTEM_PREVIOUS_YEAR="${CLEAN_SYSTEM_PREVIOUS_YEAR:-$(date --date='1 year ago' +%Y)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CLEAN_SYSTEM_CONFIG_DIR/$CLEAN_SYSTEM_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CLEAN_SYSTEM_CONFIG_DIR/$CLEAN_SYSTEM_CONFIG_FILE" ] && . "$CLEAN_SYSTEM_CONFIG_DIR/$CLEAN_SYSTEM_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CLEAN_SYSTEM_LOG_DIR" ] || mkdir -p "$CLEAN_SYSTEM_LOG_DIR" |& __devnull
+[ -d "$CLEAN_SYSTEM_TEMP_DIR" ] || mkdir -p "$CLEAN_SYSTEM_TEMP_DIR" |& __devnull
+[ -d "$CLEAN_SYSTEM_CACHE_DIR" ] || mkdir -p "$CLEAN_SYSTEM_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CLEAN_SYSTEM_TEMP_FILE="${CLEAN_SYSTEM_TEMP_FILE:-$(mktemp $CLEAN_SYSTEM_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CLEAN_SYSTEM_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CLEAN_SYSTEM_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CLEAN_SYSTEM_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CLEAN_SYSTEM_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CLEAN_SYSTEM_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CLEAN_SYSTEM_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CLEAN_SYSTEM_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CLEAN_SYSTEM_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CLEAN_SYSTEM_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CLEAN_SYSTEM_CWD="$1" && shift 1 || CLEAN_SYSTEM_CWD="${CLEAN_SYSTEM_CWD:-$PWD}"
+CLEAN_SYSTEM_CWD="$(realpath "${CLEAN_SYSTEM_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CLEAN_SYSTEM_CWD" ] && cd "$CLEAN_SYSTEM_CWD"; then
+# if [ "$CLEAN_SYSTEM_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CLEAN_SYSTEM_CWD"
+# fi
+# else
+# printf_exit "💔 $CLEAN_SYSTEM_CWD does not exist 💔"
+# fi
+export CLEAN_SYSTEM_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+printf_red "Cleaning old logs"
+if __user_is_root || __can_i_sudo; then
+ __logrotate -f /etc/logrotate.conf
+ __rm_now /var/log/bandwidth
+ __rm_now /var/log/*.gz
+ __rm_now /var/log/*/*.gz
+ __rm_now /var/log/*/*/*.gz
+ __rm_now /var/log/*.old
+ __rm_now /var/log/*/*.old
+ __rm_now /var/log/*/*/*.old
+ __rm_now /var/log/*.{0,1,2,3,4,5,6,7,8,9}
+ __rm_now /var/log/*/*.{0,1,2,3,4,5,6,7,8,9}
+ __rm_now /var/log/*/*/*.{0,1,2,3,4,5,6,7,8,9}
+ __rm_now /var/log/*{0,1,2,3,4,5,6,7,8,9}.gz
+ __rm_now /var/log/*$CLEAN_SYSTEM_CURRENT_YEAR*
+ __rm_now /var/log/*/*$CLEAN_SYSTEM_CURRENT_YEAR*
+ __rm_now /var/log/*/*/*$CLEAN_SYSTEM_CURRENT_YEAR*
+ __rm_now /var/log/*$CLEAN_SYSTEM_PREVIOUS_YEAR*
+ __rm_now /var/log/*/*$CLEAN_SYSTEM_PREVIOUS_YEAR*
+ __rm_now /var/log/*/*/*$CLEAN_SYSTEM_PREVIOUS_YEAR*
+ if [ -f "$HOME/.config/logrotate/config" ]; then
+ __logrotate -fv "$HOME/.config/logrotate/config"
+ fi
+ if [ -d "/var/spool/uptimed" ]; then
+ systemctl stop uptimed |& __devnull
+ __rm_now /var/spool/uptimed/*
+ fi
+ if [ -d "/var/lib/downtimed/downtimedb" ]; then
+ systemctl stop downtimed
+ __rm_now /var/lib/downtimed/downtimedb/*
+ touch /var/lib/downtimed/downtimedb/downtime.db |& __devnull
+ fi
+ __rm_after 1 /root/*/.local/tmp/*
+ __rm_after 7 /root/*/.local/log/*
+ __rm_after 1 /home/*/.local/tmp/*
+ __rm_after 7 /home/*/.local/log/*
+else
+ __rm_after 1 ~/.local/tmp/*
+ __rm_after 7 ~/*/.local/log/*
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/client-installs b/bin/client-installs
new file mode 100755
index 000000000..bc467b68b
--- /dev/null
+++ b/bin/client-installs
@@ -0,0 +1,586 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042238-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : client-installs --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 22:38 EDT
+# @@File : client-installs
+# @@Description : Install terminal scripts
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042238-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CLIENT_INSTALLS_REQUIRE_SUDO="${CLIENT_INSTALLS_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CLIENT_INSTALLS_CONFIG_DIR/$CLIENT_INSTALLS_CONFIG_FILE"
+ fi
+ [ -d "$CLIENT_INSTALLS_CONFIG_DIR" ] || mkdir -p "$CLIENT_INSTALLS_CONFIG_DIR"
+ [ -d "$CLIENT_INSTALLS_CONFIG_BACKUP_DIR" ] || mkdir -p "$CLIENT_INSTALLS_CONFIG_BACKUP_DIR"
+ [ -f "$CLIENT_INSTALLS_CONFIG_DIR/$CLIENT_INSTALLS_CONFIG_FILE" ] &&
+ cp -Rf "$CLIENT_INSTALLS_CONFIG_DIR/$CLIENT_INSTALLS_CONFIG_FILE" "$CLIENT_INSTALLS_CONFIG_BACKUP_DIR/$CLIENT_INSTALLS_CONFIG_FILE.$$"
+ cat <"$CLIENT_INSTALLS_CONFIG_DIR/$CLIENT_INSTALLS_CONFIG_FILE"
+# Settings for client-installs
+CLIENT_INSTALLS_DEFAULT_BINDIR="${CLIENT_INSTALLS_DEFAULT_BINDIR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CLIENT_INSTALLS_OUTPUT_COLOR_1="${CLIENT_INSTALLS_OUTPUT_COLOR_1:-}"
+CLIENT_INSTALLS_OUTPUT_COLOR_2="${CLIENT_INSTALLS_OUTPUT_COLOR_2:-}"
+CLIENT_INSTALLS_OUTPUT_COLOR_GOOD="${CLIENT_INSTALLS_OUTPUT_COLOR_GOOD:-}"
+CLIENT_INSTALLS_OUTPUT_COLOR_ERROR="${CLIENT_INSTALLS_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CLIENT_INSTALLS_NOTIFY_ENABLED="${CLIENT_INSTALLS_NOTIFY_ENABLED:-}"
+CLIENT_INSTALLS_GOOD_NAME="${CLIENT_INSTALLS_GOOD_NAME:-}"
+CLIENT_INSTALLS_ERROR_NAME="${CLIENT_INSTALLS_ERROR_NAME:-}"
+CLIENT_INSTALLS_GOOD_MESSAGE="${CLIENT_INSTALLS_GOOD_MESSAGE:-}"
+CLIENT_INSTALLS_ERROR_MESSAGE="${CLIENT_INSTALLS_ERROR_MESSAGE:-}"
+CLIENT_INSTALLS_NOTIFY_CLIENT_NAME="${CLIENT_INSTALLS_NOTIFY_CLIENT_NAME:-}"
+CLIENT_INSTALLS_NOTIFY_CLIENT_ICON="${CLIENT_INSTALLS_NOTIFY_CLIENT_ICON:-}"
+CLIENT_INSTALLS_NOTIFY_CLIENT_URGENCY="${CLIENT_INSTALLS_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CLIENT_INSTALLS_CONFIG_DIR/$CLIENT_INSTALLS_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CLIENT_INSTALLS_CONFIG_DIR/$CLIENT_INSTALLS_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "client-installs: Install terminal scripts - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: client-installs [options] [commands]"
+ __printf_line "lockdoor - "
+ __printf_line "misspell - "
+ __printf_line "anime - "
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CLIENT_INSTALLS_REQUIRE_SUDO" = "yes" ] && [ -z "$CLIENT_INSTALLS_REQUIRE_SUDO_RUN" ]; then
+ export CLIENT_INSTALLS_REQUIRE_SUDO="no"
+ export CLIENT_INSTALLS_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CLIENT_INSTALLS_TEMP_FILE" ] && rm -Rf "$CLIENT_INSTALLS_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__chmod() {
+ [ -f "$1" ] && chmod -f 755 "$1"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__err() {
+ printf_red "Failed to install ${1:-client}" && return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__installing() {
+ printf_blue "Installing $(basename -- "$1" 2>/dev/null)"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__ok() {
+ printf_green "Successfully installed ${1:-client}" && return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__curl() {
+ __installing "${name:-$2}" && curl -q -LSsf "$1" -o "$2" 2>/dev/null && __ok "$name" || __err "$name" || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__curl_src() {
+ __installing "${name:-$1}" && curl -q -LSsf "$1" | ${2:-} bash |& __devnull && __ok "$name" || __err "$name" || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__installed() {
+ cmd_exists "${name:-$1}" && printf_purple "${name:-$1} is already installed to $(builtin type -P "${name:-$1}" 2>/dev/null)" || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Clients
+__ani_cli() {
+ __curl "https://github.com/pystardust/ani-cli/raw/master/ani-cli" "$1" && __chmod "$1"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Installers
+__lockdoor_inst() {
+ __curl_src "https://github.com/SofianeHamlaoui/Lockdoor-Framework/raw/master/install.sh" "$1"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__misspell_inst() {
+ __curl_src "https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh" "$1"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CLIENT_INSTALLS_CONFIG_FILE="${CLIENT_INSTALLS_CONFIG_FILE:-settings.conf}"
+CLIENT_INSTALLS_CONFIG_DIR="${CLIENT_INSTALLS_CONFIG_DIR:-$HOME/.config/myscripts/client-installs}"
+CLIENT_INSTALLS_CONFIG_BACKUP_DIR="${CLIENT_INSTALLS_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/client-installs/backups}"
+CLIENT_INSTALLS_LOG_DIR="${CLIENT_INSTALLS_LOG_DIR:-$HOME/.local/log/client-installs}"
+CLIENT_INSTALLS_TEMP_DIR="${CLIENT_INSTALLS_TEMP_DIR:-$HOME/.local/tmp/system_scripts/client-installs}"
+CLIENT_INSTALLS_CACHE_DIR="${CLIENT_INSTALLS_CACHE_DIR:-$HOME/.cache/client-installs}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CLIENT_INSTALLS_OUTPUT_COLOR_1="${CLIENT_INSTALLS_OUTPUT_COLOR_1:-33}"
+CLIENT_INSTALLS_OUTPUT_COLOR_2="${CLIENT_INSTALLS_OUTPUT_COLOR_2:-5}"
+CLIENT_INSTALLS_OUTPUT_COLOR_GOOD="${CLIENT_INSTALLS_OUTPUT_COLOR_GOOD:-2}"
+CLIENT_INSTALLS_OUTPUT_COLOR_ERROR="${CLIENT_INSTALLS_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CLIENT_INSTALLS_NOTIFY_ENABLED="${CLIENT_INSTALLS_NOTIFY_ENABLED:-yes}"
+CLIENT_INSTALLS_GOOD_NAME="${CLIENT_INSTALLS_GOOD_NAME:-Great:}"
+CLIENT_INSTALLS_ERROR_NAME="${CLIENT_INSTALLS_ERROR_NAME:-Error:}"
+CLIENT_INSTALLS_GOOD_MESSAGE="${CLIENT_INSTALLS_GOOD_MESSAGE:-No errors reported}"
+CLIENT_INSTALLS_ERROR_MESSAGE="${CLIENT_INSTALLS_ERROR_MESSAGE:-Errors were reported}"
+CLIENT_INSTALLS_NOTIFY_CLIENT_NAME="${CLIENT_INSTALLS_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CLIENT_INSTALLS_NOTIFY_CLIENT_ICON="${CLIENT_INSTALLS_NOTIFY_CLIENT_ICON:-notification-new}"
+CLIENT_INSTALLS_NOTIFY_CLIENT_URGENCY="${CLIENT_INSTALLS_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CLIENT_INSTALLS_DEFAULT_BINDIR="${CLIENT_INSTALLS_DEFAULT_BINDIR:-$HOME/.local/bin}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CLIENT_INSTALLS_CONFIG_DIR/$CLIENT_INSTALLS_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CLIENT_INSTALLS_CONFIG_DIR/$CLIENT_INSTALLS_CONFIG_FILE" ] && . "$CLIENT_INSTALLS_CONFIG_DIR/$CLIENT_INSTALLS_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CLIENT_INSTALLS_LOG_DIR" ] || mkdir -p "$CLIENT_INSTALLS_LOG_DIR" |& __devnull
+[ -d "$CLIENT_INSTALLS_TEMP_DIR" ] || mkdir -p "$CLIENT_INSTALLS_TEMP_DIR" |& __devnull
+[ -d "$CLIENT_INSTALLS_CACHE_DIR" ] || mkdir -p "$CLIENT_INSTALLS_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CLIENT_INSTALLS_TEMP_FILE="${CLIENT_INSTALLS_TEMP_FILE:-$(mktemp $CLIENT_INSTALLS_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CLIENT_INSTALLS_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CLIENT_INSTALLS_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CLIENT_INSTALLS_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CLIENT_INSTALLS_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CLIENT_INSTALLS_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CLIENT_INSTALLS_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="anime lockdoor misspell"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CLIENT_INSTALLS_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ CLIENT_INSTALLS_CWD="$2"
+ [ -d "$CLIENT_INSTALLS_CWD" ] || mkdir -p "$CLIENT_INSTALLS_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CLIENT_INSTALLS_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CLIENT_INSTALLS_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CLIENT_INSTALLS_CWD="$1" && shift 1 || CLIENT_INSTALLS_CWD="${CLIENT_INSTALLS_CWD:-$PWD}"
+CLIENT_INSTALLS_CWD="$(realpath "${CLIENT_INSTALLS_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CLIENT_INSTALLS_CWD" ] && cd "$CLIENT_INSTALLS_CWD"; then
+# if [ "$CLIENT_INSTALLS_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CLIENT_INSTALLS_CWD"
+# fi
+# else
+# printf_exit "💔 $CLIENT_INSTALLS_CWD does not exist 💔"
+# fi
+export CLIENT_INSTALLS_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+__user_is_root && CLIENT_INSTALLS_DEFAULT_BINDIR="/usr/local/bin"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+while :; do
+ case "$@" in
+ anime)
+ shift 1
+ name="anime-cli"
+ __installed "$name" || __ani_cli "$CLIENT_INSTALLS_DEFAULT_BINDIR/$name"
+ ;;
+
+ lockdoor)
+ shift 1
+ name="lockdoor"
+ __installed "$name" || __lockdoor_inst sudo
+ ;;
+
+ misspell)
+ shift 1
+ name="misspell"
+ __installed "$name" || __misspell_inst eval
+ ;;
+
+ *)
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/clipboard b/bin/clipboard
new file mode 100755
index 000000000..a900c7ceb
--- /dev/null
+++ b/bin/clipboard
@@ -0,0 +1,600 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042242-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : clipboard --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 22:42 EDT
+# @@File : clipboard
+# @@Description : Access system clipboard
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042242-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CLIPBOARD_REQUIRE_SUDO="${CLIPBOARD_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CLIPBOARD_CONFIG_DIR/$CLIPBOARD_CONFIG_FILE"
+ fi
+ [ -d "$CLIPBOARD_CONFIG_DIR" ] || mkdir -p "$CLIPBOARD_CONFIG_DIR"
+ [ -d "$CLIPBOARD_CONFIG_BACKUP_DIR" ] || mkdir -p "$CLIPBOARD_CONFIG_BACKUP_DIR"
+ [ -f "$CLIPBOARD_CONFIG_DIR/$CLIPBOARD_CONFIG_FILE" ] &&
+ cp -Rf "$CLIPBOARD_CONFIG_DIR/$CLIPBOARD_CONFIG_FILE" "$CLIPBOARD_CONFIG_BACKUP_DIR/$CLIPBOARD_CONFIG_FILE.$$"
+ cat <"$CLIPBOARD_CONFIG_DIR/$CLIPBOARD_CONFIG_FILE"
+# Settings for clipboard
+CLIPBOARD_COMMAND="${CLIPBOARD_COMMAND:-}"
+CLIPBOARD_HISTORY_FILE="${CLIPBOARD_HISTORY_FILE:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CLIPBOARD_OUTPUT_COLOR_1="${CLIPBOARD_OUTPUT_COLOR_1:-}"
+CLIPBOARD_OUTPUT_COLOR_2="${CLIPBOARD_OUTPUT_COLOR_2:-}"
+CLIPBOARD_OUTPUT_COLOR_GOOD="${CLIPBOARD_OUTPUT_COLOR_GOOD:-}"
+CLIPBOARD_OUTPUT_COLOR_ERROR="${CLIPBOARD_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CLIPBOARD_NOTIFY_ENABLED="${CLIPBOARD_NOTIFY_ENABLED:-}"
+CLIPBOARD_GOOD_NAME="${CLIPBOARD_GOOD_NAME:-}"
+CLIPBOARD_ERROR_NAME="${CLIPBOARD_ERROR_NAME:-}"
+CLIPBOARD_GOOD_MESSAGE="${CLIPBOARD_GOOD_MESSAGE:-}"
+CLIPBOARD_ERROR_MESSAGE="${CLIPBOARD_ERROR_MESSAGE:-}"
+CLIPBOARD_NOTIFY_CLIENT_NAME="${CLIPBOARD_NOTIFY_CLIENT_NAME:-}"
+CLIPBOARD_NOTIFY_CLIENT_ICON="${CLIPBOARD_NOTIFY_CLIENT_ICON:-}"
+CLIPBOARD_NOTIFY_CLIENT_URGENCY="${CLIPBOARD_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CLIPBOARD_CONFIG_DIR/$CLIPBOARD_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CLIPBOARD_CONFIG_DIR/$CLIPBOARD_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "clipboard: Access system clipboard - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: clipboard [options] [text]"
+ __printf_line " - echo 'text'|clipboard"
+ __printf_line "clear - Clear clipboard"
+ __printf_line "show - Show the clipboard"
+ __printf_line "print - Print the last item copied"
+ __printf_line "put - Paste the contents"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CLIPBOARD_REQUIRE_SUDO" = "yes" ] && [ -z "$CLIPBOARD_REQUIRE_SUDO_RUN" ]; then
+ export CLIPBOARD_REQUIRE_SUDO="no"
+ export CLIPBOARD_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CLIPBOARD_TEMP_FILE" ] && rm -Rf "$CLIPBOARD_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__strip_code() { sed $'s/\e\\[[0-9;:]*[a-zA-Z]//g' || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__is_wayland() { { [ "$XDG_SESSION_TYPE" = "wayland" ] || grep -shqiE 'chromeos|Chromium OS' "/proc/version"; } && return 0 || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+crud_file() {
+ local ARG="$1"
+ local CONTENT="${contents}"
+ local DATE="$(date +"${CLIPBOARD_FORMAT_DATE:-%Y-%m-%d}")"
+ local TIME="$(date +"${CLIPBOARD_FORMAT_TIME:-%H:%M:%S}")"
+ local SPACER="----------------------------------------------------"
+ if [ "$ARG" == "show" ]; then
+ [ -f "$CLIPBOARD_HISTORY_FILE" ] && grep -sh '^' "$CLIPBOARD_HISTORY_FILE" | printf_readline $CLIP_OUTPUT_COLOR_2 || true
+ elif [ "$ARG" == "print" ]; then
+ __paste_clip
+ elif [ "$ARG" == "update" ]; then
+ if [ -n "$CONTENT" ]; then
+ printf '%s\n' "$contents" >"$CLIPBOARD_HISTORY_FILE_CUR"
+ printf "%s\n%s\n$SPACER\n\n" "# Clip from $DATE at $TIME #" "$contents" >>"$CLIPBOARD_HISTORY_FILE"
+ [ "$CLIPBOARD_NOTIFY" = "false" ] || [ -n "$CLIPBOARD_SILENT" ] || __notifications "$APPNAME" "$CONTENT"
+ fi
+ else
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CLIPBOARD_CONFIG_FILE="${CLIPBOARD_CONFIG_FILE:-settings.conf}"
+CLIPBOARD_CONFIG_DIR="${CLIPBOARD_CONFIG_DIR:-$HOME/.config/myscripts/clipboard}"
+CLIPBOARD_CONFIG_BACKUP_DIR="${CLIPBOARD_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/clipboard/backups}"
+CLIPBOARD_LOG_DIR="${CLIPBOARD_LOG_DIR:-$HOME/.local/log/clipboard}"
+CLIPBOARD_TEMP_DIR="${CLIPBOARD_TEMP_DIR:-$HOME/.local/tmp/system_scripts/clipboard}"
+CLIPBOARD_CACHE_DIR="${CLIPBOARD_CACHE_DIR:-$HOME/.cache/clipboard}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CLIPBOARD_OUTPUT_COLOR_1="${CLIPBOARD_OUTPUT_COLOR_1:-33}"
+CLIPBOARD_OUTPUT_COLOR_2="${CLIPBOARD_OUTPUT_COLOR_2:-5}"
+CLIPBOARD_OUTPUT_COLOR_GOOD="${CLIPBOARD_OUTPUT_COLOR_GOOD:-2}"
+CLIPBOARD_OUTPUT_COLOR_ERROR="${CLIPBOARD_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CLIPBOARD_NOTIFY_ENABLED="${CLIPBOARD_NOTIFY_ENABLED:-yes}"
+CLIPBOARD_GOOD_NAME="${CLIPBOARD_GOOD_NAME:-Great:}"
+CLIPBOARD_ERROR_NAME="${CLIPBOARD_ERROR_NAME:-Error:}"
+CLIPBOARD_GOOD_MESSAGE="${CLIPBOARD_GOOD_MESSAGE:-No errors reported}"
+CLIPBOARD_ERROR_MESSAGE="${CLIPBOARD_ERROR_MESSAGE:-Errors were reported}"
+CLIPBOARD_NOTIFY_CLIENT_NAME="${CLIPBOARD_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CLIPBOARD_NOTIFY_CLIENT_ICON="${CLIPBOARD_NOTIFY_CLIENT_ICON:-notification-new}"
+CLIPBOARD_NOTIFY_CLIENT_URGENCY="${CLIPBOARD_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CLIPBOARD_HISTORY_FILE="${CLIPBOARD_HISTORY_FILE:-$CLIPBOARD_CONFIG_DIR/history}"
+CLIPBOARD_HISTORY_FILE_CUR="${CLIPBOARD_HISTORY_FILE:-$CLIPBOARD_CONFIG_DIR/history}_CUR"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CLIPBOARD_CONFIG_DIR/$CLIPBOARD_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CLIPBOARD_CONFIG_DIR/$CLIPBOARD_CONFIG_FILE" ] && . "$CLIPBOARD_CONFIG_DIR/$CLIPBOARD_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CLIPBOARD_LOG_DIR" ] || mkdir -p "$CLIPBOARD_LOG_DIR" |& __devnull
+[ -d "$CLIPBOARD_TEMP_DIR" ] || mkdir -p "$CLIPBOARD_TEMP_DIR" |& __devnull
+[ -d "$CLIPBOARD_CACHE_DIR" ] || mkdir -p "$CLIPBOARD_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CLIPBOARD_TEMP_FILE="${CLIPBOARD_TEMP_FILE:-$(mktemp $CLIPBOARD_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CLIPBOARD_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CLIPBOARD_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CLIPBOARD_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CLIPBOARD_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CLIPBOARD_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CLIPBOARD_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="clear show print put"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CLIPBOARD_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CLIPBOARD_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CLIPBOARD_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CLIPBOARD_CWD="$1" && shift 1 || CLIPBOARD_CWD="${CLIPBOARD_CWD:-$PWD}"
+CLIPBOARD_CWD="$(realpath "${CLIPBOARD_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CLIPBOARD_CWD" ] && cd "$CLIPBOARD_CWD"; then
+# if [ "$CLIPBOARD_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CLIPBOARD_CWD"
+# fi
+# else
+# printf_exit "💔 $CLIPBOARD_CWD does not exist 💔"
+# fi
+export CLIPBOARD_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+[ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ] || exit 0
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+if [ -n "$CLIPBOARD_COMMAND" ]; then
+ __clipboard() { printf '%b' "$@" | "$CLIPBOARD_COMMAND"; }
+elif [ "$(uname -s)" = Linux ]; then
+ if __cmd_exists wl-copy && __is_wayland; then
+ __clipboard() { printf '%b' "$@" | wl-copy; }
+ elif __cmd_exists xclip; then
+ __clipboard() { printf '%b' "$@" | xclip -r -selection clipboard; }
+ elif __cmd_exists xsel; then
+ __clipboard() { printf '%b' "$@" | xsel -b; }
+ elif __cmd_exists putclip; then
+ __clipboard() { printf '%b' "$@" | putclip; }
+ fi
+elif [ "$(uname -s)" = Darwin ]; then
+ if __cmd_exists pbcopy; then
+ __clipboard() { printf '%b' "$@" | pbcopy; }
+ fi
+elif [[ "$(uname -s)" = Win* ]]; then
+ if __cmd_exists clip.exe; then
+ __clipboard() { printf '%b' "$@" | clip.exe; }
+ fi
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+clear)
+ shift 1
+ __rm_rf "$CLIPBOARD_HISTORY_FILE" "$CLIPBOARD_HISTORY_FILE_CUR"
+ touch "$CLIPBOARD_HISTORY_FILE" "$CLIPBOARD_HISTORY_FILE_CUR"
+ ;;
+
+show)
+ shift 1
+ crud_file "show"
+ exit $?
+ ;;
+
+print)
+ shift 1
+ crud_file "print"
+ exit $?
+ ;;
+
+put)
+ shift 1
+ [ $# -ne 0 ] || printf_exit "Usage: echo 'text' | clipboard put or clipboard put 'text'"
+ contents="$(<"$@")"
+ if [ -n "$contents" ]; then
+ __clipboard "$contents"
+ crud_file "update"
+ fi
+ ;;
+
+*)
+ if [ -p /dev/stdin ]; then
+ contents="$(/dev/null)"
+VERSION="202208042258-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CLOUDFLARE_REQUIRE_SUDO="${CLOUDFLARE_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CLOUDFLARE_CONFIG_DIR/$CLOUDFLARE_CONFIG_FILE"
+ fi
+ [ -d "$CLOUDFLARE_CONFIG_DIR" ] || mkdir -p "$CLOUDFLARE_CONFIG_DIR"
+ [ -d "$CLOUDFLARE_CONFIG_BACKUP_DIR" ] || mkdir -p "$CLOUDFLARE_CONFIG_BACKUP_DIR"
+ [ -f "$CLOUDFLARE_CONFIG_DIR/$CLOUDFLARE_CONFIG_FILE" ] &&
+ cp -Rf "$CLOUDFLARE_CONFIG_DIR/$CLOUDFLARE_CONFIG_FILE" "$CLOUDFLARE_CONFIG_BACKUP_DIR/$CLOUDFLARE_CONFIG_FILE.$$"
+ cat <"$CLOUDFLARE_CONFIG_DIR/$CLOUDFLARE_CONFIG_FILE"
+# Settings for cloudflare
+CLOUDFLARE_API_KEY="${CLOUDFLARE_API_KEY:-}"
+CLOUDFLARE_TUNNEL_KEY="${CLOUDFLARE_TUNNEL_KEY:-}"
+CLOUDFLARE_HOSTNAME="${CLOUDFLARE_HOSTNAME:-}"
+CLOUDFLARE_DNS_TYPE="${CLOUDFLARE_DNS_TYPE:-A}"
+CLOUDFLARE_PROXY="${CLOUDFLARE_PROXY:-}"
+CLOUDFLARE_ZONE="${CLOUDFLARE_ZONE:-}"
+CLOUDFLARE_IP_ADDR="${CLOUDFLARE_IP_ADDR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CLOUDFLARE_OUTPUT_COLOR_1="${CLOUDFLARE_OUTPUT_COLOR_1:-}"
+CLOUDFLARE_OUTPUT_COLOR_2="${CLOUDFLARE_OUTPUT_COLOR_2:-}"
+CLOUDFLARE_OUTPUT_COLOR_GOOD="${CLOUDFLARE_OUTPUT_COLOR_GOOD:-}"
+CLOUDFLARE_OUTPUT_COLOR_ERROR="${CLOUDFLARE_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CLOUDFLARE_NOTIFY_ENABLED="${CLOUDFLARE_NOTIFY_ENABLED:-}"
+CLOUDFLARE_GOOD_NAME="${CLOUDFLARE_GOOD_NAME:-}"
+CLOUDFLARE_ERROR_NAME="${CLOUDFLARE_ERROR_NAME:-}"
+CLOUDFLARE_GOOD_MESSAGE="${CLOUDFLARE_GOOD_MESSAGE:-}"
+CLOUDFLARE_ERROR_MESSAGE="${CLOUDFLARE_ERROR_MESSAGE:-}"
+CLOUDFLARE_NOTIFY_CLIENT_NAME="${CLOUDFLARE_NOTIFY_CLIENT_NAME:-}"
+CLOUDFLARE_NOTIFY_CLIENT_ICON="${CLOUDFLARE_NOTIFY_CLIENT_ICON:-}"
+CLOUDFLARE_NOTIFY_CLIENT_URGENCY="${CLOUDFLARE_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CLOUDFLARE_CONFIG_DIR/$CLOUDFLARE_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CLOUDFLARE_CONFIG_DIR/$CLOUDFLARE_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() { # --id[zone/record]
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "cloudflare: cloudflare api script - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: cloudflare [options] [ZONE RECORD DNS_TYPE PROXY]"
+ __printf_line "list - List configured records"
+ __printf_line "update hostname - Update an existing record"
+ __printf_line "create hostname - Create a new record"
+ __printf_line "delete hostname - Delete a record"
+ __printf_line "verify [record] - Verify access/record"
+ __printf_line "--api - API Access"
+ __printf_line "--key [key] - Set API key"
+ __printf_line "--ip 1.1.1.1 - Set the ip"
+ __printf_line "--zone mydomain.com - Set the zone"
+ __printf_line "--proxy [true,false] - Set Proxy"
+ __printf_line "--record [CNAME,A,AAAA] - Set the DNS record"
+ __printf_line "--delete-all - Delete all records"
+ __printf_line "--id [zone/record]=id - Manually set the ID"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CLOUDFLARE_REQUIRE_SUDO" = "yes" ] && [ -z "$CLOUDFLARE_REQUIRE_SUDO_RUN" ]; then
+ export CLOUDFLARE_REQUIRE_SUDO="no"
+ export CLOUDFLARE_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CLOUDFLARE_TEMP_FILE" ] && rm -Rf "$CLOUDFLARE_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__rm_rf() { rm -Rf "$@" 2>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_ip4() {
+ curl -q -LSs -4 "https://ifconfig.co" || curl -q -s -4 "https://api.ipify.org" || curl -q -s -4 "https://ipv4.icanhazip.com/" || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_ip6() {
+ curl -q -LSs -6 "https://ifconfig.co" || curl -q -s -6 "https://api.ipify.org" || curl -q -s -6 "https://ipv4.icanhazip.com/" || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__message() {
+ local exitStatus=0
+ if grep 'success' "$CLOUDFLARE_TEMP_FILE" | grep -q 'true'; then
+ printf_green "${1:-Successfully created $CLOUDFLARE_HOSTNAME}"
+ else
+ printf '# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n# %s\n' "$(date)" >>"$CLOUDFLARE_LOG_DIR/errors.log"
+ cat "$CLOUDFLARE_TEMP_FILE" >>"$CLOUDFLARE_LOG_DIR/errors.log"
+ printf '# %s\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n' "End Log" >>"$CLOUDFLARE_LOG_DIR/errors.log"
+ err_mess="$(__devnull2 cat "$CLOUDFLARE_TEMP_FILE" | jq -rc '.errors | .[].message' 2>/dev/null | grep '^')"
+ [ -z "$err_mess" ] && err_mess="Well something went horribly wrong" || err_mess="Error: $err_mess"
+ printf_yellow "${err_mess}"
+ exitStatus=1
+ fi
+ return $exitStatus
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__tunnel() {
+ local host="$(hostname -s)"
+ local key="$CLOUDFLARE_TUNNEL_KEY"
+ local image="cloudflare/cloudflared:latest"
+ local execute="tunnel --no-autoupdate run --token $key"
+ __cmd_exists docker || printf_exit "This requires docker"
+ [ -n "$key" ] || printf_exit "Please set CLOUDFLARE_TUNNEL_KEY variable"
+ docker run -d --name tunnel-$host --hostname $host $image $execute
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_verify() {
+ curl -q -LSs -X GET -H 'X-Auth-Key: '$CLOUDFLARE_API_KEY'' -H 'X-auth-email: '$CLOUDFLARE_EMAIL'' -H "Content-Type: application/json" "$CLOUDFLARE_API_URL/user/tokens/verify" 2>/dev/null | jq -r '.messages | .[] | .message' | grep 'valid and active' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__zone_identifier() {
+ local results=""
+ CLOUDFLARE_ZONE="${1:-$CLOUDFLARE_ZONE}"
+ results="$(curl -q -LSs -X GET -H 'X-Auth-Key: '$CLOUDFLARE_API_KEY'' -H 'X-auth-email: '$CLOUDFLARE_EMAIL'' -H "Content-Type: application/json" "$CLOUDFLARE_API_URL/zones?per_page=1000&name=$CLOUDFLARE_ZONE" 2>/dev/null || echo '')"
+ if [ -z "$results" ] && echo "$results" | jq '.success' 2>/dev/null | grep -q 'false'; then
+ exitCode="1"
+ else
+ echo "$results" | grep -Po '(?<="id":")[^"]*' | head -n1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__record_identifier() {
+ local results="" id=""
+ local CLOUDFLARE_HOSTNAME="${1:-$CLOUDFLARE_HOSTNAME}"
+ results="$(curl -q -LSs -X GET -H 'X-Auth-Key: '$CLOUDFLARE_API_KEY'' -H 'X-auth-email: '$CLOUDFLARE_EMAIL'' -H "Content-Type: application/json" "$CLOUDFLARE_API_URL/zones/$ZONE_ID/dns_records" 2>/dev/null || echo '')"
+ if echo "$results" | jq '.success' 2>/dev/null | grep -q 'false'; then
+ exitCode="1"
+ else
+ RECORD_RESULTS="$results"
+ id="$(echo "$results" | jq -r '.result | .[]' | jq -rc '{name:.name,id:.id,type:.type}' 2>/dev/null | grep '^{"name":"'$CLOUDFLARE_HOSTNAME'' | grep -Ew 'A|AAAA|CNAME' | jq -rc '.id' 2>/dev/null | head -n1 | grep '^')"
+ [ -n "$id" ] && echo "$id" && exitCode=0 || exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api() {
+ local results=""
+ results="$(curl -q -LSs -X GET -H 'X-Auth-Key: '$CLOUDFLARE_API_KEY'' -H 'X-auth-email: '$CLOUDFLARE_EMAIL'' -H "Content-Type: application/json" "$CLOUDFLARE_API_URL/zones/$ZONE_ID/dns_records" 2>/dev/null || echo '')"
+ if echo "$results" | jq '.success' 2>/dev/null | grep -q 'false'; then
+ exitCode=1
+ else
+ echo "$results" | jq '.result|.[]' | jq -rc '[.name,.type,.id]'
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_full() {
+ local results=""
+ results="$(curl -q -LSs -X GET -H 'X-Auth-Key: '$CLOUDFLARE_API_KEY'' -H 'X-auth-email: '$CLOUDFLARE_EMAIL'' -H "Content-Type: application/json" "$CLOUDFLARE_API_URL/zones/$ZONE_ID/dns_records" 2>/dev/null || echo '')"
+ #echo "$results" | jq '.result|.[]'|jq -rc '{name:.name,type:.type,content:.content,proxiable:.proxiable,proxied:.proxied}
+ echo "$results" | jq '.result|.[]'
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__delete_record() {
+ local exitStatus=0 results=""
+ printf_blue "Attempting to delete host"
+ results="$(curl -q -LSs -X DELETE -H 'X-Auth-Key: '$CLOUDFLARE_API_KEY'' -H 'X-auth-email: '$CLOUDFLARE_EMAIL'' -H "Content-Type: application/json" "$CLOUDFLARE_API_URL/zones/$ZONE_ID/dns_records/$RECORD_ID" 2>/dev/null || echo '')"
+ echo "$results" >"$CLOUDFLARE_TEMP_FILE"
+ __message "Successfully deleted $CLOUDFLARE_HOSTNAME" || exitStatus=1
+ return $exitStatus
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__bulk_delete() {
+ local exitStatus=0 results="" name=""
+ printf_cyan "Getting data for $CLOUDFLARE_ZONE"
+ results="$(curl -q -LSs -X GET -H 'X-Auth-Key: '$CLOUDFLARE_API_KEY'' -H 'X-auth-email: '$CLOUDFLARE_EMAIL'' -H "Content-Type: application/json" "$CLOUDFLARE_API_URL/zones/$ZONE_ID/dns_records?per_page=1000" 2>/dev/null | jq '.result| .[]' | jq -rc '{ "name":.name,"id":.id }' | grep "${1:-^}" || echo '')"
+ [ -n "$results" ] || printf_exit 2 0 "There doesn't seem to be any records for zone: $CLOUDFLARE_ZONE"
+ for dns_record in $(echo "$results" | jq -rc '.id'); do
+ name="$(echo "$results" | grep "$dns_record" | jq -rc '.name')"
+ printf_blue "Attempting to delete host: $name"
+ curl -q -LSs -X DELETE -H 'X-Auth-Key: '$CLOUDFLARE_API_KEY'' -H 'X-auth-email: '$CLOUDFLARE_EMAIL'' -H "Content-Type: application/json" "$CLOUDFLARE_API_URL/zones/$ZONE_ID/dns_records/$dns_record" >"$CLOUDFLARE_TEMP_FILE" || exitStatus=$((1 + exitStatus))
+ __message "Successfully deleted id: $dns_record" || exitStatus=1
+ [ -f "$CLOUDFLARE_TEMP_FILE" ] && rm -Rf "$CLOUDFLARE_TEMP_FILE"
+ done
+ return $exitStatus
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_record() {
+ local exitStatus=0
+ CLOUDFLARE_HOSTNAME="${1:-$CLOUDFLARE_HOSTNAME}"
+ CLOUDFLARE_DNS_TYPE="${2:-$CLOUDFLARE_DNS_TYPE}"
+ CLOUDFLARE_PROXY="${3:-$CLOUDFLARE_PROXY}"
+ [ "$CLOUDFLARE_PROXY" = "yes" ] && CLOUDFLARE_PROXY=true
+ [ "$CLOUDFLARE_PROXY" = "no" ] && CLOUDFLARE_PROXY=false
+ printf_blue "Attempting to create a new host"
+ curl -q -LSs -X POST -H 'X-Auth-Key: '$CLOUDFLARE_API_KEY'' -H 'X-auth-email: '$CLOUDFLARE_EMAIL'' -H "Content-Type: application/json" --data "{\"name\":\"${CLOUDFLARE_HOSTNAME}\",\"type\":\"${CLOUDFLARE_DNS_TYPE}\",\"content\":\"${CLOUDFLARE_IP_ADDR}\",\"ttl\":1200,\"priority\":0,\"proxied\":${CLOUDFLARE_PROXY}}" "$CLOUDFLARE_API_URL/zones/$ZONE_ID/dns_records" 2>/dev/null >"$CLOUDFLARE_TEMP_FILE"
+ __message "Successfully created ${CLOUDFLARE_HOSTNAME}" || exitStatus=1
+ return $exitStatus
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__update_record() {
+ local exitStatus=0
+ CLOUDFLARE_HOSTNAME="${1:-$CLOUDFLARE_HOSTNAME}"
+ CLOUDFLARE_PROXY="${2:-$CLOUDFLARE_PROXY}"
+ [ "$CLOUDFLARE_PROXY" = "yes" ] && CLOUDFLARE_PROXY=true
+ [ "$CLOUDFLARE_PROXY" = "no" ] && CLOUDFLARE_PROXY=false
+ [ -n "$RECORD_ID" ] || printf_exit "Failed to get record is for $CLOUDFLARE_HOSTNAME"
+ printf_blue "Attempting to update host"
+ curl -q -LSs -X PATCH -H 'X-Auth-Key: '$CLOUDFLARE_API_KEY'' -H 'X-auth-email: '$CLOUDFLARE_EMAIL'' -H "Content-Type: application/json" --data "{\"name\":\"${CLOUDFLARE_HOSTNAME}\",\"ttl\":1200,\"type\":\"${CLOUDFLARE_DNS_TYPE}\",\"proxied\":${CLOUDFLARE_PROXY},\"content\":\"${CLOUDFLARE_IP_ADDR}\"}" "$CLOUDFLARE_API_URL/zones/$ZONE_ID/dns_records/$RECORD_ID" 2>/dev/null >"$CLOUDFLARE_TEMP_FILE"
+ __message "Successfully Updated ${CLOUDFLARE_HOSTNAME}" || exitStatus=1
+ return $exitStatus
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__cloudflare_zone() {
+ CLOUDFLARE_ZONE="${1:-$CLOUDFLARE_ZONE}"
+ CLOUDFLARE_HOSTNAME="${2:-$CLOUDFLARE_HOSTNAME}"
+ CLOUDFLARE_DNS_TYPE="${3:-$CLOUDFLARE_DNS_TYPE}"
+ CLOUDFLARE_PROXY="${4:-$CLOUDFLARE_PROXY}"
+ CLOUDFLARE_HOSTNAME="${CLOUDFLARE_HOSTNAME:-$CLOUDFLARE_ZONE}"
+ ZONE_ID="${ZONE_ID_KEY:-$(__zone_identifier "$CLOUDFLARE_ZONE")}"
+ RECORD_ID="${RECORD_ID_KEY:-$(__record_identifier "$CLOUDFLARE_HOSTNAME")}"
+ [ "$CLOUDFLARE_PROXY" = "yes" ] && CLOUDFLARE_PROXY=true
+ [ "$CLOUDFLARE_PROXY" = "no" ] && CLOUDFLARE_PROXY=false
+ if [ "$CLOUDFLARE_DNS_TYPE" == "CNAME" ]; then
+ CLOUDFLARE_IP_ADDR="$CLOUDFLARE_ZONE"
+ elif [ "$CLOUDFLARE_DNS_TYPE" == "AAAA" ]; then
+ CLOUDFLARE_IP_ADDR=${CLOUDFLARE_IP_ADDR:-$(__get_ip6)}
+ else
+ CLOUDFLARE_IP_ADDR=${CLOUDFLARE_IP_ADDR:-$(__get_ip4)}
+ fi
+ [ -n "$CLOUDFLARE_IP_ADDR" ] || CLOUDFLARE_IP_ADDR=${IP_ADDR:-$(__get_ip4)}
+ [ -n "$CLOUDFLARE_PROXY" ] || CLOUDFLARE_PROXY="true"
+ [ -n "$CLOUDFLARE_ZONE" ] || __usage $CLOUDFLARE_ZONE || exit 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__usage() {
+ local zone="${1:-$CLOUDFLARE_ZONE}"
+ local record="${2:-$CLOUDFLARE_HOSTNAME}"
+ local type="${3:-$CLOUDFLARE_DNS_TYPE}"
+ local proxy="${4:-$CLOUDFLARE_PROXY}"
+ if [ -z "$zone" ]; then
+ printf_return "Usage: $APPNAME ${zone:-ZONE} RECORD DNS_TYPE PROXY"
+ elif [ -n "$record" ]; then
+ printf_return "Usage: $APPNAME ${zone:-ZONE} ${record:-RECORD} DNS_TYPE PROXY"
+ elif [ -n "$type" ]; then
+ printf_return "Usage: $APPNAME ${zone:-ZONE} ${record:-RECORD} ${type:-DNS_TYPE} PROXY"
+ elif [ -n "$proxy" ]; then
+ printf_return "Usage: $APPNAME ${zone:-ZONE} ${record:-RECORD} ${type:-DNS_TYPE} ${proxy:-PROXY}"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+[ -f "$HOME/.config/secure/cloudflare.txt" ] && . "$HOME/.config/secure/cloudflare.txt"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CLOUDFLARE_CONFIG_FILE="${CLOUDFLARE_CONFIG_FILE:-settings.conf}"
+CLOUDFLARE_CONFIG_DIR="${CLOUDFLARE_CONFIG_DIR:-$HOME/.config/myscripts/cloudflare}"
+CLOUDFLARE_CONFIG_BACKUP_DIR="${CLOUDFLARE_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/cloudflare/backups}"
+CLOUDFLARE_LOG_DIR="${CLOUDFLARE_LOG_DIR:-$HOME/.local/log/cloudflare}"
+CLOUDFLARE_TEMP_DIR="${CLOUDFLARE_TEMP_DIR:-$HOME/.local/tmp/system_scripts/cloudflare}"
+CLOUDFLARE_CACHE_DIR="${CLOUDFLARE_CACHE_DIR:-$HOME/.cache/cloudflare}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CLOUDFLARE_OUTPUT_COLOR_1="${CLOUDFLARE_OUTPUT_COLOR_1:-33}"
+CLOUDFLARE_OUTPUT_COLOR_2="${CLOUDFLARE_OUTPUT_COLOR_2:-5}"
+CLOUDFLARE_OUTPUT_COLOR_GOOD="${CLOUDFLARE_OUTPUT_COLOR_GOOD:-2}"
+CLOUDFLARE_OUTPUT_COLOR_ERROR="${CLOUDFLARE_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CLOUDFLARE_NOTIFY_ENABLED="${CLOUDFLARE_NOTIFY_ENABLED:-yes}"
+CLOUDFLARE_GOOD_NAME="${CLOUDFLARE_GOOD_NAME:-Great:}"
+CLOUDFLARE_ERROR_NAME="${CLOUDFLARE_ERROR_NAME:-Error:}"
+CLOUDFLARE_GOOD_MESSAGE="${CLOUDFLARE_GOOD_MESSAGE:-No errors reported}"
+CLOUDFLARE_ERROR_MESSAGE="${CLOUDFLARE_ERROR_MESSAGE:-Errors were reported}"
+CLOUDFLARE_NOTIFY_CLIENT_NAME="${CLOUDFLARE_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CLOUDFLARE_NOTIFY_CLIENT_ICON="${CLOUDFLARE_NOTIFY_CLIENT_ICON:-notification-new}"
+CLOUDFLARE_NOTIFY_CLIENT_URGENCY="${CLOUDFLARE_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CLOUDFLARE_PROXY="${CLOUDFLARE_PROXY:-}"
+CLOUDFLARE_IP_ADDR="${CLOUDFLARE_IP_ADDR:-}"
+CLOUDFLARE_DNS_TYPE="${CLOUDFLARE_DNS_TYPE:-A}"
+CLOUDFLARE_TUNNEL_KEY="${CLOUDFLARE_TUNNEL_KEY:-}"
+CLOUDFLARE_HOSTNAME="${CLOUDFLARE_HOSTNAME:-$(hostname -s)}"
+CLOUDFLARE_ZONE="${CLOUDFLARE_ZONE:-$CLOUDFLARE_DEFAULT_ZONE}"
+CLOUDFLARE_API_KEY="${CLOUDFLARE_ZONE_KEY:-$CLOUDFLARE_API_KEY}"
+CLOUDFLARE_API_URL="${CLOUDFLARE_API_URL:-https://api.cloudflare.com/client/v4}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CLOUDFLARE_CONFIG_DIR/$CLOUDFLARE_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CLOUDFLARE_CONFIG_DIR/$CLOUDFLARE_CONFIG_FILE" ] && . "$CLOUDFLARE_CONFIG_DIR/$CLOUDFLARE_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CLOUDFLARE_LOG_DIR" ] || mkdir -p "$CLOUDFLARE_LOG_DIR" |& __devnull
+[ -d "$CLOUDFLARE_TEMP_DIR" ] || mkdir -p "$CLOUDFLARE_TEMP_DIR" |& __devnull
+[ -d "$CLOUDFLARE_CACHE_DIR" ] || mkdir -p "$CLOUDFLARE_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CLOUDFLARE_TEMP_FILE="${CLOUDFLARE_TEMP_FILE:-$(mktemp $CLOUDFLARE_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CLOUDFLARE_NOTIFY_ENABLED" = "yes" ] || return
+ (
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CLOUDFLARE_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CLOUDFLARE_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CLOUDFLARE_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CLOUDFLARE_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CLOUDFLARE_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ retval=$?
+ unset NOTIFY_CLIENT_NAME NOTIFY_CLIENT_ICON NOTIFY_GOOD_MESSAGE NOTIFY_ERROR_MESSAGE NOTIFY_CLIENT_URGENCY
+ return $retval
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=",ip:,zone:,proxy:,record:,api,key:,delete-all,id:,bulk"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="create update delete list verify tunnel"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CLOUDFLARE_SILENT="true"
+ ;;
+ --api)
+ shift 1
+ SET_API="full"
+ ;;
+ --delete-all)
+ shift 1
+ CLOUDFLARE_BULK_DELETE="true"
+ ;;
+ --bulk)
+ shift 1
+ CLOUDFLARE_BULK_DELETE="true"
+ ;;
+ --ip)
+ CLOUDFLARE_IP_ADDR="$2"
+ shift 2
+ ;;
+ --zone)
+ CLOUDFLARE_ZONE="$2"
+ shift 2
+ ;;
+ --proxy)
+ CLOUDFLARE_PROXY="$2"
+ shift 2
+ ;;
+ --record)
+ CLOUDFLARE_HOSTNAME="$2"
+ shift 2
+ ;;
+ --key)
+ CLOUDFLARE_API_KEY="$2"
+ CLOUDFLARE_TUNNEL_KEY="$2"
+ shift 2
+ ;;
+ --id)
+ shift 1
+ case "$1" in
+ zone*)
+ ZONE_ID_KEY="${1//*=/}"
+ shift 1
+ ;;
+ record*)
+ RECORD_ID_KEY="${1//*=/}"
+ shift 1
+ ;;
+ *)
+ shift 1
+ ;;
+ esac
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CLOUDFLARE_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CLOUDFLARE_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CLOUDFLARE_CWD="$1" && shift 1 || CLOUDFLARE_CWD="${CLOUDFLARE_CWD:-$PWD}"
+CLOUDFLARE_CWD="$(realpath "${CLOUDFLARE_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CLOUDFLARE_CWD" ] && cd "$CLOUDFLARE_CWD"; then
+# if [ "$CLOUDFLARE_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CLOUDFLARE_CWD"
+# fi
+# else
+# printf_exit "💔 $CLOUDFLARE_CWD does not exist 💔"
+# fi
+export CLOUDFLARE_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -n "$CLOUDFLARE_API_KEY" ] || printf_exit 1 1 "Please set CLOUDFLARE_API_KEY variable"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+tunnel)
+ shift 1
+ if [ -z "$CLOUDFLARE_TUNNEL_KEY" ]; then
+ printf_cyan "Usage: $APPNAME --key 'MyAPIKEY' tunnel or set the"
+ printf_exit "CLOUDFLARE_TUNNEL_KEY variable in the config file"
+ fi
+ __tunnel
+ ;;
+
+create)
+ shift 1
+ __cloudflare_zone "$@"
+ __create_record "$CLOUDFLARE_HOSTNAME" "$CLOUDFLARE_DNS_TYPE" "$CLOUDFLARE_PROXY"
+ exit $?
+ ;;
+
+update)
+ shift 1
+ __cloudflare_zone "$@"
+ __update_record "$CLOUDFLARE_HOSTNAME" "$CLOUDFLARE_PROXY"
+ exit $?
+ ;;
+
+delete)
+ shift 1
+ __cloudflare_zone "$@"
+ if [ "$CLOUDFLARE_BULK_DELETE" = "true" ]; then
+ __bulk_delete "$CLOUDFLARE_HOSTNAME"
+ else
+ __delete_record "$CLOUDFLARE_HOSTNAME"
+ fi
+ exit $?
+ ;;
+
+verify)
+ shift 1
+ printf_cyan "Fetching data from: $CLOUDFLARE_API_URL"
+ if [ "$1" = "id" ]; then
+ shift 1
+ __cloudflare_zone "$1"
+ results="$(__record_identifier "$CLOUDFLARE_HOSTNAME")"
+ [ -n "$results" ] && printf_green "ID for $CLOUDFLARE_HOSTNAME should be: $results" || printf_exit 2 5 "Failed to get ID for $CLOUDFLARE_HOSTNAME"
+ else
+ __cloudflare_zone "$@"
+ results="$(__api_verify)"
+ [ -n "$results" ] && printf_green "$results" || printf_red "Invalid API Key"
+ fi
+ ;;
+
+list)
+ shift 1
+ if [ "$SET_API" = "full" ]; then
+ __cloudflare_zone "$@"
+ __api_full "$CLOUDFLARE_ZONE"
+ else
+ __cloudflare_zone "$@"
+ __api "$CLOUDFLARE_ZONE"
+ fi
+ ;;
+
+*)
+ __cloudflare_zone "$@"
+ if [ "$SET_API" = "full" ]; then
+ __api_full | jq "{ \"zone_name\":.zone_name,\"name\":.name,\"id\":.id,\"zone_id\":.zone_id,\"type\":.type,\"content\":.content,\"proxiable\":.proxiable,\"proxied\":.proxied }"
+ else
+ printf_cyan "Current settings for cloudflare"
+ printf_blue "Email: $CLOUDFLARE_EMAIL"
+ printf_blue "API_Key: $CLOUDFLARE_API_KEY"
+ printf_blue "Default Record: $CLOUDFLARE_HOSTNAME"
+ printf_blue "Default DNS Type $CLOUDFLARE_DNS_TYPE"
+ printf_blue "Default proxy: $CLOUDFLARE_PROXY"
+ printf_blue "Default Zone: ${CLOUDFLARE_ZONE:-$1}"
+ printf_blue "Configured IP Address: $CLOUDFLARE_IP_ADDR"
+ printf_blue "Zone ID: $ZONE_ID"
+ printf_blue "Record ID: $RECORD_ID"
+ fi
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/cmd_exists b/bin/cmd_exists
new file mode 100755
index 000000000..7b64ccd06
--- /dev/null
+++ b/bin/cmd_exists
@@ -0,0 +1,577 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042303-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : cmd_exists --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 23:03 EDT
+# @@File : cmd_exists
+# @@Description : Check to see if command exists
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042303-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CMD_EXISTS_REQUIRE_SUDO="${CMD_EXISTS_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CMD_EXISTS_CONFIG_DIR/$CMD_EXISTS_CONFIG_FILE"
+ fi
+ [ -d "$CMD_EXISTS_CONFIG_DIR" ] || mkdir -p "$CMD_EXISTS_CONFIG_DIR"
+ [ -d "$CMD_EXISTS_CONFIG_BACKUP_DIR" ] || mkdir -p "$CMD_EXISTS_CONFIG_BACKUP_DIR"
+ [ -f "$CMD_EXISTS_CONFIG_DIR/$CMD_EXISTS_CONFIG_FILE" ] &&
+ cp -Rf "$CMD_EXISTS_CONFIG_DIR/$CMD_EXISTS_CONFIG_FILE" "$CMD_EXISTS_CONFIG_BACKUP_DIR/$CMD_EXISTS_CONFIG_FILE.$$"
+ cat <"$CMD_EXISTS_CONFIG_DIR/$CMD_EXISTS_CONFIG_FILE"
+# Settings for cmd_exists
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CMD_EXISTS_OUTPUT_COLOR_1="${CMD_EXISTS_OUTPUT_COLOR_1:-}"
+CMD_EXISTS_OUTPUT_COLOR_2="${CMD_EXISTS_OUTPUT_COLOR_2:-}"
+CMD_EXISTS_OUTPUT_COLOR_GOOD="${CMD_EXISTS_OUTPUT_COLOR_GOOD:-}"
+CMD_EXISTS_OUTPUT_COLOR_ERROR="${CMD_EXISTS_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CMD_EXISTS_NOTIFY_ENABLED="${CMD_EXISTS_NOTIFY_ENABLED:-}"
+CMD_EXISTS_GOOD_NAME="${CMD_EXISTS_GOOD_NAME:-}"
+CMD_EXISTS_ERROR_NAME="${CMD_EXISTS_ERROR_NAME:-}"
+CMD_EXISTS_GOOD_MESSAGE="${CMD_EXISTS_GOOD_MESSAGE:-}"
+CMD_EXISTS_ERROR_MESSAGE="${CMD_EXISTS_ERROR_MESSAGE:-}"
+CMD_EXISTS_NOTIFY_CLIENT_NAME="${CMD_EXISTS_NOTIFY_CLIENT_NAME:-}"
+CMD_EXISTS_NOTIFY_CLIENT_ICON="${CMD_EXISTS_NOTIFY_CLIENT_ICON:-}"
+CMD_EXISTS_NOTIFY_CLIENT_URGENCY="${CMD_EXISTS_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CMD_EXISTS_CONFIG_DIR/$CMD_EXISTS_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CMD_EXISTS_CONFIG_DIR/$CMD_EXISTS_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "cmd_exists: Check to see if command exists - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: cmd_exists [options] [commands]"
+ __printf_line "--ask - Ask to install missing"
+ __printf_line "--show - Show output"
+ __printf_line "--error - Only show if missing"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CMD_EXISTS_REQUIRE_SUDO" = "yes" ] && [ -z "$CMD_EXISTS_REQUIRE_SUDO_RUN" ]; then
+ export CMD_EXISTS_REQUIRE_SUDO="no"
+ export CMD_EXISTS_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CMD_EXISTS_TEMP_FILE" ] && rm -Rf "$CMD_EXISTS_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CMD_EXISTS_CONFIG_FILE="${CMD_EXISTS_CONFIG_FILE:-settings.conf}"
+CMD_EXISTS_CONFIG_DIR="${CMD_EXISTS_CONFIG_DIR:-$HOME/.config/myscripts/cmd_exists}"
+CMD_EXISTS_CONFIG_BACKUP_DIR="${CMD_EXISTS_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/cmd_exists/backups}"
+CMD_EXISTS_LOG_DIR="${CMD_EXISTS_LOG_DIR:-$HOME/.local/log/cmd_exists}"
+CMD_EXISTS_TEMP_DIR="${CMD_EXISTS_TEMP_DIR:-$HOME/.local/tmp/system_scripts/cmd_exists}"
+CMD_EXISTS_CACHE_DIR="${CMD_EXISTS_CACHE_DIR:-$HOME/.cache/cmd_exists}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CMD_EXISTS_OUTPUT_COLOR_1="${CMD_EXISTS_OUTPUT_COLOR_1:-33}"
+CMD_EXISTS_OUTPUT_COLOR_2="${CMD_EXISTS_OUTPUT_COLOR_2:-5}"
+CMD_EXISTS_OUTPUT_COLOR_GOOD="${CMD_EXISTS_OUTPUT_COLOR_GOOD:-2}"
+CMD_EXISTS_OUTPUT_COLOR_ERROR="${CMD_EXISTS_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CMD_EXISTS_NOTIFY_ENABLED="${CMD_EXISTS_NOTIFY_ENABLED:-yes}"
+CMD_EXISTS_GOOD_NAME="${CMD_EXISTS_GOOD_NAME:-:}"
+CMD_EXISTS_ERROR_NAME="${CMD_EXISTS_ERROR_NAME:-Error:}"
+CMD_EXISTS_GOOD_MESSAGE="${CMD_EXISTS_GOOD_MESSAGE:-}"
+CMD_EXISTS_ERROR_MESSAGE="${CMD_EXISTS_ERROR_MESSAGE:-}"
+CMD_EXISTS_NOTIFY_CLIENT_NAME="${CMD_EXISTS_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CMD_EXISTS_NOTIFY_CLIENT_ICON="${CMD_EXISTS_NOTIFY_CLIENT_ICON:-notification-new}"
+CMD_EXISTS_NOTIFY_CLIENT_URGENCY="${CMD_EXISTS_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CMD_EXISTS_CONFIG_DIR/$CMD_EXISTS_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CMD_EXISTS_CONFIG_DIR/$CMD_EXISTS_CONFIG_FILE" ] && . "$CMD_EXISTS_CONFIG_DIR/$CMD_EXISTS_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CMD_EXISTS_LOG_DIR" ] || mkdir -p "$CMD_EXISTS_LOG_DIR" |& __devnull
+[ -d "$CMD_EXISTS_TEMP_DIR" ] || mkdir -p "$CMD_EXISTS_TEMP_DIR" |& __devnull
+[ -d "$CMD_EXISTS_CACHE_DIR" ] || mkdir -p "$CMD_EXISTS_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CMD_EXISTS_TEMP_FILE="${CMD_EXISTS_TEMP_FILE:-$(mktemp $CMD_EXISTS_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CMD_EXISTS_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CMD_EXISTS_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CMD_EXISTS_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CMD_EXISTS_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CMD_EXISTS_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CMD_EXISTS_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=",ask,show,error"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CMD_EXISTS_SILENT="true"
+ ;;
+ --ask)
+ shift 1
+ CMD_EXISTS_NOTIFY_ASK="yes"
+ ;;
+ --show)
+ shift 1
+ CMD_EXISTS_NOTIFY_SHOW="yes"
+ CMD_EXISTS_NOTIFY_SHOW_ERROR="yes"
+ ;;
+ --error)
+ shift 1
+ CMD_EXISTS_NOTIFY_SHOW_ERROR="yes"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CMD_EXISTS_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CMD_EXISTS_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CMD_EXISTS_CWD="$1" && shift 1 || CMD_EXISTS_CWD="${CMD_EXISTS_CWD:-$PWD}"
+CMD_EXISTS_CWD="$(realpath "${CMD_EXISTS_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CMD_EXISTS_CWD" ] && cd "$CMD_EXISTS_CWD"; then
+# if [ "$CMD_EXISTS_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CMD_EXISTS_CWD"
+# fi
+# else
+# printf_exit "💔 $CMD_EXISTS_CWD does not exist 💔"
+# fi
+export CMD_EXISTS_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+##cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+COMMANDS=("$@")
+cmdMissing=()
+cmdExists=()
+cmdExitCode=0
+cmdExitTmp=0
+cmdChoice=
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ "$(uname -s)" = Darwin ] && exit 0
+[ -n "${COMMANDS[*]}" ] || exit 0
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+for cmdExists in "${COMMANDS[@]}"; do
+ if builtin type -P "$cmdExists" &>/dev/null || builtin type -p "$cmdExists" &>/dev/null; then
+ cmdExitTmp+=$(($cmdExitTmp + 0))
+ else
+ cmdExitTmp+=$(($cmdExitTmp + 1))
+ cmdMissing+=("$cmdExists")
+ fi
+ cmdExitCode=$cmdExitTmp
+done
+
+if [ "$CMD_EXISTS_NOTIFY_SHOW" = "yes" ]; then
+ if [ $cmdExitCode -eq 0 ] && [ "$CMD_EXISTS_NOTIFY_ENABLED" = "yes" ]; then
+ __notifications "$APPNAME" "$CMD_EXISTS_GOOD_MESSAGE"
+ fi
+ for cmdExists in "${COMMANDS[@]}"; do
+ fullpath="$(type -P $cmdExists)"
+ printf_cyan "Full path to $cmdExists: ${fullpath:-N/A}"
+ done
+fi
+
+if [ "$CMD_EXISTS_NOTIFY_SHOW_ERROR" = "yes" ]; then
+ [ $cmdExitCode -ne 0 ] && __notifications "$APPNAME" "${cmdMissing[*]}"
+fi
+
+[ $cmdExitCode -eq 0 ] && cmdExitCode=0 || cmdExitCode=1
+
+if [ "$CMD_EXISTS_NOTIFY_ASK" = "yes" ]; then
+ MISSING=("${cmdMissing[@]}")
+ if [ -n "${MISSING[*]}" ]; then
+ __notifications "${CMD_EXISTS_NOTIFY_CLIENT_NAME:-$APPNAME}" "Missing ${MISSING[*]}"
+ if __cmd_exists ask_yes_no_question; then
+ ask_yes_no_question "Would you like install ${MISSING[*]}" "pkmgr silent install ${MISSING[*]}" && cmdExitCode=0 || cmdExitCode=1
+ else
+ printf_red "The following apps are missing: ${MISSING[*]}"
+ printf_read_question "2" "Would you like install the missing packages? [y/N]" "1" "cmdChoice"
+ if printf_answer_yes "$cmdChoice"; then
+ for miss in "${MISSING[@]}"; do
+ __execute "pkmgr silent install $miss" "Installing $miss" && cmdExitCode+=$(($cmdExitCode + 0)) || cmdExitCode+=$(($cmdExitCode + 1))
+ done
+ else
+ cmdExitCode=1
+ fi
+ fi
+ fi
+fi
+[ $cmdExitCode = 0 ] && exitCode=0 || exitCode=$cmdExitCode
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/cmdfu b/bin/cmdfu
new file mode 100755
index 000000000..f42edbd3d
--- /dev/null
+++ b/bin/cmdfu
@@ -0,0 +1,615 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042305-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : cmdfu --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 23:05 EDT
+# @@File : cmdfu
+# @@Description : search command usage examples on commandlinefu.com
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042305-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CMDFU_REQUIRE_SUDO="${CMDFU_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CMDFU_CONFIG_DIR/$CMDFU_CONFIG_FILE"
+ fi
+ [ -d "$CMDFU_CONFIG_DIR" ] || mkdir -p "$CMDFU_CONFIG_DIR"
+ [ -d "$CMDFU_CONFIG_BACKUP_DIR" ] || mkdir -p "$CMDFU_CONFIG_BACKUP_DIR"
+ [ -f "$CMDFU_CONFIG_DIR/$CMDFU_CONFIG_FILE" ] &&
+ cp -Rf "$CMDFU_CONFIG_DIR/$CMDFU_CONFIG_FILE" "$CMDFU_CONFIG_BACKUP_DIR/$CMDFU_CONFIG_FILE.$$"
+ cat <"$CMDFU_CONFIG_DIR/$CMDFU_CONFIG_FILE"
+# Settings for cmdfu
+CMDFU_YAD_WIDTH="${CMDFU_YAD_WIDTH:-}"
+CMDFU_YAD_HEIGHT="${CMDFU_YAD_HEIGHT:-}"
+CMDFU_API_URL="${CMDFU_API_URL:-}"
+CMDFU_API_LATEST="${CMDFU_API_LATEST:-}"
+CMDFU_API_LATEST_COUNT="${CMDFU_API_LATEST_COUNT:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CMDFU_OUTPUT_COLOR_1="${CMDFU_OUTPUT_COLOR_1:-}"
+CMDFU_OUTPUT_COLOR_2="${CMDFU_OUTPUT_COLOR_2:-}"
+CMDFU_OUTPUT_COLOR_GOOD="${CMDFU_OUTPUT_COLOR_GOOD:-}"
+CMDFU_OUTPUT_COLOR_ERROR="${CMDFU_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CMDFU_NOTIFY_ENABLED="${CMDFU_NOTIFY_ENABLED:-}"
+CMDFU_GOOD_NAME="${CMDFU_GOOD_NAME:-}"
+CMDFU_ERROR_NAME="${CMDFU_ERROR_NAME:-}"
+CMDFU_GOOD_MESSAGE="${CMDFU_GOOD_MESSAGE:-}"
+CMDFU_ERROR_MESSAGE="${CMDFU_ERROR_MESSAGE:-}"
+CMDFU_NOTIFY_CLIENT_NAME="${CMDFU_NOTIFY_CLIENT_NAME:-}"
+CMDFU_NOTIFY_CLIENT_ICON="${CMDFU_NOTIFY_CLIENT_ICON:-}"
+CMDFU_NOTIFY_CLIENT_URGENCY="${CMDFU_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CMDFU_CONFIG_DIR/$CMDFU_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CMDFU_CONFIG_DIR/$CMDFU_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "cmdfu: search command usage examples on commandlinefu.com - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: cmdfu [options] [commands] [query]"
+ __printf_line "search [query] - Search for command"
+ __printf_line "browse [query] - browse topics"
+ __printf_line "latest [query] - Get the latest posts"
+ __printf_line "user [query] - Get all from user"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CMDFU_REQUIRE_SUDO" = "yes" ] && [ -z "$CMDFU_REQUIRE_SUDO_RUN" ]; then
+ export CMDFU_REQUIRE_SUDO="no"
+ export CMDFU_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CMDFU_TEMP_FILE" ] && rm -Rf "$CMDFU_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__strip_html() {
+ sed -r 's/.*href="([^"]+).*/\1/g' |
+ sed 's|^$||g' |
+ sed 's|\\/|/|g' |
+ sed 's|//|//|g;s|/|/|g' |
+ sed 's|<.*||g' |
+ sed 's|>.*||g' |
+ sed 's|\t||g' |
+ sed "s|'||g" |
+ grep -v '^$'
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__yad__text() {
+ set -o pipefail
+ local title="$1"
+ local color="${2:-$CMDFU_OUTPUT_COLOR_1}"
+ local CMDFU_YAD_WIDTH="${CMDFU_YAD_WIDTH:-900}"
+ local CMDFU_YAD_HEIGHT="${CMDFU_YAD_HEIGHT:-600}"
+ if __cmd_exists yad && [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ]; then
+ cat - | yad --text-info --wrap --center --title="$title" --width=${CMDFU_YAD_WIDTH:-500} --height=${CMDFU_YAD_HEIGHT:-400} 2>/dev/null &
+ return $?
+ elif __cmd_exists yad && [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ]; then
+ cat - | zenity --text-info --title="$title" --width=${CMDFU_YAD_WIDTH:-500} --height=${CMDFU_YAD_HEIGHT:-400} 2>/dev/null &
+ return $?
+ else
+ cat - | printf_readline "$color"
+ return $?
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__curl() {
+ curl -q -LSsf "$1" 2>/dev/null
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_results() {
+ if [ -n "$REL_URL" ]; then
+ URL="$REL_URL"
+ else
+ local search="${*:-}"
+ URL="commands/matching/${search// /-}/$(echo -n "$search" | base64)/sort-by-votes/plaintext"
+ fi
+ printf_blue "Getting results from: $CMDFU_API_URL/$URL"
+ if __urlcheck "$CMDFU_API_URL/$URL"; then
+ formatted="$(__curl "$CMDFU_API_URL/$URL")"
+ if echo "$formatted" | grep -v "# commandlinefu" | grep -q '^$'; then
+ [ -n "$DISPLAY" ] && echo "$formatted" | __yad__text "$search" "$CMDFU_OUTPUT_COLOR_1" ||
+ echo "$formatted" | printf_readline "6"
+ else
+ printf_return "1" "1" "$CMDFU_ERROR_MESSAGE $search"
+ __notifications "$CMDFU_ERROR_MESSAGE $search"
+ fi
+ else
+ printf_return "1" "1" "$CMDFU_ERROR_MESSAGE $search"
+ __notifications "$CMDFU_ERROR_MESSAGE $search"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CMDFU_CONFIG_FILE="${CMDFU_CONFIG_FILE:-settings.conf}"
+CMDFU_CONFIG_DIR="${CMDFU_CONFIG_DIR:-$HOME/.config/myscripts/cmdfu}"
+CMDFU_CONFIG_BACKUP_DIR="${CMDFU_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/cmdfu/backups}"
+CMDFU_LOG_DIR="${CMDFU_LOG_DIR:-$HOME/.local/log/cmdfu}"
+CMDFU_TEMP_DIR="${CMDFU_TEMP_DIR:-$HOME/.local/tmp/system_scripts/cmdfu}"
+CMDFU_CACHE_DIR="${CMDFU_CACHE_DIR:-$HOME/.cache/cmdfu}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CMDFU_OUTPUT_COLOR_1="${CMDFU_OUTPUT_COLOR_1:-33}"
+CMDFU_OUTPUT_COLOR_2="${CMDFU_OUTPUT_COLOR_2:-5}"
+CMDFU_OUTPUT_COLOR_GOOD="${CMDFU_OUTPUT_COLOR_GOOD:-2}"
+CMDFU_OUTPUT_COLOR_ERROR="${CMDFU_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CMDFU_NOTIFY_ENABLED="${CMDFU_NOTIFY_ENABLED:-yes}"
+CMDFU_GOOD_NAME="${CMDFU_GOOD_NAME:-Great:}"
+CMDFU_ERROR_NAME="${CMDFU_ERROR_NAME:-Error:}"
+CMDFU_GOOD_MESSAGE="${CMDFU_GOOD_MESSAGE:-No errors reported}"
+CMDFU_ERROR_MESSAGE="${CMDFU_ERROR_MESSAGE:-Errors were reported}"
+CMDFU_NOTIFY_CLIENT_NAME="${CMDFU_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CMDFU_NOTIFY_CLIENT_ICON="${CMDFU_NOTIFY_CLIENT_ICON:-notification-new}"
+CMDFU_NOTIFY_CLIENT_URGENCY="${CMDFU_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CMDFU_YAD_WIDTH="${CMDFU_YAD_WIDTH:-900}"
+CMDFU_YAD_HEIGHT="${CMDFU_YAD_HEIGHT:-600}"
+CMDFU_API_URL="${CMDFU_API_URL:-https://www.commandlinefu.com}"
+CMDFU_API_LATEST="${CMDFU_API_LATEST:-commands/browse/plaintext}"
+CMDFU_API_LATEST_COUNT="${CMDFU_API_LATEST_COUNT:-25}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CMDFU_CONFIG_DIR/$CMDFU_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CMDFU_CONFIG_DIR/$CMDFU_CONFIG_FILE" ] && . "$CMDFU_CONFIG_DIR/$CMDFU_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CMDFU_LOG_DIR" ] || mkdir -p "$CMDFU_LOG_DIR" |& __devnull
+[ -d "$CMDFU_TEMP_DIR" ] || mkdir -p "$CMDFU_TEMP_DIR" |& __devnull
+[ -d "$CMDFU_CACHE_DIR" ] || mkdir -p "$CMDFU_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CMDFU_TEMP_FILE="${CMDFU_TEMP_FILE:-$(mktemp $CMDFU_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CMDFU_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CMDFU_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CMDFU_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CMDFU_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CMDFU_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CMDFU_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="search browse latest"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CMDFU_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ CMDFU_CWD="$2"
+ [ -d "$CMDFU_CWD" ] || mkdir -p "$CMDFU_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CMDFU_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CMDFU_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CMDFU_CWD="$1" && shift 1 || CMDFU_CWD="${CMDFU_CWD:-$PWD}"
+CMDFU_CWD="$(realpath "${CMDFU_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CMDFU_CWD" ] && cd "$CMDFU_CWD"; then
+# if [ "$CMDFU_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CMDFU_CWD"
+# fi
+# else
+# printf_exit "💔 $CMDFU_CWD does not exist 💔"
+# fi
+export CMDFU_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+latest)
+ shift 1
+ CMDFU_API_LATEST_COUNT="${1:-$CMDFU_API_LATEST_COUNT}"
+ REL_URL="$CMDFU_API_LATEST/[0-$CMDFU_API_LATEST_COUNT]:1"
+ [ -n "$REL_URL" ] && __get_results "$REL_URL" || printf_exit "No results found"
+ ;;
+
+browse)
+ shift 1
+ REL_URL="/commands/browse/plaintext"
+ [ -n "$REL_URL" ] && __get_results "$REL_URL" || printf_exit "No results found"
+ ;;
+
+search)
+ shift 1
+ REL_URL=(commands/matching/"$@"/$(echo -n "$@" | openssl base64)/plaintext)
+ [ -n "${REL_URL[*]}" ] && __get_results "$REL_URL" || printf_exit "No results found"
+ ;;
+
+user)
+ shift 1
+ REL_URL=(commands/by/"$1"/plaintext)
+ [ -n "${REL_URL[*]}" ] && __get_results "$REL_URL" || printf_exit "No results found"
+ ;;
+
+*)
+ REL_URL=(commands/matching/"${@:-commandlinefu}"/$(echo -n "${@:-commandlinefu}" | openssl base64)/plaintext)
+ [ -n "${REL_URL[*]}" ] && __get_results "$REL_URL" || printf_exit "No results found"
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/command b/bin/command
new file mode 100755
index 000000000..119610614
--- /dev/null
+++ b/bin/command
@@ -0,0 +1,526 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042309-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : command --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 23:09 EDT
+# @@File : command
+# @@Description : bash builtin command check
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042309-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+COMMAND_REQUIRE_SUDO="${COMMAND_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$COMMAND_CONFIG_DIR/$COMMAND_CONFIG_FILE"
+ fi
+ [ -d "$COMMAND_CONFIG_DIR" ] || mkdir -p "$COMMAND_CONFIG_DIR"
+ [ -d "$COMMAND_CONFIG_BACKUP_DIR" ] || mkdir -p "$COMMAND_CONFIG_BACKUP_DIR"
+ [ -f "$COMMAND_CONFIG_DIR/$COMMAND_CONFIG_FILE" ] &&
+ cp -Rf "$COMMAND_CONFIG_DIR/$COMMAND_CONFIG_FILE" "$COMMAND_CONFIG_BACKUP_DIR/$COMMAND_CONFIG_FILE.$$"
+ cat <"$COMMAND_CONFIG_DIR/$COMMAND_CONFIG_FILE"
+# Settings for command
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+COMMAND_OUTPUT_COLOR_1="${COMMAND_OUTPUT_COLOR_1:-}"
+COMMAND_OUTPUT_COLOR_2="${COMMAND_OUTPUT_COLOR_2:-}"
+COMMAND_OUTPUT_COLOR_GOOD="${COMMAND_OUTPUT_COLOR_GOOD:-}"
+COMMAND_OUTPUT_COLOR_ERROR="${COMMAND_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+COMMAND_NOTIFY_ENABLED="${COMMAND_NOTIFY_ENABLED:-}"
+COMMAND_GOOD_NAME="${COMMAND_GOOD_NAME:-}"
+COMMAND_ERROR_NAME="${COMMAND_ERROR_NAME:-}"
+COMMAND_GOOD_MESSAGE="${COMMAND_GOOD_MESSAGE:-}"
+COMMAND_ERROR_MESSAGE="${COMMAND_ERROR_MESSAGE:-}"
+COMMAND_NOTIFY_CLIENT_NAME="${COMMAND_NOTIFY_CLIENT_NAME:-}"
+COMMAND_NOTIFY_CLIENT_ICON="${COMMAND_NOTIFY_CLIENT_ICON:-}"
+COMMAND_NOTIFY_CLIENT_URGENCY="${COMMAND_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$COMMAND_CONFIG_DIR/$COMMAND_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$COMMAND_CONFIG_DIR/$COMMAND_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "command: bash builtin command check - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: command [options] [commands]"
+ __printf_line "-p - Execute command"
+ __printf_line "-v - Print full path"
+ __printf_line "-V - Extra logging"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$COMMAND_REQUIRE_SUDO" = "yes" ] && [ -z "$COMMAND_REQUIRE_SUDO_RUN" ]; then
+ export COMMAND_REQUIRE_SUDO="no"
+ export COMMAND_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$COMMAND_TEMP_FILE" ] && rm -Rf "$COMMAND_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__command() {
+ local exit=0
+ local retval=0
+ for cmd in "$@"; do
+ builtin command ${OPT:--v} "$cmd" 2>/dev/null && retval=0 || retval=1
+ exit=$(($exit + $retval))
+ done
+ exitCode=$exit
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+COMMAND_CONFIG_FILE="${COMMAND_CONFIG_FILE:-settings.conf}"
+COMMAND_CONFIG_DIR="${COMMAND_CONFIG_DIR:-$HOME/.config/myscripts/command}"
+COMMAND_CONFIG_BACKUP_DIR="${COMMAND_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/command/backups}"
+COMMAND_LOG_DIR="${COMMAND_LOG_DIR:-$HOME/.local/log/command}"
+COMMAND_TEMP_DIR="${COMMAND_TEMP_DIR:-$HOME/.local/tmp/system_scripts/command}"
+COMMAND_CACHE_DIR="${COMMAND_CACHE_DIR:-$HOME/.cache/command}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+COMMAND_OUTPUT_COLOR_1="${COMMAND_OUTPUT_COLOR_1:-33}"
+COMMAND_OUTPUT_COLOR_2="${COMMAND_OUTPUT_COLOR_2:-5}"
+COMMAND_OUTPUT_COLOR_GOOD="${COMMAND_OUTPUT_COLOR_GOOD:-2}"
+COMMAND_OUTPUT_COLOR_ERROR="${COMMAND_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+COMMAND_NOTIFY_ENABLED="${COMMAND_NOTIFY_ENABLED:-yes}"
+COMMAND_GOOD_NAME="${COMMAND_GOOD_NAME:-Great:}"
+COMMAND_ERROR_NAME="${COMMAND_ERROR_NAME:-Error:}"
+COMMAND_GOOD_MESSAGE="${COMMAND_GOOD_MESSAGE:-No errors reported}"
+COMMAND_ERROR_MESSAGE="${COMMAND_ERROR_MESSAGE:-Errors were reported}"
+COMMAND_NOTIFY_CLIENT_NAME="${COMMAND_NOTIFY_CLIENT_NAME:-$APPNAME}"
+COMMAND_NOTIFY_CLIENT_ICON="${COMMAND_NOTIFY_CLIENT_ICON:-notification-new}"
+COMMAND_NOTIFY_CLIENT_URGENCY="${COMMAND_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$COMMAND_CONFIG_DIR/$COMMAND_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$COMMAND_CONFIG_DIR/$COMMAND_CONFIG_FILE" ] && . "$COMMAND_CONFIG_DIR/$COMMAND_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$COMMAND_LOG_DIR" ] || mkdir -p "$COMMAND_LOG_DIR" |& __devnull
+[ -d "$COMMAND_TEMP_DIR" ] || mkdir -p "$COMMAND_TEMP_DIR" |& __devnull
+[ -d "$COMMAND_CACHE_DIR" ] || mkdir -p "$COMMAND_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+COMMAND_TEMP_FILE="${COMMAND_TEMP_FILE:-$(mktemp $COMMAND_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$COMMAND_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$COMMAND_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$COMMAND_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$COMMAND_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$COMMAND_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$COMMAND_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS="p,v,V"
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ COMMAND_SILENT="true"
+ ;;
+ -p | -v | -V)
+ OPT="$1"
+ shift 1
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# COMMAND_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# COMMAND_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && COMMAND_CWD="$1" && shift 1 || COMMAND_CWD="${COMMAND_CWD:-$PWD}"
+COMMAND_CWD="$(realpath "${COMMAND_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$COMMAND_CWD" ] && cd "$COMMAND_CWD"; then
+# if [ "$COMMAND_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $COMMAND_CWD"
+# fi
+# else
+# printf_exit "💔 $COMMAND_CWD does not exist 💔"
+# fi
+export COMMAND_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__command "${@:-$APPNAME}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/composemgr b/bin/composemgr
new file mode 100755
index 000000000..2c8637fec
--- /dev/null
+++ b/bin/composemgr
@@ -0,0 +1,1002 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202411011656-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : composemgr --help
+# @@Copyright : Copyright: (c) 2024 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Nov 01, 2024 16:56 EDT
+# @@File : composemgr
+# @@Description :
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202411011656-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+COMPOSEMGR_REQUIRE_SUDO="${COMPOSEMGR_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && COMPOSEMGR_EXIT_STATUS=0 || COMPOSEMGR_EXIT_STATUS=1
+ return ${COMPOSEMGR_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && COMPOSEMGR_EXIT_STATUS=0 || COMPOSEMGR_EXIT_STATUS=1
+ return ${COMPOSEMGR_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ COMPOSEMGR_EXIT_STATUS=0
+ [ -n "$1" ] && local COMPOSEMGR_EXIT_STATUS="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && COMPOSEMGR_EXIT_STATUS+=$(($COMPOSEMGR_EXIT_STATUS + 0)) || COMPOSEMGR_EXIT_STATUS+=$(($COMPOSEMGR_EXIT_STATUS + 1))
+ done
+ [ $COMPOSEMGR_EXIT_STATUS -eq 0 ] || COMPOSEMGR_EXIT_STATUS=3
+ return ${COMPOSEMGR_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local COMPOSEMGR_EXIT_STATUS=0
+ curl -q -LSsfI --max-time 1 --retry 0 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || COMPOSEMGR_EXIT_STATUS=4
+ return ${COMPOSEMGR_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$COMPOSEMGR_CONFIG_DIR/$COMPOSEMGR_CONFIG_FILE"
+ fi
+ [ -d "$COMPOSEMGR_CONFIG_DIR" ] || mkdir -p "$COMPOSEMGR_CONFIG_DIR"
+ [ -d "$COMPOSEMGR_CONFIG_BACKUP_DIR" ] || mkdir -p "$COMPOSEMGR_CONFIG_BACKUP_DIR"
+ [ -f "$COMPOSEMGR_CONFIG_DIR/$COMPOSEMGR_CONFIG_FILE" ] &&
+ cp -Rf "$COMPOSEMGR_CONFIG_DIR/$COMPOSEMGR_CONFIG_FILE" "$COMPOSEMGR_CONFIG_BACKUP_DIR/$COMPOSEMGR_CONFIG_FILE.$$"
+ cat <"$COMPOSEMGR_CONFIG_DIR/$COMPOSEMGR_CONFIG_FILE"
+# Settings for composemgr
+COMPOSE_ENV_FILES="${COMPOSE_ENV_FILES:-}"
+COMPOSEMGR_BASE_DIR="${COMPOSEMGR_BASE_DIR:-}"
+COMPOSEMGR_GIT_ORG_URL="${COMPOSEMGR_GIT_ORG_URL:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+COMPOSEMGR_OUTPUT_COLOR_1="${COMPOSEMGR_OUTPUT_COLOR_1:-}"
+COMPOSEMGR_OUTPUT_COLOR_2="${COMPOSEMGR_OUTPUT_COLOR_2:-}"
+COMPOSEMGR_OUTPUT_COLOR_GOOD="${COMPOSEMGR_OUTPUT_COLOR_GOOD:-}"
+COMPOSEMGR_OUTPUT_COLOR_ERROR="${COMPOSEMGR_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+COMPOSEMGR_SYSTEM_NOTIFY_ENABLED="${COMPOSEMGR_SYSTEM_NOTIFY_ENABLED:-}"
+COMPOSEMGR_GOOD_NAME="${COMPOSEMGR_GOOD_NAME:-}"
+COMPOSEMGR_ERROR_NAME="${COMPOSEMGR_ERROR_NAME:-}"
+COMPOSEMGR_GOOD_MESSAGE="${COMPOSEMGR_GOOD_MESSAGE:-}"
+COMPOSEMGR_ERROR_MESSAGE="${COMPOSEMGR_ERROR_MESSAGE:-}"
+COMPOSEMGR_NOTIFY_CLIENT_NAME="${COMPOSEMGR_NOTIFY_CLIENT_NAME:-}"
+COMPOSEMGR_NOTIFY_CLIENT_ICON="${COMPOSEMGR_NOTIFY_CLIENT_ICON:-}"
+COMPOSEMGR_NOTIFY_CLIENT_URGENCY="${COMPOSEMGR_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$COMPOSEMGR_CONFIG_DIR/$COMPOSEMGR_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$COMPOSEMGR_CONFIG_DIR/$COMPOSEMGR_CONFIG_FILE"
+ COMPOSEMGR_EXIT_STATUS=0
+ else
+ printf_red "Failed to create the config file"
+ COMPOSEMGR_EXIT_STATUS=1
+ fi
+ __update_env_file &>/dev/null
+ return ${COMPOSEMGR_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "composemgr: - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: composemgr [options] [commands]"
+ __printf_line "install - "
+ __printf_line "remove - "
+ __printf_line "restart - "
+ __printf_line "up - "
+ __printf_line "down - "
+ __printf_line "ps - "
+ __printf_line "logs - "
+ __printf_line ""
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_line "--no - No options"
+ __printf_line "--yes - Yes options"
+ __printf_line ""
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__grep() { grep "$@" 2>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$COMPOSEMGR_REQUIRE_SUDO" = "yes" ] && [ -z "$COMPOSEMGR_REQUIRE_SUDO_RUN" ]; then
+ export COMPOSEMGR_REQUIRE_SUDO="no"
+ export COMPOSEMGR_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ COMPOSEMGR_EXIT_STATUS=$?
+ else
+ printf '%s\n' "This requires root to run"
+ COMPOSEMGR_EXIT_STATUS=1
+ fi
+ return ${COMPOSEMGR_EXIT_STATUS:-0}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__how_long_did_it_take() {
+ local retprev=$?
+ local retval=${1:-$retprev}
+ __cmd_exists bc || return $retval
+ [ -n "$COMPOSEMGR_START_TIMER" ] || return 0
+ local stop_time="$(date +%s.%N)"
+ local dt=$(echo "$stop_time - $COMPOSEMGR_START_TIMER" | bc)
+ local dd=$(echo "$dt/86400" | bc)
+ local dt2=$(echo "$dt-86400*$dd" | bc)
+ local dh=$(echo "$dt2/3600" | bc)
+ local dt3=$(echo "$dt2-3600*$dh" | bc)
+ local dm=$(echo "$dt3/60" | bc)
+ local ds=$(echo "$dt3-60*$dm" | bc)
+ printf_purple "$(LC_NUMERIC=C printf "Total runtime: %d Days, %02d Hours, %02d Minutes, %02.4f Seconds\n" $dd $dh $dm $ds)"
+ return $retval
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ COMPOSEMGR_EXIT_STATUS=${COMPOSEMGR_EXIT_STATUS:-0}
+ [ -f "$COMPOSEMGR_TEMP_FILE" ] && rm -Rf "$COMPOSEMGR_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $COMPOSEMGR_EXIT_STATUS
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a --no-* options function
+__options_function_no() {
+ local options="${1//=*/}"
+ local argument="${1//*=/}"
+ case "$options" in
+ *) echo "${argument:-No argument provided}" && shift ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a --yes-* options function
+__options_function_yes() {
+ local options="${1//=*/}"
+ local argument="${1//*=/}"
+ case "$options" in
+ *) echo "${argument:-No argument provided}" && shift ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$COMPOSEMGR_SYSTEM_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$COMPOSEMGR_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$COMPOSEMGR_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$COMPOSEMGR_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$COMPOSEMGR_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$COMPOSEMGR_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__notify_remote() {
+ local cmd="$(echo "$COMPOSEMGR_REMOTE_NOTIFY_COMMAND" | awk -F ' ' '{print $1}')"
+ if [ "$COMPOSEMGR_REMOTE_NOTIFY_ENABLED" = "yes" ]; then
+ if [ -n "$(command -v "$cmd")" ]; then
+ eval $COMPOSEMGR_REMOTE_NOTIFY_COMMAND "$@"
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__curl() { \curl "$@" 2>/dev/null || return 1; }
+__retrieve_compose() { __curl -q -LSsf "$1" -o 'compose.yml' 2>/dev/null || return 1; }
+__get_image_name() { grep -sR 'image: ' "$COMPOSEMGR_CWD" | sed "s|.*image: ||g;s|\"||g;s|'||g;s|:.*||g"; }
+__project_name() { grep -svE '^$|#' "$COMPOSEMGR_CWD"/*compose.yml | head -n1 | grep 'name:' | sed 's|name: ||g' || __basename "${1:-$COMPOSEMGR_CWD}"; }
+__get_project_dir() { grep -R -- '-.*/' *.yml | sed "s|.*- ||g;s|'||g;s|\"||g;s|:.*||g" | grep -v '=' | grep '^/var/lib/srv' | grep -v '^$' | tr '\n' ','; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__cd() {
+ local dir="$(__basename "$1")"
+ [ -d "$COMPOSEMGR_BASE_DIR/$dir" ] || mkdir -p "$COMPOSEMGR_BASE_DIR/$dir"
+ \cd "$COMPOSEMGR_BASE_DIR/$dir" && pushd "$PWD" >/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__update_env_file() {
+ local file="${1:-$COMPOSEMGR_CONFIG_DIR/compose.env}"
+ local directory="$(dirname "$file")"
+ if [ -d "$directory/.git" ]; then
+ grep -qs '.env$' "$directory/.gitignore" || printf '%s\n%s\n' '# ignore dotenv files' '.env' >>"$directory/.gitignore"
+ fi
+ if [ -f "$file" ]; then
+ . "$file"
+ \rm -Rf "$file"
+ fi
+
+ cat <"$file"
+# Create a random secret
+# openssl rand -hex 32
+
+# create a random password
+# head -n50 '/dev/random' | tr -dc 'a-zA-Z0-9[!@]' | tr -d '[:space:]\042\047\134' | fold -w 32 | head -n 1
+
+# create a hashed password
+# head -n128 /dev/urandom|tr -dc 'A-Za-z0-9' | head -c 32|openssl passwd -1 -salt $(openssl rand -base64 6) --stdin
+
+# Docker Compose Global env
+export TZ="${TZ:-}"
+export BASE_DOMAIN_NAME="${BASE_DOMAIN_NAME:-}"
+export BASE_HOST_NAME="${BASE_HOST_NAME:-}"
+#
+export REDIS_URL="${REDIS_URL:-}"
+export VALKEY_URL="${VALKEY_URL:-}"
+export COUCHDB_URL="${COUCHDB_URL:-}"
+export MARIADB_URL="${MARIADB_URL:-}"
+export MONGODB_URL="${MONGODB_URL:-}"
+export MSSQLDB_URL="${MSSQLDB_URL:-}"
+export SUPABASE_URL="${SUPABASE_URL:-}"
+export COUCHBASE_URL="${COUCHBASE_URL:-}"
+export POSTGRESQL_URL="${POSTGRESQL_URL:-}"
+export POCKETBASE_URL="${POCKETBASE_URL:-}"
+#
+export DB_CREATE_DATABASE_NAME="${DB_CREATE_DATABASE_NAME:-}"
+#
+export DB_ADMIN_NAME="${DB_ADMIN_NAME:-}"
+export DB_ADMIN_PASS="${DB_ADMIN_PASS:-}"
+#
+export DB_USER_NAME="${DB_USER_NAME:-}"
+export DB_USER_PASS="${DB_USER_PASS:-}"
+#
+export APP_ORG_NAME="${APP_ORG_NAME:-}"
+#
+export APP_RUN_AS="${APP_RUN_AS:-}"
+#
+export APP_ADMIN_USER="${APP_ADMIN_USER:-}"
+export APP_ADMIN_PASS="${APP_ADMIN_PASS:-}"
+#
+export APP_USER_NAME="${APP_USER_NAME:-}"
+export APP_USER_PASS="${APP_USER_PASS:-}"
+#
+export APP_JWT_TOKEN="${APP_JWT_TOKEN:-}"
+#
+export APP_TEMP_PASS="${APP_TEMP_PASS:-}"
+#
+export APP_API_TOKEN="${APP_API_TOKEN:-}"
+#
+export APP_SECRET_KEY="${APP_SECRET_KEY:-}"
+export APP_SECRET_TOKEN_16="${APP_SECRET_TOKEN_16:-}"
+export APP_SECRET_TOKEN_32="${APP_SECRET_TOKEN_32:-}"
+export APP_SECRET_TOKEN_64="${APP_SECRET_TOKEN_64:-}"
+#
+export BACKUPS_PW=${BACKUPS_PW:-}
+#
+export RPC_SECRET="${RPC_SECRET:-}"
+export ENCRYPTION_KEY="${ENCRYPTION_KEY:-}"
+#
+export SECURE_SECRET="${SECURE_SECRET:-}"
+export K256_PRIVATE_KEY="${K256_PRIVATE_KEY:-}"
+#
+export EMAIL_SERVER_PORT="${EMAIL_SERVER_PORT:-}"
+export EMAIL_SERVER_TIMEOUT="${EMAIL_SERVER_TIMEOUT:-}"
+export EMAIL_SERVER_HOST="${EMAIL_SERVER_HOST:-}"
+export EMAIL_SERVER_FROM_ORG="${EMAIL_SERVER_FROM_ORG:-$APP_ORG_NAME}"
+export EMAIL_SERVER_MAIL_FROM="${EMAIL_SERVER_MAIL_FROM:-}"
+export EMAIL_SERVER_LOGIN_NAME="${EMAIL_SERVER_LOGIN_NAME:-}"
+export EMAIL_SERVER_LOGIN_PASS="${EMAIL_SERVER_LOGIN_PASS:-}"
+#
+export RFC2136_NAMESERVER="${RFC2136_NAMESERVER:-}"
+export RFC2136_TSIG_ALGORITHM="${RFC2136_TSIG_ALGORITHM:-}"
+export RFC2136_TSIG_KEY="${RFC2136_TSIG_KEY:-certbot.}"
+export RFC2136_PROPAGATION_TIMEOUT="${RFC2136_PROPAGATION_TIMEOUT:-90}"
+export RFC2136_TSIG_SECRET="${RFC2136_TSIG_SECRET:-}"
+
+EOF
+ if [ -f "$file" ]; then
+ printf_green "$file has been updated/created"
+ if [ -f ".env" ]; then . ".env"; fi
+ else
+ printf_yellow "Failed to create $file"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_data_dir() {
+ images=$(__get_image_name)
+ for image in $images; do
+ repo="$(echo "$image" | awk -F'/' '{print $NF}')"
+ org="$(echo "$image" | awk -F'/' '{print $(NF-1)}')"
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__is_docker_compose() {
+ if [ -f "docker-compose.yml" ] || [ -f "docker-compose.yaml" ] || [ -f "compose.yml" ] || [ -f "compose.yaml" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_docker_compose() {
+ local dir="$1"
+ [ -n "$dir" ] && __cd "$dir" || printf_exit "Please provide a project name"
+ if [ -f "docker-compose.yml" ]; then
+ COMPOSEMGR_FILE="docker-compose.yml"
+ elif [ -f "docker-compose.yaml" ]; then
+ COMPOSEMGR_FILE="docker-compose.yaml"
+ elif [ -f "compose.yml" ]; then
+ COMPOSEMGR_FILE="compose.yml"
+ elif [ -f "compose.yaml" ]; then
+ COMPOSEMGR_FILE="compose.yaml"
+ fi
+ [ -n "$COMPOSEMGR_FILE" ] || return 3
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__init_dir() {
+ local exitCode=0
+ local repo_name="$1"
+ local workDir="$COMPOSEMGR_BASE_DIR/$repo_name"
+ printf_green "Testing repo: $COMPOSEMGR_GIT_ORG_URL/$repo_name"
+ __curl -q -LSsfI "$COMPOSEMGR_GIT_ORG_RAW/$repo_name/refs/heads/main/docker-compose.yml" -o /dev/null >/dev/null 2>&1 || exitCode=1
+ if [ $exitCode -eq 0 ]; then
+ [ -d "$workDir" ] || mkdir -p "$workDir"
+ if \cd "$workDir"; then
+ return 0
+ else
+ return 1
+ fi
+ else
+ printf_red "Testing of the repo has failed: Make sure it exists and is public"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__install_files() {
+ local exitCode=0
+ local repo_name="$1"
+ __is_docker_compose || edit_compose_file="yes"
+ if __init_dir "$repo_name"; then
+ __cd "$repo_name" && __curl -q -LSsf "$COMPOSEMGR_GIT_ORG_RAW/$repo_name/refs/heads/main/docker-compose.yml" -o "compose.yml" && __compose_up "$1"
+ exitCode=$?
+ fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__remove_files() {
+ local exitCode=0
+ pname="$(__project_name "$1")"
+ directories="$(eval echo $(__get_project_dir))"
+ files="$(ls -A "$COMPOSEMGR_CWD" | grep -v 'compose.yml')"
+ printf_cyan "Running docker compose down for $pname"
+ if __compose_down; then
+ docker image prune -f >/dev/null 2>&1
+ if [ -n "$files" ]; then for file in $files; do [ -e "$file" ] && \rm -Rf "$file"; done; fi
+ if [ -n "$directories" ]; then for dir in ${directories//,/ }; do [ -e "$dir" ] && \rm -Rf "${dir:?}"/*; done; fi
+ fi
+ exitCode=$?
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__compose_up() {
+ local exitCode=0
+ pname="$(__project_name "$1")"
+ [ -f "$PWD/.env" ] || dotenvFile="no"
+ if __is_docker_compose; then
+ printf_cyan "Running docker compose up for $pname"
+ [ -f ".env" ] && . ".env" && . ".env"
+ __update_env_file "$PWD/.env" >/dev/null
+ if [ "$dotenvFile" = "no" ]; then
+ printf_read_question "2" "Would you like to customize the .env file? [y/N]" "1" "choice" "-s"
+ if printf_answer_yes "$choice"; then
+ "$EDITOR" "$PWD/.env"
+ wait $!
+ fi
+ fi
+ if [ "$edit_compose_file" = "yes" ]; then
+ printf_read_question "2" "Would you like to edit the the compose.yml file? [y/N]" "1" "compose" "-s"
+ if printf_answer_yes "$compose"; then
+ "$EDITOR" "$PWD/compose.yml"
+ wait $!
+ fi
+ fi
+ docker compose up -d --remove-orphans --force-recreate
+ exitCode=$?
+ else
+ printf_red "Can not file a valid compose file in $COMPOSEMGR_CWD" >&2
+ exitCode=1
+ fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__compose_down() {
+ local exitCode=0
+ if __is_docker_compose; then
+ docker compose down --remove-orphans
+ exitCode=$?
+ else
+ printf_red "Can not file a valid compose file in $COMPOSEMGR_CWD" >&2
+ exitCode=1
+ fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__compose_logs() {
+ local exitCode=0
+ if __is_docker_compose; then
+ docker compose logs -f
+ exitCode=$?
+ fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__compose_edit() {
+ if __get_docker_compose "$1"; then
+ eval $EDITOR "$COMPOSEMGR_FILE"
+ else
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+COMPOSEMGR_START_TIMER="${COMPOSEMGR_START_TIMER:-$(date +%s.%N)}"
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Default exit code
+COMPOSEMGR_EXIT_STATUS=0
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+COMPOSEMGR_CONFIG_DIR="${COMPOSEMGR_CONFIG_DIR:-$HOME/.config/myscripts/composemgr}"
+COMPOSEMGR_CONFIG_BACKUP_DIR="${COMPOSEMGR_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/composemgr/backups}"
+COMPOSEMGR_LOG_DIR="${COMPOSEMGR_LOG_DIR:-$HOME/.local/log/composemgr}"
+COMPOSEMGR_RUN_DIR="${COMPOSEMGR_RUN_DIR:-$HOME/.local/run/system_scripts/$COMPOSEMGR_SCRIPTS_PREFIX}"
+COMPOSEMGR_TEMP_DIR="${COMPOSEMGR_TEMP_DIR:-$HOME/.local/tmp/system_scripts/composemgr}"
+COMPOSEMGR_CACHE_DIR="${COMPOSEMGR_CACHE_DIR:-$HOME/.cache/composemgr}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# File settings
+COMPOSEMGR_CONFIG_FILE="${COMPOSEMGR_CONFIG_FILE:-settings.conf}"
+COMPOSEMGR_LOG_ERROR_FILE="${COMPOSEMGR_LOG_ERROR_FILE:-$COMPOSEMGR_LOG_DIR/error.log}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+COMPOSEMGR_OUTPUT_COLOR_1="${COMPOSEMGR_OUTPUT_COLOR_1:-33}"
+COMPOSEMGR_OUTPUT_COLOR_2="${COMPOSEMGR_OUTPUT_COLOR_2:-5}"
+COMPOSEMGR_OUTPUT_COLOR_GOOD="${COMPOSEMGR_OUTPUT_COLOR_GOOD:-2}"
+COMPOSEMGR_OUTPUT_COLOR_ERROR="${COMPOSEMGR_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+COMPOSEMGR_REMOTE_NOTIFY_ENABLED="${COMPOSEMGR_REMOTE_NOTIFY_ENABLED:-yes}"
+COMPOSEMGR_REMOTE_NOTIFY_COMMAND="${COMPOSEMGR_REMOTE_NOTIFY_COMMAND:-web-notify telegram}"
+# System
+COMPOSEMGR_SYSTEM_NOTIFY_ENABLED="${COMPOSEMGR_SYSTEM_NOTIFY_ENABLED:-yes}"
+COMPOSEMGR_GOOD_NAME="${COMPOSEMGR_GOOD_NAME:-Great:}"
+COMPOSEMGR_ERROR_NAME="${COMPOSEMGR_ERROR_NAME:-Error:}"
+COMPOSEMGR_GOOD_MESSAGE="${COMPOSEMGR_GOOD_MESSAGE:-No errors reported}"
+COMPOSEMGR_ERROR_MESSAGE="${COMPOSEMGR_ERROR_MESSAGE:-Errors were reported}"
+COMPOSEMGR_NOTIFY_CLIENT_NAME="${COMPOSEMGR_NOTIFY_CLIENT_NAME:-$APPNAME}"
+COMPOSEMGR_NOTIFY_CLIENT_ICON="${COMPOSEMGR_NOTIFY_CLIENT_ICON:-notification-new}"
+COMPOSEMGR_NOTIFY_CLIENT_URGENCY="${COMPOSEMGR_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+COMPOSEMGR_BASE_DIR="${COMPOSEMGR_BASE_DIR:-$COMPOSEMGR_CONFIG_DIR/docker}"
+COMPOSEMGR_GIT_ORG_URL="${COMPOSEMGR_GIT_ORG_URL:-https://github.com/composemgr}"
+COMPOSEMGR_GIT_ORG_RAW="${COMPOSEMGR_GIT_ORG_RAW:-https://raw.githubusercontent.com/composemgr}"
+COMPOSE_ENV_FILES="${COMPOSE_ENV_FILES:-$COMPOSEMGR_CONFIG_DIR/compose.env}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+TZ="${TZ:-America/New_York}"
+BASE_DOMAIN_NAME="${BASE_DOMAIN_NAME:-$(hostname -d 2>/dev/null | grep '^' || echo "$BASE_HOST_NAME")}"
+BASE_HOST_NAME="${BASE_HOST_NAME:-$HOSTNAME}"
+REDIS_URL="${REDIS_URL:-redis}"
+VALKEY_URL="${VALKEY_URL:-valkey}"
+COUCHDB_URL="${COUCHDB_URL:-couchdb}"
+MARIADB_URL="${MARIADB_URL:-mariadb}"
+MONGODB_URL="${MONGODB_URL:-mongodb}"
+MSSQLDB_URL="${MSSQLDB_URL:-mssqldb}"
+SUPABASE_URL="${SUPABASE_URL:-supabasedb}"
+COUCHBASE_URL="${COUCHBASE_URL:-couchbasedb}"
+POSTGRESQL_URL="${POSTGRESQL_URL:-postgresqldb}"
+POCKETBASE_URL="${POCKETBASE_URL:-pocketbasedb}"
+DB_ADMIN_NAME="${DB_ADMIN_NAME:-db_admin}"
+DB_ADMIN_PASS="${DB_ADMIN_PASS:-$(head -n128 '/dev/urandom' | tr -dc 'a-zA-Z0-9' | tr -d '[:space:]\042\047\134' | fold -w "32" | head -n 1)}"
+DB_USER_NAME="${DB_USER_NAME:-$USER}"
+DB_USER_PASS="${DB_USER_PASS:-$(head -n128 '/dev/urandom' | tr -dc 'a-zA-Z0-9' | tr -d '[:space:]\042\047\134' | fold -w "24" | head -n 1)}"
+APP_ORG_NAME="${APP_ORG_NAME:-CasjaysDev}"
+APP_USER_NAME="${APP_USER_NAME:-$USER}"
+APP_USER_PASS="${APP_USER_PASS:-$(head -n128 '/dev/urandom' | tr -dc 'a-zA-Z0-9' | tr -d '[:space:]\042\047\134' | fold -w "16" | head -n 1)}"
+APP_ADMIN_USER="${APP_ADMIN_USER:-admin_${USER}}"
+APP_ADMIN_PASS="${APP_ADMIN_PASS:-$(head -n128 '/dev/urandom' | tr -dc 'a-zA-Z0-9' | tr -d '[:space:]\042\047\134' | fold -w "24" | head -n 1)}"
+APP_JWT_TOKEN="${APP_JWT_TOKEN:-$(openssl rand -base64 32)}"
+APP_TEMP_PASS="${APP_TEMP_PASS:-$(head -n128 '/dev/urandom' | tr -dc 'a-zA-Z0-9' | tr -d '[:space:]\042\047\134' | fold -w "32" | head -n 1)}"
+APP_API_TOKEN="${APP_API_TOKEN:-$(head -n128 '/dev/urandom' | tr -dc 'a-zA-Z0-9' | tr -d '[:space:]\042\047\134' | fold -w "64" | head -n 1)}"
+APP_SECRET_KEY="${APP_SECRET_KEY:-$(head -n128 '/dev/urandom' | tr -dc 'a-zA-Z0-9' | tr -d '[:space:]\042\047\134' | fold -w "16" | head -n 1)}"
+APP_SECRET_TOKEN_16="${APP_SECRET_TOKEN_16:-$(openssl rand -hex 16)}"
+APP_SECRET_TOKEN_32="${APP_SECRET_TOKEN_32:-$(openssl rand -hex 32)}"
+APP_SECRET_TOKEN_64="${APP_SECRET_TOKEN_64:-$(openssl rand -hex 64)}"
+RPC_SECRET="${RPC_SECRET:-$(openssl rand -hex 32)}"
+BACKUPS_PW="${BACKUPS_PW:-$(openssl rand -hex 32)}"
+ENCRYPTION_KEY="${ENCRYPTION_KEY:-$(openssl rand -hex 32)}"
+SECURE_SECRET="${SECURE_SECRET:-$(openssl rand --hex 16)}"
+K256_PRIVATE_KEY="${K256_PRIVATE_KEY:-$(openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32)}"
+EMAIL_SERVER_PORT="${EMAIL_SERVER_PORT:-25}"
+EMAIL_SERVER_TIMEOUT="${EMAIL_SERVER_TIMEOUT:-10}"
+EMAIL_SERVER_HOST="${EMAIL_SERVER_HOST:-172.17.0.1}"
+EMAIL_SERVER_FROM_ORG="${EMAIL_SERVER_FROM_ORG:-}"
+EMAIL_SERVER_MAIL_FROM="${EMAIL_SERVER_MAIL_FROM:-no-reply@\$BASE_HOST_NAME}"
+EMAIL_SERVER_LOGIN_NAME="${EMAIL_SERVER_LOGIN_NAME:-}"
+EMAIL_SERVER_LOGIN_PASS="${EMAIL_SERVER_LOGIN_PASS:-}"
+RFC2136_NAMESERVER="${RFC2136_NAMESERVER:-}"
+RFC2136_TSIG_ALGORITHM="${RFC2136_TSIG_ALGORITHM:-}"
+RFC2136_TSIG_KEY="${RFC2136_TSIG_KEY:-certbot.}"
+RFC2136_PROPAGATION_TIMEOUT="${RFC2136_PROPAGATION_TIMEOUT:-90}"
+RFC2136_TSIG_SECRET="${RFC2136_TSIG_SECRET:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$COMPOSEMGR_CONFIG_DIR/$COMPOSEMGR_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$COMPOSEMGR_CONFIG_DIR/$COMPOSEMGR_CONFIG_FILE" ] && . "$COMPOSEMGR_CONFIG_DIR/$COMPOSEMGR_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$COMPOSEMGR_RUN_DIR" ] || mkdir -p "$COMPOSEMGR_RUN_DIR" |& __devnull
+[ -d "$COMPOSEMGR_LOG_DIR" ] || mkdir -p "$COMPOSEMGR_LOG_DIR" |& __devnull
+[ -d "$COMPOSEMGR_TEMP_DIR" ] || mkdir -p "$COMPOSEMGR_TEMP_DIR" |& __devnull
+[ -d "$COMPOSEMGR_CACHE_DIR" ] || mkdir -p "$COMPOSEMGR_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+COMPOSEMGR_TEMP_FILE="${COMPOSEMGR_TEMP_FILE:-$(mktemp $COMPOSEMGR_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+GET_OPTIONS_NO="no-*"
+GET_OPTIONS_YES="yes-*"
+LONGOPTS="completions:,config,reset-config,debug,dir:,help,options,raw,version,silent,force"
+LONGOPTS+=",project:,env"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="install,remove,up,down,restart,ps,logs,network,cat,init,new,edit,show,get,env"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST="acme,affine,aria2,authentik,blinko,bluesky,borg,budibase,bytestash,caprover,clipcascade,code-server,coder,couchbase,couchdb,"
+LIST+="dockge,freeipa,garage,gitlab,guacamole,i2p,irc,it-tools,jenkins,jitsi,kestra,keycloak,kooboo,lenpaste,linkwarden,mariadb,mastadon,"
+LIST+="matrix,mattermost,memcached,meshcentral,microbin,minio,mongodb,mqtt,mssql,nextcloud,nexterm,nginx,nginx-proxy-manager,ntfy,ollama,"
+LIST+="onedev,openfire,passed,pihole,pingvin,pocketbase,portainer,postgres,postiz,rabbitmq,redis,registry,rocketchat,rustdesk,searxng,stikked,"
+LIST+="supabase,technitium,,tor,traefix,trilium,tududi,umbrel,uptimekuma,valkey,vaultwarden,wireguard,yacht,zammad,zitadel"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS,$GET_OPTIONS_YES,$GET_OPTIONS_NO" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --reset-config)
+ shift 1
+ [ -f "$COMPOSEMGR_CONFIG_DIR/$COMPOSEMGR_CONFIG_FILE" ] && rm -Rf "${COMPOSEMGR_CONFIG_DIR:?}/$COMPOSEMGR_CONFIG_FILE"
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ COMPOSEMGR_SILENT="true"
+ ;;
+ --force)
+ shift 1
+ export FORCE_INSTALL="true"
+ COMPOSEMGR_FORCE_INSTALL="true"
+ ;;
+ --dir)
+ CWD_IS_SET="true"
+ COMPOSEMGR_CWD="$2"
+ [ -d "$COMPOSEMGR_CWD" ] || mkdir -p "$COMPOSEMGR_CWD" |& __devnull
+ shift 2
+ ;;
+ --no-*)
+ __options_function_no "$@"
+ shift 1
+ ;;
+ --yes-*)
+ __options_function_yes "$@"
+ shift 1
+ ;;
+ --project)
+ CWD_IS_SET="true"
+ COMPOSEMGR_CWD="$COMPOSEMGR_BASE_DIR/$2"
+ [ -d "$COMPOSEMGR_CWD" ] || mkdir -p "$COMPOSEMGR_CWD" |& __devnull
+ shift 2
+ ;;
+ --env)
+ shift 1
+ __update_env_file
+ exit $?
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# COMPOSEMGR_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# COMPOSEMGR_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+[ -d "$1" ] && __is_an_option "$1" && COMPOSEMGR_CWD="$1" && shift 1 || COMPOSEMGR_CWD="${COMPOSEMGR_CWD:-$PWD}"
+COMPOSEMGR_CWD="$(realpath "${COMPOSEMGR_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$COMPOSEMGR_CWD" ] && cd "$COMPOSEMGR_CWD"; then
+# if [ "$COMPOSEMGR_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $COMPOSEMGR_CWD"
+# fi
+# else
+# printf_exit "💔 $COMPOSEMGR_CWD does not exist 💔"
+# fi
+export COMPOSEMGR_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Export variables
+export COMPOSE_ENV_FILES="${COMPOSE_ENV_FILES:-$COMPOSEMGR_CONFIG_DIR/compose.env}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+[ "$CWD_IS_SET" = "true" ] && __cd "$COMPOSEMGR_CWD"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+__update_env_file >/dev/null
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+init)
+ shift 1
+ __gen_config
+ __update_env_file
+ exit
+ ;;
+env)
+ shift 1
+ [ -f "$COMPOSEMGR_CWD/.env" ] && . "$COMPOSEMGR_CWD/.env" 2>/dev/null
+ __update_env_file "$COMPOSEMGR_CWD/.env"
+ exit $?
+ ;;
+get)
+ shift 1
+ __retrieve_compose "$1"
+ exit $?
+ ;;
+install)
+ shift 1
+ for install in "$@"; do
+ __install_files "$install"
+ COMPOSEMGR_EXIT_STATUS=$?
+ done
+ exit $COMPOSEMGR_EXIT_STATUS
+ ;;
+remove)
+ shift 1
+ __remove_files
+ COMPOSEMGR_EXIT_STATUS=$?
+ ;;
+up)
+ shift 1
+ __compose_up
+ COMPOSEMGR_EXIT_STATUS=$?
+ ;;
+down)
+ shift 1
+ __compose_down
+ COMPOSEMGR_EXIT_STATUS=$?
+ ;;
+logs)
+ shift 1
+ __compose_logs "$1"
+ ;;
+ps)
+ shift 1
+ docker compose ps -a
+ ;;
+network)
+ shift 1
+ docker network "${@:-ls}"
+ ;;
+cat)
+ shift 1
+ for yml in "$COMPOSEMGR_CWD"/*.yml; do
+ cat "$yml"
+ done
+ ;;
+new)
+ shift 1
+ __cd "$1" && touch 'compose.yml' && __compose_edit "$1"
+ exit $?
+ ;;
+
+edit)
+ shift 1
+ __compose_edit "$1"
+ exit $?
+ ;;
+show)
+ shift 1
+ if __get_docker_compose "$1"; then
+ cat "$COMPOSEMGR_FILE"
+ exit $?
+ else
+ exit 1
+ fi
+ ;;
+*)
+ docker compose "${@:-ps}"
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+COMPOSEMGR_EXIT_STATUS="${COMPOSEMGR_EXIT_STATUS:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${COMPOSEMGR_EXIT_STATUS:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/config b/bin/config
new file mode 100755
index 000000000..ef136ddf2
--- /dev/null
+++ b/bin/config
@@ -0,0 +1,1052 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208042312-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : config --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 04, 2022 23:12 EDT
+# @@File : config
+# @@Description : Add dotfiles/config files to a git repo
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource : https://www.atlassian.com/git/tutorials/dotfiles
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208042312-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CONFIG_REQUIRE_SUDO="${CONFIG_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CONFIG_CONFIG_DIR/$CONFIG_CONFIG_FILE"
+ fi
+ [ -d "$CONFIG_CONFIG_DIR" ] || mkdir -p "$CONFIG_CONFIG_DIR"
+ [ -d "$CONFIG_CONFIG_BACKUP_DIR" ] || mkdir -p "$CONFIG_CONFIG_BACKUP_DIR"
+ [ -f "$CONFIG_CONFIG_DIR/$CONFIG_CONFIG_FILE" ] &&
+ cp -Rf "$CONFIG_CONFIG_DIR/$CONFIG_CONFIG_FILE" "$CONFIG_CONFIG_BACKUP_DIR/$CONFIG_CONFIG_FILE.$$"
+ cat <"$CONFIG_CONFIG_DIR/$CONFIG_CONFIG_FILE"
+# Settings for config
+CONFIG_SYSTEM_HOME="${CONFIG_SYSTEM_HOME:-}"
+CONFIG_GIT_BARE_DIR="${CONFIG_GIT_BARE_DIR:-}"
+CONFIG_SYSTEM_BACKUP_DIR="${CONFIG_SYSTEM_BACKUP_DIR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CONFIG_OUTPUT_COLOR_1="${CONFIG_OUTPUT_COLOR_1:-}"
+CONFIG_OUTPUT_COLOR_2="${CONFIG_OUTPUT_COLOR_2:-}"
+CONFIG_OUTPUT_COLOR_GOOD="${CONFIG_OUTPUT_COLOR_GOOD:-}"
+CONFIG_OUTPUT_COLOR_ERROR="${CONFIG_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CONFIG_NOTIFY_ENABLED="${CONFIG_NOTIFY_ENABLED:-}"
+CONFIG_GOOD_NAME="${CONFIG_GOOD_NAME:-}"
+CONFIG_ERROR_NAME="${CONFIG_ERROR_NAME:-}"
+CONFIG_GOOD_MESSAGE="${CONFIG_GOOD_MESSAGE:-}"
+CONFIG_ERROR_MESSAGE="${CONFIG_ERROR_MESSAGE:-}"
+CONFIG_NOTIFY_CLIENT_NAME="${CONFIG_NOTIFY_CLIENT_NAME:-}"
+CONFIG_NOTIFY_CLIENT_ICON="${CONFIG_NOTIFY_CLIENT_ICON:-}"
+CONFIG_NOTIFY_CLIENT_URGENCY="${CONFIG_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CONFIG_CONFIG_DIR/$CONFIG_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CONFIG_CONFIG_DIR/$CONFIG_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "config: Add dotfiles/config files to a git repo - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: config [options] [commands]"
+ __printf_line "init - Initialize a config repo"
+ __printf_line "info - Show current config info"
+ __printf_line "local - Change the local git config file"
+ __printf_line "log - Show the git log"
+ __printf_line "status - Show git status"
+ __printf_line "ignore - Update the gitignore file"
+ __printf_line "delete - Delete the config repo"
+ __printf_line "reset - Resets the git repo"
+ __printf_line "rm - Remove a file from the repo"
+ __printf_line "add - Adds files to repo"
+ __printf_line "commit - Commits the changes"
+ __printf_line "checkout - Checkout files from the repo"
+ __printf_line "remote - Add a remote repo"
+ __printf_line "pull - Update the repo from remote"
+ __printf_line "push - Push changes to remote repo"
+ __printf_line "set - Set config options"
+ __printf_line "rename - Rename a branch"
+ __printf_line "clone - Clone a config repo"
+ __printf_line "bare - Checkout bare repo"
+ __printf_line "backup - Backup the files in your repo"
+ __printf_line "system - Add system files to a repo (root) "
+ __printf_line "name - This allows the use of a custom git dir"
+ __printf_line "custom - This allows the use of a custom git dir and home dir"
+ __printf_line "root - Sets HOME to /"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CONFIG_REQUIRE_SUDO" = "yes" ] && [ -z "$CONFIG_REQUIRE_SUDO_RUN" ]; then
+ export CONFIG_REQUIRE_SUDO="no"
+ export CONFIG_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CONFIG_TEMP_FILE" ] && rm -Rf "$CONFIG_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__symlink() { ls -l "$1" | awk '{print $NF}' | grep '^'; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__online_check() { am_i_online --error && return 0 || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__cp() {
+ realpath="$(realpath "$1")"
+ from="${realpath//$HOME\//}"
+ todir="${2//$HOME\//}"
+ { [[ "$todir" =~ /.git ]] || [[ "$todir" =~ /node_modules ]] || [[ "$from" =~ "$CONFIG_CWD_HOME_DIR"/** ]]; } && return 0
+ [ -d "${todir}" ] || mkdir -p "${todir}"
+ cp -Rdfva --parents --preserve=mode,ownership,timestamps "${from}" "${todir}" &>/dev/null
+ rm -Rf "$todir/.git" "$todir/node_modules" &>/dev/null
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__gitcmd() {
+ local cmd="$*"
+ git --git-dir="$CONFIG_CWD_BARE_DIR" --work-tree="$CONFIG_CWD_HOME_DIR" ${cmd:-} $GIT_OPTS 2>&1
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__stow() {
+ local cmd="$*"
+ git --git-dir="$CONFIG_CWD_BARE_DIR" --work-tree="$CONFIG_CWD_HOME_DIR" ${cmd:-} $GIT_OPTS 2>&1 | printf_readline "$CONFIG_OUTPUT_COLOR"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__stow__add() {
+ [ -n "$1" ] && FILES="$1" || FILES="."
+ git --git-dir="$CONFIG_CWD_BARE_DIR" --work-tree="$CONFIG_CWD_HOME_DIR" add "$FILES" $GIT_OPTS 2>&1
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__stow_commit() {
+ [ -n "$1" ] && MESSAGE="$1" || MESSAGE='🏠🐜❗ Added files 🏠🐜❗'
+ git --git-dir="$CONFIG_CWD_BARE_DIR" --work-tree="$CONFIG_CWD_HOME_DIR" commit $GIT_OPTS -q -m "$MESSAGE" 2>&1
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__show_info() {
+ printf_blue "Git bare dir is $CONFIG_CWD_BARE_DIR"
+ printf_blue "Git Working dir is $CONFIG_CWD_HOME_DIR"
+ printf_blue "Git backup dir is $CONFIG_CWD_BACKUP_DIR"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__copy() {
+ [ $# -ne 0 ] || return
+ local -a args=("$@")
+ local exitCode=0
+ local gitDir="$CONFIG_CWD_BARE_DIR"
+ local workingTree="$CONFIG_CWD_HOME_DIR"
+ local backupDir="$CONFIG_CWD_BACKUP_DIR"
+ local file=""
+ local symlink=""
+ for f in "${args[@]}"; do
+ file="${f//$HOME\//}"
+ symlink="$(__symlink "${f//$HOME\//}")"
+ if [ "$file" = "$symlink" ]; then
+ __cp "$symlink" "$workingTree" &>/dev/null
+ __cp "$file" "$workingTree" &>/dev/null
+ else
+ __cp "$file" "$workingTree" &>/dev/null
+ fi
+ done
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__add() {
+ cd "$HOME" || return 1
+ [ $# -ne 0 ] || return
+ local -a args=("$@")
+ local gitDir="$CONFIG_CWD_BARE_DIR"
+ local workingTree="$CONFIG_CWD_HOME_DIR"
+ local backupDir="$CONFIG_CWD_BACKUP_DIR"
+ mkdir -p "$workingTree"
+ for f in "${args[@]}"; do
+ file="${f//$HOME\//}"
+ todir="$file"
+ stow_file="${todir//$workingTree\//}"
+ if [ "$file" = "$workingTree/$todir" ]; then
+ __stow add -f "$stow_file"
+ else
+ __copy "$file" && __stow add -f "$stow_file"
+ fi
+ done
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__restore() {
+ [ $# -ne 0 ] || return
+ local backupName
+ local -a args=("$@")
+ local gitDir="$CONFIG_CWD_BARE_DIR"
+ local workingTree="$CONFIG_CWD_HOME_DIR"
+ backupName="$CONFIG_BACKUP_DIR/$(date +'%Y%m%d_%H%M').tar.gz"
+ mkdir -p "$CONFIG_BACKUP_DIR"
+ for f in "${args[@]}"; do
+ file="${f//workingTree\//}"
+ if [ -f "$file" ] && [ "$f" = "$file" ]; then
+ tar cfvzu "$backupDir" "$backupName" --exclude="*/.git" --exclude="*/node_modules"
+ __cp "$f" "$file" && true || false
+ exitCode=$(($? + exitCode))
+ fi
+ done
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__checkout() {
+ local gitDir="$CONFIG_CWD_BARE_DIR"
+ local workingTree="$CONFIG_CWD_HOME_DIR"
+ local backupDir="$CONFIG_CWD_BACKUP_DIR"
+ eval __gitcmd checkout --force | printf_readline 4
+ __restore "$workingTree"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__bare() {
+ [ $# -ne 0 ] || return
+ local gitDir="$CONFIG_CWD_BARE_DIR"
+ local workingTree="$CONFIG_CWD_HOME_DIR"
+ local backupDir="$CONFIG_CWD_BACKUP_DIR"
+ __gitcmd ${1} 2>&1 | printf_readline 4
+ cd "$workingTree" && git checkout --git-dir="$gitDir/" --work-tree="$workingTree" | printf_readline 4 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__backup() {
+ [ $# -ne 0 ] || return
+ local gitDir="$CONFIG_CWD_BARE_DIR"
+ local workingTree="$CONFIG_CWD_HOME_DIR/os"
+ local backupDir="$CONFIG_CWD_BACKUP_DIR"
+ rsync -a --remove-source-files "$1" "$backupDir/"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__git_remote() {
+ if [ -z "$1" ]; then
+ printf_read_input "3" "Enter the url to your git repo:" "120" "url"
+ __stow remote add origin "$url"
+ __gitcmd push --set-upstream origin main | printf_readline
+ else
+ __stow remote "$*"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__gitconfig_local() {
+ local gitDir="$CONFIG_CWD_BARE_DIR"
+ local workingTree="$CONFIG_CWD_HOME_DIR"
+ printf_green "Setting up the local gitconfig file"
+ if grep -sh "$gitDir/config.local" "$gitDir/config" | grep -v '=' | sed 's| *||g' | grep -q '^'; then
+ cat </dev/null
+
+[include]
+path = $gitDir/config.local
+
+EOF
+ fi
+
+ cat </dev/null
+[color "branch"]
+ current = green bold
+ local = green
+ remote = yellow
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+[status]
+ submoduleSummary = 1
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+[color "diff"]
+ frag = magenta
+ meta = yellow
+ new = green
+ old = red
+ newMoved = cyan
+ oldMoved = blue
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+[color "status"]
+ added = green reverse
+ changed = yellow reverse
+ untracked = red reverse
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+[diff]
+ colorMoved = zebra
+ submodule = log
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+[diff "bin"]
+ textconv = hexdump -v -C
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#pretty log
+[pretty]
+ custom = "%C(magenta)%h%C(red)%d %C(yellow)%ar %C(green)%s %C(yellow)(%an)"
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Aliases
+g = "!(){ git --git-dir="$gitDir/" --work-tree="$workingTree" log --graph --pretty=custom; };f"
+l = "!f(){ git --git-dir="$gitDir/" --work-tree="$workingTree" log --pretty=custom; };f"
+s = "!f(){ git --git-dir="$gitDir/" --work-tree="$workingTree" status -s -b; };f"
+p = "!f(){ git --git-dir="$gitDir/" --work-tree="$workingTree" push; };f"
+
+EOF
+
+ __gitcmd config --local commit.gpgSign false &>/dev/null
+ __gitcmd config --local status.showUntrackedFiles no &>/dev/null
+ __gitcmd config --local core.excludesfile "$workingTree/.gitignore" &>/dev/null
+
+ if [ -f "$gitDir/config.local" ]; then
+ printf_blue "The local git config file has been created in"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file in"
+ exitCode=1
+ fi
+ printf_blue "$gitDir/config.local"
+ return ${exitCode:-0}
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__git_init() {
+ if [ $# -gt 1 ] && [[ "$*" = *config ]] || [[ "$*" = *bare ]] || [[ "$*" = *clone ]] || [[ "$*" = *bare ]] || [[ "$*" = *info ]]; then
+ return 0
+ fi
+ local choice="" email="" name="" gitDir="" workingTree=""
+ local gitDir="$CONFIG_CWD_BARE_DIR"
+ local workingTree="$CONFIG_CWD_HOME_DIR"
+ if [ ! -d "$gitDir/.git" ] || [ ! -f "$gitDir/config" ] || [ ! -f "$workingTree/.gitignore" ]; then
+ printf_read_question "4" "Should I initialize $gitDir [y/n]" "1" "continue"
+ if printf_answer_yes "$continue"; then
+ if [ ! -f "$workingTree/.gitignore" ]; then
+ printf '%s' '# Disable reminder in prompt\nignoredirmessage\n\n' >>"$workingTree/.gitignore"
+ printf '%s' "# Ignore the bare repo\n$gitDir\n*/.git/*\n" >>"$workingTree/.gitignore"
+ else
+ grep -shq "$gitDir" "$workingTree/.gitignore" &>/dev/null || printf '%s' '# Disable reminder in prompt\nignoredirmessage\n\n' >>"$workingTree/.gitignore"
+ grep -shq '/.git/' "$workingTree/.gitignore" &>/dev/null || printf '%s' "# Ignore the bare repo\n$gitDir\n*/.git/*\n" >>"$workingTree/.gitignore"
+ fi
+ printf_read_question "4" "Do you already have a dotfiles repo: [y/n]" "1" "repo_init"
+ if printf_answer_yes "$repo_init"; then
+ printf_read_input "4" "What is the repo url:" "120" "repo_init_url"
+ git clone --bare "$repo_init_url" "$gitDir" -q &>/dev/null
+ __checkout
+ else
+ printf_cyan "Initializing $gitDir"
+ git init --bare "$gitDir" -q
+ git branch -m main &>/dev/null
+ [ -f "$gitDir/config" ] || printf_exit "Failed to initialize the repo"
+ printf_read_question "4" "Would you like to add a remote git repo: [y/n]" "1" "remote_repo_init"
+ if printf_answer_yes "$remote_repo_init"; then
+ printf_read_input "4" "Enter the url to your git repo:" "120" "remote_repo_init_url"
+ __stow remote add origin "$remote_repo_init_url" && remote_enabled=true
+ else
+ printf_green "You did not add a remote git repo"
+ fi
+ fi
+ __gitconfig_local "$gitDir"
+ name="$(__gitcmd config --local --get user.name 2>/dev/null | grep '^' || git config --get user.name 2>/dev/null | grep '^')"
+ email="$(__gitcmd config --local --get user.email 2>/dev/null | grep '^' || git config --get user.email 2>/dev/null | grep '^')"
+ if [ -z "$name" ]; then
+ printf_read_input "4" "Enter your name:" "120" "name"
+ fi
+ if [ -z "$email" ]; then
+ printf_read_input "4" "Enter email address:" "120" "email"
+ fi
+ printf_cyan "Adding include.path config.local to $gitDir/config"
+ __gitcmd config --local include.path "$gitDir/config.local"
+ printf_blue "Adding status.showUntrackedFiles no to $gitDir/config"
+ __gitcmd config --local status.showUntrackedFiles "no"
+ printf_green "Adding commit.gpgSign false to $gitDir/config"
+ __gitcmd config --local commit.gpgSign false
+ printf_cyan "Adding user.name $name to $gitDir/config"
+ __gitcmd config --local user.name "$name"
+ printf_blue "Adding user.email $email to $gitDir/config"
+ __gitcmd config --local user.email "$email"
+ printf_green "Adding core.excludesfile to $workingTree/config"
+ __gitcmd config --local core.excludesfile "$workingTree/.gitignore"
+ if [ -f "$workingTree/.gitignore" ]; then
+ printf_cyan 'Adding .gitignore'
+ __stow__add ".gitignore"
+ fi
+ if [ -z "$repo_init_url" ]; then
+ printf_purple 'Committing .gitignore'
+ __stow_commit '🏠🐜❗ Added .gitignore 🏠🐜❗'
+ sleep 1
+ fi
+ if [ -n "$remote_repo_init_url" ] && [ -z "$repo_init_url" ]; then
+ printf_read_question "4" "Would you like to push your changes: [y/n]" "1" "push"
+ printf_read_question "5" "This will overwrite anything in the remote repo, Continue: [y/n]" "1" "confirm"
+ if printf_answer_yes "$push" && printf_answer_yes "$confirm"; then
+ __gitcmd push --set-upstream origin main -f -q
+ fi
+ fi
+ __stow l | head -n 5
+ __show_info
+ [ -f "$CONFIG_CWD_BARE_DIR/config" ] && __stow status | grep -v 'On branch '
+ exit "$?"
+ fi
+ else
+ return
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CONFIG_CONFIG_FILE="${CONFIG_CONFIG_FILE:-settings.conf}"
+CONFIG_CONFIG_DIR="${CONFIG_CONFIG_DIR:-$HOME/.config/myscripts/config}"
+CONFIG_CONFIG_BACKUP_DIR="${CONFIG_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/config/backups}"
+CONFIG_LOG_DIR="${CONFIG_LOG_DIR:-$HOME/.local/log/config}"
+CONFIG_TEMP_DIR="${CONFIG_TEMP_DIR:-$HOME/.local/tmp/system_scripts/config}"
+CONFIG_CACHE_DIR="${CONFIG_CACHE_DIR:-$HOME/.cache/config}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CONFIG_OUTPUT_COLOR_1="${CONFIG_OUTPUT_COLOR_1:-33}"
+CONFIG_OUTPUT_COLOR_2="${CONFIG_OUTPUT_COLOR_2:-5}"
+CONFIG_OUTPUT_COLOR_GOOD="${CONFIG_OUTPUT_COLOR_GOOD:-2}"
+CONFIG_OUTPUT_COLOR_ERROR="${CONFIG_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CONFIG_NOTIFY_ENABLED="${CONFIG_NOTIFY_ENABLED:-yes}"
+CONFIG_GOOD_NAME="${CONFIG_GOOD_NAME:-Great:}"
+CONFIG_ERROR_NAME="${CONFIG_ERROR_NAME:-Error:}"
+CONFIG_GOOD_MESSAGE="${CONFIG_GOOD_MESSAGE:-No errors reported}"
+CONFIG_ERROR_MESSAGE="${CONFIG_ERROR_MESSAGE:-Errors were reported}"
+CONFIG_NOTIFY_CLIENT_NAME="${CONFIG_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CONFIG_NOTIFY_CLIENT_ICON="${CONFIG_NOTIFY_CLIENT_ICON:-notification-new}"
+CONFIG_NOTIFY_CLIENT_URGENCY="${CONFIG_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CONFIG_SYSTEM_HOME="${CONFIG_SYSTEM_HOME:-$HOME/.config/myscripts/config/home}"
+CONFIG_GIT_BARE_DIR="${CONFIG_GIT_BARE_DIR:-$HOME/.local/dotfiles/config/bare}"
+CONFIG_SYSTEM_BACKUP_DIR="${CONFIG_SYSTEM_BACKUP_DIR:-$HOME/.local/share/myscripts/config/backups}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CONFIG_CONFIG_DIR/$CONFIG_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CONFIG_CONFIG_DIR/$CONFIG_CONFIG_FILE" ] && . "$CONFIG_CONFIG_DIR/$CONFIG_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CONFIG_LOG_DIR" ] || mkdir -p "$CONFIG_LOG_DIR" |& __devnull
+[ -d "$CONFIG_TEMP_DIR" ] || mkdir -p "$CONFIG_TEMP_DIR" |& __devnull
+[ -d "$CONFIG_CACHE_DIR" ] || mkdir -p "$CONFIG_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CONFIG_TEMP_FILE="${CONFIG_TEMP_FILE:-$(mktemp $CONFIG_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CONFIG_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CONFIG_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CONFIG_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CONFIG_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CONFIG_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CONFIG_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS="a,b,c,d,e,f,g,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=",system:,name::,custom:::,root"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="init,info,ignore,local,log,status,delete,restore,remove,add,commit,"
+ARRAY+="checkout,remote,pull,push,set,rename,clone,bare,backup"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CONFIG_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ CONFIG_CWD="$2"
+ CONFIG_CWD_HOME_DIR="$2"
+ CONFIG_SYSTEM_NAME="$(basename -- "$2" 2>/dev/null)" shift 2
+ [ -d "$CONFIG_CWD" ] || mkdir -p "$CONFIG_CWD" |& __devnull
+ shift 2
+ ;;
+ --root)
+ shift 1
+ CONFIG_CWD_HOME_DIR="/"
+ ;;
+ --system)
+ shift 1
+ if [ "$1" = "help" ]; then
+ printf_custom "41" "Allows you to keep your system settings in a git repo"
+ printf_green "Usage: config --system commands"
+ printf_exit "See config help for commands"
+ __help
+ fi
+ __requiresudo true
+ CONFIG_SYSTEM_NAME="$(hostname -s)"
+ ;;
+ --name)
+ if [ -z "$1" ] || [ -z "$2" ]; then
+ printf_custom "41" "This allows the use of a custom git dir"
+ printf_green "Usage: config --custom $CONFIG_GIT_BARE_DIR commands"
+ printf_exit "See config help for commands"
+ exit 1
+ fi
+ CONFIG_SYSTEM_NAME="$2"
+ if [ -d "$CONFIG_GIT_BARE_DIR" ]; then
+ printf_yellow "Warning: $CONFIG_GIT_BARE_DIR already in use"
+ printf_read_question "Are you sure you want to continue using this repo? " "1" || exit 1
+ fi
+ shift 2
+ ;;
+ --custom)
+ if [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then
+ printf_custom "41" "This allows the use of a custom git dir and home dir"
+ printf_green "Usage: $APPNAME --custom $CONFIG_GIT_BARE_DIR $CONFIG_SYSTEM_HOME commands"
+ printf_green 'IE: $APPNAME --custom "'$HOME/.local/dotfiles/custom/bare'" "'$HOME/.local/dotfiles/custom/bare/home'" commands'
+ printf_exit "See config help for commands"
+ fi
+ CONFIG_CWD_BARE_DIR="$2"
+ CONFIG_CWD_HOME_DIR="$3"
+ shift 3
+ ;;
+ -a | -b | -c | -d | -e | -f | -g | -h | -i | -j | -k | -l | -m | -n | -o | -p | -q | -r | -s | -t | -u | -v | -w | -x | -y | -z)
+ GIT_OPTS+="$1 "
+ shift 1
+ ;;
+ -A | -B | -C | -D | -E | -F | -G | -H | -I | -J | -K | -L | -M | -N | -O | -P | -Q | -R | -S | -T | -U | -V | -W | -X | -Y | -Z)
+ #GIT_OPTS+="$1 "
+ shift 1
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CONFIG_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CONFIG_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CONFIG_CWD="$1" && shift 1 || CONFIG_CWD="${CONFIG_CWD:-$PWD}"
+CONFIG_CWD="$(realpath "${CONFIG_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CONFIG_CWD" ] && cd "$CONFIG_CWD"; then
+# if [ "$CONFIG_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CONFIG_CWD"
+# fi
+# else
+# printf_exit "💔 $CONFIG_CWD does not exist 💔"
+# fi
+export CONFIG_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+CONFIG_SYSTEM_NAME="${CONFIG_SYSTEM_NAME:-$USER}"
+CONFIG_CWD_HOME_DIR="${CONFIG_CWD_HOME_DIR:-$CONFIG_SYSTEM_HOME}/$CONFIG_SYSTEM_NAME" # Git working dir
+CONFIG_CWD_BARE_DIR="${CONFIG_CWD_BARE_DIR:-$CONFIG_GIT_BARE_DIR}/$CONFIG_SYSTEM_NAME" # Git bare dir
+CONFIG_CWD_BACKUP_DIR="${CONFIG_CWD_BACKUP_DIR:-$CONFIG_SYSTEM_BACKUP_DIR}/$CONFIG_SYSTEM_NAME/$(date +'%Y/%m')" # Git backup dir
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+mkdir -p "$CONFIG_CWD_HOME_DIR" "$CONFIG_CWD_BACKUP_DIR" &>/dev/null
+{ [ -d "$CONFIG_CWD_HOME_DIR" ] && [ -f "$CONFIG_CWD_BARE_DIR/config" ]; } || __git_init "$*"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+init)
+ shift 1
+ __git_init "$*"
+ ;;
+
+info)
+ shift 1
+ __show_info
+ exit
+ ;;
+
+local)
+ shift 1
+ for opt in "$@"; do
+ printf_cyan "Adding $opt into $CONFIG_CWD_BARE_DIR/config"
+ __gitcmd config --local "$opt" &>/dev/null || exitCode=$(exitCode++)
+ done
+ exit ${exitCode:-0}
+ ;;
+
+log | l)
+ shift 1
+ __stow log --graph --pretty=custom "$*"
+ exit
+ ;;
+
+status | s)
+ shift 1
+ __stow status -s -b "$*"
+ exit
+ ;;
+
+ignore)
+ shift 1
+ gitignore "$CONFIG_CWD_HOME_DIR" add "$*"
+ exit
+ ;;
+
+delete)
+ shift 1
+ printf_read_question 1 "This will delete the git repo are you sure?" "1" "delete"
+ if printf_answer_yes "$delete"; then
+ printf_green "Backing up to $CONFIG_CWD_BACKUP_DIR/deleted"
+ mkdir -p "$CONFIG_CWD_BACKUP_DIR/deleted" &>/dev/null
+ cp -Rfa "$CONFIG_CWD_HOME_DIR/." "$CONFIG_CWD_BACKUP_DIR/deleted/" &>/dev/null
+ printf_blue "Deleting the files in $CONFIG_CWD_BARE_DIR"
+ rm -Rf "$CONFIG_CWD_BARE_DIR"
+ printf_cyan "Deleting the files in $CONFIG_CWD_HOME_DIR"
+ rm -Rf "$CONFIG_CWD_HOME_DIR"
+ fi
+ exit $?
+ ;;
+
+restore | reset)
+ shift 1
+ __stow reset -- "$*"
+ ;;
+
+rm | remove)
+ shift 1
+ __stow rm -q -r --cached -f "$*"
+ ;;
+
+add | stow)
+ shift 1
+ printf_green "'🏠🐜❗ Adding files to repo - this may take a moment 🏠🐜❗'"
+ for file in "$@"; do
+ f="$(realpath "$file")"
+ printf_blue "Adding $f to repo"
+ __add "$f"
+ done
+ [ $? = 0 ] && printf_green "Don't forget to run config commit"
+ #__stow commit -q -m "'🏠🐜❗ Added Files 🏠🐜❗'"
+ ;;
+
+commit)
+ shift 1
+ if [ -z "$1" ]; then
+ printf_green "'🏠🐜❗ Committing files to repo 🏠🐜❗'"
+ __stow_commit "'🏠🐜❗ Added files to repo 🏠🐜❗'"
+ else
+ __gitcmd commit "$*"
+ fi
+ ;;
+
+checkout)
+ shift 1
+ __checkout "$*"
+ ;;
+
+remote)
+ shift 1
+ if __online_check; then
+ __git_remote "$*"
+ fi
+ ;;
+
+pull)
+ shift 1
+ if __online_check; then
+ __stow pull "$*"
+ fi
+ ;;
+
+push)
+ shift 1
+ if __online_check; then
+ __stow push "$*" || __stow push --set-upstream origin main "$@"
+ fi
+ ;;
+
+set)
+ shift 1
+ __stow config "$*"
+ exit $?
+ ;;
+
+rename)
+ shift 1
+ [ "$1" = "help" ] && printf_exit 1 2 "Usage: $APPNAME rename fromBranch toBranch - $APPNAME rename master main"
+ fromBranch="${1:-master}"
+ toBranch="${2:-main}"
+ __stow branch -m $fromBranch $toBranch
+ __stow fetch origin
+ __stow branch -u origin/$fromBranch $toBranch
+ __stow remote set-head origin -a
+ __stow push --set-upstream origin $toBranch
+ __stow branch -d "$fromBranch"
+ exit $?
+ ;;
+
+clone)
+ shift 1
+ git clone "$1" "${2:-$CONFIG_CWD_HOME_DIR}" -q
+ exit $?
+ ;;
+
+bare)
+ shift 1
+ ARGS="$*"
+ __bare $ARGS
+ exit $?
+ ;;
+
+backup)
+ shift 1
+ __backup "$*"
+ exit $?
+ ;;
+
+*)
+ [ "$#" = 0 ] && __help || __stow "$*"
+ exit $?
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/config-editor b/bin/config-editor
new file mode 100755
index 000000000..c46849f78
--- /dev/null
+++ b/bin/config-editor
@@ -0,0 +1,575 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202303122115-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : config-editor --help
+# @@Copyright : Copyright: (c) 2023 Jason Hempstead, Casjays Developments
+# @@Created : Sunday, Mar 12, 2023 21:15 EDT
+# @@File : config-editor
+# @@Description :
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202303122115-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CONFIG_EDITOR_REQUIRE_SUDO="${CONFIG_EDITOR_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && CONFIG_EDITOR_EXIT_STATUS=0 || CONFIG_EDITOR_EXIT_STATUS=1
+ return ${CONFIG_EDITOR_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && CONFIG_EDITOR_EXIT_STATUS=0 || CONFIG_EDITOR_EXIT_STATUS=1
+ return ${CONFIG_EDITOR_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ CONFIG_EDITOR_EXIT_STATUS=0
+ [ -n "$1" ] && local CONFIG_EDITOR_EXIT_STATUS="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && CONFIG_EDITOR_EXIT_STATUS+=$(($CONFIG_EDITOR_EXIT_STATUS + 0)) || CONFIG_EDITOR_EXIT_STATUS+=$(($CONFIG_EDITOR_EXIT_STATUS + 1))
+ done
+ [ $CONFIG_EDITOR_EXIT_STATUS -eq 0 ] || CONFIG_EDITOR_EXIT_STATUS=3
+ return ${CONFIG_EDITOR_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local CONFIG_EDITOR_EXIT_STATUS=0
+ curl -q -LSsfI --max-time 1 --retry 0 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || CONFIG_EDITOR_EXIT_STATUS=4
+ return ${CONFIG_EDITOR_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CONFIG_EDITOR_CONFIG_DIR/$CONFIG_EDITOR_CONFIG_FILE"
+ fi
+ [ -d "$CONFIG_EDITOR_CONFIG_DIR" ] || mkdir -p "$CONFIG_EDITOR_CONFIG_DIR"
+ [ -d "$CONFIG_EDITOR_CONFIG_BACKUP_DIR" ] || mkdir -p "$CONFIG_EDITOR_CONFIG_BACKUP_DIR"
+ [ -f "$CONFIG_EDITOR_CONFIG_DIR/$CONFIG_EDITOR_CONFIG_FILE" ] &&
+ cp -Rf "$CONFIG_EDITOR_CONFIG_DIR/$CONFIG_EDITOR_CONFIG_FILE" "$CONFIG_EDITOR_CONFIG_BACKUP_DIR/$CONFIG_EDITOR_CONFIG_FILE.$$"
+ cat <"$CONFIG_EDITOR_CONFIG_DIR/$CONFIG_EDITOR_CONFIG_FILE"
+# Settings for config-editor
+CONFIG_FILE_EDITOR="${CONFIG_FILE_EDITOR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# config files
+CONFIG_EDITOR_FILE_LIST+=(alacritty="$HOME/.config/alacritty/alacritty.yml")
+CONFIG_EDITOR_FILE_LIST+=(awesome="$HOME/.config/awesome/rc.lua")
+CONFIG_EDITOR_FILE_LIST+=(bashrc="$HOME/.bashrc")
+CONFIG_EDITOR_FILE_LIST+=(bspwm="$HOME/.config/bspwm/bspwmrc")
+CONFIG_EDITOR_FILE_LIST+=(dunst="$HOME/.config/dunst/dunstrc")
+CONFIG_EDITOR_FILE_LIST+=(dwm="$HOME/dwm/config.h")
+CONFIG_EDITOR_FILE_LIST+=(i3="$HOME/.i3/config")
+CONFIG_EDITOR_FILE_LIST+=(neovim="$HOME/.config/nvim/init.vim")
+CONFIG_EDITOR_FILE_LIST+=(picom="$HOME/.config/picom/picom.conf")
+CONFIG_EDITOR_FILE_LIST+=(polybar="$HOME/.config/polybar/config")
+CONFIG_EDITOR_FILE_LIST+=(qtile="$HOME/.config/qtile/config.py")
+CONFIG_EDITOR_FILE_LIST+=(sxhkd="$HOME/.config/sxhkd/sxhkdrc")
+CONFIG_EDITOR_FILE_LIST+=(termite="$HOME/.config/termite/config")
+CONFIG_EDITOR_FILE_LIST+=(vifm="$HOME/.config/vifm/vifmrc")
+CONFIG_EDITOR_FILE_LIST+=(vim="$HOME/.config/vim/vimrc")
+CONFIG_EDITOR_FILE_LIST+=(vimb="$HOME/.config/vimb/config")
+CONFIG_EDITOR_FILE_LIST+=(xmobar="$HOME/.config/xmobar/xmobarrc")
+CONFIG_EDITOR_FILE_LIST+=(xmonad="$HOME/.config/xmonad/xmonad.hs")
+CONFIG_EDITOR_FILE_LIST+=(Xresources="$HOME/.Xresources")
+CONFIG_EDITOR_FILE_LIST+=(zsh="$HOME/.zshrc")
+CONFIG_EDITOR_FILE_LIST+=(emacs="$HOME/.emacs.d/init.el")
+$(__get_file_list)
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CONFIG_EDITOR_OUTPUT_COLOR_1="${CONFIG_EDITOR_OUTPUT_COLOR_1:-}"
+CONFIG_EDITOR_OUTPUT_COLOR_2="${CONFIG_EDITOR_OUTPUT_COLOR_2:-}"
+CONFIG_EDITOR_OUTPUT_COLOR_GOOD="${CONFIG_EDITOR_OUTPUT_COLOR_GOOD:-}"
+CONFIG_EDITOR_OUTPUT_COLOR_ERROR="${CONFIG_EDITOR_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CONFIG_EDITOR_NOTIFY_ENABLED="${CONFIG_EDITOR_NOTIFY_ENABLED:-}"
+CONFIG_EDITOR_GOOD_NAME="${CONFIG_EDITOR_GOOD_NAME:-}"
+CONFIG_EDITOR_ERROR_NAME="${CONFIG_EDITOR_ERROR_NAME:-}"
+CONFIG_EDITOR_GOOD_MESSAGE="${CONFIG_EDITOR_GOOD_MESSAGE:-}"
+CONFIG_EDITOR_ERROR_MESSAGE="${CONFIG_EDITOR_ERROR_MESSAGE:-}"
+CONFIG_EDITOR_NOTIFY_CLIENT_NAME="${CONFIG_EDITOR_NOTIFY_CLIENT_NAME:-}"
+CONFIG_EDITOR_NOTIFY_CLIENT_ICON="${CONFIG_EDITOR_NOTIFY_CLIENT_ICON:-}"
+CONFIG_EDITOR_NOTIFY_CLIENT_URGENCY="${CONFIG_EDITOR_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CONFIG_EDITOR_CONFIG_DIR/$CONFIG_EDITOR_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CONFIG_EDITOR_CONFIG_DIR/$CONFIG_EDITOR_CONFIG_FILE"
+ CONFIG_EDITOR_EXIT_STATUS=0
+ else
+ printf_red "Failed to create the config file"
+ CONFIG_EDITOR_EXIT_STATUS=1
+ fi
+ return ${CONFIG_EDITOR_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "config-editor: - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: config-editor [options] [commands]"
+ __printf_line " - "
+ __printf_line " - "
+ __printf_line "--dir - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__grep() { grep "$@" 2>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CONFIG_EDITOR_REQUIRE_SUDO" = "yes" ] && [ -z "$CONFIG_EDITOR_REQUIRE_SUDO_RUN" ]; then
+ export CONFIG_EDITOR_REQUIRE_SUDO="no"
+ export CONFIG_EDITOR_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ CONFIG_EDITOR_EXIT_STATUS=$?
+ else
+ printf '%s\n' "This requires root to run"
+ CONFIG_EDITOR_EXIT_STATUS=1
+ fi
+ return ${CONFIG_EDITOR_EXIT_STATUS:-0}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ CONFIG_EDITOR_EXIT_STATUS=${CONFIG_EDITOR_EXIT_STATUS:-0}
+ [ -f "$CONFIG_EDITOR_TEMP_FILE" ] && rm -Rf "$CONFIG_EDITOR_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $CONFIG_EDITOR_EXIT_STATUS
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+if __cmd_exists rofi; then
+ __dmenu() { rofi -theme ${ROFI_THEME:-purple} -show -dmenu -i -p 'Edit config file' || return 1; }
+elif __cmd_exists dmenu; then
+ __dmenu() { dmenu -i -p 'Edit config file' || return 1; }
+else
+ notifications "$PROG" "This requires either dmenu or rofi"
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_file_list() {
+ CONFIG_EDITOR_GET_FILES="$(find ~/.config -maxdepth 10 -name 'settings.conf' -o -name -o -name '*.hs' -o -name 'config*.' -type f)"
+ for file in $CONFIG_EDITOR_GET_FILES; do
+ filename="$(basename -- "$(dirname "$file")")"
+ echo 'CONFIG_EDITOR_FILE_LIST+=("'${filename}'='${file}'")'
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CONFIG_EDITOR_EXIT_STATUS=0
+CONFIG_EDITOR_CONFIG_FILE="${CONFIG_EDITOR_CONFIG_FILE:-settings.conf}"
+CONFIG_EDITOR_CONFIG_DIR="${CONFIG_EDITOR_CONFIG_DIR:-$HOME/.config/myscripts/config-editor}"
+CONFIG_EDITOR_CONFIG_BACKUP_DIR="${CONFIG_EDITOR_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/config-editor/backups}"
+CONFIG_EDITOR_LOG_DIR="${CONFIG_EDITOR_LOG_DIR:-$HOME/.local/log/config-editor}"
+CONFIG_EDITOR_RUN_DIR="${CONFIG_EDITOR_RUN_DIR:-$HOME/.local/run/system_scripts/$CONFIG_EDITOR_SCRIPTS_PREFIX}"
+CONFIG_EDITOR_TEMP_DIR="${CONFIG_EDITOR_TEMP_DIR:-$HOME/.local/tmp/system_scripts/config-editor}"
+CONFIG_EDITOR_CACHE_DIR="${CONFIG_EDITOR_CACHE_DIR:-$HOME/.cache/config-editor}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CONFIG_EDITOR_OUTPUT_COLOR_1="${CONFIG_EDITOR_OUTPUT_COLOR_1:-33}"
+CONFIG_EDITOR_OUTPUT_COLOR_2="${CONFIG_EDITOR_OUTPUT_COLOR_2:-5}"
+CONFIG_EDITOR_OUTPUT_COLOR_GOOD="${CONFIG_EDITOR_OUTPUT_COLOR_GOOD:-2}"
+CONFIG_EDITOR_OUTPUT_COLOR_ERROR="${CONFIG_EDITOR_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CONFIG_EDITOR_NOTIFY_ENABLED="${CONFIG_EDITOR_NOTIFY_ENABLED:-yes}"
+CONFIG_EDITOR_GOOD_NAME="${CONFIG_EDITOR_GOOD_NAME:-Great:}"
+CONFIG_EDITOR_ERROR_NAME="${CONFIG_EDITOR_ERROR_NAME:-Error:}"
+CONFIG_EDITOR_GOOD_MESSAGE="${CONFIG_EDITOR_GOOD_MESSAGE:-No errors reported}"
+CONFIG_EDITOR_ERROR_MESSAGE="${CONFIG_EDITOR_ERROR_MESSAGE:-Errors were reported}"
+CONFIG_EDITOR_NOTIFY_CLIENT_NAME="${CONFIG_EDITOR_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CONFIG_EDITOR_NOTIFY_CLIENT_ICON="${CONFIG_EDITOR_NOTIFY_CLIENT_ICON:-notification-new}"
+CONFIG_EDITOR_NOTIFY_CLIENT_URGENCY="${CONFIG_EDITOR_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CONFIG_EDITOR_FILE_LIST=()
+CONFIG_FILE_EDITOR="${CONFIG_FILE_EDITOR:-${EDITOR:-$(type -P 'vim' || type -P 'nano')}}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CONFIG_EDITOR_CONFIG_DIR/$CONFIG_EDITOR_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CONFIG_EDITOR_CONFIG_DIR/$CONFIG_EDITOR_CONFIG_FILE" ] && . "$CONFIG_EDITOR_CONFIG_DIR/$CONFIG_EDITOR_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CONFIG_EDITOR_RUN_DIR" ] || mkdir -p "$CONFIG_EDITOR_RUN_DIR" |& __devnull
+[ -d "$CONFIG_EDITOR_LOG_DIR" ] || mkdir -p "$CONFIG_EDITOR_LOG_DIR" |& __devnull
+[ -d "$CONFIG_EDITOR_TEMP_DIR" ] || mkdir -p "$CONFIG_EDITOR_TEMP_DIR" |& __devnull
+[ -d "$CONFIG_EDITOR_CACHE_DIR" ] || mkdir -p "$CONFIG_EDITOR_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CONFIG_EDITOR_TEMP_FILE="${CONFIG_EDITOR_TEMP_FILE:-$(mktemp $CONFIG_EDITOR_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CONFIG_EDITOR_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CONFIG_EDITOR_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CONFIG_EDITOR_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CONFIG_EDITOR_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CONFIG_EDITOR_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CONFIG_EDITOR_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CONFIG_EDITOR_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ CONFIG_EDITOR_CWD="$2"
+ [ -d "$CONFIG_EDITOR_CWD" ] || mkdir -p "$CONFIG_EDITOR_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CONFIG_EDITOR_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CONFIG_EDITOR_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CONFIG_EDITOR_CWD="$1" && shift 1 || CONFIG_EDITOR_CWD="${CONFIG_EDITOR_CWD:-$PWD}"
+CONFIG_EDITOR_CWD="$(realpath "${CONFIG_EDITOR_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CONFIG_EDITOR_CWD" ] && cd "$CONFIG_EDITOR_CWD"; then
+# if [ "$CONFIG_EDITOR_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CONFIG_EDITOR_CWD"
+# fi
+# else
+# printf_exit "💔 $CONFIG_EDITOR_CWD does not exist 💔"
+# fi
+export CONFIG_EDITOR_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Export variables
+printf '%s\n' "${CONFIG_EDITOR_FILE_LIST[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+if [ $# -ne 0 ] && [ -f "$1" ]; then
+ OPEN_FILE="$1"
+else
+ EDIT_NAME="$(printf '%s\n%s\n' "exit" "${CONFIG_EDITOR_FILE_LIST[@]}" | awk -F '=' '{print $1}' | __dmenu)"
+ OPEN_FILE="$(printf '%s\n' "${CONFIG_EDITOR_FILE_LIST[@]}" | grep ^"$EDIT_NAME" | awk -F '=' '{print $2}')"
+fi
+if [ -f "$OPEN_FILE" ]; then
+ __notifications "Opening $OPEN_FILE in $CONFIG_FILE_EDITOR"
+ eval "$CONFIG_FILE_EDITOR $OPEN_FILE"
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+CONFIG_EDITOR_EXIT_STATUS="${CONFIG_EDITOR_EXIT_STATUS:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${CONFIG_EDITOR_EXIT_STATUS:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/corona-virus b/bin/corona-virus
new file mode 100755
index 000000000..34708e96e
--- /dev/null
+++ b/bin/corona-virus
@@ -0,0 +1,561 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208050033-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : corona-virus --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 00:33 EDT
+# @@File : corona-virus
+# @@Description : corona-virus local stats
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208050033-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CORONA_VIRUS_REQUIRE_SUDO="${CORONA_VIRUS_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CORONA_VIRUS_CONFIG_DIR/$CORONA_VIRUS_CONFIG_FILE"
+ fi
+ [ -d "$CORONA_VIRUS_CONFIG_DIR" ] || mkdir -p "$CORONA_VIRUS_CONFIG_DIR"
+ [ -d "$CORONA_VIRUS_CONFIG_BACKUP_DIR" ] || mkdir -p "$CORONA_VIRUS_CONFIG_BACKUP_DIR"
+ [ -f "$CORONA_VIRUS_CONFIG_DIR/$CORONA_VIRUS_CONFIG_FILE" ] &&
+ cp -Rf "$CORONA_VIRUS_CONFIG_DIR/$CORONA_VIRUS_CONFIG_FILE" "$CORONA_VIRUS_CONFIG_BACKUP_DIR/$CORONA_VIRUS_CONFIG_FILE.$$"
+ cat <"$CORONA_VIRUS_CONFIG_DIR/$CORONA_VIRUS_CONFIG_FILE"
+# Settings for corona-virus
+CORONA_VIRUS_COUNTRY="${CORONA_VIRUS_COUNTRY:-}"
+CORONA_VIRUS_API_URL="${CORONA_VIRUS_API_URL:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CORONA_VIRUS_OUTPUT_COLOR_1="${CORONA_VIRUS_OUTPUT_COLOR_1:-}"
+CORONA_VIRUS_OUTPUT_COLOR_2="${CORONA_VIRUS_OUTPUT_COLOR_2:-}"
+CORONA_VIRUS_OUTPUT_COLOR_GOOD="${CORONA_VIRUS_OUTPUT_COLOR_GOOD:-}"
+CORONA_VIRUS_OUTPUT_COLOR_ERROR="${CORONA_VIRUS_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CORONA_VIRUS_NOTIFY_ENABLED="${CORONA_VIRUS_NOTIFY_ENABLED:-}"
+CORONA_VIRUS_GOOD_NAME="${CORONA_VIRUS_GOOD_NAME:-}"
+CORONA_VIRUS_ERROR_NAME="${CORONA_VIRUS_ERROR_NAME:-}"
+CORONA_VIRUS_GOOD_MESSAGE="${CORONA_VIRUS_GOOD_MESSAGE:-}"
+CORONA_VIRUS_ERROR_MESSAGE="${CORONA_VIRUS_ERROR_MESSAGE:-}"
+CORONA_VIRUS_NOTIFY_CLIENT_NAME="${CORONA_VIRUS_NOTIFY_CLIENT_NAME:-}"
+CORONA_VIRUS_NOTIFY_CLIENT_ICON="${CORONA_VIRUS_NOTIFY_CLIENT_ICON:-}"
+CORONA_VIRUS_NOTIFY_CLIENT_URGENCY="${CORONA_VIRUS_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CORONA_VIRUS_CONFIG_DIR/$CORONA_VIRUS_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CORONA_VIRUS_CONFIG_DIR/$CORONA_VIRUS_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "corona-virus: corona-virus local stats - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: corona-virus [options] [countryCode]"
+ __printf_line "usa - Show the stats for the USA"
+ __printf_line "ca - Show the stats for the Canada"
+ __printf_line "mx - Show the stats for the Mexico"
+ __printf_line "uk - Show the stats for the UK"
+ __printf_line "it - Show the stats for the Italy"
+ __printf_line "help - Show the API help page"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CORONA_VIRUS_REQUIRE_SUDO" = "yes" ] && [ -z "$CORONA_VIRUS_REQUIRE_SUDO_RUN" ]; then
+ export CORONA_VIRUS_REQUIRE_SUDO="no"
+ export CORONA_VIRUS_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CORONA_VIRUS_TEMP_FILE" ] && rm -Rf "$CORONA_VIRUS_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__curl() {
+ curl -q -LSsf --max-time 2 --retry 0 "$1" -o "$2" 2>/dev/null
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__print_results() {
+ grep -sh "$LOCATION" "$CORONA_VIRUS_CACHE_DIR/corona-virus" |
+ sed "s/\x1b\[[0-9;]*m//g" |
+ sed "s/\s*//g ; s/║//g ; s/│/;/g" |
+ awk -F';' '{print "😷" $3 " (" $9") 💀" $5 " 🏠("$7"%)"}'
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__initial_app() {
+ if [ "$FORCE" = "true" ]; then
+ __rm_rf "$CORONA_VIRUS_CACHE_DIR/corona-virus"
+ __curl "$CORONA_VIRUS_API_URL" "$CORONA_VIRUS_CACHE_DIR/corona-virus"
+ if [ ! -f "$CORONA_VIRUS_CACHE_DIR/corona-virus" ]; then
+ printf_exit "Download unsuccessful"
+ fi
+ fi
+ if [ "$(find "$CORONA_VIRUS_CACHE_DIR/corona-virus" -type f -mmin +120 -delete &>/dev/null)" ] || [ ! -f "$CORONA_VIRUS_CACHE_DIR/corona-virus" ]; then
+ __curl "$CORONA_VIRUS_API_URL" "$CORONA_VIRUS_CACHE_DIR/corona-virus"
+ if [ ! -f "$CORONA_VIRUS_CACHE_DIR/corona-virus" ]; then
+ printf_exit "Download unsuccessful"
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_corona-virus() {
+ __initial_app
+ local LOCATION="$(echo "${1:-$CORONA_VIRUS_COUNTRY}" | tr '[:lower:]' '[:upper:]')"
+ local results="$(__print_results)"
+ local resultsx="$(echo "$results" | sed 's|: |:\n|g;s|) |)\n|g')"
+ if [ -n "$results" ]; then
+ printf_color "$LOCATION: $results\n" "$CORONA_VIRUS_OUTPUT_COLOR"
+ [ -z "$resultsx" ] || __notifications "Stats for $LOCATION:\n$resultsx\n"
+ else
+ printf_exit "I'm sorry but an error has occurred"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+CORONA_VIRUS_CONFIG_FILE="${CORONA_VIRUS_CONFIG_FILE:-settings.conf}"
+CORONA_VIRUS_CONFIG_DIR="${CORONA_VIRUS_CONFIG_DIR:-$HOME/.config/myscripts/corona-virus}"
+CORONA_VIRUS_CONFIG_BACKUP_DIR="${CORONA_VIRUS_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/corona-virus/backups}"
+CORONA_VIRUS_LOG_DIR="${CORONA_VIRUS_LOG_DIR:-$HOME/.local/log/corona-virus}"
+CORONA_VIRUS_TEMP_DIR="${CORONA_VIRUS_TEMP_DIR:-$HOME/.local/tmp/system_scripts/corona-virus}"
+CORONA_VIRUS_CACHE_DIR="${CORONA_VIRUS_CACHE_DIR:-$HOME/.cache/corona-virus}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CORONA_VIRUS_OUTPUT_COLOR_1="${CORONA_VIRUS_OUTPUT_COLOR_1:-33}"
+CORONA_VIRUS_OUTPUT_COLOR_2="${CORONA_VIRUS_OUTPUT_COLOR_2:-5}"
+CORONA_VIRUS_OUTPUT_COLOR_GOOD="${CORONA_VIRUS_OUTPUT_COLOR_GOOD:-2}"
+CORONA_VIRUS_OUTPUT_COLOR_ERROR="${CORONA_VIRUS_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CORONA_VIRUS_NOTIFY_ENABLED="${CORONA_VIRUS_NOTIFY_ENABLED:-yes}"
+CORONA_VIRUS_GOOD_NAME="${CORONA_VIRUS_GOOD_NAME:-Great:}"
+CORONA_VIRUS_ERROR_NAME="${CORONA_VIRUS_ERROR_NAME:-Error:}"
+CORONA_VIRUS_GOOD_MESSAGE="${CORONA_VIRUS_GOOD_MESSAGE:-No errors reported}"
+CORONA_VIRUS_ERROR_MESSAGE="${CORONA_VIRUS_ERROR_MESSAGE:-Errors were reported}"
+CORONA_VIRUS_NOTIFY_CLIENT_NAME="${CORONA_VIRUS_NOTIFY_CLIENT_NAME:-$APPNAME}"
+CORONA_VIRUS_NOTIFY_CLIENT_ICON="${CORONA_VIRUS_NOTIFY_CLIENT_ICON:-notification-new}"
+CORONA_VIRUS_NOTIFY_CLIENT_URGENCY="${CORONA_VIRUS_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+CORONA_VIRUS_COUNTRY="${CORONA_VIRUS_COUNTRY:-USA}"
+CORONA_VIRUS_API_URL="${CORONA_VIRUS_API_URL:-https://corona-stats.online}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$CORONA_VIRUS_CONFIG_DIR/$CORONA_VIRUS_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$CORONA_VIRUS_CONFIG_DIR/$CORONA_VIRUS_CONFIG_FILE" ] && . "$CORONA_VIRUS_CONFIG_DIR/$CORONA_VIRUS_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$CORONA_VIRUS_LOG_DIR" ] || mkdir -p "$CORONA_VIRUS_LOG_DIR" |& __devnull
+[ -d "$CORONA_VIRUS_TEMP_DIR" ] || mkdir -p "$CORONA_VIRUS_TEMP_DIR" |& __devnull
+[ -d "$CORONA_VIRUS_CACHE_DIR" ] || mkdir -p "$CORONA_VIRUS_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CORONA_VIRUS_TEMP_FILE="${CORONA_VIRUS_TEMP_FILE:-$(mktemp $CORONA_VIRUS_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CORONA_VIRUS_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CORONA_VIRUS_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CORONA_VIRUS_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CORONA_VIRUS_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CORONA_VIRUS_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CORONA_VIRUS_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=",force"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CORONA_VIRUS_SILENT="true"
+ ;;
+ --force)
+ shift 1
+ FORCE="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CORONA_VIRUS_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CORONA_VIRUS_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CORONA_VIRUS_CWD="$1" && shift 1 || CORONA_VIRUS_CWD="${CORONA_VIRUS_CWD:-$PWD}"
+CORONA_VIRUS_CWD="$(realpath "${CORONA_VIRUS_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CORONA_VIRUS_CWD" ] && cd "$CORONA_VIRUS_CWD"; then
+# if [ "$CORONA_VIRUS_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CORONA_VIRUS_CWD"
+# fi
+# else
+# printf_exit "💔 $CORONA_VIRUS_CWD does not exist 💔"
+# fi
+export CORONA_VIRUS_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__execute_corona-virus "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/covid19 b/bin/covid19
new file mode 100755
index 000000000..a5e382b28
--- /dev/null
+++ b/bin/covid19
@@ -0,0 +1,541 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208050213-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : covid19 --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 02:13 EDT
+# @@File : covid19
+# @@Description : script to track the covid-19 outbreak
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208050213-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+COVID19_REQUIRE_SUDO="${COVID19_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$COVID19_CONFIG_DIR/$COVID19_CONFIG_FILE"
+ fi
+ [ -d "$COVID19_CONFIG_DIR" ] || mkdir -p "$COVID19_CONFIG_DIR"
+ [ -d "$COVID19_CONFIG_BACKUP_DIR" ] || mkdir -p "$COVID19_CONFIG_BACKUP_DIR"
+ [ -f "$COVID19_CONFIG_DIR/$COVID19_CONFIG_FILE" ] &&
+ cp -Rf "$COVID19_CONFIG_DIR/$COVID19_CONFIG_FILE" "$COVID19_CONFIG_BACKUP_DIR/$COVID19_CONFIG_FILE.$$"
+ cat <"$COVID19_CONFIG_DIR/$COVID19_CONFIG_FILE"
+# Settings for covid19
+COVID19_SERVER_HOST="${COVID19_SERVER_HOST:-}"
+COVID19_PING_URL="${COVID19_PING_URL:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+COVID19_OUTPUT_COLOR_1="${COVID19_OUTPUT_COLOR_1:-}"
+COVID19_OUTPUT_COLOR_2="${COVID19_OUTPUT_COLOR_2:-}"
+COVID19_OUTPUT_COLOR_GOOD="${COVID19_OUTPUT_COLOR_GOOD:-}"
+COVID19_OUTPUT_COLOR_ERROR="${COVID19_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+COVID19_NOTIFY_ENABLED="${COVID19_NOTIFY_ENABLED:-}"
+COVID19_GOOD_NAME="${COVID19_GOOD_NAME:-}"
+COVID19_ERROR_NAME="${COVID19_ERROR_NAME:-}"
+COVID19_GOOD_MESSAGE="${COVID19_GOOD_MESSAGE:-}"
+COVID19_ERROR_MESSAGE="${COVID19_ERROR_MESSAGE:-}"
+COVID19_NOTIFY_CLIENT_NAME="${COVID19_NOTIFY_CLIENT_NAME:-}"
+COVID19_NOTIFY_CLIENT_ICON="${COVID19_NOTIFY_CLIENT_ICON:-}"
+COVID19_NOTIFY_CLIENT_URGENCY="${COVID19_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$COVID19_CONFIG_DIR/$COVID19_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$COVID19_CONFIG_DIR/$COVID19_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "covid19: script to track the covid-19 outbreak - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: covid19 [options] [countryCode]"
+ __printf_line "us - Show the stats for the USA"
+ __printf_line "ca - Show the stats for the Canada"
+ __printf_line "mx - Show the stats for the Mexico"
+ __printf_line "uk - Show the stats for the UK"
+ __printf_line "it - Show the stats for the Italy"
+ __printf_line "help - Show the API help page"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$COVID19_REQUIRE_SUDO" = "yes" ] && [ -z "$COVID19_REQUIRE_SUDO_RUN" ]; then
+ export COVID19_REQUIRE_SUDO="no"
+ export COVID19_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$COVID19_TEMP_FILE" ] && rm -Rf "$COVID19_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__curl() {
+ curl -q -LSsf --max-time 1 --retry 0 "$1" 2>/dev/null | grep '^' || false
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_covid19() {
+ COVID19_SERVER_QUERY="${*:-$COVID19_SERVER_QUERY}${COVID19_SERVER_OPTIONS:-}"
+ results="$(__curl "$COVID19_SERVER_HOST/$COVID19_SERVER_QUERY")"
+ printf '\n'
+ if [ -n "$results" ]; then
+ __curl "$COVID19_SERVER_HOST/$COVID19_SERVER_QUERY"
+ else
+ __curl "$COVID19_SERVER_HOST/help"
+ fi
+ printf '\n'
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+COVID19_CONFIG_FILE="${COVID19_CONFIG_FILE:-settings.conf}"
+COVID19_CONFIG_DIR="${COVID19_CONFIG_DIR:-$HOME/.config/myscripts/covid19}"
+COVID19_CONFIG_BACKUP_DIR="${COVID19_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/covid19/backups}"
+COVID19_LOG_DIR="${COVID19_LOG_DIR:-$HOME/.local/log/covid19}"
+COVID19_TEMP_DIR="${COVID19_TEMP_DIR:-$HOME/.local/tmp/system_scripts/covid19}"
+COVID19_CACHE_DIR="${COVID19_CACHE_DIR:-$HOME/.cache/covid19}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+COVID19_OUTPUT_COLOR_1="${COVID19_OUTPUT_COLOR_1:-33}"
+COVID19_OUTPUT_COLOR_2="${COVID19_OUTPUT_COLOR_2:-5}"
+COVID19_OUTPUT_COLOR_GOOD="${COVID19_OUTPUT_COLOR_GOOD:-2}"
+COVID19_OUTPUT_COLOR_ERROR="${COVID19_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+COVID19_NOTIFY_ENABLED="${COVID19_NOTIFY_ENABLED:-yes}"
+COVID19_GOOD_NAME="${COVID19_GOOD_NAME:-Great:}"
+COVID19_ERROR_NAME="${COVID19_ERROR_NAME:-Error:}"
+COVID19_GOOD_MESSAGE="${COVID19_GOOD_MESSAGE:-No errors reported}"
+COVID19_ERROR_MESSAGE="${COVID19_ERROR_MESSAGE:-Errors were reported}"
+COVID19_NOTIFY_CLIENT_NAME="${COVID19_NOTIFY_CLIENT_NAME:-$APPNAME}"
+COVID19_NOTIFY_CLIENT_ICON="${COVID19_NOTIFY_CLIENT_ICON:-notification-new}"
+COVID19_NOTIFY_CLIENT_URGENCY="${COVID19_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+COVID19_SERVER_HOST="${COVID19_SERVER_HOST:-https://corona-stats.online}"
+COVID19_PING_URL="${COVID19_PING_URL:-8.8.8.8}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$COVID19_CONFIG_DIR/$COVID19_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$COVID19_CONFIG_DIR/$COVID19_CONFIG_FILE" ] && . "$COVID19_CONFIG_DIR/$COVID19_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$COVID19_LOG_DIR" ] || mkdir -p "$COVID19_LOG_DIR" |& __devnull
+[ -d "$COVID19_TEMP_DIR" ] || mkdir -p "$COVID19_TEMP_DIR" |& __devnull
+[ -d "$COVID19_CACHE_DIR" ] || mkdir -p "$COVID19_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+COVID19_TEMP_FILE="${COVID19_TEMP_FILE:-$(mktemp $COVID19_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$COVID19_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$COVID19_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$COVID19_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$COVID19_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$COVID19_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$COVID19_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,help,config,debug,options,raw,version,silent"
+LONGOPTS+=",json,country:"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ COVID19_SILENT="true"
+ ;;
+ --country)
+ COVID19_SERVER_HOST="$COVID19_SERVER_HOST/$2"
+ shift 2
+ ;;
+ --json)
+ shift 1
+ COVID19_SERVER_OPTIONS="?format=json"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# COVID19_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# COVID19_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && COVID19_CWD="$1" && shift 1 || COVID19_CWD="${COVID19_CWD:-$PWD}"
+COVID19_CWD="$(realpath "${COVID19_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$COVID19_CWD" ] && cd "$COVID19_CWD"; then
+# if [ "$COVID19_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $COVID19_CWD"
+# fi
+# else
+# printf_exit "💔 $COVID19_CWD does not exist 💔"
+# fi
+export COVID19_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__execute_covid19 "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/currency b/bin/currency
new file mode 100755
index 000000000..0154f5dfa
--- /dev/null
+++ b/bin/currency
@@ -0,0 +1,628 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208050218-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : currency --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 02:18 EDT
+# @@File : currency
+# @@Description : Get currency data
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208050218-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+CURRENCY_REQUIRE_SUDO="${CURRENCY_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$CURRENCY_CONFIG_DIR/$CURRENCY_CONFIG_FILE"
+ fi
+ [ -d "$CURRENCY_CONFIG_DIR" ] || mkdir -p "$CURRENCY_CONFIG_DIR"
+ [ -d "$CURRENCY_CONFIG_BACKUP_DIR" ] || mkdir -p "$CURRENCY_CONFIG_BACKUP_DIR"
+ [ -f "$CURRENCY_CONFIG_DIR/$CURRENCY_CONFIG_FILE" ] &&
+ cp -Rf "$CURRENCY_CONFIG_DIR/$CURRENCY_CONFIG_FILE" "$CURRENCY_CONFIG_BACKUP_DIR/$CURRENCY_CONFIG_FILE.$$"
+ cat <"$CURRENCY_CONFIG_DIR/$CURRENCY_CONFIG_FILE"
+# Settings for currency
+CURRENCY_DEFAULT="${CURRENCY_DEFAULT:-}"
+CURRENCY_API_HOST="${CURRENCY_API_HOST:-}"
+CURRENCY_API_OPTIONS="${CURRENCY_API_OPTIONS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+CURRENCY_OUTPUT_COLOR_1="${CURRENCY_OUTPUT_COLOR_1:-}"
+CURRENCY_OUTPUT_COLOR_2="${CURRENCY_OUTPUT_COLOR_2:-}"
+CURRENCY_OUTPUT_COLOR_GOOD="${CURRENCY_OUTPUT_COLOR_GOOD:-}"
+CURRENCY_OUTPUT_COLOR_ERROR="${CURRENCY_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+CURRENCY_NOTIFY_ENABLED="${CURRENCY_NOTIFY_ENABLED:-}"
+CURRENCY_GOOD_NAME="${CURRENCY_GOOD_NAME:-}"
+CURRENCY_ERROR_NAME="${CURRENCY_ERROR_NAME:-}"
+CURRENCY_GOOD_MESSAGE="${CURRENCY_GOOD_MESSAGE:-}"
+CURRENCY_ERROR_MESSAGE="${CURRENCY_ERROR_MESSAGE:-}"
+CURRENCY_NOTIFY_CLIENT_NAME="${CURRENCY_NOTIFY_CLIENT_NAME:-}"
+CURRENCY_NOTIFY_CLIENT_ICON="${CURRENCY_NOTIFY_CLIENT_ICON:-}"
+CURRENCY_NOTIFY_CLIENT_URGENCY="${CURRENCY_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$CURRENCY_CONFIG_DIR/$CURRENCY_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$CURRENCY_CONFIG_DIR/$CURRENCY_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "currency: Get currency data - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: currency [options] [commands]"
+ __printf_line "convert [from] [to] [amount] - Convert currencies"
+ __printf_line "search [query] - Search for a currency"
+ __printf_line "crypto [query] - Lookup crypto currenties"
+ __printf_line "exchange [currency] - Get the exchange rate of a currency"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$CURRENCY_REQUIRE_SUDO" = "yes" ] && [ -z "$CURRENCY_REQUIRE_SUDO_RUN" ]; then
+ export CURRENCY_REQUIRE_SUDO="no"
+ export CURRENCY_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$CURRENCY_TEMP_FILE" ] && rm -Rf "$CURRENCY_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__to_uppercase() { tr '[:lower:]' '[:upper:]'; }
+__to_lowercase() { tr '[:upper:]' '[:lower:]'; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__lookup() {
+ curl -q -LSsf --max-time 3 --retry 0 "${1:-$CURRENCY_API_HOST}" 2>/dev/null | grep -v 'ERROR:' | grep '^' && true || false
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_data() {
+ cur="$(echo "${1:-$CURRENCY_DEFAULT}" | __to_uppercase)"
+ url="$(echo "$cur.$CURRENCY_API_HOST" | __to_lowercase)"
+ results="$(__lookup "$url/${CURRENCY_API_OPTIONS:-}" || echo '')"
+ [[ -n "$results" ]] && printf_blue "Showing the data from $url" &&
+ printf '%s\n' "$results" || printf_exit "Something went wrong while accessing: $url"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__currencies() {
+ cat </dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$CURRENCY_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$CURRENCY_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$CURRENCY_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$CURRENCY_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$CURRENCY_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$CURRENCY_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="exchange crypto list convert search"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ CURRENCY_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# CURRENCY_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# CURRENCY_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && CURRENCY_CWD="$1" && shift 1 || CURRENCY_CWD="${CURRENCY_CWD:-$PWD}"
+CURRENCY_CWD="$(realpath "${CURRENCY_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$CURRENCY_CWD" ] && cd "$CURRENCY_CWD"; then
+# if [ "$CURRENCY_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $CURRENCY_CWD"
+# fi
+# else
+# printf_exit "💔 $CURRENCY_CWD does not exist 💔"
+# fi
+export CURRENCY_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+convert)
+ shift 1
+ [ "$1" = "help" ] && printf_exit "Usage: $APPNAME convert [from] [to] [amount]"
+ fromCur="$(echo "${1:-EUR}" | __to_uppercase)"
+ toCur="$(echo "${2:-$CURRENCY_DEFAULT}" | __to_uppercase)"
+ amount="$(echo "${3:-1}" | __to_uppercase)"
+ cur="$(__lookup "${toCur}.$CURRENCY_API_HOST/${amount}${fromCur}${CURRENCY_API_OPTIONS:-}" || echo '')"
+ if [ -n "$cur" ]; then
+ result="$(printf "%.2f" "$cur")"
+ printf_blue "${amount} ${fromCur} is ${result} ${toCur}"
+ else
+ printf_exit "Something went wrong"
+ fi
+ exit $?
+ ;;
+
+search)
+ shift 1
+ [ "$1" = "help" ] && printf_exit "Usage: $APPNAME search [query]"
+ [ -n "$1" ] && query="$(echo "$1" | __to_uppercase)"
+ result="$(__currencies | grep -i "${query:-^}")"
+ [ -n "$result" ] && printf_cyan "Found the following currencies" &&
+ printf '%s\n' "$result" | printf_readline $CURRENCY_OUTPUT_COLOR ||
+ printf_exit "No search results"
+ exit $?
+ ;;
+
+list)
+ shift 1
+ [ "$1" = "help" ] && printf_exit "Usage: $APPNAME list"
+ __currencies | printf_readline
+ exit $?
+ ;;
+
+crypto)
+ shift 1
+ [ "$1" = "help" ] && printf_exit "Usage: $APPNAME crypto [query]"
+ result="$(__lookup "$CURRENCY_API_HOST/:coins${CURRENCY_API_OPTIONS:-}")"
+ printf_blue "Below is a very long list of crypto currencies"
+ printf '%s\n' "$result" | grep -E "${1:-^}" | printf_column $CURRENCY_OUTPUT_COLOR
+ printf_cyan "Reduce the results by searching - $APPNAME crypto [searchTerm]"
+ exit $?
+ ;;
+
+exchange)
+ shift 1
+ [ "$1" = "help" ] && printf_exit "Usage: $APPNAME exchange currency"
+ __get_data "$@"
+ exit $?
+ ;;
+
+*)
+ if [ $# -eq 0 ] || [ "$1" = "" ] || [ "$1" = "help" ]; then
+ __lookup "$CURRENCY_API_HOST/:help${CURRENCY_API_OPTIONS:-}"
+ else
+ __get_data "$@"
+ fi
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/daysup b/bin/daysup
new file mode 100755
index 000000000..baad1b6fe
--- /dev/null
+++ b/bin/daysup
@@ -0,0 +1,552 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202303131056-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : daysup --help
+# @@Copyright : Copyright: (c) 2023 Jason Hempstead, Casjays Developments
+# @@Created : Monday, Mar 13, 2023 10:56 EDT
+# @@File : daysup
+# @@Description : Show the days the system has been up
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202303131056-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DAYSUP_REQUIRE_SUDO="${DAYSUP_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && DAYSUP_EXIT_STATUS=0 || DAYSUP_EXIT_STATUS=1
+ return ${DAYSUP_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && DAYSUP_EXIT_STATUS=0 || DAYSUP_EXIT_STATUS=1
+ return ${DAYSUP_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ DAYSUP_EXIT_STATUS=0
+ [ -n "$1" ] && local DAYSUP_EXIT_STATUS="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && DAYSUP_EXIT_STATUS+=$(($DAYSUP_EXIT_STATUS + 0)) || DAYSUP_EXIT_STATUS+=$(($DAYSUP_EXIT_STATUS + 1))
+ done
+ [ $DAYSUP_EXIT_STATUS -eq 0 ] || DAYSUP_EXIT_STATUS=3
+ return ${DAYSUP_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local DAYSUP_EXIT_STATUS=0
+ curl -q -LSsfI --max-time 1 --retry 0 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || DAYSUP_EXIT_STATUS=4
+ return ${DAYSUP_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DAYSUP_CONFIG_DIR/$DAYSUP_CONFIG_FILE"
+ fi
+ [ -d "$DAYSUP_CONFIG_DIR" ] || mkdir -p "$DAYSUP_CONFIG_DIR"
+ [ -d "$DAYSUP_CONFIG_BACKUP_DIR" ] || mkdir -p "$DAYSUP_CONFIG_BACKUP_DIR"
+ [ -f "$DAYSUP_CONFIG_DIR/$DAYSUP_CONFIG_FILE" ] &&
+ cp -Rf "$DAYSUP_CONFIG_DIR/$DAYSUP_CONFIG_FILE" "$DAYSUP_CONFIG_BACKUP_DIR/$DAYSUP_CONFIG_FILE.$$"
+ cat <"$DAYSUP_CONFIG_DIR/$DAYSUP_CONFIG_FILE"
+# Settings for daysup
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DAYSUP_OUTPUT_COLOR_1="${DAYSUP_OUTPUT_COLOR_1:-}"
+DAYSUP_OUTPUT_COLOR_2="${DAYSUP_OUTPUT_COLOR_2:-}"
+DAYSUP_OUTPUT_COLOR_GOOD="${DAYSUP_OUTPUT_COLOR_GOOD:-}"
+DAYSUP_OUTPUT_COLOR_ERROR="${DAYSUP_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DAYSUP_NOTIFY_ENABLED="${DAYSUP_NOTIFY_ENABLED:-}"
+DAYSUP_GOOD_NAME="${DAYSUP_GOOD_NAME:-}"
+DAYSUP_ERROR_NAME="${DAYSUP_ERROR_NAME:-}"
+DAYSUP_GOOD_MESSAGE="${DAYSUP_GOOD_MESSAGE:-}"
+DAYSUP_ERROR_MESSAGE="${DAYSUP_ERROR_MESSAGE:-}"
+DAYSUP_NOTIFY_CLIENT_NAME="${DAYSUP_NOTIFY_CLIENT_NAME:-}"
+DAYSUP_NOTIFY_CLIENT_ICON="${DAYSUP_NOTIFY_CLIENT_ICON:-}"
+DAYSUP_NOTIFY_CLIENT_URGENCY="${DAYSUP_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DAYSUP_CONFIG_DIR/$DAYSUP_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DAYSUP_CONFIG_DIR/$DAYSUP_CONFIG_FILE"
+ DAYSUP_EXIT_STATUS=0
+ else
+ printf_red "Failed to create the config file"
+ DAYSUP_EXIT_STATUS=1
+ fi
+ return ${DAYSUP_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "daysup: Show the days the system has been up - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: daysup [options] [commands]"
+ __printf_line "time - Show uptime"
+ __printf_line "simple - Show only the uptime"
+ __printf_line "since - Show only the uptime"
+ __printf_line "* - Show system uptime message"
+ __printf_line "--dir - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__grep() { grep "$@" 2>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DAYSUP_REQUIRE_SUDO" = "yes" ] && [ -z "$DAYSUP_REQUIRE_SUDO_RUN" ]; then
+ export DAYSUP_REQUIRE_SUDO="no"
+ export DAYSUP_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ DAYSUP_EXIT_STATUS=$?
+ else
+ printf '%s\n' "This requires root to run"
+ DAYSUP_EXIT_STATUS=1
+ fi
+ return ${DAYSUP_EXIT_STATUS:-0}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ DAYSUP_EXIT_STATUS=${DAYSUP_EXIT_STATUS:-0}
+ [ -f "$DAYSUP_TEMP_FILE" ] && rm -Rf "$DAYSUP_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $DAYSUP_EXIT_STATUS
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__uptime() { __cmd_exists uptime && uptime "$@" || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DAYSUP_EXIT_STATUS=0
+DAYSUP_CONFIG_FILE="${DAYSUP_CONFIG_FILE:-settings.conf}"
+DAYSUP_CONFIG_DIR="${DAYSUP_CONFIG_DIR:-$HOME/.config/myscripts/daysup}"
+DAYSUP_CONFIG_BACKUP_DIR="${DAYSUP_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/daysup/backups}"
+DAYSUP_LOG_DIR="${DAYSUP_LOG_DIR:-$HOME/.local/log/daysup}"
+DAYSUP_RUN_DIR="${DAYSUP_RUN_DIR:-$HOME/.local/run/system_scripts/$DAYSUP_SCRIPTS_PREFIX}"
+DAYSUP_TEMP_DIR="${DAYSUP_TEMP_DIR:-$HOME/.local/tmp/system_scripts/daysup}"
+DAYSUP_CACHE_DIR="${DAYSUP_CACHE_DIR:-$HOME/.cache/daysup}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DAYSUP_OUTPUT_COLOR_1="${DAYSUP_OUTPUT_COLOR_1:-33}"
+DAYSUP_OUTPUT_COLOR_2="${DAYSUP_OUTPUT_COLOR_2:-5}"
+DAYSUP_OUTPUT_COLOR_GOOD="${DAYSUP_OUTPUT_COLOR_GOOD:-2}"
+DAYSUP_OUTPUT_COLOR_ERROR="${DAYSUP_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DAYSUP_NOTIFY_ENABLED="${DAYSUP_NOTIFY_ENABLED:-yes}"
+DAYSUP_GOOD_NAME="${DAYSUP_GOOD_NAME:-Great:}"
+DAYSUP_ERROR_NAME="${DAYSUP_ERROR_NAME:-Error:}"
+DAYSUP_GOOD_MESSAGE="${DAYSUP_GOOD_MESSAGE:-No errors reported}"
+DAYSUP_ERROR_MESSAGE="${DAYSUP_ERROR_MESSAGE:-Errors were reported}"
+DAYSUP_NOTIFY_CLIENT_NAME="${DAYSUP_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DAYSUP_NOTIFY_CLIENT_ICON="${DAYSUP_NOTIFY_CLIENT_ICON:-notification-new}"
+DAYSUP_NOTIFY_CLIENT_URGENCY="${DAYSUP_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DAYSUP_CONFIG_DIR/$DAYSUP_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DAYSUP_CONFIG_DIR/$DAYSUP_CONFIG_FILE" ] && . "$DAYSUP_CONFIG_DIR/$DAYSUP_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DAYSUP_RUN_DIR" ] || mkdir -p "$DAYSUP_RUN_DIR" |& __devnull
+[ -d "$DAYSUP_LOG_DIR" ] || mkdir -p "$DAYSUP_LOG_DIR" |& __devnull
+[ -d "$DAYSUP_TEMP_DIR" ] || mkdir -p "$DAYSUP_TEMP_DIR" |& __devnull
+[ -d "$DAYSUP_CACHE_DIR" ] || mkdir -p "$DAYSUP_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DAYSUP_TEMP_FILE="${DAYSUP_TEMP_FILE:-$(mktemp $DAYSUP_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DAYSUP_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DAYSUP_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DAYSUP_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DAYSUP_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DAYSUP_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DAYSUP_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="full time since simple"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DAYSUP_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ DAYSUP_CWD="$2"
+ # [ -d "$DAYSUP_CWD" ] || mkdir -p "$DAYSUP_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DAYSUP_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DAYSUP_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DAYSUP_CWD="$1" && shift 1 || DAYSUP_CWD="${DAYSUP_CWD:-$PWD}"
+DAYSUP_CWD="$(realpath "${DAYSUP_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DAYSUP_CWD" ] && cd "$DAYSUP_CWD"; then
+# if [ "$DAYSUP_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DAYSUP_CWD"
+# fi
+# else
+# printf_exit "💔 $DAYSUP_CWD does not exist 💔"
+# fi
+export DAYSUP_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+DAYSUP_FULL="$(__uptime || echo 'Unknown')"
+DAYSUP_SINCE="$(__uptime -s | grep '^' || echo 'Unknown')"
+DAYSUP_SIMPLE="$(__uptime | sed 's|.* up ||g;s|,.*||g' | grep '^' || echo 'Unknown')"
+DAYSUP_TIME="$(__uptime -p | sed 's|.*up ||g;s| .*||g' | grep '^' || echo 'Unknown')"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Export variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+full)
+ shift 1
+ printf_cyan "$DAYSUP_FULL"
+ ;;
+time)
+ shift 1
+ printf_cyan "$DAYSUP_TIME"
+ ;;
+since)
+ shift 1
+ printf_cyan "This system has been up since: $DAYSUP_SINCE"
+ ;;
+simple)
+ shift 1
+ printf_cyan "$DAYSUP_SIMPLE"
+ ;;
+*)
+ printf_cyan "This system has been up for: $DAYSUP_TIME"
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+DAYSUP_EXIT_STATUS="${DAYSUP_EXIT_STATUS:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${DAYSUP_EXIT_STATUS:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/decrypt b/bin/decrypt
new file mode 100755
index 000000000..73c241f29
--- /dev/null
+++ b/bin/decrypt
@@ -0,0 +1,529 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208051039-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : decrypt --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 10:39 EDT
+# @@File : decrypt
+# @@Description : perl oneliner to decrypt files
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208051039-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DECRYPT_REQUIRE_SUDO="${DECRYPT_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DECRYPT_CONFIG_DIR/$DECRYPT_CONFIG_FILE"
+ fi
+ [ -d "$DECRYPT_CONFIG_DIR" ] || mkdir -p "$DECRYPT_CONFIG_DIR"
+ [ -d "$DECRYPT_CONFIG_BACKUP_DIR" ] || mkdir -p "$DECRYPT_CONFIG_BACKUP_DIR"
+ [ -f "$DECRYPT_CONFIG_DIR/$DECRYPT_CONFIG_FILE" ] &&
+ cp -Rf "$DECRYPT_CONFIG_DIR/$DECRYPT_CONFIG_FILE" "$DECRYPT_CONFIG_BACKUP_DIR/$DECRYPT_CONFIG_FILE.$$"
+ cat <"$DECRYPT_CONFIG_DIR/$DECRYPT_CONFIG_FILE"
+# Settings for decrypt
+DECRYPT_PASSWORD="${DECRYPT_PASSWORD:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DECRYPT_OUTPUT_COLOR_1="${DECRYPT_OUTPUT_COLOR_1:-}"
+DECRYPT_OUTPUT_COLOR_2="${DECRYPT_OUTPUT_COLOR_2:-}"
+DECRYPT_OUTPUT_COLOR_GOOD="${DECRYPT_OUTPUT_COLOR_GOOD:-}"
+DECRYPT_OUTPUT_COLOR_ERROR="${DECRYPT_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DECRYPT_NOTIFY_ENABLED="${DECRYPT_NOTIFY_ENABLED:-}"
+DECRYPT_GOOD_NAME="${DECRYPT_GOOD_NAME:-}"
+DECRYPT_ERROR_NAME="${DECRYPT_ERROR_NAME:-}"
+DECRYPT_GOOD_MESSAGE="${DECRYPT_GOOD_MESSAGE:-}"
+DECRYPT_ERROR_MESSAGE="${DECRYPT_ERROR_MESSAGE:-}"
+DECRYPT_NOTIFY_CLIENT_NAME="${DECRYPT_NOTIFY_CLIENT_NAME:-}"
+DECRYPT_NOTIFY_CLIENT_ICON="${DECRYPT_NOTIFY_CLIENT_ICON:-}"
+DECRYPT_NOTIFY_CLIENT_URGENCY="${DECRYPT_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DECRYPT_CONFIG_DIR/$DECRYPT_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DECRYPT_CONFIG_DIR/$DECRYPT_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "decrypt: perl oneliner to decrypt files - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: decrypt [options] [commands]"
+ __printf_line "/path/to/file - Decrypt file"
+ __printf_line "echo 'some text'|decrypt - Decrypt text"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DECRYPT_REQUIRE_SUDO" = "yes" ] && [ -z "$DECRYPT_REQUIRE_SUDO_RUN" ]; then
+ export DECRYPT_REQUIRE_SUDO="no"
+ export DECRYPT_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DECRYPT_TEMP_FILE" ] && rm -Rf "$DECRYPT_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DECRYPT_CONFIG_FILE="${DECRYPT_CONFIG_FILE:-settings.conf}"
+DECRYPT_CONFIG_DIR="${DECRYPT_CONFIG_DIR:-$HOME/.config/myscripts/decrypt}"
+DECRYPT_CONFIG_BACKUP_DIR="${DECRYPT_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/decrypt/backups}"
+DECRYPT_LOG_DIR="${DECRYPT_LOG_DIR:-$HOME/.local/log/decrypt}"
+DECRYPT_TEMP_DIR="${DECRYPT_TEMP_DIR:-$HOME/.local/tmp/system_scripts/decrypt}"
+DECRYPT_CACHE_DIR="${DECRYPT_CACHE_DIR:-$HOME/.cache/decrypt}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DECRYPT_OUTPUT_COLOR_1="${DECRYPT_OUTPUT_COLOR_1:-33}"
+DECRYPT_OUTPUT_COLOR_2="${DECRYPT_OUTPUT_COLOR_2:-5}"
+DECRYPT_OUTPUT_COLOR_GOOD="${DECRYPT_OUTPUT_COLOR_GOOD:-2}"
+DECRYPT_OUTPUT_COLOR_ERROR="${DECRYPT_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DECRYPT_NOTIFY_ENABLED="${DECRYPT_NOTIFY_ENABLED:-yes}"
+DECRYPT_GOOD_NAME="${DECRYPT_GOOD_NAME:-Great:}"
+DECRYPT_ERROR_NAME="${DECRYPT_ERROR_NAME:-Error:}"
+DECRYPT_GOOD_MESSAGE="${DECRYPT_GOOD_MESSAGE:-No errors reported}"
+DECRYPT_ERROR_MESSAGE="${DECRYPT_ERROR_MESSAGE:-Errors were reported}"
+DECRYPT_NOTIFY_CLIENT_NAME="${DECRYPT_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DECRYPT_NOTIFY_CLIENT_ICON="${DECRYPT_NOTIFY_CLIENT_ICON:-notification-new}"
+DECRYPT_NOTIFY_CLIENT_URGENCY="${DECRYPT_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+DECRYPT_PASSWORD="${DECRYPT_PASSWORD:-verylongsecurepassword}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DECRYPT_CONFIG_DIR/$DECRYPT_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DECRYPT_CONFIG_DIR/$DECRYPT_CONFIG_FILE" ] && . "$DECRYPT_CONFIG_DIR/$DECRYPT_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DECRYPT_LOG_DIR" ] || mkdir -p "$DECRYPT_LOG_DIR" |& __devnull
+[ -d "$DECRYPT_TEMP_DIR" ] || mkdir -p "$DECRYPT_TEMP_DIR" |& __devnull
+[ -d "$DECRYPT_CACHE_DIR" ] || mkdir -p "$DECRYPT_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DECRYPT_TEMP_FILE="${DECRYPT_TEMP_FILE:-$(mktemp $DECRYPT_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DECRYPT_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DECRYPT_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DECRYPT_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DECRYPT_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DECRYPT_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DECRYPT_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DECRYPT_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DECRYPT_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DECRYPT_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DECRYPT_CWD="$1" && shift 1 || DECRYPT_CWD="${DECRYPT_CWD:-$PWD}"
+DECRYPT_CWD="$(realpath "${DECRYPT_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DECRYPT_CWD" ] && cd "$DECRYPT_CWD"; then
+# if [ "$DECRYPT_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DECRYPT_CWD"
+# fi
+# else
+# printf_exit "💔 $DECRYPT_CWD does not exist 💔"
+# fi
+export DECRYPT_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -f "$DECRYPT_CONFIG_DIR/.password" ] && DECRYPT_PASSWORD="$(<"$DECRYPT_CONFIG_DIR/.password")"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+if [ -t 0 ]; then
+ fname="$1"
+ shift $#
+ if echo "$DECRYPT_PASSWORD" | openssl aes-256-cbc -pbkdf2 -d -in "$fname" -out "${fname%\.*}" "$@" -pass stdin 2>/dev/null; then
+ printf_green "Successfully decrypted $1"
+ printf_cyan "Using the password from config"
+ else
+ printf_return "Something went wrong: check your password"
+ fi
+else
+ perl -e 'use IO::Select; $ready=IO::Select->new(STDIN)->can_read();'
+ if echo "$DECRYPT_PASSWORD" | openssl aes-256-cbc -pbkdf2 -d "$@" -pass stdin 2>/dev/null; then
+ printf_green "Successfully decrypted $1"
+ printf_cyan "Using the password from config"
+ else
+ printf_return "Something went wrong: check your password"
+ fi
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/define b/bin/define
new file mode 100755
index 000000000..db55e1c59
--- /dev/null
+++ b/bin/define
@@ -0,0 +1,557 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208051042-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : define --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 10:42 EDT
+# @@File : define
+# @@Description : Script to lookup definition of words using dict
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208051042-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DEFINE_REQUIRE_SUDO="${DEFINE_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DEFINE_CONFIG_DIR/$DEFINE_CONFIG_FILE"
+ fi
+ [ -d "$DEFINE_CONFIG_DIR" ] || mkdir -p "$DEFINE_CONFIG_DIR"
+ [ -d "$DEFINE_CONFIG_BACKUP_DIR" ] || mkdir -p "$DEFINE_CONFIG_BACKUP_DIR"
+ [ -f "$DEFINE_CONFIG_DIR/$DEFINE_CONFIG_FILE" ] &&
+ cp -Rf "$DEFINE_CONFIG_DIR/$DEFINE_CONFIG_FILE" "$DEFINE_CONFIG_BACKUP_DIR/$DEFINE_CONFIG_FILE.$$"
+ cat <"$DEFINE_CONFIG_DIR/$DEFINE_CONFIG_FILE"
+# Settings for define
+DEFINE_YAD_WIDTH="${DEFINE_YAD_WIDTH:-}"
+DEFINE_YAD_HEIGHT="${DEFINE_YAD_HEIGHT:-}"
+DEFINE_SERVER_HOST="${DEFINE_SERVER_HOST:-}"
+DEFINE_SERVER_PORT="${DEFINE_SERVER_PORT:-}"
+DEFINE_PING_URL="${DEFINE_PING_URL:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DEFINE_OUTPUT_COLOR_1="${DEFINE_OUTPUT_COLOR_1:-}"
+DEFINE_OUTPUT_COLOR_2="${DEFINE_OUTPUT_COLOR_2:-}"
+DEFINE_OUTPUT_COLOR_GOOD="${DEFINE_OUTPUT_COLOR_GOOD:-}"
+DEFINE_OUTPUT_COLOR_ERROR="${DEFINE_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DEFINE_NOTIFY_ENABLED="${DEFINE_NOTIFY_ENABLED:-}"
+DEFINE_GOOD_NAME="${DEFINE_GOOD_NAME:-}"
+DEFINE_ERROR_NAME="${DEFINE_ERROR_NAME:-}"
+DEFINE_GOOD_MESSAGE="${DEFINE_GOOD_MESSAGE:-}"
+DEFINE_ERROR_MESSAGE="${DEFINE_ERROR_MESSAGE:-}"
+DEFINE_NOTIFY_CLIENT_NAME="${DEFINE_NOTIFY_CLIENT_NAME:-}"
+DEFINE_NOTIFY_CLIENT_ICON="${DEFINE_NOTIFY_CLIENT_ICON:-}"
+DEFINE_NOTIFY_CLIENT_URGENCY="${DEFINE_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DEFINE_CONFIG_DIR/$DEFINE_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DEFINE_CONFIG_DIR/$DEFINE_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "define: Script to lookup definition of words using dict - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: define [options] [word]"
+ __printf_line "google - Get definition of the word google"
+ __printf_line "--gtk - Opens a prompt"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DEFINE_REQUIRE_SUDO" = "yes" ] && [ -z "$DEFINE_REQUIRE_SUDO_RUN" ]; then
+ export DEFINE_REQUIRE_SUDO="no"
+ export DEFINE_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DEFINE_TEMP_FILE" ] && rm -Rf "$DEFINE_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__lookup() {
+ dict -h ${DEFINE_SERVER_HOST} -p ${DEFINE_SERVER_PORT} -d gcide "$1" 2>/dev/null |
+ grep -v 'No definitions found' | sed '/^$/d' | sed 's#From The Collaborative International.*##g'
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__yad__text() {
+ set -o pipefail
+ local title="$1"
+ local color="${2:-$DEFINE_OUTPUT_COLOR_1}"
+ local DEFINE_YAD_WIDTH="${DEFINE_YAD_WIDTH:-900}"
+ local DEFINE_YAD_HEIGHT="${DEFINE_YAD_HEIGHT:-600}"
+ if __cmd_exists yad && [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ]; then
+ cat - | yad --text-info --wrap --center --title="$title" --width=${DEFINE_YAD_WIDTH:-500} --height=${DEFINE_YAD_HEIGHT:-400} 2>/dev/null &
+ return $?
+ elif __cmd_exists zenity && [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ]; then
+ cat - | zenity --text-info --title="$title" --width=${DEFINE_YAD_WIDTH:-500} --height=${DEFINE_YAD_HEIGHT:-400} 2>/dev/null &
+ return $?
+ else
+ cat - | printf_readline "$color"
+ return $?
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DEFINE_CONFIG_FILE="${DEFINE_CONFIG_FILE:-settings.conf}"
+DEFINE_CONFIG_DIR="${DEFINE_CONFIG_DIR:-$HOME/.config/myscripts/define}"
+DEFINE_CONFIG_BACKUP_DIR="${DEFINE_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/define/backups}"
+DEFINE_LOG_DIR="${DEFINE_LOG_DIR:-$HOME/.local/log/define}"
+DEFINE_TEMP_DIR="${DEFINE_TEMP_DIR:-$HOME/.local/tmp/system_scripts/define}"
+DEFINE_CACHE_DIR="${DEFINE_CACHE_DIR:-$HOME/.cache/define}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DEFINE_OUTPUT_COLOR_1="${DEFINE_OUTPUT_COLOR_1:-33}"
+DEFINE_OUTPUT_COLOR_2="${DEFINE_OUTPUT_COLOR_2:-5}"
+DEFINE_OUTPUT_COLOR_GOOD="${DEFINE_OUTPUT_COLOR_GOOD:-2}"
+DEFINE_OUTPUT_COLOR_ERROR="${DEFINE_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DEFINE_NOTIFY_ENABLED="${DEFINE_NOTIFY_ENABLED:-yes}"
+DEFINE_GOOD_NAME="${DEFINE_GOOD_NAME:-Great:}"
+DEFINE_ERROR_NAME="${DEFINE_ERROR_NAME:-Error:}"
+DEFINE_GOOD_MESSAGE="${DEFINE_GOOD_MESSAGE:-No errors reported}"
+DEFINE_ERROR_MESSAGE="${DEFINE_ERROR_MESSAGE:-Errors were reported}"
+DEFINE_NOTIFY_CLIENT_NAME="${DEFINE_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DEFINE_NOTIFY_CLIENT_ICON="${DEFINE_NOTIFY_CLIENT_ICON:-notification-new}"
+DEFINE_NOTIFY_CLIENT_URGENCY="${DEFINE_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+DEFINE_SERVER_HOST="${DEFINE_SERVER_HOST:-dict.org}"
+DEFINE_SERVER_PORT="${DEFINE_SERVER_PORT:-2628}"
+DEFINE_PING_URL="${DEFINE_PING_URL:-8.8.8.8}"
+DEFINE_YAD_WIDTH="${DEFINE_YAD_WIDTH:-900}"
+DEFINE_YAD_HEIGHT="${DEFINE_YAD_HEIGHT:-600}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DEFINE_CONFIG_DIR/$DEFINE_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DEFINE_CONFIG_DIR/$DEFINE_CONFIG_FILE" ] && . "$DEFINE_CONFIG_DIR/$DEFINE_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DEFINE_LOG_DIR" ] || mkdir -p "$DEFINE_LOG_DIR" |& __devnull
+[ -d "$DEFINE_TEMP_DIR" ] || mkdir -p "$DEFINE_TEMP_DIR" |& __devnull
+[ -d "$DEFINE_CACHE_DIR" ] || mkdir -p "$DEFINE_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DEFINE_TEMP_FILE="${DEFINE_TEMP_FILE:-$(mktemp $DEFINE_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DEFINE_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DEFINE_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DEFINE_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DEFINE_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DEFINE_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DEFINE_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=",gtk"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DEFINE_SILENT="true"
+ ;;
+ --gtk)
+ search="$(INPUT_NAME="$APPNAME" ask_for_input)"
+ shift 1
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DEFINE_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DEFINE_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DEFINE_CWD="$1" && shift 1 || DEFINE_CWD="${DEFINE_CWD:-$PWD}"
+DEFINE_CWD="$(realpath "${DEFINE_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DEFINE_CWD" ] && cd "$DEFINE_CWD"; then
+# if [ "$DEFINE_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DEFINE_CWD"
+# fi
+# else
+# printf_exit "💔 $DEFINE_CWD does not exist 💔"
+# fi
+export DEFINE_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ "$CONSOLE_APP" = "true" ] && __yad__text() { tee | printf_readline "$DEFINE_OUTPUT_COLOR_2"; }
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+[ $# -eq 0 ] && search="${search:-$(INPUT_NAME="$APPNAME" ask_for_input "Define:")}" || search="$*"
+if [ -z "$search" ]; then
+ __notifications "Usage: $APPNAME [query]"
+ exit 1
+fi
+results="$(__lookup "${search:-$*}")"
+if [ -n "$results" ]; then
+ echo "$results" | __yad__text "$1" || echo "$results" | printf_readline "$DEFINE_OUTPUT_COLOR_2"
+else
+ printf_red "Nothing was found for $1"
+ __notifications "Nothing was found for $1"
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/desktopmgr b/bin/desktopmgr
new file mode 100755
index 000000000..23fa98691
--- /dev/null
+++ b/bin/desktopmgr
@@ -0,0 +1,937 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208231021-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : desktopmgr --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Tuesday, Aug 23, 2022 10:21 EDT
+# @@File : desktopmgr
+# @@Description : Desktop ManaGeR
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : installers/mgr-script.system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208231021-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DESKTOPMGR_REQUIRE_SUDO="${DESKTOPMGR_REQUIRE_SUDO:-no}"
+DESKTOPMGR_SCRIPTS_PREFIX="${APPNAME:-desktopmgr}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-managers.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/$DESKTOPMGR_SCRIPTS_PREFIX/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 90
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+desktopmgr_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_color "$1\n" "5"; }
+__printf_opts() { printf_color "$1\n" "6"; }
+__printf_line() { printf_color "$1\n" "4"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list all packages
+__list_available() {
+ echo -e "${1:-$LIST}" | tr ',' ' ' | tr ' ' '\n' && exit 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_custom "5" "$1: $(echo ${2:-$ARRAY} | __sed 's|:||g;s|'$3'| '$4'|g' 2>/dev/null | tr '\n' ' ')"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME=""
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Generating the config file in"
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "$DESKTOPMGR_CONFIG_DIR/$DESKTOPMGR_CONFIG_FILE"
+ [ -d "$DESKTOPMGR_CONFIG_DIR" ] || mkdir -p "$DESKTOPMGR_CONFIG_DIR"
+ [ -d "$DESKTOPMGR_CONFIG_BACKUP_DIR" ] || mkdir -p "$DESKTOPMGR_CONFIG_BACKUP_DIR"
+ [ -f "$DESKTOPMGR_CONFIG_DIR/$DESKTOPMGR_CONFIG_FILE" ] &&
+ cp -Rf "$DESKTOPMGR_CONFIG_DIR/$DESKTOPMGR_CONFIG_FILE" "$DESKTOPMGR_CONFIG_BACKUP_DIR/$DESKTOPMGR_CONFIG_FILE.$$"
+ cat <"$DESKTOPMGR_CONFIG_DIR/$DESKTOPMGR_CONFIG_FILE"
+# Settings for desktopmgr
+DESKTOPMGR_GIT_REPO_BRANCH="${DESKTOPMGR_GIT_REPO_BRANCH:-}"
+DESKTOPMGR_APP_DIR="${DESKTOPMGR_APP_DIR:-}"
+DESKTOPMGR_INSTALL_DIR="${DESKTOPMGR_INSTALL_DIR:-}"
+DESKTOPMGR_CLONE_DIR="${DESKTOPMGR_CLONE_DIR:-}"
+DESKTOPMGR_REPO_URL="${DESKTOPMGR_REPO_URL:-}"
+DESKTOPMGR_REPO_RAW="${DESKTOPMGR_REPO_RAW:-}"
+DESKTOPMGR_REPO_API_URL="${DESKTOPMGR_REPO_API_URL:-}"
+DESKTOPMGR_REPO_API_PER_PAGE="${DESKTOPMGR_REPO_API_PER_PAGE:-}"
+DESKTOPMGR_FORCE_INSTALL="${DESKTOPMGR_FORCE_INSTALL:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DESKTOPMGR_OUTPUT_COLOR_1="${DESKTOPMGR_OUTPUT_COLOR_1:-}"
+DESKTOPMGR_OUTPUT_COLOR_2="${DESKTOPMGR_OUTPUT_COLOR_2:-}"
+DESKTOPMGR_OUTPUT_COLOR_GOOD="${DESKTOPMGR_OUTPUT_COLOR_GOOD:-}"
+DESKTOPMGR_OUTPUT_COLOR_ERROR="${DESKTOPMGR_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DESKTOPMGR_NOTIFY_ENABLED="${DESKTOPMGR_NOTIFY_ENABLED:-}"
+DESKTOPMGR_GOOD_NAME="${DESKTOPMGR_GOOD_NAME:-}"
+DESKTOPMGR_ERROR_NAME="${DESKTOPMGR_ERROR_NAME:-}"
+DESKTOPMGR_GOOD_MESSAGE="${DESKTOPMGR_GOOD_MESSAGE:-}"
+DESKTOPMGR_ERROR_MESSAGE="${DESKTOPMGR_ERROR_MESSAGE:-}"
+DESKTOPMGR_NOTIFY_CLIENT_NAME="${DESKTOPMGR_NOTIFY_CLIENT_NAME:-}"
+DESKTOPMGR_NOTIFY_CLIENT_ICON="${DESKTOPMGR_NOTIFY_CLIENT_ICON:-}"
+DESKTOPMGR_NOTIFY_CLIENT_URGENCY="${DESKTOPMGR_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DESKTOPMGR_CONFIG_DIR/$DESKTOPMGR_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=11
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "desktopmgr: Desktop ManaGeR - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: $DESKTOPMGR_SCRIPTS_PREFIX [options] [packageName]"
+ __printf_line "available - List all available packages"
+ __printf_line "list - List installed packages"
+ __printf_line "search [package] - Search for a package"
+ __printf_line "install [package] - Install a package"
+ __printf_line "update [package] - Update a package"
+ __printf_line "download [package] - Downloads the source"
+ __printf_line "remove [package] - Remove a package"
+ __printf_line "cron [package] - Enables the use of cron to update packages on a schedule"
+ __printf_line "version [package] - Shows the version of an installed package"
+ __printf_line "qemu [linux,windows,macos,arm] - launch a vm"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--debug - enable debugging"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--help - Shows this message"
+ __printf_line "--options - Shows all available options"
+ __printf_line ""
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__broken_symlinks() { find "$*" -xtype l -exec rm {} \; &>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__rm_rf() { if [ -e "$1" ]; then rm -Rf "$@" &>/dev/null; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_install_version() {
+ local upd file exitCode=0
+ if [ -d "$DESKTOPMGR_DIR_SYSTEM" ] && ls -A "$DESKTOPMGR_DIR_SYSTEM" 2>&1 | grep -q '^'; then
+ file="$(ls -A "$DESKTOPMGR_DIR_SYSTEM/$1" 2>/dev/null)"
+ export file
+ if [ -f "$file" ]; then
+ appname="$(__basename "$file")"
+ eval "$file" "--version $appname"
+ exitCode=$?
+ fi
+ fi
+ [ "$exitCode" = 0 ] && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__cron_updater() {
+ local upd file exitCode=0
+ if [ -z "$1" ] && [ -d "$DESKTOPMGR_DIR_SYSTEM" ] && ls -A "$DESKTOPMGR_DIR_SYSTEM" 2>&1 | grep -q '^'; then
+ for upd in $(ls -A "$DESKTOPMGR_DIR_SYSTEM"); do
+ file="$(ls -A "$DESKTOPMGR_DIR_SYSTEM/$upd" 2>/dev/null)"
+ export file
+ if [ -f "$file" ]; then
+ appname="$(__basename "$file")"
+ eval "$file" "--cron $appname"
+ exitCode=$(($exitCode + $?))
+ fi
+ done
+ else
+ if [ -d "$DESKTOPMGR_DIR_SYSTEM" ] && ls -A "$DESKTOPMGR_DIR_SYSTEM" 2>&1 | grep -q '^'; then
+ file="$(ls -A "$DESKTOPMGR_DIR_SYSTEM/$1" 2>/dev/null)"
+ export file
+ if [ -f "$file" ]; then
+ appname="$(__basename "$file")"
+ bash -c "$file --cron $appname"
+ exitCode=$(($exitCode + $?))
+ fi
+ fi
+ fi
+ [ "$exitCode" = 0 ] && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__installer_delete() {
+ local app="${1:-}"
+ local exitCode=0
+ local APP_DIR_NAME="$DESKTOPMGR_APP_DIR"
+ local INSTALL_DIR_NAME="$DESKTOPMGR_INSTALL_DIR"
+ local MESSAGE="${MESSAGE:-Removing $app from ${msg:-your system}}"
+ [ -n "$app" ] || printf_exit "Please specify the name to delete"
+ [ "$INSTALL_DIR_NAME/$app" == "$INSTALL_DIR_NAME/" ] && return
+ if [ -d "$APP_DIR_NAME/$app" ] || [ -d "$INSTALL_DIR_NAME/$app" ]; then
+ printf_yellow "$MESSAGE"
+ if [ -e "$APP_DIR_NAME/$app" ]; then
+ printf_blue "Deleting the files from $APP_DIR_NAME/$app"
+ __rm_rf "$APP_DIR_NAME/$app"
+ fi
+ if [ -e "$INSTALL_DIR_NAME/$app" ]; then
+ printf_blue "Deleting the files from $APP_DIR_NAME/$app"
+ __rm_rf "$INSTALL_DIR_NAME/$app"
+ fi
+ if [ -e "$DESKTOPMGR_VERSION_DIR_USER/$app" ]; then
+ printf_blue "Deleting the files from $APP_DIR_NAME/$app"
+ __rm_rf "$DESKTOPMGR_VERSION_DIR_USER/$app"
+ fi
+ printf_yellow "Removing any broken symlinks"
+ __broken_symlinks "$BIN" "$SHARE" "$COMPDIR" "$CONF" "$THEMEDIR" "$FONTDIR" "$ICONDIR"
+ { [ -e "$DESKTOPMGR_VERSION_DIR_USER/$app" ] || [ -d "$INSTALL_DIR_NAME/$app" ] || [ -d "$APP_DIR_NAME/$app" ]; } && exitCode=1 || exitCode=0
+ [ $exitCode = 0 ] && printf_cyan "$app has been removed"
+ return $exitCode
+ else
+ printf_error "$app doesn't seem to be installed"
+ fi
+ return ${exitCode}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_install_init() {
+ local app="$1"
+ local exitCode=0
+ local INSTALL_DIR_NAME="$DESKTOPMGR_INSTALL_DIR"
+ export SUDO_USER
+ if __urlcheck "$DESKTOPMGR_REPO_URL/$app/$DESKTOPMGR_REPO_RAW/install.sh"; then
+ export FORCE_INSTALL="$FORCE_INSTALL"
+ bash -c "$(curl -q -LSsf "$DESKTOPMGR_REPO_URL/$app/$DESKTOPMGR_REPO_RAW/install.sh")" 2>/dev/null
+ exitCode=$?
+ else
+ printf_error "Failed to initialize the installer from:"
+ printf_red "$DESKTOPMGR_REPO_URL/$app/$DESKTOPMGR_REPO_RAW/install.sh\n"
+ exitCode=1
+ fi
+ [ "$exitCode" = 0 ] && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_install_update() {
+ local app APPNAME exitCode=0
+ local USER_SHARE_DIR="$SYSSHARE/CasjaysDev/$DESKTOPMGR_SCRIPTS_PREFIX"
+ local SYSTEM_SHARE_DIR="$SYSSHARE/CasjaysDev/$DESKTOPMGR_SCRIPTS_PREFIX"
+ local USRUPDATEDIR="$DESKTOPMGR_DIR_SYSTEM"
+ local SYSUPDATEDIR="$DESKTOPMGR_DIR_SYSTEM"
+ local NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME}"
+ local NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME NOTIFY_CLIENT_ICON
+ __run_install_init "$1" && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__download() {
+ local REPO_NAME="$1"
+ local DIR_NAME="${2:-$DESKTOPMGR_CLONE_DIR/$REPO_NAME}"
+ local REPO_URL="$DESKTOPMGR_REPO_URL"
+ local exitCode=0
+ [ -d "$DESKTOPMGR_CLONE_DIR" ] || mkdir -p "$DESKTOPMGR_CLONE_DIR"
+ if __cmd_exists gitadmin; then
+ if [ -d "$DIR_NAME/.git" ]; then
+ gitadmin pull "$DIR_NAME"
+ exitCode=$?
+ else
+ gitadmin clone "$REPO_URL/$REPO_NAME" "$DIR_NAME"
+ exitCode=$?
+ fi
+ else
+ if [ -d "$DIR_NAME/.git" ]; then
+ git -C "$DIR_NAME" pull
+ exitCode=$?
+ else
+ git clone "$REPO_URL/$REPO_NAME" "$DIR_NAME"
+ exitCode=$?
+ fi
+ fi
+ if [ -d "$DIR_NAME/.git" ]; then
+ exitCode=0
+ fi
+ [ "$exitCode" = 0 ] && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_list() {
+ local exitCode=0
+ local api_call=""
+ local prefix="$DESKTOPMGR_SCRIPTS_PREFIX"
+ local per_page="${DESKTOPMGR_REPO_API_PER_PAGE:-1000}"
+ local api_url="${DESKTOPMGR_REPO_API_URL:-https://api.github.com/orgs/$prefix/repos}"
+ if __urlcheck "$api_url"; then
+ api_call="$(curl -q -LSsf -H "Accept: application/vnd.github.v3+json" "$api_url?per_page=$per_page" 2>/dev/null | jq '.[].name' 2>/dev/null | sed 's#"##g' | grep -Ev '.github|template|^null$' | grep '^')"
+ if [ -n "$api_call" ]; then
+ printf '%s\n' "$api_call"
+ else
+ __list_available "$LIST"
+ fi
+ exitCode=$?
+ else
+ __list_available "$LIST"
+ exitCode=$?
+ fi
+ [ "$exitCode" = 0 ] && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_search() {
+ local -a results=""
+ local LIST="${LIST:-$(__api_list)}"
+ [ -n "$LIST" ] || printf_exit "The environment variable LIST does not exist"
+ for app in "$@"; do
+ result+="$(echo -e "$LIST" | tr ' ' '\n' | grep -Fi "$app" | grep -shv '^$') "
+ done
+ results="$(echo "$result" | sort -u | tr '\n' ' ' | sed 's| | |g' | grep '^')"
+ if [ -n "$results" ]; then
+ printf '%s\n' "$results" | printf_column "${PRINTF_COLOR:-4}"
+ exitCode=0
+ else
+ printf_exit "Your search produced no results"
+ exitCode=1
+ fi
+ [ "$exitCode" = 0 ] && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+__requiresudo() {
+ if [ "$DESKTOPMGR_REQUIRE_SUDO" = "yes" ] && [ -z "$DESKTOPMGR_REQUIRE_SUDO_RUN" ]; then
+ export DESKTOPMGR_REQUIRE_SUDO="no"
+ export DESKTOPMGR_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DESKTOPMGR_TEMP_FILE" ] && rm -Rf "$DESKTOPMGR_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Default variables
+DESKTOPMGR_USER_DIR="${DESKTOPMGR_USER_DIR:-$USRUPDATEDIR}"
+DESKTOPMGR_SYSTEM_DIR="${DESKTOPMGR_SYSTEM_DIR:-$SYSUPDATEDIR}"
+DESKTOPMGR_INSTALL_DIR="${DESKTOPMGR_INSTALL_DIR:-$SHARE/CasjaysDev/$DESKTOPMGR_SCRIPTS_PREFIX}"
+# Application Folders
+DESKTOPMGR_LOG_DIR="${DESKTOPMGR_LOG_DIR:-$HOME/.local/log/$DESKTOPMGR_SCRIPTS_PREFIX}"
+DESKTOPMGR_CACHE_DIR="${DESKTOPMGR_CACHE_DIR:-$HOME/.cache/$DESKTOPMGR_SCRIPTS_PREFIX}"
+DESKTOPMGR_CONFIG_DIR="${DESKTOPMGR_CONFIG_DIR:-$HOME/.config/myscripts/$DESKTOPMGR_SCRIPTS_PREFIX}"
+DESKTOPMGR_CONFIG_BACKUP_DIR="${DESKTOPMGR_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/$DESKTOPMGR_SCRIPTS_PREFIX/backups}"
+DESKTOPMGR_TEMP_DIR="${DESKTOPMGR_TEMP_DIR:-$HOME/.local/tmp/system_scripts/$DESKTOPMGR_SCRIPTS_PREFIX}"
+DESKTOPMGR_CONFIG_FILE="${DESKTOPMGR_CONFIG_FILE:-settings.conf}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DESKTOPMGR_OUTPUT_COLOR_1="${DESKTOPMGR_OUTPUT_COLOR_1:-33}"
+DESKTOPMGR_OUTPUT_COLOR_2="${DESKTOPMGR_OUTPUT_COLOR:-6}"
+DESKTOPMGR_OUTPUT_COLOR_GOOD="${DESKTOPMGR_OUTPUT_COLOR_GOOD:-2}"
+DESKTOPMGR_OUTPUT_COLOR_ERROR="${DESKTOPMGR_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DESKTOPMGR_NOTIFY_ENABLED="${DESKTOPMGR_NOTIFY_ENABLED:-yes}"
+DESKTOPMGR_GOOD_NAME="${DESKTOPMGR_GOOD_NAME:-Great:}"
+DESKTOPMGR_ERROR_NAME="${DESKTOPMGR_ERROR_NAME:-Error:}"
+DESKTOPMGR_GOOD_MESSAGE="${DESKTOPMGR_GOOD_MESSAGE:-No errors reported}"
+DESKTOPMGR_ERROR_MESSAGE="${DESKTOPMGR_ERROR_MESSAGE:-Errors were reported}"
+DESKTOPMGR_NOTIFY_CLIENT_NAME="${DESKTOPMGR_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DESKTOPMGR_NOTIFY_CLIENT_ICON="${DESKTOPMGR_NOTIFY_CLIENT_ICON:-notification-new}"
+DESKTOPMGR_NOTIFY_CLIENT_URGENCY="${DESKTOPMGR_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+DESKTOPMGR_GIT_REPO_BRANCH="${DESKTOPMGR_GIT_REPO_BRANCH:-main}"
+DESKTOPMGR_APP_DIR="${DESKTOPMGR_APP_DIR:-$SHARE/CasjaysDev/$DESKTOPMGR_SCRIPTS_PREFIX}"
+DESKTOPMGR_INSTALL_DIR="${DESKTOPMGR_INSTALL_DIR:-$SHARE/CasjaysDev/$DESKTOPMGR_SCRIPTS_PREFIX}"
+DESKTOPMGR_CLONE_DIR="${DESKTOPMGR_CLONE_DIR:-$HOME/Projects/github/$DESKTOPMGR_SCRIPTS_PREFIX}"
+DESKTOPMGR_REPO_URL="${DESKTOPMGR_REPO_URL:-https://github.com/$DESKTOPMGR_SCRIPTS_PREFIX}"
+DESKTOPMGR_REPO_RAW="${DESKTOPMGR_REPO_RAW:-raw/$DESKTOPMGR_GIT_REPO_BRANCH}"
+DESKTOPMGR_REPO_API_URL="${DESKTOPMGR_REPO_API_URL:-https://api.github.com/orgs/$DESKTOPMGR_SCRIPTS_PREFIX/repos}"
+DESKTOPMGR_REPO_API_PER_PAGE="${DESKTOPMGR_REPO_API_PER_PAGE:-1000}"
+DESKTOPMGR_FORCE_INSTALL="${DESKTOPMGR_FORCE_INSTALL:-false}"
+DESKTOPMGR_DIR_USER="${DESKTOPMGR_DIR_USER:-$USRUPDATEDIR}"
+DESKTOPMGR_DIR_SYSTEM="${DESKTOPMGR_DIR_SYSTEM:-$SYSUPDATEDIR}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate non-existing config files
+[ -f "$DESKTOPMGR_CONFIG_DIR/$DESKTOPMGR_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DESKTOPMGR_CONFIG_DIR/$DESKTOPMGR_CONFIG_FILE" ] && . "$DESKTOPMGR_CONFIG_DIR/$DESKTOPMGR_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories and files exist
+[ -d "$DESKTOPMGR_LOG_DIR" ] || mkdir -p "$DESKTOPMGR_LOG_DIR" &>/dev/null
+[ -d "$DESKTOPMGR_TEMP_DIR" ] || mkdir -p "$DESKTOPMGR_TEMP_DIR" &>/dev/null
+[ -d "$DESKTOPMGR_CACHE_DIR" ] || mkdir -p "$DESKTOPMGR_CACHE_DIR" &>/dev/null
+DESKTOPMGR_TEMP_FILE="${DESKTOPMGR_TEMP_FILE:-$(mktemp $DESKTOPMGR_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DESKTOPMGR_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DESKTOPMGR_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DESKTOPMGR_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DESKTOPMGR_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DESKTOPMGR_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DESKTOPMGR_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set additional variables/Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS="a,f"
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,options,config,version,help,force,all,raw"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="download,list,search,available,remove,version,update,install,cron"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST="awesome bspwm dusk dwm herbstluftwm i3 leftwm openbox qtile spectrwm xfce4 xmonad "
+LIST+="cutefish plasma mate sway cwm twm "
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ SHOW_LIST="$(__api_list || echo '' &)"
+ [ -n "$1" ] || printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-'
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--'
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' ''
+ [ -n "$SHOW_LIST" ] && printf '\n' && printf_yellow "Below are the available packages:" &&
+ printf '%s\n' "$SHOW_LIST" | printf_column $DESKTOPMGR_OUTPUT_COLOR
+ printf '\n'
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ -f | --force)
+ shift 1
+ export FORCE_INSTALL="true"
+ ;;
+ -a | --all)
+ shift 1
+ INSTALL_ALL="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DESKTOPMGR_CWD="$arg" && shift 1
+# elif [ -f "$arg" ]; then
+# DESKTOPMGR_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DESKTOPMGR_CWD="$1" && shift 1 || DESKTOPMGR_CWD="${DESKTOPMGR_CWD:-$PWD}"
+DESKTOPMGR_CWD="$(realpath "${DESKTOPMGR_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DESKTOPMGR_CWD" ] && cd "$DESKTOPMGR_CWD"; then
+# if [ "$DESKTOPMGR_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DESKTOPMGR_CWD"
+# fi
+# else
+# printf_exit "💔 $DESKTOPMGR_CWD does not exist 💔"
+# fi
+export DESKTOPMGR_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+# __sudoif && __requiresudo "$0" "${SETARGS[@]}" || exit 2 # exit 2 if errors
+# __cmd_exists bash || exit 3 # exit with error code 3 if not found
+# __am_i_online "1.1.1.1" || exit 4 # exit with error code 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+declare -a LISTARRAY=()
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+list)
+ shift 1
+ printf_green "All installed $DESKTOPMGR_SCRIPTS_PREFIX packages"
+ LISTARRAY=("$(ls -A "$DESKTOPMGR_DIR_SYSTEM" 2>/dev/null)")
+ [ -n "${LISTARRAY[*]}" ] && printf '%s\n' "${LISTARRAY[@]}" | printf_column '5' ||
+ printf_exit "There doesn't seem to be any packages installed"
+ exit ${exitCode:-0}
+ ;;
+
+available)
+ shift 1
+ api_info="$(__api_list)"
+ pkg_count="$(echo "$api_info" | tr ' ' '\n' | wc -l)"
+ if [ -n "$api_info" ]; then
+ printf_purple "$DESKTOPMGR_SCRIPTS_PREFIX currently has $pkg_count packages available"
+ printf '%s\n' "$api_info" | printf_column '6'
+ true
+ else
+ false
+ fi
+ exit ${exitCode:-0}
+ ;;
+
+search)
+ shift 1
+ [ $# = 0 ] && printf_exit "Nothing to search for"
+ __run_search "$@"
+ exit ${exitCode:-0}
+ ;;
+
+remove)
+ shift 1
+ if [ "$INSTALL_ALL" = "true" ]; then
+ LISTARRAY=("$(ls -A "$DESKTOPMGR_DIR_SYSTEM" 2>/dev/null)")
+ else
+ LISTARRAY=("$@")
+ fi
+ [ ${#LISTARRAY} -ne 0 ] || printf_exit "No packages selected for removal"
+ for rmf in "${LISTARRAY[@]}"; do
+ MESSAGE="Removing $rmf from $DESKTOPMGR_INSTALL_DIR/$rmf"
+ __installer_delete "$rmf"
+ retVal=$?
+ [ $retVal = 0 ] && __notifications "Deletion of $APPNAME was successfull" || __notifications "Deletetion of $APPNAME has failed"
+ exitCode=$(($retVal + $exitCode))
+ printf '\n'
+ done
+ exit ${exitCode:-0}
+ ;;
+
+install)
+ shift 1
+ if [ "$INSTALL_ALL" = "true" ] || [ $# -eq 0 ]; then
+ printf_blue "No packages provide running the updater"
+ exit
+ else
+ LISTARRAY=("$@")
+ fi
+ for ins in "${LISTARRAY[@]}"; do
+ if [ -e "$DESKTOPMGR_INSTALL_DIR/$ins" ] || [ -e "$DESKTOPMGR_DIR_SYSTEM/$ins" ] || [ -e "$DESKTOPMGR_DIR_USER/$ins" ] || [ -e "$SHARE/CasjaysDev/$SCRIPTS_PREFIX/$ins" ]; then
+ __notifications "$ins is already installed"
+ continue
+ else
+ APPNAME="$ins"
+ __run_install_update "$APPNAME"
+ retVal=$?
+ [ $retVal = 0 ] && __notifications "Successfully installed $APPNAME" || __notifications "Installation of $APPNAME has failed"
+ exitCode=$(($retVal + $exitCode))
+ fi
+ done
+ exit ${exitCode:-0}
+ ;;
+
+update)
+ shift 1
+ if [ $# -eq 0 ] || [ "$INSTALL_ALL" = "true" ]; then
+ LISTARRAY=("$(ls -A "$DESKTOPMGR_DIR_SYSTEM" 2>/dev/null)")
+ else
+ LISTARRAY=("$@")
+ fi
+ if [ $# -ne 0 ]; then
+ for ins in "${LISTARRAY[@]}"; do
+ APPNAME="$ins"
+ __run_install_update "$APPNAME"
+ retVal=$?
+ [ $retVal = 0 ] && __notifications "Successfully updated $APPNAME" || __notifications "Update of $APPNAME has failed"
+ exitCode=$(($retVal + $exitCode))
+ done
+ elif [ -d "$DESKTOPMGR_DIR_SYSTEM" ] && [ ${#LISTARRAY} -ne 0 ]; then
+ for upd in $(ls -A "$DESKTOPMGR_DIR_SYSTEM" 2>/dev/null); do
+ APPNAME="$upd"
+ __run_install_update "$APPNAME"
+ retVal=$?
+ [ $retVal = 0 ] && __notifications "Successfully updated $APPNAME" || __notifications "Update of $APPNAME has failed"
+ exitCode=$(($retVal + $exitCode))
+ done
+ else
+ printf_yellow "There doesn't seem to be any packages installed"
+ __notifications "There doesn't seem to be any packages installed"
+ fi
+ exit ${exitCode:-0}
+ ;;
+
+download | clone)
+ shift 1
+ if [ $# = 0 ] || [ "$INSTALL_ALL" = "true" ]; then
+ LISTARRAY=("$(__api_list)")
+ else
+ LISTARRAY=("$@")
+ fi
+ if [ -n "${LISTARRAY[*]}" ]; then
+ for pkgs in "${LISTARRAY[@]}"; do
+ __download "$pkgs"
+ retVal=$?
+ [ $retVal = 0 ] && __notifications "Downloaded $APPNAME" || __notifications "Download of $APPNAME has failed"
+ exitCode=$(($retVal + $exitCode))
+ done
+ else
+ printf_exit "No packages selected for download"
+ fi
+ exit ${exitCode:-0}
+ ;;
+
+cron)
+ shift 1
+ [ "$*" = "help" ] && printf_exit 2 0 "Usage: $APPNAME cron $APPNAME"
+ LISTARRAY=("$@")
+ for cron in "${LISTARRAY[@]}"; do
+ APPNAME="$cron"
+ __cron_updater "$APPNAME"
+ exitCode=$(($? + $exitCode))
+ done
+ exit ${exitCode:-0}
+ ;;
+
+version)
+ shift 1
+ LISTARRAY=("$@")
+ for ver in "${LISTARRAY[@]}"; do
+ APPNAME="$ver"
+ __run_install_version "$ver"
+ exitCode=$(($? + $exitCode))
+ done
+ exit ${exitCode:-0}
+ ;;
+
+qemu)
+ shift 1
+ [ -e "/dev/kvm" ] && virt-check test || printf_exit "virtualization doesn't seem to be enabled"
+ retVal=0
+ CURRENT_IP_4="${CURRENT_IP_4:-127.0.0.1}"
+ case "$1" in
+ lin | linux)
+ shift 1
+ VERSION="${1:-https://repo.almalinux.org/almalinux/9/isos/x86_64/AlmaLinux-9-latest-x86_64-boot.iso}"
+ VM_NAME="linux"
+ PORT="65301"
+ echo "initializing qemu-$VM_NAME"
+ if ! docker ps -a 2>%1 | grep -q qemu-$VM_NAME; then
+ docker run --quiet --detach --memory=4G -it --privileged --name qemu-$VM_NAME --publish $PORT:8006 --device=/dev/kvm --volume "$HOME/.local/share/qemu/$VM_NAME":/storage --cap-add NET_ADMIN --stop-timeout 120 --env "VERSION=${VERSION}" --env "DISK_SIZE=100G" --env "RAM_SIZE=4G" --env CPU_CORES="2" qemux/qemu-docker
+ retVal=$?
+ fi
+ [ $retVal -eq 0 ] && echo "Go to http://$CURRENT_IP_4:$PORT and open docker logs --follow qemu-$VM_NAME" || { echo "Failed to create $VM_NAME" && docker rm -f "$VM_NAME" >/dev/null 2>&1; }
+ ;;
+ win | windows)
+ shfit 1
+ VERSION="${1:-ventura}"
+ VM_NAME="windows"
+ PORT="65302"
+ echo "initializing qemu-$VM_NAME"
+ if ! docker ps -a 2>%1 | grep -q qemu-$VM_NAME; then
+ docker run --quiet --detach --memory=4G -it --privileged --name qemu-$VM_NAME --publish $PORT:8006 --device=/dev/kvm --cap-add NET_ADMIN --volume "$HOME/.local/share/qemu/$VM_NAME":/storage --stop-timeout 120 --env "VERSION=${VERSION}" --env "DISK_SIZE=100G" --env "RAM_SIZE=4G" --env CPU_CORES="2" dockurr/windows
+ retVal=$?
+ fi
+ [ $retVal -eq 0 ] && echo "Go to http://$CURRENT_IP_4:$PORT and open docker logs --follow qemu-$VM_NAME" || { echo "Failed to create $VM_NAME" && docker rm -f "$VM_NAME" >/dev/null 2>&1; }
+ ;;
+ mac | macos)
+ shfit 1
+ VERSION="${1:-10}"
+ VM_NAME="macos"
+ PORT="65303"
+ echo "initializing qemu-$VM_NAME"
+ if ! docker ps -a 2>%1 | grep -q qemu-$VM_NAME; then
+ docker run --quiet --detach --memory=4G -it --privileged --name qemu-$VM_NAME --publish $PORT:8006 --device=/dev/kvm --cap-add NET_ADMIN --volume "$HOME/.local/share/qemu/$VM_NAME":/storage --stop-timeout 120 --env "VERSION=${VERSION}" --env "DISK_SIZE=100G" --env "RAM_SIZE=4G" --env CPU_CORES="2" dockurr/macos
+ retVal=$?
+ fi
+ [ $retVal -eq 0 ] && echo "Go to http://$CURRENT_IP_4:$PORT and open docker logs --follow qemu-$VM_NAME" || { echo "Failed to create $VM_NAME" && docker rm -f "$VM_NAME" >/dev/null 2>&1; }
+ ;;
+ arm | arm64)
+ VERSION="${1:-https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/aarch64/alpine-standard-3.20.1-aarch64.iso}"
+ VM_NAME="arm"
+ PORT="65304"
+ echo "initializing qemu-$VM_NAME"
+ if ! docker ps -a 2>%1 | grep -q qemu-$VM_NAME; then
+ docker run --quiet --detach --memory=4G -it --privileged --name qemu-$VM_NAME --publish $PORT:8006 --device=/dev/kvm --volume "$HOME/.local/share/qemu/$VM_NAME":/storage --cap-add NET_ADMIN --stop-timeout 120 --env "BOOT=${VERSION}" --env "DISK_SIZE=100G" --env "RAM_SIZE=4G" --env CPU_CORES="2" qemux/qemu-arm
+ retVal=$?
+ fi
+ [ $retVal -eq 0 ] && echo "Go to http://$CURRENT_IP_4:$PORT and open docker logs --follow qemu-$VM_NAME" || { echo "Failed to create $VM_NAME" && docker rm -f "$VM_NAME" >/dev/null 2>&1; }
+ ;;
+ esac
+ ;;
+
+*)
+ printf_red "User ID: $UID"
+ printf_green "User Name: $RUN_USER"
+ printf_blue "Script Name: $APPNAME"
+ printf_cyan "Version: $VERSION"
+ printf_yellow "Config Dir: $DESKTOPMGR_CONFIG_DIR"
+ printf_purple "Git Source Dir: $DESKTOPMGR_CLONE_DIR"
+ __help
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/detectostype b/bin/detectostype
new file mode 100755
index 000000000..9565aa9a1
--- /dev/null
+++ b/bin/detectostype
@@ -0,0 +1,335 @@
+#!/usr/bin/env sh
+# shellcheck shell=sh
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208181555-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : detectostype --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Aug 18, 2022 15:55 EDT
+# @@File : detectostype
+# @@Description : Script to detect the OS
+# @@Changelog : New script
+# @@TODO : TODO: Update scripts to use new variables
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : shell/sh
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set sh options
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ __printf_color() { printf '%b' "$1\n" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ __printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1\n" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { __printf_color "$1" "5"; }
+__printf_opts() { __printf_color "$1" "6"; }
+__printf_line() { __printf_color "$1" "4"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { __printf_color "202208181555-git" "3"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "detectostype: Script to detect the OS - 202208181555-git"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: detectostype [options] [commands]"
+ __printf_line "* - Exports the variables"
+ __printf_line "all - Show all variables"
+ __printf_line "arch - Show arch type"
+ __printf_line "name - Show OS name/ID"
+ __printf_line "type - Show OS type"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional functions
+__get_lsb_release_name() { $LSB_RELEASE -a 2>/dev/null | grep -i '^Distributor' | grep -v '/' | awk '{print $3}' | grep '^' || false; }
+__get_distro_id() { grep -sh '^ID=' "/etc/os-release" | awk -F'=' '{print $2}' | awk -F' ' '{print $1$2}' | sed 's|"||g' | grep '^' || false; }
+__get_distro_name() { grep -sh '^NAME=' "/etc/os-release" | awk -F'=' '{print $2}' | awk -F' ' '{print $1$2}' | sed 's|"||g' | grep '^' || false; }
+__get_distro_pretty() { grep 'PRETTY_NAME=' /etc/os-release | awk -F'=' '{print $2}' | awk -F' ' '{print $1$2}' | sed 's|"||g' | grep '^' || false; }
+__get_codename() { grep -E '^VERSION_CODENAME=|^CODENAME=' /etc/*-release | awk -F'=' '{print $2}' | awk -F' ' '{print $1$2}' | sed 's|"||g' | grep '^' || false; }
+__get_lsb_codename() { $LSB_RELEASE -a 2>/dev/null | grep -i '^Codename' | awk '{print $2}' | grep '^' || $LSB_RELEASE -a 2>/dev/null | grep 'CODE' | sed 's#CODE_NAME:##g' | awk '{print $2}' | grep '^' || false; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_distro_version() {
+ os_v=""
+ if [ -n "$DISTRO_VERSION" ] && [ "$DISTRO_VERSION" != "N/A" ] && printf '%s\n' "$DISTRO_VERSION" | grep -q '^[0-9]'; then
+ printf '%s\n' "$DISTRO_VERSION"
+ return
+ fi
+ if [ -n "$(ls -A /etc/*-release 2>/dev/null)" ]; then
+ os_v="$(cat /etc/os-release | grep '^VERSION="' | sed 's#VERSION="##g;s#"##g' | awk '{print $1}' | grep '^')"
+ elif [ -f "/etc/redhat-release" ]; then
+ os_v="$(cat /etc/redhat-release | awk '{print $4}' | tr '[:upper:]' '[:lower:]' | sed 's#"##g' | grep '^')"
+ elif [ -f "/etc/os-release" ]; then
+ os_v="$(grep -sh "^VERSION_ID=" /etc/*-release | cut -f1 -d'.' | cut -f2 -d'"' | grep -v '' | grep '^')"
+ fi
+ if [ -z "$os_v" ]; then
+ os_v="$([ -f "/etc/debian_version" ] && grep '[0-9]' "/etc/debian_version" | head -n1 | awk -F '.' '{print $1}')"
+ fi
+ if [ -z "$os_v" ]; then
+ os_v="$(grep -sh '^VERSION=' /etc/os-release 2>/dev/null | sed 's|[a-zA-Z]||g;s/[^.0-9]*//g' | grep -v '/' | grep '[0-9]$')"
+ fi
+ if [ -z "$os_v" ]; then
+ os_v="$(grep -sh 'BUILD_ID' /etc/os-release 2>/dev/null | awk -F '=' '{print $2}' | sed 's|[a-zA-Z]||g;s/[^.0-9]*//g' | grep '[0-9]$')"
+ fi
+ if [ -z "$os_v" ]; then
+ os_v="$($LSB_RELEASE -a 2>/dev/null | grep -i '^Release' | grep -v '/' | awk '{print $2}' | grep '^' | grep '[0-9]')"
+ fi
+ [ -n "$os_v" ] && printf '%s\n' "$os_v" | sed 's|"||g' || echo "Version: Unknown"
+ unset os_v
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set variables
+KERNEL_VERSION="$(command -v uname 2>/dev/null 1>/dev/null && uname -r || echo 'Unknown')"
+LSB_RELEASE="$(command -v lsb_release 2>/dev/null || command -v lsb-release 2>/dev/null || false)"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# if needed add getopts here
+SHORTOPTS=""
+LONGOPTS="debug,help,raw,version,options"
+ARRAY="all arch name type"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# execute options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "detectostype" -- "$@" 2>/dev/null)
+eval set -- "${setopts}" #2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ __printf_color() { printf '%b' "$1\n" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -x
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ ;;
+ --help)
+ shift 1
+ __help
+ exit
+ ;;
+ --version)
+ shift 1
+ __version
+ exit
+ ;;
+ --options)
+ [ -z "$SHORTOPTS" ] || echo "short: $SHORTOPTS" | sed 's|: |: -|g;s|,| -|g;s|^-||g'
+ [ -z "$LONGOPTS" ] || echo "long: $LONGOPTS" | sed 's|: |: --|g;s|,| --|g;s|^--||g'
+ [ -z "$ARRAY" ] || echo "commands: $ARRAY"
+ exit
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Main application
+case "$(uname -s)" in
+'Linux') OS_NAME='Linux' ;;
+'FreeBSD') OS_NAME='FreeBSD' ;;
+'Darwin') OS_NAME='Mac' ;;
+'SunOS') OS_NAME='Solaris' ;;
+'AIX') OS_NAME=AIX ;;
+'WindowsNT' | msys* | mingw* | cygwin* | win*) OS_NAME='Windows' ;;
+*) [ -n "$OS" ] && OS_NAME="$OS" || OS_NAME="Unknown" ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#Set OS Detection
+if [ -n "$LSB_RELEASE" ]; then
+ DISTRO_NAME=$(__get_lsb_release_name)
+elif [ -f "/etc/os-release" ]; then
+ DISTRO_NAME=$(__get_distro_name || __get_distro_pretty || echo "Unknown")
+elif [ -f "/etc/debian_version" ]; then
+ DISTRO_NAME="Debian"
+elif [ -f "/etc/redhat-release" ]; then
+ DISTRO_NAME="RHEL"
+else
+ DISTRO_NAME="$(uname -s)"
+ DISTRO_VERSION="$KERNEL_VERSION"
+fi
+[ "$DISTRO_NAME" = "Unknown" ] && DISTRO_NAME="$(__get_distro_name)"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#Version
+CODE_NAME="$(__get_codename | grep '^')"
+DISTRO_VERSION="$(__get_distro_version | grep '^')"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set temp variables
+o="$(echo "$OS_NAME" | tr '[:upper:]' '[:lower:]')"
+n="$(echo "$DISTRO_NAME" | tr '[:upper:]' '[:lower:]')"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#Various Arch Distros
+if [ "$n" = "arcoLinux" ] || [ "$n" = "archlinux" ] || [ "$n" = "manjarolinux" ] || [ "$n" = "arch" ] || [ "$n" = "blackarch" ]; then
+ DISTRO_ID="Arch"
+ DISTRO_VERSION="${DISTRO_VERSION:-$(cat /etc/os-release | grep '^BUILD_ID' | sed 's#BUILD_ID=##g')}"
+#Raspberry pi
+elif [ "$n" = "raspbian" ]; then
+ DISTRO_ID="Raspbian"
+ CODE_NAME="$(__get_codename || __get_lsb_codename)"
+#Various RedHat Distros
+elif [ "$n" = "scientific" ] || [ "$n" = "redhat" ] || [ "$n" = "centos" ] || [ "$n" = "casjay" ] || [ "$n" = "almalinux" ] || [ "$n" = "rockylinux" ] || [ "$n" = "alma" ] || [ "$n" = "rocky" ]; then
+ DISTRO_ID="RHEL"
+#Various Debian Distros
+elif [ "$n" = "kali" ] || [ "$n" = "peppermint" ] || [ "$n" = "parrot" ] || [ "$n" = "debian" ]; then
+ DISTRO_ID="Debian"
+ if [ "$n" = "debian" ]; then
+ CODE_NAME="$(__get_codename || __get_lsb_codename)"
+ fi
+ if [ "$n" = "kali" ]; then
+ CODE_NAME="kali"
+ fi
+ if [ "$n" = "parrot" ]; then
+ CODE_NAME="parrot"
+ fi
+elif [ "$n" = "ubuntu" ] || [ "$n" = "mint" ] || [ "$n" = "elementary" ] || [ "$n" = "kde neon" ]; then
+ DISTRO_ID="Ubuntu"
+ CODE_NAME=$(__get_codename || __get_lsb_codename)
+elif [ "$n" = "fedora" ]; then
+ DISTRO_NAME="Fedora"
+fi
+if [ "$o" = "mac" ] || [ "$o" = "darwin" ]; then
+ DISTRO_NAME="MacOS"
+ DISTRO_VERSION="10.x"
+ [ -f "$(command -v sw_vers 2>/dev/null)" ] && DISTRO_VERSION="$(sw_vers -productVersion)"
+fi
+if [ "$o" = "Windows" ] || [ "$o" = "windowsnt" ]; then
+ DISTRO_NAME="Windows"
+ DISTRO_VERSION="NT"
+fi
+[ -n "$DISTRO_ID" ] || DISTRO_ID="N/A"
+[ -n "$CODE_NAME" ] || CODE_NAME="$(__get_codename || __get_lsb_codename || echo 'N/A')"
+[ -n "$DISTRO_VERSION" ] && [ "$DISTRO_VERSION" != "rolling" ] && DISTRO_VERSION="$(echo "$DISTRO_VERSION" | awk '{print $1}' | sed -e 's|[()A-Za-z]||g' | grep '^' || echo "N/A")"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Detect architecture. We only support linux.
+case "$(uname -m)" in
+x86_64)
+ CPU_TYPE="amd64"
+ CPU_NAME="64bit..."
+ ;;
+x86)
+ CPU_TYPE="386"
+ CPU_NAME="32bit..."
+ ;;
+i686)
+ CPU_TYPE="386"
+ CPU_NAME="32bit..."
+ ;;
+i386)
+ CPU_TYPE="386"
+ CPU_NAME="32bit..."
+ ;;
+aarch64)
+ CPU_TYPE="arm64"
+ CPU_NAME="AArch64..."
+ ;;
+armv5*)
+ CPU_TYPE="armv5"
+ CPU_NAME="ARM 5..."
+ ;;
+armv6*)
+ CPU_TYPE="armv6"
+ CPU_NAME="ARM 6..."
+ ;;
+armv7*)
+ CPU_TYPE="armv7"
+ CPU_NAME="ARM 7..."
+ ;;
+*)
+ CPU_TYPE="Unknown"
+ CPU_NAME="Uknown"
+ ;;
+esac
+
+DISTRO_ID="$(echo "$DISTRO_ID" | sed 's|[0-9]||g;s|\.||g')"
+DISTRO_NAME="$(echo "$DISTRO_NAME" | sed 's|[0-9]||g;s|\.||g')"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# TODO: Update scripts to use new variables and remove these
+OS="$OS_NAME"
+DISTRO="$DISTRO_NAME"
+DISTROID="$DISTRO_ID"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+case "$1" in
+all)
+ shift 1
+ __printf_color "OS Name : $OS_NAME" "4"
+ __printf_color "CPU Type : $CPU_TYPE" "4"
+ __printf_color "CPU NAME : $CPU_NAME" "4"
+ __printf_color "DISTRO Name : $DISTRO_NAME" "4"
+ __printf_color "DISTRO ID : $DISTRO_ID" "4"
+ __printf_color "CODE_NAME : $CODE_NAME" "4"
+ __printf_color "DISTRO Version : $DISTRO_VERSION" "4"
+ exit
+ ;;
+arch)
+ shift 1
+ __printf_color "CPU Type : $CPU_TYPE" "4"
+ __printf_color "CPU NAME : $CPU_NAME" "4"
+ exit
+ ;;
+name)
+ shift 1
+ __printf_color "DISTRO Name : $DISTRO_NAME" "4"
+ __printf_color "DISTRO ID : $DISTRO_ID" "4"
+ __printf_color "CODE_NAME : $CODE_NAME" "4"
+ __printf_color "DISTRO Version : $DISTRO_VERSION" "4"
+ exit
+ ;;
+type)
+ shift 1
+ __printf_color "OS Name : $OS_NAME" "4"
+ exit
+ ;;
+*)
+ # TODO Remove DISTRO DISTROID
+ export OS_NAME DISTRO_NAME DISTRO_ID DISTRO DISTROID CODE_NAME DISTRO_VERSION CPU_TYPE CPU_NAME
+ unset o n
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
diff --git a/bin/devenvmgr b/bin/devenvmgr
new file mode 100755
index 000000000..8c27cbd9b
--- /dev/null
+++ b/bin/devenvmgr
@@ -0,0 +1,1341 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202210031720-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : devenvmgr --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Monday, Oct 03, 2022 17:20 EDT
+# @@File : devenvmgr
+# @@Description : Setup a development environment
+# @@Changelog : New script
+# @@TODO : Create user config
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202210031720-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DEVENVMGR_REQUIRE_SUDO="${DEVENVMGR_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DEVENVMGR_CONFIG_DIR/$DEVENVMGR_CONFIG_FILE"
+ fi
+ [ -d "$DEVENVMGR_CONFIG_DIR" ] || mkdir -p "$DEVENVMGR_CONFIG_DIR"
+ [ -d "$DEVENVMGR_CONFIG_BACKUP_DIR" ] || mkdir -p "$DEVENVMGR_CONFIG_BACKUP_DIR"
+ [ -f "$DEVENVMGR_CONFIG_DIR/$DEVENVMGR_CONFIG_FILE" ] &&
+ cp -Rf "$DEVENVMGR_CONFIG_DIR/$DEVENVMGR_CONFIG_FILE" "$DEVENVMGR_CONFIG_BACKUP_DIR/$DEVENVMGR_CONFIG_FILE.$$"
+ cat <"$DEVENVMGR_CONFIG_DIR/$DEVENVMGR_CONFIG_FILE"
+# Settings for devenvmgr
+DEVENVMGR_DEFAULT_GITHUB_ORG="${DEVENVMGR_DEFAULT_GITHUB_ORG:-}"
+DEVENVMGR_BASEDIR="${DEVENVMGR_BASEDIR:-}"
+DEVENVMGR_GIT_PROJECT_DIR="${DEVENVMGR_GIT_PROJECT_DIR:-}"
+DEVENVMGR_TEMPLATESDIR="${DEVENVMGR_TEMPLATESDIR:-}"
+DEVENVMGR_FILEMANAGER="${DEVENVMGR_FILEMANAGER:-}"
+DEVENVMGR_COMMAND="${DEVENVMGR_COMMAND:-}"
+DEVENVMGR_COMMAND_TERM="${DEVENVMGR_COMMAND_TERM:-}"
+DEVENVMGR_TMUX_CMD="${DEVENVMGR_TMUX_CMD:-}"
+DEVENVMGR_SCREEN_CMD="${DEVENVMGR_SCREEN_CMD:-}"
+DEVENVMGR_TMUX_CONF="${DEVENVMGR_TMUX_CONF:-}"
+DEVENVMGR_SCREEN_CONF="${DEVENVMGR_SCREEN_CONF:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DEVENVMGR_OUTPUT_COLOR_1="${DEVENVMGR_OUTPUT_COLOR_1:-}"
+DEVENVMGR_OUTPUT_COLOR_2="${DEVENVMGR_OUTPUT_COLOR_2:-}"
+DEVENVMGR_OUTPUT_COLOR_GOOD="${DEVENVMGR_OUTPUT_COLOR_GOOD:-}"
+DEVENVMGR_OUTPUT_COLOR_ERROR="${DEVENVMGR_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DEVENVMGR_NOTIFY_ENABLED="${DEVENVMGR_NOTIFY_ENABLED:-}"
+DEVENVMGR_GOOD_NAME="${DEVENVMGR_GOOD_NAME:-}"
+DEVENVMGR_ERROR_NAME="${DEVENVMGR_ERROR_NAME:-}"
+DEVENVMGR_GOOD_MESSAGE="${DEVENVMGR_GOOD_MESSAGE:-}"
+DEVENVMGR_ERROR_MESSAGE="${DEVENVMGR_ERROR_MESSAGE:-}"
+DEVENVMGR_NOTIFY_CLIENT_NAME="${DEVENVMGR_NOTIFY_CLIENT_NAME:-}"
+DEVENVMGR_NOTIFY_CLIENT_ICON="${DEVENVMGR_NOTIFY_CLIENT_ICON:-}"
+DEVENVMGR_NOTIFY_CLIENT_URGENCY="${DEVENVMGR_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DEVENVMGR_CONFIG_DIR/$DEVENVMGR_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DEVENVMGR_CONFIG_DIR/$DEVENVMGR_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "devenvmgr: Setup a development environment - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: devenvmgr [options] [commands]"
+ __printf_line " - "
+ __printf_line " - "
+ __printf_line "--dir - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DEVENVMGR_REQUIRE_SUDO" = "yes" ] && [ -z "$DEVENVMGR_REQUIRE_SUDO_RUN" ]; then
+ export DEVENVMGR_REQUIRE_SUDO="no"
+ export DEVENVMGR_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DEVENVMGR_TEMP_FILE" ] && rm -Rf "$DEVENVMGR_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__requires() {
+ local COMMAND="$1"
+ shift 1
+ local ARGS="$*"
+ shift $#
+ local cmd=""
+ local choice=""
+ local MISSING=""
+ export APP="${APPNAME:-$PROG}"
+ export NOTIFY_CLIENT_ICON="software"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$APP}"
+ for cmd in $COMMAND; do
+ type -p "$cmd" &>/dev/null || MISSING+="$cmd "
+ done
+ if [ -n "$MISSING" ]; then
+ notifications "${NOTIFY_CLIENT_NAME:-$APPNAME}" "Missing $MISSING"
+ if [ -n "$DESKTOP_SESSION" ]; then
+ __ask_confirm "Would you like install $MISSING" "${ARGS:-pkmgr silent install $MISSING}" && return 0 || return 1
+ else
+ printf_red "The following apps are missing: $MISSING"
+ printf_read_question "2" "Would you like install the missing packages? [y/N]" "1" "choice" "-s"
+ if printf_answer_yes "$choice"; then
+ for miss in $MISSING; do
+ return 0 || return 1
+ done
+ else
+ return 1
+ fi
+ fi
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__start_servers() {
+ case "$1" in
+ jekyll)
+ __requires jekyll || printf_exit 1 1 "jekyll can't be found"
+ if [ -f "$DEVENV_PROJECT_DIR/_config.yml" ]; then
+ if __cmd_exists watchy; then
+ watchy -w "$DEVENV_PROJECT_DIR/_config.yml" -- jekyll serve --host=0.0.0.0
+ elif __cmd_exists jekyll; then
+ jekyll serve --host=0.0.0.0
+ else
+ printf_exit "There was a problem staring - no config found"
+ fi
+ else
+ printf_exit "There was a problem starting - no config found"
+ fi
+ ;;
+ *)
+ printf_red "No parameters specified"
+ exit
+ ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__editor_gui() {
+ local editor="$(type -P "$EDITOR" 2>/dev/null || type -P "vim" 2>/dev/null || type -P "nano" 2>/dev/null || type -P "nvim" 2>/dev/null || type -P "vi" 2>/dev/null || type -P "vi" 2>/dev/null || false)"
+ if [ -n "$DEVENVMGR_COMMAND" ] && __cmd_exists "$DEVENVMGR_COMMAND"; then
+ if [ "$DEVENVMGR_COMMAND" = "$(basename code)" ]; then
+ code .
+ elif [ "$DEVENVMGR_COMMAND" = "$(basename code-insiders)" ]; then
+ code-insiders .
+ elif [ "$DEVENVMGR_COMMAND" = "$(basename code-oss)" ]; then
+ code-oss .
+ elif [ -n "$DEVENVMGR_COMMAND" ]; then
+ $DEVENVMGR_COMMAND .
+ elif [ -n "$editor" ]; then
+ eval $editor .
+ else
+ printf_red "Could not determine your editor"
+ printf_blue "Please set the variable DEVENVMGR_COMMAND"
+ fi
+ elif [ -f "$DEVENVMGR_TMUX_CONF" ]; then
+ $DEVENVMGR_TMUX_CMD -f "$DEVENVMGR_TMUX_CONF"
+ elif __cmd_exists $DEVENVMGR_FILEMANAGER; then
+ $DEVENVMGR_FILEMANAGER ${1:-$DEVENV_PROJECT_DIR}
+ elif [ -n "$editor" ]; then
+ eval $editor
+ else
+ printf_red "Your site has been setup"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__editor_term() {
+ if __cmd_exists $DEVENVMGR_COMMAND_TERM; then
+ $DEVENVMGR_COMMAND_TERM
+ elif __cmd_exists $DEVENVMGR_SCREEN_CMD; then
+ $DEVENVMGR_SCREEN_CMD -c "$DEVENVMGR_SCREEN_CONF"
+ elif cmd $DEVENVMGR_TMUX_CMD; then
+ tmux -f "$DEVENVMGR_TMUX_CONF"
+ elif __cmd_exists $DEVENVMGR_FILEMANAGER; then
+ $DEVENVMGR_FILEMANAGER .
+ elif __cmd_exists vim; then
+ vim .
+ else
+ printf_red "Your site has been setup"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# What to do after creating project
+__finalize_new_project() {
+ local message="${1:-$final_message}"
+ [ -n "$message" ] && printf_cyan "$message"
+ printf_green "Attempting to launch editor for $DEVENV_PROJECT_NAME in $DEVENV_PROJECT_DIR"
+ cd "$DEVENV_PROJECT_DIR" || { printf_green "$DEVENVMG_PROGRAM_NAME has been created in $DEVENV_PROJECT_DIR" && return 1; }
+ if [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ]; then
+ __editor_gui "$DEVENV_PROJECT_DIR"
+ else
+ __editor_term "$DEVENV_PROJECT_DIR"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check for sample files
+__if_sample() {
+ if [ -f .env.sample ] || [ -f .env ]; then cp -Rf .env.sample .env; fi
+ if [ -f .config.sample ] || [ -f .config ]; then cp -Rf .config.sample .config; fi
+ if [ -f config.example.js ] || [ -f config.js ]; then cp -Rf config.example.js config.js; fi
+ if [ -f .config.json.sample ] || [ -f .config.json ]; then cp -Rf .config.json.sample .config.json; fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup node manager
+__fnm_setup() {
+ [ $# -eq 0 ] || shift $#
+ nodev="$(node 2>/dev/null -v | tr ' ' '\n' | grep v[0-9] | head -n1)"
+ if [ "$NODE_MANAGER" = "fnm" ]; then
+ if __cmd_exists fnm; then
+ printf_cyan "Configuring for node $nodev"
+ eval $(fnm env 2>/dev/null)
+ fnm use $nodev &>/dev/null
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initialize node env
+__execute_npm() {
+ local exitCode=0
+ local DEVENV_PROJECT_BASE="${DEVENV_PROJECT_NAME:-$(basename $(realpath "$DEVENV_PROJECT_DIR"))}"
+ if __cmd_exists npm; then
+ __execute_npm_modules && exitCode=0 || exitCode=1
+ if [ $exitCode = 0 ]; then
+ gitignore "$DEVENV_PROJECT_DIR" -f dirignore default node
+ printf_green "The project has been successfully setup"
+ else
+ printf_return "Failed to initialize the modules"
+ fi
+ else
+ printf_exit 1 1 "The program npm can not be found"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initialize node modules
+__execute_npm_modules() {
+ local ARGS="$*"
+ local CDFAILED=""
+ local projectname=""
+ local DEVENV_PROJECT_DIR="${DEVENV_PROJECT_DIR:-.}"
+ local DEVENV_PROJECT_NAME="${DEVENV_PROJECT_NAME:-$(basename $(realpath "$DEVENV_PROJECT_DIR"))}"
+ local DEVENV_PROJECT_BASE="${DEVENV_PROJECT_BASE:-$DEVENV_PROJECT_NAME}"
+ __fnm_setup "init"
+ __cmd_exists npm || printf_exit 1 1 "The program npm can not be found"
+ if [ -z "$CDFAILED" ]; then
+ printf_blue "Installing node modules for: $DEVENV_PROJECT_BASE"
+ printf_blue "This may time a few minutes"
+ if [ $# = 0 ]; then
+ npm install &>>"$DEVENV_PROJECT_DIR/init.log"
+ npm install -D &>>"$DEVENV_PROJECT_DIR/init.log"
+ else
+ npm install $ARGS &>>"$DEVENV_PROJECT_DIR/init.log"
+ fi
+ else
+ printf_exit "Failed to cd into $DEVENV_PROJECT_DIR"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a static server
+__run_static_site() {
+ printf_blue "Enter location for your new or existing site"
+ printf_read_input "3" "enter . for current:" "200" "DEVENV_PROJECT_DIR" "-i ${DEVENV_PROJECT_DIR:-$DEVENVMGR_BASEDIR/$DEVENVMG_PROGRAM_NAME}"
+ __run_new_site
+ if cd "$DEVENV_PROJECT_DIR"; then
+ if __cmd_exists run_server && __cmd_exists caddy; then
+ run_server static "${1:-20000}"
+ elif __cmd_exists run_server; then
+ run_server "${1:-20000}"
+ fi
+ else
+ printf_return 1 1 "Failed to enter into $DEVENV_PROJECT_DIR"
+ fi
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import new site from git
+__run_import_site() {
+ local import=""
+ printf_read_input "3" "Enter the url to your git repo:" "200" "import"
+ printf_read_input "3" "Enter location for your new site: " "200" "DEVENV_PROJECT_DIR" "-i ${DEVENV_PROJECT_DIR:-$DEVENVMGR_BASEDIR/$DEVENVMG_PROGRAM_NAME}"
+ [ -n "$DEVENV_PROJECT_DIR" ] || [ -n "$import" ] || printf_exit "Something went wrong"
+ [ -d "$DEVENV_PROJECT_DIR" ] || __mkd "$DEVENV_PROJECT_DIR"
+ if git clone "$import" "$DEVENV_PROJECT_DIR" -q &>/dev/null; then
+ printf_green "Import from $import completed"
+ else
+ printf_red "Something went wrong with the import"
+ printf_exit "git clone $import $DEVENV_PROJECT_DIR -q"
+ fi
+ cd "$DEVENV_PROJECT_DIR" || printf_exit 1 1 "$DEVENV_PROJECT_DIR doesn't exist"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set site directory
+__set_sitedir() {
+ if [ -z "$DEVENV_PROJECT_DIR" ]; then
+ printf_green "Enter the full path for your new project!"
+ printf_read_input "3" "enter . for current:" "300" "NEW_DEVENV_PROJECT_DIR" "-r"
+ fi
+ [ -n "$NEW_DEVENV_PROJECT_DIR" ] && DEVENV_PROJECT_DIR="$(realpath "$NEW_DEVENV_PROJECT_DIR")" || DEVENV_PROJECT_DIR="$(realpath "${DEVENV_PROJECT_DIR:-$PWD}")"
+ DEVENV_PROJECT_BASE="$(basename $(realpath "$DEVENV_PROJECT_DIR"))"
+ printf_green "Enter a project name!"
+ printf_read_input "3" "enter . to use folder:" "300" "DEVENV_PROJECT_NAME" "-r -i ."
+ [ -n "$DEVENV_PROJECT_NAME" ] && [ "$DEVENV_PROJECT_NAME" != "." ] && DEVENV_PROJECT_NAME="$(basename -- "$DEVENV_PROJECT_NAME")" || DEVENV_PROJECT_NAME="$DEVENV_PROJECT_BASE"
+ export DEVENV_PROJECT_DIR DEVENV_PROJECT_NAME DEVENV_PROJECT_BASE
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a new site dir
+__run_new_site() {
+ __set_sitedir || return 1
+ [ -d "$DEVENV_PROJECT_DIR" ] || __mkd "$DEVENV_PROJECT_DIR"
+ cd "$DEVENV_PROJECT_DIR" || printf_exit 1 1 "$DEVENV_PROJECT_DIR doesn't exist"
+ local DEVENV_PROJECT_BASE="${DEVENV_PROJECT_NAME:-$(basename $(realpath "$DEVENV_PROJECT_DIR"))}"
+ export DEVENV_PROJECT_DIR DEVENV_PROJECT_NAME
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a html project
+__run_html() {
+ local appname=html
+ local project=html
+ local templatedir="$TEMPLATESDIR"
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ __run_new_site
+ __mkd css images js
+ __touch css/.gitkeep images/.gitkeep js/.gitkeep
+ if [ ! -f "index.html" ]; then
+ if [ -f "$TEMPLATESDIR/html/index.html" ]; then
+ printf_green "Copying files from: $TEMPLATESDIR/html/"
+ __cp_rf "$TEMPLATESDIR/html/." .
+ else
+ printf_green "Copying index.html from: $CASJAYSDEVDIR/templates/template.html"
+ __cp_rf "$CASJAYSDEVDIR/templates/template.html" index.html
+ fi
+ fi
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run jekyll server
+__run_jekyll() {
+ local appname=jekyll
+ local project=jekyll
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ __run_new_site
+ __requires "$appname" "pkmgr gem install $appname" || printf_exit "$appname is not installed"
+ __if_sample
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run hugo server
+__run_hugo() {
+ local appname=hugo
+ local project=hugo
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ __requires "$appname" "pkmgr silent install $appname" || printf_exit "$appname is not installed"
+ __run_new_site
+ __if_sample
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a ruby project
+__run_ruby() {
+ local appname=ruby
+ local project=ruby
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ __requires "$appname" "pkmgr silent install $appname" || printf_exit "$appname is not installed"
+ __run_new_site
+ __if_sample
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a new python project
+__run_python() {
+ local appname=python
+ local project=python
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ __requires "$appname" "pkmgr silent install $appname" || printf_exit "$appname is not installed"
+ __run_new_site
+ __if_sample
+ if [ "$(command -v python3 2>/dev/null)" ] && [ ! -d "$DEVENV_PROJECT_DIR/venv" ]; then
+ printf_green "Setting up python virtual enviroment"
+ mkdir -p "$DEVENV_PROJECT_DIR" && cd "$DEVENV_PROJECT_DIR" && python3 -m venv venv
+ fi
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a new django project
+__run_django() {
+ local appname=python
+ local project=python
+ final_message="To start development server run: python3 manage.py runserver"
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ __requires "$appname" "pkmgr silent install $appname" || printf_exit "$appname is not installed"
+ __run_new_site
+ __if_sample
+ if [ "$(command -v python3 2>/dev/null)" ] && [ ! -d "$DEVENV_PROJECT_DIR/venv" ]; then
+ printf_green "Setting up python virtual enviroment"
+ mkdir -p "$DEVENV_PROJECT_DIR" && cd "$DEVENV_PROJECT_DIR" && python3 -m venv "$DEVENV_PROJECT_DIR/.venv" && . "./.venv/bin/activate" &&
+ pip3 install django &>/dev/null && django-admin startproject "$(basename -- "$(realpath "$DEVENV_PROJECT_DIR")")" . &>/dev/null &&
+ pip3 freeze >"$DEVENV_PROJECT_DIR/requirements.txt" 2>/dev/null
+ __finalize_new_project
+ fi
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a new perl project
+__run_perl() {
+ local appname=perl
+ local project=perl
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ __requires "$appname" "pkmgr silent install $appname" || printf_exit "$appname is not installed"
+ __run_new_site
+ __if_sample
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a new PHP Project
+__run_php() {
+ local appname=php
+ local project=php
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ __requires "$appname" "pkmgr silent install $appname" || printf_exit "$appname is not installed"
+ __run_new_site
+ __if_sample
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a new laravel Project - https://laravel.com/docs/9.x/installation#your-first-laravel-project
+__run_laravel() {
+ local appname=php
+ local project=laravel
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ __get_composer || printf_exit "composer is required"
+ __requires "$appname" "pkmgr silent install $appname" || printf_exit "$appname is not installed"
+ __run_new_site
+ __if_sample
+ if [ -f "$DEVENV_PROJECT_DIR/artisan" ] || [ -f "$DEVENV_PROJECT_DIR/composer.json" ] || [ -f "$DEVENV_PROJECT_DIR/package.json" ]; then
+ printf_red "A project sseems to already exist"
+ else
+ composer create-project laravel/laravel "$DEVENV_PROJECT_DIR" &>/dev/null
+ fi
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a new node project
+__run_node() {
+ local appname=node || appname=nodejs || appname=npm
+ local project=node
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ __requires "$appname" "pkmgr silent install $appname" || printf_exit "$appname is not installed"
+ __run_new_site
+ __if_sample
+ if [ -f "$DEVENV_PROJECT_DIR/package.json" ]; then
+ printf_red "A package.json already exist"
+ else
+ __gen_nodeconfig
+ fi
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a new deno fresh project
+__run_deno() {
+ local appname=deno
+ local project=fresh
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ type -p $appname &>/dev/null || printf_exit "$appname is not installed"
+ __run_new_site
+ __if_sample
+ cd "$DEVENV_PROJECT_DIR" || return 1
+ deno run --quiet -A -r https://fresh.deno.dev .
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a new VueJS project
+__run_vuecli() {
+ local appname=vue
+ local project=node
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ type -p $project &>/dev/null || printf_exit "$project is not installed"
+ __execute_npm_modules "-g @vue/cli"
+ __run_new_site
+ __if_sample
+ if [ -f "$DEVENV_PROJECT_DIR/package.json" ]; then printf_exit 1 1 "The package.json file already exits"; fi
+ cd "$DEVENV_PROJECT_DIR" || return 1
+ npx $appname create .
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a new ReactJS project
+__run_reactcli() {
+ local appname=create-react-app
+ local project=node
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ type -p $project &>/dev/null || printf_exit "$project is not installed"
+ __run_new_site
+ __if_sample
+ __execute_npm_modules "-g create-react-app"
+ if [ -f "$DEVENV_PROJECT_DIR/package.json" ]; then printf_exit 1 1 "The package.json file already exits"; fi
+ $appname
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a new ExpressJS project
+__run_expresscli() {
+ local appname=express
+ local project=node
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ type -p $project &>/dev/null || npm -g || printf_exit "$project is not installed"
+ __run_new_site
+ __if_sample
+ __execute_npm_modules "-g express-generator"
+ if [ "$1" = "template" ] || [ "$TEMPLATE" = "yes" ]; then
+ __download "create-express-app"
+ __execute_npm &>/dev/null
+ else
+ __gen_nodeconfig "$DEVENV_PROJECT_DIR"
+ __execute_npm_modules "express cors ejs nodemon morgan helmet"
+ fi
+ __gen_prettierconfig "$DEVENV_PROJECT_DIR"
+ __gen_eslintconfig "$DEVENV_PROJECT_DIR"
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a new javascript project
+__run_create-project() {
+ local appname=create-project
+ local project=node
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ type -p $project &>/dev/null || printf_exit "$project is not installed"
+ __run_new_site
+ __if_sample
+ __execute_npm_modules "-g create-project"
+ if [ -f "$DEVENV_PROJECT_DIR/package.json" ]; then printf_exit 1 1 "The package.json file already exits"; fi
+ __gen_nodeconfig "$DEVENV_PROJECT_DIR"
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Start a new mevn project
+__run_mevn() {
+ local appname=mevn
+ local project=javascript
+ local gitrepo="https://github.com/devenvmgr/create-mevn-app"
+ if [ "$*" = "new" ]; then echo "$appname" && exit; fi
+ if [ "$*" = "help" ]; then __help; fi
+ __requires "git" "pkmgr silent install git" || printf_exit "git is not installed"
+ __requires "npm" "pkmgr silent install node" || printf_exit "node is not installed"
+ __run_new_site
+ __if_sample
+ if [ -f "$DEVENV_PROJECT_DIR/package.json" ]; then printf_exit 1 1 "The package.json file already exits"; fi
+ git clone -q "$gitrepo" "$DEVENV_PROJECT_DIR"
+ __finalize_new_project
+ exit $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a shellcheckrc file
+__gen_shellcheck() {
+ local DEVENV_PROJECT_DIR="${1:-$DEVENV_PROJECT_DIR}"
+ if [ -f "$DEVENV_PROJECT_DIR/.shellcheckrc" ]; then
+ printf_yellow ".shellcheckrc already existis in $DEVENV_PROJECT_DIR"
+ printf_cyan "Delete the file and re-run script"
+ return 1
+ else
+ printf_green "Generating .shellcheckrc"
+ __cp_rf "$CASJAYSDEVDIR/templates/shellcheckrc" "$DEVENV_PROJECT_DIR/.shellcheckrc"
+ [ -f "$DEVENV_PROJECT_DIR/.shellcheckrc" ] &&
+ printf_green ".shellcheckrc has been generated" ||
+ printf_exit 1 1 "Failed to create .shellcheckrc"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a editorconfig file
+__gen_editorconfig() {
+ local DEVENV_PROJECT_DIR="${1:-$DEVENV_PROJECT_DIR}"
+ if [ -f "$DEVENV_PROJECT_DIR/.editorconfig" ]; then
+ printf_yellow ".editorconfig already existis in $DEVENV_PROJECT_DIR"
+ printf_cyan "Delete the file and re-run script"
+ return 1
+ else
+ printf_green "Generating .editorconfig"
+ __cp_rf "$CASJAYSDEVDIR/templates/editorconfig" "$DEVENV_PROJECT_DIR/.editorconfig"
+ [ -f "$DEVENV_PROJECT_DIR/.editorconfig" ] &&
+ printf_green ".editorconfig has been generated" ||
+ printf_exit 1 1 "Failed to create .editorconfig"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create prettier config
+__gen_prettierconfig() {
+ local DEVENV_PROJECT_DIR="${1:-$DEVENV_PROJECT_DIR}"
+ if [ -f "$DEVENV_PROJECT_DIR/.prettierrc.json" ]; then
+ printf_yellow ".prettierrc.json already existis in $DEVENV_PROJECT_DIR"
+ printf_cyan "Delete the file and re-run script"
+ return 1
+ else
+ printf_green "Generating .prettierrc.json"
+ __cp_rf "$CASJAYSDEVDIR/templates/prettierrc.json" "$DEVENV_PROJECT_DIR/.prettierrc.json"
+ if [ -f "$DEVENV_PROJECT_DIR/.prettierrc.json" ]; then
+ __execute_npm_modules "-D prettier"
+ printf_green ".prettierrc.json has been generated"
+ else
+ printf_exit 1 1 "Failed to create .prettierrc.json"
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create eslint config
+__gen_eslintconfig() {
+ local DEVENV_PROJECT_DIR="${1:-$DEVENV_PROJECT_DIR}"
+ if [ -f "$DEVENV_PROJECT_DIR/.eslintrc.json" ]; then
+ printf_yellow ".eslintrc.json already existis in $DEVENV_PROJECT_DIR"
+ printf_cyan "Delete the file and re-run script"
+ return 1
+ else
+ printf_green "Generating .eslintrc.json"
+ __cp_rf "$CASJAYSDEVDIR/templates/eslintrc.json" "$DEVENV_PROJECT_DIR/.eslintrc.json"
+ if [ -f "$DEVENV_PROJECT_DIR/.eslintrc.json" ]; then
+ __execute_npm_modules "-D @babel/eslint-parser eslint eslint-config-airbnb-base eslint-config-node eslint-config-prettier eslint-plugin-import eslint-plugin-import eslint-plugin-prettier"
+ printf_green ".eslintrc.json has been generated"
+ else
+ printf_exit 1 1 "Failed to create .eslintrc.json"
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create a tsconfig file
+__gen_tsconfig() {
+ local DEVENV_PROJECT_DIR="${1:-$DEVENV_PROJECT_DIR}"
+ if [ -f "$DEVENV_PROJECT_DIR/tsconfig.json" ]; then
+ printf_yellow "tsconfig.json already existis in $DEVENV_PROJECT_DIR"
+ printf_cyan "Delete the file and re-run script"
+ return 1
+ else
+ printf_green "Generating tsconfig.json"
+ __cp_rf "$CASJAYSDEVDIR/templates/tsconfig.json" "$DEVENV_PROJECT_DIR/tsconfig.json"
+ [ -f "$DEVENV_PROJECT_DIR/tsconfig.json" ] &&
+ printf_green "tsconfig.json has been generated" ||
+ printf_exit 1 1 "Failed to create tsconfig.json"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Create node config
+__gen_nodeconfig() {
+ printf_green "Generating package.json"
+ __setup_git "$DEVENV_PROJECT_DIR"
+ __cp_rf "$CASJAYSDEVDIR/templates/nodejs.json" "$DEVENV_PROJECT_DIR/package.json"
+ if [ -f "$DEVENV_PROJECT_DIR/package.json" ]; then
+ __replace "REPLACE_NAME" "$DEVENV_PROJECT_NAME" "$DEVENV_PROJECT_DIR/package.json"
+ __replace "REPLACE_EMAIL" "$email" "$DEVENV_PROJECT_DIR/package.json"
+ __replace "REPLACE_AUTHOR" "$author" "$DEVENV_PROJECT_DIR/package.json"
+ __replace "REPLACE_REPONAME" "$reponame" "$DEVENV_PROJECT_DIR/package.json"
+ printf_green "Installing required node modules"
+ npm outdated | awk 'NR>1 {print $1"@"$4}' | xargs npm install &>/dev/null
+ __mkd "$DEVENV_PROJECT_DIR/src/api" "$DEVENV_PROJECT_DIR/src/lib"
+ __mkd "$DEVENV_PROJECT_DIR/src/views" "$DEVENV_PROJECT_DIR/src/controllers" "$DEVENV_PROJECT_DIR/src/routes" "$DEVENV_PROJECT_DIR/src/middlewares"
+ __mkd "$DEVENV_PROJECT_DIR/src/public" "$DEVENV_PROJECT_DIR/src/public/images" "$DEVENV_PROJECT_DIR/src/public/css" "$DEVENV_PROJECT_DIR/src/public/js"
+ __touch "$DEVENV_PROJECT_DIR/src/index.js"
+ __gen_prettierconfig "$DEVENV_PROJECT_DIR" &>/dev/null
+ __gen_eslintconfig "$DEVENV_PROJECT_DIR" &>/dev/null
+ __gen_editorconfig "$DEVENV_PROJECT_DIR" &>/dev/null
+ printf_green "package.json has been generated"
+ else
+ printf_exit 1 1 "Failed to create package.json"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__setup_git() {
+ DEVENV_PROJECT_DIR="${1:-$DEVENV_PROJECT_DIR}"
+ author="$(__git_globaluser)"
+ email="$(__git_globalemail)"
+ reponame="${DEVENVMGR_DEFAULT_GITHUB_ORG:-$(__git_globaluser | sed 's| |_|g')}"
+ DEVENV_PROJECT_BASE="${DEVENV_PROJECT_NAME:-$(basename $(realpath "$DEVENV_PROJECT_DIR"))}"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_git() {
+ [ -d "${1:-$DEVENV_PROJECT_DIR}/.git" ] && return
+ __setup_git ${1:-$DEVENV_PROJECT_DIR}
+ gitadmin --dir "${1:-$DEVENV_PROJECT_DIR}" setup "https://github.com/${DEVENVMGR_DEFAULT_GITHUB_ORG:-$reponame}/$DEVENV_PROJECT_NAME"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Download the repo
+__download() {
+ [ "$1" = "list" ] || [ -n "$LIST" ] && __download_list
+ local REPO="$DEVENVMGRREPO/$1"
+ local DIR="${2:-$DEVENV_PROJECT_DIR}"
+ shift $#
+ printf_blue "Attempting to download from $REPO"
+ if __urlcheck "$REPO"; then
+ git clone "$REPO" "$DIR" -q &>/dev/null
+ else
+ printf_exit "$REPO is an invalid repo!"
+ fi
+ if [ -d "$DIR/.git" ]; then
+ printf_green "The repo has successfully been cloned to $DIR"
+ else
+ printf_return 1 1 "Failed to clone the repository"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# List templates
+__download_list() {
+ local TEMPLATES="express-cors-api express-mongodb-auth jekyll-simple nuxt-full-website php-composer "
+ local TEMPLATES+="php-simple vue-template node-portfolio react-firebase-auth bootstrap create-react-app "
+ local TEMPLATES+="create-vue-app "
+ echo "$TEMPLATES" | printf_column
+ exit
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_list() {
+ local api_url="https://api.github.com/orgs/$DEVENVMGR_DEFAULT_GITHUB_ORG/repos?per_page=1000"
+ am_i_online && curl -q -H "Accept: application/vnd.github.v3+json" -LSs "$api_url" 2>/dev/null |
+ jq '.[].name' 2>/dev/null | sed 's#"##g' | grep -v 'template' || __list_available
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_composer() {
+ __cmd_exists composer && return 0
+ curl -q -LSsf "https://github.com/composer/getcomposer.org/raw/main/web/installer" 2>/dev/null | php -- --quiet --install-dir="$HOME/.local/bin" --filename=composer
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+DEFAULT_GITHUB_ORG="${DEFAULT_GITHUB_ORG:-devenvmgr}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DEVENVMGR_CONFIG_FILE="${DEVENVMGR_CONFIG_FILE:-settings.conf}"
+DEVENVMGR_CONFIG_DIR="${DEVENVMGR_CONFIG_DIR:-$HOME/.config/myscripts/devenvmgr}"
+DEVENVMGR_CONFIG_BACKUP_DIR="${DEVENVMGR_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/devenvmgr/backups}"
+DEVENVMGR_LOG_DIR="${DEVENVMGR_LOG_DIR:-$HOME/.local/log/devenvmgr}"
+DEVENVMGR_RUN_DIR="${DEVENVMGR_RUN_DIR:-$HOME/.local/run/system_scripts/$DEVENVMGR_SCRIPTS_PREFIX}"
+DEVENVMGR_TEMP_DIR="${DEVENVMGR_TEMP_DIR:-$HOME/.local/tmp/system_scripts/devenvmgr}"
+DEVENVMGR_CACHE_DIR="${DEVENVMGR_CACHE_DIR:-$HOME/.cache/devenvmgr}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DEVENVMGR_OUTPUT_COLOR_1="${DEVENVMGR_OUTPUT_COLOR_1:-33}"
+DEVENVMGR_OUTPUT_COLOR_2="${DEVENVMGR_OUTPUT_COLOR_2:-5}"
+DEVENVMGR_OUTPUT_COLOR_GOOD="${DEVENVMGR_OUTPUT_COLOR_GOOD:-2}"
+DEVENVMGR_OUTPUT_COLOR_ERROR="${DEVENVMGR_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DEVENVMGR_NOTIFY_ENABLED="${DEVENVMGR_NOTIFY_ENABLED:-yes}"
+DEVENVMGR_GOOD_NAME="${DEVENVMGR_GOOD_NAME:-Great:}"
+DEVENVMGR_ERROR_NAME="${DEVENVMGR_ERROR_NAME:-Error:}"
+DEVENVMGR_GOOD_MESSAGE="${DEVENVMGR_GOOD_MESSAGE:-No errors reported}"
+DEVENVMGR_ERROR_MESSAGE="${DEVENVMGR_ERROR_MESSAGE:-Errors were reported}"
+DEVENVMGR_NOTIFY_CLIENT_NAME="${DEVENVMGR_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DEVENVMGR_NOTIFY_CLIENT_ICON="${DEVENVMGR_NOTIFY_CLIENT_ICON:-notification-new}"
+DEVENVMGR_NOTIFY_CLIENT_URGENCY="${DEVENVMGR_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+DEVENVMGR_DEFAULT_GITHUB_ORG="${DEVENVMGR_DEFAULT_GITHUB_ORG:-$DEFAULT_GITHUB_ORG}"
+DEVENVMGR_BASEDIR="${DEVENVMGR_BASEDIR:-$HOME/.local/share/devenvmgr}"
+DEVENVMGR_GIT_PROJECT_DIR="${DEVENVMGR_GIT_PROJECT_DIR:-$HOME/Projects/devenvmgr}"
+DEVENVMGR_TEMPLATESDIR="${DEVENVMGR_TEMPLATESDIR:-$CASJAYSDEVDIR/templates}"
+DEVENVMGR_COMMAND="${DEVENVMGR_COMMAND:-}"
+DEVENVMGR_FILEMANAGER="${DEVENVMGR_FILEMANAGER:-}"
+DEVENVMGR_COMMAND_TERM="${DEVENVMGR_COMMAND_TERM:-vim}"
+DEVENVMGR_TMUX_CMD="${DEVENVMGR_TMUX_CMD:-tmux}"
+DEVENVMGR_SCREEN_CMD="${DEVENVMGR_SCREEN_CMD:-screen}"
+DEVENVMGR_TMUX_CONF="${DEVENVMGR_TMUX_CONF:-$HOME/.config/tmux/dev/tmux.conf}"
+DEVENVMGR_SCREEN_CONF="${DEVENVMGR_SCREEN_CONF:-$HOME/.config/screen/dev/singlerc}"
+DEVENVMGR_SILENT="${DEVENVMGR_SILENT:-true}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DEVENVMGR_CONFIG_DIR/$DEVENVMGR_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DEVENVMGR_CONFIG_DIR/$DEVENVMGR_CONFIG_FILE" ] && . "$DEVENVMGR_CONFIG_DIR/$DEVENVMGR_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DEVENVMGR_RUN_DIR" ] || mkdir -p "$DEVENVMGR_RUN_DIR" |& __devnull
+[ -d "$DEVENVMGR_LOG_DIR" ] || mkdir -p "$DEVENVMGR_LOG_DIR" |& __devnull
+[ -d "$DEVENVMGR_TEMP_DIR" ] || mkdir -p "$DEVENVMGR_TEMP_DIR" |& __devnull
+[ -d "$DEVENVMGR_CACHE_DIR" ] || mkdir -p "$DEVENVMGR_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DEVENVMGR_TEMP_FILE="${DEVENVMGR_TEMP_FILE:-$(mktemp $DEVENVMGR_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DEVENVMGR_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DEVENVMGR_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DEVENVMGR_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DEVENVMGR_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DEVENVMGR_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DEVENVMGR_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=",start:,list,all,template"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="available deno django download editorconfig eslint express html hugo import jekyll "
+ARRAY+="laravel mevn node package perl php prettier python react ruby shellcheck static tsconfig "
+ARRAY+="vue "
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DEVENVMGR_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ DEVENVMGR_CWD="$2"
+ [ -d "$DEVENVMGR_CWD" ] || mkdir -p "$DEVENVMGR_CWD" |& __devnull
+ shift 2
+ ;;
+ --start)
+ shift 1
+ __start_servers "$1"
+ exit $?
+ ;;
+ --list)
+ shift 1
+ LIST="true"
+ ;;
+ --all)
+ shift 1
+ GET_ALL="true"
+ ;;
+ --template)
+ shift 1
+ TEMPLATE="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DEVENVMGR_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DEVENVMGR_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+[ -d "$1" ] && __is_an_option "$1" && DEVENVMGR_CWD="$1" && shift 1 || DEVENVMGR_CWD="${DEVENVMGR_CWD:-$PWD}"
+DEVENVMGR_CWD="$(realpath "${DEVENVMGR_CWD:-$PWD}" 2>/dev/null)"
+if [ -d "$DEVENVMGR_CWD" ] && cd "$DEVENVMGR_CWD"; then
+ if [ "$DEVENVMGR_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+ true
+ #printf_cyan "Setting working dir to $DEVENVMGR_CWD"
+ fi
+else
+ printf_exit "💔 $DEVENVMGR_CWD does not exist 💔"
+fi
+export DEVENVMGR_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -n "$1" ] && DEVENVMG_PROGRAM_NAME="$1" && shift 1
+[ "$1" = "." ] && DEVENV_PROJECT_DIR="$PWD" && shift 1
+[ "$1" = "$PWD" ] && DEVENV_PROJECT_DIR="$PWD" && shift 1
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$DEVENVMG_PROGRAM_NAME" in
+available)
+ shift 1
+ __api_list
+ exit $?
+ ;;
+import)
+ __run_import_site
+ ;;
+static)
+ shift 1
+ __run_static_site "$@"
+ ;;
+jekyll)
+ shift 1
+ __run_jekyll "$@"
+ ;;
+hugo)
+ shift 1
+ __run_hugo "$@"
+ ;;
+ruby)
+ shift 1
+ __run_ruby "$@"
+ ;;
+python)
+ shift 1
+ __run_python "$@"
+ ;;
+django)
+ shift 1
+ __run_django "$@"
+ ;;
+perl)
+ shift 1
+ __run_perl "$@"
+ ;;
+php)
+ shift 1
+ __run_php "$@"
+ ;;
+laravel)
+ shift 1
+ __run_laravel "$@"
+ ;;
+deno)
+ shift 1
+ __run_deno "$@"
+ ;;
+node)
+ shift 1
+ __run_node "$@"
+ ;;
+vue)
+ shift 1
+ __run_vuecli "$@"
+ ;;
+react)
+ shift 1
+ __run_reactcli "$@"
+ ;;
+express)
+ shift 1
+ __run_expresscli "$@"
+ ;;
+create-project)
+ shift 1
+ __run_create-project "$@"
+ ;;
+mevn)
+ shift 1
+ __run_mevn "$@"
+ ;;
+html)
+ shift 1
+ __run_html "$@"
+ ;;
+package)
+ shift 1
+ __set_sitedir && __gen_nodeconfig "$@"
+ ;;
+prettier)
+ shift 1
+ __set_sitedir && __gen_prettierconfig "$@"
+ ;;
+eslint)
+ shift 1
+ __set_sitedir && __gen_eslintconfig "$@"
+ ;;
+tsconfig)
+ shift 1
+ __set_sitedir && __gen_tsconfig "$@"
+ ;;
+editorconfig)
+ shift 1
+ __set_sitedir && __gen_editorconfig "$@"
+ ;;
+shellcheck)
+ shift 1
+ __set_sitedir && __gen_shellcheck "$@"
+ ;;
+download)
+ shift 1
+ if [ $# = 2 ]; then
+ __download "$1" "$2"
+ elif [ $GET_ALL = "true" ]; then
+ for repo in $(__api_list); do
+ __download "$repo" "$DEVENVMGR_GIT_PROJECT_DIR/$repo"
+ done
+ else
+ __set_sitedir && __download "$@"
+ fi
+ ;;
+*)
+ __help "$@"
+ ;;
+esac
+__run_git "$DEVENV_PROJECT_DIR"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/devhints b/bin/devhints
new file mode 100755
index 000000000..6daff29d9
--- /dev/null
+++ b/bin/devhints
@@ -0,0 +1,579 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208051123-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : devhints --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 11:23 EDT
+# @@File : devhints
+# @@Description : search devhints.io
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208051123-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DEVHINTS_REQUIRE_SUDO="${DEVHINTS_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DEVHINTS_CONFIG_DIR/$DEVHINTS_CONFIG_FILE"
+ fi
+ [ -d "$DEVHINTS_CONFIG_DIR" ] || mkdir -p "$DEVHINTS_CONFIG_DIR"
+ [ -d "$DEVHINTS_CONFIG_BACKUP_DIR" ] || mkdir -p "$DEVHINTS_CONFIG_BACKUP_DIR"
+ [ -f "$DEVHINTS_CONFIG_DIR/$DEVHINTS_CONFIG_FILE" ] &&
+ cp -Rf "$DEVHINTS_CONFIG_DIR/$DEVHINTS_CONFIG_FILE" "$DEVHINTS_CONFIG_BACKUP_DIR/$DEVHINTS_CONFIG_FILE.$$"
+ cat <"$DEVHINTS_CONFIG_DIR/$DEVHINTS_CONFIG_FILE"
+# Settings for devhints
+DEVHINTS_URL_RAW="${DEVHINTS_URL_RAW:-}"
+DEVHINTS_URL_API="${DEVHINTS_URL_API:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DEVHINTS_OUTPUT_COLOR_1="${DEVHINTS_OUTPUT_COLOR_1:-}"
+DEVHINTS_OUTPUT_COLOR_2="${DEVHINTS_OUTPUT_COLOR_2:-}"
+DEVHINTS_OUTPUT_COLOR_GOOD="${DEVHINTS_OUTPUT_COLOR_GOOD:-}"
+DEVHINTS_OUTPUT_COLOR_ERROR="${DEVHINTS_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DEVHINTS_NOTIFY_ENABLED="${DEVHINTS_NOTIFY_ENABLED:-}"
+DEVHINTS_GOOD_NAME="${DEVHINTS_GOOD_NAME:-}"
+DEVHINTS_ERROR_NAME="${DEVHINTS_ERROR_NAME:-}"
+DEVHINTS_GOOD_MESSAGE="${DEVHINTS_GOOD_MESSAGE:-}"
+DEVHINTS_ERROR_MESSAGE="${DEVHINTS_ERROR_MESSAGE:-}"
+DEVHINTS_NOTIFY_CLIENT_NAME="${DEVHINTS_NOTIFY_CLIENT_NAME:-}"
+DEVHINTS_NOTIFY_CLIENT_ICON="${DEVHINTS_NOTIFY_CLIENT_ICON:-}"
+DEVHINTS_NOTIFY_CLIENT_URGENCY="${DEVHINTS_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DEVHINTS_CONFIG_DIR/$DEVHINTS_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DEVHINTS_CONFIG_DIR/$DEVHINTS_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "devhints: search devhints.io - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: devhints [options] [commands] [query]"
+ __printf_line "[query] - Search for [query]"
+ __printf_line "search [query] - Search for query"
+ __printf_line "list - Lists the hints"
+ __printf_line "--refresh - Updates the devhints files"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DEVHINTS_REQUIRE_SUDO" = "yes" ] && [ -z "$DEVHINTS_REQUIRE_SUDO_RUN" ]; then
+ export DEVHINTS_REQUIRE_SUDO="no"
+ export DEVHINTS_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DEVHINTS_TEMP_FILE" ] && rm -Rf "$DEVHINTS_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__create_local() { true; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__refresh() {
+ query="${1:-query}"
+ name="$(basename -- "$query")"
+ DEVHINTS_CACHE_FILE="${DEVHINTS_CACHE_FILE:-$DEVHINTS_CONFIG_DIR/files/$name}"
+ { [ -n "$FORCE_REFRESH" ] || [ ! -e "$DEVHINTS_CACHE_FILE" ]; } && find_tools "$@"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+find_tools() {
+ query="${1:-query}"
+ name="$(basename -- "$query")"
+ DEVHINTS_CACHE_FILE="${DEVHINTS_CACHE_FILE:-$DEVHINTS_CONFIG_DIR/files/$name}"
+ if [ -f "$DEVHINTS_CACHE_FILE" ]; then
+ printf_cyan "loading $name from cache"
+ else
+ printf_yellow "Grabbing ${1:-$RAW_MD_URL}"
+ wget -qO- --server-response=no -nv "${1:-$RAW_MD_URL}" 2>/dev/null | sed -e '/^{: /d' >"$DEVHINTS_CACHE_FILE"
+ fi
+ [ -s "$DEVHINTS_CACHE_FILE" ] || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__find_api() {
+ curl -q -LSs "$DEVHINTS_URL_API" | jq -r '.[].name' |
+ grep '\.md' | sed 's|\.md||g' | grep '^'
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DEVHINTS_CONFIG_FILE="${DEVHINTS_CONFIG_FILE:-settings.conf}"
+DEVHINTS_CONFIG_DIR="${DEVHINTS_CONFIG_DIR:-$HOME/.config/myscripts/devhints}"
+DEVHINTS_CONFIG_BACKUP_DIR="${DEVHINTS_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/devhints/backups}"
+DEVHINTS_LOG_DIR="${DEVHINTS_LOG_DIR:-$HOME/.local/log/devhints}"
+DEVHINTS_TEMP_DIR="${DEVHINTS_TEMP_DIR:-$HOME/.local/tmp/system_scripts/devhints}"
+DEVHINTS_CACHE_DIR="${DEVHINTS_CACHE_DIR:-$HOME/.cache/devhints}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DEVHINTS_OUTPUT_COLOR_1="${DEVHINTS_OUTPUT_COLOR_1:-33}"
+DEVHINTS_OUTPUT_COLOR_2="${DEVHINTS_OUTPUT_COLOR_2:-5}"
+DEVHINTS_OUTPUT_COLOR_GOOD="${DEVHINTS_OUTPUT_COLOR_GOOD:-2}"
+DEVHINTS_OUTPUT_COLOR_ERROR="${DEVHINTS_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DEVHINTS_NOTIFY_ENABLED="${DEVHINTS_NOTIFY_ENABLED:-yes}"
+DEVHINTS_GOOD_NAME="${DEVHINTS_GOOD_NAME:-Great:}"
+DEVHINTS_ERROR_NAME="${DEVHINTS_ERROR_NAME:-Error:}"
+DEVHINTS_GOOD_MESSAGE="${DEVHINTS_GOOD_MESSAGE:-No errors reported}"
+DEVHINTS_ERROR_MESSAGE="${DEVHINTS_ERROR_MESSAGE:-Errors were reported}"
+DEVHINTS_NOTIFY_CLIENT_NAME="${DEVHINTS_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DEVHINTS_NOTIFY_CLIENT_ICON="${DEVHINTS_NOTIFY_CLIENT_ICON:-notification-new}"
+DEVHINTS_NOTIFY_CLIENT_URGENCY="${DEVHINTS_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+DEVHINTS_URL_RAW="${DEVHINTS_URL_RAW:-https://github.com/rstacruz/cheatsheets/raw/master}"
+DEVHINTS_URL_API="${DEVHINTS_URL_API:-https://api.github.com/repos/rstacruz/cheatsheets/contents}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DEVHINTS_CONFIG_DIR/$DEVHINTS_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DEVHINTS_CONFIG_DIR/$DEVHINTS_CONFIG_FILE" ] && . "$DEVHINTS_CONFIG_DIR/$DEVHINTS_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DEVHINTS_LOG_DIR" ] || mkdir -p "$DEVHINTS_LOG_DIR" |& __devnull
+[ -d "$DEVHINTS_TEMP_DIR" ] || mkdir -p "$DEVHINTS_TEMP_DIR" |& __devnull
+[ -d "$DEVHINTS_CACHE_DIR" ] || mkdir -p "$DEVHINTS_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DEVHINTS_TEMP_FILE="${DEVHINTS_TEMP_FILE:-$(mktemp $DEVHINTS_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DEVHINTS_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DEVHINTS_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DEVHINTS_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DEVHINTS_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DEVHINTS_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DEVHINTS_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=",refresh"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DEVHINTS_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ DEVHINTS_CWD="$2"
+ #[ -d "$DEVHINTS_CWD" ] || mkdir -p "$DEVHINTS_CWD" |& __devnull
+ shift 2
+ ;;
+ --refresh)
+ shift 1
+ FORCE_REFRESH="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DEVHINTS_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DEVHINTS_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DEVHINTS_CWD="$1" && shift 1 || DEVHINTS_CWD="${DEVHINTS_CWD:-$PWD}"
+DEVHINTS_CWD="$(realpath "${DEVHINTS_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DEVHINTS_CWD" ] && cd "$DEVHINTS_CWD"; then
+# if [ "$DEVHINTS_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DEVHINTS_CWD"
+# fi
+# else
+# printf_exit "💔 $DEVHINTS_CWD does not exist 💔"
+# fi
+export DEVHINTS_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -d "$DEVHINTS_CONFIG_DIR/files" ] || mkdir -p "$DEVHINTS_CONFIG_DIR/files"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+list)
+ shift 1
+ __find_api | printf_column $DEVHINTS_OUTPUT_COLOR
+ ;;
+
+search)
+ shift 1
+ query="$1"
+ results="$(__find_api | grep -i "${query:-help}")"
+ if [[ -n "$results" ]]; then
+ printf_blue "Found the following:"
+ printf '%s\n' "$results" | printf_column $DEVHINTS_OUTPUT_COLOR
+ else
+ printf_exit "No results fount for $query"
+ fi
+ ;;
+
+*)
+ query="${1:-bash}"
+ printf_green "Finding the results for $query"
+ printf_blue "This may take a few moments............."
+ if find_tools "$DEVHINTS_URL_RAW/${query}.md"; then
+ mdless "$DEVHINTS_CACHE_FILE" 2>/dev/null
+ else
+ printf_red "No cheat sheet found!"
+ fi
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/dfmgr b/bin/dfmgr
new file mode 100755
index 000000000..149e4144e
--- /dev/null
+++ b/bin/dfmgr
@@ -0,0 +1,450 @@
+#!/usr/bin/env bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202207042242-git
+# @Author : Jason Hempstead
+# @Contact : jason@casjaysdev.pro
+# @License : WTFPL
+# @ReadME : dfmgr --help
+# @Copyright : Copyright: (c) 2021 Jason Hempstead, CasjaysDev
+# @Created : Wednesday, Mar 31, 2021 07:10 EDT
+# @File : dfmgr
+# @Description : DotFiles ManaGeR
+# @TODO :
+# @Other :
+# @Resource :
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202103310710-git"
+USER="${SUDO_USER:-${USER}}"
+HOME="${USER_HOME:-${HOME}}"
+SRC_DIR="${BASH_SOURCE%/*}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set bash options
+if [[ "$1" == "--debug" ]]; then shift 1 && set -xo pipefail && export SCRIPT_OPTS="--debug" && export _DEBUG="on"; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 90
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# user system devenv dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+dfmgr_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__list_options() { printf_custom "$1" "$2: $(echo ${3:-$ARRAY} | __sed 's|:||g;s|'$4'| '$5'|g')" 2>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__gen_config() {
+ [[ "$INIT_CONFIG" = "TRUE" ]] || printf_green "Generating the config file in"
+ [[ "$INIT_CONFIG" = "TRUE" ]] || printf_green "$DFMGR_CONFIG_DIR/$DFMGR_CONFIG_FILE"
+ [ -d "$DFMGR_CONFIG_DIR" ] || mkdir -p "$DFMGR_CONFIG_DIR"
+ [ -d "$DFMGR_CONFIG_BACKUP_DIR" ] || mkdir -p "$DFMGR_CONFIG_BACKUP_DIR"
+ [ -f "$DFMGR_CONFIG_DIR/$DFMGR_CONFIG_FILE" ] &&
+ cp -Rf "$DFMGR_CONFIG_DIR/$DFMGR_CONFIG_FILE" "$DFMGR_CONFIG_DIR/$DFMGR_CONFIG_FILE.$$"
+ cat <"$DFMGR_CONFIG_DIR/$DFMGR_CONFIG_FILE"
+# Settings for dfmgr
+DFMGR_GIT_REPO="https://github.com/dfmgr"
+DFMGR_DOTFILES_DIR="${PERSONAL_DOTFILES_DIR:-$HOME/.local/dotfiles/personal}"
+DFMGR_FORCE_INSTALL="false"
+DFMGR_NOTIFY_ENABLED="yes"
+DFMGR_NOTIFY_CLIENT_NAME="\${NOTIFY_CLIENT_NAME:-\$APPNAME}"
+DFMGR_NOTIFY_CLIENT_ICON="\${NOTIFY_CLIENT_ICON:-\$DFMGR_NOTIFY_CLIENT_ICON}"
+DFMGR_TEMP_FILE="${TMPDIR:-/tmp}/dfmgr"
+DFMGR_CLONE_DIR="$HOME/Projects/github/dfmgr"
+EOF
+ if [ -f "$DFMGR_CONFIG_DIR/$DFMGR_CONFIG_FILE" ]; then
+ [[ "$INIT_CONFIG" = "TRUE" ]] || printf_green "Your config file for $APPNAME has been created"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ ACME_CLI_EXIT_STATUS=${ACME_CLI_EXIT_STATUS:-0}
+ [ -f "$ACME_CLI_TEMP_FILE" ] && rm -Rf "$ACME_CLI_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $ACME_CLI_EXIT_STATUS
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__gpg_import() {
+ if [ -d "$1" ]; then
+ local dir="$1"
+ local gpg="$(find $dir -type f -iname '*.gpg' 2>/dev/null | grep '^')"
+ local sec="$(find $dir -type f -iname '*.sec' 2>/dev/null | grep '^')"
+ local asc="$(find $dir -type f -iname '*.asc' 2>/dev/null | grep '^')"
+ local trust="$(find $dir -type f -iname '*.trust' 2>/dev/null | grep '^')"
+ [ -n "$gpg" ] && gpg --import "$1"/*.gpg 2>/dev/null
+ [ -n "$sec" ] && gpg --import "$1"/*.sec 2>/dev/null
+ [ -n "$asc" ] && gpg --import "$1"/*.asc 2>/dev/null
+ [ -n "$trust" ] && gpg --import-ownertrust "$1"/*.trust 2>/dev/null
+ return 0
+ else
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__download() {
+ REPO_NAME="$1"
+ REPO_URL="$DFMGR_GIT_REPO/$REPO_NAME"
+ DIR_NAME="$DFMGR_CLONE_DIR/$REPO_NAME"
+ gitadmin clone "$REPO_URL" "$DIR_NAME"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+dfprivate() {
+ local private_base=""
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+df_personal() {
+ shift 1
+ local personal_dir="${PERSONAL_DOTFILES_DIR:-$DFMGR_DOTFILES_DIR}"
+ local dir="${DOTFILES_PERSONAL:-$personal_dir}"
+ if [ -d "$dir/.git" ]; then
+ git -C "$dir" pull -q
+ fi
+ if [ -f "$dir/install.sh" ]; then
+ bash -c "$dir/install.sh"
+ return $?
+ elif [ -f "$dir/update.sh" ]; then
+ bash -c "$dir/update.sh"
+ return $?
+ else
+ printf_red "Can't install your personal dotfiles"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__list_available() { echo -e "$LIST" | tr ' ' '\n' && exit 0; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_list() {
+ local api_url="https://api.github.com/orgs/dfmgr/repos?per_page=1000"
+ am_i_online && curl -q -H "Accept: application/vnd.github.v3+json" -LSs "$api_url" 2>/dev/null |
+ jq '.[].name' 2>/dev/null | sed 's#"##g' | grep -v 'template' || __list_available
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Defaults
+exitCode="0"
+DFMGR_CONFIG_FILE="settings.conf"
+DFMGR_CONFIG_DIR="$HOME/.config/myscripts/dfmgr"
+DFMGR_CONFIG_BACKUP_DIR="$HOME/.local/share/myscripts/dfmgr/backups"
+DFMGR_OPTIONS_DIR="$HOME/.local/share/myscripts/dfmgr/options"
+DFMGR_TEMP_FILE="${TMPDIR:-/tmp}/dfmgr"
+DFMGR_NOTIFY_ENABLED="${DFMGR_NOTIFY_ENABLED:-yes}"
+DFMGR_NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$APPNAME}"
+DFMGR_NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DFMGR_NOTIFY_CLIENT_ICON}"
+DFMGR_DOTFILES_DIR="${PERSONAL_DOTFILES_DIR:-$HOME/.local/dotfiles/personal}"
+DFMGR_FORCE_INSTALL="false"
+DFMGR_GIT_REPO="https://github.com/dfmgr"
+DFMGR_CLONE_DIR="$HOME/Projects/github/dfmgr"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate non-existing config files
+[ -f "$DFMGR_CONFIG_DIR/$DFMGR_CONFIG_FILE" ] || [[ "$*" = *config ]] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DFMGR_CONFIG_DIR/$DFMGR_CONFIG_FILE" ] && . "$DFMGR_CONFIG_DIR/$DFMGR_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+# [ -d "$DFMGR_LOG_DIR" ] || mkdir -p "$DFMGR_LOG_DIR" &>/dev/null
+# [ -d "$DFMGR_TEMP_DIR" ] || mkdir -p "$DFMGR_TEMP_DIR" &>/dev/null
+# [ -d "$DFMGR_CACHE_DIR" ] || mkdir -p "$DFMGR_CACHE_DIR" &>/dev/null
+# [ -f "$DFMGR_TEMP_FILE" ] || touch "$DFMGR_TEMP_FILE" &>/dev/null
+[ -f "$DFMGR_TEMP_FILE" ] || touch "$DFMGR_TEMP_FILE" &>/dev/null
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap 'exitCode=${exitCode:-0};[ -n "$DFMGR_TEMP_FILE" ] && [ -f "$DFMGR_TEMP_FILE" ] && rm -Rf "$DFMGR_TEMP_FILE" &>/dev/null;__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+if [ "$DFMGR_NOTIFY_ENABLED" = "yes" ]; then
+ __notifications() {
+ export NOTIFY_GOOD_MESSAGE="${DFMGR_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${DFMGR_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_NAME="${DFMGR_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_ICON="${DFMGR_NOTIFY_CLIENT_ICON}"
+ notifications "$@" || return 1
+ }
+else
+ __notifications() { false; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Show warn message if variables are missing
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set additional variables/Argument/Option settings
+SETARGS="$*"
+SHORTOPTS="f,l,a"
+LONGOPTS="options,config,version,help,force,list,all,raw"
+ARRAY="personal,list,search,available,update,install,cron,version,remove,download"
+LIST="Thunar alacritty asciinema bash bashtop byobu caja castero chromium cmus deadbeef deadd "
+LIST+="dircolors dmenu dunst easytag emacs firefox fish geany git gtk-2.0 gtk-3.0 guake "
+LIST+="htop installer jgmenu lemonbar lf lua misc mpd mutt nano neofetch neovim newsboat "
+LIST+="nitrogen nodejs personal pianobar picard polybar powershell pragha qterminal ranger "
+LIST+="remmina rofi ruby sakura screen smplayer smtube st sxhkd terminology termite tig tint2 "
+LIST+="tmux transmission variety vifm vim volumeicon xfce4-terminal youtube-dl youtube-viewer ytmdl zsh "
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case $1 in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --options)
+ shift 1
+ [ -n "$1" ] || printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "5" "Short Options" "-$SHORTOPTS" ',' '-'
+ [ -z "$LONGOPTS" ] || __list_options "5" "Long Options" "--$LONGOPTS" ',' '--'
+ [ -z "$ARRAY" ] || __list_options "5" "Base Options" "$ARRAY" ',' ''
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ -f | --force)
+ shift 1
+ export FORCE_INSTALL="true"
+ ;;
+ -l | --list)
+ shift 1
+ __api_list
+ ;;
+ -a | --all)
+ shift 1
+ INSTALL_ALL="true"
+ ;;
+ --debug)
+ shift 1
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+unset setopts
+#set -- "$SETARGS"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+cmd_exists --error --ask bash || exit 1
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables
+export REPO="$DFMGR_GIT_REPO"
+export DFMGRREPO="$DFMGR_GIT_REPO"
+export APPDIR="$CONF"
+export INSTDIR="$SHARE/CasjaysDev/$SCRIPTS_PREFIX"
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case $1 in
+list)
+ shift 1
+ printf_green "All available dotfiles"
+ __list_available | printf_column '5'
+ ;;
+
+search)
+ shift 1
+ run_install_search "$@"
+ ;;
+
+available)
+ shift 1
+ if [[ "$1" = raw ]] || [[ "$SHOW_RAW" = "true" ]]; then
+ __api_list | tr '\t' '\n' | grep -Ev '^$' | sort -u | tr '\n' ' ' && echo
+ else
+ printf_cyan "All available dotfiles"
+ __api_list | sort -u | printf_column '6'
+ fi
+ ;;
+
+personal)
+ shift 1
+ df_personal && __notifications "Install/Update of personal dotfiles completed" || __notifications "Install/Update of personal dotfiles has failed"
+ ;;
+
+reset)
+ shift 1
+ printf_red "Resetting your home [This will delete everything]"
+ printf_yellow "sleeping for 5 seconds [ctrl-c cancel]" && sleep 5
+ if [ -d "$HOME/.local/dotfiles" ]; then
+ mv_f "$HOME/.local/dotfiles" /tmp/tmp-personal
+ fi
+ rm_rf "$HOME"/.*
+ rm_rf "$HOME"/*
+ cp -Rfa /etc/skel/. "$HOME/"
+ if [ -d /tmp/tmp-personal ]; then
+ mkdir -p $HOME/.local
+ mv_f /tmp/tmp-personal "$HOME/.local/dotfiles"
+ if [ -f "$HOME/.local/dotfiles/personal/install.sh" ]; then
+ bash -c "$HOME/.local/dotfiles/personal/install.sh"
+ fi
+ fi
+ getexitcode "Reset Complete"
+ ;;
+
+remove)
+ shift 1
+ if [ "$INSTALL_ALL" = "true" ]; then
+ LISTARRAY="$(ls -A "$USRUPDATEDIR" 2>/dev/null)"
+ else
+ LISTARRAY="$*"
+ fi
+ [ ${#LISTARRAY} -ne 0 ] || printf_exit "No packages selected for removal"
+ for rmf in $LISTARRAY; do
+ MESSAGE="Removing $rmf from $CONF"
+ APPNAME="$rmf"
+ installer_delete "$APPNAME"
+ echo ""
+ done
+ ;;
+
+update)
+ shift 1
+ if [ $# -eq 0 ] || [ "$INSTALL_ALL" = "true" ]; then
+ LISTARRAY="$(ls -A "$USRUPDATEDIR" 2>/dev/null)"
+ else
+ LISTARRAY="$*"
+ fi
+ if [ $# -ne 0 ]; then
+ for ins in $LISTARRAY; do
+ APPNAME="$ins"
+ run_install_update "$APPNAME"
+ done
+ elif [[ -d "$USRUPDATEDIR" ]] && [[ ${#LISTARRAY} -ne 0 ]]; then
+ for upd in $(ls "$USRUPDATEDIR"); do
+ APPNAME="$upd"
+ run_install_update "$APPNAME"
+ done
+ else
+ printf_yellow "There doesn't seem to be any packages installed"
+ __notifications "There doesn't seem to be any packages installed"
+ fi
+ exit $?
+ ;;
+
+install)
+ shift 1
+ if [ "$INSTALL_ALL" = "true" ]; then
+ LISTARRAY="$(__list_available)"
+ elif [ $# -eq 0 ]; then
+ printf_blue "No packages provide running the updater"
+ run_install_update
+ else
+ LISTARRAY="$*"
+ fi
+ for ins in $LISTARRAY; do
+ APPNAME="$ins"
+ run_install "$APPNAME"
+ done
+ exit $?
+ ;;
+
+clone | download)
+ shift 1
+ if [ "$INSTALL_ALL" = "true" ]; then
+ LISTARRAY="$(__list_available)"
+ elif [ $# -ne 0 ]; then
+ LISTARRAY="$*"
+ fi
+ if [[ -n "$LISTARRAY" ]]; then
+ for pkgs in $LISTARRAY; do
+ __download "$pkgs"
+ done
+ else
+ printf_exit "No packages selected for download"
+ fi
+ ;;
+
+cron)
+ shift 1
+ LISTARRAY="$*"
+ for cron in $LISTARRAY; do
+ APPNAME="$cron"
+ cron_updater "$APPNAME"
+ done
+ ;;
+
+version)
+ shift 1
+ LISTARRAY="$*"
+ for ver in $LISTARRAY; do
+ APPNAME="$ver"
+ run_install_version "$APPNAME"
+ done
+ ;;
+
+*)
+ __help
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/dictionary b/bin/dictionary
new file mode 100755
index 000000000..ecee2f11b
--- /dev/null
+++ b/bin/dictionary
@@ -0,0 +1,726 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208051209-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : dictionary --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 12:09 EDT
+# @@File : dictionary
+# @@Description : Thesaurus
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208051209-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DICTIONARY_REQUIRE_SUDO="${DICTIONARY_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DICTIONARY_CONFIG_DIR/$DICTIONARY_CONFIG_FILE"
+ fi
+ [ -d "$DICTIONARY_CONFIG_DIR" ] || mkdir -p "$DICTIONARY_CONFIG_DIR"
+ [ -d "$DICTIONARY_CONFIG_BACKUP_DIR" ] || mkdir -p "$DICTIONARY_CONFIG_BACKUP_DIR"
+ [ -f "$DICTIONARY_CONFIG_DIR/$DICTIONARY_CONFIG_FILE" ] &&
+ cp -Rf "$DICTIONARY_CONFIG_DIR/$DICTIONARY_CONFIG_FILE" "$DICTIONARY_CONFIG_BACKUP_DIR/$DICTIONARY_CONFIG_FILE.$$"
+ cat <"$DICTIONARY_CONFIG_DIR/$DICTIONARY_CONFIG_FILE"
+# Settings for dictionary
+DICTIONARY_YAD_WIDTH="${DICTIONARY_YAD_WIDTH:-900}"
+DICTIONARY_YAD_HEIGHT="${DICTIONARY_YAD_HEIGHT:-600}"
+DICTIONARY_PLAY_AUDIO="${DICTIONARY_PLAY_AUDIO:-}"
+DICTIONARY_SERVER_LANG="${DICTIONARY_SERVER_LANG:-}"
+DICTIONARY_SERVER_HOST="${DICTIONARY_SERVER_HOST:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DICTIONARY_OUTPUT_COLOR_1="${DICTIONARY_OUTPUT_COLOR_1:-}"
+DICTIONARY_OUTPUT_COLOR_2="${DICTIONARY_OUTPUT_COLOR_2:-}"
+DICTIONARY_OUTPUT_COLOR_GOOD="${DICTIONARY_OUTPUT_COLOR_GOOD:-}"
+DICTIONARY_OUTPUT_COLOR_ERROR="${DICTIONARY_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DICTIONARY_NOTIFY_ENABLED="${DICTIONARY_NOTIFY_ENABLED:-}"
+DICTIONARY_GOOD_NAME="${DICTIONARY_GOOD_NAME:-}"
+DICTIONARY_ERROR_NAME="${DICTIONARY_ERROR_NAME:-}"
+DICTIONARY_GOOD_MESSAGE="${DICTIONARY_GOOD_MESSAGE:-}"
+DICTIONARY_ERROR_MESSAGE="${DICTIONARY_ERROR_MESSAGE:-}"
+DICTIONARY_NOTIFY_CLIENT_NAME="${DICTIONARY_NOTIFY_CLIENT_NAME:-}"
+DICTIONARY_NOTIFY_CLIENT_ICON="${DICTIONARY_NOTIFY_CLIENT_ICON:-}"
+DICTIONARY_NOTIFY_CLIENT_URGENCY="${DICTIONARY_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DICTIONARY_CONFIG_DIR/$DICTIONARY_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DICTIONARY_CONFIG_DIR/$DICTIONARY_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "dictionary: Thesaurus - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: dictionary [options] [word]"
+ __printf_line "definition [word] - Definitions"
+ __printf_line "example [word] - Example usage"
+ __printf_line "origin [word] - Gets the origins of a word"
+ __printf_line "phonetic [word] - Get the pronunciations of a word"
+ __printf_line "antonym [word] - Get antonym for a word"
+ __printf_line "synonym [word] - Get synonyms for a word"
+ __printf_line "[word] - Outputs all the above"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DICTIONARY_REQUIRE_SUDO" = "yes" ] && [ -z "$DICTIONARY_REQUIRE_SUDO_RUN" ]; then
+ export DICTIONARY_REQUIRE_SUDO="no"
+ export DICTIONARY_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DICTIONARY_TEMP_FILE" ] && rm -Rf "$DICTIONARY_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__trap_exit_local() {
+ [ -f "${DICTIONARY_TEMP_FILE}.out" ] && rm -Rf "${DICTIONARY_TEMP_FILE}.out" &>/dev/null
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__sort_u() {
+ sort -u
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__curl_dl() {
+
+ [ $# -ne 0 ] || printf_exit "Usage: $APPNAME [word]"
+ curl -q -LSsf --max-time 2 --retry 0 "$DICTIONARY_SERVER_HOST/v2/entries/$DICTIONARY_SERVER_LANG/$1" 2>/dev/null | tee -p "${DICTIONARY_TEMP_FILE}.out" &>/dev/null
+ [ $? -eq 0 ] && api_status=0 || api_status=1
+ return ${api_status:-$?}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__play_phonetic() {
+ (
+ [ "$DICTIONARY_PLAY_AUDIO" = "yes" ] || return 0
+ phonetic_audio="$(__phonetic "$1" | grep "pronunciations/en/$search-us" | head -n1 | grep '^' || __phonetic "$1" | grep "pronunciations/en/$search" | head -n1 | grep '^' || false)"
+ if [ -n "$phonetic_audio" ]; then
+ if __cmd_exists sox; then
+ __notifications "Playing the audio from\n$phonetic_audio"
+ sox "$phonetic_audio" -d 2>/dev/null && true || false
+ fi
+ fi
+ return $?
+ ) &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__word() {
+ local api word
+ api="$([ -f "${DICTIONARY_TEMP_FILE}.out" ] && cat ${DICTIONARY_TEMP_FILE}.out | jq -r '.[].word' 2>/dev/null | grep -v '^null')"
+ word="$(echo "$api" | sed 's|^ ||g' | sed '/^$/d' | grep '^' || echo '')"
+ [ -n "$word" ] && printf '%s' "$word" || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__phonetic() {
+ local query api text audio
+ query="${1:-$(__word)}"
+ api="$([ -f "${DICTIONARY_TEMP_FILE}.out" ] && cat ${DICTIONARY_TEMP_FILE}.out | jq -r '.[].phonetics|.[]|{text:.text,audio:.audio}' 2>/dev/null)"
+ text="$(echo "$api" | jq -rc '.text' 2>/dev/null | sed 's|^ ||g' | sed '/^$/d' | grep -v '^null' | __sort_u | grep '^' || echo '')"
+ audio="$(echo "$api" | jq -rc '.audio' 2>/dev/null | sed 's|^ ||g' | sed '/^$/d' | grep -v '^null' | __sort_u | grep '^' || echo '')"
+ [ -n "$text" ] && printf '# Phonetic text for %s\n%s\n\n' "$query" "$text"
+ [ -n "$audio" ] && printf '# phonetics audio for %s\n%s\n' "$query" "$audio"
+ { [ -n "$text" ] || [ -n "$audio" ]; } && printf '# End phonetics\n' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__definition() {
+ local query api definition
+ query="${1:-$(__word)}"
+ api="$([ -f "${DICTIONARY_TEMP_FILE}.out" ] && cat ${DICTIONARY_TEMP_FILE}.out | jq -r '.[].meanings|.[].definitions|.[].definition' 2>/dev/null | grep -v '^null' | grep '^')"
+ definition="$(echo "$api" | sed 's|^ ||g' | sed '/^$/d' | grep '^' || echo '')"
+ [ -n "$definition" ] && printf '# definitions for %s\n%s\n' "$query" "$definition" && printf '# End definitions\n' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__synonym() {
+ local query api synonyms
+ query="${1:-$(__word)}"
+ api="$([ -f "${DICTIONARY_TEMP_FILE}.out" ] && cat ${DICTIONARY_TEMP_FILE}.out | jq -r '.[].meanings|.[].synonyms|.[]' 2>/dev/null | grep -v '^null' | grep '^')"
+ synonyms="$(echo "$api" | tr ' ' '\n' | sort -u | sed '/^$/d' | grep '^' || echo '')"
+ [ -n "$synonyms" ] && printf '# synonyms for %s\n%s\n' "$query" "$synonyms" && printf '# End synonyms\n' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__antonym() {
+ local query api antonyms
+ query="${1:-$(__word)}"
+ api="$([ -f "${DICTIONARY_TEMP_FILE}.out" ] && cat ${DICTIONARY_TEMP_FILE}.out | jq -r '.[].meanings|.[]|.antonyms|.[]' 2>/dev/null | grep -v '^null' | grep '^')"
+ antonyms="$(echo "$api" | tr ' ' '\n' | sort -u | sed '/^$/d' | grep '^' || echo '')"
+ [ -n "$antonyms" ] && printf '# antonyms for %s\n%s\n' "$query" "$antonyms" && printf '# End antonyms\n' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__origin() {
+ local query api origin
+ query="${1:-$(__word)}"
+ api="$([ -f "${DICTIONARY_TEMP_FILE}.out" ] && cat ${DICTIONARY_TEMP_FILE}.out | jq -r '.[]|.meanings|.[]|.origin|.[]' 2>/dev/null | grep -v '^null' | grep '^')"
+ origin="$(echo "$api" | sed 's|^ ||g' | sed '/^$/d' | grep '^' || echo '')"
+ [ -n "$origin" ] && printf '# origins of %s\n%s\n' "$query" "$origin" && printf '# End origins\n' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__example() {
+ local query api example
+ query="${1:-$(__word)}"
+ api="$([ -f "${DICTIONARY_TEMP_FILE}.out" ] && cat ${DICTIONARY_TEMP_FILE}.out | jq -r '.[].meanings|.[].definitions|.[].example' 2>/dev/null | grep -v '^null' | grep '^')"
+ example="$(echo "$api" | sed 's|^ ||g' | sed '/^$/d' | grep '^' || echo '')"
+ [ -n "$example" ] && printf '# example usage of %s\n%s\n' "$query" "$example" && printf '# End examples\n' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__search_results() {
+ search="${1:-$search}"
+ show="$(__${action})"
+ __curl_dl "$search"
+ if [ "$api_status" -eq 0 ] && [ -n "$show" ]; then
+ { printf '%s\n' "$show"; } >"$DICTIONARY_TEMP_FILE"
+ __display
+ else
+ printf_custom $DICTIONARY_OUTPUT_COLOR_ERROR "😿 No results where found for $search 😿"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__display() {
+ if [ "$DICTIONARY_TEMP_FILE" ] && [ -s "$DICTIONARY_TEMP_FILE" ]; then
+ cat "$DICTIONARY_TEMP_FILE" | __yad__text "$search" && exitCode=0 || exitCode=1
+ else
+ echo "An error has occurred!" | __yad__text "$search"
+ exitCode=1
+ fi
+ rm -Rf "${DICTIONARY_TEMP_FILE}" "${DICTIONARY_TEMP_FILE}.out"
+ return ${exitCode:-1}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__yad__text() {
+ set -o pipefail
+ local title="$1"
+ local color="${2:-$DICTIONARY_OUTPUT_COLOR_1}"
+ local DICTIONARY_YAD_WIDTH="${DICTIONARY_YAD_WIDTH:-900}"
+ local DICTIONARY_YAD_HEIGHT="${DICTIONARY_YAD_HEIGHT:-600}"
+ if __cmd_exists yad && [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ]; then
+ cat - | yad --text-info --wrap --center --title="$title" --width=${DICTIONARY_YAD_WIDTH:-500} --height=${DICTIONARY_YAD_HEIGHT:-400} 2>/dev/null &
+ return $?
+ elif __cmd_exists yad && [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ]; then
+ cat - | zenity --text-info --title="$title" --width=${DICTIONARY_YAD_WIDTH:-500} --height=${DICTIONARY_YAD_HEIGHT:-400} 2>/dev/null &
+ return $?
+ else
+ cat - | printf_readline "$color"
+ return $?
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DICTIONARY_CONFIG_FILE="${DICTIONARY_CONFIG_FILE:-settings.conf}"
+DICTIONARY_CONFIG_DIR="${DICTIONARY_CONFIG_DIR:-$HOME/.config/myscripts/dictionary}"
+DICTIONARY_CONFIG_BACKUP_DIR="${DICTIONARY_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/dictionary/backups}"
+DICTIONARY_LOG_DIR="${DICTIONARY_LOG_DIR:-$HOME/.local/log/dictionary}"
+DICTIONARY_TEMP_DIR="${DICTIONARY_TEMP_DIR:-$HOME/.local/tmp/system_scripts/dictionary}"
+DICTIONARY_CACHE_DIR="${DICTIONARY_CACHE_DIR:-$HOME/.cache/dictionary}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DICTIONARY_OUTPUT_COLOR_1="${DICTIONARY_OUTPUT_COLOR_1:-33}"
+DICTIONARY_OUTPUT_COLOR_2="${DICTIONARY_OUTPUT_COLOR_2:-5}"
+DICTIONARY_OUTPUT_COLOR_GOOD="${DICTIONARY_OUTPUT_COLOR_GOOD:-2}"
+DICTIONARY_OUTPUT_COLOR_ERROR="${DICTIONARY_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DICTIONARY_NOTIFY_ENABLED="${DICTIONARY_NOTIFY_ENABLED:-yes}"
+DICTIONARY_GOOD_NAME="${DICTIONARY_GOOD_NAME:-Great:}"
+DICTIONARY_ERROR_NAME="${DICTIONARY_ERROR_NAME:-Error:}"
+DICTIONARY_GOOD_MESSAGE="${DICTIONARY_GOOD_MESSAGE:-No errors reported}"
+DICTIONARY_ERROR_MESSAGE="${DICTIONARY_ERROR_MESSAGE:-Errors were reported}"
+DICTIONARY_NOTIFY_CLIENT_NAME="${DICTIONARY_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DICTIONARY_NOTIFY_CLIENT_ICON="${DICTIONARY_NOTIFY_CLIENT_ICON:-notification-new}"
+DICTIONARY_NOTIFY_CLIENT_URGENCY="${DICTIONARY_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+DICTIONARY_YAD_WIDTH="${DICTIONARY_YAD_WIDTH:-900}"
+DICTIONARY_YAD_HEIGHT="${DICTIONARY_YAD_HEIGHT:-600}"
+DICTIONARY_PLAY_AUDIO="${DICTIONARY_PLAY_AUDIO:-yes}"
+DICTIONARY_SERVER_LANG="${DICTIONARY_SERVER_LANG:-en}"
+DICTIONARY_SERVER_HOST="${DICTIONARY_SERVER_HOST:-https://api.dictionaryapi.dev/api}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DICTIONARY_CONFIG_DIR/$DICTIONARY_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DICTIONARY_CONFIG_DIR/$DICTIONARY_CONFIG_FILE" ] && . "$DICTIONARY_CONFIG_DIR/$DICTIONARY_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DICTIONARY_LOG_DIR" ] || mkdir -p "$DICTIONARY_LOG_DIR" |& __devnull
+[ -d "$DICTIONARY_TEMP_DIR" ] || mkdir -p "$DICTIONARY_TEMP_DIR" |& __devnull
+[ -d "$DICTIONARY_CACHE_DIR" ] || mkdir -p "$DICTIONARY_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DICTIONARY_TEMP_FILE="${DICTIONARY_TEMP_FILE:-$(mktemp $DICTIONARY_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DICTIONARY_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DICTIONARY_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DICTIONARY_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DICTIONARY_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DICTIONARY_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DICTIONARY_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="antonym definition example origin phonetic synonym"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DICTIONARY_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DICTIONARY_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DICTIONARY_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DICTIONARY_CWD="$1" && shift 1 || DICTIONARY_CWD="${DICTIONARY_CWD:-$PWD}"
+DICTIONARY_CWD="$(realpath "${DICTIONARY_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DICTIONARY_CWD" ] && cd "$DICTIONARY_CWD"; then
+# if [ "$DICTIONARY_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DICTIONARY_CWD"
+# fi
+# else
+# printf_exit "💔 $DICTIONARY_CWD does not exist 💔"
+# fi
+export DICTIONARY_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ "$CONSOLE_APP" = "true" ] && __yad__text() { tee | printf_readline "$DICTIONARY_OUTPUT_COLOR_2"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+phonetic)
+ shift 1
+ [ $# -ne 0 ] || printf_exit 5 1 "Usage: $APPNAME phonetic [searchTerm]"
+ search="$1"
+ action="phonetic"
+ __curl_dl "$search"
+ __play_phonetic "$search"
+ __search_results "$search"
+ ;;
+definition)
+ shift 1
+ [ $# -ne 0 ] || printf_exit 5 1 "Usage: $APPNAME definition [searchTerm]"
+ search="$1"
+ action="definition"
+ __curl_dl "$search"
+ __search_results "$search"
+ ;;
+example)
+ shift 1
+ [ $# -ne 0 ] || printf_exit 5 1 "Usage: $APPNAME example [searchTerm]"
+ search="$1"
+ action="example"
+ __curl_dl "$search"
+ __search_results "$search"
+ ;;
+synonym)
+ shift 1
+ [ $# -ne 0 ] || printf_exit 5 1 "Usage: $APPNAME synonym [searchTerm]"
+ search="$1"
+ action="synonym"
+ __curl_dl "$search"
+ __search_results "$search"
+ ;;
+antonym)
+ shift 1
+ [ $# -ne 0 ] || printf_exit 5 1 "Usage: $APPNAME antonym [searchTerm]"
+ search="$1"
+ action="antonym"
+ __curl_dl "$search"
+ __search_results "$search"
+ ;;
+origin)
+ shift 1
+ [ $# -ne 0 ] || printf_exit 5 1 "Usage: $APPNAME origin [searchTerm]"
+ search="$1"
+ action="origin"
+ __curl_dl "$search"
+ __search_results "$search"
+ ;;
+*)
+ search="$1"
+ [ $# -ne 0 ] || printf_exit 5 1 "Usage: $APPNAME [searchTerm]"
+ __curl_dl "$search"
+ phonetic="$(__phonetic "$search")"
+ definition="$(__definition "$search")"
+ example="$(__example "$search")"
+ synonym="$(__synonym "$search")"
+ antonyms="$(__antonym "$search")"
+ origin="$(__origin "$search")"
+ if [ "$api_status" -eq 0 ] && [ -n "$definition" ]; then
+ {
+ [ -n "$phonetic" ] && printf '%s\n\n' "$phonetic"
+ [ -n "$definition" ] && printf '%s\n\n' "$definition"
+ [ -n "$example" ] && printf '%s\n\n' "$example"
+ [ -n "$synonym" ] && printf '%s\n\n' "$synonym"
+ [ -n "$antonyms" ] && printf '%s\n\n' "$antonyms"
+ [ -n "$origin" ] && printf '%s\n\n' "$origin"
+ } >"$DICTIONARY_TEMP_FILE"
+ __display
+ else
+ printf_custom $DICTIONARY_OUTPUT_COLOR_ERROR "😿 No results where found for $search 😿"
+ fi
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/diskusage b/bin/diskusage
new file mode 100755
index 000000000..de21cdd37
--- /dev/null
+++ b/bin/diskusage
@@ -0,0 +1,599 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202307061143-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : diskusage --help
+# @@Copyright : Copyright: (c) 2023 Jason Hempstead, Casjays Developments
+# @@Created : Thursday, Jul 06, 2023 11:43 EDT
+# @@File : diskusage
+# @@Description : See the disk usage
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202307061143-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DISKUSAGE_REQUIRE_SUDO="${DISKUSAGE_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && DISKUSAGE_EXIT_STATUS=0 || DISKUSAGE_EXIT_STATUS=1
+ return ${DISKUSAGE_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && DISKUSAGE_EXIT_STATUS=0 || DISKUSAGE_EXIT_STATUS=1
+ return ${DISKUSAGE_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ DISKUSAGE_EXIT_STATUS=0
+ [ -n "$1" ] && local DISKUSAGE_EXIT_STATUS="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && DISKUSAGE_EXIT_STATUS+=$(($DISKUSAGE_EXIT_STATUS + 0)) || DISKUSAGE_EXIT_STATUS+=$(($DISKUSAGE_EXIT_STATUS + 1))
+ done
+ [ $DISKUSAGE_EXIT_STATUS -eq 0 ] || DISKUSAGE_EXIT_STATUS=3
+ return ${DISKUSAGE_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local DISKUSAGE_EXIT_STATUS=0
+ curl -q -LSsfI --max-time 1 --retry 0 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || DISKUSAGE_EXIT_STATUS=4
+ return ${DISKUSAGE_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DISKUSAGE_CONFIG_DIR/$DISKUSAGE_CONFIG_FILE"
+ fi
+ [ -d "$DISKUSAGE_CONFIG_DIR" ] || mkdir -p "$DISKUSAGE_CONFIG_DIR"
+ [ -d "$DISKUSAGE_CONFIG_BACKUP_DIR" ] || mkdir -p "$DISKUSAGE_CONFIG_BACKUP_DIR"
+ [ -f "$DISKUSAGE_CONFIG_DIR/$DISKUSAGE_CONFIG_FILE" ] &&
+ cp -Rf "$DISKUSAGE_CONFIG_DIR/$DISKUSAGE_CONFIG_FILE" "$DISKUSAGE_CONFIG_BACKUP_DIR/$DISKUSAGE_CONFIG_FILE.$$"
+ cat <"$DISKUSAGE_CONFIG_DIR/$DISKUSAGE_CONFIG_FILE"
+# Settings for diskusage
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DISKUSAGE_OUTPUT_COLOR_1="${DISKUSAGE_OUTPUT_COLOR_1:-}"
+DISKUSAGE_OUTPUT_COLOR_2="${DISKUSAGE_OUTPUT_COLOR_2:-}"
+DISKUSAGE_OUTPUT_COLOR_GOOD="${DISKUSAGE_OUTPUT_COLOR_GOOD:-}"
+DISKUSAGE_OUTPUT_COLOR_ERROR="${DISKUSAGE_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DISKUSAGE_NOTIFY_ENABLED="${DISKUSAGE_NOTIFY_ENABLED:-}"
+DISKUSAGE_GOOD_NAME="${DISKUSAGE_GOOD_NAME:-}"
+DISKUSAGE_ERROR_NAME="${DISKUSAGE_ERROR_NAME:-}"
+DISKUSAGE_GOOD_MESSAGE="${DISKUSAGE_GOOD_MESSAGE:-}"
+DISKUSAGE_ERROR_MESSAGE="${DISKUSAGE_ERROR_MESSAGE:-}"
+DISKUSAGE_NOTIFY_CLIENT_NAME="${DISKUSAGE_NOTIFY_CLIENT_NAME:-}"
+DISKUSAGE_NOTIFY_CLIENT_ICON="${DISKUSAGE_NOTIFY_CLIENT_ICON:-}"
+DISKUSAGE_NOTIFY_CLIENT_URGENCY="${DISKUSAGE_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DISKUSAGE_CONFIG_DIR/$DISKUSAGE_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DISKUSAGE_CONFIG_DIR/$DISKUSAGE_CONFIG_FILE"
+ DISKUSAGE_EXIT_STATUS=0
+ else
+ printf_red "Failed to create the config file"
+ DISKUSAGE_EXIT_STATUS=1
+ fi
+ return ${DISKUSAGE_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "diskusage: See the disk usage - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: diskusage [options] [commands]"
+ __printf_line "* - Get usage for current dir"
+ __printf_line "show - Show all usage for directory"
+ __printf_line "percent - Show disk usage"
+ __printf_line "--maxdepth [0-9] - Set the search depth"
+ __printf_line "--simple - Only print the usage"
+ __printf_line "--dir - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__grep() { grep "$@" 2>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DISKUSAGE_REQUIRE_SUDO" = "yes" ] && [ -z "$DISKUSAGE_REQUIRE_SUDO_RUN" ]; then
+ export DISKUSAGE_REQUIRE_SUDO="no"
+ export DISKUSAGE_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ DISKUSAGE_EXIT_STATUS=$?
+ else
+ printf '%s\n' "This requires root to run"
+ DISKUSAGE_EXIT_STATUS=1
+ fi
+ return ${DISKUSAGE_EXIT_STATUS:-0}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ DISKUSAGE_EXIT_STATUS=${DISKUSAGE_EXIT_STATUS:-0}
+ [ -f "$DISKUSAGE_TEMP_FILE" ] && rm -Rf "$DISKUSAGE_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $DISKUSAGE_EXIT_STATUS
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__show_usage() {
+ local usage=""
+ local dir="$(realpath "${1:-$DISKUSAGE_CWD}")"
+ local depth="${DISKUSAGE_DEPTH:-3}"
+ [ -d "$dir" ] || printf_exit "$dir does not exist"
+ du -h --max-depth=$depth $dir 2>/dev/null | printf_readline "$DISKUSAGE_OUTPUT_COLOR_2"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_usage() {
+ local usage=""
+ local dir="$(realpath "${1:-$DISKUSAGE_CWD}")"
+ local depth="${DISKUSAGE_DEPTH:-1}"
+ [ -d "$dir" ] || printf_exit "$dir does not exist"
+ [ "$DISKUSAGE_SIMPLE" = "true" ] || printf '%b%s%b' "$YELLOW" "Getting usage for $dir : " "$GREEN"
+ usage="$(du -h --max-depth=1 $dir 2>/dev/null | tail -n1 | awk '{print $1}' | grep '^' || false)"
+ if [ -n "$usage" ]; then
+ printf '%s\n' "$usage"
+ return 0
+ else
+ printf_red "Failed to get usage"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_percentage() {
+ local usage=""
+ local mount="$(realpath "${1:-/}")"
+ [ "$DISKUSAGE_SIMPLE" = "true" ] || printf '%b%s%b' "$YELLOW" "usage for $mount : " "$GREEN"
+ usage="$(df -h | grep "$mount"$ | tr ' ' '\n' | grep '%' || false)"
+ if [ -n "$usage" ]; then
+ printf '%s\n' "$usage"
+ return 0
+ else
+ printf '%s\r' " "
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Default exit code
+DISKUSAGE_EXIT_STATUS=0
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DISKUSAGE_CONFIG_DIR="${DISKUSAGE_CONFIG_DIR:-$HOME/.config/myscripts/diskusage}"
+DISKUSAGE_CONFIG_BACKUP_DIR="${DISKUSAGE_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/diskusage/backups}"
+DISKUSAGE_LOG_DIR="${DISKUSAGE_LOG_DIR:-$HOME/.local/log/diskusage}"
+DISKUSAGE_RUN_DIR="${DISKUSAGE_RUN_DIR:-$HOME/.local/run/system_scripts/$DISKUSAGE_SCRIPTS_PREFIX}"
+DISKUSAGE_TEMP_DIR="${DISKUSAGE_TEMP_DIR:-$HOME/.local/tmp/system_scripts/diskusage}"
+DISKUSAGE_CACHE_DIR="${DISKUSAGE_CACHE_DIR:-$HOME/.cache/diskusage}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# File settings
+DISKUSAGE_CONFIG_FILE="${DISKUSAGE_CONFIG_FILE:-settings.conf}"
+DISKUSAGE_LOG_ERROR_FILE="${DISKUSAGE_LOG_ERROR_FILE:-$DISKUSAGE_LOG_DIR/error.log}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DISKUSAGE_OUTPUT_COLOR_1="${DISKUSAGE_OUTPUT_COLOR_1:-33}"
+DISKUSAGE_OUTPUT_COLOR_2="${DISKUSAGE_OUTPUT_COLOR_2:-5}"
+DISKUSAGE_OUTPUT_COLOR_GOOD="${DISKUSAGE_OUTPUT_COLOR_GOOD:-2}"
+DISKUSAGE_OUTPUT_COLOR_ERROR="${DISKUSAGE_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DISKUSAGE_NOTIFY_ENABLED="${DISKUSAGE_NOTIFY_ENABLED:-yes}"
+DISKUSAGE_GOOD_NAME="${DISKUSAGE_GOOD_NAME:-Great:}"
+DISKUSAGE_ERROR_NAME="${DISKUSAGE_ERROR_NAME:-Error:}"
+DISKUSAGE_GOOD_MESSAGE="${DISKUSAGE_GOOD_MESSAGE:-No errors reported}"
+DISKUSAGE_ERROR_MESSAGE="${DISKUSAGE_ERROR_MESSAGE:-Errors were reported}"
+DISKUSAGE_NOTIFY_CLIENT_NAME="${DISKUSAGE_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DISKUSAGE_NOTIFY_CLIENT_ICON="${DISKUSAGE_NOTIFY_CLIENT_ICON:-notification-new}"
+DISKUSAGE_NOTIFY_CLIENT_URGENCY="${DISKUSAGE_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DISKUSAGE_CONFIG_DIR/$DISKUSAGE_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DISKUSAGE_CONFIG_DIR/$DISKUSAGE_CONFIG_FILE" ] && . "$DISKUSAGE_CONFIG_DIR/$DISKUSAGE_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DISKUSAGE_RUN_DIR" ] || mkdir -p "$DISKUSAGE_RUN_DIR" |& __devnull
+[ -d "$DISKUSAGE_LOG_DIR" ] || mkdir -p "$DISKUSAGE_LOG_DIR" |& __devnull
+[ -d "$DISKUSAGE_TEMP_DIR" ] || mkdir -p "$DISKUSAGE_TEMP_DIR" |& __devnull
+[ -d "$DISKUSAGE_CACHE_DIR" ] || mkdir -p "$DISKUSAGE_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DISKUSAGE_TEMP_FILE="${DISKUSAGE_TEMP_FILE:-$(mktemp $DISKUSAGE_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DISKUSAGE_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DISKUSAGE_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DISKUSAGE_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DISKUSAGE_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DISKUSAGE_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DISKUSAGE_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent,force"
+LONGOPTS+=",maxdepth:,simple"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="percent show"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DISKUSAGE_SILENT="true"
+ ;;
+ --force)
+ shift 1
+ DISKUSAGE_FORCE="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ DISKUSAGE_CWD="$2"
+ [ -d "$DISKUSAGE_CWD" ] || mkdir -p "$DISKUSAGE_CWD" |& __devnull
+ shift 2
+ ;;
+ --simple)
+ shift 1
+ DISKUSAGE_SIMPLE="true"
+ ;;
+ --maxdepth)
+ DISKUSAGE_DEPTH="$2"
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DISKUSAGE_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DISKUSAGE_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DISKUSAGE_CWD="$1" && shift 1 || DISKUSAGE_CWD="${DISKUSAGE_CWD:-$PWD}"
+DISKUSAGE_CWD="$(realpath "${DISKUSAGE_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DISKUSAGE_CWD" ] && cd "$DISKUSAGE_CWD"; then
+# if [ "$DISKUSAGE_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DISKUSAGE_CWD"
+# fi
+# else
+# printf_exit "💔 $DISKUSAGE_CWD does not exist 💔"
+# fi
+export DISKUSAGE_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Export variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+percent)
+ shift 1
+ __get_percentage "$1"
+ DISKUSAGE_EXIT_STATUS=$?
+ ;;
+show)
+ shift 1
+ __show_usage "$1"
+ DISKUSAGE_EXIT_STATUS=$?
+ ;;
+*)
+ __get_usage "$1"
+ DISKUSAGE_EXIT_STATUS=$?
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+DISKUSAGE_EXIT_STATUS="${DISKUSAGE_EXIT_STATUS:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${DISKUSAGE_EXIT_STATUS:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/displayselect b/bin/displayselect
new file mode 100755
index 000000000..816731071
--- /dev/null
+++ b/bin/displayselect
@@ -0,0 +1,587 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208051237-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : displayselect --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 12:37 EDT
+# @@File : displayselect
+# @@Description : A UI for detecting and selecting all displays
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208051237-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DISPLAYSELECT_REQUIRE_SUDO="${DISPLAYSELECT_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DISPLAYSELECT_CONFIG_DIR/$DISPLAYSELECT_CONFIG_FILE"
+ fi
+ [ -d "$DISPLAYSELECT_CONFIG_DIR" ] || mkdir -p "$DISPLAYSELECT_CONFIG_DIR"
+ [ -d "$DISPLAYSELECT_CONFIG_BACKUP_DIR" ] || mkdir -p "$DISPLAYSELECT_CONFIG_BACKUP_DIR"
+ [ -f "$DISPLAYSELECT_CONFIG_DIR/$DISPLAYSELECT_CONFIG_FILE" ] &&
+ cp -Rf "$DISPLAYSELECT_CONFIG_DIR/$DISPLAYSELECT_CONFIG_FILE" "$DISPLAYSELECT_CONFIG_BACKUP_DIR/$DISPLAYSELECT_CONFIG_FILE.$$"
+ cat <"$DISPLAYSELECT_CONFIG_DIR/$DISPLAYSELECT_CONFIG_FILE"
+# Settings for displayselect
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DISPLAYSELECT_OUTPUT_COLOR_1="${DISPLAYSELECT_OUTPUT_COLOR_1:-}"
+DISPLAYSELECT_OUTPUT_COLOR_2="${DISPLAYSELECT_OUTPUT_COLOR_2:-}"
+DISPLAYSELECT_OUTPUT_COLOR_GOOD="${DISPLAYSELECT_OUTPUT_COLOR_GOOD:-}"
+DISPLAYSELECT_OUTPUT_COLOR_ERROR="${DISPLAYSELECT_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DISPLAYSELECT_NOTIFY_ENABLED="${DISPLAYSELECT_NOTIFY_ENABLED:-}"
+DISPLAYSELECT_GOOD_NAME="${DISPLAYSELECT_GOOD_NAME:-}"
+DISPLAYSELECT_ERROR_NAME="${DISPLAYSELECT_ERROR_NAME:-}"
+DISPLAYSELECT_GOOD_MESSAGE="${DISPLAYSELECT_GOOD_MESSAGE:-}"
+DISPLAYSELECT_ERROR_MESSAGE="${DISPLAYSELECT_ERROR_MESSAGE:-}"
+DISPLAYSELECT_NOTIFY_CLIENT_NAME="${DISPLAYSELECT_NOTIFY_CLIENT_NAME:-}"
+DISPLAYSELECT_NOTIFY_CLIENT_ICON="${DISPLAYSELECT_NOTIFY_CLIENT_ICON:-}"
+DISPLAYSELECT_NOTIFY_CLIENT_URGENCY="${DISPLAYSELECT_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DISPLAYSELECT_CONFIG_DIR/$DISPLAYSELECT_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DISPLAYSELECT_CONFIG_DIR/$DISPLAYSELECT_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "displayselect: A UI for detecting and selecting all displays - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: displayselect [options] [commands]"
+ __printf_line "* - Opens the selection menu"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DISPLAYSELECT_REQUIRE_SUDO" = "yes" ] && [ -z "$DISPLAYSELECT_REQUIRE_SUDO_RUN" ]; then
+ export DISPLAYSELECT_REQUIRE_SUDO="no"
+ export DISPLAYSELECT_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DISPLAYSELECT_TEMP_FILE" ] && rm -Rf "$DISPLAYSELECT_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+if __cmd_exists rofi; then
+ __dmenu() { rofi -theme ${ROFI_THEME:-purple} -dmenu -i -p "$1" 2>/dev/null; }
+elif __cmd_exists dmenu; then
+ __dmenu() { dmenu -i -p "$1" 2>/dev/null; }
+else
+ __dmenu() { false; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+twoscreen() {
+ # Mirror displays using native resolution of external display
+ mirror=$(printf "no\\nyes" | __dmenu "Mirror displays?")
+ if [ "$mirror" = "yes" ]; then
+ external=$(echo "$screens" | __dmenu "Optimize resolution for:")
+ internal=$(echo "$screens" | grep -v "$external")
+ res_external=$(xrandr --query | sed -n "/^$external/,/\+/p" | tail -n 1 | awk '{print $1}')
+ res_internal=$(xrandr --query | sed -n "/^$internal/,/\+/p" | tail -n 1 | awk '{print $1}')
+ res_ext_x=$(echo "$res_external" | sed 's/x.*//')
+ res_ext_y=$(echo "$res_external" | sed 's/.*x//')
+ res_int_x=$(echo "$res_internal" | sed 's/x.*//')
+ res_int_y=$(echo "$res_internal" | sed 's/.*x//')
+ scale_x=$(echo "$res_ext_x / $res_int_x" | bc -l)
+ scale_y=$(echo "$res_ext_y / $res_int_y" | bc -l)
+ xrandr --output "$external" --auto --scale 1.0x1.0 --output "$internal" --auto --same-as "$external" --scale "$scale_x"x"$scale_y"
+ else
+ primary=$(echo "$screens" | __dmenu "Select primary display:")
+ secondary=$(echo "$screens" | grep -v "$primary")
+ direction=$(printf "left\\nright" | __dmenu "What side of $primary should $secondary be on?")
+ xrandr --output "$primary" --auto --scale 1.0x1.0 --output "$secondary" --"$direction"-of "$primary" --auto --scale 1.0x1.0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+morescreen() {
+ # If multi-monitor is selected and there are more than two screens.
+ primary=$(echo "$screens" | __dmenu "Select primary display:")
+ secondary=$(echo "$screens" | grep -v "$primary" | __dmenu "Select secondary display:")
+ direction=$(printf "left\\nright" | __dmenu "What side of $primary should $secondary be on?")
+ tertiary=$(echo "$screens" | grep -v "$primary" | grep -v "$secondary" | __dmenu "Select third display:")
+ xrandr --output "$primary" --auto --output "$secondary" --"$direction"-of "$primary" --auto --output "$tertiary" --"$(printf "left\\nright" | grep -v "$direction")"-of "$primary" --auto
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+multimon() {
+ # Multi-monitor handler.
+ case "$(echo "$screens" | wc -l)" in
+ 1) xrandr $(echo "$allposs" | grep -v "$screens" | awk '{print "--output", $1, "--off"}' | tr '\n' ' ') ;;
+ 2) twoscreen ;;
+ *) morescreen ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_displayselect() {
+ local allposs="" screens="" chosen=""
+ __cmd_exists xrandr || return 1
+ allposs=$(xrandr -q 2>/dev/null | grep "connected")
+ screens=$(echo "$allposs" | grep " connected" | awk '{print $1}')
+ chosen=$(printf "%s\\nmulti-monitor\\nmanual selection\\ncancel" "$screens" | __dmenu "Select display arrangement:" || exit 1)
+ case "$chosen" in
+ "manual selection")
+ arandr 2>/dev/null
+ exit
+ ;;
+ "multi-monitor")
+ multimon
+ ;;
+ cancel)
+ exit 1
+ ;;
+ *)
+ xrandr --output "$chosen" --auto --scale 1.0x1.0 $(echo "$allposs" | grep -v "$chosen" | awk '{print "--output", $1, "--off"}' | tr '\n' ' ') 2>/dev/null
+ ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DISPLAYSELECT_CONFIG_FILE="${DISPLAYSELECT_CONFIG_FILE:-settings.conf}"
+DISPLAYSELECT_CONFIG_DIR="${DISPLAYSELECT_CONFIG_DIR:-$HOME/.config/myscripts/displayselect}"
+DISPLAYSELECT_CONFIG_BACKUP_DIR="${DISPLAYSELECT_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/displayselect/backups}"
+DISPLAYSELECT_LOG_DIR="${DISPLAYSELECT_LOG_DIR:-$HOME/.local/log/displayselect}"
+DISPLAYSELECT_TEMP_DIR="${DISPLAYSELECT_TEMP_DIR:-$HOME/.local/tmp/system_scripts/displayselect}"
+DISPLAYSELECT_CACHE_DIR="${DISPLAYSELECT_CACHE_DIR:-$HOME/.cache/displayselect}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DISPLAYSELECT_OUTPUT_COLOR_1="${DISPLAYSELECT_OUTPUT_COLOR_1:-33}"
+DISPLAYSELECT_OUTPUT_COLOR_2="${DISPLAYSELECT_OUTPUT_COLOR_2:-5}"
+DISPLAYSELECT_OUTPUT_COLOR_GOOD="${DISPLAYSELECT_OUTPUT_COLOR_GOOD:-2}"
+DISPLAYSELECT_OUTPUT_COLOR_ERROR="${DISPLAYSELECT_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DISPLAYSELECT_NOTIFY_ENABLED="${DISPLAYSELECT_NOTIFY_ENABLED:-yes}"
+DISPLAYSELECT_GOOD_NAME="${DISPLAYSELECT_GOOD_NAME:-Great:}"
+DISPLAYSELECT_ERROR_NAME="${DISPLAYSELECT_ERROR_NAME:-Error:}"
+DISPLAYSELECT_GOOD_MESSAGE="${DISPLAYSELECT_GOOD_MESSAGE:-No errors reported}"
+DISPLAYSELECT_ERROR_MESSAGE="${DISPLAYSELECT_ERROR_MESSAGE:-Errors were reported}"
+DISPLAYSELECT_NOTIFY_CLIENT_NAME="${DISPLAYSELECT_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DISPLAYSELECT_NOTIFY_CLIENT_ICON="${DISPLAYSELECT_NOTIFY_CLIENT_ICON:-notification-new}"
+DISPLAYSELECT_NOTIFY_CLIENT_URGENCY="${DISPLAYSELECT_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DISPLAYSELECT_CONFIG_DIR/$DISPLAYSELECT_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DISPLAYSELECT_CONFIG_DIR/$DISPLAYSELECT_CONFIG_FILE" ] && . "$DISPLAYSELECT_CONFIG_DIR/$DISPLAYSELECT_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DISPLAYSELECT_LOG_DIR" ] || mkdir -p "$DISPLAYSELECT_LOG_DIR" |& __devnull
+[ -d "$DISPLAYSELECT_TEMP_DIR" ] || mkdir -p "$DISPLAYSELECT_TEMP_DIR" |& __devnull
+[ -d "$DISPLAYSELECT_CACHE_DIR" ] || mkdir -p "$DISPLAYSELECT_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DISPLAYSELECT_TEMP_FILE="${DISPLAYSELECT_TEMP_FILE:-$(mktemp $DISPLAYSELECT_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DISPLAYSELECT_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DISPLAYSELECT_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DISPLAYSELECT_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DISPLAYSELECT_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DISPLAYSELECT_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DISPLAYSELECT_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DISPLAYSELECT_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ DISPLAYSELECT_CWD="$2"
+ [ -d "$DISPLAYSELECT_CWD" ] || mkdir -p "$DISPLAYSELECT_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DISPLAYSELECT_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DISPLAYSELECT_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DISPLAYSELECT_CWD="$1" && shift 1 || DISPLAYSELECT_CWD="${DISPLAYSELECT_CWD:-$PWD}"
+DISPLAYSELECT_CWD="$(realpath "${DISPLAYSELECT_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DISPLAYSELECT_CWD" ] && cd "$DISPLAYSELECT_CWD"; then
+# if [ "$DISPLAYSELECT_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DISPLAYSELECT_CWD"
+# fi
+# else
+# printf_exit "💔 $DISPLAYSELECT_CWD does not exist 💔"
+# fi
+export DISPLAYSELECT_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__execute_displayselect
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/dmenu-usb b/bin/dmenu-usb
new file mode 100755
index 000000000..44959287b
--- /dev/null
+++ b/bin/dmenu-usb
@@ -0,0 +1,687 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208052152-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : dmenu-usb --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 21:52 EDT
+# @@File : dmenu-usb
+# @@Description : dmenu prompt to unmount drives
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208052152-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DMENU_USB_REQUIRE_SUDO="${DMENU_USB_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DMENU_USB_CONFIG_DIR/$DMENU_USB_CONFIG_FILE"
+ fi
+ [ -d "$DMENU_USB_CONFIG_DIR" ] || mkdir -p "$DMENU_USB_CONFIG_DIR"
+ [ -d "$DMENU_USB_CONFIG_BACKUP_DIR" ] || mkdir -p "$DMENU_USB_CONFIG_BACKUP_DIR"
+ [ -f "$DMENU_USB_CONFIG_DIR/$DMENU_USB_CONFIG_FILE" ] &&
+ cp -Rf "$DMENU_USB_CONFIG_DIR/$DMENU_USB_CONFIG_FILE" "$DMENU_USB_CONFIG_BACKUP_DIR/$DMENU_USB_CONFIG_FILE.$$"
+ cat <"$DMENU_USB_CONFIG_DIR/$DMENU_USB_CONFIG_FILE"
+# Settings for dmenu-usb
+DMENU_USB_EXCLUDE_DRIVE="${DMENU_USB_EXCLUDE_DRIVE:-}"
+DMENU_USB_EXCLUDE_FSTYPE="${DMENU_USB_EXCLUDE_DRIVE:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DMENU_USB_OUTPUT_COLOR_1="${DMENU_USB_OUTPUT_COLOR_1:-}"
+DMENU_USB_OUTPUT_COLOR_2="${DMENU_USB_OUTPUT_COLOR_2:-}"
+DMENU_USB_OUTPUT_COLOR_GOOD="${DMENU_USB_OUTPUT_COLOR_GOOD:-}"
+DMENU_USB_OUTPUT_COLOR_ERROR="${DMENU_USB_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DMENU_USB_NOTIFY_ENABLED="${DMENU_USB_NOTIFY_ENABLED:-}"
+DMENU_USB_GOOD_NAME="${DMENU_USB_GOOD_NAME:-}"
+DMENU_USB_ERROR_NAME="${DMENU_USB_ERROR_NAME:-}"
+DMENU_USB_GOOD_MESSAGE="${DMENU_USB_GOOD_MESSAGE:-}"
+DMENU_USB_ERROR_MESSAGE="${DMENU_USB_ERROR_MESSAGE:-}"
+DMENU_USB_NOTIFY_CLIENT_NAME="${DMENU_USB_NOTIFY_CLIENT_NAME:-}"
+DMENU_USB_NOTIFY_CLIENT_ICON="${DMENU_USB_NOTIFY_CLIENT_ICON:-}"
+DMENU_USB_NOTIFY_CLIENT_URGENCY="${DMENU_USB_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DMENU_USB_CONFIG_DIR/$DMENU_USB_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DMENU_USB_CONFIG_DIR/$DMENU_USB_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "dmenu-usb: dmenu prompt to unmount drives - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: dmenu-usb [options] [commands]"
+ __printf_line " - Prompt user for action"
+ __printf_line "mount - Mount device menu"
+ __printf_line "unmount - Unmount device menu"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DMENU_USB_REQUIRE_SUDO" = "yes" ] && [ -z "$DMENU_USB_REQUIRE_SUDO_RUN" ]; then
+ export DMENU_USB_REQUIRE_SUDO="no"
+ export DMENU_USB_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DMENU_USB_TEMP_FILE" ] && rm -Rf "$DMENU_USB_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+if __cmd_exists rofi; then
+ __dmenu() { rofi -theme ${ROFI_THEME:-purple} -dmenu -i -p "$1" 2>/dev/null; }
+elif __cmd_exists dmenu; then
+ __dmenu() { dmenu -i -p "$1" 2>/dev/null; }
+else
+ __dmenu() { false; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__ask_option() {
+ case $(printf "Mount\\nUnmount" | __dmenu "Would you like to mount or unmount a device?") in
+ Mount) "$APPNAME" mount ;;
+ Unmount) "$APPNAME" umount ;;
+ *) exit 1 ;;
+ esac
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+unmountusb() {
+ [ -n "$drives" ] || exit 1
+ chosen="$(echo "$drives" | __dmenu "Unmount which drive?")"
+ chosen="$(echo "$chosen" | awk '{print $1}')"
+ [ -n "$chosen" ] || exit 1
+ sudo -A umount "$chosen" &>/dev/null && __notifications "💻 USB unmounting" "$chosen unmounted."
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+unmountandroid() {
+ chosen="$(awk '/simple-mtpfs/ {print $2}' /etc/mtab | __dmenu "Unmount which device?")"
+ [ -n "$chosen" ] || exit 1
+ sudo -A umount -l "$chosen" && __notifications "🤖 Android unmounting" "$chosen unmounted."
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+asktype_unmount() {
+ choice="$(printf "USB\\nAndroid" | __dmenu "Unmount a USB drive or Android device?")"
+ [ -n "$choice" ] || exit 1
+ case "$choice" in
+ USB) unmountusb ;;
+ Android) unmountandroid ;;
+ esac
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+getmount() {
+ [ -z "$chosen" ] && exit 1
+ mp="$(find "$1" 2>/dev/null | __dmenu "Type in mount point.")"
+ [ "$mp" = "" ] && exit 1
+ if [ ! -d "$mp" ]; then
+ mkdiryn=$(printf "No\\nYes" | __dmenu "$mp does not exist. Create it?")
+ if [ "$mkdiryn" = "Yes" ]; then
+ if ! mkdir -p "$mp" &>/dev/null; then
+ ask_for_password sudo true && sudo -A mkdir -p "$mp" &>/dev/null
+ fi
+ fi
+ fi
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+mountusb() {
+ chosen="$(echo "$usbdrives" | __dmenu "Mount which drive?" | awk '{print $1}')"
+ alreadymounted=$(lsblk -nrpo "name,type,mountpoint" 2>/dev/null | awk '$2=="part"&&$3!~/\/boot|\/home$|SWAP/&&length($3)>1{printf "-not \\( -path *%s -prune \\) \\ \n",$3}')
+ getmount "/mnt /media /mount /home -maxdepth 5 -type d $alreadymounted"
+ partitiontype="$(lsblk -no "fstype" "$chosen" 2>/dev/null | grep -v '^$')"
+ case "$partitiontype" in
+ "vfat")
+ ask_for_password sudo true && sudo -A mount -t vfat "$chosen" "$mp" -o rw,umask=0000 && __notifications "💻 USB mounting" "$chosen mounted to $mp." && exit 0
+ ;;
+ "ntfs")
+ ask_for_password sudo true && sudo -A mount -t ntfs "$chosen" "$mp" && __notifications "💻 USB mounting" "$chosen mounted to $mp." && exit 0
+ ;;
+ *)
+ user="$(whoami)"
+ ug="$(groups | awk '{print $1}')"
+ ask_for_password sudo true && sudo -A mount "$chosen" 2>/dev/null && __notifications "💻 USB mounting" "$chosen mounted to $mp."
+ #ask_for_password sudo true && sudo -A chown "$user":"$ug" "$mp"
+ exit $?
+ ;;
+ esac
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+mountandroid() {
+ __cmd_exists simple-mtpfs || return 1
+ chosen=$(echo "$anddrives" | __dmenu "Which Android device?" | cut -d : -f 1)
+ getmount "$HOME -maxdepth 3 -type d"
+ simple-mtpfs --device "$chosen" "$mp"
+ echo "OK" | __dmenu "Tap Allow on your phone if it asks for permission and then press enter"
+ simple-mtpfs --device "$chosen" "$mp"
+ __notifications "🤖 Android Mounting" "Android device mounted to $mp."
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+asktype_mount() {
+ case $(printf "USB\\nAndroid" | __dmenu "Mount a USB drive or Android device?") in
+ USB) mountusb ;;
+ Android) mountandroid ;;
+ esac
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__is_system_disk() {
+ local disk="${1:-$disk}"
+ local -a exclude=("${DMENU_USB_EXCLUDE_DRIVE//,/ }")
+ for disk in /mnt/shared /mnt/system /mnt/backup "${exclude[@]}"; do
+ [ "$drive" = "$disk" ] && return 0 || return 1
+ done
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__is_system_type() {
+ local disk="${1:-$disk}"
+ local -a exclude=("${DMENU_USB_EXCLUDE_FSTYPE//,/ }")
+ [ -n "$disk" ] || [ -n "${exclude[*]}" ] || return 1
+ for type in "${exclude[@]}"; do
+ grep -sh "$disk" "/etc/mtab" | grep -q "$type" && return 0 || return 1
+ done
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__no_device() {
+ __notifications "No USB drive or Android device detected"
+ exit 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_dmenu() {
+ anddrives=$(__cmd_exists simple-mtpfs && simple-mtpfs -l 2>/dev/null || false)
+ usbdrives="$(lsblk -rpo "name,type,size,mountpoint" 2>/dev/null | awk '$2=="part"&&$4==""{printf "%s (%s)\n",$1,$3}')"
+ drives=$(lsblk -nrpo "name,type,size,mountpoint" 2>/dev/null | awk '$4!~/\/boot|\/efi|\/home$|SWAP/&&length($4)>1{printf "%s (%s)\n",$4,$3}')
+ case "$1" in
+ mount)
+ shift 1
+ if [ -z "$usbdrives" ]; then
+ if [ -z "$anddrives" ]; then
+ __no_device
+ else
+ __notifications "Android device(s) detected."
+ mountandroid
+ fi
+ else
+ if [ -z "$anddrives" ]; then
+ __notifications "USB drive(s) detected."
+ mountusb
+ else
+ __notifications "Mountable USB drive(s) and Android device(s) detected."
+ asktype_mount
+ fi
+ fi
+ ;;
+ umount | unmount)
+ shift 1
+ if ! grep simple-mtpfs "/etc/mtab"; then
+ if [ -z "$drives" ] || __is_system_disk "$drive" || __is_system_type "$drive"; then
+ __notifications "No drives to unmount."
+ exit 1
+ else
+ __notifications "Unmountable USB drive detected."
+ unmountusb
+ fi
+ else
+ if [ -z "$drives" ]; then
+ __notifications "Unmountable Android device detected."
+ unmountandroid
+ else
+ __notifications "Unmountable USB drive(s) and Android device(s) detected."
+ asktype_unmount
+ fi
+ fi
+ ;;
+ *)
+ __ask_option
+ ;;
+ esac
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DMENU_USB_CONFIG_FILE="${DMENU_USB_CONFIG_FILE:-settings.conf}"
+DMENU_USB_CONFIG_DIR="${DMENU_USB_CONFIG_DIR:-$HOME/.config/myscripts/dmenu-usb}"
+DMENU_USB_CONFIG_BACKUP_DIR="${DMENU_USB_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/dmenu-usb/backups}"
+DMENU_USB_LOG_DIR="${DMENU_USB_LOG_DIR:-$HOME/.local/log/dmenu-usb}"
+DMENU_USB_TEMP_DIR="${DMENU_USB_TEMP_DIR:-$HOME/.local/tmp/system_scripts/dmenu-usb}"
+DMENU_USB_CACHE_DIR="${DMENU_USB_CACHE_DIR:-$HOME/.cache/dmenu-usb}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DMENU_USB_OUTPUT_COLOR_1="${DMENU_USB_OUTPUT_COLOR_1:-33}"
+DMENU_USB_OUTPUT_COLOR_2="${DMENU_USB_OUTPUT_COLOR_2:-5}"
+DMENU_USB_OUTPUT_COLOR_GOOD="${DMENU_USB_OUTPUT_COLOR_GOOD:-2}"
+DMENU_USB_OUTPUT_COLOR_ERROR="${DMENU_USB_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DMENU_USB_NOTIFY_ENABLED="${DMENU_USB_NOTIFY_ENABLED:-yes}"
+DMENU_USB_GOOD_NAME="${DMENU_USB_GOOD_NAME:-Great:}"
+DMENU_USB_ERROR_NAME="${DMENU_USB_ERROR_NAME:-Error:}"
+DMENU_USB_GOOD_MESSAGE="${DMENU_USB_GOOD_MESSAGE:-No errors reported}"
+DMENU_USB_ERROR_MESSAGE="${DMENU_USB_ERROR_MESSAGE:-Errors were reported}"
+DMENU_USB_NOTIFY_CLIENT_NAME="${DMENU_USB_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DMENU_USB_NOTIFY_CLIENT_ICON="${DMENU_USB_NOTIFY_CLIENT_ICON:-notification-new}"
+DMENU_USB_NOTIFY_CLIENT_URGENCY="${DMENU_USB_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DMENU_USB_CONFIG_DIR/$DMENU_USB_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DMENU_USB_CONFIG_DIR/$DMENU_USB_CONFIG_FILE" ] && . "$DMENU_USB_CONFIG_DIR/$DMENU_USB_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DMENU_USB_LOG_DIR" ] || mkdir -p "$DMENU_USB_LOG_DIR" |& __devnull
+[ -d "$DMENU_USB_TEMP_DIR" ] || mkdir -p "$DMENU_USB_TEMP_DIR" |& __devnull
+[ -d "$DMENU_USB_CACHE_DIR" ] || mkdir -p "$DMENU_USB_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DMENU_USB_TEMP_FILE="${DMENU_USB_TEMP_FILE:-$(mktemp $DMENU_USB_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DMENU_USB_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DMENU_USB_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DMENU_USB_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DMENU_USB_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DMENU_USB_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DMENU_USB_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=",mount,unmount"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DMENU_USB_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DMENU_USB_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DMENU_USB_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DMENU_USB_CWD="$1" && shift 1 || DMENU_USB_CWD="${DMENU_USB_CWD:-$PWD}"
+DMENU_USB_CWD="$(realpath "${DMENU_USB_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DMENU_USB_CWD" ] && cd "$DMENU_USB_CWD"; then
+# if [ "$DMENU_USB_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DMENU_USB_CWD"
+# fi
+# else
+# printf_exit "💔 $DMENU_USB_CWD does not exist 💔"
+# fi
+export DMENU_USB_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__execute_dmenu-usb "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/dmenuhandler b/bin/dmenuhandler
new file mode 100755
index 000000000..ec007265f
--- /dev/null
+++ b/bin/dmenuhandler
@@ -0,0 +1,527 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208051342-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : dmenuhandler --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 13:42 EDT
+# @@File : dmenuhandler
+# @@Description : Feed this script a link and it will give dmenu
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208051342-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DMENUHANDLER_REQUIRE_SUDO="${DMENUHANDLER_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DMENUHANDLER_CONFIG_DIR/$DMENUHANDLER_CONFIG_FILE"
+ fi
+ [ -d "$DMENUHANDLER_CONFIG_DIR" ] || mkdir -p "$DMENUHANDLER_CONFIG_DIR"
+ [ -d "$DMENUHANDLER_CONFIG_BACKUP_DIR" ] || mkdir -p "$DMENUHANDLER_CONFIG_BACKUP_DIR"
+ [ -f "$DMENUHANDLER_CONFIG_DIR/$DMENUHANDLER_CONFIG_FILE" ] &&
+ cp -Rf "$DMENUHANDLER_CONFIG_DIR/$DMENUHANDLER_CONFIG_FILE" "$DMENUHANDLER_CONFIG_BACKUP_DIR/$DMENUHANDLER_CONFIG_FILE.$$"
+ cat <"$DMENUHANDLER_CONFIG_DIR/$DMENUHANDLER_CONFIG_FILE"
+# Settings for dmenuhandler
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DMENUHANDLER_OUTPUT_COLOR_1="${DMENUHANDLER_OUTPUT_COLOR_1:-}"
+DMENUHANDLER_OUTPUT_COLOR_2="${DMENUHANDLER_OUTPUT_COLOR_2:-}"
+DMENUHANDLER_OUTPUT_COLOR_GOOD="${DMENUHANDLER_OUTPUT_COLOR_GOOD:-}"
+DMENUHANDLER_OUTPUT_COLOR_ERROR="${DMENUHANDLER_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DMENUHANDLER_NOTIFY_ENABLED="${DMENUHANDLER_NOTIFY_ENABLED:-}"
+DMENUHANDLER_GOOD_NAME="${DMENUHANDLER_GOOD_NAME:-}"
+DMENUHANDLER_ERROR_NAME="${DMENUHANDLER_ERROR_NAME:-}"
+DMENUHANDLER_GOOD_MESSAGE="${DMENUHANDLER_GOOD_MESSAGE:-}"
+DMENUHANDLER_ERROR_MESSAGE="${DMENUHANDLER_ERROR_MESSAGE:-}"
+DMENUHANDLER_NOTIFY_CLIENT_NAME="${DMENUHANDLER_NOTIFY_CLIENT_NAME:-}"
+DMENUHANDLER_NOTIFY_CLIENT_ICON="${DMENUHANDLER_NOTIFY_CLIENT_ICON:-}"
+DMENUHANDLER_NOTIFY_CLIENT_URGENCY="${DMENUHANDLER_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DMENUHANDLER_CONFIG_DIR/$DMENUHANDLER_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DMENUHANDLER_CONFIG_DIR/$DMENUHANDLER_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "dmenuhandler: Feed this script a link and it will give dmenu - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: dmenuhandler [options] [commands]"
+ __printf_line "* - Opens the menu"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DMENUHANDLER_REQUIRE_SUDO" = "yes" ] && [ -z "$DMENUHANDLER_REQUIRE_SUDO_RUN" ]; then
+ export DMENUHANDLER_REQUIRE_SUDO="no"
+ export DMENUHANDLER_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DMENUHANDLER_TEMP_FILE" ] && rm -Rf "$DMENUHANDLER_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+if __cmd_exists rofi; then
+ __dmenu() { rofi -theme ${ROFI_THEME:-purple} -dmenu -i -p "Open link with what program?" 2>/dev/null; }
+elif __cmd_exists dmenu; then
+ __dmenu() { dmenu -i -p "Open link with what program?" 2>/dev/null; }
+else
+ __dmenu() { false; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DMENUHANDLER_CONFIG_FILE="${DMENUHANDLER_CONFIG_FILE:-settings.conf}"
+DMENUHANDLER_CONFIG_DIR="${DMENUHANDLER_CONFIG_DIR:-$HOME/.config/myscripts/dmenuhandler}"
+DMENUHANDLER_CONFIG_BACKUP_DIR="${DMENUHANDLER_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/dmenuhandler/backups}"
+DMENUHANDLER_LOG_DIR="${DMENUHANDLER_LOG_DIR:-$HOME/.local/log/dmenuhandler}"
+DMENUHANDLER_TEMP_DIR="${DMENUHANDLER_TEMP_DIR:-$HOME/.local/tmp/system_scripts/dmenuhandler}"
+DMENUHANDLER_CACHE_DIR="${DMENUHANDLER_CACHE_DIR:-$HOME/.cache/dmenuhandler}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DMENUHANDLER_OUTPUT_COLOR_1="${DMENUHANDLER_OUTPUT_COLOR_1:-33}"
+DMENUHANDLER_OUTPUT_COLOR_2="${DMENUHANDLER_OUTPUT_COLOR_2:-5}"
+DMENUHANDLER_OUTPUT_COLOR_GOOD="${DMENUHANDLER_OUTPUT_COLOR_GOOD:-2}"
+DMENUHANDLER_OUTPUT_COLOR_ERROR="${DMENUHANDLER_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DMENUHANDLER_NOTIFY_ENABLED="${DMENUHANDLER_NOTIFY_ENABLED:-yes}"
+DMENUHANDLER_GOOD_NAME="${DMENUHANDLER_GOOD_NAME:-Great:}"
+DMENUHANDLER_ERROR_NAME="${DMENUHANDLER_ERROR_NAME:-Error:}"
+DMENUHANDLER_GOOD_MESSAGE="${DMENUHANDLER_GOOD_MESSAGE:-No errors reported}"
+DMENUHANDLER_ERROR_MESSAGE="${DMENUHANDLER_ERROR_MESSAGE:-Errors were reported}"
+DMENUHANDLER_NOTIFY_CLIENT_NAME="${DMENUHANDLER_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DMENUHANDLER_NOTIFY_CLIENT_ICON="${DMENUHANDLER_NOTIFY_CLIENT_ICON:-notification-new}"
+DMENUHANDLER_NOTIFY_CLIENT_URGENCY="${DMENUHANDLER_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DMENUHANDLER_CONFIG_DIR/$DMENUHANDLER_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DMENUHANDLER_CONFIG_DIR/$DMENUHANDLER_CONFIG_FILE" ] && . "$DMENUHANDLER_CONFIG_DIR/$DMENUHANDLER_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DMENUHANDLER_LOG_DIR" ] || mkdir -p "$DMENUHANDLER_LOG_DIR" |& __devnull
+[ -d "$DMENUHANDLER_TEMP_DIR" ] || mkdir -p "$DMENUHANDLER_TEMP_DIR" |& __devnull
+[ -d "$DMENUHANDLER_CACHE_DIR" ] || mkdir -p "$DMENUHANDLER_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DMENUHANDLER_TEMP_FILE="${DMENUHANDLER_TEMP_FILE:-$(mktemp $DMENUHANDLER_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DMENUHANDLER_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DMENUHANDLER_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DMENUHANDLER_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DMENUHANDLER_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DMENUHANDLER_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DMENUHANDLER_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DMENUHANDLER_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DMENUHANDLER_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DMENUHANDLER_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DMENUHANDLER_CWD="$1" && shift 1 || DMENUHANDLER_CWD="${DMENUHANDLER_CWD:-$PWD}"
+DMENUHANDLER_CWD="$(realpath "${DMENUHANDLER_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DMENUHANDLER_CWD" ] && cd "$DMENUHANDLER_CWD"; then
+# if [ "$DMENUHANDLER_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DMENUHANDLER_CWD"
+# fi
+# else
+# printf_exit "💔 $DMENUHANDLER_CWD does not exist 💔"
+# fi
+export DMENUHANDLER_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$(printf "copy url\\nmpv\\nmpv (loop)\\nqueue download\\n\\nqueue youtube-dl\\nfeh\\nbrowser\\nw3m\\nmpv (float)" | __dmenu)" in
+"copy url") echo "$1" | clipboard ;;
+mpv) __setsid mpv -quiet "$1" 2>/dev/null & ;;
+"mpv (loop)") __setsid mpv --input-ipc-server=/tmp/mpvsoc"$(date +%s)" -quiet --loop "$1" 2>/dev/null & ;;
+"queue download") tsp curl -LO "$1" 2>/dev/null ;;
+"queue youtube-dl") tsp youtube-dl --write-metadata -ic "$1" 2>/dev/null ;;
+browser) __setsid "$BROWSER" "$1" 2>/dev/null & ;;
+feh) __setsid feh "$1" 2>/dev/null & ;;
+w3m) w3m "$1" 2>/dev/null ;;
+"mpv (float)") __setsid mpv --input-ipc-server=/tmp/mpvsoc"$(date +%s)" --geometry=+0-0 --autofit=30% --title="mpvfloat" "$1" 2>/dev/null & ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/dmenurecord b/bin/dmenurecord
new file mode 100755
index 000000000..298d88510
--- /dev/null
+++ b/bin/dmenurecord
@@ -0,0 +1,665 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208052145-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : dmenurecord --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 21:45 EDT
+# @@File : dmenurecord
+# @@Description : Ask for recording type via dmenu
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208052145-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DMENURECORD_REQUIRE_SUDO="${DMENURECORD_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DMENURECORD_CONFIG_DIR/$DMENURECORD_CONFIG_FILE"
+ fi
+ [ -d "$DMENURECORD_CONFIG_DIR" ] || mkdir -p "$DMENURECORD_CONFIG_DIR"
+ [ -d "$DMENURECORD_CONFIG_BACKUP_DIR" ] || mkdir -p "$DMENURECORD_CONFIG_BACKUP_DIR"
+ [ -f "$DMENURECORD_CONFIG_DIR/$DMENURECORD_CONFIG_FILE" ] &&
+ cp -Rf "$DMENURECORD_CONFIG_DIR/$DMENURECORD_CONFIG_FILE" "$DMENURECORD_CONFIG_BACKUP_DIR/$DMENURECORD_CONFIG_FILE.$$"
+ cat <"$DMENURECORD_CONFIG_DIR/$DMENURECORD_CONFIG_FILE"
+# Settings for dmenurecord
+DMENURECORD_EXT="${DMENURECORD_EXT:-}"
+DMENURECORD_SAVE_DIR="${DMENURECORD_SAVE_DIR:-}"
+DMENURECORD_DATE_FMT="${DMENURECORD_DATE_FMT:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DMENURECORD_OUTPUT_COLOR_1="${DMENURECORD_OUTPUT_COLOR_1:-}"
+DMENURECORD_OUTPUT_COLOR_2="${DMENURECORD_OUTPUT_COLOR_2:-}"
+DMENURECORD_OUTPUT_COLOR_GOOD="${DMENURECORD_OUTPUT_COLOR_GOOD:-}"
+DMENURECORD_OUTPUT_COLOR_ERROR="${DMENURECORD_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DMENURECORD_NOTIFY_ENABLED="${DMENURECORD_NOTIFY_ENABLED:-}"
+DMENURECORD_GOOD_NAME="${DMENURECORD_GOOD_NAME:-}"
+DMENURECORD_ERROR_NAME="${DMENURECORD_ERROR_NAME:-}"
+DMENURECORD_GOOD_MESSAGE="${DMENURECORD_GOOD_MESSAGE:-}"
+DMENURECORD_ERROR_MESSAGE="${DMENURECORD_ERROR_MESSAGE:-}"
+DMENURECORD_NOTIFY_CLIENT_NAME="${DMENURECORD_NOTIFY_CLIENT_NAME:-}"
+DMENURECORD_NOTIFY_CLIENT_ICON="${DMENURECORD_NOTIFY_CLIENT_ICON:-}"
+DMENURECORD_NOTIFY_CLIENT_URGENCY="${DMENURECORD_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DMENURECORD_CONFIG_DIR/$DMENURECORD_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DMENURECORD_CONFIG_DIR/$DMENURECORD_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "dmenurecord: Ask for recording type via dmenu - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: dmenurecord [options] [commands]"
+ __printf_line "screencast - Record your screen"
+ __printf_line "audio - Record audio"
+ __printf_line "video - Record webcam"
+ __printf_line "stop - Stop/Kill recording"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DMENURECORD_REQUIRE_SUDO" = "yes" ] && [ -z "$DMENURECORD_REQUIRE_SUDO_RUN" ]; then
+ export DMENURECORD_REQUIRE_SUDO="no"
+ export DMENURECORD_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DMENURECORD_TEMP_FILE" ] && rm -Rf "$DMENURECORD_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__is_recording() { [ -f "$DMENURECORD_PID_FILE" ] && return 1 || return 0; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if __cmd_exists rofi; then
+ __dmenu() { rofi -theme ${ROFI_THEME:-purple} -dmenu -i -p "$1" 2>/dev/null; }
+elif __cmd_exists dmenu; then
+ __dmenu() { dmenu -i -p "$1" 2>/dev/null; }
+else
+ __dmenu() { false; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+updateicon() {
+ echo "$1" >"$DMENURECORD_TEMP_DIR/recordingicon"
+ [ -z "${STATUSBAR}" ] || pkill -RTMIN+9 "${STATUSBAR:?}"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+killrecording() {
+ recpid="$([ -f "$DMENURECORD_PID_FILE" ] && cat "$DMENURECORD_PID_FILE" | grep '^')"
+ local icons="🛑"
+ [ -n "$recpid" ] || return 0
+ # kill with SIGTERM, allowing finishing touches.
+ kill -15 "$recpid" &>/dev/null
+ [ -z "${STATUSBAR}" ] || pkill -RTMIN+9 "${STATUSBAR:?}"
+ # even after SIGTERM, ffmpeg may still run, so SIGKILL it.
+ sleep 3
+ kill -9 "$recpid" &>/dev/null
+ __notifications "Recording" "$icons Saved to:\n$DMENURECORD_SAVE_DIR"
+ updateicon "$icons"
+ rm -f "$DMENURECORD_PID_FILE"
+ exit
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+screencast() {
+ __is_recording || asktoend
+ __cmd_exists ffmpeg xdpyinfo || return 1
+ local icons="⏺️🎙️"
+ local filename="$DMENURECORD_SAVE_DIR/screencast-$DMENURECORD_DATE$DMENURECORD_EXT"
+ ffmpeg -y \
+ -f x11grab \
+ -framerate 60 \
+ -s "$(xdpyinfo | grep dimensions | awk '{print $2;}')" \
+ -i $DISPLAY \
+ -f alsa -i default \
+ -r 30 \
+ -c:v libx264rgb -crf 0 -preset ultrafast \
+ -c:a flac "$filename" &>/dev/null &
+ echo $! >"$DMENURECORD_PID_FILE"
+ __notifications "Recording" "screencast $icons"
+ updateicon "$icons"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+video() {
+ __is_recording || asktoend
+ __cmd_exists ffmpeg xdpyinfo || return 1
+ local icons="⏺️"
+ local filename="$DMENURECORD_SAVE_DIR/video-$DMENURECORD_DATE$DMENURECORD_EXT"
+ ffmpeg \
+ -f x11grab \
+ -s "$(xdpyinfo | grep dimensions | awk '{print $2;}')" \
+ -i $DISPLAY \
+ -c:v libx264 -qp 0 -r 30 "$filename" &>/dev/null &
+ echo $! >"$DMENURECORD_PID_FILE"
+ __notifications "Recording" "video $icons"
+ updateicon "$icons"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+webcamhidef() {
+ __is_recording || asktoend
+ __cmd_exists ffmpeg || return 1
+ local icons="🎥"
+ local filename="$DMENURECORD_SAVE_DIR/webcam-$DMENURECORD_DATE$DMENURECORD_EXT"
+ ffmpeg \
+ -f v4l2 \
+ -i /dev/video0 \
+ -video_size 1920x1080 "$filename" &>/dev/null &
+ echo $! >"$DMENURECORD_PID_FILE"
+ __notifications "Recording" "webcam HD $icons"
+ updateicon "🎥"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+webcam() {
+ __is_recording || asktoend
+ __cmd_exists ffmpeg || return 1
+ local icons="🎥"
+ local filename="$DMENURECORD_SAVE_DIR/webcam-$DMENURECORD_DATE$DMENURECORD_EXT"
+ ffmpeg \
+ -f v4l2 \
+ -i /dev/video0 \
+ -video_size 640x480 "$filename" &>/dev/null &
+ echo $! >"$DMENURECORD_PID_FILE"
+ __notifications "Recording" "webcam $icons"
+ updateicon "$icons"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+audio() {
+ __is_recording || asktoend
+ __cmd_exists ffmpeg || return 1
+ local icons="🎥"
+ local filename="$DMENURECORD_SAVE_DIR/audio-$DMENURECORD_DATE.flac"
+ ffmpeg \
+ -f alsa -i default \
+ -c:a flac "$filename" &>/dev/null &
+ echo $! >"$DMENURECORD_PID_FILE"
+ __notifications "Recording" "audio $icons"
+ updateicon "$icons"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+askrecording() {
+ choice=$(printf "screencast\\nvideo\\naudio\\nwebcam\\nwebcam (hi-def)" | __dmenu "Select recording style:")
+ case "$choice" in
+ screencast) screencast ;;
+ audio) audio ;;
+ video) video ;;
+ webcam) webcam ;;
+ "webcam (hi-def)") webcamhidef ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+asktoend() {
+ response=$(printf "No\\nYes" | __dmenu "Recording still active. End recording?")
+ if [ "$response" = "Yes" ]; then
+ killrecording
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DMENURECORD_CONFIG_FILE="${DMENURECORD_CONFIG_FILE:-settings.conf}"
+DMENURECORD_CONFIG_DIR="${DMENURECORD_CONFIG_DIR:-$HOME/.config/myscripts/dmenurecord}"
+DMENURECORD_CONFIG_BACKUP_DIR="${DMENURECORD_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/dmenurecord/backups}"
+DMENURECORD_LOG_DIR="${DMENURECORD_LOG_DIR:-$HOME/.local/log/dmenurecord}"
+DMENURECORD_TEMP_DIR="${DMENURECORD_TEMP_DIR:-$HOME/.local/tmp/system_scripts/dmenurecord}"
+DMENURECORD_CACHE_DIR="${DMENURECORD_CACHE_DIR:-$HOME/.cache/dmenurecord}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DMENURECORD_OUTPUT_COLOR_1="${DMENURECORD_OUTPUT_COLOR_1:-33}"
+DMENURECORD_OUTPUT_COLOR_2="${DMENURECORD_OUTPUT_COLOR_2:-5}"
+DMENURECORD_OUTPUT_COLOR_GOOD="${DMENURECORD_OUTPUT_COLOR_GOOD:-2}"
+DMENURECORD_OUTPUT_COLOR_ERROR="${DMENURECORD_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DMENURECORD_NOTIFY_ENABLED="${DMENURECORD_NOTIFY_ENABLED:-yes}"
+DMENURECORD_GOOD_NAME="${DMENURECORD_GOOD_NAME:-Great:}"
+DMENURECORD_ERROR_NAME="${DMENURECORD_ERROR_NAME:-Error:}"
+DMENURECORD_GOOD_MESSAGE="${DMENURECORD_GOOD_MESSAGE:-No errors reported}"
+DMENURECORD_ERROR_MESSAGE="${DMENURECORD_ERROR_MESSAGE:-Errors were reported}"
+DMENURECORD_NOTIFY_CLIENT_NAME="${DMENURECORD_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DMENURECORD_NOTIFY_CLIENT_ICON="${DMENURECORD_NOTIFY_CLIENT_ICON:-notification-new}"
+DMENURECORD_NOTIFY_CLIENT_URGENCY="${DMENURECORD_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+DMENURECORD_EXT="${DMENURECORD_EXT:-.mkv}"
+DMENURECORD_DATE_FMT="${DMENURECORD_DATE_FMT:-"%y%m%d-%H%M-%S"}"
+DMENURECORD_SAVE_DIR="${DMENURECORD_SAVE_DIR:-$HOME/Videos/Recordings}"
+DMENURECORD_PID_FILE="${DMENURECORD_PID_FILE:-$DMENURECORD_TEMP_DIR/recordingpid}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DMENURECORD_CONFIG_DIR/$DMENURECORD_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DMENURECORD_CONFIG_DIR/$DMENURECORD_CONFIG_FILE" ] && . "$DMENURECORD_CONFIG_DIR/$DMENURECORD_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DMENURECORD_LOG_DIR" ] || mkdir -p "$DMENURECORD_LOG_DIR" |& __devnull
+[ -d "$DMENURECORD_TEMP_DIR" ] || mkdir -p "$DMENURECORD_TEMP_DIR" |& __devnull
+[ -d "$DMENURECORD_CACHE_DIR" ] || mkdir -p "$DMENURECORD_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DMENURECORD_TEMP_FILE="${DMENURECORD_TEMP_FILE:-$(mktemp $DMENURECORD_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DMENURECORD_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DMENURECORD_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DMENURECORD_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DMENURECORD_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DMENURECORD_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DMENURECORD_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="screencast audio video stop"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DMENURECORD_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DMENURECORD_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DMENURECORD_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DMENURECORD_CWD="$1" && shift 1 || DMENURECORD_CWD="${DMENURECORD_CWD:-$PWD}"
+DMENURECORD_CWD="$(realpath "${DMENURECORD_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DMENURECORD_CWD" ] && cd "$DMENURECORD_CWD"; then
+# if [ "$DMENURECORD_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DMENURECORD_CWD"
+# fi
+# else
+# printf_exit "💔 $DMENURECORD_CWD does not exist 💔"
+# fi
+export DMENURECORD_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+DMENURECORD_DATE="$(date +"$DMENURECORD_DATE_FMT")"
+DMENURECORD_SAVE_DIR="${DMENURECORD_CWD:-$DMENURECORD_SAVE_DIR}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -d "$DMENURECORD_SAVE_DIR" ] || mkdir -p "$DMENURECORD_SAVE_DIR"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+screencast)
+ screencast
+ exitCode=$?
+ ;;
+audio)
+ audio
+ exitCode=$?
+ ;;
+video)
+ video
+ exitCode=$?
+ ;;
+kill | stop)
+ killrecording
+ exitCode=$?
+ ;;
+*)
+ [ -f "$DMENURECORD_TEMP_DIR/recordingpid" ] && asktoend && exit || askrecording
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/dockerignore b/bin/dockerignore
new file mode 100755
index 000000000..06d232253
--- /dev/null
+++ b/bin/dockerignore
@@ -0,0 +1,563 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202210021714-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : LICENSE.md
+# @@ReadME : dockerignore --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Sunday, Oct 02, 2022 17:15 EDT
+# @@File : dockerignore
+# @@Description :
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202210021714-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DOCKERIGNORE_REQUIRE_SUDO="${DOCKERIGNORE_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DOCKERIGNORE_CONFIG_DIR/$DOCKERIGNORE_CONFIG_FILE"
+ fi
+ [ -d "$DOCKERIGNORE_CONFIG_DIR" ] || mkdir -p "$DOCKERIGNORE_CONFIG_DIR"
+ [ -d "$DOCKERIGNORE_CONFIG_BACKUP_DIR" ] || mkdir -p "$DOCKERIGNORE_CONFIG_BACKUP_DIR"
+ [ -f "$DOCKERIGNORE_CONFIG_DIR/$DOCKERIGNORE_CONFIG_FILE" ] &&
+ cp -Rf "$DOCKERIGNORE_CONFIG_DIR/$DOCKERIGNORE_CONFIG_FILE" "$DOCKERIGNORE_CONFIG_BACKUP_DIR/$DOCKERIGNORE_CONFIG_FILE.$$"
+ cat <"$DOCKERIGNORE_CONFIG_DIR/$DOCKERIGNORE_CONFIG_FILE"
+# Settings for dockerignore
+DOCKERIGNORE_IGNORE_LIST="${DOCKERIGNORE_IGNORE_LIST:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DOCKERIGNORE_OUTPUT_COLOR_1="${DOCKERIGNORE_OUTPUT_COLOR_1:-}"
+DOCKERIGNORE_OUTPUT_COLOR_2="${DOCKERIGNORE_OUTPUT_COLOR_2:-}"
+DOCKERIGNORE_OUTPUT_COLOR_GOOD="${DOCKERIGNORE_OUTPUT_COLOR_GOOD:-}"
+DOCKERIGNORE_OUTPUT_COLOR_ERROR="${DOCKERIGNORE_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DOCKERIGNORE_NOTIFY_ENABLED="${DOCKERIGNORE_NOTIFY_ENABLED:-}"
+DOCKERIGNORE_GOOD_NAME="${DOCKERIGNORE_GOOD_NAME:-}"
+DOCKERIGNORE_ERROR_NAME="${DOCKERIGNORE_ERROR_NAME:-}"
+DOCKERIGNORE_GOOD_MESSAGE="${DOCKERIGNORE_GOOD_MESSAGE:-}"
+DOCKERIGNORE_ERROR_MESSAGE="${DOCKERIGNORE_ERROR_MESSAGE:-}"
+DOCKERIGNORE_NOTIFY_CLIENT_NAME="${DOCKERIGNORE_NOTIFY_CLIENT_NAME:-}"
+DOCKERIGNORE_NOTIFY_CLIENT_ICON="${DOCKERIGNORE_NOTIFY_CLIENT_ICON:-}"
+DOCKERIGNORE_NOTIFY_CLIENT_URGENCY="${DOCKERIGNORE_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DOCKERIGNORE_CONFIG_DIR/$DOCKERIGNORE_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DOCKERIGNORE_CONFIG_DIR/$DOCKERIGNORE_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "dockerignore: - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: dockerignore [options] [commands]"
+ __printf_line " - "
+ __printf_line " - "
+ __printf_line "--dir - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DOCKERIGNORE_REQUIRE_SUDO" = "yes" ] && [ -z "$DOCKERIGNORE_REQUIRE_SUDO_RUN" ]; then
+ export DOCKERIGNORE_REQUIRE_SUDO="no"
+ export DOCKERIGNORE_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DOCKERIGNORE_TEMP_FILE" ] && rm -Rf "$DOCKERIGNORE_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__trap_exit_local() {
+ return
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_default() {
+ if [ -n "$DOCKERIGNORE_IGNORE_LIST" ]; then
+ for list in $DOCKERIGNORE_IGNORE_LIST; do
+ __grep_check "$list" || __create_ignore "$list"
+ done
+ fi
+ __grep_check ".gitkeep" || __create_ignore ".gitkeep"
+ __grep_check ".gitignore" || __create_ignore ".gitignore"
+ __grep_check "node_modules/**" || __create_ignore "node_modules/**"
+ __grep_check ".node_modules/**" || __create_ignore ".node_modules/**"
+ __grep_check "**/.gitkeep" || __create_ignore "**/.gitkeep"
+ __grep_check "**/.gitignore" || __create_ignore "**/.gitignore"
+ __grep_check "**/node_modules/**" || __create_ignore "**/node_modules/**"
+ __grep_check "**/.node_modules/**" || __create_ignore "**/.node_modules/**"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__grep_check() {
+ grep -shqFwx "$1" "$DOCKERIGNORE_IGNORE_FILE" 2>/dev/null || false
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_ignore() {
+ if __grep_check "$1"; then
+ printf_yellow "Already ignoring $1"
+ else
+ printf_cyan "Adding $1 to $DOCKERIGNORE_IGNORE_FILE"
+ printf '# Tell docker to ignore %s\n%s\n' "$1" "$1" >>"$DOCKERIGNORE_IGNORE_FILE"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DOCKERIGNORE_CONFIG_FILE="${DOCKERIGNORE_CONFIG_FILE:-settings.conf}"
+DOCKERIGNORE_CONFIG_DIR="${DOCKERIGNORE_CONFIG_DIR:-$HOME/.config/myscripts/dockerignore}"
+DOCKERIGNORE_CONFIG_BACKUP_DIR="${DOCKERIGNORE_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/dockerignore/backups}"
+DOCKERIGNORE_LOG_DIR="${DOCKERIGNORE_LOG_DIR:-$HOME/.local/log/dockerignore}"
+DOCKERIGNORE_TEMP_DIR="${DOCKERIGNORE_TEMP_DIR:-$HOME/.local/tmp/system_scripts/dockerignore}"
+DOCKERIGNORE_CACHE_DIR="${DOCKERIGNORE_CACHE_DIR:-$HOME/.cache/dockerignore}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DOCKERIGNORE_OUTPUT_COLOR_1="${DOCKERIGNORE_OUTPUT_COLOR_1:-33}"
+DOCKERIGNORE_OUTPUT_COLOR_2="${DOCKERIGNORE_OUTPUT_COLOR_2:-5}"
+DOCKERIGNORE_OUTPUT_COLOR_GOOD="${DOCKERIGNORE_OUTPUT_COLOR_GOOD:-2}"
+DOCKERIGNORE_OUTPUT_COLOR_ERROR="${DOCKERIGNORE_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DOCKERIGNORE_NOTIFY_ENABLED="${DOCKERIGNORE_NOTIFY_ENABLED:-yes}"
+DOCKERIGNORE_GOOD_NAME="${DOCKERIGNORE_GOOD_NAME:-Great:}"
+DOCKERIGNORE_ERROR_NAME="${DOCKERIGNORE_ERROR_NAME:-Error:}"
+DOCKERIGNORE_GOOD_MESSAGE="${DOCKERIGNORE_GOOD_MESSAGE:-No errors reported}"
+DOCKERIGNORE_ERROR_MESSAGE="${DOCKERIGNORE_ERROR_MESSAGE:-Errors were reported}"
+DOCKERIGNORE_NOTIFY_CLIENT_NAME="${DOCKERIGNORE_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DOCKERIGNORE_NOTIFY_CLIENT_ICON="${DOCKERIGNORE_NOTIFY_CLIENT_ICON:-notification-new}"
+DOCKERIGNORE_NOTIFY_CLIENT_URGENCY="${DOCKERIGNORE_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DOCKERIGNORE_CONFIG_DIR/$DOCKERIGNORE_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DOCKERIGNORE_CONFIG_DIR/$DOCKERIGNORE_CONFIG_FILE" ] && . "$DOCKERIGNORE_CONFIG_DIR/$DOCKERIGNORE_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DOCKERIGNORE_LOG_DIR" ] || mkdir -p "$DOCKERIGNORE_LOG_DIR" |& __devnull
+[ -d "$DOCKERIGNORE_TEMP_DIR" ] || mkdir -p "$DOCKERIGNORE_TEMP_DIR" |& __devnull
+[ -d "$DOCKERIGNORE_CACHE_DIR" ] || mkdir -p "$DOCKERIGNORE_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DOCKERIGNORE_TEMP_FILE="${DOCKERIGNORE_TEMP_FILE:-$(mktemp $DOCKERIGNORE_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DOCKERIGNORE_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DOCKERIGNORE_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DOCKERIGNORE_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DOCKERIGNORE_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DOCKERIGNORE_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DOCKERIGNORE_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DOCKERIGNORE_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ DOCKERIGNORE_CWD="$2"
+ [ -d "$DOCKERIGNORE_CWD" ] || mkdir -p "$DOCKERIGNORE_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DOCKERIGNORE_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DOCKERIGNORE_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+[ -d "$1" ] && __is_an_option "$1" && DOCKERIGNORE_CWD="$1" && shift 1 || DOCKERIGNORE_CWD="${DOCKERIGNORE_CWD:-$PWD}"
+DOCKERIGNORE_CWD="$(realpath "${DOCKERIGNORE_CWD:-$PWD}" 2>/dev/null)"
+if [ -d "$DOCKERIGNORE_CWD" ] && cd "$DOCKERIGNORE_CWD"; then
+ true
+ # if [ "$DOCKERIGNORE_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+ # printf_cyan "Setting working dir to $DOCKERIGNORE_CWD"
+ # fi
+else
+ printf_exit "💔 $DOCKERIGNORE_CWD does not exist 💔"
+fi
+export DOCKERIGNORE_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+DOCKERIGNORE_IGNORE_FILE="$DOCKERIGNORE_CWD/.dockerignore"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+if [ -f "$DOCKERIGNORE_IGNORE_FILE" ]; then
+ printf_blue "Updating $DOCKERIGNORE_IGNORE_FILE"
+else
+ printf_blue "Creating $DOCKERIGNORE_IGNORE_FILE"
+ printf '# Files to ignore\n' >"$DOCKERIGNORE_IGNORE_FILE"
+fi
+__create_default
+if [ $# -ne 0 ]; then
+ for ignore in "$@"; do
+ __create_ignore "$ignore"
+ done
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/dockermgr b/bin/dockermgr
new file mode 100755
index 000000000..3ef18f077
--- /dev/null
+++ b/bin/dockermgr
@@ -0,0 +1,2627 @@
+#!/usr/bin/env bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202207042242-git
+# @Author : Jason Hempstead
+# @Contact : jason@casjaysdev.pro
+# @License : WTFPL
+# @ReadME : dockermgr --help
+# @Copyright : Copyright: (c) 2021 Jason Hempstead, Casjays Developments
+# @Created : Saturday, Aug 28, 2021 19:04 EDT
+# @File : dockermgr
+# @Description : docker script to manage containers
+# @TODO :
+# @Other :
+# @Resource :
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shell check options
+# shellcheck disable=SC1001
+# shellcheck disable=SC2003
+# shellcheck disable=SC2016
+# shellcheck disable=SC2031
+# shellcheck disable=SC2120
+# shellcheck disable=SC2155
+# shellcheck disable=SC2199
+# shellcheck disable=SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202108281904-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SRC_DIR="${BASH_SOURCE%/*}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set bash options
+if [ "$1" == "--debug" ]; then shift 1 && set -xo pipefail && export SCRIPT_OPTS="--debug" && export _DEBUG="on"; fi
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 90
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# user system devenv dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+dockermgr_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set functions
+__list_available() { echo -e "$LIST" | tr ' ' '\n' && exit 0; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_list() {
+ local api_user="$(basename -- "$DOCKERMGR_GIT_REPO" | sed 's|/||g' | grep '^' || echo 'dockermgr')"
+ local api_url="https://api.github.com/orgs/$api_user/repos?per_page=1000"
+ am_i_online && curl -q -LSs "$api_url" | jq -r '.[].name' | __jq_exclude | sort -u ||
+ __list_available
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__gen_config() {
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Generating the config file in"
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "$DOCKERMGR_CONFIG_DIR/$DOCKERMGR_CONFIG_FILE"
+ [ -d "$DOCKERMGR_CONFIG_DIR" ] || mkdir -p "$DOCKERMGR_CONFIG_DIR"
+ [ -d "$DOCKERMGR_CONFIG_BACKUP_DIR" ] || mkdir -p "$DOCKERMGR_CONFIG_BACKUP_DIR"
+ [ -f "$DOCKERMGR_CONFIG_DIR/$DOCKERMGR_CONFIG_FILE" ] &&
+ cp -Rf "$DOCKERMGR_CONFIG_DIR/$DOCKERMGR_CONFIG_FILE" "$DOCKERMGR_CONFIG_BACKUP_DIR/$DOCKERMGR_CONFIG_FILE.$$"
+ cat <"$DOCKERMGR_CONFIG_DIR/$DOCKERMGR_CONFIG_FILE"
+# Settings for dockermgr
+DOCKERMGR_GIT_USERNAME="${DOCKERMGR_GIT_USERNAME:-}"
+DOCKERMGR_REGISTRY_USERNAME="${DOCKERMGR_REGISTRY_USERNAME:-casjaysdevdocker}"
+DOCKERMGR_HOME="${DOCKERMGR_HOME:-$HOME/.config/myscripts/dockermgr}"
+DOCKERMGR_GIT_REPO="${DOCKERMGR_GIT_REPO:-https://github.com/dockermgr}"
+DOCKERMGR_GIT_SRC_REPO_NAME="${DOCKERMGR_GIT_SRC_REPO_NAME:-https://github.com/casjaysdevdocker}"
+DOCKERMGR_GIT_SRC_REPO_API="${DOCKERMGR_GIT_SRC_REPO_API:-https://api.github.com/orgs/$(basename $DOCKERMGR_GIT_SRC_REPO_NAME)/repos}"
+DOCKERMGR_CLONE_DIR="${DOCKERMGR_CLONE_DIR:-$HOME/Projects/github/dockermgr}"
+DOCKERMGR_DOCKER_BIN="${DOCKERMGR_DOCKER_BIN:-sudo -HE docker}"
+DOCKERMGR_INSTALL_SCRIPT="${DOCKERMGR_INSTALL_SCRIPT:-https://get.docker.com}"
+DOCKERMGR_K3B_INSTALL_SCRIPT="${DOCKERMGR_K3B_INSTALL_SCRIPT:-https://get.k3s.io}"
+DOCKERMGR_INSTALL_TMP="${DOCKERMGR_INSTALL_TMP:-/tmp/docker_install.sh}"
+DOCKERMGR_HUB_URL="${DOCKERMGR_HUB_URL:-https://hub.docker.com}"
+DOCKERMGR_REGISTRY_URL="${DOCKERMGR_REGISTRY_URL:-https://hub.docker.com}"
+DOCKERMGR_NET_DEVICE="${DOCKERMGR_NET_DEVICE:-}"
+DOCKERMGR_BUILD_IMAGE="${DOCKERMGR_BUILD_IMAGE:-}"
+DOCKERMGR_MANIFEST_TEMPLATE="${DOCKERMGR_MANIFEST_TEMPLATE:-}"
+# Notification settings
+DOCKERMGR_GOOD_MESSAGE="${DOCKERMGR_GOOD_MESSAGE:-Everything Went OK}"
+DOCKERMGR_ERROR_MESSAGE="${DOCKERMGR_ERROR_MESSAGE:-Well something seems to have gone wrong}"
+DOCKERMGR_NOTIFY_ENABLED="${DOCKERMGR_NOTIFY_ENABLED:-yes}"
+DOCKERMGR_NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$APPNAME}"
+DOCKERMGR_NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DOCKERMGR_NOTIFY_CLIENT_ICON}"
+
+# Colorization settings
+DOCKERMGR_OUTPUT_COLOR="${DOCKERMGR_OUTPUT_COLOR:-5}"
+DOCKERMGR_OUTPUT_COLOR_GOOD="${DOCKERMGR_OUTPUT_COLOR_GOOD:-2}"
+DOCKERMGR_OUTPUT_COLOR_ERROR="${DOCKERMGR_OUTPUT_COLOR_ERROR:-1}"
+
+EOF
+
+ if [ ! -f "$HOME/.docker/config.json" ]; then
+ mkdir -p "$HOME/.docker" &>/dev/null
+ echo '{ "auths": {} }' >"$HOME/.docker/config.json"
+ fi
+ if [ -f "$DOCKERMGR_CONFIG_DIR/$DOCKERMGR_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-$?}
+ [ -n "$DOCKERMGR_TEMP_FILE" ] && [ -f "$DOCKERMGR_TEMP_FILE" ] && rm -Rf "$DOCKERMGR_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional functions
+__cd() { \builtin cd "$1" || return 1; }
+__jq_exclude() { grep -vEw 'tools|templates|.github|community|template|docker-compose' | sort -u | grep -v 'null' | grep '^'; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_docker_cron() { printf '# Clean old docker images\n%s\n' '5 4 * * * root docker image prune -a --force >/dev/null 2>&1' | sudo tee /etc/cron.d/dockermgr >/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__disk_usage_pre() { export total_disk_usage="$(\df -k | grep '/$' | awk '{print $3}' | sed 's|[a-zA-Z]||g' | grep '^' || return 1)"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_test() { curl -q -LSsfI "$DOCKERMGR_HUB_URL/v2/repositories/$1" &>/dev/null || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__col() { awk -v col=$1 '{print $col}' | grep '^' || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker() { eval $DOCKERMGR_DOCKER_BIN "$@" 2>"$DOCKERMGR_TEMP_FILE" || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_pull() { __docker pull $DOCKER_PULL_ARG "$@" || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__rancher() { __install_script rancher || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__download_src_api() { curl -q -LSsf "$DOCKERMGR_GIT_SRC_REPO_API?page_size=1000" 2>/dev/null || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__download_src_custom_api() { curl -q -LSsf "https://api.github.com/orgs/$1/repos?page_size=1000" 2>/dev/null || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_releases_github() { curl -q -LSsf "https://api.github.com/repos/$1/releases/latest" 2>/dev/null | jq -r '.assets|.[]|.browser_download_url' 2>/dev/null || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_releases_google() { curl -q -LSsf "https://storage.googleapis.com/$1/releases/latest/$2" || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__minikube_delete() { unbuffer minikube delete -p "${@:-minikube}" | printf_readline || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__container_exists() { docker ps -a -q -f name=^$1$ | grep '^' || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__container_is_running() { __docker ps -a -q -f status=running -f name=^/$1$ | grep '^' || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__swap_status() { swapon -s 2>&1 | grep -v 'Filename.* Type' | grep -q "$1" && echo 'enabled' || false; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__grep_is_dotted() { grep -q '[a-zA-Z0-9]\.[a-zA-Z0-9][a-zA-Z0-9]' || return 1; }
+__container_name() { docker ps -a 2>&1 | grep -v ' NAMES$' | grep -Ew ''$1'|'$1'-*' | awk '{print $NF}' | grep '^' || return 1; }
+__docker_manifest_log() { [ $1 -eq 0 ] && rm -Rf "$DOCKERMGR_LOG_DIR/$2.log" || { [ -f "$DOCKERMGR_LOG_DIR/$2.log" ] && cat "$DOCKERMGR_LOG_DIR/$2.log" | printf_readline && false; } || exit 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__server_status() {
+ local url="$1"
+ local name="$2"
+ local script="$3"
+ local exitCode="0"
+ local code="$(curl -q -Ssf -kI -m 1 "$url" -o /dev/null -w "%{http_code}" 2>/dev/null | grep -E '^2[0-9][0-9]|^30[012]' || false)"
+ if [ -n "$code" ]; then
+ exitCode=0
+ else
+ if [ -n "$name" ]; then printf_red "$name is not running" >&2; fi
+ if [ -n "$script" ] && [ -x "$script" ]; then
+ eval bash "$script"
+ exitCode=$?
+ fi
+ return $exitCode
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_arch() {
+ local uname="$(uname -s)"
+ local arch="$(uname -m)"
+ { [[ "$arch" = i386* ]] && osarch="i386"; } ||
+ { [[ "$arch" = i686* ]] && osarch="i386"; } ||
+ { [ "$arch" = "x86_64" ] && osarch="amd64"; } ||
+ { [ "$arch" = "aarch64" ] && osarch="arm64"; } ||
+ { [ "$arch" = "armv7l" ] && osarch="arm"; }
+ { [ "$uname" == "Linux" ] && osname="linux"; } ||
+ { [ "$uname" == "Darwin" ] && osname="darwin"; } ||
+ { [[ "$uname" = CYGWIN* || "$uname" = MINGW* || "$uname" = MSYS* ]] && osname="windows"; }
+ [ -n "$arch" ] && [ -n "$osname" ] && export arch osname || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__update_repo_info() {
+ local image="$1" && shift
+ local token="$(<"$DOCKERMGR_CACHE_DIR/token")"
+ local info=("${@:-$description}")
+ local code=$(
+ jq -n --arg msg "${info[@]}" '{"registry":"registry-1.docker.io","full_description": $msg }' |
+ curl -q -LSs -X PATCH -H "Content-Type: application/json" -H "Authorization: Bearer ${token}" -o /dev/null -w "%{http_code}" "$DOCKERMGR_REGISTRY_URL/v2/repositories/${image}"/ -d @-
+ )
+ if [ "$code" = "200" ]; then
+ printf_green "Successfully pushed full description to Docker Hub"
+ else
+ printf_red "Unable to push full description to Docker Hub, response code: ${code}"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__registry_delete_tag() {
+ if [ -f "$DOCKERMGR_CACHE_DIR/token" ]; then
+ local TOKEN="$(<"$DOCKERMGR_CACHE_DIR/token")"
+ local log_file="$DOCKERMGR_CACHE_DIR/delete.log"
+ printf '%s' "$(printf_cyan "Attempting to delete temporary tag: $1:$2"): "
+ curl -q -LSsfi -H "Authorization: Bearer $TOKEN" -X DELETE "$DOCKERMGR_REGISTRY_URL/v2/repositories/$1/tags/$2" &>"$log_file" || return 1
+ elif __api_auth_token; then
+ __registry_delete_tag "$1" "$2"
+ else
+ printf '%b'"Can not delete $1:$2 "
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_manifest() {
+ [ -f "$DOCKERMGR_CACHE_DIR/token" ] || printf_exit "Please run $APPNAME api auth"
+ local code=0
+ local tag=""
+ local name=""
+ local amend=""
+ local tag_push=""
+ local delete_tag=""
+ local date_tag="$(date +'%y%m')"
+ local do_not_delete="$DOCKERMGER_MANIFEST_DELETE_TMP_TAGS"
+ if echo "$1" | grep -q ':'; then
+ local image="${1//:*/}"
+ local tag="${1//*:/}"
+ else
+ local image="$1"
+ local tag="latest"
+ fi
+ if echo "$2" | grep -q ':'; then
+ local push="${2//:*/}"
+ local tag_push="${2//*:/}"
+ else
+ local push="$2"
+ fi
+ name="$(basename -- "$image")"
+ description="${3:-$description}"
+ local AMEND=""
+ local ADD_TAGS="no"
+ local platforms="x86_64 arm64"
+ local base_tag="$tag"
+ local base_name="$image"
+ local base_image="$image:${tag:-latest}"
+ local pull_image="$image:${tag:-latest}"
+ local pull_image="${pull_image//::/:}"
+ local pull_from_pretty="${pull_image//:*/}"
+ local manifest_log_file="$(echo "$push" | awk -F '/' '{print $(NF-1)"-"$NF}')"
+ [ -n "$tag" ] && tag=":$tag" || tag=":latest"
+ [ -n "$tag_push" ] && tag_push=":$tag_push" || tag_push=":${DOCKERMGR_SET_TAG:-latest}"
+ [ -z "$push" ] && [ -n "$DOCKERMGR_REGISTRY_USERNAME" ] && push="$DOCKERMGR_REGISTRY_USERNAME/$name"
+ [ -n "$push" ] || printf_exit "Usage: $APPNAME manifest [image] [push]"
+ [ -n "$image" ] || printf_exit "Usage: $APPNAME manifest [image] [push]"
+ MANIFEST_TAG="$push$tag_push"
+ [ -n "$description" ] && printf_blue "$name description: $description"
+ printf_green "🔽 Running docker pull $pull_image 🔽"
+ docker pull $pull_image &>/dev/null || printf_exit "Failed to pull $pull_image"
+ if [ "$tag_push" = ":latest" ] || [ "$tag_push" = ":nightly" ] || [ "$tag_push" = ":edge" ] || [ "$tag_push" = ":devel" ]; then
+ MANIFEST_TAG="$push$tag_push $push:$date_tag"
+ fi
+ for platform in $platforms; do
+ local set_tag="$tag"
+ local new_tag="$set_tag-$platform"
+ set_push="${push//:*/}:${tag_push//*:/}-$platform"
+ printf_cyan "Attempting to build $image$tag for platform: $platform"
+ echo "FROM --platform="linux/$platform" $image$tag" | docker build --pull -t $set_push - 2>"$DOCKERMGR_LOG_DIR/$manifest_log_file.log" >/dev/null && amend+="--amend $set_push " delete_tag+="$set_push " || code=1
+ [ $code -ne 0 ] && printf_red "Failed to build $set_push" && __docker_manifest_log $code "$name"
+ printf_yellow "Pushing $set_push"
+ docker push -q $set_push >/dev/null 2>"$DOCKERMGR_LOG_DIR/$manifest_log_file.log"
+ [ $code -ne 0 ] && printf_red "Failed to build $set_push" && __docker_manifest_log $code "$name"
+ done
+ for tag in $MANIFEST_TAG; do
+ printf_blue "Running: docker manifest create $tag ${amend[*]}"
+ docker manifest create $tag $amend >/dev/null 2>"$DOCKERMGR_LOG_DIR/$manifest_log_file.log" || code=$((code++))
+ __docker_manifest_log $code "$name - $tag"
+ printf_cyan "Pushing $tag"
+ docker manifest push --purge $tag >/dev/null 2>>"$DOCKERMGR_LOG_DIR/$manifest_log_file.log" || code=$((code++))
+ __docker_manifest_log $code "$name - $tag"
+ done
+ base_id="$(docker images -a | grep "$base_name.*$base_tag" | awk '{print $3}' | grep '^' || false)"
+ [ -n "$base_image" ] && docker rmi $base_id >/dev/null 2>>"$DOCKERMGR_LOG_DIR/$manifest_log_file.log" && printf_cyan "🦄 Deleted base image $base_image with id: $base_id 🦄"
+ for del_tag in $delete_tag; do
+ rm_tag="${del_tag//*:/}"
+ rm_name="${push//:*/}"
+ local_name="$(docker images -a | grep "$push.*$tag" | awk '{print $3}' | grep '^' || false)"
+ if [ -z "$do_not_delete" ]; then
+ __registry_delete_tag "$rm_name" "$rm_tag" && printf_green "Success 😺" || { printf_red "Failed 😿" && code=1; }
+ fi
+ [ -n "$local_name" ] && docker rmi $local_name >/dev/null 2>>"$DOCKERMGR_LOG_DIR/$manifest_log_file.log" && printf_cyan "🦄 Deleted local image $push:$tag with id: $local_name 🦄"
+ done
+ #__orgs_api_update "$push" "description" "This image was built from $pull_from_pretty"
+ __update_repo_info "$push" "${description:-See $DOCKERMGR_HUB_URL/r/$pull_from_pretty for info}"
+ if [ $code -eq 0 ]; then
+ printf_green "😸 Successfully created/updated $push 😸"
+ else
+ printf_red "😿 Failed to create/update $push 😿"
+ printf_yellow "error log saved to: $DOCKERMGR_LOG_DIR/$manifest_log_file.log"
+ fi
+ return $code
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_readme() {
+
+ return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__upload_readme_to_hub() {
+ [ "${1:-}" = "generate" ] && shift 1 && __create_readme && README_NEW_FILE="" || FILE=""
+ [ -f "$1" ] && DOCKERHUB_README="$(realpath "$1")" && shift 1 || DOCKERHUB_README="${README_NEW_FILE:-$PWD/README.md}"
+ if echo "$1" | grep -q '.*/[A-Za-z0-9]'; then
+ DOCKERHUB_REPO_PREFIX="$(echo "$1" | awk -F'/' '{print $1}')"
+ DOCKERHUB_REPO_NAME="$(echo "$1" | awk -F'/' '{print $2}')"
+ shift 1
+ else
+ DOCKERHUB_REPO_NAME="${2:-}"
+ DOCKERHUB_REPO_PREFIX="${1:-}"
+ shift 2
+ fi
+ if [ -n "$1" ] && echo "$1" | grep -qE ' .*[A-Za-z0-9] .*[A-Za-z0-9]'; then
+ DOCKERHUB_DESCRIPTION="$1"
+ shift 1
+ fi
+ [ -n "$DOCKERHUB_REPO_NAME" ] || printf_exit 1 3 "Usage: $APPNAME readme [file] [org] [repo] [description]"
+ [ -n "$DOCKERHUB_REPO_PREFIX" ] || printf_exit 1 3 "Usage: $APPNAME readme [file] [org] [repo] [description]"
+ DOCKERHUB_USERNAME="${1:-$DOCKERHUB_USERNAME}"
+ DOCKERHUB_PASSWORD="${2:-$DOCKERHUB_PASSWORD}"
+ [ -f "$DOCKERHUB_README" ] || printf_exit "Please provide a valid path to your readme file"
+ [ -n "$DOCKERHUB_DESCRIPTION" ] || DOCKERHUB_DESCRIPTION="Docker build files for $DOCKERHUB_REPO_NAME"
+ [ -z "$DOCKERMGR_SHOW_INFO" ] || printf_exit "Variables: [$DOCKERHUB_README] [$DOCKERHUB_REPO_PREFIX] [$DOCKERHUB_REPO_NAME] [${DOCKERHUB_USERNAME:-username}] [password]"
+ [ -n "$DOCKERHUB_USERNAME" ] || printf_exit "Missing Username - Usage: [$DOCKERHUB_README] [$DOCKERHUB_REPO_PREFIX] [$DOCKERHUB_REPO_NAME] [${DOCKERHUB_USERNAME:-username}] [password]"
+ [ -n "$DOCKERHUB_PASSWORD" ] || printf_exit "Missing password - Usage: [$DOCKERHUB_README] [$DOCKERHUB_REPO_PREFIX] [$DOCKERHUB_REPO_NAME] [${DOCKERHUB_USERNAME:-username}] [password]"
+ [ -f "$DOCKERMGR_CONFIG_DIR/.hub_username" ] || echo "$DOCKERHUB_USERNAME" >"$DOCKERMGR_CONFIG_DIR/.hub_username"
+ [ -f "$DOCKERMGR_CONFIG_DIR/.hub_password" ] || echo "$DOCKERHUB_PASSWORD" >"$DOCKERMGR_CONFIG_DIR/.hub_password"
+ chmod 600 "$DOCKERMGR_CONFIG_DIR/.hub_username" "$DOCKERMGR_CONFIG_DIR/.hub_password"
+ __api_test "$DOCKERHUB_REPO_PREFIX/$DOCKERHUB_REPO_NAME" || printf_exit 2 6 "$DOCKERMGR_HUB_URL/r/$DOCKERHUB_REPO_PREFIX/$DOCKERHUB_REPO_NAME does not seem to exist"
+ printf_cyan "Pulling image from casjaysdevdocker/readme-to-dockerhub"
+ $DOCKERMGR_DOCKER_BIN pull casjaysdevdocker/readme-to-dockerhub &>/dev/null
+ printf_cyan "Uploading $DOCKERHUB_README to $DOCKERHUB_REPO_PREFIX/$DOCKERHUB_REPO_NAME"
+ $DOCKERMGR_DOCKER_BIN run --rm --name dockermgr-readme \
+ -e DOCKERHUB_USERNAME="${DOCKERHUB_USERNAME}" \
+ -e DOCKERHUB_PASSWORD="${DOCKERHUB_PASSWORD}" \
+ -e DOCKERHUB_REPO_NAME="$DOCKERHUB_REPO_NAME" \
+ -e DOCKERHUB_REPO_PREFIX="$DOCKERHUB_REPO_PREFIX" \
+ -e SHORT_DESCRIPTION="${DOCKERHUB_DESCRIPTION:-Container image for $DOCKERHUB_REPO_NAME}" \
+ -v $DOCKERHUB_README:/data/README.md:ro \
+ casjaysdevdocker/readme-to-dockerhub 1>/dev/null || false
+ if [ $? = 0 ]; then
+ printf_green "Updated the readme on https://hub.docker.com/r/$DOCKERHUB_REPO_PREFIX/$DOCKERHUB_REPO_NAME"
+ return 0
+ else
+ printf_red "Failed to updated the readme on https://hub.docker.com/r/$DOCKERHUB_REPO_PREFIX/$DOCKERHUB_REPO_NAME"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__disk_usage_post() {
+ local usage="" total_disk_end="" mess="" total_disk_usage="${total_disk_usage:-}"
+ total_disk_end="$(\df -k | grep '/$' | awk '{print $3}' | sed 's|[a-zA-Z]||g' | grep '^' || return 1)"
+ if [ -n "$total_disk_usage" ] && [ -n "$total_disk_end" ]; then
+ if [ "$total_disk_usage" -eq "$total_disk_end" ]; then
+ mess=""
+ elif [ "$total_disk_end" -gt "$total_disk_usage" ]; then
+ mess="Used"
+ usage=$((total_disk_end - total_disk_usage))
+ else
+ mess="Cleaned up"
+ usage=$((total_disk_usage - total_disk_end))
+ fi
+ if [ -n "$mess" ]; then
+ if [ "$usage" -ge 1048576 ]; then
+ usage=$((usage / 1048576))
+ printf_cyan "$mess ${usage}G"
+ elif [ "$usage" -ge 1024 ]; then
+ usage=$((usage / 1024))
+ printf_cyan "$mess ${usage}M"
+ else
+ printf_cyan "$mess ${usage}K"
+ fi
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_run() {
+ [ "$_DEBUG" = "on" ] && set -xe
+ local arguments="$*"
+ __docker run -ti --privileged --cap-add NET_ADMIN --cap-add SYS_ADMIN -e DISPLAY=$DISPLAY \
+ -v /sys/fs/cgroup/:/sys/fs/cgroup:ro -v /tmp/.X11-unix:/tmp/.X11-unix \
+ -v "$HOME/.Xauthority:/home/x11user/.Xauthority" $arguments #2>"$DOCKERMGR_TEMP_FILE" || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_stop() {
+ get_running="$(__docker ps -q 2>/dev/null)"
+ __docker stop "$get_running" &>/dev/null &&
+ printf_green "Stopped the following containers: $get_running" ||
+ printf_red "Failed to stop the following containers: $get_running"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_rm() {
+ getcontents=$(__docker ps -a 2>/dev/null | grep -v 'CONTAINER ID.*IMAGE.*COMMAND.*CREATED.*STATUS.*PORTS.*NAMES' | grep "${1:-^}" | __col 1)
+ for content in $getcontents; do
+ __docker rm -f --volumes $content &>/dev/null &&
+ printf_green "Removed container: $content" ||
+ printf_red "Failed to remove container: $content"
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_rmi() {
+ getcontents=$(__docker images 2>/dev/null | grep -v 'REPOSITORY.*TAG.*IMAGE ID.*CREATED.*SIZE' | grep "${1:-^}" | __col 3)
+ for contents in $getcontents; do
+ image_name="$(__docker images 2>/dev/null | grep -v 'REPOSITORY' | grep "$contents" | awk '{print $1}')"
+ running_container="$(__docker container ls 2>/dev/null | grep -v 'CONTAINER ID' | grep "$image_name" | awk '{print $1}')"
+ [ -n "$running_container" ] && __docker rm -f --volumes "$running_container" &>/dev/null && running_container=""
+ __docker rmi -f $contents 2>&1 | grep -q 'running container' &>/dev/null && REMOVED="TRUE" || REMOVED="FALSE"
+ [ "$REMOVED" = "TRUE" ] && printf_green "Removed image: $contents" || printf_red "Failed to remove image: $contents"
+ [ -z "$running_container" ] || printf_blue "Can not delete an image that is currently running"
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_untagged_rm() {
+ local getcontents="" image_name="" image_id=""
+ getcontents="$(__docker images | grep ' ' | awk '{print $3"=="$1}' | grep -v '^IMAGE==REPOSITORY' || false)"
+ get_image_id="$(echo "$getcontents" | awk -F'==' '{print $1}')"
+ if [ -n "$get_image_id" ]; then
+ for contents in $get_image_id; do
+ image_id="$(echo "$contents" | awk -F'==' '{print $1}')"
+ image_name="$(echo "$contents" | awk -F'==' '{print $2}')"
+ printf_cyan "Deleting untagged image $image_name"
+ __docker rmi -f "$image_id " &>/dev/null
+ done
+ else
+ printf_yellow "No untagged images found"
+ return 1
+ fi
+ return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_ps() {
+ docker ps -a | awk -F' ' '{print $NF}' | grep -v '^NAMES$'
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__prune() {
+ local i="" c="" v="" name="" saved="" disk_end="" disk_use=""
+ printf_blue "Pruning containers"
+ __disk_usage_pre
+ __docker container prune -f &>/dev/null
+ containers="$(__docker ps -a -q)"
+ [ -n "$containers" ] || printf '\r%b' "${RED}No containers to delete ${NC}"
+ for c in $(__docker ps -a -q); do
+ if [ -n "$c" ]; then
+ printf '\r%b' "${YELLOW}Deleting container: $c ${NC}"
+ __docker rm -vf "$c" -f &>/dev/null
+ fi
+ done
+ echo ""
+ printf_blue "Pruning images"
+ images="$(__docker images -a -q)"
+ [ -n "$images" ] || printf '\r%b' "${RED}No images to delete ${NC}"
+ for i in $(__docker images -a -q); do
+ if [ -n "$i" ]; then
+ printf '\r%b' "${YELLOW}Deleting image: $i ${NC}"
+ __docker rmi "$i" -f &>/dev/null
+ fi
+ done
+ echo ""
+ printf_blue "Pruning volumes"
+ volumes="$(__docker volume ls -q --filter dangling=true)"
+ [ -n "$volumes" ] || printf '\r%b' "${RED}No volumes to delete ${NC}"
+ for v in $(__docker volume ls -q --filter dangling=true); do
+ if [ -n "$v" ]; then
+ printf '\r%b' "${YELLOW}Deleting volume: $v ${NC}"
+ __docker volume rm "$v" -f &>/dev/null
+ fi
+ done
+ echo ""
+ printf_blue "Pruning temporary volumes"
+ temp_volumes="$(ls -A "$DOCKERMGR_TEMP_DIR/volumes" 2>/dev/null)"
+ [ -n "$temp_volumes" ] || printf '\r%b' "${RED}No temporary volumes to delete ${NC}"
+ for v in $(ls -A "$DOCKERMGR_TEMP_DIR/volumes" 2>/dev/null); do
+ if [ -n "$v" ]; then
+ printf '\r%b' "${YELLOW}Deleting temporary volume: $v ${NC}"
+ rm -Rf "$DOCKERMGR_TEMP_DIR/volumes/$v" &>/dev/null
+ fi
+ done
+ echo ""
+ __disk_usage_post
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__watchtower_setup() {
+ local exitCodep=0
+ local name="watchtower"
+ local container_name="casjaysdevdocker-${name}-latest"
+ if ! __container_exists "$container_name" >/dev/null 2>&1; then
+ printf_yellow "Installing ${name}"
+ dockermgr install ${name} >/dev/null 2>&1 || exitCodep=1
+ fi
+ return $exitCodep
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__setup_bridge() {
+ if grep -qs 'net.bridge.bridge-nf-call-iptables' '/etc/sysctl.conf'; then
+ __sudo $sed -i 's|net.bridge.bridge-nf-call-iptables.*|net.bridge.bridge-nf-call-iptables = 1|g' '/etc/sysctl.conf'
+ elif grep -qsR 'net.bridge.bridge-nf-call-iptables' '/etc/sysctl.d'; then
+ __sudo $sed -i 's|net.bridge.bridge-nf-call-iptables.*|net.bridge.bridge-nf-call-iptables = 1|g' '/etc/sysctl.d/*'
+ else
+ __sudo echo "net.bridge.bridge-nf-call-iptables = 1" | tee -a /etc/sysctl.conf >/dev/null 2>&1
+ fi
+ if grep -qs 'net.bridge.bridge-nf-call-ip6tables' '/etc/sysctl.conf'; then
+ __sudo $sed -i 's|net.bridge.bridge-nf-call-ip6tables.*|net.bridge.bridge-nf-call-ip6tables = 1|g' '/etc/sysctl.conf'
+ elif grep -qsR 'net.bridge.bridge-nf-call-ip6tables' '/etc/sysctl.d'; then
+ __sudo $sed -i 's|net.bridge.bridge-nf-call-ip6tables.*|net.bridge.bridge-nf-call-ip6tables = 1|g' '/etc/sysctl.d/*'
+ else
+ __sudo echo "net.bridge.bridge-nf-call-ip6tables = 1" | tee -a /etc/sysctl.conf >/dev/null 2>&1
+ fi
+ __sudo modprobe br_netfilter >/dev/null 2>&1
+ __sudo sysctl -p /etc/sysctl.conf >/dev/null 2>&1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__multiarch() {
+ local qemu_imagename="buildx-qemu"
+ local binfmt_imagename="buildx-binfmt"
+ # Setup qemu
+ if ! __container_exists "$qemu_imagename" >/dev/null 2>&1; then
+ printf_yellow "Setting up the qemu image - multiarch/qemu-user-static as $qemu_imagename"
+ __docker run -d --name "$qemu_imagename" --privileged multiarch/qemu-user-static --reset -p yes --credential yes &>/dev/null
+ fi
+ # Setup binfmt
+ if ! __container_exists "$binfmt_imagename" >/dev/null 2>&1; then
+ printf_yellow "Setting up the binfmt image - tonistiigi/binfmt as $binfmt_imagename"
+ __docker run -d --name "$binfmt_imagename" --privileged tonistiigi/binfmt --install all &>/dev/null
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__sudo_rm() {
+ if sudo -n true &>/dev/null && sudo true; then
+ sudo rm -Rf "$*" || printf_return "Can not remove $*"
+ else
+ printf_return "Can not remove $* with sudo"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# TODO Make variables user defined
+__docker_proxy_setup() {
+ local exitCodep=0
+ local name="dockerproxy"
+ local container_name="casjaysdevdocker-${name}-latest"
+ if ! __container_exists "$container_name" >/dev/null 2>&1; then
+ printf_yellow "Installing ${name}"
+ dockermgr install ${name} >/dev/null 2>&1 || exitCodep=1
+ fi
+ return $exitCodep
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__status() {
+ local status
+ if ps -aux | grep -w [d]ocker &>/dev/null; then
+ status="$(ps -aux | grep -wv 'docker-proxy' | grep -w [d]ocker | tr ' ' '\n' | grep -v '^$' | grep -E 'unix|tcp' | tr '\n' ',' | sed 's|,$||g' | grep '^')"
+ if [ -n "$status" ]; then
+ printf '%s: %s' "$(printf_green "Docker is listening on the following")" "$(printf '%b' "$status")"
+ printf '\n'
+ exitCode=0
+ else
+ printf_cyan "Docker is running"
+ fi
+ else
+ printf_red "docker does not seem to be running"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_service() {
+ service_active="$(systemctl show -p ActiveState "docker" | cut -d'=' -f2 | grep ^active)"
+ service_running="$(systemctl status docker 2>/dev/null | grep -F running)"
+ if [ -z "$service_active" ] || [ -z "$service_running" ]; then
+ sudo -HE -n true && ask_for_password true &>/dev/null || return 1
+ sudo -HE systemctl start docker &>/dev/null || return 1
+ sudo -HE systemctl enable --now docker &>/dev/null || return 1
+ fi
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__init() {
+ local docker_proxy_name=dockerproxy
+ { [ "$DOCKERMGR_FORCE_INSTALL" != "true" ] && cmd_exists docker; } || DOCKERMGR_FORCE_INSTALL="false"
+ am_i_online --error -m "Can not setup docker: No internet" || exit 1
+ sudo -HE -n true &>/dev/null && sudo -HE true || printf_exit 1 1 "This script requires root privileges"
+ if [ "$DOCKERMGR_FORCE_INSTALL" = "true" ]; then
+ printf_cyan "docker seems to be installed: add --force to reinitialize"
+ return 0
+ elif [ "$DOCKERMGR_FORCE_INSTALL" = "false" ]; then
+ printf_newline
+ cmd_exists docker || ask_yes_no_question --off "Docker is not installed: would you like to install it?" true || return 1
+ printf_green "Installing docker and setting up systemd"
+ printf_green "This will take a few minutes"
+ if cmd_exists pacman; then
+ sudo -HE pacman -Syy --noconfirm docker &>/dev/null
+ elif cmd_exists dnf || cmd_exists yum; then
+ __dnf_yum="$(type -P dnf || type -P yum || false)"
+ if [ ! -f "/etc/yum.repos.d/casjay.repo" ]; then
+ curl -q -LSsf "https://download.docker.com/linux/centos/docker-ce.repo" | sudo tee -p "/etc/yum.repos.d/docker-ce.repo" &>/dev/null
+ fi
+ sudo $__dnf_yum update -y -q &>/dev/null
+ sudo $__dnf_yum remove -y -q podman buildah &>/dev/null
+ sudo $__dnf_yum install -y -q docker-ce docker-ce-cli containerd.io &>/dev/null
+ sudo systemctl enable docker.service --now &>/dev/null
+ elif cmd_exists apk; then
+ apk add docker docker-cli-compose docker-cli-buildx &>/dev/null
+ else
+ if curl -q -LSsfk --connect-timeout 3 --retry 1 "$DOCKERMGR_INSTALL_SCRIPT" >"$DOCKERMGR_INSTALL_TMP"; then
+ chmod 755 "$DOCKERMGR_INSTALL_TMP"
+ sudo -HE bash -c "$DOCKERMGR_INSTALL_TMP" 2>&1 | tee -p "$DOCKERMGR_TEMP_FILE" &>/dev/null
+ if grep -Eqi 'E: The repository|ERROR: Unsupported' "$DOCKERMGR_TEMP_FILE" 2>/dev/null; then
+ printf_red "Distro not supported please do a manual install"
+ printf_red "https://github.com/dockermgr/community/wiki"
+ printf_red "https://docs.docker.com/engine/install/"
+ exit 1
+ fi
+ else
+ printf_exit "Failed to download the script from $DOCKERMGR_INSTALL_SCRIPT"
+ fi
+ fi
+ fi
+ if cmd_exists docker; then
+ printf_green "Docker has been installed."
+ if ! grep -qs '^docker' /etc/group; then
+ sudo groupadd --system --force docker
+ fi
+ else
+ printf_exit "Installation has failed: could not install docker"
+ fi
+ printf_green "Continuing with configuration"
+ mkdir -p "$HOME/.docker"
+ if grep -q docker /etc/group; then
+ printf_cyan "Adding $USER to the docker group"
+ sudo -HE usermod -aG docker "$USER" &>/dev/null
+ sudo -HE chown -R "$USER":"$USER" "$HOME/.docker" &>/dev/null
+ sudo -HE chmod -R g+rwx "$HOME/.docker" &>/dev/null
+ [ -n "$(builtin type -P gpasswd 2>/dev/null)" ] && sudo -HE gpasswd -a "${USER}" docker &>/dev/null
+ fi
+
+ if [ ! -f "/etc/systemd/system/docker.service.d/docker.conf" ]; then
+ __update_systemd_docker_service
+ fi
+ if __docker_service; then
+ printf_green "docker installation has completed"
+ __create_docker_cron
+ __multiarch
+ __watchtower_setup
+ __docker_proxy_setup
+ __setup_bridge
+ printf_cyan "You should logout and log back in for the changes to take effect"
+ exitCode=0
+ else
+ printf_red "docker installation has failed"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__update_systemd_docker_service() {
+ printf_green "Updating the docker systemd service"
+ sudo -HE mkdir -p /etc/systemd/system/docker.service.d
+ cat </dev/null | sudo -HE tee "/etc/systemd/system/docker.service.d/docker.conf" &>/dev/null
+[Service]
+ExecStart=
+ExecStart=/usr/bin/dockerd -H unix://var/run/docker.sock
+
+EOF
+ systemctl daemon-reload
+ systemctl enable --now docker
+ systemctl restart docker
+ if systemctl is-active docker grep -q 'running$' 2>&1; then
+ printf_cyan "Docker service has been updated"
+ return 0
+ else
+ printf_red "Docker service has failed to be updated"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__port_is_free() {
+ local retVal=0
+ if netstat -tauln 2>&1 | grep ' LISTEN' | awk -F' ' '{print $4}' | awk -F':' '{print $NF}' | sort -u | grep -q "^$1$"; then
+ retVal=1
+ fi
+ return $retVal
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__init_help() {
+ printf_green "Setup docker"
+ exit 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__k3b() {
+ __execute "curl -q -LSsf $DOCKERMGR_K3B_INSTALL_SCRIPT | sudo -HE bash -" "Installing k3b please wait....."
+ if cmd_exists k3s; then
+ k3s kubectl get node &>/dev/null
+ sudo -HE k3s server &>/dev/null &
+ printf_green "Kubernetes has been installed"
+ exitCode=0
+ else
+ printf_red "Kubernetes install has failed"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__install_helm() {
+ curl -q -LSsf "https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3" | bash &>/dev/null
+ if cmd_exists helm; then
+ printf_green "Helm has been installed"
+ helm completion bash | sudo -HE tee "/etc/bash_completion.d/helm" &>/dev/null
+ exitCode=0
+ else
+ printf_red "Helm install has failed"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__minikube() {
+ cmd_exists minikube || __minikube_init
+ unbuffer minikube "$@" | printf_readline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__minikube_dashboard() {
+ netstatg 'kubectl' | grep -q '8001' &&
+ printf_green "🎉 http://127.0.0.1:8001" ||
+ {
+ unbuffer minikube kubectl -- proxy | printf_readline 7 &
+ disown
+ }
+ netstatg 'kubectl' | grep -q '18080' &&
+ printf_green "🎉 http://127.0.0.1:18080/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/" ||
+ {
+ unbuffer minikube dashboard --url false --port 18080 2>&1 | printf_readline 7 &
+ disown
+ sleep 30
+ }
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__minikube_services() {
+ cat </dev/null)" ]; then
+ driver="kvm2"
+ elif [ "$(command -v hyperkit 2>/dev/null)" ]; then
+ driver="hyperkit"
+ elif [ "$(command -v Virtualbox 2>/dev/null)" ]; then
+ driver="virtualbox"
+ elif [ "$(command -v docker 2>/dev/null)" ]; then
+ driver="docker"
+ else
+ printf_red "No driver found. If you know the driver please specify it"
+ printf_yellow "$APPNAME minikube [virtualbox|vmware|kvm2|docker|hyperkit|none]"
+ printf_exit "Docs: https://minikube.sigs.k8s.io/docs/drivers/"
+ fi
+ fi
+ [ -n "$uname" ] || printf_exit "minikube is not supported on $uname"
+ printf_purple "Downloading minikube for $osname [$osarch]"
+ if __minikube_curl $osname-$osarch; then
+ if cmd_exists minikube; then
+ unalias kubectl &>/dev/null
+ printf_green "Minikube has been installed"
+ [ -d "/etc/bash_completion.d" ] || mkdir -p "/etc/bash_completion.d"
+ minikube completion bash | sudo -HE tee /etc/bash_completion.d/minikube &>/dev/null
+ printf_blue "Attempting to start minikube cluster - This may take awhile" &&
+ (unbuffer minikube start --driver=$driver 2>&1 |& grep -v 'Using image' && kubectl config use-context minikube &>/dev/null) | printf_readline 7 | grep -v '^$'
+ echo &&
+ printf_purple "Attempting to configure minikube to use driver: $driver" &&
+ (unbuffer minikube config set driver $driver 2>&1) | printf_readline 7 | grep --line-buffered -v '^$'
+ echo &&
+ printf_purple "configuring minikube addons: $m"
+ for m in ingress portainer registry dashboard; do
+ unbuffer minikube addons enable $m | grep -v '^$' | head -n 1 | printf_readline 7
+ done
+ echo &&
+ printf_purple "Getting minikube pod info" &&
+ (unbuffer minikube kubectl -- get pods -A | grep '^kube' 2>&1) | printf_readline 7 | grep --line-buffered -v '^$'
+ echo &&
+ printf_purple "Setting up minikube dashboard " &&
+ __minikube_dashboard |& grep -v '^$' &
+ disown
+ sleep 30
+ echo &&
+ [ "$driver" != "none" ] || [ "$driver" != "docker" ] &&
+ printf_yellow="default login is, username: docker & password: tcuser."
+ exitCode=$?
+ else
+ printf_red "Minikube install has failed"
+ __minikube_delete
+ return 1
+ fi
+ else
+ printf_red "Minikube install has failed"
+ __minikube_delete
+ return $1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__minikube_curl() {
+ [ -n "$releases" ] && __get_releases_google "minikube" "minikube-$1" -o "/tmp/minikube" &>/dev/null
+ if [ $? -eq 0 ]; then
+ [ -f "/tmp/minikube" ] &&
+ { sudo -HE mv -f "/tmp/minikube" "/usr/local/bin/minikube" &&
+ chmod +x "/usr/local/bin/minikube" || false; } ||
+ { mv -f "/tmp/minikube" "$HOME/.local/bin/minikube" &&
+ chmod +x "/usr/local/bin/minikube" || false; }
+ return $?
+ else
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__download() {
+ if echo "$1" | grep -q "/"; then
+ ORG_NAME="$(echo "$1" | awk -F '/' '{print $1}')"
+ REPO_NAME="$(echo "$1" | awk -F '/' '{print $2}')"
+ REPO_URL="$(dirname "$DOCKERMGR_GIT_REPO")/$ORG_NAME/$REPO_NAME"
+ else
+ REPO_NAME="$1"
+ REPO_URL="$DOCKERMGR_GIT_REPO/$REPO_NAME"
+ fi
+ gitadmin clone "$REPO_URL"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__download_src() {
+ if echo "$1" | grep -q "/"; then
+ ORG_NAME="$(echo "$1" | awk -F '/' '{print $1}')"
+ REPO_NAME="$(echo "$1" | awk -F '/' '{print $2}')"
+ REPO_URL="$(dirname "$DOCKERMGR_GIT_SRC_REPO_NAME")/$ORG_NAME/$REPO_NAME"
+ else
+ REPO_NAME="$1"
+ REPO_URL="$DOCKERMGR_GIT_SRC_REPO_NAME/$REPO_NAME"
+ fi
+ gitadmin clone "$REPO_URL"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_source_list() {
+ local api_source_list="" api_source_name=""
+ [ "$1" = "help" ] && printf_exit "Usage: $APPNAME api sources [name,url,all]"
+ if [ "$1" = "name" ]; then
+ api_source_name="true"
+ api_source_list="$(__download_src_api | jq -rc '.[] | {name:.name,url:.html_url}' | jq -r '.name' | __jq_exclude | grep '^' || echo '')"
+ elif [ "$1" = "url" ]; then
+ api_source_list="$(__download_src_api | jq -rc '.[] | {name:.name,url:.html_url}' | jq -r '.url' | __jq_exclude | grep '^' || echo '')"
+ else
+ api_source_list="$(__download_src_api | jq -rc '.[] | {name:.name,url:.html_url}' | __jq_exclude | grep '^' || echo '')"
+ fi
+ [ -n "$api_source_list" ] && printf '%s\n' "$api_source_list" || { [ "$api_source_name" = "true" ] && printf '%s\n' "$SRCS"; }
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_uninstall_info() {
+ local CONTAINER_INFO="$DOCKERMGR_CONFIG_DIR/installed/$APPNAME"
+ local CONTAINER_NAME="${DOCKERMGR_REGISTRY_USERNAME}-$APPNAME-latest"
+ [ -f "$DOCKERMGR_CONFIG_DIR/uninstall/$APPNAME" ] && . "$DOCKERMGR_CONFIG_DIR/uninstall/$APPNAME"
+ [ -f "$DOCKERMGR_CONFIG_DIR/uninstall/$CONTAINER_NAME" ] && . "$DOCKERMGR_CONFIG_DIR/uninstall/$CONTAINER_NAME"
+ [ -f "$CONTAINER_INFO" ] && container_name="$(<"$CONTAINER_INFO")"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+installer_delete() {
+ local LISTARRAY="$*"
+ local exitCode="0"
+ local APPNAME=""
+ for APPNAME in $LISTARRAY; do
+ __disk_usage_pre
+ __get_uninstall_info
+ local EPOCH="$(date +'%s')"
+ local DATE="$(date +'%Y%m%d%H%M')"
+ local SCRIPTS_DIR="$DOCKERMGR_CONFIG_DIR/scripts"
+ local DOCKER_REGISTRY_URL="${DOCKER_REGISTRY_URL:-docker.io}"
+ local DOCKER_REGISTRY_IMAGE_TAG="${DOCKER_REGISTRY_IMAGE_TAG:-latest}"
+ local DOCKER_REGISTRY_REPO_NAME="${DOCKER_REGISTRY_REPO_NAME:-$APPNAME}"
+ local DOCKER_REGISTRY_USER_NAME="${DOCKER_REGISTRY_USER_NAME:-casjaysdevdocker}"
+ local APPDIR="$HOME/.local/share/CasjaysDev/dockermgr/$APPNAME"
+ local INSTDIR="$HOME/.local/share/CasjaysDev/dockermgr/$APPNAME"
+ local DATADIR="/var/lib/srv/$USER/docker/$DOCKER_REGISTRY_USER_NAME/$DOCKER_REGISTRY_REPO_NAME/$DOCKER_REGISTRY_IMAGE_TAG"
+ local SHAREDIR="$HOME/.local/share/CasjaysDev/dockermgr/$APPNAME"
+ local MESSAGE="${MESSAGE:-Removing $APPNAME from ${msg:-your system}}"
+ __get_uninstall_info
+ if [ -d "$APPDIR]" ] || [ -d "$INSTDIR" ] || [ -d "$DATADIR" ] || [ -f "$SHAREDIR" ] || [ -f "$CONTAINER_INFO" ]; then
+ local name="${CONTAINER_NAME:-$APPNAME}"
+ local container_name="$(__container_name "$name")"
+ local script_bak_name="$DOCKERMGR_CONFIG_BACKUP_DIR/scripts/$container_name.$DATE.bak"
+ local REMOVE_CRON="$(find /etc/cron.* -type f 2>/dev/null | grep "$name" || false)"
+ local OLD_SCRIPTS="$(find "$DOCKERMGR_CONFIG_BACKUP_DIR/scripts" -name "*${name}*" -type f 2>/dev/null | grep '^' || false)"
+ local SCRIPT_NAME="$(find "$SCRIPTS_DIR" -name "*${name}*" -type f 2>/dev/null | grep -vE "$script_bak_name|\.bak" | grep '^' || false)"
+ local REMOVE_FILES="$(find "$DOCKERMGR_CONFIG_DIR"/*$name* "/etc/nginx"/*${name//-/.}* -type f 2>/dev/null | grep -Ev "$DOCKERMGR_CONFIG_BACKUP_DIR|$SCRIPT_NAME")"
+ local REMOVE_DOCKERMGR_FILE="$REMOVE_FILES $ADD_REMOVE_FILES"
+ local REMOVE_DOCKERMGR_FILE="${REMOVE_DOCKERMGR_FILE//$script_bak_name/}"
+ mkdir -p "$DOCKERMGR_CONFIG_BACKUP_DIR/databases" "$DOCKERMGR_CONFIG_BACKUP_DIR/scripts"
+ printf_yellow "$MESSAGE"
+ if [ -n "$container_name" ]; then
+ printf_blue "Removing docker container: $container_name"
+ __docker rm -f --volumes "${container_name[@]}" ${container_name}-web &>/dev/null || eval $DOCKERMGR_DOCKER_BIN rm -f "${container_name[@]}" ${container_name}-web &>/dev/null
+ __container_name "$container_name" &>/dev/null && printf_yellow "Can not remove container: Please use docker rm -f $container_name"
+ fi
+ if [ -n "$DATABASE_BASE_DIR" ] && [ -d "$DATABASE_BASE_DIR" ]; then
+ printf_cyan "Backing up database dir to: $DOCKERMGR_CONFIG_BACKUP_DIR/databases/$name.$EPOCH.gz"
+ if tar cfvz "$DOCKERMGR_CONFIG_BACKUP_DIR/databases/$name.$EPOCH.gz" "$DATABASE_BASE_DIR" >/dev/null 2>&1; then
+ printf_green "The database directory has been backed up to: $DOCKERMGR_CONFIG_BACKUP_DIR/databases/$name.$EPOCH.gz"
+ else
+ printf_red "Failed to backup the database directory"
+ fi
+ fi
+ if [ -f "$SCRIPT_NAME" ]; then
+ printf_cyan "Backing up the install script: ${script_bak_name//$HOME/~}"
+ mv -f "$SCRIPT_NAME" "$script_bak_name" 2>/dev/null
+ fi
+ if [ -n "$NGINX_FILES" ]; then
+ printf_cyan "Removing nginx config files"
+ for nginx_conf in $NGINX_FILES; do
+ [ -f "$nginx_conf" ] && printf_cyan "Deleting $nginx_conf" && sudo rm -Rf "$nginx_conf"
+ done
+ fi
+ if [ -n "$HOST_ROOTFS_DIR" ] && [ -d "$HOST_ROOTFS_DIR" ]; then
+ printf_yellow "Deleting $HOST_ROOTFS_DIR"
+ rm -Rf "$HOST_ROOTFS_DIR"
+ fi
+ if [ "$INSTDIR" != "$APPDIR" ]; then
+ printf_blue "Deleting Installer from $INSTDIR"
+ rm -Rf "$INSTDIR" 2>/dev/null || __sudo_rm "$INSTDIR" 2>/dev/null
+ fi
+ if [ -d "$APPDIR" ]; then
+ printf_cyan "Deleting APP files from $APPDIR"
+ rm -Rf "$APPDIR" 2>/dev/null || __sudo_rm "$APPDIR" 2>/dev/null
+ fi
+ if [ -d "$DATADIR" ]; then
+ printf_green "Deleting the Data from $DATADIR"
+ rm -Rf "$DATADIR" 2>/dev/null || __sudo_rm "$DATADIR" 2>/dev/null
+ fi
+ if [ -d "$SHAREDIR" ]; then
+ printf_yellow "Deleting $SHAREDIR"
+ rm -Rf "$SHAREDIR" 2>/dev/null || __sudo_rm "$SHAREDIR" 2>/dev/null
+ fi
+ if [ -n "$REMOVE_DOCKERMGR_FILE" ]; then
+ for file in $REMOVE_DOCKERMGR_FILE; do
+ if [ "$file" != " " ]; then
+ if [ -n "$file" ] && [ -f "$file" ]; then
+ printf_purple "Deleting $file"
+ { rm -Rf "$file" 2>/dev/null || __sudo rm -Rf "$file" 2>/dev/null || printf_red "Failed to delete $file"; }
+ fi
+ fi
+ done
+ fi
+ if [ -n "$REMOVE_CRON" ]; then
+ for cron in $REMOVE_CRON; do
+ printf_cyan "Deleting: $cron"
+ [ -f "$cron" ] && rm -Rf "$cron"
+ done
+ fi
+ if [ -n "$CONTAINER_INFO" ] && [ -f "$CONTAINER_INFO" ]; then
+ rm -Rf "$CONTAINER_INFO"
+ fi
+ if [ -n "$OLD_SCRIPTS" ]; then
+ for old_script in $OLD_SCRIPTS; do
+ [ -f "$old_script" ] && printf_green "Removing old script: $old_script" && rm -Rf "$old_script"
+ done
+ fi
+ if [ -f "$DOCKERMGR_CONFIG_DIR/installed/$APPNAME" ]; then
+ printf_yellow "Deleting "$DOCKERMGR_CONFIG_DIR/installed/$APPNAME" "
+ fi
+ if [ -f "$DOCKERMGR_CONFIG_DIR/uninstall/$APPNAME" ]; then
+ printf_yellow "Deleting "$DOCKERMGR_CONFIG_DIR/uninstall/$APPNAME" "
+ fi
+ if [ -d "$APPDIR" ] || [ -d "$INSTDIR" ] || [ -d "$DATADIR" ] || [ -f "$SHAREDIR" ]; then
+ exitCode=$((exitCode++))
+ printf_red "There was a problem deleting $APPNAME"
+ else
+ printf_green "$APPNAME has been removed"
+ echo ""
+ fi
+ __sudo bash -c 'if [ -w "/etc/nginx" ];then mkdir -p /etc/nginx/global.d;touch /etc/nginx/global.d/nginx-defaults.conf;fi'
+ [ "$DOCKERMGR_SHOW_USAGE" = "yes" ] && __disk_usage_post
+ else
+ printf_error "$APPNAME doesn't seem to be installed"
+ fi
+ done
+ return ${exitCode}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__install_script() {
+ __docker_service
+ sudo -HE -n true || printf_exit "sudo has failed"
+ local LISTARRAY="$*"
+ for container in $LISTARRAY; do
+ __disk_usage_pre
+ local APPNAME="$container"
+ local REPO="https://github.com/$SCRIPTS_PREFIX/$APPNAME"
+ local REPORAW="https://github.com/$SCRIPTS_PREFIX/$APPNAME/raw/$GIT_REPO_BRANCH"
+ local APPVERSION="$(__appversion "$https://github.com/$SCRIPTS_PREFIX/$APPNAME/raw/$GIT_REPO_BRANCH/version.txt")"
+ local CONTAINER_NAME="${CONTAINER_NAME:-$APPNAME}"
+ local INSTDIR="$HOME/.local/share/CasjaysDev/dockermgr/$APPNAME"
+ local SHAREDIR="$HOME/.local/share/CasjaysDev/dockermgr/$APPNAME"
+ local DOCKER_REGISTRY_IMAGE_TAG="${DOCKER_REGISTRY_IMAGE_TAG:-latest}"
+ local DOCKER_REGISTRY_REPO_NAME="$(echo "$REPO" | awk -F '/' '{print $NF}')"
+ local DOCKER_REGISTRY_USER_NAME="$(echo "$REPO" | awk -F '/' '{print $(NF-1)}')"
+ local APPDIR="/var/lib/srv/$USER/docker/$DOCKER_REGISTRY_USER_NAME/$DOCKER_REGISTRY_REPO_NAME/$DOCKER_REGISTRY_IMAGE_TAG"
+ local DATADIR="/var/lib/srv/$USER/docker/$DOCKER_REGISTRY_USER_NAME/$DOCKER_REGISTRY_REPO_NAME/$DOCKER_REGISTRY_IMAGE_TAG"
+ export APPNAME APPDIR INSTDIR DATADIR
+ if ! curl -q -LSsfI "$REPO" &>/dev/null; then
+ rm -Rf "$APPDIR" "$DATADIR" "$INSTDIR" 2>/dev/null
+ printf_exit 3 3 "The URL $REPO returned an error"
+ fi
+ printf_green "Running the installer script for $APPNAME"
+ am_i_online --error -m "Can not setup docker: No internet" || exit 1
+ if [ -f "$INSTDIR/install.sh" ] && [ -d "$INSTDIR/.git" ]; then
+ printf_green "Updating source files in $INSTDIR"
+ if git -C "$INSTDIR" reset --hard -q && git -C "$INSTDIR" pull -q && [ -f "$INSTDIR/install.sh" ]; then
+ chmod -f 755 "$INSTDIR/install.sh"
+ bash -c "$INSTDIR/install.sh"
+ else
+ printf_red "Failed to update Source files in $INSTDIR"
+ return 1
+ fi
+ else
+ printf_green "Installing source files to $INSTDIR"
+ if git clone -q "$REPO" "$INSTDIR" && [ -f "$INSTDIR/install.sh" ]; then
+ chmod -f 755 "$INSTDIR/install.sh"
+ bash -c "$INSTDIR/install.sh"
+ else
+ rm -Rf "$APPDIR" "$DATADIR" "$INSTDIR" 2>/dev/null
+ printf_red "Failed to install Source files to $INSTDIR"
+ return 1
+ fi
+ fi
+ [ "$DOCKERMGR_SHOW_USAGE" = "yes" ] && __disk_usage_post
+ printf '\n'
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__install_help() {
+ printf_green "Usage: $APPNAME install NAME | $APPNAME install transmission"
+ exit 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_help() {
+ printf_green "Usage: dockermgr run imageName"
+ printf_green "See http://hub.docker.com for images"
+ exit 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_exec() {
+ __docker exec -it "$@" 2>/dev/null
+ exitCode="$?"
+ echo ""
+ printf_read_question "4" "Should I delete the container?" "1"
+ printf_answer_yes && __docker rm -f --volumes "$name" &>/dev/null
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_main() {
+ NAME="$(echo "$1" | sed 's/[!@#\$%^&*():]//g' | sed 's|/|-|g' | grep -v '^$' | grep '^')"
+ IMAGE="${2:-$1}"
+ EXISTS="$(__container_is_running "$NAME" || false)"
+ if [ -n "$EXISTS" ]; then
+ __docker container exec -it "$NAME" "/bin/bash"
+ else
+ if [ -n "$1" ]; then
+ __docker run -d $DOCKER_ARG --network host -it --name "$NAME" --restart always "$IMAGE"
+ __docker container exec -it "$NAME" "/bin/bash" || printf_exit "Failed to run $NAME"
+ else
+ printf_exit "Error: No container name was given"
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_update() {
+ local install_dir="$DOCKERMGR_HOME/installed"
+ if [ "$*" != "" ]; then
+ __install_script "$@"
+ else
+ printf_cyan "Looking in $install_dir for installed containers"
+ if [ -d "$install_dir" ] && [ "$(find "$install_dir" -mindepth 1 -maxdepth 1 -type f | wc -l)" -ne 0 ]; then
+ for d in $(ls -A "$install_dir" | grep -Ewv '.env|env|--'); do
+ __install_script "$d"
+ done
+ else
+ printf_return "There is nothing to update in $install_dir"
+ fi
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_cron() {
+ local frequency="0 4 * * 6"
+ local croncmd="$APPNAME cron run"
+ case $1 in
+ run)
+ logr bash -c "am_i_online && $(expr $RANDOM \% 300) && docker images | awk '(NR>1) && ($2!~/none/) {print $1":"$2}' | xargs -L1 docker pull"
+ ;;
+ remove)
+ shift 1
+ removecrontab "$frequency $croncmd"
+ ;;
+ add)
+ addtocrontab "$frequency $croncmd"
+ ;;
+ *)
+ addtocrontab "$frequency $croncmd"
+ ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__ssh_help() {
+ printf_green "Auto connect to first container if none are specified"
+ printf_green "Usage: $APPNAME ssh container_name"
+ exit 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__ssh_error() {
+ printf_red "There are no running containers"
+ exit 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__connect_main() {
+ CONTAINER="$1"
+ if [ "$CONTAINER" == "" ]; then
+ CONTAINER=$(__docker ps | grep -Eo "^[0-9a-z]{8,}\b") || __ssh_error
+ fi
+ __docker exec -i -t "$CONTAINER" bash -l
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__install_front() {
+ cmd_exists docker || __init || exit 1
+ printf_cyan "Installing yacht"
+ $DOCKERMGR_DOCKER_BIN rm yacht -f &>/dev/null
+ if __install_script yacht &>/dev/null; then
+ printf_yellow "Username: admin@yacht.local"
+ printf_yellow "Password: pass"
+ printf_yellow "URL: http://yacht.local:14053"
+ printf_green "Yacht has been installed"
+ else
+ printf_red "Failed to install yacht"
+ fi
+ echo
+ printf_cyan "Installing nginx-proxy-manager"
+ $DOCKERMGR_DOCKER_BIN rm nginx-manager -f &>/dev/null
+ if __install_script nginx-manager &>/dev/null; then
+ printf_yellow "Username: admin@example.com"
+ printf_yellow "Password: changeme"
+ printf_yellow "URL: http://nginx-manager.local:8888"
+ printf_green "nginx-manager has been installed"
+ else
+ printf_red "Failed to install nginx-proxy-manager"
+ fi
+ echo
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_swap() {
+ local swapSize="${1:-2}"
+ local swapName="dockermgr.swap"
+ local swapDir="/var/lib/cache/swap"
+ local setSwapSize=$((swapSize * 1024))
+ local swapLocation="$swapDir/$swapName"
+ [ -f "$swapLocation" ] && return 0
+ printf_blue "Creating swap file and setting size to ${swapSize}G"
+ [ -d "$swapDir" ] || sudo mkdir -p "$swapDir"
+ sudo dd if=/dev/zero bs=1M count=$setSwapSize of="$swapLocation" &>/dev/null
+ sudo chmod 600 "$swapLocation" &>/dev/null && sudo mkswap "$swapLocation" &>/dev/null && sudo swapon "$swapLocation" &>/dev/null
+ grep -qsw "$swapLocation" "/etc/fstab" || echo "$swapLocation swap swap defaults 0 0" | sudo tee -p -a "/etc/fstab" &>/dev/null
+ if grep -qsw "$swapLocation" "/etc/fstab" && [ -n "$(__swap_status "$swapLocation")" ]; then
+ printf_green "The swap file has been created"
+ return 0
+ else
+ printf_red "Failed to create the swap file"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__kasm_bin() {
+ local port=$1
+ sudo -HE /tmp/kasm_release/install.sh \
+ --accept-eula \
+ --no-check-disk \
+ --use-rolling-images \
+ -L $port 2>/dev/null
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__install_kasm() {
+ local port="" url="" file=""
+ local version="${DOCKERMGR_KASM_VERSION:-1.16.0.f2d6e1}"
+ if [ -f "$DOCKERMGR_CONFIG_DIR/kasm_port" ]; then
+ port="$(<"$DOCKERMGR_CONFIG_DIR/kasm_port")"
+ else
+ port="$(__generate_random_port || echo '19042')"
+ fi
+ url="https://kasm-static-content.s3.amazonaws.com"
+ file="kasm_release_${version}.tar.gz"
+ printf_green "Downloading kasm installation file"
+ cd "/tmp" || printf_exit "Failed to cd into /tmp"
+ [ -d "/tmp/kasm_release" ] && rm -Rf "/tmp/kasm_release"
+ curl -q -LSsf "$url/$file" -o "/tmp/$file" 2>/dev/null || printf_exit "Failed to download the file"
+ [ -f "/tmp/$file" ] && tar -xf "/tmp/$file" || printf_exit "Failed to extract the file"
+ if [ -f "/tmp/kasm_release/install.sh" ]; then
+ cd "/tmp/kasm_release" || printf_exit "Failed to cd into /tmp/kasm_release"
+ printf_green "Please wait while I install kasm which may take some time"
+ sudo chmod 755 "/tmp/kasm_release/install.sh"
+ if __kasm_bin $port; then
+ printf_green "kasm has been installed and should be running on https://${CURRENT_IP_4:-$HOSTNAME}:${port}"
+ echo $port >"$DOCKERMGR_CONFIG_DIR/kasm_port"
+ else
+ printf_exit "Failed to install kasm"
+ fi
+ else
+ printf_exit "Failed to install kasm"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_compose() {
+ os="$(uname -s | tr '[:upper:]' '[:lower:]')"
+ arch="$(uname -m | tr '[:upper:]' '[:lower:]')"
+ release="$(__get_releases_github "docker/compose" | grep "docker-compose-$os-$arch$")"
+ if [ "$1" != "update" ] && cmd_exists docker-compose; then
+ return 0
+ elif [ -n "$release" ]; then
+ printf_green "Attempting to install docker-compose"
+ sudo curl -q -LSsf "https://github.com/docker/compose/releases/download/latest/docker-compose-$os-$arch" -o "/usr/local/bin/docker-compose" 2>/dev/null
+ [ -x "$(builtin type -P docker-compose 2>/dev/null)" ] || sudo chmod +x "/usr/local/bin/docker-compose"
+ cmd_exists docker-compose && printf_cyan "docker-compose has been installed" || printf_exit "Failed to download docker-compose"
+ else
+ printf_exit "Can not get release from: https://github.com/docker/compose/releases/latest"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_auth_token() {
+ local user="${1:-$DOCKERHUB_USERNAME}"
+ local pass="${2:-$DOCKERHUB_PASSWORD}"
+ curl -q -LSsf -H "Content-Type: application/json" -X POST -d "{\"username\": \"$user\", \"password\": \"$pass\"}" "$DOCKERMGR_HUB_URL/v2/users/login/" 2>"$DOCKERMGR_CACHE_DIR/token.err" | jq -r '.token' | grep '^' || { echo '' && return 1; }
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__orgs_api_auth() {
+ if [ -z "${1:-$DOCKERMGR_REGISTRY_USERNAME}" ]; then
+ printf_exit "Please provide a username or organization name"
+ fi
+ local user="${1:-$DOCKERMGR_REGISTRY_USERNAME}" && shift 1
+ if [ -n "$user" ] && [ -n "$1" ]; then
+ local pass="$1" && shift 1
+ if [ ! -f "$DOCKERMGR_CONFIG_DIR/.hub_password" ]; then
+ printf_green "Password saved to $DOCKERMGR_CONFIG_DIR/.hub_password"
+ echo "$pass" >"$DOCKERMGR_CONFIG_DIR/.hub_password"
+ fi
+ elif [ -f "$DOCKERMGR_CONFIG_DIR/.hub_password" ]; then
+ printf_green "Setting password from $DOCKERMGR_CONFIG_DIR/.hub_password"
+ local pass="$(<"$DOCKERMGR_CONFIG_DIR/.hub_password")"
+ else
+ printf_cyan "Please put your hub password/api token in:"
+ printf_cyan "$DOCKERMGR_CONFIG_DIR/.hub_password"
+ printf_yellow "And set the permissions to 600"
+ exit 1
+ fi
+ chmod 600 "$DOCKERMGR_CONFIG_DIR/.hub_password"
+ TOKEN=$(__api_auth_token "$@")
+ if [ -n "$TOKEN" ]; then
+ printf_purple "Successfully retrieved a token"
+ printf_yellow "$DOCKERMGR_CACHE_DIR/token"
+ echo "$TOKEN" >"$DOCKERMGR_CACHE_DIR/token"
+ return 0
+ else
+ printf_red "An error has occured. The message is:"
+ [ -f "$DOCKERMGR_CACHE_DIR/token" ] && rm "$DOCKERMGR_CACHE_DIR/token"
+ [ -f "$DOCKERMGR_CACHE_DIR/token.err" ] && cat "$DOCKERMGR_CACHE_DIR/token.err" | printf_readline 1 &&
+ rm "$DOCKERMGR_CACHE_DIR/token.err"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__orgs_api_list() {
+ [ -n "$1" ] || printf_exit "Please provide a organization name"
+ results="$(curl -q -LSsf "$DOCKERMGR_HUB_URL/v2/repositories/$1?page_size=1000" 2>/dev/null | jq -r '.results|.[]|.name' | grep -v 'null' | grep '^' || return)"
+ if [ -n "$results" ]; then
+ printf '%s\n' "$results" | printf_column 154
+ else
+ printf_red "No repositories found for $1"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__orgs_api_org_info() {
+ if [ -f "$DOCKERMGR_CACHE_DIR/token" ]; then
+ local org="" repo=""
+ local token="$(<"$DOCKERMGR_CACHE_DIR/token")"
+ if echo "$1" | grep -q '/'; then
+ org="$(echo "$1" | awk -F '/' '{print $1}')"
+ repo="$(echo "$1" | awk -F '/' '{print $2}')"
+ shift 1
+ else
+ org="${1:-$DOCKERMGR_REGISTRY_USERNAME}"
+ repo="$2"
+ shift 2
+ fi
+ [ -n "$org" ] || printf_exit "Usage: $APPNAME api info [org] [repo]"
+ curl -q -fsSL -X GET -H "Authorization: Bearer $token" "$DOCKERMGR_REGISTRY_URL/v2/repositories/$org/${repo:-}?page_size=10000" 2>/dev/null | jq
+ else
+ printf_exit 1 1 "token not set: $APPNAME api auth [username] [password]"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__orgs_api_user_info() {
+ if [ -f "$DOCKERMGR_CACHE_DIR/token" ]; then
+ local token="$(<"$DOCKERMGR_CACHE_DIR/token")"
+ curl -q -fsSL -X GET -H "Authorization: Bearer $token" "$DOCKERMGR_REGISTRY_URL/v2/user/" 2>/dev/null | jq
+ else
+ printf_exit 1 1 "token not set: $APPNAME api auth [username] [password]"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__orgs_api_delete() {
+ local org="" repo=""
+ local prettify_registry="${DOCKERMGR_REGISTRY_URL//http*:\/\//}"
+ if echo "$1" | grep -q '/'; then
+ org="$(echo "$1" | awk -F '/' '{print $1}')"
+ repo="$(echo "$1" | awk -F '/' '{print $2}')"
+ shift 1
+ else
+ org="$1"
+ repo="$2"
+ shift 2
+ fi
+ [ -n "$org" ] || printf_exit "Please provide a organization name"
+ [ -n "$repo" ] || printf_exit "Please provide a repository name"
+ if [ -f "$DOCKERMGR_CACHE_DIR/token" ]; then
+ local TOKEN="$(<"$DOCKERMGR_CACHE_DIR/token")"
+ printf_cyan "Attempting to delete $repo from $org on $prettify_registry"
+ curl -q -LSsfi -H "Authorization: Bearer $TOKEN" -X DELETE "$DOCKERMGR_REGISTRY_URL/v2/repositories/$org/$repo" &>"$DOCKERMGR_CACHE_DIR/delete.log"
+ if grep -qis '405 Not Allowed' "$DOCKERMGR_CACHE_DIR/delete.log"; then
+ __api_auth_error
+ elif grep -qis '404.*Not.*Found' "$DOCKERMGR_CACHE_DIR/delete.log"; then
+ message="$repo does not exist on: $DOCKERMGR_REGISTRY_URL/v2/repositories/$org/$repo"
+ elif grep -qis 'HTTP.*404.NO.*Content' "$DOCKERMGR_CACHE_DIR/delete.log"; then
+ message="$repo does not exist on: $DOCKERMGR_REGISTRY_URL/v2/repositories/$org/$repo"
+ elif grep -qis 'HTTP.*204.NO.*Content' "$DOCKERMGR_CACHE_DIR/delete.log"; then
+ message="$repo does not exist on: $DOCKERMGR_REGISTRY_URL/v2/repositories/$org/$repo"
+ elif grep -qis 'HTTP.*202.*Accepted' "$DOCKERMGR_CACHE_DIR/delete.log"; then
+ message="Successfully deleted $repo from: $DOCKERMGR_REGISTRY_URL/v2/repositories/$org/$repo"
+ else
+ printf_exit "Failed to delete $repo from $DOCKERMGR_REGISTRY_URL/v2/repositories/$org/$repo"
+ grep -i 'HTTP/.*' "$DOCKERMGR_CACHE_DIR/delete.log" | printf_readline 1
+ grep -i 'URL returned error' "$DOCKERMGR_CACHE_DIR/delete.log" | sed 's|*.The requested URL returned error: ||g' | printf_readline 1
+ fi
+ rm -Rf "$DOCKERMGR_CACHE_DIR/delete.log"
+ else
+ printf_exit 1 1 "token not set: $APPNAME api auth [username] [password]"
+ fi
+ printf_green "$message"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__orgs_api_update() {
+ local org="" repo=""
+ if echo "$1" | grep -q '/'; then
+ org="$(echo "$1" | awk -F '/' '{print $1}')"
+ repo="$(echo "$1" | awk -F '/' '{print $2}')"
+ shift 1
+ else
+ org="$1"
+ repo="$2"
+ shift 2
+ fi
+ printf_exit "This is not working for me!"
+ [ -n "$org" ] || printf_exit "Please provide a organization name"
+ [ -n "$repo" ] || printf_exit "Please provide a repository name"
+ [ -n "$1" ] && field="$1" || printf_exit "Please provide a field to update [description,full_description,is_private]"
+ [ -n "$2" ] && field_value="$2" || printf_exit "Please provide a value to field"
+ # [ -n "$3" ] && full_description="$3" || printf_exit "Please provide full description"
+ # [ -n "$4" ] && is_private="$4" || printf_exit "private repo true/false"
+ # [ -n "$5" ] && can_edit="$5" || printf_exit "can edit true/false"
+ #-d "{\"description\": \"$description\", \"is_private\": \"$is_private\", \"can_edit\": \"$can_edit\", \"full_description\": \"$full_description\"}" \
+ if [ -f "$DOCKERMGR_CACHE_DIR/token" ]; then
+ local TOKEN="$(<"$DOCKERMGR_CACHE_DIR/token")"
+ printf_cyan "Attempting to update $org from:"
+ printf_cyan "$DOCKERMGR_REGISTRY_URL/v2/repositories/$org/$repo"
+ curl -q -LSsfi -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" -X PATCH -d "{\"$field\":\"$field_value\"}" \
+ "$DOCKERMGR_REGISTRY_URL/v2/repositories/$org/$repo/" &>"$DOCKERMGR_CACHE_DIR/update.log"
+ if grep -qis '405 Not Allowed' "$DOCKERMGR_CACHE_DIR/update.log"; then
+ __api_auth_error
+ elif grep -qis '404.*Not.*Found' "$DOCKERMGR_CACHE_DIR/update.log"; then
+ printf_green "Repository does not exist"
+ elif grep -qis '403.*FORBIDDEN' "$DOCKERMGR_CACHE_DIR/update.log"; then
+ printf_green "You are not authorized to make this request"
+ elif grep -qis 'HTTP.*404.NO.*Content' "$DOCKERMGR_CACHE_DIR/update.log"; then
+ printf_green "Repository does not exist"
+ elif grep -qis 'HTTP.*204.NO.*Content' "$DOCKERMGR_CACHE_DIR/update.log"; then
+ printf_green "Repository does not exist"
+ elif grep -qis 'HTTP.*202.*Accepted' "$DOCKERMGR_CACHE_DIR/update.log"; then
+ printf_green "Successfully updated the repository"
+ else
+ printf_exit "Failed to update the repository"
+ grep -i 'HTTP/.*' "$DOCKERMGR_CACHE_DIR/update.log" | printf_readline 1
+ grep -i 'URL returned error' "$DOCKERMGR_CACHE_DIR/update.log" | sed 's|*.The requested URL returned error: ||g' | printf_readline 1
+ fi
+ else
+ printf_exit 1 1 "Well something went terribly wrong"
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__api_auth_error() {
+ printf_exit "Please authenticate with the command:"
+ printf_yellow "dockermgr api auth username password/key"
+ exit 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__datecmd() {
+ local version="$(date +"$1")"
+ printf_yellow "Creating the version file with version $version"
+ [ -n "$2" ] && printf '%s\n' "$version" >"$2" && printf '\n' || printf '%s\n' "$version"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__restart_container() {
+ local containers="$*"
+ local existing="$(docker ps -a | grep ' Up ' | grep -v ' NAMES$' | awk '{print $NF}')"
+ if [ -n "$containers" ]; then
+ restart="$containers"
+ elif [ -n "$existing" ]; then
+ restart="$existing"
+ fi
+ for r in $restart; do
+ printf_cyan "Restarting container $r"
+ docker restart "$r" &>/dev/null
+ done
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__generate() {
+ local exitCode="0"
+ local workDir="$(realpath "${1:-$PWD}")"
+ local dataDir="$workDir/rootfs"
+ local binDir="$workDir/rootfs/usr/local/bin"
+ local version_file="$workDir/version.txt"
+ local readme_template="installers/dockermgr.md"
+ local date_time="${VERSION_DATE_FORMAT:-%Y%m%d%H%M-git}"
+ local name="$(basename -- "$(dirname "$workDir/install.sh")")"
+ export GEN_README_GIT_USER="$DOCKERMGR_GIT_USERNAME"
+ [ -d "$workDir" ] || mkdir -p "$workDir"
+ [ -d "$dataDir/data" ] || mkdir -p "$dataDir/data"
+ [ -d "$dataDir/config" ] || mkdir -p "$dataDir/config"
+ cd "$workDir" || printf_exit "Failed to cd to $workDir"
+ if [ -n "$DOCKERMGR_CREATE_BUILD" ]; then
+ readme_template="projects/docker.md"
+ [ -d "$binDir" ] || mkdir -p "$binDir"
+ [ -f "$workDir/Dockerfile" ] || gen-dockerfile --dir "$workDir" --template "alpine" "./Dockerfile" && echo ''
+ [ -f "$binDir/entrypoint-$name" ] || gen-script --dir "$workDir" --name "$name" "other/docker-entrypoint" "$binDir/entrypoint-$name"
+ # Validation check
+ [ -d "$binDir" ] || { printf_red "Failed to create $binDir" && exitCode=$(($exitCode + 1)); }
+ [ -f "$workDir/Dockerfile" ] || { printf_red "Failed to create $workDir/Dockerfile" && exitCode=$(($exitCode + 1)); }
+ [ -f "$binDir/entrypoint-$name" ] || { printf_red "Failed to create $binDir/entrypoint-$name" && exitCode=$(($exitCode + 1)); }
+ else
+ [ -f "$workDir/install.sh" ] || gen-script --dir "$workDir" "installers/dockermgr.sh" "$workDir/install.sh"
+ [ -f "$workDir/install.sh" ] || { printf_red "Failed to create $workDir/install.sh" && exitCode=$(($exitCode + 1)); }
+ fi
+ [ -f "$workDir/.dockerignore" ] || dockerignore --dir "$workDir"
+ [ -f "$workDir/version.txt" ] || __datecmd "$date_time" "$version_file"
+ [ -f "$workDir/.gitignore" ] || gitignore --dir "$workDir" default
+ [ -f "$workDir/LICENSE.md" ] || gen-license --dir "$workDir" "wtfpl" "LICENSE.md"
+ [ -f "$workDir/README.md" ] || gen-readme --dir "$workDir" "$readme_template" "$workDir/README.md"
+ [ -d "$dataDir/data" ] || { printf_red "Failed to create $dataDir/data" && exitCode=$(($exitCode + 1)); }
+ [ -d "$dataDir/config" ] || { printf_red "Failed to create $dataDir/config" && exitCode=$(($exitCode + 1)); }
+ [ -f "$workDir/README.md" ] || { printf_red "Failed to create $workDir/README.md" && exitCode=$(($exitCode + 1)); }
+ [ -f "$workDir/LICENSE.md" ] || { printf_red "Failed to create $workDir/LICENSE.md" && exitCode=$(($exitCode + 1)); }
+ [ -f "$workDir/version.txt" ] || { printf_red "Failed to create $workDir/version.txt" && exitCode=$(($exitCode + 1)); }
+ printf_green "Done setting up new docker directory"
+ if [ "$exitCode" -ne 0 ]; then
+ printf_red "Failed to setup the new docker directory"
+ exitCode=1
+ fi
+ echo ''
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__remove_test_container() {
+ if [ -n "$(__container_exists "$1" || false)" ]; then
+ printf_read_question "4" "Should I delete the container?" "1"
+ if printf_answer_yes; then
+ __docker rm -f --volumes "$1" &>/dev/null
+ sudo rm -Rf "$2" &>/dev/null
+ [ -d "$2" ] && [ -z "$(__container_exists "$1" || false)" ] && printf_yellow failed to delete "$2" && exit 0 || exit 1
+ fi
+ exit 0
+ else
+ printf_red "Failed to create $1"
+ [ -s "$DOCKERMGR_TEMP_FILE" ] && cat "$DOCKERMGR_TEMP_FILE" | printf_readline
+ exit 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__attach() {
+ local CONTAINER="${1:-$(__docker ps | grep -Eo "^[0-9a-z]{8,}\b")}"
+ [ -n "$CONTAINER" ] || printf_exit "Please provide the container name"
+ __docker ps 2>/dev/null | grep -q "$CONTAINER" || { printf_red "There are no running containers" && return 1; }
+ __docker attach "$CONTAINER"
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__how_long_did_it_take() {
+ local retprev=$?
+ local retval=${1:-$retprev}
+ [ -n "$DOCKERMGR_START_TIMER" ] || return 0
+ [ "$DOCKERMGR_CMD_EXISTS_BC" != "false" ] || return $retval
+ local stop_time="$(date +%s.%N)"
+ local dt=$(echo "$stop_time - $DOCKERMGR_START_TIMER" | bc)
+ local dd=$(echo "$dt/86400" | bc)
+ local dt2=$(echo "$dt-86400*$dd" | bc)
+ local dh=$(echo "$dt2/3600" | bc)
+ local dt3=$(echo "$dt2-3600*$dh" | bc)
+ local dm=$(echo "$dt3/60" | bc)
+ local ds=$(echo "$dt3-60*$dm" | bc)
+ printf_purple "$(LC_NUMERIC=C printf "Total runtime: %d Days, %02d Hours, %02d Minutes, %02.4f Seconds\n" $dd $dh $dm $ds)"
+ return $retval
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__curl_save() { { [ -f "$2" ] && rm -Rf "$2" || true; } && curl -q -LSsf -H 'Cache-Control: no-cache, no-store' "$1" -o "$2" || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Default variables
+exitCode="0"
+DOCKERMGR_START_TIMER="$(date +%s.%N)"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DOCKERMGR_LOG_DIR="${DOCKERMGR_LOG_DIR:-$HOME/.local/log/dockermgr}"
+DOCKERMGR_CACHE_DIR="${DOCKERMGR_CACHE_DIR:-$HOME/.cache/dockermgr}"
+DOCKERMGR_CONFIG_DIR="${DOCKERMGR_CONFIG_DIR:-$HOME/.config/myscripts/dockermgr}"
+DOCKERMGR_OPTIONS_DIR="${DOCKERMGR_OPTIONS_DIR:-$HOME/.local/share/myscripts/dockermgr/options}"
+DOCKERMGR_CONFIG_BACKUP_DIR="${DOCKERMGR_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/dockermgr/backups}"
+DOCKERMGR_TEMP_DIR="${DOCKERMGR_TEMP_DIR:-$HOME/.local/tmp/system_scripts/dockermgr}"
+DOCKERMGR_CONFIG_FILE="${DOCKERMGR_CONFIG_FILE:-settings.conf}"
+DOCKERMGR_GOOD_MESSAGE="${DOCKERMGR_GOOD_MESSAGE:-Everything Went OK}"
+DOCKERMGR_ERROR_MESSAGE="${DOCKERMGR_ERROR_MESSAGE:-Well something seems to have gone wrong}"
+DOCKERMGR_NOTIFY_ENABLED="${DOCKERMGR_NOTIFY_ENABLED:-yes}"
+DOCKERMGR_NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$APPNAME}"
+DOCKERMGR_NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DOCKERMGR_NOTIFY_CLIENT_ICON}"
+DOCKERMGR_OUTPUT_COLOR="${DOCKERMGR_OUTPUT_COLOR:-5}"
+DOCKERMGR_OUTPUT_COLOR_GOOD="${DOCKERMGR_OUTPUT_COLOR_GOOD:-2}"
+DOCKERMGR_OUTPUT_COLOR_ERROR="${DOCKERMGR_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DOCKERMGR_GIT_USERNAME="${DOCKERMGR_GIT_USERNAME:-}"
+DOCKERMGR_REGISTRY_USERNAME="${DOCKERMGR_REGISTRY_USERNAME:-casjaysdevdocker}"
+DOCKERMGR_HOME="${DOCKERMGR_HOME:-$HOME/.config/myscripts/dockermgr}"
+DOCKERMGR_GIT_REPO="${DOCKERMGR_GIT_REPO:-https://github.com/dockermgr}"
+DOCKERMGR_GIT_SRC_REPO_NAME="${DOCKERMGR_GIT_SRC_REPO_NAME:-https://github.com/casjaysdevdocker}"
+DOCKERMGR_GIT_SRC_REPO_API="${DOCKERMGR_GIT_SRC_REPO_API:-https://api.github.com/orgs/$(basename $DOCKERMGR_GIT_SRC_REPO_NAME)/repos}"
+DOCKERMGR_CLONE_DIR="${DOCKERMGR_CLONE_DIR:-$HOME/Projects/github/dockermgr}"
+DOCKERMGR_DOCKER_BIN="${DOCKERMGR_DOCKER_BIN:-sudo -HE docker}"
+DOCKERMGR_INSTALL_SCRIPT="${DOCKERMGR_INSTALL_SCRIPT:-https://get.docker.com}"
+DOCKERMGR_K3B_INSTALL_SCRIPT="${DOCKERMGR_K3B_INSTALL_SCRIPT:-https://get.k3s.io}"
+DOCKERMGR_HUB_URL="${DOCKERMGR_HUB_URL:-https://hub.docker.com}"
+DOCKERMGR_REGISTRY_URL="${DOCKERMGR_REGISTRY_URL:-https://hub.docker.com}"
+DOCKERMGR_INSTALL_TMP="${DOCKERMGR_INSTALL_TMP:-/tmp/docker_install.sh}"
+DOCKERMGR_NET_DEVICE="${DOCKERMGR_NET_ADDRESS:-docker0}"
+DOCKERMGR_BUILD_IMAGE="${DOCKERMGR_BUILD_IMAGE:-casjaysdevdocker/docker:latest}"
+DOCKERMGR_FORCE_INSTALL="${DOCKERMGR_FORCE_INSTALL:-}"
+DOCKERMGER_MANIFEST_DELETE_TMP_TAGS=""
+DOCKERMGR_MANIFEST_TEMPLATE="${DOCKERMGR_MANIFEST_TEMPLATE:-https://gist.githubusercontent.com/casjay/d7a33dda283183c0187ce67bf8dbd9d3/raw/docker-migrate.txt}"
+DOCKERMGR_SHOW_USAGE="${DOCKERMGR_SHOW_USAGE:-yes}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DOCKERMGR_CONFIG_DIR/$DOCKERMGR_CONFIG_FILE" ] || [[ "$*" = *config ]] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DOCKERMGR_CONFIG_DIR/$DOCKERMGR_CONFIG_FILE" ] && . "$DOCKERMGR_CONFIG_DIR/$DOCKERMGR_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories and files exist
+[ -d "$DOCKERMGR_LOG_DIR" ] || mkdir -p "$DOCKERMGR_LOG_DIR" &>/dev/null
+[ -d "$DOCKERMGR_TEMP_DIR" ] || mkdir -p "$DOCKERMGR_TEMP_DIR" &>/dev/null
+[ -d "$DOCKERMGR_CACHE_DIR" ] || mkdir -p "$DOCKERMGR_CACHE_DIR" &>/dev/null
+[ -d "$DOCKERMGR_CONFIG_DIR/containers" ] || mkdir -p "$DOCKERMGR_CONFIG_DIR/containers" &>/dev/null
+DOCKERMGR_TEMP_FILE="${DOCKERMGR_TEMP_FILE:-$(mktemp $DOCKERMGR_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap 'exitCode=${exitCode:-0};[ -n "$DOCKERMGR_TEMP_FILE" ] && [ -f "$DOCKERMGR_TEMP_FILE" ] && rm -Rf "$DOCKERMGR_TEMP_FILE" &>/dev/null' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+if [ "$DOCKERMGR_NOTIFY_ENABLED" = "yes" ]; then
+ __notifications() {
+ export NOTIFY_GOOD_MESSAGE="${DOCKERMGR_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${DOCKERMGR_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_NAME="${DOCKERMGR_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_ICON="${DOCKERMGR_NOTIFY_CLIENT_ICON}"
+ notifications "$@" || return 1
+ }
+else
+ __notifications() { false; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Show warn message if variables are missing
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set additional variables/Argument/Option settings
+SETARGS="$*"
+SHORTOPTS="p:,P,v:,m:,e:,d,u:,w:,"
+LONGOPTS="raw,completions:,options,config,version,help,dir:,"
+LONGOPTS+="force,all,describe:,platform:,dockerfile,name:,info,domain:,hostname:,network:,registry:,tag:no-delete,interactive,cron"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="service proxy health attach multiarch builder api enter test exec active available connect cron download inactive init install k3b minikube "
+ARRAY+="list log ps rancher remove rm rmi run search status update version ds network helm prune generate manifest rebuild "
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST="airsonic ampache apache2 aria2 buildah bun caddy cherokee community coolify couchdb daapd ddns deno dictd docker dockerproxy flaresolverr "
+LIST+="gitea gohttpserver hub ifconfig it-tools jekyll lenpaste lidarr lighttpd mariadb mongodb navidrome nextcloud nginx nginx-manager "
+LIST+="opengist php pihole podman portainer postgres prowlarr radarr rancher rarbg readarr readmes redis registry search soft-serve sonarr "
+LIST+="stikked supabase template tor tor-browser traefik transmission uptime vault watchtower webvirtmgr wireguard yacht ympd youtubedl-web "
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SRCS="$LIST"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$(basename -- "$0" 2>/dev/null)" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case $1 in
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --dir)
+ DOCKERMGR_CWD="$2"
+ shift 2
+ ;;
+ --force)
+ shift 1
+ export DOCKERMGR_FORCE_INSTALL="true"
+ ;;
+ --all)
+ shift 1
+ INSTALL_ALL="true"
+ ;;
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ printf_readline() { cat -; }
+ printf_red() { echo "$1"; }
+ printf_green() { echo "$1"; }
+ printf_cyan() { echo "$1"; }
+ printf_purple() { echo "$1"; }
+ printf_exit() { echo "$2"; }
+ ;;
+ --cron)
+ shift 1
+ __create_docker_cron
+ exit $?
+ ;;
+ --dockerfile)
+ shift 1
+ DOCKERMGR_CREATE_BUILD="true"
+ ;;
+ --info)
+ shift 1
+ DOCKERMGR_SHOW_INFO="true"
+ ;;
+ -d)
+ shift 1
+ DOCKER_ARG+="--detach "
+ ;;
+ -P)
+ shift 1
+ DOCKER_ARG+="--publish-all "
+ ;;
+ -p)
+ if [ -n "$2" ]; then
+ ports="${2//,/ }"
+ for test in $ports; do
+ echo "$test" | grep -q ":" && port="$test" || port="$test:$test"
+ DOCKER_ARG+="--publish $port "
+ done
+ unset test ports port
+ fi
+ shift 2
+ ;;
+ -e)
+ DOCKER_ARG+="--env $2 "
+ shift 2
+ ;;
+ -v)
+ echo "$2" | grep -q ":" || printf_exit "Invalid mount: /path/to/dir:/mnt/dir"
+ DOCKER_ARG+="--volume $2 "
+ shift 2
+ ;;
+ -m)
+ DOCKER_ARG+="--platform $2 "
+ shift 2
+ ;;
+ -u)
+ DOCKER_ARG+="--user $2 "
+ shift 2
+ ;;
+ -w)
+ DOCKER_ARG+="--workdir $2 "
+ shift 2
+ ;;
+ --platform)
+ DOCKER_PULL_ARG+="--platform $2 "
+ DOCKER_ARG+="--platform $2 "
+ shift 2
+ ;;
+ --network)
+ DOCKER_ARG+="--network $2 "
+ shift 2
+ ;;
+ --interactive)
+ DOCKER_ARG+="--interactive --tty "
+ shift 2
+ ;;
+ --describe)
+ DOCKERHUB_DESCRIPTION="$2"
+ shift 2
+ ;;
+ --name)
+ DOCKERMGR_CONTAINER_NAME="$2"
+ shift 2
+ ;;
+ --domain)
+ export CONTAINER_DOMAINNAME="$2"
+ shift 2
+ ;;
+ --hostname)
+ export CONTAINER_HOSTNAME="$2"
+ shift 2
+ ;;
+ --registry)
+ DOCKERMGR_SET_REGISTRY="$2"
+ shift 2
+ ;;
+ --tag)
+ DOCKERMGR_SET_TAG="$2"
+ shift 2
+ ;;
+ --no-delete)
+ shift 1
+ DOCKERMGER_MANIFEST_DELETE_TMP_TAGS="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+#set -- "$SETARGS"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+__cmd_exists docker || __cmd_exists podman || [ "$1" = "init" ] || { __init || exit 1; }
+__docker_service || [ "$1" = "init" ] || { __notifications "$APPNAME" "Docker is not running" && exit 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+__cmd_exists bc || DOCKERMGR_CMD_EXISTS_BC="false"
+cmd_exists --error --ask bash || exit 1 # exexpectit 1 if not found
+#am_i_online --error || exit 1 # exit 1 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+__cmd_exists expect_unbuffer && unbuffer() { expect_unbuffer "$@"; }
+[ -n "$(type unbuffer)" ] || unbuffer() { printf_exit "The command unbuffered is required: unbuffered or expect or expect-devel/expect-dev"; }
+__cmd_exists podman && alias docker='podman ' && DOCKERMGR_CLI="podman"
+[ -d "$DOCKERMGR_HOME" ] || mkdir -p "$DOCKERMGR_HOME"
+[ -f "$DOCKERMGR_HOME/env" ] && rm -Rf "$DOCKERMGR_HOME/env"
+[ -d "$DOCKERMGR_HOME/env" ] && mkdir -p "$DOCKERMGR_HOME/env"
+[ -f "$DOCKERMGR_HOME/.env.sh" ] || touch "$DOCKERMGR_HOME/.env.sh"
+[ -f "$DOCKERMGR_CONFIG_DIR/.hub_username" ] && DOCKERHUB_USERNAME="$(<"$DOCKERMGR_CONFIG_DIR/.hub_username")"
+[ -f "$DOCKERMGR_CONFIG_DIR/.hub_password" ] && DOCKERHUB_PASSWORD="$(<"$DOCKERMGR_CONFIG_DIR/.hub_password")"
+DOCKERMGR_NET_ADDRESS="$(ip a show $DOCKERMGR_NET_DEVICE 2>/dev/null | grep -w 'inet' | awk -F'/' '{print $1}' | awk '{print $2}' | grep '^' || false)"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+export DOCKERMGRREPO="$DOCKERMGR_GIT_REPO" DOCKERMGR_HOME="${DOCKERMGR_HOME:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+api)
+ shift 1
+ case $1 in
+ auth)
+ shift 1
+ case "$1" in
+ info)
+ shift 1
+ __orgs_api_user_info "$@"
+ exit
+ ;;
+ *)
+ shift 1
+ DOCKERHUB_USERNAME="${1:-$DOCKERHUB_USERNAME}"
+ DOCKERHUB_PASSWORD="${2:-$DOCKERHUB_PASSWORD}"
+ [ -n "$DOCKERHUB_USERNAME" ] || { printf_read_question 4 "What is your username:" "100" "DOCKERHUB_USERNAME" || return 1; } || printf_exit "usage: $APPNAME auth [username] [password]"
+ [ -n "$DOCKERHUB_PASSWORD" ] || { printf_read_password 4 "What is your password" "DOCKERHUB_PASSWORD" || return 1; } || printf_exit "usage: $APPNAME auth [$DOCKERHUB_USERNAME] [password]"
+ [ -f "$DOCKERMGR_CONFIG_DIR/.hub_username" ] || echo "$DOCKERHUB_USERNAME" >"$DOCKERMGR_CONFIG_DIR/.hub_username"
+ [ -f "$DOCKERMGR_CONFIG_DIR/.hub_password" ] || echo "$DOCKERHUB_PASSWORD" >"$DOCKERMGR_CONFIG_DIR/.hub_password"
+ __orgs_api_auth "$@"
+ exit $?
+ ;;
+ esac
+ ;;
+ list)
+ shift 1
+ __orgs_api_list "${1:-$DOCKERMGR_REGISTRY_USERNAME}"
+ exit $?
+ ;;
+ info)
+ shift 1
+ echo "$@"
+ __orgs_api_org_info "$@"
+ exit
+ ;;
+ update)
+ shift 1
+ __orgs_api_update "$@"
+ ;;
+ readme)
+ shift 1
+ __upload_readme_to_hub "$@"
+ exit $?
+ ;;
+ sources)
+ shift 1
+ __api_source_list "$@"
+ exit $?
+ ;;
+ clone)
+ shift 1
+ $APPNAME clone src "$@"
+ exit $?
+ ;;
+ delete)
+ shift 1
+ case "$1" in
+ tag)
+ shift 1
+ [ $# -eq 2 ] || printf_exit "Usage: $APPNAME api delete tag [org/repo] [tag]"
+ __registry_delete_tag "$1" "$2"
+ exit $?
+ ;;
+ repo)
+ shift 1
+ [ $# -eq 1 ] || [ $# -eq 2 ] || printf_exit "Usage: $APPNAME api delete repo [org/repo]"
+ __orgs_api_delete "$@"
+ exit $?
+ ;;
+ *)
+ [ $# -eq 1 ] || [ $# -eq 2 ] || printf_exit "Usage: $APPNAME api delete [org/repo]"
+ __orgs_api_delete "$@"
+ exit $?
+ ;;
+ esac
+ ;;
+ *)
+ printf_help "Usage: $APPNAME api [auth,list,delete,info,update,readme,sources,clone]"
+ ;;
+ esac
+ ;;
+
+health)
+ shift 1
+ docker inspect --format "{{json .State.Health }}" $1 | jq -r '.'
+ exit $?
+ ;;
+
+proxy)
+ shift 1
+ __docker_proxy_setup
+ exit $?
+ ;;
+
+service)
+ shift 1
+ __update_systemd_docker_service
+ ;;
+
+commit)
+ shift 1
+ name="$1"
+ tag="$2"
+ [ -n "$name" ] || printf_help "Usage: $APPNAME commit name tag"
+ commit_id="$(docker ps -l 2>/dev/null | grep "$name" | awk '{print $1}' | grep '^' || false)"
+ if [ -n "$commit_id" ]; then
+ printf_cyan "$name: $commit_id"
+ commit_container="$(docker commit $commit_id | grep '^' || false)"
+ if [ -n "$commit_container" ]; then
+ printf_green "Successfully committed: $commit_container"
+ if [ -n "$tag" ]; then
+ docker tag $name $tag
+ fi
+ else
+ printf_exit "Failed to commit $commit_id"
+ fi
+ else
+ printf_exit "No containers match $name"
+ fi
+ exit $?
+ ;;
+
+manifest)
+ shift 1
+ DOCKERMGR_EXIT_STATUS=0
+ DOCKERMGR_BUILD_FILE_LOG="$DOCKERMGR_LOG_DIR/manifest.log"
+ DOCKERMGR_BUILD_FILE_TEMP="$DOCKERMGR_TEMP_DIR/manifest.log"
+ if [ -f "$1" ]; then
+ cat "$1" >"$DOCKERMGR_BUILD_FILE_TEMP"
+ elif [ $# -eq 0 ] && [ -p "/dev/stdin" ]; then
+ cat - >"$DOCKERMGR_BUILD_FILE_TEMP"
+ elif [ $# -ge 1 ]; then
+ printf '%s\n' "$@" >"$DOCKERMGR_BUILD_FILE_TEMP"
+ elif __curl_save "$DOCKERMGR_MANIFEST_TEMPLATE" "$HOME/Documents/docker-migrate.txt"; then
+ cat "$HOME/Documents/docker-migrate.txt" >"$DOCKERMGR_BUILD_FILE_TEMP"
+ else
+ printf_cyan "Usage: $APPNAME manifest [file,pull push #description]"
+ fi
+ [ -s "$DOCKERMGR_CONFIG_DIR/.hub_username" ] && [ -s "$DOCKERMGR_CONFIG_DIR/.hub_password" ] && __orgs_api_auth "$@" >/dev/null 2>&1 || printf_exit "Failed to authenticate"
+ cat "$DOCKERMGR_BUILD_FILE_TEMP" | sed 's|^#.*||g' | grep -Ev '^$' | grep '^' | while read line; do
+ image="$(echo "$line" | awk '{print $1}')"
+ name="$(echo "$line" | awk '{print $2}' | grep '^' || echo "$(basename -- "$image")")"
+ url="//$(echo "$line" | awk '{print $1}' | grep '/.*/' | awk -F '/' '{print $1}')"
+ description="$(echo "$line" | awk -F '#' '{print $2}' | sed 's/^[ \t]*//' | grep '^')"
+ echo "$name" | grep -q '/' || name="$DOCKERMGR_REGISTRY_USERNAME/$name"
+ __create_manifest "$image" "$name" "$description"
+ retVal=$?
+ DOCKERMGR_EXIT_STATUS=$((retVal + DOCKERMGR_EXIT_STATUS))
+ echo ""
+ done
+ [ -f "$DOCKERMGR_BUILD_FILE_TEMP" ] && rm -Rf "$DOCKERMGR_BUILD_FILE_TEMP"
+ unset DOCKERMGR_BUILD_FILE_LOG DOCKERMGR_BUILD_FILE_TEMP
+ __how_long_did_it_take $DOCKERMGR_EXIT_STATUS
+ exit $?
+ ;;
+
+rebuild)
+ shift 1
+ repo_dir="$(realpath "${1:-$PWD}")"
+ repo_name="$(basename -- "${2:-$repo_dir}")"
+ if [ -d "$1" ]; then
+ [ -n "$(ls -A "$repo_dir"/Dockerfile* 2>/dev/null)" ] || printf_exit "Can not find a Dockerfile in $repo_dir"
+ __cd "$repo_dir" && buildx all --image ${DOCKERMGR_CONTAINER_NAME:-$repo_name}
+ exit $?
+ elif [ -f "$1" ]; then
+ repo_dir="$(realpath "$(dirname "$repo_dir")")"
+ repo_name="$(basename -- "${2:-$repo_dir}")"
+ [ -n "$(ls -A "$repo_dir"/Dockerfile* 2>/dev/null)" ] || printf_exit "Can not find a Dockerfile in $repo_dir"
+ __cd "$repo_dir" && buildx all --image ${DOCKERMGR_CONTAINER_NAME:-$repo_name}
+ exit $?
+ else
+ repo_url="$1"
+ repo_name="${2:-$repo_name}"
+ org_name="$(basename -- "$(dirname "$repo_url")")"
+ build_dir="$DOCKERMGR_TEMP_DIR/${org_name}_${repo_name}"
+ [ -n "$repo_url" ] && [ -n "$repo_name" ] || printf_exit "Usage: $APPNAME build [repo] [name]"
+ if [ ! -d "$build_dir/.git" ]; then
+ printf_cyan "Cloning $repo_url > $build_dir"
+ [ -d "$build_dir" ] && rm -Rf "$build_dir"
+ git clone --depth 1 -q "$repo_url" "$build_dir"
+ fi
+ [ -n "$(ls -A "$build_dir"/Dockerfile* 2>/dev/null)" ] || printf_exit "Can not find a Dockerfile in $build_dir"
+ __cd "$build_dir" && buildx all --image ${DOCKERMGR_CONTAINER_NAME:-$repo_name} && rm -Rf "$build_dir"
+ exit $?
+ fi
+ ;;
+
+multiarch)
+ shift 1
+ printf_yellow "Setting up the qemu image - multiarch/qemu-user-static as qemu-user-static"
+ __docker pull multiarch/qemu-user-static &>/dev/null
+ __docker run -rm -d --name "qemu-user-static-multi" --privileged multiarch/qemu-user-static --reset -p yes --credential yes &>/dev/null
+ printf_yellow "Setting up the binfmt image - tonistiigi/binfmt as binfmt-multi"
+ __docker pull tonistiigi/binfmt &>/dev/null
+ __docker run -d --name "binfmt-multi" --privileged tonistiigi/binfmt --install all &>/dev/null
+ ;;
+
+generate)
+ shift 1
+ __generate "$@"
+ exit $?
+ ;;
+
+readme)
+ shift 1
+ __upload_readme_to_hub "$@"
+ exit $?
+ ;;
+
+swap)
+ shift 1
+ __create_swap "$1"
+ ;;
+
+org)
+ shift 1
+ case "$1" in
+ *)
+ __orgs_api_list "${1:-$DOCKERMGR_REGISTRY_USERNAME}"
+ ;;
+ esac
+ ;;
+
+builder)
+ shift 1
+ printf_exit "This is a work in progress"
+ set -x
+ if [ "$1" = "buildx_script" ]; then
+ shift 1
+ build_cmd="--platform $1 --rm --pull --push --no-cache --progress auto --output=type=registry $2 $3 -f $4"
+ else
+ build_cmd="$*"
+ fi
+ name="$DOCKERMGR_CONTAINER_NAME"
+ mounts="--workdir $3 -v $HOME/.docker/config.json:/config/docker/daemon.json -v $PWD:/$3"
+ printf_cyan "Updating image: $DOCKERMGR_BUILD_IMAGE"
+ __docker pull "$DOCKERMGR_BUILD_IMAGE" &>/dev/null || printf_exit "Failed to pull $DOCKERMGR_BUILD_IMAGE"
+ __docker run -d --hostname $name.build.casjaysdev.pro --name "$name-builder" --privileged $mounts $DOCKERMGR_BUILD_IMAGE
+ __docker exec -it "$name-builder" docker buildx build $build_cmd
+ [ $? -eq 0 ] && exitCode=0 && docker rm -f "$name-builder" || { exitCode=1 && docker logs --follow $name-builder; }
+ exit $exitCode
+ ;;
+
+test)
+ shift 1
+ [ $# -ne 0 ] && set_image="$1" && shift 1 || printf_exit "Please provide the imageName [myuser/myimage]"
+ if [ "$set_image" = "server" ]; then
+ if echo "$1" | grep -q '/'; then
+ registry="$(echo "$1" | sed 's|.*//||g' | awk -F'/' '{print $1}' | grep '[a-zA-Z0-9]\.[a-zA-Z0-9][a-zA-Z0-9]' | grep '^' || false)"
+ organization="$(echo "$1" | awk -F '/' '{print $(NF-1)}' | grep '^' || false)"
+ name="$(echo "$1" | awk -F '/' '{print $NF}' | grep '^' || false)"
+ shift 1
+ else
+ name="$1"
+ registry=""
+ organization="casjaysdevdocker"
+ shift 1
+ fi
+ args="$*"
+ suffix="testing"
+ container_name="$organization-$name-$suffix"
+ [ -n "$registry" ] && registry_url="$registry/$organization/$name" || registry_url="$organization/$name"
+ rootfs_dir="$DOCKERMGR_TEMP_DIR/volumes/${container_name// /_}"
+ if [ "$set_image" = "remove" ]; then
+ __remove_test_container "$container_name" "$rootfs_dir"
+ exit $?
+ fi
+ printf_blue "Creating test container $container_name"
+ docker rm -f $container_name &>/dev/null
+ rm -Rf "$rootfs_dir" &>/dev/null
+ docker run -d --pull always --restart always --privileged --name $container_name \
+ --hostname $name \
+ -e TZ=${TIMEZONE:-America/New_York} $DOCKER_ARG \
+ -v $rootfs_dir/rootfs/data:/data:z \
+ -v $rootfs_dir/rootfs/config:/config:z \
+ $registry_url:latest &>"$DOCKERMGR_TEMP_FILE" && printf_cyan "Created $container_name" && true || false
+ [ $? -eq 0 ] || printf_exit "Failed to create $container_name: $(grep -shi 'error' "$DOCKERMGR_TEMP_FILE" | head -n1)"
+ printf_yellow "run dockermgr log $container_name" && sleep 5
+ __container_exists "$container_name" &>/dev/null || exit 1
+ printf_purple "mounted rootfs to $rootfs_dir/rootfs"
+ exit 0
+ else
+ args="${*:-/bin/sh}"
+ fmt_name="${set_image//:*/}"
+ docker_args="${DOCKER_ARG[*]}"
+ base_name="$(basename -- "$fmt_name")"
+ set_name="$DOCKERMGR_CONTAINER_NAME"
+ name="${set_name:-casjaysdev-$base_name-test}"
+ status="$(__container_exists "$name" || false)"
+ mktemp="$DOCKERMGR_TEMP_DIR/volumes/${name// /_}"
+ echo "$set_image" | grep -q ':.*' || set_image="$set_image:latest"
+ image="$set_image"
+ fi
+ printf_blue "Attempting to pull $image"
+ __docker_pull "$image" &>/dev/null
+ if __container_is_running; then
+ printf_purple "Entering container: $name"
+ __docker_exec "$name" $args 2>/dev/null
+ exit 0
+ elif [ -n "$status" ]; then
+ printf_cyan "Attempting to start $name"
+ if __docker start "$name" &>"$DOCKERMGR_TEMP_FILE" && sleep 3; then
+ printf_purple "Entering container: $name"
+ __docker_exec "$name" $args 2>/dev/null
+ exit 0
+ else
+ printf_return "An error has occured while entering $name"
+ cat "$DOCKERMGR_TEMP_FILE" | printf_readline
+ exit 1
+ fi
+ else
+ printf_purple "Creating container: $name with image: $image"
+ sudo mkdir -p "$mktemp"
+ sudo chmod -Rf 755 "$mktemp"
+ sudo chown -Rf $USER:$USER "$mktemp"
+ __docker_run --name "$name" --hostname "$name" $docker_args -v $mktemp/config:/config -v $mktemp/data:/data "$image" $args 2>"$DOCKERMGR_TEMP_FILE"
+ __remove_test_container "$name" "$mktemp"
+ fi
+ ;;
+
+enter)
+ shift 1
+ DOCKER_OPTS=
+ while :; do
+ case "$@" in
+ -*) DOCKER_OPTS+="${1//=/ } " && shift 1 ;;
+ *) break ;;
+ esac
+ done
+ name="$1"
+ shift 1
+ if __docker ps -a | grep -q "$name" &>/dev/null; then
+ __docker start "$name" &>/dev/null
+ __docker exec -it $DOCKER_OPTS $DOCKER_ARG "$name" "${@:-/bin/sh}"
+ elif __docker_pull "$name" &>/dev/null; then
+ image="$name"
+ printf_cyan "Attempting to grab $image"
+ __docker_pull "$image" &>/dev/null
+ __docker run -ti --name "$name" $DOCKER_OPTS $DOCKER_ARG "$image" "${@:-/bin/sh}"
+ else
+ printf_return "There is no such container"
+ fi
+ exit $?
+ ;;
+
+attach)
+ shift 1
+ __attach "$1"
+ exit $?
+ ;;
+
+exec)
+ name="$2"
+ shift 2
+ if __docker ps | grep "$name" &>/dev/null; then
+ __docker exec -it "$name" "${@:-/bin/sh}"
+ else
+ printf_return "Container either doesn't exist or is not running"
+ fi
+ exit $?
+ ;;
+
+connect)
+ shift 1
+ [ "$1" = "help" ] && __ssh_help
+ __connect_main "$1"
+ exit $?
+ ;;
+
+run)
+ shift 1
+ [ "$1" = "help" ] && __run_help
+ __run_main "$@"
+ exit $?
+ ;;
+
+tag)
+ shift 1
+ [ $# -eq 2 ] || printf_exit "Usage: $APPNAME tag from_tag to_tag [alpine:latest alpine:dev]"
+ __docker image tag "$1" "$2" 2>/dev/null
+ exit $?
+ ;;
+
+active)
+ shift 1
+ [ "$1" = "help" ] && printf_exit "Show active containers"
+ __docker ps | sed "s#$(head -n1)##g" | grep -v "^#" ||
+ printf_exit "There are no active containers"
+ exit $?
+ ;;
+
+inactive)
+ shift 1
+ [ "$1" = "help" ] && printf_exit "Show all containers"
+ __docker ps -a | sed "s#$(head -n1)##g" | grep -v "^#" ||
+ printf_exit "There doesn't seem to be any containers on this system"
+ exit $?
+ ;;
+
+log)
+ shift 1
+ ARGS="$*"
+ [ "${#ARGS}" -ne 0 ] || printf_exit "Usage: $APPNAME log [container]"
+ printf_blue "Following the log for $1"
+ __docker logs --follow "$ARGS"
+ exit $?
+ ;;
+
+ps)
+ shift 1
+ ARGS="$*"
+ if [ "${#ARGS}" -eq 0 ]; then
+ __docker ps -a
+ else
+ __docker ps -a | grep "${ARGS:-^}"
+ fi
+ exit $?
+ ;;
+
+pull)
+ shift 1
+ if [ $# = 0 ] || [ "$INSTALL_ALL" = "true" ]; then
+ D_IMAGES="$(__docker images | grep -v REPOSITORY | awk 'BEGIN{OFS=":"} {print $1,$2}' | grep -Ev '^:|:$' | grep '^')"
+ for image in $D_IMAGES; do
+ printf_purple "Pulling image: $image"
+ __docker_pull "$image" &>/dev/null
+ done
+ else
+ for image in "$@"; do
+ printf_purple "Pulling image: $image"
+ __docker_pull "$image" &>/dev/null
+ done
+ fi
+ exit $?
+ ;;
+
+rm)
+ shift 1
+ ARGS="$*"
+ [ "${#ARGS}" -ne 0 ] || [ "$INSTALL_ALL" = "true" ] || __docker ps -a
+ if [ "$INSTALL_ALL" = "true" ]; then
+ shift 1
+ printf_red "Deleting all docker containers"
+ printf_yellow "However, your data files will remain in"
+ printf_blue "/var/lib/srv/$USER/docker"
+ __docker_rm &>/dev/null
+ exit $?
+ else
+ for container in $ARGS; do
+ if __docker ps -a | grep -q "$container"; then
+ printf_blue "Deleting the container: $container"
+ __docker_rm "$container" &>/dev/null
+ if __docker ps -a | grep -q "$container"; then
+ printf_red "Failed to delete $container"
+ else
+ printf_green "Successfully deleted $container"
+ fi
+ else
+ printf_red "$container is not a valid container"
+ fi
+ done
+ fi
+ exit $?
+ ;;
+
+rmi)
+ shift 1
+ ARGS="$*"
+ [ "${#ARGS}" -ne 0 ] || [ -n "$INSTALL_ALL" ] || __docker images
+ if [ "$1" = "prune" ]; then
+ images="$(docker images | awk '{print $1","$3}' | grep -Ev 'IMAGE ID|REPOSITORY')"
+ for image in $images; do
+ id="${image//*,/}"
+ name="${image//,*/}"
+ printf_cyan "Deleting $name"
+ docker rmi $id &>/dev/null && printf_green "Successfully deleted $id" || printf_red "Failed to delete $id"
+ done
+ exit $?
+ fi
+ if [ "$1" = "force" ]; then
+ printf_red "Deleting all docker images"
+ printf_yellow "However, your data files will remain in"
+ printf_blue "/var/lib/srv/$USER/docker"
+ __docker_rmi
+ exit $?
+ elif [ "$1" = "all" ] || [ "$INSTALL_ALL" = "true" ]; then
+ IMAGES=($(__docker images | grep -v 'IMAGE ID' | awk '{print $3}' | sort -u | grep '^'))
+ for image in "${IMAGES[@]}"; do
+ __docker rmi "$image" 2>&1 | grep -q 'running container' && RUNNING="true" || RUNNING=""
+ [ "$RUNNING" != "" ] || true
+ done
+ exit $?
+ elif [ "$1" = "unnamed" ] || [ "$1" = "untagged" ]; then
+ __docker_untagged_rm
+ exit $?
+ else
+ for image in $ARGS; do
+ if __docker images | grep -q "$image"; then
+ printf_blue "Deleting the image: $image"
+ __docker_rmi "$image" &>/dev/null
+ if __docker images | grep -q "$image"; then
+ printf_red "Failed to delete $image"
+ else
+ printf_green "Successfully deleted $image"
+ fi
+ else
+ printf_red "$image is not a valid image"
+ fi
+ done
+ fi
+ exit $?
+ ;;
+
+restart)
+ shift 1
+ __restart_container "$@"
+ exit $?
+ ;;
+
+status)
+ shift 1
+ __status
+ exit $?
+ ;;
+
+network)
+ shift 1
+ __getlipaddr
+ NETWORK="${1:-bridge}"
+ printf_green "Getting info for $NETWORK"
+ printf_blue "Host IP $CURRENT_IP_4"
+ __docker network inspect $NETWORK |
+ jq -rc '.[] | .Containers | .[] | { Containers: .Name,IP4: .IPv4Address,IP6: .IPv6Address }' |
+ sed 's|""|"None"|g' | printf_readline
+ printf_newline '\n'
+ exit
+ ;;
+
+rancher)
+ shift 1
+ __rancher
+ exit $?
+ ;;
+
+k3b)
+ shift 1
+ __k3b
+ exit $?
+ ;;
+
+minikube)
+ shift 1
+ if [ "$1" = "delete" ]; then
+ shift 1
+ __minikube_delete "$1"
+ elif [ "$1" = "init" ] || [ "$1" = "install" ] || [ "$1" = "setup" ]; then
+ shift 1
+ __minikube_init "$@"
+ elif [ "$1" = "dashboard" ]; then
+ shift 1
+ __minikube_dashboard &
+ sleep 30
+ elif [ "$1" = "services" ]; then
+ shift 1
+ __minikube_services
+ else
+ __minikube "$@"
+ fi
+ exit $?
+ ;;
+
+helm)
+ shift 1
+ __install_helm
+ exit $?
+ ;;
+
+kasm)
+ shift 1
+ cmd_exists docker || __init || printf_exit "kasm requires docker"
+ cmd_exists docker-compose || __docker_compose || printf_exit "kasm requires docker-compose"
+ __install_kasm
+ exit $?
+ ;;
+
+compose)
+ shift 1
+ __docker_compose "$@"
+ exit $?
+ ;;
+
+init)
+ shift 1
+ [ "$1" = "help" ] && __init_help
+ [ "$1" = "force" ] && DOCKERMGR_FORCE_INSTALL="true"
+ __init "$@"
+ exit $?
+ ;;
+
+fe)
+ shift 1
+ __install_front
+ exit $?
+ ;;
+
+ds)
+ shift 1
+ # sudo -HE -n true && ask_for_password true || exit 1
+ # if grep -Rsq 'sudo' /etc/group; then
+ # adduser -m -U -d /var/lib/dockstarter --uid 901 dockstarter &>/dev/null
+ # usermod -aG sudo -aG docker -aG wheel dockstarter &>/dev/null
+ # else
+ # adduser -u 901 -m -U -d /var/lib/dockstarter dockstarter &>/dev/null
+ # usermod -aG wheel -aG docker dockstarter &>/dev/null
+ # fi
+ # if grep -qs dockstarter /etc/passwd; then
+ # sudo -HE passwd -u dockstarter -f &>/dev/null
+ # echo "dockstarter ALL=(ALL) NOPASSWD:ALL" | sudo -HE tee /etc/sudoers.d/dockstarter &>/dev/null
+ # sudo -HE -HE -u dockstarter bash -c "$(curl -q -fsSL https://get.dockstarter.com)"
+ export DOCKERCONFDIR="${DOCKERCONFDIR:-$HOME/.config/dockstarter}"
+ bash -c "$(curl -q -fsSL https://get.dockstarter.com)"
+ # fi
+ ;;
+
+list)
+ shift 1
+ printf_green "All available system configs"
+ __list_available | printf_column '4'
+ exit $?
+ ;;
+
+search)
+ shift 1
+ run_install_search "$@"
+ exit $?
+ ;;
+
+available)
+ shift 1
+ if [ "$1" = "sources" ]; then
+ printf_cyan "All available sources"
+ __api_source_list "name" | printf_column '6'
+ else
+ printf_cyan "All available system configs"
+ __api_list | printf_column '6'
+ fi
+ exit $?
+ ;;
+
+remove)
+ shift 1
+ unset APPNAME
+ if [ "$INSTALL_ALL" = "true" ]; then
+ LISTARRAY="$(ls -A "/var/lib/srv/$USER/docker" 2>/dev/null)"
+ else
+ LISTARRAY="${*}"
+ fi
+ [ ${#LISTARRAY} -ne 0 ] || printf_exit "No packages selected for removal"
+ for rmf in ${LISTARRAY}; do
+ installer_delete "$rmf"
+ done
+ exit $?
+ ;;
+
+update)
+ shift 1
+ unset APPNAME
+ LISTARRAY="$*"
+ if [ ${#LISTARRAY} -eq 0 ]; then
+ __run_update
+ elif [ ${#LISTARRAY} -ne 0 ]; then
+ for ins in "${LISTARRAY[@]}"; do
+ APPNAME="$ins"
+ __run_update "$APPNAME"
+ done
+ else
+ printf_yellow "There doesn't seem to be any packages installed"
+ __notifications "There doesn't seem to be any packages installed"
+ fi
+ exit $?
+ ;;
+
+install)
+ shift 1
+ if [ "$INSTALL_ALL" = "true" ]; then
+ LISTARRAY="$(__list_available)"
+ elif [ $# -eq 0 ]; then
+ printf_blue "No packages provide running the updater"
+ __install_script
+ exit $?
+ else
+ LISTARRAY="$*"
+ fi
+ for ins in $LISTARRAY; do
+ APPNAME="$ins"
+ __install_script "$APPNAME"
+ done
+ exit $?
+ ;;
+
+clone | download)
+ shift 1
+ if [ "$1" = "src" ] || [ "$1" = "source" ]; then
+ shift 1
+ DL_SRC="true"
+ LISTARRAY="${*:-$(__api_source_list 'name' | grep '^' || false)}"
+ else
+ if [ "$INSTALL_ALL" = "true" ]; then
+ LISTARRAY="$(__api_list)"
+ elif [ $# -ne 0 ]; then
+ LISTARRAY="$*"
+ fi
+ fi
+ if [ -n "$LISTARRAY" ]; then
+ for pkgs in $LISTARRAY; do
+ if [ "$DL_SRC" = "true" ]; then
+ __download_src "$pkgs"
+ else
+ __download "$pkgs"
+ fi
+ done
+ else
+ printf_exit "No packages selected for download"
+ fi
+ ;;
+
+prune)
+ shift 1
+ __prune
+ ;;
+
+cron)
+ shift 1
+ cron_updater "$*"
+ exit $?
+ ;;
+
+version)
+ shift 1
+ run_install_version "$@"
+ exit $?
+ ;;
+
+server_status)
+ shift 1
+ __server_status "$@"
+ exit $?
+ ;;
+
+*)
+ export -f __init
+ if ! cmd_exists docker; then
+ __init
+ elif [ $# -ne 0 ]; then
+ __docker "$SETARGS"
+ else
+ __help
+ fi
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/dockerrun b/bin/dockerrun
new file mode 100755
index 000000000..bd789f7f7
--- /dev/null
+++ b/bin/dockerrun
@@ -0,0 +1,650 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# shellcheck disable=SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202304191255-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : dockerrun --help
+# @@Copyright : Copyright: (c) 2023 Jason Hempstead, Casjays Developments
+# @@Created : Wednesday, Apr 19, 2023 12:55 EDT
+# @@File : dockerrun
+# @@Description : run docker image
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202304191255-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DOCKERRUN_REQUIRE_SUDO="${DOCKERRUN_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && DOCKERRUN_EXIT_STATUS=0 || DOCKERRUN_EXIT_STATUS=1
+ return ${DOCKERRUN_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && DOCKERRUN_EXIT_STATUS=0 || DOCKERRUN_EXIT_STATUS=1
+ return ${DOCKERRUN_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ DOCKERRUN_EXIT_STATUS=0
+ [ -n "$1" ] && local DOCKERRUN_EXIT_STATUS="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && DOCKERRUN_EXIT_STATUS+=$(($DOCKERRUN_EXIT_STATUS + 0)) || DOCKERRUN_EXIT_STATUS+=$(($DOCKERRUN_EXIT_STATUS + 1))
+ done
+ [ $DOCKERRUN_EXIT_STATUS -eq 0 ] || DOCKERRUN_EXIT_STATUS=3
+ return ${DOCKERRUN_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local DOCKERRUN_EXIT_STATUS=0
+ curl -q -LSsfI --max-time 1 --retry 0 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || DOCKERRUN_EXIT_STATUS=4
+ return ${DOCKERRUN_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DOCKERRUN_CONFIG_DIR/$DOCKERRUN_CONFIG_FILE"
+ fi
+ [ -d "$DOCKERRUN_CONFIG_DIR" ] || mkdir -p "$DOCKERRUN_CONFIG_DIR"
+ [ -d "$DOCKERRUN_CONFIG_BACKUP_DIR" ] || mkdir -p "$DOCKERRUN_CONFIG_BACKUP_DIR"
+ [ -f "$DOCKERRUN_CONFIG_DIR/$DOCKERRUN_CONFIG_FILE" ] &&
+ cp -Rf "$DOCKERRUN_CONFIG_DIR/$DOCKERRUN_CONFIG_FILE" "$DOCKERRUN_CONFIG_BACKUP_DIR/$DOCKERRUN_CONFIG_FILE.$$"
+ cat <"$DOCKERRUN_CONFIG_DIR/$DOCKERRUN_CONFIG_FILE"
+# Settings for dockerrun
+DOCKERRUN_DOCKER_BIN="${DOCKERRUN_DOCKER_BIN:-}"
+DOCKERUN_DEFAULT_ORG_LIST="${DOCKERUN_DEFAULT_ORG_LIST:-}"
+DOCKERRUN_DEFAULT_IMAGE="${DOCKERRUN_DEFAULT_IMAGE:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DOCKERRUN_OUTPUT_COLOR_1="${DOCKERRUN_OUTPUT_COLOR_1:-}"
+DOCKERRUN_OUTPUT_COLOR_2="${DOCKERRUN_OUTPUT_COLOR_2:-}"
+DOCKERRUN_OUTPUT_COLOR_GOOD="${DOCKERRUN_OUTPUT_COLOR_GOOD:-}"
+DOCKERRUN_OUTPUT_COLOR_ERROR="${DOCKERRUN_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DOCKERRUN_NOTIFY_ENABLED="${DOCKERRUN_NOTIFY_ENABLED:-}"
+DOCKERRUN_GOOD_NAME="${DOCKERRUN_GOOD_NAME:-}"
+DOCKERRUN_ERROR_NAME="${DOCKERRUN_ERROR_NAME:-}"
+DOCKERRUN_GOOD_MESSAGE="${DOCKERRUN_GOOD_MESSAGE:-}"
+DOCKERRUN_ERROR_MESSAGE="${DOCKERRUN_ERROR_MESSAGE:-}"
+DOCKERRUN_NOTIFY_CLIENT_NAME="${DOCKERRUN_NOTIFY_CLIENT_NAME:-}"
+DOCKERRUN_NOTIFY_CLIENT_ICON="${DOCKERRUN_NOTIFY_CLIENT_ICON:-}"
+DOCKERRUN_NOTIFY_CLIENT_URGENCY="${DOCKERRUN_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DOCKERRUN_CONFIG_DIR/$DOCKERRUN_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DOCKERRUN_CONFIG_DIR/$DOCKERRUN_CONFIG_FILE"
+ DOCKERRUN_EXIT_STATUS=0
+ else
+ printf_red "Failed to create the config file"
+ DOCKERRUN_EXIT_STATUS=1
+ fi
+ return ${DOCKERRUN_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "dockerrun: run docker image - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: dockerrun [containerID,containerName] [commands] [image]"
+ __printf_line "alpine /bin/sh alpine - Runs the alpine container with sh"
+ __printf_line "--dir - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__grep() { grep "$@" 2>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DOCKERRUN_REQUIRE_SUDO" = "yes" ] && [ -z "$DOCKERRUN_REQUIRE_SUDO_RUN" ]; then
+ export DOCKERRUN_REQUIRE_SUDO="no"
+ export DOCKERRUN_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ DOCKERRUN_EXIT_STATUS=$?
+ else
+ printf '%s\n' "This requires root to run"
+ DOCKERRUN_EXIT_STATUS=1
+ fi
+ return ${DOCKERRUN_EXIT_STATUS:-0}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ DOCKERRUN_EXIT_STATUS=${DOCKERRUN_EXIT_STATUS:-0}
+ [ -f "$DOCKERRUN_TEMP_FILE" ] && rm -Rf "$DOCKERRUN_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $DOCKERRUN_EXIT_STATUS
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__jq() { jq "$@" 2>/dev/null; }
+__gen_config_local() { __dockerrun_complete; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_exec() { $DOCKERRUN_DOCKER_BIN exec --tty --interactive "$DOCKERRUN_NAME" $DOCKERRUN_EXEC || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__dockerrun_complete() {
+ local count=""
+ local list_dir="$DOCKERRUN_CONFIG_DIR/lists"
+ local org_list="${*:-$DOCKERUN_DEFAULT_ORG_LIST}"
+ local api="https://hub.docker.com/v2/repositories"
+ org_list="${org_list//,/ }"
+ [ -d "$list_dir" ] || mkdir -p "$list_dir"
+ for org in $org_list; do
+ prev_org="$org"
+ org_name="$org"
+ list_file="$list_dir/$org_name.list"
+ [ $prev_org = $org_name ] || count=""
+ count="${count:-$(curl -q -LSsf "$api/$org_name" 2>/dev/null | jq -rc '.count' | grep '^[0-9]' | grep -v 'null' | grep '^' || echo '0')}"
+ if [ -n "$org_name" ] && [ $count -ne 0 ]; then
+ [ -f "$list_file" ] && rm -Rf "$list_file"
+ repo_name="$(curl -q -LSsf "$api/${org_name}?page_size=1000" 2>/dev/null | __jq -rc '.results|.[]|.name')"
+ if [ -n "$repo_name" ]; then
+ for repo in $repo_name; do
+ [ -n "$repo" ] && printf '%s\n' "$org_name/$repo" >>"$list_file"
+ done
+ fi
+ fi
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_run() {
+ cmd="$DOCKERRUN_DOCKER_BIN run -d --restart always --network $DOCKERRUN_NETWORK -it "
+ cmd+="--name $DOCKERRUN_NAME $DOCKERRUN_OPTS $DOCKERRUN_MOUNTS $DOCKERRUN_PORTS $DOCKERRUN_IMAGE"
+ #printf_purple "$cmd"
+ eval $cmd >/dev/null 2>"$DOCKERRUN_TEMP_FILE" && sleep 10 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__show_log_file() { tail -n2 "$DOCKERRUN_TEMP_FILE" | sed 's|docker: Error.*daemon: ||g;s|\. .*||g;s|: .*||g' | grep -v 'docker run --help' | grep '^' || tail -n1 "$DOCKERRUN_TEMP_FILE"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__docker_ps_listen() {
+ col=$(($COLUMNS - 10))
+ listen="$(docker ps --format '{{.Names}} {{.Ports}}' 2>&1 | grep "$DOCKERRUN_NAME" | sed "s|$DOCKERRUN_NAME ||g" | tr ' ' '\n' | grep -v '^$' | sed 's|,|;|g;s|:::|0.0.0.0:|g;s|/.*|;|g;s| *| |g' | sort -urV | grep '^')"
+ [ ${#listen} -ge $col ] && listen="${listen:0:$col}..."
+ [ -n "$listen" ] && printf '%s port mappings: %s\n' "$DOCKERRUN_NAME" "${listen//0.0.0.0/$CURRENT_IP_4}" | tr '\n' ' ' | sed 's| $||g;s|;$||g' | grep '^' | printf_readline "$DOCKERRUN_OUTPUT_COLOR_2"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__create_volume() {
+ local mounts=()
+ for volume in $DOCKERRUN_MOUNTS; do
+ if echo "$volume" | grep -q ':'; then
+ host="$(echo "$volume" | awk -F ':' '{print $1}' | sed 's|^/||g')"
+ container="$(echo "$volume" | awk -F ':' '{print $2}' | sed 's|^/||g')"
+ else
+ host="$DOCKERRUN_TEMP_DIR/$NAME/$(echo "$volume" | sed 's|^/||g')"
+ container="$(echo "$volume" | sed 's|^/||g')"
+ fi
+ mounts+=("--volume $host:/$container")
+ done
+ DOCKERRUN_MOUNTS="${mounts[*]}"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Default exit code
+DOCKERRUN_EXIT_STATUS=0
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DOCKERRUN_CONFIG_DIR="${DOCKERRUN_CONFIG_DIR:-$HOME/.config/myscripts/dockerrun}"
+DOCKERRUN_CONFIG_BACKUP_DIR="${DOCKERRUN_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/dockerrun/backups}"
+DOCKERRUN_LOG_DIR="${DOCKERRUN_LOG_DIR:-$HOME/.local/log/dockerrun}"
+DOCKERRUN_RUN_DIR="${DOCKERRUN_RUN_DIR:-$HOME/.local/run/system_scripts/$DOCKERRUN_SCRIPTS_PREFIX}"
+DOCKERRUN_TEMP_DIR="${DOCKERRUN_TEMP_DIR:-$HOME/.local/tmp/system_scripts/dockerrun}"
+DOCKERRUN_CACHE_DIR="${DOCKERRUN_CACHE_DIR:-$HOME/.cache/dockerrun}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# File settings
+DOCKERRUN_CONFIG_FILE="${DOCKERRUN_CONFIG_FILE:-settings.conf}"
+DOCKERRUN_LOG_ERROR_FILE="${DOCKERRUN_LOG_ERROR_FILE:-$DOCKERRUN_LOG_DIR/error.log}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DOCKERRUN_OUTPUT_COLOR_1="${DOCKERRUN_OUTPUT_COLOR_1:-33}"
+DOCKERRUN_OUTPUT_COLOR_2="${DOCKERRUN_OUTPUT_COLOR_2:-5}"
+DOCKERRUN_OUTPUT_COLOR_GOOD="${DOCKERRUN_OUTPUT_COLOR_GOOD:-2}"
+DOCKERRUN_OUTPUT_COLOR_ERROR="${DOCKERRUN_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DOCKERRUN_NOTIFY_ENABLED="${DOCKERRUN_NOTIFY_ENABLED:-yes}"
+DOCKERRUN_GOOD_NAME="${DOCKERRUN_GOOD_NAME:-Great:}"
+DOCKERRUN_ERROR_NAME="${DOCKERRUN_ERROR_NAME:-Error:}"
+DOCKERRUN_GOOD_MESSAGE="${DOCKERRUN_GOOD_MESSAGE:-No errors reported}"
+DOCKERRUN_ERROR_MESSAGE="${DOCKERRUN_ERROR_MESSAGE:-Errors were reported}"
+DOCKERRUN_NOTIFY_CLIENT_NAME="${DOCKERRUN_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DOCKERRUN_NOTIFY_CLIENT_ICON="${DOCKERRUN_NOTIFY_CLIENT_ICON:-notification-new}"
+DOCKERRUN_NOTIFY_CLIENT_URGENCY="${DOCKERRUN_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+DOCKERRUN_DOCKER_BIN="${DOCKERRUN_DOCKER_BIN:-docker}"
+DOCKERRUN_DEFAULT_IMAGE="${DOCKERRUN_DEFAULT_IMAGE:-casjaysdev/alpine}"
+DOCKERRUN_DEFAULT_MOUNTS="app data config "
+DOCKERUN_DEFAULT_ORG_LIST="${DOCKERUN_DEFAULT_ORG_LIST:-casjaysdev,casjaysdevdocker}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DOCKERRUN_CONFIG_DIR/$DOCKERRUN_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DOCKERRUN_CONFIG_DIR/$DOCKERRUN_CONFIG_FILE" ] && . "$DOCKERRUN_CONFIG_DIR/$DOCKERRUN_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DOCKERRUN_RUN_DIR" ] || mkdir -p "$DOCKERRUN_RUN_DIR" |& __devnull
+[ -d "$DOCKERRUN_LOG_DIR" ] || mkdir -p "$DOCKERRUN_LOG_DIR" |& __devnull
+[ -d "$DOCKERRUN_TEMP_DIR" ] || mkdir -p "$DOCKERRUN_TEMP_DIR" |& __devnull
+[ -d "$DOCKERRUN_CACHE_DIR" ] || mkdir -p "$DOCKERRUN_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DOCKERRUN_TEMP_FILE="${DOCKERRUN_TEMP_FILE:-$(mktemp $DOCKERRUN_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DOCKERRUN_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DOCKERRUN_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DOCKERRUN_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DOCKERRUN_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DOCKERRUN_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DOCKERRUN_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent,force"
+LONGOPTS+=",network:,mount:,docker:,publish:,ports:"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DOCKERRUN_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ DOCKERRUN_CWD="$2"
+ [ -d "$DOCKERRUN_CWD" ] || mkdir -p "$DOCKERRUN_CWD" |& __devnull
+ shift 2
+ ;;
+ --network)
+ DOCKERRUN_SET_NETWORK="$2"
+ shift 2
+ ;;
+ --docker)
+ DOCKERRUN_SET_OPTS+=("$2")
+ shift 2
+ ;;
+ --mount)
+ DOCKERRUN_SET_MOUNTS+=("$2")
+ shift 2
+ ;;
+ --publish)
+ DOCKERRUN_SET_PORTS+=("--publish $2")
+ shift 2
+ ;;
+ --ports)
+ DOCKERRUN_NAME="$2"
+ __docker_ps_listen
+ exit $?
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DOCKERRUN_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DOCKERRUN_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DOCKERRUN_CWD="$1" && shift 1 || DOCKERRUN_CWD="${DOCKERRUN_CWD:-$PWD}"
+DOCKERRUN_CWD="$(realpath "${DOCKERRUN_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DOCKERRUN_CWD" ] && cd "$DOCKERRUN_CWD"; then
+# if [ "$DOCKERRUN_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DOCKERRUN_CWD"
+# fi
+# else
+# printf_exit "💔 $DOCKERRUN_CWD does not exist 💔"
+# fi
+export DOCKERRUN_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+__dockerrun_complete ${1//\/*/}
+[ -n "$1" ] || printf_exit "Please provide the container name or ID"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+DOCKERRUN_NAME="${1//*\//}"
+DOCKERRUN_EXEC="${2:-/usr/bin/env sh}"
+DOCKERRUN_PORTS="${DOCKERRUN_SET_PORTS[*]:--P}"
+DOCKERRUN_NETWORK="${DOCKERRUN_SET_NETWORK:-bridge}"
+DOCKERRUN_OPTS="${DOCKERRUN_SET_OPTS[*]} --privileged"
+DOCKERRUN_MOUNTS="${DOCKERRUN_DEFAULT_MOUNTS[*]} ${DOCKERRUN_SET_MOUNTS[*]}"
+if [ $# -eq 1 ]; then
+ echo "$1" | grep -q '/' && DOCKERRUN_IMAGE="$1" || DOCKERRUN_IMAGE="$DOCKERRUN_DEFAULT_IMAGE"
+elif [ $# -eq 2 ]; then
+ DOCKERRUN_IMAGE="$2"
+elif [ $# -eq 3 ]; then
+ DOCKERRUN_IMAGE="$2"
+ DOCKERRUN_EXEC="$3"
+else
+ printf_red "Usage: $APPNAME [containerID,containerName] [commands] [image]"
+ printf_exit "$DOCKERRUN_NAME either doesn't exist or is not running"
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+DOCKERRUN_NAME="$(echo "$DOCKERRUN_NAME" | sed 's/[!@#\$%^&*():]//g')"
+DOCKERRUN_CONTAINER_EXISTS="$($DOCKERRUN_DOCKER_BIN ps -a 2>&1 | grep "$DOCKERRUN_NAME" || echo '')"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Export variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+if [ -n "$($DOCKERRUN_DOCKER_BIN ps -q -f status=running -f name=^/${DOCKERRUN_NAME}$)" ]; then
+ __docker_exec
+elif [ -n "$DOCKERRUN_CONTAINER_EXISTS" ]; then
+ printf_exit "The container exists, however, it does not seem to be running"
+else
+ printf_cyan "Creating and starting $DOCKERRUN_NAME using image: $DOCKERRUN_IMAGE"
+ __create_volume
+ if __docker_run; then
+ printf_blue "Your container has been created"
+ __docker_ps_listen
+ __docker_exec
+ else
+ printf_return "Failed to created the container: $(__show_log_file)"
+ fi
+fi
+DOCKERRUN_EXIT_STATUS=$?
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+DOCKERRUN_EXIT_STATUS="${DOCKERRUN_EXIT_STATUS:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${DOCKERRUN_EXIT_STATUS:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/dos2unix b/bin/dos2unix
new file mode 100755
index 000000000..d1d786432
--- /dev/null
+++ b/bin/dos2unix
@@ -0,0 +1,564 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208052222-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : dos2unix --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 22:22 EDT
+# @@File : dos2unix
+# @@Description : Find files with Windows line endings (and convert them to Unix in force mode)
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208052222-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DOS2UNIX_REQUIRE_SUDO="${DOS2UNIX_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DOS2UNIX_CONFIG_DIR/$DOS2UNIX_CONFIG_FILE"
+ fi
+ [ -d "$DOS2UNIX_CONFIG_DIR" ] || mkdir -p "$DOS2UNIX_CONFIG_DIR"
+ [ -d "$DOS2UNIX_CONFIG_BACKUP_DIR" ] || mkdir -p "$DOS2UNIX_CONFIG_BACKUP_DIR"
+ [ -f "$DOS2UNIX_CONFIG_DIR/$DOS2UNIX_CONFIG_FILE" ] &&
+ cp -Rf "$DOS2UNIX_CONFIG_DIR/$DOS2UNIX_CONFIG_FILE" "$DOS2UNIX_CONFIG_BACKUP_DIR/$DOS2UNIX_CONFIG_FILE.$$"
+ cat <"$DOS2UNIX_CONFIG_DIR/$DOS2UNIX_CONFIG_FILE"
+# Settings for dos2unix
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DOS2UNIX_OUTPUT_COLOR_1="${DOS2UNIX_OUTPUT_COLOR_1:-}"
+DOS2UNIX_OUTPUT_COLOR_2="${DOS2UNIX_OUTPUT_COLOR_2:-}"
+DOS2UNIX_OUTPUT_COLOR_GOOD="${DOS2UNIX_OUTPUT_COLOR_GOOD:-}"
+DOS2UNIX_OUTPUT_COLOR_ERROR="${DOS2UNIX_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DOS2UNIX_NOTIFY_ENABLED="${DOS2UNIX_NOTIFY_ENABLED:-}"
+DOS2UNIX_GOOD_NAME="${DOS2UNIX_GOOD_NAME:-}"
+DOS2UNIX_ERROR_NAME="${DOS2UNIX_ERROR_NAME:-}"
+DOS2UNIX_GOOD_MESSAGE="${DOS2UNIX_GOOD_MESSAGE:-}"
+DOS2UNIX_ERROR_MESSAGE="${DOS2UNIX_ERROR_MESSAGE:-}"
+DOS2UNIX_NOTIFY_CLIENT_NAME="${DOS2UNIX_NOTIFY_CLIENT_NAME:-}"
+DOS2UNIX_NOTIFY_CLIENT_ICON="${DOS2UNIX_NOTIFY_CLIENT_ICON:-}"
+DOS2UNIX_NOTIFY_CLIENT_URGENCY="${DOS2UNIX_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DOS2UNIX_CONFIG_DIR/$DOS2UNIX_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DOS2UNIX_CONFIG_DIR/$DOS2UNIX_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "dos2unix: Find files with Windows line endings (and convert them to Unix in force mode) - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: dos2unix [options] [path/to/files]"
+ __printf_line "/path/to/file[s] - Converts to unix format"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DOS2UNIX_REQUIRE_SUDO" = "yes" ] && [ -z "$DOS2UNIX_REQUIRE_SUDO_RUN" ]; then
+ export DOS2UNIX_REQUIRE_SUDO="no"
+ export DOS2UNIX_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DOS2UNIX_TEMP_FILE" ] && rm -Rf "$DOS2UNIX_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__get_file() {
+ local args=("$@")
+ local getPath=""
+ local files=""
+ local file=""
+ for file in "${args[@]}"; do
+ if [ -d "$file" ]; then
+ find="$(find "$file" -maxdepth 1 -type f,l -not -path "*/.git/*" -not -path "*/node_modules/*" -not -path "*/.npm/*" 2>/dev/null)"
+ for f in $find; do
+ getPath="$(realpath "$f" 2>/dev/null)"
+ setFiles+=("$(find "$getPath" -exec file {} \; 2>/dev/null | grep 'ASCII' | cut -d: -f1 || echo '')")
+ done
+ echoFile+=("${setFiles[@]}")
+ unset setFiles
+ elif [ -e "$file" ]; then
+ getPath="$(realpath "$file" 2>/dev/null)"
+ files="$(find "$getPath" -exec file {} \; 2>/dev/null | grep 'ASCII' | cut -d: -f1 || echo '')"
+ echoFile+=("$files")
+ fi
+ done
+ [ -n "${echoFile[*]}" ] && printf '%s\n' "${echoFile[@]}" | uniq || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__dos2unix() {
+ [ -e "$1" ] || return
+ printf_cyan "$APPNAME: converting file $1 to Unix format..."
+ sed -i 's|$||' "$1" &>/dev/null
+ sed -i 's|^M$||' "$1" &>/dev/null
+ sed -i 's|\x0D$||' "$1" &>/dev/null
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_dos2unix() {
+ local exitCode=""
+ local files=
+ files=("$(__get_file "$@" || echo '')")
+ if [ -n "${files[*]}" ]; then
+ for file in $files; do
+ __dos2unix "$file" && exitCode=0 || exitCode=1
+ done
+ else
+ printf_exit "Usage: $APPNAME [file,folder]"
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DOS2UNIX_CONFIG_FILE="${DOS2UNIX_CONFIG_FILE:-settings.conf}"
+DOS2UNIX_CONFIG_DIR="${DOS2UNIX_CONFIG_DIR:-$HOME/.config/myscripts/dos2unix}"
+DOS2UNIX_CONFIG_BACKUP_DIR="${DOS2UNIX_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/dos2unix/backups}"
+DOS2UNIX_LOG_DIR="${DOS2UNIX_LOG_DIR:-$HOME/.local/log/dos2unix}"
+DOS2UNIX_TEMP_DIR="${DOS2UNIX_TEMP_DIR:-$HOME/.local/tmp/system_scripts/dos2unix}"
+DOS2UNIX_CACHE_DIR="${DOS2UNIX_CACHE_DIR:-$HOME/.cache/dos2unix}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DOS2UNIX_OUTPUT_COLOR_1="${DOS2UNIX_OUTPUT_COLOR_1:-33}"
+DOS2UNIX_OUTPUT_COLOR_2="${DOS2UNIX_OUTPUT_COLOR_2:-5}"
+DOS2UNIX_OUTPUT_COLOR_GOOD="${DOS2UNIX_OUTPUT_COLOR_GOOD:-2}"
+DOS2UNIX_OUTPUT_COLOR_ERROR="${DOS2UNIX_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DOS2UNIX_NOTIFY_ENABLED="${DOS2UNIX_NOTIFY_ENABLED:-yes}"
+DOS2UNIX_GOOD_NAME="${DOS2UNIX_GOOD_NAME:-Great:}"
+DOS2UNIX_ERROR_NAME="${DOS2UNIX_ERROR_NAME:-Error:}"
+DOS2UNIX_GOOD_MESSAGE="${DOS2UNIX_GOOD_MESSAGE:-No errors reported}"
+DOS2UNIX_ERROR_MESSAGE="${DOS2UNIX_ERROR_MESSAGE:-Errors were reported}"
+DOS2UNIX_NOTIFY_CLIENT_NAME="${DOS2UNIX_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DOS2UNIX_NOTIFY_CLIENT_ICON="${DOS2UNIX_NOTIFY_CLIENT_ICON:-notification-new}"
+DOS2UNIX_NOTIFY_CLIENT_URGENCY="${DOS2UNIX_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DOS2UNIX_CONFIG_DIR/$DOS2UNIX_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DOS2UNIX_CONFIG_DIR/$DOS2UNIX_CONFIG_FILE" ] && . "$DOS2UNIX_CONFIG_DIR/$DOS2UNIX_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DOS2UNIX_LOG_DIR" ] || mkdir -p "$DOS2UNIX_LOG_DIR" |& __devnull
+[ -d "$DOS2UNIX_TEMP_DIR" ] || mkdir -p "$DOS2UNIX_TEMP_DIR" |& __devnull
+[ -d "$DOS2UNIX_CACHE_DIR" ] || mkdir -p "$DOS2UNIX_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DOS2UNIX_TEMP_FILE="${DOS2UNIX_TEMP_FILE:-$(mktemp $DOS2UNIX_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DOS2UNIX_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DOS2UNIX_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DOS2UNIX_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DOS2UNIX_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DOS2UNIX_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DOS2UNIX_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=",force"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DOS2UNIX_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ DOS2UNIX_CWD="$2"
+ [ -d "$DOS2UNIX_CWD" ] || mkdir -p "$DOS2UNIX_CWD" |& __devnull
+ shift 2
+ ;;
+ --force)
+ shift 1
+ DOS2UNIX_FORCE=1
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DOS2UNIX_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DOS2UNIX_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DOS2UNIX_CWD="$1" && shift 1 || DOS2UNIX_CWD="${DOS2UNIX_CWD:-$PWD}"
+DOS2UNIX_CWD="$(realpath "${DOS2UNIX_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DOS2UNIX_CWD" ] && cd "$DOS2UNIX_CWD"; then
+# if [ "$DOS2UNIX_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DOS2UNIX_CWD"
+# fi
+# else
+# printf_exit "💔 $DOS2UNIX_CWD does not exist 💔"
+# fi
+export DOS2UNIX_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+DOS2UNIX_FORCE="${DOS2UNIX_FORCE:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__execute_dos2unix "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/dotfiles b/bin/dotfiles
new file mode 100755
index 000000000..5a6c9dfeb
--- /dev/null
+++ b/bin/dotfiles
@@ -0,0 +1,165 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202305052232-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : dotfiles --help
+# @@Copyright : Copyright: (c) 2023 Jason Hempstead, Casjays Developments
+# @@Created : Friday, May 05, 2023 22:32 EDT
+# @@File : dotfiles
+# @@Description : legacy dotfiles installer script
+# @@Changelog : Updated to allow execution of all mgr scripts
+# @@TODO : Better documentation
+# @@Other : This script is obsolete
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : shell/bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC2317
+# shellcheck disable=SC2120
+# shellcheck disable=SC2155
+# shellcheck disable=SC2199
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# script variables
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202305052232-git"
+RUN_USER="$USER"
+SET_UID="$(id -u)"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DOTFILES_CWD="$(realpath "$PWD")"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# script functions
+if [ "$SHOW_RAW" != "true" ]; then
+ __printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1\n" "$(tput sgr0 2>/dev/null)"; }
+else
+ # Disable colorization
+ __printf_color() { { [ -z "$2" ] || DEFAULT_COLOR=$2; } && printf '%b\n' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check for command
+__cmd_exists() { which $1 >/dev/null 2>&1 || return 1; }
+__function_exists() { builtin type $1 >/dev/null 2>&1 || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# custom functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Define Variables
+DEFAULT_COLOR="254"
+DOTFILES_EXIT_STATUS=0
+DOTFILES_DIR_USER="$HOME/.local/share/CasjaysDev/apps/dotfiles"
+DOTFILES_DIR_SYSTEM="/usr/local/share/CasjaysDev/apps/dotfiles"
+DOTFILES_OPTIONS="installed config desktopmgr devenvmgr dfmgr dockermgr fontmgr hakmgr "
+DOTFILES_OPTIONS+="iconmgr lxcmgr passmgr pkmgr systemmgr thememgr virtmgr wallpapermgr"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Main application
+case "$1" in
+installed)
+ printf '%-15s%5s%30s\n' "mgr name:" " " "app name"
+ files_user="$(ls -A "$DOTFILES_DIR_USER" | sort -u | grep '^' || false)"
+ files_system="$(ls -A "$DOTFILES_DIR_SYSTEM" | sort -u | grep '^' || false)"
+ if [ -n "$files_user" ]; then
+ for uf in $files_user; do
+ mgr="$(echo "${uf}" | awk -F '-' '{print $1}')"
+ app="${uf//$mgr-/}"
+ __printf_color "$(printf '%-15s%5s%30s' "$mgr:" " " "$app")" 4
+ done
+ fi
+ if [ -n "$files_system" ]; then
+ for sf in $files_system; do
+ mgr="$(echo "${sf}" | awk -F '-' '{print $1}')"
+ app="${sf//$mgr-/}"
+ __printf_color "$(printf '%-15s%5s%30s' "$mgr:" " " "$app")" 3
+ done
+ fi
+ ;;
+config | stow)
+ shift 1
+ config "${@:---help}"
+ exit $?
+ ;;
+desktopmgr)
+ shift 1
+ desktopmgr "${@:---help}"
+ exit #?
+ ;;
+devenvmgr)
+ shift 1
+ devenvmgr "${@:---help}"
+ exit #?
+ ;;
+dfmgr)
+ shift 1
+ dfmgr "${@:---help}"
+ exit #?
+ ;;
+dockermgr)
+ shift 1
+ dockermgr "${@:---help}"
+ exit #?
+ ;;
+fontmgr)
+ shift 1
+ fontmgr "${@:---help}"
+ exit #?
+ ;;
+hakmgr)
+ shift 1
+ hakmgr "${@:---help}"
+ exit #?
+ ;;
+iconmgr)
+ shist 1
+ iconmgr "${@:---help}"
+ exit #?
+ ;;
+lxcmgr)
+ shift 1
+ lxcmgr "${@:---help}"
+ exit #?
+ ;;
+passmgr)
+ shift 1
+ passmgr "${@:---help}"
+ exit #?
+ ;;
+pkmgr)
+ shift 1
+ pkmgr "${@:---help}"
+ exit #?
+ ;;
+systemmgr)
+ shift 1
+ systemmgr "${@:---help}"
+ exit #?
+ ;;
+thememgr)
+ shift 1
+ thememgr "${@:---help}"
+ exit #?
+ ;;
+virtmgr)
+ shift 1
+ virtmgr "${@:---help}"
+ exit #?
+ ;;
+wallpapermgr)
+ shift 1
+ wallpapermgr "${@:---help}"
+ exit #?
+ ;;
+*)
+ dfmgr "${@:---help}"
+ DOTFILES_EXIT_STATUS=$?
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+exit $DOTFILES_EXIT_STATUS
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/duckdns b/bin/duckdns
new file mode 100755
index 000000000..7144f6007
--- /dev/null
+++ b/bin/duckdns
@@ -0,0 +1,738 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208052230-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : duckdns --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Friday, Aug 05, 2022 22:30 EDT
+# @@File : duckdns
+# @@Description : DuckDNS api script
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208052230-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+DUCKDNS_REQUIRE_SUDO="${DUCKDNS_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$DUCKDNS_CONFIG_DIR/$DUCKDNS_CONFIG_FILE"
+ fi
+ [ -d "$DUCKDNS_CONFIG_DIR" ] || mkdir -p "$DUCKDNS_CONFIG_DIR"
+ [ -d "$DUCKDNS_CONFIG_BACKUP_DIR" ] || mkdir -p "$DUCKDNS_CONFIG_BACKUP_DIR"
+ [ -f "$DUCKDNS_CONFIG_DIR/$DUCKDNS_CONFIG_FILE" ] &&
+ cp -Rf "$DUCKDNS_CONFIG_DIR/$DUCKDNS_CONFIG_FILE" "$DUCKDNS_CONFIG_BACKUP_DIR/$DUCKDNS_CONFIG_FILE.$$"
+ cat <"$DUCKDNS_CONFIG_DIR/$DUCKDNS_CONFIG_FILE"
+# Settings for duckdns
+DUCKDNS_API_KEY="${DUCKDNS_API_KEY:-}"
+DUCKDNS_DOMAIN="${DUCKDNS_DOMAIN:-}"
+DUCKDNS_CLEAR="${DUCKDNS_CLEAR:-}"
+DUCKDNS_API_URL="${DUCKDNS_API_URL:-}"
+DUCKDNS_EXTERNAL_IP="${DUCKDNS_EXTERNAL_IP:-}"
+DUCKDNS_LETSENCRYPT_EMAIL="${DUCKDNS_LETSENCRYPT_EMAIL:-}"
+DUCKDNS_CERTBOT_CONTAINER="${DUCKDNS_CERTBOT_CONTAINER:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DUCKDNS_OUTPUT_COLOR_1="${DUCKDNS_OUTPUT_COLOR_1:-}"
+DUCKDNS_OUTPUT_COLOR_2="${DUCKDNS_OUTPUT_COLOR_2:-}"
+DUCKDNS_OUTPUT_COLOR_GOOD="${DUCKDNS_OUTPUT_COLOR_GOOD:-}"
+DUCKDNS_OUTPUT_COLOR_ERROR="${DUCKDNS_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DUCKDNS_NOTIFY_ENABLED="${DUCKDNS_NOTIFY_ENABLED:-}"
+DUCKDNS_GOOD_NAME="${DUCKDNS_GOOD_NAME:-}"
+DUCKDNS_ERROR_NAME="${DUCKDNS_ERROR_NAME:-}"
+DUCKDNS_GOOD_MESSAGE="${DUCKDNS_GOOD_MESSAGE:-}"
+DUCKDNS_ERROR_MESSAGE="${DUCKDNS_ERROR_MESSAGE:-}"
+DUCKDNS_NOTIFY_CLIENT_NAME="${DUCKDNS_NOTIFY_CLIENT_NAME:-}"
+DUCKDNS_NOTIFY_CLIENT_ICON="${DUCKDNS_NOTIFY_CLIENT_ICON:-}"
+DUCKDNS_NOTIFY_CLIENT_URGENCY="${DUCKDNS_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$DUCKDNS_CONFIG_DIR/$DUCKDNS_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$DUCKDNS_CONFIG_DIR/$DUCKDNS_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "duckdns: DuckDNS api script - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: duckdns [options] [domain] [ip4] [ipv6]"
+ __printf_line "update [domain] - Automatically sets ip addresses and updates domain"
+ __printf_line "--api [apiKey] - Sets the API key"
+ __printf_line "--domain [domain] - Set the domain"
+ __printf_line "--ip4 [ip4Address] - Set the ipv4 address"
+ __printf_line "--ip6 [ip6Address] - Set the ipv6 address"
+ __printf_line "--txt [textRecord] - Set the text record"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$DUCKDNS_REQUIRE_SUDO" = "yes" ] && [ -z "$DUCKDNS_REQUIRE_SUDO_RUN" ]; then
+ export DUCKDNS_REQUIRE_SUDO="no"
+ export DUCKDNS_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$DUCKDNS_TEMP_FILE" ] && rm -Rf "$DUCKDNS_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__curl() { curl -q -LSsf "$@" 2>/dev/null || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__duckdns_api() { __curl "$DUCKDNS_API_URL/${*}" && return 0 || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_external_ip4() { __curl -q --max-time 2 -4 "$DUCKDNS_EXTERNAL_IP" && return 0 || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__get_external_ip6() { __curl -q --max-time 2 -6 "$DUCKDNS_EXTERNAL_IP" && return 0 || return 1; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__set_full_domain() {
+ local dom="${1:-$DUCKDNS_DOMAIN}" set_domain=""
+ if [ -n "$dom" ]; then
+ echo "$dom" | grep -q '\..*\..*' || set_domain="$dom.duckdns.org"
+ else
+ printf_exit "Please set the domain you want manage"
+ fi
+ export DUCKDNS_DOMAIN="${set_domain:-$dom}"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__var_check() {
+ local set_domain="${1:-$DUCKDNS_DOMAIN}" ip4="$2" ip6="$3"
+ __set_full_domain "$set_domain"
+ [ "$DUCKDNS_IP4" = "yes" ] && DUCKDNS_NOIP4="true" && DUCKDNS_IP4="$(__get_external_ip4)"
+ [ "$DUCKDNS_IP6" = "yes" ] && DUCKDNS_NOIP6="true" && DUCKDNS_IP6="$(__get_external_ip6)"
+ export DUCKDNS_DOMAIN="$DUCKDNS_DOMAIN" DUCKDNS_IP4="${DUCKDNS_IP4:-$ip4}" DUCKDNS_IP6="${DUCKDNS_IP6:-$ip6}"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__duckdns_update() {
+ local domain="${1:-$DUCKDNS_DOMAIN}" verbose="" clear="" token=""
+ [ -n "$domain" ] && domains="domains=$domain"
+ [ -z "$DUCKDNS_IP4" ] && [ "$DUCKDNS_NOIP4" != "true" ] && DUCKDNS_IP4="$(__get_external_ip4 || echo "")"
+ [ -z "$DUCKDNS_IP6" ] && [ "$DUCKDNS_NOIP6" != "true" ] && DUCKDNS_IP6="$(__get_external_ip6 || echo "")"
+ [ -n "$DUCKDNS_IP4" ] && ip4='&ip='${DUCKDNS_IP4}''
+ [ -n "$DUCKDNS_IP6" ] && ip6='&ipv6='${DUCKDNS_IP6}''
+ [ "$DUCKDNS_SILENT" = "true" ] || printf_cyan "Attempting to update $domain"
+ clear="&clear=${DUCKDNS_CLEAR:-false}"
+ token="&token=${DUCKDNS_API_KEY:-}"
+ if [ -n "$DUCKDNS_TEXT" ]; then
+ textrecord="$(__uriencode "$DUCKDNS_TEXT")"
+ resp="$(__duckdns_api "update/?${domains}${token}${ip4}${ip6}${clear}&verbose=true&txt=${textrecord}")"
+ else
+ resp="$(__duckdns_api "update/?${domains}${token}${ip4}${ip6}${clear}&verbose=true")"
+ fi
+ changed4="$(echo "$resp" | __ipv4_valid)"
+ changed6="$(echo "$resp" | __ipv6_valid)"
+ nochange="$(echo "$resp" | grep 'NOCHANGE')"
+ if echo "$resp" | grep -q 'OK'; then
+ if [ -n "$nochange" ]; then
+ printf_green "Successfully sent command, however, nothing was changed"
+ else
+ if [ -n "$textrecord" ]; then
+ printf_green "Successfully updated $domain with txt: ${DUCKDNS_TEXT}"
+ fi
+ if [ -n "$changed4" ]; then
+ printf_green "Successfully updated $domain with ip4: ${changed4}"
+ fi
+ if [ -n "$changed6" ]; then
+ printf_green "Successfully updated $domain with ip6: ${changed6}"
+ fi
+ fi
+ return 0
+ else
+ printf_red "Update of $domain has failed with error: ${CYAN}$resp${NC}"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__ipv4_valid() {
+ cat - | grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" | grep '^'
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__ipv6_valid() {
+ cat - | grep -E '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))' | grep '^'
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__uriencode() {
+ local s="$1"
+ s="${s//'%'/%25}"
+ s="${s//' '/%20}"
+ s="${s//'"'/%22}"
+ s="${s//'#'/%23}"
+ s="${s//'$'/%24}"
+ s="${s//'&'/%26}"
+ s="${s//'+'/%2B}"
+ s="${s//','/%2C}"
+ s="${s//'/'/%2F}"
+ s="${s//':'/%3A}"
+ s="${s//';'/%3B}"
+ s="${s//'='/%3D}"
+ s="${s//'?'/%3F}"
+ s="${s//'@'/%40}"
+ s="${s//'['/%5B}"
+ s="${s//']'/%5D}"
+ printf '%s' "$s"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__letsencrypt_cron() {
+ [ -n "$DUCKDNS_DOMAIN" ] || return 0
+ echo "0 3 */8 * * root $APPNAME letsencrypt renew" | sudo tee -p "/etc/cron.d/$DUCKDNS_DOMAIN" &>/dev/null
+ [ -f "/etc/cron.d/$DUCKDNS_DOMAIN" ] && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__letsencrypt_create() {
+ [ -n "$DUCKDNS_API_KEY" ] || printf_exit "The api key is not set"
+ [ -n "$DUCKDNS_LETSENCRYPT_EMAIL" ] || DUCKDNS_LETSENCRYPT_EMAIL="ssl@$DUCKDNS_DOMAIN"
+ printf_cyan "Please wait while I setup the certs for the following domain: ${YELLOW}$DUCKDNS_DOMAIN *.$DUCKDNS_DOMAIN${NC}"
+ sudo -n true && sudo mkdir -p /etc/letsencrypt /var/log/letsencrypt && chmod 777 /etc/letsencrypt /var/log/letsencrypt
+ docker pull $DUCKDNS_CERTBOT_CONTAINER &>/dev/null
+ docker run \
+ --rm \
+ --name duckdns-letsencrypt-bot \
+ -v "/etc/letsencrypt:/etc/letsencrypt" \
+ -v "/var/log/letsencrypt:/var/log/letsencrypt" \
+ $DUCKDNS_CERTBOT_CONTAINER certonly --non-interactive --agree-tos --email $DUCKDNS_LETSENCRYPT_EMAIL \
+ --preferred-challenges dns --authenticator dns-duckdns --dns-duckdns-propagation-seconds 60 --expand \
+ --dns-duckdns-token "$DUCKDNS_API_KEY" -d "$DUCKDNS_DOMAIN" -d "*.$DUCKDNS_DOMAIN" >"$DUCKDNS_LOG_DIR/lecert.log" 2>&1 && __letsencrypt_cron || false
+ if [ -d "/etc/letsencrypt/live/$DUCKDNS_DOMAIN" ]; then
+ printf_green "Certs saved to: /etc/letsencrypt/live/$DUCKDNS_DOMAIN"
+ return 0
+ else
+ printf_red "Failed to create the certs: $DUCKDNS_LOG_DIR/lecert.log"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__letsencrypt_renew() {
+ docker pull $DUCKDNS_CERTBOT_CONTAINER &>/dev/null
+ docker run \
+ --rm \
+ --name duckdns-letsencrypt-bot \
+ -v "/etc/letsencrypt:/etc/letsencrypt" \
+ -v "/var/log/letsencrypt:/var/log/letsencrypt" \
+ $DUCKDNS_CERTBOT_CONTAINER renew && __letsencrypt_cron || false
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__run_cron() {
+ dom="${1:-$DUCKDNS_DOMAIN}"
+ DUCKDNS_SILENT="true"
+ [ -n "$dom" ] || { echo "No domain was given" && return 1; }
+ sep='# - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+ status="$(__duckdns_update "$dom" | grep '^' || echo 'Something went wrong')"
+ printf '%s\n%s\n%s\n' "$status" "Updated $(date)" "$sep" | tee -a "$DUCKDNS_LOG_DIR/cron.$dom.log"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+DUCKDNS_CONFIG_FILE="${DUCKDNS_CONFIG_FILE:-settings.conf}"
+DUCKDNS_CONFIG_DIR="${DUCKDNS_CONFIG_DIR:-$HOME/.config/myscripts/duckdns}"
+DUCKDNS_CONFIG_BACKUP_DIR="${DUCKDNS_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/duckdns/backups}"
+DUCKDNS_LOG_DIR="${DUCKDNS_LOG_DIR:-$HOME/.local/log/duckdns}"
+DUCKDNS_TEMP_DIR="${DUCKDNS_TEMP_DIR:-$HOME/.local/tmp/system_scripts/duckdns}"
+DUCKDNS_CACHE_DIR="${DUCKDNS_CACHE_DIR:-$HOME/.cache/duckdns}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+DUCKDNS_OUTPUT_COLOR_1="${DUCKDNS_OUTPUT_COLOR_1:-33}"
+DUCKDNS_OUTPUT_COLOR_2="${DUCKDNS_OUTPUT_COLOR_2:-5}"
+DUCKDNS_OUTPUT_COLOR_GOOD="${DUCKDNS_OUTPUT_COLOR_GOOD:-2}"
+DUCKDNS_OUTPUT_COLOR_ERROR="${DUCKDNS_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+DUCKDNS_NOTIFY_ENABLED="${DUCKDNS_NOTIFY_ENABLED:-yes}"
+DUCKDNS_GOOD_NAME="${DUCKDNS_GOOD_NAME:-Great:}"
+DUCKDNS_ERROR_NAME="${DUCKDNS_ERROR_NAME:-Error:}"
+DUCKDNS_GOOD_MESSAGE="${DUCKDNS_GOOD_MESSAGE:-No errors reported}"
+DUCKDNS_ERROR_MESSAGE="${DUCKDNS_ERROR_MESSAGE:-Errors were reported}"
+DUCKDNS_NOTIFY_CLIENT_NAME="${DUCKDNS_NOTIFY_CLIENT_NAME:-$APPNAME}"
+DUCKDNS_NOTIFY_CLIENT_ICON="${DUCKDNS_NOTIFY_CLIENT_ICON:-notification-new}"
+DUCKDNS_NOTIFY_CLIENT_URGENCY="${DUCKDNS_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+DUCKDNS_API_KEY="${DUCKDNS_API_KEY:-}"
+DUCKDNS_DOMAIN="${DUCKDNS_DOMAIN:-}"
+DUCKDNS_CLEAR="${DUCKDNS_CLEAR:-false}"
+DUCKDNS_API_URL="${DUCKDNS_API_URL:-https://www.duckdns.org}"
+DUCKDNS_EXTERNAL_IP="${DUCKDNS_EXTERNAL_IP:-https://ifconfig.co}"
+DUCKDNS_LETSENCRYPT_EMAIL="${DUCKDNS_LETSENCRYPT_EMAIL:-}"
+DUCKDNS_CERTBOT_CONTAINER="${DUCKDNS_CERTBOT_CONTAINER:-casjaysdevdocker/certbot-duckdns}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$DUCKDNS_CONFIG_DIR/$DUCKDNS_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$DUCKDNS_CONFIG_DIR/$DUCKDNS_CONFIG_FILE" ] && . "$DUCKDNS_CONFIG_DIR/$DUCKDNS_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$DUCKDNS_LOG_DIR" ] || mkdir -p "$DUCKDNS_LOG_DIR" |& __devnull
+[ -d "$DUCKDNS_TEMP_DIR" ] || mkdir -p "$DUCKDNS_TEMP_DIR" |& __devnull
+[ -d "$DUCKDNS_CACHE_DIR" ] || mkdir -p "$DUCKDNS_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DUCKDNS_TEMP_FILE="${DUCKDNS_TEMP_FILE:-$(mktemp $DUCKDNS_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$DUCKDNS_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$DUCKDNS_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$DUCKDNS_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$DUCKDNS_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$DUCKDNS_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$DUCKDNS_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=",api:,domain:,ip4:,ip6:,txt:"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="update ssl cron"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ DUCKDNS_SILENT="true"
+ ;;
+ --api)
+ DUCKDNS_API_KEY="$2"
+ shift 2
+ ;;
+ --domain)
+ DUCKDNS_DOMAIN="$2"
+ shift 2
+ ;;
+ --ip4)
+ DUCKDNS_IP4="$2"
+ shift 2
+ ;;
+ --ip6)
+ DUCKDNS_IP6="$2"
+ shift 2
+ ;;
+ --txt)
+ DUCKDNS_TEXT="$2"
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# DUCKDNS_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# DUCKDNS_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && DUCKDNS_CWD="$1" && shift 1 || DUCKDNS_CWD="${DUCKDNS_CWD:-$PWD}"
+DUCKDNS_CWD="$(realpath "${DUCKDNS_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$DUCKDNS_CWD" ] && cd "$DUCKDNS_CWD"; then
+# if [ "$DUCKDNS_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $DUCKDNS_CWD"
+# fi
+# else
+# printf_exit "💔 $DUCKDNS_CWD does not exist 💔"
+# fi
+export DUCKDNS_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ -n "$DUCKDNS_API_KEY" ] || printf_exit "Please set the environment variable: DUCKDNS_API_KEY"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+update)
+ shift 1
+ __var_check "$1"
+ __duckdns_update "$@"
+ ;;
+ssl)
+ shift 1
+ __var_check "$2"
+ if [ "$1" = "renew" ]; then
+ __letsencrypt_renew
+ elif [ "$1" = "cron" ]; then
+ __letsencrypt_cron
+ else
+ shift $#
+ __letsencrypt_create
+ fi
+ exit $?
+ ;;
+cron)
+ case "$2" in
+ install)
+ shift 2
+ __var_check "$1"
+ printf_exit "Not enabled yet"
+ ;;
+ remove)
+ shift 2
+ __var_check "$1"
+ printf_exit "Not enabled yet"
+ ;;
+ run)
+ shift 2
+ __var_check "$1"
+ __run_cron "$1"
+ ;;
+ *)
+ shift 2
+ __run_cron "$1"
+ ;;
+ esac
+ ;;
+*)
+ __var_check "$1"
+ __duckdns_update "$@"
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/earthquakes b/bin/earthquakes
new file mode 100755
index 000000000..0bbff5249
--- /dev/null
+++ b/bin/earthquakes
@@ -0,0 +1,823 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208062115-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : earthquakes --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Saturday, Aug 06, 2022 21:15 EDT
+# @@File : earthquakes
+# @@Description : Get earthquake information from the USGS
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208062115-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+EARTHQUAKES_REQUIRE_SUDO="${EARTHQUAKES_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$EARTHQUAKES_CONFIG_DIR/$EARTHQUAKES_CONFIG_FILE"
+ fi
+ [ -d "$EARTHQUAKES_CONFIG_DIR" ] || mkdir -p "$EARTHQUAKES_CONFIG_DIR"
+ [ -d "$EARTHQUAKES_CONFIG_BACKUP_DIR" ] || mkdir -p "$EARTHQUAKES_CONFIG_BACKUP_DIR"
+ [ -f "$EARTHQUAKES_CONFIG_DIR/$EARTHQUAKES_CONFIG_FILE" ] &&
+ cp -Rf "$EARTHQUAKES_CONFIG_DIR/$EARTHQUAKES_CONFIG_FILE" "$EARTHQUAKES_CONFIG_BACKUP_DIR/$EARTHQUAKES_CONFIG_FILE.$$"
+ cat <"$EARTHQUAKES_CONFIG_DIR/$EARTHQUAKES_CONFIG_FILE"
+# Settings for earthquakes
+EARTHQUAKES_YAD_WIDTH="${EARTHQUAKES_YAD_WIDTH:-}"
+EARTHQUAKES_YAD_HEIGHT="${EARTHQUAKES_YAD_HEIGHT:-}"
+EARTHQUAKES_API_URL="${EARTHQUAKES_API_URL:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+EARTHQUAKES_OUTPUT_COLOR_1="${EARTHQUAKES_OUTPUT_COLOR_1:-}"
+EARTHQUAKES_OUTPUT_COLOR_2="${EARTHQUAKES_OUTPUT_COLOR_2:-}"
+EARTHQUAKES_OUTPUT_COLOR_GOOD="${EARTHQUAKES_OUTPUT_COLOR_GOOD:-}"
+EARTHQUAKES_OUTPUT_COLOR_ERROR="${EARTHQUAKES_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+EARTHQUAKES_NOTIFY_ENABLED="${EARTHQUAKES_NOTIFY_ENABLED:-}"
+EARTHQUAKES_GOOD_NAME="${EARTHQUAKES_GOOD_NAME:-}"
+EARTHQUAKES_ERROR_NAME="${EARTHQUAKES_ERROR_NAME:-}"
+EARTHQUAKES_GOOD_MESSAGE="${EARTHQUAKES_GOOD_MESSAGE:-}"
+EARTHQUAKES_ERROR_MESSAGE="${EARTHQUAKES_ERROR_MESSAGE:-}"
+EARTHQUAKES_NOTIFY_CLIENT_NAME="${EARTHQUAKES_NOTIFY_CLIENT_NAME:-}"
+EARTHQUAKES_NOTIFY_CLIENT_ICON="${EARTHQUAKES_NOTIFY_CLIENT_ICON:-}"
+EARTHQUAKES_NOTIFY_CLIENT_URGENCY="${EARTHQUAKES_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$EARTHQUAKES_CONFIG_DIR/$EARTHQUAKES_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$EARTHQUAKES_CONFIG_DIR/$EARTHQUAKES_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "earthquakes: Get earthquake information from the USGS - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: earthquakes [options] [search] [query]"
+ __printf_line "* - Show all data for today"
+ __printf_line "search [query] [refineQuery] - Search for data"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$EARTHQUAKES_REQUIRE_SUDO" = "yes" ] && [ -z "$EARTHQUAKES_REQUIRE_SUDO_RUN" ]; then
+ export EARTHQUAKES_REQUIRE_SUDO="no"
+ export EARTHQUAKES_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$EARTHQUAKES_TEMP_FILE" ] && rm -Rf "$EARTHQUAKES_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__jq_output() {
+ jq -rc '.features[].properties' |
+ __jq_date | __jq_reformat | __sed_clean
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__jq_reformat() {
+ jq -rc '. | [{Place: .place,Time: .time,Updated: .updated,Magnitude: .mag,Alert: .alert,tsunami: .tsunami,URL: .url}]' 2>/dev/null |
+ jq 2>/dev/null | sed 's|null|none|g' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__jq_date() {
+ jq '.time|= (. / 1000 | strftime("%Y-%m-%d %H:%M:%S")) | .updated|= (. / 1000 | strftime("%Y-%m-%d %H:%M:%S"))' 2>/dev/null
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__sed_clean() {
+ tr -d '{' |
+ sed 's|\[||g;s|\"||g;s|{||g' |
+ sed 's|\]||g;s|\}||g' |
+ sed 's|"||g;s|||g' |
+ sed 's|\\t||g;s|,||g' |
+ sed 's/\\n/\n/g; s/\\t/\t/g' |
+ sed 's|tsunami: 1|tsunami: yes|g' |
+ sed 's|tsunami: 0|tsunami: no|g' |
+ sed '/^$/d' |
+ sed '$!N; /^\(.*\)\n\1$/!P; D'
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__output() { echo "${1:-$RES}" | __jq_output; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__yad__text() {
+ set -o pipefail
+ local title="$1"
+ local color="${2:-$EARTHQUAKES_OUTPUT_COLOR_1}"
+ local EARTHQUAKES_YAD_WIDTH="${EARTHQUAKES_YAD_WIDTH:-900}"
+ local EARTHQUAKES_YAD_HEIGHT="${EARTHQUAKES_YAD_HEIGHT:-600}"
+ if __cmd_exists yad && [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ]; then
+ cat - | yad --text-info --wrap --center --title="$title" --width=${EARTHQUAKES_YAD_WIDTH:-500} --height=${EARTHQUAKES_YAD_HEIGHT:-400} 2>/dev/null &
+ return $?
+ elif __cmd_exists yad && [ -n "$DISPLAY" ] && [ -z "$SSH_CONNECTION" ]; then
+ cat - | zenity --text-info --title="$title" --width=${EARTHQUAKES_YAD_WIDTH:-500} --height=${EARTHQUAKES_YAD_HEIGHT:-400} 2>/dev/null &
+ return $?
+ else
+ cat - | printf_readline "$color"
+ return $?
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_search() {
+ QUERY="$1"
+ EARTHQUAKES_TYPE="${EARTHQUAKES_TYPE:-all_day}"
+ RES="$(curl -q -LSsf "$EARTHQUAKES_API_URL/$EARTHQUAKES_TYPE.geojson" 2>/dev/null | grep '^' || echo "")"
+ SEARCH="$(echo "$RES" | jq -rc '.features|.[].properties' | grep -Fi "$QUERY" | grep -Fi "${2:-.}" | __jq_date | __jq_reformat | __sed_clean | grep '^')"
+ if [ -n "$SEARCH" ]; then
+ echo "$SEARCH" | __yad__text "Earthquake Data for $QUERY" "$EARTHQUAKES_OUTPUT_COLOR_1"
+ exitCode=0
+ else
+ echo "Your search for $QUERY produced no results" | __yad__text "$EARTHQUAKES_OUTPUT_COLOR_1"
+ exitCode=1
+ fi
+ exit ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_earthquakes() {
+ EARTHQUAKES_TYPE="${EARTHQUAKES_TYPE:-all_day}"
+ RES="$(curl -q -LSsf "$EARTHQUAKES_API_URL/$EARTHQUAKES_TYPE.geojson" 2>/dev/null | grep '^' || echo "")"
+ if [ -n "$RES" ]; then
+ __output "$RES" | __yad__text "Earthquake Data" "$EARTHQUAKES_OUTPUT_COLOR_1"
+ exitCode=0
+ else
+ printf 'Failed to get earthquake data from\n%s\n' "$EARTHQUAKES_API_URL/$EARTHQUAKES_TYPE.geojson" | __yad__text "Failed" "$EARTHQUAKES_OUTPUT_COLOR_1"
+ exitCode=1
+ fi
+ exit ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+EARTHQUAKES_CONFIG_FILE="${EARTHQUAKES_CONFIG_FILE:-settings.conf}"
+EARTHQUAKES_CONFIG_DIR="${EARTHQUAKES_CONFIG_DIR:-$HOME/.config/myscripts/earthquakes}"
+EARTHQUAKES_CONFIG_BACKUP_DIR="${EARTHQUAKES_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/earthquakes/backups}"
+EARTHQUAKES_LOG_DIR="${EARTHQUAKES_LOG_DIR:-$HOME/.local/log/earthquakes}"
+EARTHQUAKES_TEMP_DIR="${EARTHQUAKES_TEMP_DIR:-$HOME/.local/tmp/system_scripts/earthquakes}"
+EARTHQUAKES_CACHE_DIR="${EARTHQUAKES_CACHE_DIR:-$HOME/.cache/earthquakes}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+EARTHQUAKES_OUTPUT_COLOR_1="${EARTHQUAKES_OUTPUT_COLOR_1:-33}"
+EARTHQUAKES_OUTPUT_COLOR_2="${EARTHQUAKES_OUTPUT_COLOR_2:-5}"
+EARTHQUAKES_OUTPUT_COLOR_GOOD="${EARTHQUAKES_OUTPUT_COLOR_GOOD:-2}"
+EARTHQUAKES_OUTPUT_COLOR_ERROR="${EARTHQUAKES_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+EARTHQUAKES_NOTIFY_ENABLED="${EARTHQUAKES_NOTIFY_ENABLED:-yes}"
+EARTHQUAKES_GOOD_NAME="${EARTHQUAKES_GOOD_NAME:-Great:}"
+EARTHQUAKES_ERROR_NAME="${EARTHQUAKES_ERROR_NAME:-Error:}"
+EARTHQUAKES_GOOD_MESSAGE="${EARTHQUAKES_GOOD_MESSAGE:-No errors reported}"
+EARTHQUAKES_ERROR_MESSAGE="${EARTHQUAKES_ERROR_MESSAGE:-Errors were reported}"
+EARTHQUAKES_NOTIFY_CLIENT_NAME="${EARTHQUAKES_NOTIFY_CLIENT_NAME:-$APPNAME}"
+EARTHQUAKES_NOTIFY_CLIENT_ICON="${EARTHQUAKES_NOTIFY_CLIENT_ICON:-notification-new}"
+EARTHQUAKES_NOTIFY_CLIENT_URGENCY="${EARTHQUAKES_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+EARTHQUAKES_YAD_WIDTH="${EARTHQUAKES_YAD_WIDTH:-900}"
+EARTHQUAKES_YAD_HEIGHT="${EARTHQUAKES_YAD_HEIGHT:-600}"
+EARTHQUAKES_API_URL="${EARTHQUAKES_API_URL:-https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$EARTHQUAKES_CONFIG_DIR/$EARTHQUAKES_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$EARTHQUAKES_CONFIG_DIR/$EARTHQUAKES_CONFIG_FILE" ] && . "$EARTHQUAKES_CONFIG_DIR/$EARTHQUAKES_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$EARTHQUAKES_LOG_DIR" ] || mkdir -p "$EARTHQUAKES_LOG_DIR" |& __devnull
+[ -d "$EARTHQUAKES_TEMP_DIR" ] || mkdir -p "$EARTHQUAKES_TEMP_DIR" |& __devnull
+[ -d "$EARTHQUAKES_CACHE_DIR" ] || mkdir -p "$EARTHQUAKES_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+EARTHQUAKES_TEMP_FILE="${EARTHQUAKES_TEMP_FILE:-$(mktemp $EARTHQUAKES_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$EARTHQUAKES_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$EARTHQUAKES_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$EARTHQUAKES_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$EARTHQUAKES_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$EARTHQUAKES_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$EARTHQUAKES_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,help,options,raw,version,silent,"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="hour day week month"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST="major 4 2 1 minor"
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ EARTHQUAKES_SILENT="true"
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# EARTHQUAKES_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# EARTHQUAKES_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && EARTHQUAKES_CWD="$1" && shift 1 || EARTHQUAKES_CWD="${EARTHQUAKES_CWD:-$PWD}"
+EARTHQUAKES_CWD="$(realpath "${EARTHQUAKES_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$EARTHQUAKES_CWD" ] && cd "$EARTHQUAKES_CWD"; then
+# if [ "$EARTHQUAKES_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $EARTHQUAKES_CWD"
+# fi
+# else
+# printf_exit "💔 $EARTHQUAKES_CWD does not exist 💔"
+# fi
+export EARTHQUAKES_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+[ "$CONSOLE_APP" = "true" ] && __yad__text() { tee | printf_readline "$EARTHQUAKES_OUTPUT_COLOR_2"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+hour)
+ shift 1
+ case "$1" in
+ major)
+ shift 1
+ EARTHQUAKES_TYPE="significant_hour"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ 4)
+ shift 1
+ EARTHQUAKES_TYPE="4.5_hour"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ 2)
+ shift 1
+ EARTHQUAKES_TYPE="2.5_hour"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ minor)
+ shift 1
+ EARTHQUAKES_TYPE="1.0_hour"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ *)
+ EARTHQUAKES_TYPE="all_hour"
+ [ "$1" = "all" ] && shift 1
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ esac
+ ;;
+day)
+ shift 1
+ case "$1" in
+ major)
+ shift 1
+ EARTHQUAKES_TYPE="significant_day"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ 4)
+ shift 1
+ EARTHQUAKES_TYPE="4.5_day"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ 2)
+ shift 1
+ EARTHQUAKES_TYPE="2.5_day"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ minor)
+ shift 1
+ EARTHQUAKES_TYPE="1.0_day"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ *)
+ EARTHQUAKES_TYPE="all_day"
+ [ "$1" = "all" ] && shift 1
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ esac
+ ;;
+
+week)
+ shift 1
+ case "$1" in
+ major)
+ shift 1
+ EARTHQUAKES_TYPE="significant_week"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ 4)
+ shift 1
+ EARTHQUAKES_TYPE="4.5_week"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ 2)
+ shift 1
+ EARTHQUAKES_TYPE="2.5_week"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ minor)
+ shift 1
+ EARTHQUAKES_TYPE="1.0_week"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ *)
+ EARTHQUAKES_TYPE="all_week"
+ [ "$1" = "all" ] && shift 1
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ esac
+ ;;
+
+month)
+ shift 1
+ case "$1" in
+ major)
+ shift 1
+ EARTHQUAKES_TYPE="significant_month"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ 4)
+ shift 1
+ EARTHQUAKES_TYPE="4.5_month"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ 2)
+ shift 1
+ EARTHQUAKES_TYPE="2.5_month"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ minor)
+ shift 1
+ EARTHQUAKES_TYPE="1.0_month"
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ *)
+ EARTHQUAKES_TYPE="all_month"
+ [ "$1" = "all" ] && shift 1
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+ esac
+ ;;
+
+*)
+ EARTHQUAKES_TYPE="all_day"
+ [ "$1" = "all" ] && shift 1
+ [ "$1" = "search" ] && [ -n "$2" ] && SEARCH="true" && shift 1
+ if [ -n "${SEARCH:-$1}" ]; then
+ __execute_search "$1"
+ else
+ __execute_earthquakes
+ fi
+ ;;
+esac
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/emojis b/bin/emojis
new file mode 100755
index 000000000..2c3d64ba5
--- /dev/null
+++ b/bin/emojis
@@ -0,0 +1,633 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208062250-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : emojis --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Saturday, Aug 06, 2022 22:50 EDT
+# @@File : emojis
+# @@Description : show and choose an emoji
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208062250-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+EMOJIS_REQUIRE_SUDO="${EMOJIS_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$EMOJIS_CONFIG_DIR/$EMOJIS_CONFIG_FILE"
+ fi
+ [ -d "$EMOJIS_CONFIG_DIR" ] || mkdir -p "$EMOJIS_CONFIG_DIR"
+ [ -d "$EMOJIS_CONFIG_BACKUP_DIR" ] || mkdir -p "$EMOJIS_CONFIG_BACKUP_DIR"
+ [ -f "$EMOJIS_CONFIG_DIR/$EMOJIS_CONFIG_FILE" ] &&
+ cp -Rf "$EMOJIS_CONFIG_DIR/$EMOJIS_CONFIG_FILE" "$EMOJIS_CONFIG_BACKUP_DIR/$EMOJIS_CONFIG_FILE.$$"
+ cat <"$EMOJIS_CONFIG_DIR/$EMOJIS_CONFIG_FILE"
+# Settings for emojis
+EMOJIS_EMOJIFY_BIN="${EMOJIS_EMOJIFY_BIN:-}"
+EMOJIS_EMOJIFY_URL="${EMOJIS_EMOJIFY_URL:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+EMOJIS_OUTPUT_COLOR_1="${EMOJIS_OUTPUT_COLOR_1:-}"
+EMOJIS_OUTPUT_COLOR_2="${EMOJIS_OUTPUT_COLOR_2:-}"
+EMOJIS_OUTPUT_COLOR_GOOD="${EMOJIS_OUTPUT_COLOR_GOOD:-}"
+EMOJIS_OUTPUT_COLOR_ERROR="${EMOJIS_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+EMOJIS_NOTIFY_ENABLED="${EMOJIS_NOTIFY_ENABLED:-}"
+EMOJIS_GOOD_NAME="${EMOJIS_GOOD_NAME:-}"
+EMOJIS_ERROR_NAME="${EMOJIS_ERROR_NAME:-}"
+EMOJIS_GOOD_MESSAGE="${EMOJIS_GOOD_MESSAGE:-}"
+EMOJIS_ERROR_MESSAGE="${EMOJIS_ERROR_MESSAGE:-}"
+EMOJIS_NOTIFY_CLIENT_NAME="${EMOJIS_NOTIFY_CLIENT_NAME:-}"
+EMOJIS_NOTIFY_CLIENT_ICON="${EMOJIS_NOTIFY_CLIENT_ICON:-}"
+EMOJIS_NOTIFY_CLIENT_URGENCY="${EMOJIS_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$EMOJIS_CONFIG_DIR/$EMOJIS_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$EMOJIS_CONFIG_DIR/$EMOJIS_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "emojis: show and choose an emoji - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: emojis [options] [commands]"
+ __printf_line "* - echo 'I :heart: you'|emojis"
+ __printf_line "update - Update the script"
+ __printf_line "dmenu - Opens a dmenu prompt"
+ __printf_line "search - Search for an emoji"
+ __printf_line "print - emojis ':heart:'"
+ __printf_line "list - List all the emojis"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$EMOJIS_REQUIRE_SUDO" = "yes" ] && [ -z "$EMOJIS_REQUIRE_SUDO_RUN" ]; then
+ export EMOJIS_REQUIRE_SUDO="no"
+ export EMOJIS_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$EMOJIS_TEMP_FILE" ] && rm -Rf "$EMOJIS_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+if __cmd_exists rofi; then
+ __dmenu() { rofi -theme ${ROFI_THEME:-purple} -dmenu -l 20 -p "$1" 2>/dev/null; }
+elif __cmd_exists dmenu; then
+ __dmenu() { dmenu -i -l 20 -p "$1" 2>/dev/null; }
+else
+ __dmenu() { false; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__list_emojis() {
+ [ -f "$EMOJIS_EMOJIFY_BIN" ] || printf_exit "Can not find $EMOJIS_EMOJIFY_BIN"
+ $EMOJIS_EMOJIFY_BIN --list | grep -vE '^$|emojify - emoji on the|USAGE: emojify|Supported emojis:' | awk -F' ' '{print $2" "$1}'
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+dmenu_emojis() {
+ builtin type -P clipboard &>/dev/null || exit 1
+ export CLIPBOARD_NOTIFY="false"
+ chosen="$(__list_emojis | __dmenu "Emoji Picker" | awk -F ' ' '{print $1}')"
+ [ -n "$chosen" ] || exit 1
+ printf '%s' "$chosen" | clipboard
+ __notifications "Emojify" "$chosen copied to clipboard."
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+update_list() {
+ (
+ __list_emojis | grep ':.*:' | awk -F' ' '{print $1}' | sed 's| ||g' | grep -v '^$' | tr '\n' ' '
+ printf_newline "\n"
+ ) >"${1:-$EMOJIS_CONFIG_DIR/list}"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__update_emoji_bin() {
+ [ -d "$HOME/.local/share/myscripts/emojis" ] || mkdir -p "$HOME/.local/share/myscripts/emojis"
+ if curl -q -LSs "$EMOJIS_EMOJIFY_URL" -o "$EMOJIS_EMOJIFY_BIN" 2>/dev/null; then
+ chmod +x "$EMOJIS_EMOJIFY_BIN"
+ printf_green "Successfully update $EMOJIS_EMOJIFY_BIN"
+ else
+ printf_red "Failed to update $EMOJIS_EMOJIFY_BIN"
+ printf_red "from $EMOJIS_EMOJIFY_URL"
+ fi
+ update_list "$EMOJIS_CONFIG_DIR/list"
+ if [ $? -eq 0 ]; then
+ printf_green "Successfully update emoji list"
+ return 0
+ else
+ printf_return "Failed to update emoji list"
+ return 1
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+EMOJIS_CONFIG_FILE="${EMOJIS_CONFIG_FILE:-settings.conf}"
+EMOJIS_CONFIG_DIR="${EMOJIS_CONFIG_DIR:-$HOME/.config/myscripts/emojis}"
+EMOJIS_CONFIG_BACKUP_DIR="${EMOJIS_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/emojis/backups}"
+EMOJIS_LOG_DIR="${EMOJIS_LOG_DIR:-$HOME/.local/log/emojis}"
+EMOJIS_TEMP_DIR="${EMOJIS_TEMP_DIR:-$HOME/.local/tmp/system_scripts/emojis}"
+EMOJIS_CACHE_DIR="${EMOJIS_CACHE_DIR:-$HOME/.cache/emojis}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+EMOJIS_OUTPUT_COLOR_1="${EMOJIS_OUTPUT_COLOR_1:-33}"
+EMOJIS_OUTPUT_COLOR_2="${EMOJIS_OUTPUT_COLOR_2:-5}"
+EMOJIS_OUTPUT_COLOR_GOOD="${EMOJIS_OUTPUT_COLOR_GOOD:-2}"
+EMOJIS_OUTPUT_COLOR_ERROR="${EMOJIS_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+EMOJIS_NOTIFY_ENABLED="${EMOJIS_NOTIFY_ENABLED:-yes}"
+EMOJIS_GOOD_NAME="${EMOJIS_GOOD_NAME:-Great:}"
+EMOJIS_ERROR_NAME="${EMOJIS_ERROR_NAME:-Error:}"
+EMOJIS_GOOD_MESSAGE="${EMOJIS_GOOD_MESSAGE:-No errors reported}"
+EMOJIS_ERROR_MESSAGE="${EMOJIS_ERROR_MESSAGE:-Errors were reported}"
+EMOJIS_NOTIFY_CLIENT_NAME="${EMOJIS_NOTIFY_CLIENT_NAME:-$APPNAME}"
+EMOJIS_NOTIFY_CLIENT_ICON="${EMOJIS_NOTIFY_CLIENT_ICON:-notification-new}"
+EMOJIS_NOTIFY_CLIENT_URGENCY="${EMOJIS_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+EMOJIS_EMOJIFY_BIN="${EMOJIS_EMOJIFY_BIN:-$HOME/.local/share/myscripts/emojis/emojify}"
+EMOJIS_EMOJIFY_URL="${EMOJIS_EMOJIFY_URL:-https://raw.githubusercontent.com/mrowa44/emojify/master/emojify}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$EMOJIS_CONFIG_DIR/$EMOJIS_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$EMOJIS_CONFIG_DIR/$EMOJIS_CONFIG_FILE" ] && . "$EMOJIS_CONFIG_DIR/$EMOJIS_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$EMOJIS_LOG_DIR" ] || mkdir -p "$EMOJIS_LOG_DIR" |& __devnull
+[ -d "$EMOJIS_TEMP_DIR" ] || mkdir -p "$EMOJIS_TEMP_DIR" |& __devnull
+[ -d "$EMOJIS_CACHE_DIR" ] || mkdir -p "$EMOJIS_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+EMOJIS_TEMP_FILE="${EMOJIS_TEMP_FILE:-$(mktemp $EMOJIS_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$EMOJIS_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$EMOJIS_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$EMOJIS_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$EMOJIS_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$EMOJIS_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$EMOJIS_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY="update dmenu search print list"
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ EMOJIS_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ EMOJIS_CWD="$2"
+ [ -d "$EMOJIS_CWD" ] || mkdir -p "$EMOJIS_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# EMOJIS_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# EMOJIS_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && EMOJIS_CWD="$1" && shift 1 || EMOJIS_CWD="${EMOJIS_CWD:-$PWD}"
+EMOJIS_CWD="$(realpath "${EMOJIS_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$EMOJIS_CWD" ] && cd "$EMOJIS_CWD"; then
+# if [ "$EMOJIS_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $EMOJIS_CWD"
+# fi
+# else
+# printf_exit "💔 $EMOJIS_CWD does not exist 💔"
+# fi
+export EMOJIS_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+export CLIPBOARD_NOTIFY="false"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+if [ "$EMOJIS_EMOJIFY_BIN" = "$CASJAYSDEVDIR/sources/emojify" ]; then
+ cp -Rfv "$CASJAYSDEVDIR/sources/emojify" "$HOME/.local/share/myscripts/emojis/emojify"
+ EMOJIS_EMOJIFY_BIN="$HOME/.local/share/myscripts/emojis/emojify"
+fi
+[ -f "$EMOJIS_EMOJIFY_BIN" ] || __update_emoji_bin
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$1" in
+update)
+ __update_emoji_bin
+ exit $?
+ ;;
+
+dmenu)
+ dmenu_emojis
+ exit $?
+ ;;
+
+search)
+ shift 1
+ res=""
+ for search in "$@"; do
+ s+="$search "
+ res+="$($EMOJIS_EMOJIFY_BIN --list | grep -i --color=auto "$search" | awk -F ' ' '{print $2}' | tr '\n' '\t' | grep '^')"
+ done
+ [ -n "$res" ] && printf_cyan "Found the following results" && printf_cyan "$res" || printf_red "No result for $search were found"
+ exit $?
+ ;;
+
+print)
+ shift 1
+ if [ $# -eq 0 ]; then
+ if [ $# -eq 0 ] && [ -p "/dev/stdin" ]; then
+ message="$(/dev/null)"
+VERSION="202208062253-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+ENCRYPT_REQUIRE_SUDO="${ENCRYPT_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$ENCRYPT_CONFIG_DIR/$ENCRYPT_CONFIG_FILE"
+ fi
+ [ -d "$ENCRYPT_CONFIG_DIR" ] || mkdir -p "$ENCRYPT_CONFIG_DIR"
+ [ -d "$ENCRYPT_CONFIG_BACKUP_DIR" ] || mkdir -p "$ENCRYPT_CONFIG_BACKUP_DIR"
+ [ -f "$ENCRYPT_CONFIG_DIR/$ENCRYPT_CONFIG_FILE" ] &&
+ cp -Rf "$ENCRYPT_CONFIG_DIR/$ENCRYPT_CONFIG_FILE" "$ENCRYPT_CONFIG_BACKUP_DIR/$ENCRYPT_CONFIG_FILE.$$"
+ cat <"$ENCRYPT_CONFIG_DIR/$ENCRYPT_CONFIG_FILE"
+# Settings for encrypt
+ENCRYPT_PASSWORD="${ENCRYPT_PASSWORD:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ENCRYPT_OUTPUT_COLOR_1="${ENCRYPT_OUTPUT_COLOR_1:-}"
+ENCRYPT_OUTPUT_COLOR_2="${ENCRYPT_OUTPUT_COLOR_2:-}"
+ENCRYPT_OUTPUT_COLOR_GOOD="${ENCRYPT_OUTPUT_COLOR_GOOD:-}"
+ENCRYPT_OUTPUT_COLOR_ERROR="${ENCRYPT_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ENCRYPT_NOTIFY_ENABLED="${ENCRYPT_NOTIFY_ENABLED:-}"
+ENCRYPT_GOOD_NAME="${ENCRYPT_GOOD_NAME:-}"
+ENCRYPT_ERROR_NAME="${ENCRYPT_ERROR_NAME:-}"
+ENCRYPT_GOOD_MESSAGE="${ENCRYPT_GOOD_MESSAGE:-}"
+ENCRYPT_ERROR_MESSAGE="${ENCRYPT_ERROR_MESSAGE:-}"
+ENCRYPT_NOTIFY_CLIENT_NAME="${ENCRYPT_NOTIFY_CLIENT_NAME:-}"
+ENCRYPT_NOTIFY_CLIENT_ICON="${ENCRYPT_NOTIFY_CLIENT_ICON:-}"
+ENCRYPT_NOTIFY_CLIENT_URGENCY="${ENCRYPT_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$ENCRYPT_CONFIG_DIR/$ENCRYPT_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$ENCRYPT_CONFIG_DIR/$ENCRYPT_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "encrypt: perl oneliner is to enable encrypt files - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: encrypt [options] [commands]"
+ __printf_line "/path/to/file - Encrypt file"
+ __printf_line "echo 'some text'|encrypt - Encrypt text"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$ENCRYPT_REQUIRE_SUDO" = "yes" ] && [ -z "$ENCRYPT_REQUIRE_SUDO_RUN" ]; then
+ export ENCRYPT_REQUIRE_SUDO="no"
+ export ENCRYPT_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$ENCRYPT_TEMP_FILE" ] && rm -Rf "$ENCRYPT_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+ENCRYPT_CONFIG_FILE="${ENCRYPT_CONFIG_FILE:-settings.conf}"
+ENCRYPT_CONFIG_DIR="${ENCRYPT_CONFIG_DIR:-$HOME/.config/myscripts/encrypt}"
+ENCRYPT_CONFIG_BACKUP_DIR="${ENCRYPT_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/encrypt/backups}"
+ENCRYPT_LOG_DIR="${ENCRYPT_LOG_DIR:-$HOME/.local/log/encrypt}"
+ENCRYPT_TEMP_DIR="${ENCRYPT_TEMP_DIR:-$HOME/.local/tmp/system_scripts/encrypt}"
+ENCRYPT_CACHE_DIR="${ENCRYPT_CACHE_DIR:-$HOME/.cache/encrypt}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ENCRYPT_OUTPUT_COLOR_1="${ENCRYPT_OUTPUT_COLOR_1:-33}"
+ENCRYPT_OUTPUT_COLOR_2="${ENCRYPT_OUTPUT_COLOR_2:-5}"
+ENCRYPT_OUTPUT_COLOR_GOOD="${ENCRYPT_OUTPUT_COLOR_GOOD:-2}"
+ENCRYPT_OUTPUT_COLOR_ERROR="${ENCRYPT_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ENCRYPT_NOTIFY_ENABLED="${ENCRYPT_NOTIFY_ENABLED:-yes}"
+ENCRYPT_GOOD_NAME="${ENCRYPT_GOOD_NAME:-Great:}"
+ENCRYPT_ERROR_NAME="${ENCRYPT_ERROR_NAME:-Error:}"
+ENCRYPT_GOOD_MESSAGE="${ENCRYPT_GOOD_MESSAGE:-No errors reported}"
+ENCRYPT_ERROR_MESSAGE="${ENCRYPT_ERROR_MESSAGE:-Errors were reported}"
+ENCRYPT_NOTIFY_CLIENT_NAME="${ENCRYPT_NOTIFY_CLIENT_NAME:-$APPNAME}"
+ENCRYPT_NOTIFY_CLIENT_ICON="${ENCRYPT_NOTIFY_CLIENT_ICON:-notification-new}"
+ENCRYPT_NOTIFY_CLIENT_URGENCY="${ENCRYPT_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+ENCRYPT_PASSWORD="${ENCRYPT_PASSWORD:-verylongsecurepassword}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$ENCRYPT_CONFIG_DIR/$ENCRYPT_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$ENCRYPT_CONFIG_DIR/$ENCRYPT_CONFIG_FILE" ] && . "$ENCRYPT_CONFIG_DIR/$ENCRYPT_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$ENCRYPT_LOG_DIR" ] || mkdir -p "$ENCRYPT_LOG_DIR" |& __devnull
+[ -d "$ENCRYPT_TEMP_DIR" ] || mkdir -p "$ENCRYPT_TEMP_DIR" |& __devnull
+[ -d "$ENCRYPT_CACHE_DIR" ] || mkdir -p "$ENCRYPT_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ENCRYPT_TEMP_FILE="${ENCRYPT_TEMP_FILE:-$(mktemp $ENCRYPT_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$ENCRYPT_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$ENCRYPT_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$ENCRYPT_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$ENCRYPT_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$ENCRYPT_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$ENCRYPT_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ ENCRYPT_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ ENCRYPT_CWD="$2"
+ [ -d "$ENCRYPT_CWD" ] || mkdir -p "$ENCRYPT_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# ENCRYPT_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# ENCRYPT_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && ENCRYPT_CWD="$1" && shift 1 || ENCRYPT_CWD="${ENCRYPT_CWD:-$PWD}"
+ENCRYPT_CWD="$(realpath "${ENCRYPT_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$ENCRYPT_CWD" ] && cd "$ENCRYPT_CWD"; then
+# if [ "$ENCRYPT_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $ENCRYPT_CWD"
+# fi
+# else
+# printf_exit "💔 $ENCRYPT_CWD does not exist 💔"
+# fi
+export ENCRYPT_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+[ -f "$ENCRYPT_CONFIG_DIR/.password" ] && ENCRYPT_PASSWORD="$(<"$ENCRYPT_CONFIG_DIR/.password")"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+if [ -t 0 ]; then
+ fname="$1"
+ shift
+ if echo "$ENCRYPT_PASSWORD" | openssl aes-256-cbc -pbkdf2 -salt -in "$fname" -out "${fname}.enc" "$@" -pass stdin; then
+ printf_green "Successfully encrypted $1"
+ printf_cyan "Using the password from config"
+ else
+ printf_return "Something went wrong: check your password"
+ fi
+else
+ perl -e 'use IO::Select; $ready=IO::Select->new(STDIN)->can_read();'
+ if echo "$ENCRYPT_PASSWORD" | openssl aes-256-cbc -pbkdf2 -salt "$@" -pass stdin; then
+ printf_green "Successfully encrypted $1"
+ printf_cyan "Using the password from config"
+ else
+ printf_return "Something went wrong: check your password"
+ fi
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/eslint-config b/bin/eslint-config
new file mode 100755
index 000000000..f0e4f761b
--- /dev/null
+++ b/bin/eslint-config
@@ -0,0 +1,758 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208062255-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : eslint-config --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Saturday, Aug 06, 2022 22:55 EDT
+# @@File : eslint-config
+# @@Description : Setup eslint for current project
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208062255-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+ESLINT_CONFIG_REQUIRE_SUDO="${ESLINT_CONFIG_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$ESLINT_CONFIG_CONFIG_DIR/$ESLINT_CONFIG_CONFIG_FILE"
+ fi
+ [ -d "$ESLINT_CONFIG_CONFIG_DIR" ] || mkdir -p "$ESLINT_CONFIG_CONFIG_DIR"
+ [ -d "$ESLINT_CONFIG_CONFIG_BACKUP_DIR" ] || mkdir -p "$ESLINT_CONFIG_CONFIG_BACKUP_DIR"
+ [ -f "$ESLINT_CONFIG_CONFIG_DIR/$ESLINT_CONFIG_CONFIG_FILE" ] &&
+ cp -Rf "$ESLINT_CONFIG_CONFIG_DIR/$ESLINT_CONFIG_CONFIG_FILE" "$ESLINT_CONFIG_CONFIG_BACKUP_DIR/$ESLINT_CONFIG_CONFIG_FILE.$$"
+ cat <"$ESLINT_CONFIG_CONFIG_DIR/$ESLINT_CONFIG_CONFIG_FILE"
+# Settings for eslint-config
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ESLINT_CONFIG_OUTPUT_COLOR_1="${ESLINT_CONFIG_OUTPUT_COLOR_1:-}"
+ESLINT_CONFIG_OUTPUT_COLOR_2="${ESLINT_CONFIG_OUTPUT_COLOR_2:-}"
+ESLINT_CONFIG_OUTPUT_COLOR_GOOD="${ESLINT_CONFIG_OUTPUT_COLOR_GOOD:-}"
+ESLINT_CONFIG_OUTPUT_COLOR_ERROR="${ESLINT_CONFIG_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ESLINT_CONFIG_NOTIFY_ENABLED="${ESLINT_CONFIG_NOTIFY_ENABLED:-}"
+ESLINT_CONFIG_GOOD_NAME="${ESLINT_CONFIG_GOOD_NAME:-}"
+ESLINT_CONFIG_ERROR_NAME="${ESLINT_CONFIG_ERROR_NAME:-}"
+ESLINT_CONFIG_GOOD_MESSAGE="${ESLINT_CONFIG_GOOD_MESSAGE:-}"
+ESLINT_CONFIG_ERROR_MESSAGE="${ESLINT_CONFIG_ERROR_MESSAGE:-}"
+ESLINT_CONFIG_NOTIFY_CLIENT_NAME="${ESLINT_CONFIG_NOTIFY_CLIENT_NAME:-}"
+ESLINT_CONFIG_NOTIFY_CLIENT_ICON="${ESLINT_CONFIG_NOTIFY_CLIENT_ICON:-}"
+ESLINT_CONFIG_NOTIFY_CLIENT_URGENCY="${ESLINT_CONFIG_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$ESLINT_CONFIG_CONFIG_DIR/$ESLINT_CONFIG_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$ESLINT_CONFIG_CONFIG_DIR/$ESLINT_CONFIG_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "eslint-config: Setup eslint for current project - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: eslint-config [options]"
+ __printf_line " - Sets up an eslint config file"
+ __printf_line "--dir [/path/to/dir] - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$ESLINT_CONFIG_REQUIRE_SUDO" = "yes" ] && [ -z "$ESLINT_CONFIG_REQUIRE_SUDO_RUN" ]; then
+ export ESLINT_CONFIG_REQUIRE_SUDO="no"
+ export ESLINT_CONFIG_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$ESLINT_CONFIG_TEMP_FILE" ] && rm -Rf "$ESLINT_CONFIG_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__check_existing() {
+ ls -a "$1" | grep "$2" | xargs -n 1 basename 2>/dev/null | tr '\n' ' ' | grep '^' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__execute_eslint_config() {
+ # Package Manager Prompt
+ printf_blue "Which package manager are you using? "
+ select package_command_choices in "Yarn" "npm" "Cancel"; do
+ case $package_command_choices in
+ Yarn)
+ pkg_cmd='yarn add'
+ __cmd_exists yarn && break ||
+ { printf_red "yarn is not installed: try npm instead or install yarn" && continue; }
+ ;;
+ npm)
+ pkg_cmd='npm install'
+ __cmd_exists npm && break ||
+ { printf_red "npm is not installed: try yarn instead or install npme" && continue; }
+ break
+ ;;
+ Cancel) exit 1 ;;
+ esac
+ done
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ # File Format Prompt
+ printf_blue "Which ESLint and Prettier configuration format do you prefer? "
+ select config_extension in ".js" ".json" "Cancel"; do
+ case $config_extension in
+ .js)
+ config_opening='module.exports = {'
+ break
+ ;;
+ .json)
+ config_opening='{'
+ break
+ ;;
+ Cancel) exit 1 ;;
+ esac
+ done
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ # Checks for existing eslintrc files
+ if [ -f ".eslintrc.js" ] || [ -f ".eslintrc.yaml" ] || [ -f ".eslintrc.yml" ] || [ -f ".eslintrc.json" ] || [ -f ".eslintrc" ]; then
+ existing="$(__check_existing "." '.eslint.*')"
+ printf_red "Existing ESLint config file(s) found: $existing"
+ printf_red "CAUTION: there is loading priority when more than one config file is present:"
+ printf_blue "https://eslint.org/docs/user-guide/configuring#configuration-file-formats"
+ printf_read_question "3" "Write .eslintrc${config_extension} (Y/n)?" "1" "REPLY"
+ if [[ $REPLY =~ ^[Nn]$ ]]; then
+ printf_yellow ">>>>> Skipping ESLint config"
+ skip_eslint_setup="true"
+ fi
+ fi
+ finished="false"
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ # Max Line Length Prompt
+ while ! $finished; do
+ printf_read_input "3" "What max line length do you want to set for ESLint and Prettier? (Recommendation: 80)" "3" "REPLY" "-i 120 "
+ if [[ $REPLY =~ ^[0-9]{2,3}$ ]]; then
+ max_len_val=$REPLY
+ finished=true
+ else
+ printf_yellow "Please choose a max length of two or three digits, e.g. 80 or 100 or 120 "
+ fi
+ done
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ # Trailing Commas Prompt
+ printf_blue "What style of trailing commas do you want to enforce with Prettier? "
+ printf_yellow ">>>>> See https://prettier.io/docs/en/options.html#trailing-commas for more details."
+ select trailing_comma_pref in "none" "es5" "all"; do
+ case $trailing_comma_pref in
+ none) break ;;
+ es5) break ;;
+ all) break ;;
+ esac
+ done
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ # Checks for existing prettierrc files
+ if [ -f ".prettierrc.js" ] || [ -f "prettier.config.js" ] || [ -f ".prettierrc.yaml" ] || [ -f ".prettierrc.yml" ] || [ -f ".prettierrc.json" ] || [ -f ".prettierrc.toml" ] || [ -f ".prettierrc" ]; then
+ existing="$(__check_existing '.' 'prettier.*')"
+ printf_red "Existing Prettier config file(s) found: $existing"
+ printf_red "CAUTION: The configuration file will be resolved starting from the location of the file being formatted, "
+ printf_red "and searching up the file tree until a config file is (or isn't) found. https://prettier.io/docs/en/configuration.html"
+ printf_read_question "3" "Write .prettierrc${config_extension} (Y/n)?" "1" "REPLY"
+ if [[ $REPLY =~ ^[Nn]$ ]]; then
+ printf_yellow ">>>>> Skipping Prettier config"
+ skip_prettier_setup="true"
+ fi
+ fi
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ # Perform Configuration
+ printf_green "Configuring your development environment... "
+ printf_cyan "1/5 ESLint & Prettier Installation... "
+ $pkg_cmd -D eslint prettier eslint-plugin-react-hooks &>/dev/null || false
+ printf_yellow "2/5 Conforming to Airbnb's JavaScript Style Guide... "
+ $pkg_cmd -D eslint-config-airbnb eslint-plugin-jsx-a11y eslint-plugin-import eslint-plugin-react @babel/eslint-parser &>/dev/null || false
+ printf_cyan "3/5 Making ESlint and Prettier play nice with each other... "
+ printf_blue "See https://github.com/prettier/eslint-config-prettier for more details."
+ $pkg_cmd -D eslint-config-prettier eslint-plugin-prettier &>/dev/null || false
+ if [ "$skip_eslint_setup" != "true" ]; then
+ printf_yellow "4/5 Building your .eslintrc${config_extension} file... > .eslintrc${config_extension}"
+ echo ${config_opening}'
+ "extends": [
+ "airbnb",
+ "prettier",
+ "prettier/react",
+ "plugin:jsx-a11y/recommended"
+ ],
+ "parser": "babel-eslint",
+ "parserOptions": {
+ "ecmaVersion": 8,
+ "ecmaFeatures": {
+ "experimentalObjectRestSpread": true,
+ "impliedStrict": true,
+ "classes": true
+ }
+ },
+ "env": {
+ "browser": true,
+ "node": true,
+ "jquery": true,
+ "jest": true
+ },
+ "rules": {
+ "react/prop-types": 0,
+ "react-hooks/rules-of-hooks": "error",
+ "no-debugger": 0,
+ "no-alert": 0,
+ "no-unused-vars": 1,
+ "prefer-const": [
+ "error",
+ {
+ "destructuring": "all"
+ }
+ ],
+ "arrow-body-style": [
+ 2,
+ "as-needed"
+ ],
+ "no-unused-expressions": [
+ 2,
+ {
+ "allowTaggedTemplates": true
+ }
+ ],
+ "no-param-reassign": [
+ 2,
+ {
+ "props": false
+ }
+ ],
+ "no-console": 0,
+ "import/prefer-default-export": 0,
+ "import": 0,
+ "func-names": 0,
+ "space-before-function-paren": 0,
+ "comma-dangle": 0,
+ "class-methods-use-this": 0,
+ "max-len": 0,
+ "import/extensions": 0,
+ "no-underscore-dangle": 0,
+ "consistent-return": 0,
+ "react/display-name": 1,
+ "react/no-array-index-key": 0,
+ "react/react-in-jsx-scope": 0,
+ "react/prefer-stateless-function": 0,
+ "react/forbid-prop-types": 0,
+ "react/jsx-props-no-spreading": 0,
+ "react/no-unescaped-entities": 0,
+ "jsx-a11y/accessible-emoji": 0,
+ "react/require-default-props": 0,
+ "react/jsx-filename-extension": [
+ 1,
+ {
+ "extensions": [
+ ".js",
+ ".jsx"
+ ]
+ }
+ ],
+ "radix": 0,
+ "no-shadow": [
+ 2,
+ {
+ "hoist": "all",
+ "allow": [
+ "resolve",
+ "reject",
+ "done",
+ "next",
+ "err",
+ "error"
+ ]
+ }
+ ],
+ "quotes": [
+ 2,
+ "single",
+ {
+ "avoidEscape": true,
+ "allowTemplateLiterals": true
+ }
+ ],
+ "prettier/prettier": [
+ "error",
+ {
+ "trailingComma": "es5",
+ "singleQuote": true,
+ "printWidth": 80
+ }
+ ],
+ "jsx-a11y/href-no-hash": "off",
+ "jsx-a11y/anchor-is-valid": [
+ "warn",
+ {
+ "aspects": [
+ "invalidHref"
+ ]
+ }
+ ]
+ },
+ "plugins": [
+ "prettier",
+ "react",
+ "react-hooks"
+ ]
+}' >>".eslintrc${config_extension}"
+ fi
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ if [ "$skip_prettier_setup" = "true" ]; then
+ true
+ else
+ printf_yellow "5/5 Building your .prettierrc${config_extension} file... >.prettierrc${config_extension}"
+ echo ${config_opening}'
+ "printWidth": '${max_len_val}',
+ "singleQuote": true,
+ "trailingComma": "'${trailing_comma_pref}'"
+}' >>".prettierrc${config_extension}"
+ fi
+ [ -f ".prettierrc${config_extension}" ] && printf_green "Finished setting up!" || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+ESLINT_CONFIG_CONFIG_FILE="${ESLINT_CONFIG_CONFIG_FILE:-settings.conf}"
+ESLINT_CONFIG_CONFIG_DIR="${ESLINT_CONFIG_CONFIG_DIR:-$HOME/.config/myscripts/eslint-config}"
+ESLINT_CONFIG_CONFIG_BACKUP_DIR="${ESLINT_CONFIG_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/eslint-config/backups}"
+ESLINT_CONFIG_LOG_DIR="${ESLINT_CONFIG_LOG_DIR:-$HOME/.local/log/eslint-config}"
+ESLINT_CONFIG_TEMP_DIR="${ESLINT_CONFIG_TEMP_DIR:-$HOME/.local/tmp/system_scripts/eslint-config}"
+ESLINT_CONFIG_CACHE_DIR="${ESLINT_CONFIG_CACHE_DIR:-$HOME/.cache/eslint-config}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+ESLINT_CONFIG_OUTPUT_COLOR_1="${ESLINT_CONFIG_OUTPUT_COLOR_1:-33}"
+ESLINT_CONFIG_OUTPUT_COLOR_2="${ESLINT_CONFIG_OUTPUT_COLOR_2:-5}"
+ESLINT_CONFIG_OUTPUT_COLOR_GOOD="${ESLINT_CONFIG_OUTPUT_COLOR_GOOD:-2}"
+ESLINT_CONFIG_OUTPUT_COLOR_ERROR="${ESLINT_CONFIG_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+ESLINT_CONFIG_NOTIFY_ENABLED="${ESLINT_CONFIG_NOTIFY_ENABLED:-yes}"
+ESLINT_CONFIG_GOOD_NAME="${ESLINT_CONFIG_GOOD_NAME:-Great:}"
+ESLINT_CONFIG_ERROR_NAME="${ESLINT_CONFIG_ERROR_NAME:-Error:}"
+ESLINT_CONFIG_GOOD_MESSAGE="${ESLINT_CONFIG_GOOD_MESSAGE:-No errors reported}"
+ESLINT_CONFIG_ERROR_MESSAGE="${ESLINT_CONFIG_ERROR_MESSAGE:-Errors were reported}"
+ESLINT_CONFIG_NOTIFY_CLIENT_NAME="${ESLINT_CONFIG_NOTIFY_CLIENT_NAME:-$APPNAME}"
+ESLINT_CONFIG_NOTIFY_CLIENT_ICON="${ESLINT_CONFIG_NOTIFY_CLIENT_ICON:-notification-new}"
+ESLINT_CONFIG_NOTIFY_CLIENT_URGENCY="${ESLINT_CONFIG_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$ESLINT_CONFIG_CONFIG_DIR/$ESLINT_CONFIG_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$ESLINT_CONFIG_CONFIG_DIR/$ESLINT_CONFIG_CONFIG_FILE" ] && . "$ESLINT_CONFIG_CONFIG_DIR/$ESLINT_CONFIG_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$ESLINT_CONFIG_LOG_DIR" ] || mkdir -p "$ESLINT_CONFIG_LOG_DIR" |& __devnull
+[ -d "$ESLINT_CONFIG_TEMP_DIR" ] || mkdir -p "$ESLINT_CONFIG_TEMP_DIR" |& __devnull
+[ -d "$ESLINT_CONFIG_CACHE_DIR" ] || mkdir -p "$ESLINT_CONFIG_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ESLINT_CONFIG_TEMP_FILE="${ESLINT_CONFIG_TEMP_FILE:-$(mktemp $ESLINT_CONFIG_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$ESLINT_CONFIG_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$ESLINT_CONFIG_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$ESLINT_CONFIG_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$ESLINT_CONFIG_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$ESLINT_CONFIG_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$ESLINT_CONFIG_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ ESLINT_CONFIG_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ ESLINT_CONFIG_CWD="$2"
+ [ -d "$ESLINT_CONFIG_CWD" ] || mkdir -p "$ESLINT_CONFIG_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# ESLINT_CONFIG_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# ESLINT_CONFIG_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+[ -d "$1" ] && __is_an_option "$1" && ESLINT_CONFIG_CWD="$1" && shift 1 || ESLINT_CONFIG_CWD="${ESLINT_CONFIG_CWD:-$PWD}"
+ESLINT_CONFIG_CWD="$(realpath "${ESLINT_CONFIG_CWD:-$PWD}" 2>/dev/null)"
+if [ -d "$ESLINT_CONFIG_CWD" ] && cd "$ESLINT_CONFIG_CWD"; then
+ true
+# if [ "$ESLINT_CONFIG_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $ESLINT_CONFIG_CWD"
+# fi
+else
+ printf_exit "💔 $ESLINT_CONFIG_CWD does not exist 💔"
+fi
+export ESLINT_CONFIG_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__execute_eslint_config
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/ex b/bin/ex
new file mode 100755
index 000000000..04f59cbdc
--- /dev/null
+++ b/bin/ex
@@ -0,0 +1,675 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202303131032-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : ex --help
+# @@Copyright : Copyright: (c) 2023 Jason Hempstead, Casjays Developments
+# @@Created : Monday, Mar 13, 2023 10:32 EDT
+# @@File : ex
+# @@Description :
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202303131032-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+EX_REQUIRE_SUDO="${EX_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && EX_EXIT_STATUS=0 || EX_EXIT_STATUS=1
+ return ${EX_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && EX_EXIT_STATUS=0 || EX_EXIT_STATUS=1
+ return ${EX_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ EX_EXIT_STATUS=0
+ [ -n "$1" ] && local EX_EXIT_STATUS="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && EX_EXIT_STATUS+=$(($EX_EXIT_STATUS + 0)) || EX_EXIT_STATUS+=$(($EX_EXIT_STATUS + 1))
+ done
+ [ $EX_EXIT_STATUS -eq 0 ] || EX_EXIT_STATUS=3
+ return ${EX_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local EX_EXIT_STATUS=0
+ curl -q -LSsfI --max-time 1 --retry 0 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || EX_EXIT_STATUS=4
+ return ${EX_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$EX_CONFIG_DIR/$EX_CONFIG_FILE"
+ fi
+ [ -d "$EX_CONFIG_DIR" ] || mkdir -p "$EX_CONFIG_DIR"
+ [ -d "$EX_CONFIG_BACKUP_DIR" ] || mkdir -p "$EX_CONFIG_BACKUP_DIR"
+ [ -f "$EX_CONFIG_DIR/$EX_CONFIG_FILE" ] &&
+ cp -Rf "$EX_CONFIG_DIR/$EX_CONFIG_FILE" "$EX_CONFIG_BACKUP_DIR/$EX_CONFIG_FILE.$$"
+ cat <"$EX_CONFIG_DIR/$EX_CONFIG_FILE"
+# Settings for ex
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+EX_OUTPUT_COLOR_1="${EX_OUTPUT_COLOR_1:-}"
+EX_OUTPUT_COLOR_2="${EX_OUTPUT_COLOR_2:-}"
+EX_OUTPUT_COLOR_GOOD="${EX_OUTPUT_COLOR_GOOD:-}"
+EX_OUTPUT_COLOR_ERROR="${EX_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+EX_NOTIFY_ENABLED="${EX_NOTIFY_ENABLED:-}"
+EX_GOOD_NAME="${EX_GOOD_NAME:-}"
+EX_ERROR_NAME="${EX_ERROR_NAME:-}"
+EX_GOOD_MESSAGE="${EX_GOOD_MESSAGE:-}"
+EX_ERROR_MESSAGE="${EX_ERROR_MESSAGE:-}"
+EX_NOTIFY_CLIENT_NAME="${EX_NOTIFY_CLIENT_NAME:-}"
+EX_NOTIFY_CLIENT_ICON="${EX_NOTIFY_CLIENT_ICON:-}"
+EX_NOTIFY_CLIENT_URGENCY="${EX_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$EX_CONFIG_DIR/$EX_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$EX_CONFIG_DIR/$EX_CONFIG_FILE"
+ EX_EXIT_STATUS=0
+ else
+ printf_red "Failed to create the config file"
+ EX_EXIT_STATUS=1
+ fi
+ return ${EX_EXIT_STATUS:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "ex: - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: ex [options] [commands] [file]"
+ __printf_line "[file] - Specify the file to extract"
+ __printf_line "--dir - Sets the working directory"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__grep() { grep "$@" 2>/dev/null; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$EX_REQUIRE_SUDO" = "yes" ] && [ -z "$EX_REQUIRE_SUDO_RUN" ]; then
+ export EX_REQUIRE_SUDO="no"
+ export EX_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ EX_EXIT_STATUS=$?
+ else
+ printf '%s\n' "This requires root to run"
+ EX_EXIT_STATUS=1
+ fi
+ return ${EX_EXIT_STATUS:-0}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ EX_EXIT_STATUS=${EX_EXIT_STATUS:-0}
+ [ -f "$EX_TEMP_FILE" ] && rm -Rf "$EX_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $EX_EXIT_STATUS
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+EX_EXIT_STATUS=0
+EX_CONFIG_FILE="${EX_CONFIG_FILE:-settings.conf}"
+EX_CONFIG_DIR="${EX_CONFIG_DIR:-$HOME/.config/myscripts/ex}"
+EX_CONFIG_BACKUP_DIR="${EX_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/ex/backups}"
+EX_LOG_DIR="${EX_LOG_DIR:-$HOME/.local/log/ex}"
+EX_RUN_DIR="${EX_RUN_DIR:-$HOME/.local/run/system_scripts/$EX_SCRIPTS_PREFIX}"
+EX_TEMP_DIR="${EX_TEMP_DIR:-$HOME/.local/tmp/system_scripts/ex}"
+EX_CACHE_DIR="${EX_CACHE_DIR:-$HOME/.cache/ex}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+EX_OUTPUT_COLOR_1="${EX_OUTPUT_COLOR_1:-33}"
+EX_OUTPUT_COLOR_2="${EX_OUTPUT_COLOR_2:-5}"
+EX_OUTPUT_COLOR_GOOD="${EX_OUTPUT_COLOR_GOOD:-2}"
+EX_OUTPUT_COLOR_ERROR="${EX_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+EX_NOTIFY_ENABLED="${EX_NOTIFY_ENABLED:-yes}"
+EX_GOOD_NAME="${EX_GOOD_NAME:-Great:}"
+EX_ERROR_NAME="${EX_ERROR_NAME:-Error:}"
+EX_GOOD_MESSAGE="${EX_GOOD_MESSAGE:-No errors reported}"
+EX_ERROR_MESSAGE="${EX_ERROR_MESSAGE:-Errors were reported}"
+EX_NOTIFY_CLIENT_NAME="${EX_NOTIFY_CLIENT_NAME:-$APPNAME}"
+EX_NOTIFY_CLIENT_ICON="${EX_NOTIFY_CLIENT_ICON:-notification-new}"
+EX_NOTIFY_CLIENT_URGENCY="${EX_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$EX_CONFIG_DIR/$EX_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$EX_CONFIG_DIR/$EX_CONFIG_FILE" ] && . "$EX_CONFIG_DIR/$EX_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$EX_RUN_DIR" ] || mkdir -p "$EX_RUN_DIR" |& __devnull
+[ -d "$EX_LOG_DIR" ] || mkdir -p "$EX_LOG_DIR" |& __devnull
+[ -d "$EX_TEMP_DIR" ] || mkdir -p "$EX_TEMP_DIR" |& __devnull
+[ -d "$EX_CACHE_DIR" ] || mkdir -p "$EX_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+EX_TEMP_FILE="${EX_TEMP_FILE:-$(mktemp $EX_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$EX_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$EX_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$EX_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$EX_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$EX_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$EX_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS="f"
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=",file:"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ EX_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ EX_CWD="$2"
+ [ -d "$EX_CWD" ] || mkdir -p "$EX_CWD" |& __devnull
+ builtin cd "$EX_CWD" || printf_exit "CD into $EX_CWD failed"
+ shift 2
+ ;;
+ -f | --file)
+ EX_FILE_LOCATION="$2"
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# EX_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# EX_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && EX_CWD="$1" && shift 1 || EX_CWD="${EX_CWD:-$PWD}"
+EX_CWD="$(realpath "${EX_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$EX_CWD" ] && cd "$EX_CWD"; then
+# if [ "$EX_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $EX_CWD"
+# fi
+# else
+# printf_exit "💔 $EX_CWD does not exist 💔"
+# fi
+export EX_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+EX_FILE_LOCATION="$(realpath "${EX_FILE_LOCATION:-${1:-$PWD}}")"
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+if [ ! -f "$EX_FILE_LOCATION" ]; then
+ printf_red "$EX_FILE_LOCATION is not a valid file"
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Export variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+case "$EX_FILE_LOCATION" in
+*.tar.bz2)
+ __cmd_exists tar || printf_exit "Please install tar"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using tar"
+ if tar xjf "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.tar.gz)
+ __cmd_exists tar || printf_exit "Please install tar"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using tar"
+ if tar xzf "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.bz2)
+ __cmd_exists bunzip2 || printf_exit "Please install bunzip2"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using bunzip2"
+ if bunzip2 "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.rar)
+ __cmd_exists unrar || printf_exit "Please install unrar"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using unrar"
+ if unrar x "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.gz)
+ __cmd_exists gunzip || printf_exit "Please install gunzip"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using gunzip"
+ if gunzip "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.tar)
+ __cmd_exists tar || printf_exit "Please install tar"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using tar"
+ if tar xf "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.tbz2)
+ __cmd_exists tar || printf_exit "Please install tar"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using tar"
+ if tar xjf "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.tgz)
+ __cmd_exists tar || printf_exit "Please install tar"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using tar"
+ if tar xzf "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.zip)
+ __cmd_exists unzip || printf_exit "Please install unzip"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using unzip"
+ if unzip "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.Z)
+ __cmd_exists uncompress || printf_exit "Please install uncompress"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using uncompress"
+ if uncompress "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.7z)
+ __cmd_exists 7z || printf_exit "Please install 7z"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using 7z"
+ if 7z x "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.xz)
+ __cmd_exists unxz || printf_exit "Please install unxz"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using unxz"
+ if unxz "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*.iso)
+ __cmd_exists 7z || printf_exit "Please install 7z"
+ printf_blue "Attempting to extract $EX_FILE_LOCATION using 7z"
+ if 7z x -y -bb0 -bd -o"$PWD" "$EX_FILE_LOCATION" &>/dev/null; then
+ exitCode=0
+ else
+ exitCode=1
+ fi
+ ;;
+
+*)
+ printf_red "$EX_FILE_LOCATION cannot be extracted "
+ exitCode=1
+ ;;
+esac
+if [ "$exitCode" = 0 ]; then
+ printf_green "File has been extracted"
+else
+ printf_red "Failed to extract file"
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+EX_EXIT_STATUS="${exitCode:-$EX_EXIT_STATUS}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${EX_EXIT_STATUS:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/expandurl b/bin/expandurl
new file mode 100755
index 000000000..71b00a2a6
--- /dev/null
+++ b/bin/expandurl
@@ -0,0 +1,529 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208062301-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : expandurl --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Saturday, Aug 06, 2022 23:01 EDT
+# @@File : expandurl
+# @@Description : Get full url from a shortner and copy to clipboard
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208062301-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+EXPANDURL_REQUIRE_SUDO="${EXPANDURL_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$EXPANDURL_CONFIG_DIR/$EXPANDURL_CONFIG_FILE"
+ fi
+ [ -d "$EXPANDURL_CONFIG_DIR" ] || mkdir -p "$EXPANDURL_CONFIG_DIR"
+ [ -d "$EXPANDURL_CONFIG_BACKUP_DIR" ] || mkdir -p "$EXPANDURL_CONFIG_BACKUP_DIR"
+ [ -f "$EXPANDURL_CONFIG_DIR/$EXPANDURL_CONFIG_FILE" ] &&
+ cp -Rf "$EXPANDURL_CONFIG_DIR/$EXPANDURL_CONFIG_FILE" "$EXPANDURL_CONFIG_BACKUP_DIR/$EXPANDURL_CONFIG_FILE.$$"
+ cat <"$EXPANDURL_CONFIG_DIR/$EXPANDURL_CONFIG_FILE"
+# Settings for expandurl
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+EXPANDURL_OUTPUT_COLOR_1="${EXPANDURL_OUTPUT_COLOR_1:-}"
+EXPANDURL_OUTPUT_COLOR_2="${EXPANDURL_OUTPUT_COLOR_2:-}"
+EXPANDURL_OUTPUT_COLOR_GOOD="${EXPANDURL_OUTPUT_COLOR_GOOD:-}"
+EXPANDURL_OUTPUT_COLOR_ERROR="${EXPANDURL_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+EXPANDURL_NOTIFY_ENABLED="${EXPANDURL_NOTIFY_ENABLED:-}"
+EXPANDURL_GOOD_NAME="${EXPANDURL_GOOD_NAME:-}"
+EXPANDURL_ERROR_NAME="${EXPANDURL_ERROR_NAME:-}"
+EXPANDURL_GOOD_MESSAGE="${EXPANDURL_GOOD_MESSAGE:-}"
+EXPANDURL_ERROR_MESSAGE="${EXPANDURL_ERROR_MESSAGE:-}"
+EXPANDURL_NOTIFY_CLIENT_NAME="${EXPANDURL_NOTIFY_CLIENT_NAME:-}"
+EXPANDURL_NOTIFY_CLIENT_ICON="${EXPANDURL_NOTIFY_CLIENT_ICON:-}"
+EXPANDURL_NOTIFY_CLIENT_URGENCY="${EXPANDURL_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$EXPANDURL_CONFIG_DIR/$EXPANDURL_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$EXPANDURL_CONFIG_DIR/$EXPANDURL_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "expandurl: Get full url from a shortner and copy to clipboard - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: expandurl [options] [commands]"
+ __printf_line "[url] - Get the full url from a short one"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$EXPANDURL_REQUIRE_SUDO" = "yes" ] && [ -z "$EXPANDURL_REQUIRE_SUDO_RUN" ]; then
+ export EXPANDURL_REQUIRE_SUDO="no"
+ export EXPANDURL_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$EXPANDURL_TEMP_FILE" ] && rm -Rf "$EXPANDURL_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__execute_expandurl() {
+ local URL="$1"
+ GET_URL="$(curl -q -ILSsif "$URL" 2>/dev/null | grep -v "$URL" | grep -i ^Location | awk '{print $2}' | grep '^')"
+ [ -n "$URL" ] || printf_exit "Nothing to expand"
+ if [ -z "$GET_URL" ]; then
+ __notifications "$APPNAME" "Your search for $URL returned no results"
+ exitCode=1
+ else
+ __notifications "$APPNAME" "Found the following url[s]:\n$GET_URL\n"
+ echo "$GET_URL" | clipboard --silent
+ exitCode=0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined variables/import external variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Application Folders
+EXPANDURL_CONFIG_FILE="${EXPANDURL_CONFIG_FILE:-settings.conf}"
+EXPANDURL_CONFIG_DIR="${EXPANDURL_CONFIG_DIR:-$HOME/.config/myscripts/expandurl}"
+EXPANDURL_CONFIG_BACKUP_DIR="${EXPANDURL_CONFIG_BACKUP_DIR:-$HOME/.local/share/myscripts/expandurl/backups}"
+EXPANDURL_LOG_DIR="${EXPANDURL_LOG_DIR:-$HOME/.local/log/expandurl}"
+EXPANDURL_TEMP_DIR="${EXPANDURL_TEMP_DIR:-$HOME/.local/tmp/system_scripts/expandurl}"
+EXPANDURL_CACHE_DIR="${EXPANDURL_CACHE_DIR:-$HOME/.cache/expandurl}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+EXPANDURL_OUTPUT_COLOR_1="${EXPANDURL_OUTPUT_COLOR_1:-33}"
+EXPANDURL_OUTPUT_COLOR_2="${EXPANDURL_OUTPUT_COLOR_2:-5}"
+EXPANDURL_OUTPUT_COLOR_GOOD="${EXPANDURL_OUTPUT_COLOR_GOOD:-2}"
+EXPANDURL_OUTPUT_COLOR_ERROR="${EXPANDURL_OUTPUT_COLOR_ERROR:-1}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+EXPANDURL_NOTIFY_ENABLED="${EXPANDURL_NOTIFY_ENABLED:-yes}"
+EXPANDURL_GOOD_NAME="${EXPANDURL_GOOD_NAME:-Great:}"
+EXPANDURL_ERROR_NAME="${EXPANDURL_ERROR_NAME:-Error:}"
+EXPANDURL_GOOD_MESSAGE="${EXPANDURL_GOOD_MESSAGE:-No errors reported}"
+EXPANDURL_ERROR_MESSAGE="${EXPANDURL_ERROR_MESSAGE:-Errors were reported}"
+EXPANDURL_NOTIFY_CLIENT_NAME="${EXPANDURL_NOTIFY_CLIENT_NAME:-$APPNAME}"
+EXPANDURL_NOTIFY_CLIENT_ICON="${EXPANDURL_NOTIFY_CLIENT_ICON:-notification-new}"
+EXPANDURL_NOTIFY_CLIENT_URGENCY="${EXPANDURL_NOTIFY_CLIENT_URGENCY:-normal}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional Variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Generate config files
+[ -f "$EXPANDURL_CONFIG_DIR/$EXPANDURL_CONFIG_FILE" ] || [ "$*" = "--config" ] || INIT_CONFIG="${INIT_CONFIG:-TRUE}" __gen_config ${SETARGS:-$@}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import config
+[ -f "$EXPANDURL_CONFIG_DIR/$EXPANDURL_CONFIG_FILE" ] && . "$EXPANDURL_CONFIG_DIR/$EXPANDURL_CONFIG_FILE"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Ensure Directories exist
+[ -d "$EXPANDURL_LOG_DIR" ] || mkdir -p "$EXPANDURL_LOG_DIR" |& __devnull
+[ -d "$EXPANDURL_TEMP_DIR" ] || mkdir -p "$EXPANDURL_TEMP_DIR" |& __devnull
+[ -d "$EXPANDURL_CACHE_DIR" ] || mkdir -p "$EXPANDURL_CACHE_DIR" |& __devnull
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+EXPANDURL_TEMP_FILE="${EXPANDURL_TEMP_FILE:-$(mktemp $EXPANDURL_TEMP_DIR/XXXXXX 2>/dev/null)}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup trap to remove temp file
+trap '__trap_exit' EXIT
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup notification function
+__notifications() {
+ __cmd_exists notifications || return
+ [ "$EXPANDURL_NOTIFY_ENABLED" = "yes" ] || return
+ [ "$SEND_NOTIFICATION" = "no" ] && return
+ (
+ export SCRIPT_OPTS="" _DEBUG=""
+ export NOTIFY_GOOD_MESSAGE="${NOTIFY_GOOD_MESSAGE:-$EXPANDURL_GOOD_MESSAGE}"
+ export NOTIFY_ERROR_MESSAGE="${NOTIFY_ERROR_MESSAGE:-$EXPANDURL_ERROR_MESSAGE}"
+ export NOTIFY_CLIENT_ICON="${NOTIFY_CLIENT_ICON:-$EXPANDURL_NOTIFY_CLIENT_ICON}"
+ export NOTIFY_CLIENT_NAME="${NOTIFY_CLIENT_NAME:-$EXPANDURL_NOTIFY_CLIENT_NAME}"
+ export NOTIFY_CLIENT_URGENCY="${NOTIFY_CLIENT_URGENCY:-$EXPANDURL_NOTIFY_CLIENT_URGENCY}"
+ notifications "$@"
+ ) |& __devnull &
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set custom actions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Argument/Option settings
+SETARGS=("$@")
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+SHORTOPTS=""
+SHORTOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LONGOPTS="completions:,config,debug,dir:,help,options,raw,version,silent"
+LONGOPTS+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ARRAY=""
+ARRAY+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+LIST=""
+LIST+=""
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Setup application options
+setopts=$(getopt -o "$SHORTOPTS" --long "$LONGOPTS" -n "$APPNAME" -- "$@" 2>/dev/null)
+eval set -- "${setopts[@]}" 2>/dev/null
+while :; do
+ case "$1" in
+ --raw)
+ shift 1
+ export SHOW_RAW="true"
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+ ;;
+ --debug)
+ shift 1
+ set -xo pipefail
+ export SCRIPT_OPTS="--debug"
+ export _DEBUG="on"
+ __devnull() { tee || return 1; }
+ __devnull2() { eval "$@" |& tee -p || return 1; }
+ ;;
+ --completions)
+ if [ "$2" = "short" ]; then
+ printf '%s\n' "-$SHORTOPTS" | sed 's|"||g;s|:||g;s|,|,-|g' | tr ',' '\n'
+ elif [ "$2" = "long" ]; then
+ printf '%s\n' "--$LONGOPTS" | sed 's|"||g;s|:||g;s|,|,--|g' | tr ',' '\n'
+ elif [ "$2" = "array" ]; then
+ printf '%s\n' "$ARRAY" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ elif [ "$2" = "list" ]; then
+ printf '%s\n' "$LIST" | sed 's|"||g;s|:||g' | tr ',' '\n'
+ else
+ exit 1
+ fi
+ shift 2
+ exit $?
+ ;;
+ --options)
+ shift 1
+ printf_blue "Current options for ${PROG:-$APPNAME}"
+ [ -z "$SHORTOPTS" ] || __list_options "Short Options" "-${SHORTOPTS}" ',' '-' 4
+ [ -z "$LONGOPTS" ] || __list_options "Long Options" "--${LONGOPTS}" ',' '--' 4
+ [ -z "$ARRAY" ] || __list_options "Base Options" "${ARRAY}" ',' '' 4
+ [ -z "$LIST" ] || __list_options "LIST Options" "${LIST}" ',' '' 4
+ exit $?
+ ;;
+ --version)
+ shift 1
+ __version
+ exit $?
+ ;;
+ --help)
+ shift 1
+ __help
+ exit $?
+ ;;
+ --config)
+ shift 1
+ __gen_config
+ exit $?
+ ;;
+ --silent)
+ shift 1
+ EXPANDURL_SILENT="true"
+ ;;
+ --dir)
+ CWD_IS_SET="TRUE"
+ EXPANDURL_CWD="$2"
+ [ -d "$EXPANDURL_CWD" ] || mkdir -p "$EXPANDURL_CWD" |& __devnull
+ shift 2
+ ;;
+ --)
+ shift 1
+ break
+ ;;
+ esac
+done
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get directory from args
+# set -- "$@"
+# for arg in "$@"; do
+# if [ -d "$arg" ]; then
+# EXPANDURL_CWD="$arg" && shift 1 && SET_NEW_ARGS=("$@") && break
+# elif [ -f "$arg" ]; then
+# EXPANDURL_CWD="$(dirname "$arg" 2>/dev/null)" && shift 1 && SET_NEW_ARGS=("$@") && break
+# else
+# SET_NEW_ARGS+=("$arg")
+# fi
+# done
+# set -- "${SET_NEW_ARGS[@]}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set directory to first argument
+# [ -d "$1" ] && __is_an_option "$1" && EXPANDURL_CWD="$1" && shift 1 || EXPANDURL_CWD="${EXPANDURL_CWD:-$PWD}"
+EXPANDURL_CWD="$(realpath "${EXPANDURL_CWD:-$PWD}" 2>/dev/null)"
+# if [ -d "$EXPANDURL_CWD" ] && cd "$EXPANDURL_CWD"; then
+# if [ "$EXPANDURL_SILENT" != "true" ] && [ "$CWD_SILENCE" != "true" ]; then
+# printf_cyan "Setting working dir to $EXPANDURL_CWD"
+# fi
+# else
+# printf_exit "💔 $EXPANDURL_CWD does not exist 💔"
+# fi
+export EXPANDURL_CWD
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set actions based on variables
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for required applications/Network check
+#requiresudo "$0" "$@" || exit 2 # exit 2 if errors
+#cmd_exists --error --ask bash || exit 3 # exit 3 if not found
+#am_i_online --error || exit 4 # exit 4 if no internet
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# APP Variables overrides
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Actions based on env
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute functions
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute commands
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin main app
+__execute_expandurl "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set exit code
+exitCode="${exitCode:-0}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# End application
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# lets exit with code
+exit ${exitCode:-0}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# ex: ts=2 sw=2 et filetype=sh
diff --git a/bin/explainshell b/bin/explainshell
new file mode 100755
index 000000000..616d16b41
--- /dev/null
+++ b/bin/explainshell
@@ -0,0 +1,586 @@
+#!/usr/bin/env bash
+# shellcheck shell=bash
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+##@Version : 202208062305-git
+# @@Author : Jason Hempstead
+# @@Contact : jason@casjaysdev.pro
+# @@License : WTFPL
+# @@ReadME : explainshell --help
+# @@Copyright : Copyright: (c) 2022 Jason Hempstead, Casjays Developments
+# @@Created : Saturday, Aug 06, 2022 23:05 EDT
+# @@File : explainshell
+# @@Description : search explainshell.com for commands
+# @@Changelog : New script
+# @@TODO : Better documentation
+# @@Other :
+# @@Resource :
+# @@Terminal App : no
+# @@sudo/root : no
+# @@Template : bash/system
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# shellcheck disable=SC1003,SC2016,SC2031,SC2120,SC2155,SC2199,SC2317
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+APPNAME="$(basename -- "$0" 2>/dev/null)"
+VERSION="202208062305-git"
+USER="${SUDO_USER:-$USER}"
+RUN_USER="${RUN_USER:-$USER}"
+USER_HOME="${USER_HOME:-$HOME}"
+SCRIPT_SRC_DIR="${BASH_SOURCE%/*}"
+EXPLAINSHELL_REQUIRE_SUDO="${EXPLAINSHELL_REQUIRE_SUDO:-no}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Reopen in a terminal
+#if [ ! -t 0 ] && { [ "$1" = --term ] || [ $# = 0 ]; }; then { [ "$1" = --term ] && shift 1 || true; } && TERMINAL_APP="TRUE" myterminal -e "$APPNAME $*" && exit || exit 1; fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Set script title
+#CASJAYS_DEV_TILE_FORMAT="${USER}@${HOSTNAME}:${PWD//$HOME/\~} - $APPNAME"
+#CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}"
+#[ -z "$CASJAYSDEV_TITLE_SET" ] && printf '\033]2│;%s\033\\' "$CASJAYS_DEV_TILE_FORMAT" && CASJAYSDEV_TITLE_SET="$APPNAME"
+export CASJAYSDEV_TITLE_PREV="${CASJAYSDEV_TITLE_PREV:-${CASJAYSDEV_TITLE_SET:-$APPNAME}}" CASJAYSDEV_TITLE_SET
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Initial debugging
+[ "$1" = "--debug" ] && set -x && export SCRIPT_OPTS="--debug" && export _DEBUG="on"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Disables colorization
+[ "$1" = "--raw" ] && export SHOW_RAW="true"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# pipes fail
+set -o pipefail
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Import functions
+CASJAYSDEVDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}"
+SCRIPTSFUNCTDIR="${CASJAYSDEVDIR:-/usr/local/share/CasjaysDev/scripts}/functions"
+SCRIPTSFUNCTFILE="${SCRIPTSAPPFUNCTFILE:-testing.bash}"
+SCRIPTSFUNCTURL="${SCRIPTSAPPFUNCTURL:-https://github.com/dfmgr/installer/raw/main/functions}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if [ -f "$PWD/$SCRIPTSFUNCTFILE" ]; then
+ . "$PWD/$SCRIPTSFUNCTFILE"
+elif [ -f "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" ]; then
+ . "$SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE"
+else
+ echo "Can not load the functions file: $SCRIPTSFUNCTDIR/$SCRIPTSFUNCTFILE" 1>&2
+ exit 1
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Options are: *_install
+# system user desktopmgr devenvmgr dfmgr dockermgr fontmgr iconmgr pkmgr systemmgr thememgr wallpapermgr
+user_install && __options "$@"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Send all output to /dev/null
+__devnull() {
+ tee &>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# Send errors to /dev/null
+__devnull2() {
+ [ -n "$1" ] && local cmd="$1" && shift 1 || return 1
+ eval $cmd "$*" 2>/dev/null && exitCode=0 || exitCode=1
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'
+# See if the executable exists
+__cmd_exists() {
+ exitCode=0
+ [ -n "$1" ] && local exitCode="" || return 0
+ for cmd in "$@"; do
+ builtin command -v "$cmd" &>/dev/null && exitCode+=$(($exitCode + 0)) || exitCode+=$(($exitCode + 1))
+ done
+ [ $exitCode -eq 0 ] || exitCode=3
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check for a valid internet connection
+__am_i_online() {
+ local exitCode=0
+ curl -q -LSsfI --max-time 2 --retry 1 "${1:-https://1.1.1.1}" 2>&1 | grep -qi 'server:.*cloudflare' || exitCode=4
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# colorization
+if [ "$SHOW_RAW" = "true" ]; then
+ NC=""
+ RESET=""
+ BLACK=""
+ RED=""
+ GREEN=""
+ YELLOW=""
+ BLUE=""
+ PURPLE=""
+ CYAN=""
+ WHITE=""
+ ORANGE=""
+ LIGHTRED=""
+ BG_GREEN=""
+ BG_RED=""
+ ICON_INFO="[ info ]"
+ ICON_GOOD="[ ok ]"
+ ICON_WARN="[ warn ]"
+ ICON_ERROR="[ error ]"
+ ICON_QUESTION="[ ? ]"
+ printf_column() { tee | grep '^'; }
+ printf_color() { printf '%b' "$1" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
+else
+ printf_color() { printf "%b" "$(tput setaf "${2:-7}" 2>/dev/null)" "$1" "$(tput sgr0 2>/dev/null)"; }
+fi
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Additional printf_ colors
+__printf_head() { printf_blue "$1"; }
+__printf_opts() { printf_purple "$1"; }
+__printf_line() { printf_cyan "$1"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# output version
+__version() { printf_cyan "$VERSION"; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# list options
+__list_options() {
+ printf_color "$1: " "$5"
+ echo -ne "$2" | sed 's|:||g;s/'$3'/ '$4'/g' | tr '\n' ' '
+ printf_newline
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# create the config file
+__gen_config() {
+ local NOTIFY_CLIENT_NAME="$APPNAME"
+ if [ "$INIT_CONFIG" != "TRUE" ]; then
+ printf_blue "Generating the config file in"
+ printf_cyan "$EXPLAINSHELL_CONFIG_DIR/$EXPLAINSHELL_CONFIG_FILE"
+ fi
+ [ -d "$EXPLAINSHELL_CONFIG_DIR" ] || mkdir -p "$EXPLAINSHELL_CONFIG_DIR"
+ [ -d "$EXPLAINSHELL_CONFIG_BACKUP_DIR" ] || mkdir -p "$EXPLAINSHELL_CONFIG_BACKUP_DIR"
+ [ -f "$EXPLAINSHELL_CONFIG_DIR/$EXPLAINSHELL_CONFIG_FILE" ] &&
+ cp -Rf "$EXPLAINSHELL_CONFIG_DIR/$EXPLAINSHELL_CONFIG_FILE" "$EXPLAINSHELL_CONFIG_BACKUP_DIR/$EXPLAINSHELL_CONFIG_FILE.$$"
+ cat <"$EXPLAINSHELL_CONFIG_DIR/$EXPLAINSHELL_CONFIG_FILE"
+# Settings for explainshell
+EXPLAINSHELL_API="${EXPLAINSHELL_API:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Color Settings
+EXPLAINSHELL_OUTPUT_COLOR_1="${EXPLAINSHELL_OUTPUT_COLOR_1:-}"
+EXPLAINSHELL_OUTPUT_COLOR_2="${EXPLAINSHELL_OUTPUT_COLOR_2:-}"
+EXPLAINSHELL_OUTPUT_COLOR_GOOD="${EXPLAINSHELL_OUTPUT_COLOR_GOOD:-}"
+EXPLAINSHELL_OUTPUT_COLOR_ERROR="${EXPLAINSHELL_OUTPUT_COLOR_ERROR:-}"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Notification Settings
+EXPLAINSHELL_NOTIFY_ENABLED="${EXPLAINSHELL_NOTIFY_ENABLED:-}"
+EXPLAINSHELL_GOOD_NAME="${EXPLAINSHELL_GOOD_NAME:-}"
+EXPLAINSHELL_ERROR_NAME="${EXPLAINSHELL_ERROR_NAME:-}"
+EXPLAINSHELL_GOOD_MESSAGE="${EXPLAINSHELL_GOOD_MESSAGE:-}"
+EXPLAINSHELL_ERROR_MESSAGE="${EXPLAINSHELL_ERROR_MESSAGE:-}"
+EXPLAINSHELL_NOTIFY_CLIENT_NAME="${EXPLAINSHELL_NOTIFY_CLIENT_NAME:-}"
+EXPLAINSHELL_NOTIFY_CLIENT_ICON="${EXPLAINSHELL_NOTIFY_CLIENT_ICON:-}"
+EXPLAINSHELL_NOTIFY_CLIENT_URGENCY="${EXPLAINSHELL_NOTIFY_CLIENT_URGENCY:-}"
+
+EOF
+ if builtin type -t __gen_config_local | grep -q 'function'; then __gen_config_local; fi
+ if [ -f "$EXPLAINSHELL_CONFIG_DIR/$EXPLAINSHELL_CONFIG_FILE" ]; then
+ [ "$INIT_CONFIG" = "TRUE" ] || printf_green "Your config file for $APPNAME has been created"
+ . "$EXPLAINSHELL_CONFIG_DIR/$EXPLAINSHELL_CONFIG_FILE"
+ exitCode=0
+ else
+ printf_red "Failed to create the config file"
+ exitCode=1
+ fi
+ return ${exitCode:-0}
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Help function - Align to 50
+__help() {
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "explainshell: search explainshell.com for commands - $VERSION"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "Usage: explainshell [options] -- [command] [arguments]"
+ __printf_line "--[options] -- curl -o - Search for curl with option -o"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_opts "Other Options"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ __printf_line "--help - Shows this message"
+ __printf_line "--config - Generate user config file"
+ __printf_line "--version - Show script version"
+ __printf_line "--options - Shows all available options"
+ __printf_line "--debug - Enables script debugging"
+ __printf_line "--raw - Removes all formatting on output"
+ __printf_head "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# check if arg is a builtin option
+__is_an_option() { if echo "$ARRAY" | grep -q "${1:-^}"; then return 1; else return 0; fi; }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user root
+__user_is_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Is current user not root
+__user_is_not_root() {
+ { [ $(id -u) -eq 0 ] || [ $EUID -eq 0 ] || [ "$WHOAMI" = "root" ]; } && return 1 || return 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Check if user is a member of sudo
+__sudo_group() {
+ grep -sh "${1:-$USER}" "/etc/group" | grep -Eq 'wheel|adm|sudo' || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# # Get sudo password
+__sudoask() {
+ ask_for_password sudo true && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run sudo
+__sudorun() {
+ __sudoif && __cmd_exists sudo && sudo -HE "$@" || { __sudoif && eval "$@"; }
+ return $?
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Test if user has access to sudo
+__can_i_sudo() {
+ (sudo -vn && sudo -ln) 2>&1 | grep -vq 'may not' >/dev/null && return 0
+ __sudo_group "${1:-$USER}" || __sudoif || __sudo true &>/dev/null || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User can run sudo
+__sudoif() {
+ __user_is_root && return 0
+ __can_i_sudo "${RUN_USER:-$USER}" && return 0
+ __user_is_not_root && __sudoask && return 0 || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Run command as root
+requiresudo() {
+ if [ "$EXPLAINSHELL_REQUIRE_SUDO" = "yes" ] && [ -z "$EXPLAINSHELL_REQUIRE_SUDO_RUN" ]; then
+ export EXPLAINSHELL_REQUIRE_SUDO="no"
+ export EXPLAINSHELL_REQUIRE_SUDO_RUN="true"
+ __sudo "$@"
+ exit $?
+ else
+ return 0
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Execute sudo
+__sudo() {
+ CMD="${1:-echo}" && shift 1
+ CMD_ARGS="${*:--e "${RUN_USER:-$USER}"}"
+ SUDO="$(builtin command -v sudo 2>/dev/null || echo 'eval')"
+ [ "$(basename -- "$SUDO" 2>/dev/null)" = "sudo" ] && OPTS="--preserve-env=PATH -HE"
+ if __sudoif; then
+ export PATH="$PATH"
+ $SUDO ${OPTS:-} $CMD $CMD_ARGS && true || false
+ exitCode=$?
+ else
+ printf '%s\n' "This requires root to run"
+ exitCode=1
+ fi
+ return ${exitCode:-1}
+}
+# End of sudo functions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__trap_exit() {
+ exitCode=${exitCode:-0}
+ [ -f "$EXPLAINSHELL_TEMP_FILE" ] && rm -Rf "$EXPLAINSHELL_TEMP_FILE" &>/dev/null
+ #unset CASJAYSDEV_TITLE_SET && printf '\033]2│;%s\033\\' "${USER}@${HOSTNAME}:${PWD//$HOME/\~} - ${CASJAYSDEV_TITLE_PREV:-$SHELL}"
+ if builtin type -t __trap_exit_local | grep -q 'function'; then __trap_exit_local; fi
+ return $exitCode
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# User defined functions
+__encode_url() {
+ [ -n "$1" ] || [ -n "$SEARCH" ] || return 1
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/%/%25/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/ /%20/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/!/%21/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/"/%22/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/#/%23/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/\$/%24/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/\&/%26/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/'\''/%27/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/'\('/%28/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/'\)'/%29/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/\*/%2a/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/+/%2b/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/,/%2c/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/-/%2d/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/\./%2e/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/\//%2f/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/:/%3a/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/;/%3b/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/>/%3e/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/?/%3f/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/@/%40/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/\[/%5b/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/\\/%5c/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/\]/%5d/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/\^/%5e/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/_/%5f/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/`/%60/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/{/%7b/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/|/%7c/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/}/%7d/g')
+ CMD=$(echo "${1:-$SEARCH}" | sed -e 's/~/%7e/g')
+ [ -n "$CMD" ] && echo "$CMD" || return 1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+__explain() {
+ local HEAD="" URL=""
+ URL="${1:?printf_exit "Please provide a valid URL"}"
+ HEAD="$(curl -q -ILSsi "$URL" | grep '200 OK' | grep '^.' || false)"
+ if [ -z "$HEAD" ]; then
+ return 1
+ else
+ curl -q -LSsf "$URL" 2>/dev/null |
+ sed -e '/
+
+
+
+
+
+
+
+${GEN_LINKS_TITLE:-List of links from $from}
+$GEN_LINKS_HEADER
+
+
+
+
+
+
+
List of links from $from
+
+
+
+$([ -f "$GEN_LINKS_TEMP_FILE" ] && cat "$GEN_LINKS_TEMP_FILE" | sed '/^$/N;/^\n$/D' | __sed_separator)
+
+
+
+
+
+
+$GEN_LINKS_FOOTER
+
+
+
+
+
+
+