mirror of
				https://tildegit.org/ben/dotfiles.git
				synced 2025-08-10 05:02:03 +00:00 
			
		
		
		
	fish v4 and some weechat stuff
This commit is contained in:
		
							parent
							
								
									734e67fb1f
								
							
						
					
					
						commit
						bfd96e2285
					
				| @ -1,4 +1,7 @@ | |||||||
| #!/bin/sh | #!/bin/sh | ||||||
|  | set -e | ||||||
|  | set -u | ||||||
|  | 
 | ||||||
| matchplayApiKey=$(cat ~/Sync/Notes/keys/matchplayapikey.txt) | matchplayApiKey=$(cat ~/Sync/Notes/keys/matchplayapikey.txt) | ||||||
| ifpaApiKey=$(cat ~/Sync/Notes/keys/ifpa-api-key.txt) | ifpaApiKey=$(cat ~/Sync/Notes/keys/ifpa-api-key.txt) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -76,4 +76,4 @@ | |||||||
| # Set this to zero to hide seconds int the time display | # Set this to zero to hide seconds int the time display | ||||||
| # Default 1 | # Default 1 | ||||||
| #TIME_SECONDS=0 | #TIME_SECONDS=0 | ||||||
| BYOBU_CHARMAP=x | BYOBU_CHARMAP=UTF-8 | ||||||
|  | |||||||
							
								
								
									
										185
									
								
								fish/.config/fish/completions/bun.fish
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								fish/.config/fish/completions/bun.fish
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,185 @@ | |||||||
|  | # This is terribly complicated | ||||||
|  | # It's because: | ||||||
|  | # 1. bun run has to have dynamic completions | ||||||
|  | # 2. there are global options | ||||||
|  | # 3. bun {install add remove} gets special options | ||||||
|  | # 4. I don't know how to write fish completions well | ||||||
|  | # Contributions very welcome!! | ||||||
|  | 
 | ||||||
|  | function __fish__get_bun_bins | ||||||
|  | 	string split ' ' (bun getcompletes b) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function __fish__get_bun_scripts | ||||||
|  | 	set -lx SHELL bash | ||||||
|  | 	set -lx MAX_DESCRIPTION_LEN 40 | ||||||
|  | 	string trim (string split '\n' (string split '\t' (bun getcompletes z))) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function __fish__get_bun_packages | ||||||
|  | 	if test (commandline -ct) != "" | ||||||
|  | 		set -lx SHELL fish | ||||||
|  | 		string split ' ' (bun getcompletes a (commandline -ct)) | ||||||
|  | 	end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function __history_completions | ||||||
|  | 	set -l tokens (commandline --current-process --tokenize) | ||||||
|  | 	history --prefix (commandline) | string replace -r \^$tokens[1]\\s\* "" | string replace -r \^$tokens[2]\\s\* "" | string split ' ' | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function __fish__get_bun_bun_js_files | ||||||
|  | 	string split ' ' (bun getcompletes j) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | set -l bun_install_boolean_flags yarn production optional development no-save dry-run force no-cache silent verbose global | ||||||
|  | set -l bun_install_boolean_flags_descriptions "Write a yarn.lock file (yarn v1)" "Don't install devDependencies" "Add dependency to optionalDependencies" "Add dependency to devDependencies" "Don't install devDependencies" "Don't install anything" "Always request the latest versions from the registry & reinstall all dependencies" "Ignore manifest cache entirely" "Don't output anything" "Excessively verbose logging" "Use global folder" | ||||||
|  | 
 | ||||||
|  | set -l bun_builtin_cmds_without_run dev create help bun upgrade discord install remove add init pm x | ||||||
|  | set -l bun_builtin_cmds_accepting_flags create help bun upgrade discord run init link unlink pm x | ||||||
|  | 
 | ||||||
|  | function __bun_complete_bins_scripts --inherit-variable bun_builtin_cmds_without_run -d "Emit bun completions for bins and scripts" | ||||||
|  |     # Do nothing if we already have a builtin subcommand, | ||||||
|  |     # or any subcommand other than "run". | ||||||
|  |     if __fish_seen_subcommand_from $bun_builtin_cmds_without_run | ||||||
|  |     or not __fish_use_subcommand && not __fish_seen_subcommand_from run | ||||||
|  |         return | ||||||
|  |     end | ||||||
|  |     # Do we already have a bin or script subcommand? | ||||||
|  |     set -l bins (__fish__get_bun_bins) | ||||||
|  |     if __fish_seen_subcommand_from $bins | ||||||
|  |         return | ||||||
|  |     end | ||||||
|  |     # Scripts have descriptions appended with a tab separator. | ||||||
|  |     # Strip off descriptions for the purposes of subcommand testing. | ||||||
|  |     set -l scripts (__fish__get_bun_scripts) | ||||||
|  |     if __fish_seen_subcommand_from (string split \t -f 1 -- $scripts) | ||||||
|  |         return | ||||||
|  |     end | ||||||
|  |     # Emit scripts. | ||||||
|  |     for script in $scripts | ||||||
|  |         echo $script | ||||||
|  |     end | ||||||
|  |     # Emit binaries and JS files (but only if we're doing `bun run`). | ||||||
|  |     if __fish_seen_subcommand_from run | ||||||
|  |         for bin in $bins | ||||||
|  |             echo "$bin"\t"package bin" | ||||||
|  |         end | ||||||
|  |         for file in (__fish__get_bun_bun_js_files) | ||||||
|  |             echo "$file"\t"Bun.js" | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Clear existing completions | ||||||
|  | complete -e -c bun | ||||||
|  | 
 | ||||||
|  | # Dynamically emit scripts and binaries | ||||||
|  | complete -c bun -f -a "(__bun_complete_bins_scripts)" | ||||||
|  | 
 | ||||||
|  | # Complete flags if we have no subcommand or a flag-friendly one. | ||||||
|  | set -l flag_applies "__fish_use_subcommand; or __fish_seen_subcommand_from $bun_builtin_cmds_accepting_flags" | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n $flag_applies --no-files -s 'u' -l 'origin' -r -d 'Server URL. Rewrites import paths' | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n $flag_applies --no-files  -s 'p' -l 'port' -r -d 'Port number to start server from' | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n $flag_applies --no-files  -s 'd' -l 'define' -r -d 'Substitute K:V while parsing, e.g. --define process.env.NODE_ENV:\"development\"' | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n $flag_applies --no-files  -s 'e' -l 'external' -r -d 'Exclude module from transpilation (can use * wildcards). ex: -e react' | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n $flag_applies --no-files -l 'use' -r -d 'Use a framework (ex: next)' | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n $flag_applies --no-files -l 'hot' -r -d 'Enable hot reloading in Bun\'s JavaScript runtime' | ||||||
|  | 
 | ||||||
|  | # Complete dev and create as first subcommand. | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_use_subcommand" -a 'dev' -d 'Start dev server' | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_use_subcommand" -a 'create' -f -d 'Create a new project from a template' | ||||||
|  | 
 | ||||||
|  | # Complete "next" and "react" if we've seen "create". | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_seen_subcommand_from create" -a 'next' -d 'new Next.js project' | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_seen_subcommand_from create" -a 'react' -d 'new React project' | ||||||
|  | 
 | ||||||
|  | # Complete "upgrade" as first subcommand. | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_use_subcommand" -a 'upgrade' -d 'Upgrade bun to the latest version' -x | ||||||
|  | # Complete "-h/--help" unconditionally. | ||||||
|  | complete -c bun \ | ||||||
|  | 	-s "h" -l "help" -d 'See all commands and flags' -x | ||||||
|  | 
 | ||||||
|  | # Complete "-v/--version" if we have no subcommand. | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "not __fish_use_subcommand" -l "version" -s "v" -d 'Bun\'s version' -x | ||||||
|  | 
 | ||||||
|  | # Complete additional subcommands. | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_use_subcommand" -a 'discord' -d 'Open bun\'s Discord server' -x | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_use_subcommand" -a 'bun' -d 'Generate a new bundle' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_seen_subcommand_from bun" -F -d 'Bundle this' | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_seen_subcommand_from create; and __fish_seen_subcommand_from react next" -F -d "Create in directory" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_use_subcommand" -a 'init' -F -d 'Start an empty Bun project' | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_use_subcommand" -a 'install' -f -d 'Install packages from package.json' | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_use_subcommand" -a 'add' -F -d 'Add a package to package.json' | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_use_subcommand" -a 'remove' -F -d 'Remove a package from package.json' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | for i in (seq (count $bun_install_boolean_flags)) | ||||||
|  | 	complete -c bun \ | ||||||
|  | 		-n "__fish_seen_subcommand_from install add remove" -l "$bun_install_boolean_flags[$i]" -d "$bun_install_boolean_flags_descriptions[$i]" | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_seen_subcommand_from install add remove" -l 'cwd' -d 'Change working directory' | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_seen_subcommand_from install add remove" -l 'cache-dir' -d 'Choose a cache directory (default: $HOME/.bun/install/cache)' | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_seen_subcommand_from add" -d 'Popular' -a '(__fish__get_bun_packages)' | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_seen_subcommand_from add" -d 'History' -a '(__history_completions)' | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_seen_subcommand_from pm; and not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts) cache;" -a 'bin ls cache hash hash-print hash-string' -f | ||||||
|  | 
 | ||||||
|  | complete -c bun \ | ||||||
|  | 	-n "__fish_seen_subcommand_from pm; and __fish_seen_subcommand_from cache; and not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts);" -a 'rm' -f | ||||||
|  | 
 | ||||||
|  | # Add built-in subcommands with descriptions. | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "create" -f -d "Create a new project from a template" | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "build bun" --require-parameter -F -d "Transpile and bundle one or more files" | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "upgrade" -d "Upgrade Bun" | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "run" -d "Run a script or package binary" | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "install" -d "Install dependencies from package.json" -f | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "remove" -d "Remove a dependency from package.json" -f | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "add" -d "Add a dependency to package.json" -f | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "init" -d "Initialize a Bun project in this directory" -f | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "link" -d "Register or link a local npm package" -f | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "unlink" -d "Unregister a local npm package" -f | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "pm" -d "Additional package management utilities" -f | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "x" -d "Execute a package binary, installing if needed" -f | ||||||
|  | complete -c bun -n "__fish_use_subcommand" -a "outdated" -d "Display the latest versions of outdated dependencies" -f | ||||||
| @ -1,3 +0,0 @@ | |||||||
| if test -f ~/.cargo/env.fish |  | ||||||
|     source ~/.cargo/env.fish |  | ||||||
| end |  | ||||||
| @ -1,6 +1,3 @@ | |||||||
| set -xg EDITOR vim |  | ||||||
| set -xg TZ 'America/Detroit' |  | ||||||
| 
 |  | ||||||
| if test -d ~/Maildir | if test -d ~/Maildir | ||||||
|   set -x MAIL ~/Maildir |   set -x MAIL ~/Maildir | ||||||
| end | end | ||||||
| @ -29,7 +26,6 @@ if status --is-interactive && type -q rbenv | |||||||
|   end |   end | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| #set -x SSH_AGENT_PID "" |  | ||||||
| if test -S $HOME/.gnupg/S.gpg-agent | if test -S $HOME/.gnupg/S.gpg-agent | ||||||
|   set -x SSH_AUTH_SOCK $HOME/.gnupg/S.gpg-agent |   set -x SSH_AUTH_SOCK $HOME/.gnupg/S.gpg-agent | ||||||
|   set -x GPG_SOCK $HOME/.gnupg/S.gpg-agent |   set -x GPG_SOCK $HOME/.gnupg/S.gpg-agent | ||||||
| @ -37,10 +33,6 @@ else | |||||||
|   type -q gpgconf && set -x SSH_AUTH_SOCK (gpgconf --list-dirs agent-ssh-socket) |   type -q gpgconf && set -x SSH_AUTH_SOCK (gpgconf --list-dirs agent-ssh-socket) | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| set -x BBJ_USER $USER |  | ||||||
| set -x DEBEMAIL ben@tilde.team |  | ||||||
| set -x DEBFULLNAME "Ben Harris" |  | ||||||
| 
 |  | ||||||
| # add dotnet completions if needed | # add dotnet completions if needed | ||||||
| if status --is-interactive && type -q dotnet | if status --is-interactive && type -q dotnet | ||||||
|   complete -f -c dotnet -a "(dotnet complete)" |   complete -f -c dotnet -a "(dotnet complete)" | ||||||
|  | |||||||
| @ -1,40 +1,54 @@ | |||||||
| # This file contains fish universal variable definitions. | # This file contains fish universal variable definitions. | ||||||
| # VERSION: 3.0 | # VERSION: 3.0 | ||||||
|  | SETUVAR --export BBJ_USER:ben | ||||||
| SETUVAR --export DEBEMAIL:ben\x40tilde\x2eteam | SETUVAR --export DEBEMAIL:ben\x40tilde\x2eteam | ||||||
|  | SETUVAR --export DEBFULLNAME:Ben\x20Harris | ||||||
| SETUVAR DOTNET_CLI_TELEMETRY_OPTOUT:1 | SETUVAR DOTNET_CLI_TELEMETRY_OPTOUT:1 | ||||||
|  | SETUVAR --export EDITOR:vim | ||||||
| SETUVAR EMAIL:ben\x40tilde\x2eteam | SETUVAR EMAIL:ben\x40tilde\x2eteam | ||||||
|  | SETUVAR --export TZ:America/Detroit | ||||||
| SETUVAR __fish_init_2_39_8:\x1d | SETUVAR __fish_init_2_39_8:\x1d | ||||||
| SETUVAR __fish_init_2_3_0:\x1d | SETUVAR __fish_init_2_3_0:\x1d | ||||||
| SETUVAR __fish_init_3_x:\x1d | SETUVAR __fish_init_3_x:\x1d | ||||||
| SETUVAR __fish_initialized:3400 | SETUVAR __fish_initialized:3800 | ||||||
| SETUVAR fish_color_autosuggestion:555\x1ebrblack | SETUVAR fish_color_autosuggestion:brblack | ||||||
| SETUVAR fish_color_cancel:\x2dr | SETUVAR fish_color_cancel:\x2dr | ||||||
| SETUVAR fish_color_command:\x2d\x2dbold | SETUVAR fish_color_command:normal | ||||||
| SETUVAR fish_color_comment:990000 | SETUVAR fish_color_comment:red | ||||||
| SETUVAR fish_color_cwd:green | SETUVAR fish_color_cwd:green | ||||||
| SETUVAR fish_color_cwd_root:red | SETUVAR fish_color_cwd_root:red | ||||||
| SETUVAR fish_color_end:009900 | SETUVAR fish_color_end:green | ||||||
| SETUVAR fish_color_error:ff0000 | SETUVAR fish_color_error:brred | ||||||
| SETUVAR fish_color_escape:00a6b2 | SETUVAR fish_color_escape:brcyan | ||||||
| SETUVAR fish_color_history_current:\x2d\x2dbold | SETUVAR fish_color_history_current:\x2d\x2dbold | ||||||
| SETUVAR fish_color_host:normal | SETUVAR fish_color_host:normal | ||||||
| SETUVAR fish_color_host_remote:yellow | SETUVAR fish_color_host_remote:yellow | ||||||
|  | SETUVAR fish_color_keyword:normal | ||||||
| SETUVAR fish_color_match:\x2d\x2dbackground\x3dbrblue | SETUVAR fish_color_match:\x2d\x2dbackground\x3dbrblue | ||||||
| SETUVAR fish_color_normal:normal | SETUVAR fish_color_normal:normal | ||||||
| SETUVAR fish_color_operator:00a6b2 | SETUVAR fish_color_operator:brcyan | ||||||
| SETUVAR fish_color_param:00afff | SETUVAR fish_color_option:cyan | ||||||
| SETUVAR fish_color_quote:999900 | SETUVAR fish_color_param:cyan | ||||||
| SETUVAR fish_color_redirection:00afff | SETUVAR fish_color_quote:yellow | ||||||
|  | SETUVAR fish_color_redirection:cyan\x1e\x2d\x2dbold | ||||||
| SETUVAR fish_color_search_match:bryellow\x1e\x2d\x2dbackground\x3dbrblack | SETUVAR fish_color_search_match:bryellow\x1e\x2d\x2dbackground\x3dbrblack | ||||||
| SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack | SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack | ||||||
| SETUVAR fish_color_status:990000 | SETUVAR fish_color_status:red | ||||||
| SETUVAR fish_color_user:brgreen | SETUVAR fish_color_user:brgreen | ||||||
| SETUVAR fish_color_valid_path:\x2d\x2dunderline | SETUVAR fish_color_valid_path:\x2d\x2dunderline | ||||||
| SETUVAR fish_greeting:Welcome\x20to\x20fish\x2c\x20the\x20friendly\x20interactive\x20shell | SETUVAR fish_greeting:Welcome\x20to\x20fish\x2c\x20the\x20friendly\x20interactive\x20shell | ||||||
| SETUVAR fish_key_bindings:fish_default_key_bindings | SETUVAR fish_key_bindings:fish_default_key_bindings | ||||||
|  | SETUVAR fish_pager_color_background:\x1d | ||||||
| SETUVAR fish_pager_color_completion:normal | SETUVAR fish_pager_color_completion:normal | ||||||
| SETUVAR fish_pager_color_description:B3A06D\x1eyellow | SETUVAR fish_pager_color_description:yellow\x1e\x2di | ||||||
| SETUVAR fish_pager_color_prefix:white\x1e\x2d\x2dbold\x1e\x2d\x2dunderline | SETUVAR fish_pager_color_prefix:normal\x1e\x2d\x2dbold\x1e\x2d\x2dunderline | ||||||
| SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan | SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan | ||||||
|  | SETUVAR fish_pager_color_secondary_background:\x1d | ||||||
|  | SETUVAR fish_pager_color_secondary_completion:\x1d | ||||||
|  | SETUVAR fish_pager_color_secondary_description:\x1d | ||||||
|  | SETUVAR fish_pager_color_secondary_prefix:\x1d | ||||||
| SETUVAR fish_pager_color_selected_background:\x2dr | SETUVAR fish_pager_color_selected_background:\x2dr | ||||||
|  | SETUVAR fish_pager_color_selected_completion:\x1d | ||||||
|  | SETUVAR fish_pager_color_selected_description:\x1d | ||||||
|  | SETUVAR fish_pager_color_selected_prefix:\x1d | ||||||
| SETUVAR fisher_dependency_count:bass\x1edone\x1egetopts\x1egitignore\x1ehumanize_duration\x1envm\x1espin | SETUVAR fisher_dependency_count:bass\x1edone\x1egetopts\x1egitignore\x1ehumanize_duration\x1envm\x1espin | ||||||
|  | |||||||
| @ -74,3 +74,6 @@ | |||||||
| 	sort = version:refname | 	sort = version:refname | ||||||
| [safe] | [safe] | ||||||
| 	directory = * | 	directory = * | ||||||
|  | [fetch] | ||||||
|  | 	prune = true | ||||||
|  | 	all = true | ||||||
|  | |||||||
| @ -14,4 +14,3 @@ instant = on | |||||||
| timer = 1 | timer = 1 | ||||||
| 
 | 
 | ||||||
| [buffer] | [buffer] | ||||||
| irc.tilde.#trivia.hotlist_max_level_nicks_add = "Oz:2,Nerd:2" |  | ||||||
|  | |||||||
| @ -25,7 +25,7 @@ use_items = 1 | |||||||
| 
 | 
 | ||||||
| [format] | [format] | ||||||
| buffer = "${format_number}${indent}${format_nick_prefix}${color_hotlist}${if:(${buffer.full_name} =~ ^irc)?${if:(${irc_server.away_time} > 0)?${color:yellow}>}${if:(${irc_channel.part} == 1)?${color:red}_}${if:(${irc_server.is_connected} == 0)?${color:*magenta}*}}${if:${type}==private?↪}${name}" | buffer = "${format_number}${indent}${format_nick_prefix}${color_hotlist}${if:(${buffer.full_name} =~ ^irc)?${if:(${irc_server.away_time} > 0)?${color:yellow}>}${if:(${irc_channel.part} == 1)?${color:red}_}${if:(${irc_server.is_connected} == 0)?${color:*magenta}*}}${if:${type}==private?↪}${name}" | ||||||
| buffer_current = "${color:,233}${format_number}${indent}${format_nick_prefix}${color:lightcyan}${name}" | buffer_current = "${color:,darkgray}${format_number}${indent}${format_nick_prefix}${color:yellow}${name}" | ||||||
| hotlist = " ${color:green}(${hotlist}${color:green})" | hotlist = " ${color:green}(${hotlist}${color:green})" | ||||||
| hotlist_highlight = "${color:magenta}" | hotlist_highlight = "${color:magenta}" | ||||||
| hotlist_low = "${color:default}" | hotlist_low = "${color:default}" | ||||||
|  | |||||||
| @ -51,7 +51,7 @@ join_auto_add_chantype = off | |||||||
| list_buffer = on | list_buffer = on | ||||||
| list_buffer_format_export = "${name} (${users}): "${topic}"" | list_buffer_format_export = "${name} (${users}): "${topic}"" | ||||||
| list_buffer_scroll_horizontal = 10 | list_buffer_scroll_horizontal = 10 | ||||||
| list_buffer_sort = "~name2" | list_buffer_sort = "-users" | ||||||
| list_buffer_topic_strip_colors = on | list_buffer_topic_strip_colors = on | ||||||
| msgbuffer_fallback = current | msgbuffer_fallback = current | ||||||
| new_channel_position = none | new_channel_position = none | ||||||
| @ -62,6 +62,7 @@ nick_mode = both | |||||||
| nick_mode_empty = off | nick_mode_empty = off | ||||||
| nicks_hide_password = "nickserv" | nicks_hide_password = "nickserv" | ||||||
| notice_as_pv = auto | notice_as_pv = auto | ||||||
|  | notice_nicks_disable_notify = "chanserv,nickserv" | ||||||
| notice_welcome_redirect = on | notice_welcome_redirect = on | ||||||
| notice_welcome_tags = "" | notice_welcome_tags = "" | ||||||
| notify_tags_ison = "notify_message" | notify_tags_ison = "notify_message" | ||||||
| @ -219,7 +220,7 @@ tilde.usermode | |||||||
| tilde.command_delay | tilde.command_delay | ||||||
| tilde.command = "/msg idlerpg_bot login wowbagger ${sec.data.idlerpgpass}" | tilde.command = "/msg idlerpg_bot login wowbagger ${sec.data.idlerpgpass}" | ||||||
| tilde.autojoin_delay | tilde.autojoin_delay | ||||||
| tilde.autojoin = "#opers,#.tilde,#adventofcode,#anelki,#ascii.town,#aussie,#binary-counting,#bots,#club,#cosmic,#counting,#covid19,#fr,#gemini,#gopher,#helpdesk,#idlerpg,#linux,#meta,#midgard,#netnews,#nsfw,#rw.rs,#secret-sudoers,#selfhosting,#team,#tilde.zone-admin,#tildebot,#tilderadio,#tilderadio-djs,#tildetel,#topm,#town,#vim,#wiki,#tilde.green,#tildeverse,#pink,#politics,#tilde.zone,#institute,#ctrl-c,#music,#zine" | tilde.autojoin = "#opers,#.tilde,#adventofcode,#anelki,#ascii.town,#bots,#club,#cosmic,#covid19,#fr,#gemini,#gopher,#helpdesk,#idlerpg,#linux,#meta,#netnews,#nsfw,#rw.rs,#secret-sudoers,#selfhosting,#team,#tilde.zone-admin,#tildebot,#tilderadio,#tilderadio-djs,#topm,#town,#wiki,#tilde.green,#tildeverse,#pink,#politics,#tilde.zone,#institute,#ctrl-c,#music,#zine" | ||||||
| tilde.autojoin_dynamic | tilde.autojoin_dynamic | ||||||
| tilde.autorejoin | tilde.autorejoin | ||||||
| tilde.autorejoin_delay | tilde.autorejoin_delay | ||||||
| @ -311,7 +312,7 @@ town.usermode | |||||||
| town.command_delay | town.command_delay | ||||||
| town.command | town.command | ||||||
| town.autojoin_delay | town.autojoin_delay | ||||||
| town.autojoin = "#announcements,#bots,#counting,#tildetown" | town.autojoin = "#announcements,#bots,#counting,#tildetown,#sickos.net" | ||||||
| town.autojoin_dynamic | town.autojoin_dynamic | ||||||
| town.autorejoin | town.autorejoin | ||||||
| town.autorejoin_delay | town.autorejoin_delay | ||||||
| @ -449,7 +450,7 @@ oftc.usermode | |||||||
| oftc.command_delay | oftc.command_delay | ||||||
| oftc.command | oftc.command | ||||||
| oftc.autojoin_delay | oftc.autojoin_delay | ||||||
| oftc.autojoin = "#bitlbee,#debian-devel,#fish,#salsa,#tilde.team" | oftc.autojoin = "#bitlbee,#debian-devel,#fish,#osm" | ||||||
| oftc.autojoin_dynamic | oftc.autojoin_dynamic | ||||||
| oftc.autorejoin | oftc.autorejoin | ||||||
| oftc.autorejoin_delay | oftc.autorejoin_delay | ||||||
| @ -511,10 +512,10 @@ blinkenshell.split_msg_max_length | |||||||
| blinkenshell.charset_message | blinkenshell.charset_message | ||||||
| blinkenshell.default_chantypes | blinkenshell.default_chantypes | ||||||
| blinkenshell.registered_mode | blinkenshell.registered_mode | ||||||
| inspircd.addresses = "irc.inspircd.org" | inspircd.addresses = "irc.teranova.net/6697" | ||||||
| inspircd.proxy | inspircd.proxy | ||||||
| inspircd.ipv6 | inspircd.ipv6 | ||||||
| inspircd.tls | inspircd.tls = on | ||||||
| inspircd.tls_cert | inspircd.tls_cert | ||||||
| inspircd.tls_password | inspircd.tls_password | ||||||
| inspircd.tls_priorities | inspircd.tls_priorities | ||||||
| @ -692,98 +693,6 @@ libera.split_msg_max_length | |||||||
| libera.charset_message | libera.charset_message | ||||||
| libera.default_chantypes | libera.default_chantypes | ||||||
| libera.registered_mode | libera.registered_mode | ||||||
| ergo.addresses = "irc.ergo.chat/6697" |  | ||||||
| ergo.proxy |  | ||||||
| ergo.ipv6 |  | ||||||
| ergo.tls = on |  | ||||||
| ergo.tls_cert |  | ||||||
| ergo.tls_password |  | ||||||
| ergo.tls_priorities |  | ||||||
| ergo.tls_dhkey_size |  | ||||||
| ergo.tls_fingerprint |  | ||||||
| ergo.tls_verify |  | ||||||
| ergo.password |  | ||||||
| ergo.capabilities |  | ||||||
| ergo.sasl_mechanism = external |  | ||||||
| ergo.sasl_username |  | ||||||
| ergo.sasl_password |  | ||||||
| ergo.sasl_key |  | ||||||
| ergo.sasl_timeout |  | ||||||
| ergo.sasl_fail |  | ||||||
| ergo.autoconnect |  | ||||||
| ergo.autoreconnect |  | ||||||
| ergo.autoreconnect_delay |  | ||||||
| ergo.nicks = "ben" |  | ||||||
| ergo.nicks_alternate |  | ||||||
| ergo.username |  | ||||||
| ergo.realname |  | ||||||
| ergo.local_hostname |  | ||||||
| ergo.usermode |  | ||||||
| ergo.command_delay |  | ||||||
| ergo.command |  | ||||||
| ergo.autojoin_delay |  | ||||||
| ergo.autojoin = "#ergo" |  | ||||||
| ergo.autojoin_dynamic |  | ||||||
| ergo.autorejoin |  | ||||||
| ergo.autorejoin_delay |  | ||||||
| ergo.connection_timeout |  | ||||||
| ergo.anti_flood |  | ||||||
| ergo.away_check |  | ||||||
| ergo.away_check_max_nicks |  | ||||||
| ergo.msg_kick |  | ||||||
| ergo.msg_part |  | ||||||
| ergo.msg_quit |  | ||||||
| ergo.notify |  | ||||||
| ergo.split_msg_max_length |  | ||||||
| ergo.charset_message |  | ||||||
| ergo.default_chantypes |  | ||||||
| ergo.registered_mode |  | ||||||
| snoonet.addresses = "irc.snoonet.org/6697" |  | ||||||
| snoonet.proxy |  | ||||||
| snoonet.ipv6 |  | ||||||
| snoonet.tls = on |  | ||||||
| snoonet.tls_cert |  | ||||||
| snoonet.tls_password |  | ||||||
| snoonet.tls_priorities |  | ||||||
| snoonet.tls_dhkey_size |  | ||||||
| snoonet.tls_fingerprint |  | ||||||
| snoonet.tls_verify |  | ||||||
| snoonet.password |  | ||||||
| snoonet.capabilities |  | ||||||
| snoonet.sasl_mechanism |  | ||||||
| snoonet.sasl_username = "benharri" |  | ||||||
| snoonet.sasl_password = "${sec.data.snoonetpass}" |  | ||||||
| snoonet.sasl_key |  | ||||||
| snoonet.sasl_timeout |  | ||||||
| snoonet.sasl_fail |  | ||||||
| snoonet.autoconnect |  | ||||||
| snoonet.autoreconnect |  | ||||||
| snoonet.autoreconnect_delay |  | ||||||
| snoonet.nicks |  | ||||||
| snoonet.nicks_alternate |  | ||||||
| snoonet.username |  | ||||||
| snoonet.realname |  | ||||||
| snoonet.local_hostname |  | ||||||
| snoonet.usermode |  | ||||||
| snoonet.command_delay |  | ||||||
| snoonet.command |  | ||||||
| snoonet.autojoin_delay |  | ||||||
| snoonet.autojoin = "#personalfinance" |  | ||||||
| snoonet.autojoin_dynamic |  | ||||||
| snoonet.autorejoin |  | ||||||
| snoonet.autorejoin_delay |  | ||||||
| snoonet.connection_timeout |  | ||||||
| snoonet.anti_flood |  | ||||||
| snoonet.away_check |  | ||||||
| snoonet.away_check_max_nicks |  | ||||||
| snoonet.msg_kick |  | ||||||
| snoonet.msg_part |  | ||||||
| snoonet.msg_quit |  | ||||||
| snoonet.notify |  | ||||||
| snoonet.split_msg_max_length |  | ||||||
| snoonet.charset_message |  | ||||||
| snoonet.default_chantypes |  | ||||||
| snoonet.registered_mode |  | ||||||
| m455.addresses = "m455.casa/6697" | m455.addresses = "m455.casa/6697" | ||||||
| m455.proxy | m455.proxy | ||||||
| m455.ipv6 | m455.ipv6 | ||||||
| @ -814,7 +723,7 @@ m455.usermode | |||||||
| m455.command_delay | m455.command_delay | ||||||
| m455.command | m455.command | ||||||
| m455.autojoin_delay | m455.autojoin_delay | ||||||
| m455.autojoin = "#basement,#serverroom,#siliconpals" | m455.autojoin = "#basement" | ||||||
| m455.autojoin_dynamic | m455.autojoin_dynamic | ||||||
| m455.autorejoin | m455.autorejoin | ||||||
| m455.autorejoin_delay | m455.autorejoin_delay | ||||||
| @ -830,52 +739,6 @@ m455.split_msg_max_length | |||||||
| m455.charset_message | m455.charset_message | ||||||
| m455.default_chantypes | m455.default_chantypes | ||||||
| m455.registered_mode | m455.registered_mode | ||||||
| hackint.addresses = "irc.hackint.org/6697" |  | ||||||
| hackint.proxy |  | ||||||
| hackint.ipv6 |  | ||||||
| hackint.tls = on |  | ||||||
| hackint.tls_cert |  | ||||||
| hackint.tls_password |  | ||||||
| hackint.tls_priorities |  | ||||||
| hackint.tls_dhkey_size |  | ||||||
| hackint.tls_fingerprint |  | ||||||
| hackint.tls_verify |  | ||||||
| hackint.password |  | ||||||
| hackint.capabilities |  | ||||||
| hackint.sasl_mechanism |  | ||||||
| hackint.sasl_username = "ben" |  | ||||||
| hackint.sasl_password = "${sec.data.hackintpass}" |  | ||||||
| hackint.sasl_key |  | ||||||
| hackint.sasl_timeout |  | ||||||
| hackint.sasl_fail |  | ||||||
| hackint.autoconnect |  | ||||||
| hackint.autoreconnect |  | ||||||
| hackint.autoreconnect_delay |  | ||||||
| hackint.nicks |  | ||||||
| hackint.nicks_alternate |  | ||||||
| hackint.username |  | ||||||
| hackint.realname |  | ||||||
| hackint.local_hostname |  | ||||||
| hackint.usermode |  | ||||||
| hackint.command_delay |  | ||||||
| hackint.command |  | ||||||
| hackint.autojoin_delay |  | ||||||
| hackint.autojoin = "" |  | ||||||
| hackint.autojoin_dynamic |  | ||||||
| hackint.autorejoin |  | ||||||
| hackint.autorejoin_delay |  | ||||||
| hackint.connection_timeout |  | ||||||
| hackint.anti_flood |  | ||||||
| hackint.away_check |  | ||||||
| hackint.away_check_max_nicks |  | ||||||
| hackint.msg_kick |  | ||||||
| hackint.msg_part |  | ||||||
| hackint.msg_quit |  | ||||||
| hackint.notify |  | ||||||
| hackint.split_msg_max_length |  | ||||||
| hackint.charset_message |  | ||||||
| hackint.default_chantypes |  | ||||||
| hackint.registered_mode |  | ||||||
| syn.addresses = "irc.us.synirc.net/6697" | syn.addresses = "irc.us.synirc.net/6697" | ||||||
| syn.proxy | syn.proxy | ||||||
| syn.ipv6 | syn.ipv6 | ||||||
| @ -968,3 +831,49 @@ efnet.split_msg_max_length | |||||||
| efnet.charset_message | efnet.charset_message | ||||||
| efnet.default_chantypes | efnet.default_chantypes | ||||||
| efnet.registered_mode | efnet.registered_mode | ||||||
|  | twitch.addresses = "irc.chat.twitch.tv" | ||||||
|  | twitch.proxy | ||||||
|  | twitch.ipv6 | ||||||
|  | twitch.tls | ||||||
|  | twitch.tls_cert | ||||||
|  | twitch.tls_password | ||||||
|  | twitch.tls_priorities | ||||||
|  | twitch.tls_dhkey_size | ||||||
|  | twitch.tls_fingerprint | ||||||
|  | twitch.tls_verify | ||||||
|  | twitch.password = "${sec.data.twitchoauth}" | ||||||
|  | twitch.capabilities | ||||||
|  | twitch.sasl_mechanism | ||||||
|  | twitch.sasl_username | ||||||
|  | twitch.sasl_password | ||||||
|  | twitch.sasl_key | ||||||
|  | twitch.sasl_timeout | ||||||
|  | twitch.sasl_fail | ||||||
|  | twitch.autoconnect | ||||||
|  | twitch.autoreconnect | ||||||
|  | twitch.autoreconnect_delay | ||||||
|  | twitch.nicks = "harriben" | ||||||
|  | twitch.nicks_alternate | ||||||
|  | twitch.username | ||||||
|  | twitch.realname | ||||||
|  | twitch.local_hostname | ||||||
|  | twitch.usermode | ||||||
|  | twitch.command_delay | ||||||
|  | twitch.command | ||||||
|  | twitch.autojoin_delay | ||||||
|  | twitch.autojoin = "" | ||||||
|  | twitch.autojoin_dynamic | ||||||
|  | twitch.autorejoin | ||||||
|  | twitch.autorejoin_delay | ||||||
|  | twitch.connection_timeout | ||||||
|  | twitch.anti_flood | ||||||
|  | twitch.away_check | ||||||
|  | twitch.away_check_max_nicks | ||||||
|  | twitch.msg_kick | ||||||
|  | twitch.msg_part | ||||||
|  | twitch.msg_quit | ||||||
|  | twitch.notify | ||||||
|  | twitch.split_msg_max_length | ||||||
|  | twitch.charset_message | ||||||
|  | twitch.default_chantypes | ||||||
|  | twitch.registered_mode | ||||||
|  | |||||||
| @ -13,18 +13,6 @@ | |||||||
| fifo.fifo = "on" | fifo.fifo = "on" | ||||||
| guile.check_license = "off" | guile.check_license = "off" | ||||||
| lua.check_license = "off" | lua.check_license = "off" | ||||||
| lua.matrix.backlog_lines = "120" |  | ||||||
| lua.matrix.debug = "off" |  | ||||||
| lua.matrix.encrypted_message_color = "lightgreen" |  | ||||||
| lua.matrix.homeserver_url = "https://l4p1n.ch/" |  | ||||||
| lua.matrix.local_echo = "on" |  | ||||||
| lua.matrix.nick_style = "nick" |  | ||||||
| lua.matrix.password = "${sec.data.matrixpw}" |  | ||||||
| lua.matrix.presence_filter = "off" |  | ||||||
| lua.matrix.read_receipts = "on" |  | ||||||
| lua.matrix.timeout = "5" |  | ||||||
| lua.matrix.typing_notices = "on" |  | ||||||
| lua.matrix.user = "ben" |  | ||||||
| perl.check_license = "off" | perl.check_license = "off" | ||||||
| perl.colorize_lines.alternate_color = "" | perl.colorize_lines.alternate_color = "" | ||||||
| perl.colorize_lines.blacklist_buffers = "" | perl.colorize_lines.blacklist_buffers = "" | ||||||
| @ -35,7 +23,7 @@ perl.colorize_lines.highlight_words = "off" | |||||||
| perl.colorize_lines.highlight_words_color = "" | perl.colorize_lines.highlight_words_color = "" | ||||||
| perl.colorize_lines.ignore_tags = "irc_ctcp" | perl.colorize_lines.ignore_tags = "irc_ctcp" | ||||||
| perl.colorize_lines.lines = "nicks" | perl.colorize_lines.lines = "nicks" | ||||||
| perl.colorize_lines.nicks = "benharri,ben,bhh" | perl.colorize_lines.nicks = "benharri,ben" | ||||||
| perl.colorize_lines.own_lines = "off" | perl.colorize_lines.own_lines = "off" | ||||||
| perl.colorize_lines.own_lines_color = "" | perl.colorize_lines.own_lines_color = "" | ||||||
| perl.colorize_lines.tags = "irc_privmsg" | perl.colorize_lines.tags = "irc_privmsg" | ||||||
| @ -50,16 +38,6 @@ perl.highmon.nick_prefix = "<" | |||||||
| perl.highmon.nick_suffix = ">" | perl.highmon.nick_suffix = ">" | ||||||
| perl.highmon.output = "buffer" | perl.highmon.output = "buffer" | ||||||
| perl.highmon.short_names = "off" | perl.highmon.short_names = "off" | ||||||
| perl.rslap.slapback = "random" |  | ||||||
| python.apply_corrections.check_every = "5" |  | ||||||
| python.apply_corrections.data_timeout = "60" |  | ||||||
| python.apply_corrections.message_limit = "2" |  | ||||||
| python.apply_corrections.print_format = "[nick]: [corrected]" |  | ||||||
| python.apply_corrections.print_limit = "1" |  | ||||||
| python.autojoin.autosave = "off" |  | ||||||
| python.autosavekey.add = "on" |  | ||||||
| python.autosavekey.mute = "off" |  | ||||||
| python.autosavekey.secure = "on" |  | ||||||
| python.buffer_autoclose.age_limit = "30" | python.buffer_autoclose.age_limit = "30" | ||||||
| python.buffer_autoclose.ignore = "bitlbee.marley" | python.buffer_autoclose.ignore = "bitlbee.marley" | ||||||
| python.buffer_autoclose.interval = "1" | python.buffer_autoclose.interval = "1" | ||||||
| @ -67,7 +45,7 @@ python.buffer_autoclose.prefer = "" | |||||||
| python.check_license = "off" | python.check_license = "off" | ||||||
| python.completion.replace_values = "shrug=>¯\_(ツ)_/¯;;wiki=>https://tilde.team/wiki/;;sword=>o()xxxx[{::::::::::::::::::::::::::::::::::>;;lenny=>( ͡° ͜ʖ ͡°);;byobu=>https://superuser.com/a/423397/866501;;fg=>(☞゚ヮ゚)☞;;huh=>(-_-)ゞ゛;;tablefix=>┬─┬ノ( º _ ºノ);;weedoc=>https://weechat.org/files/doc/stable/weechat_user.en.html;;weekeys=>https://weechat.org/files/doc/stable/weechat_user.en.html#key_bindings;;denko=>(´・ω・`);;yuno=>ლ(́ಠ◞益◟ಠ‵ლ);;tf=>(ノಥ益ಥ)ノ彡┻━┻;;tb=>┬─┬ノ( º _ ºノ);;ducc=>・゜゜・。。・゜゜\_o< QUACK!;;wat=>https://bhh.sh/wat.jpg;;matrix=>https://www.moparisthebest.com/images/xmpp-vs-matrix.jpg;;servers=>https://tilde.wiki/wiki/User:Ben/Servers;;nft=>https://youtu.be/YQ_xWvX1n9g" | python.completion.replace_values = "shrug=>¯\_(ツ)_/¯;;wiki=>https://tilde.team/wiki/;;sword=>o()xxxx[{::::::::::::::::::::::::::::::::::>;;lenny=>( ͡° ͜ʖ ͡°);;byobu=>https://superuser.com/a/423397/866501;;fg=>(☞゚ヮ゚)☞;;huh=>(-_-)ゞ゛;;tablefix=>┬─┬ノ( º _ ºノ);;weedoc=>https://weechat.org/files/doc/stable/weechat_user.en.html;;weekeys=>https://weechat.org/files/doc/stable/weechat_user.en.html#key_bindings;;denko=>(´・ω・`);;yuno=>ლ(́ಠ◞益◟ಠ‵ლ);;tf=>(ノಥ益ಥ)ノ彡┻━┻;;tb=>┬─┬ノ( º _ ºノ);;ducc=>・゜゜・。。・゜゜\_o< QUACK!;;wat=>https://bhh.sh/wat.jpg;;matrix=>https://www.moparisthebest.com/images/xmpp-vs-matrix.jpg;;servers=>https://tilde.wiki/wiki/User:Ben/Servers;;nft=>https://youtu.be/YQ_xWvX1n9g" | ||||||
| python.go.auto_jump = "off" | python.go.auto_jump = "off" | ||||||
| python.go.buffer_number = "on" | python.go.buffer_number = "off" | ||||||
| python.go.color_name = "black,cyan" | python.go.color_name = "black,cyan" | ||||||
| python.go.color_name_highlight = "red,cyan" | python.go.color_name_highlight = "red,cyan" | ||||||
| python.go.color_name_highlight_selected = "red,brown" | python.go.color_name_highlight_selected = "red,brown" | ||||||
| @ -89,12 +67,6 @@ python.grep.max_lines = "4000" | |||||||
| python.grep.show_summary = "on" | python.grep.show_summary = "on" | ||||||
| python.grep.size_limit = "2048" | python.grep.size_limit = "2048" | ||||||
| python.grep.timeout_secs = "300" | python.grep.timeout_secs = "300" | ||||||
| python.listbuffer.autofocus = "on" |  | ||||||
| python.listbuffer.channel_min_width = "25" |  | ||||||
| python.listbuffer.modes_min_width = "8" |  | ||||||
| python.listbuffer.sort_inverted = "off" |  | ||||||
| python.listbuffer.sort_order = "users" |  | ||||||
| python.listbuffer.users_min_width = "8" |  | ||||||
| python.screen_away.away_suffix = "" | python.screen_away.away_suffix = "" | ||||||
| python.screen_away.command_on_attach = "" | python.screen_away.command_on_attach = "" | ||||||
| python.screen_away.command_on_detach = "" | python.screen_away.command_on_detach = "" | ||||||
| @ -106,51 +78,6 @@ python.screen_away.no_output = "off" | |||||||
| python.screen_away.set_away = "on" | python.screen_away.set_away = "on" | ||||||
| python.screen_away.socket_file = "" | python.screen_away.socket_file = "" | ||||||
| python.screen_away.time_format = "since %Y-%m-%d %H:%M:%S%z" | python.screen_away.time_format = "since %Y-%m-%d %H:%M:%S%z" | ||||||
| python.slack.auto_open_threads = "false" |  | ||||||
| python.slack.background_load_all_history = "false" |  | ||||||
| python.slack.channel_name_typing_indicator = "true" |  | ||||||
| python.slack.color_buflist_muted_channels = "darkgray" |  | ||||||
| python.slack.color_deleted = "red" |  | ||||||
| python.slack.color_edited_suffix = "095" |  | ||||||
| python.slack.color_reaction_suffix = "darkgray" |  | ||||||
| python.slack.color_reaction_suffix_added_by_you = "blue" |  | ||||||
| python.slack.color_thread_suffix = "lightcyan" |  | ||||||
| python.slack.color_typing_notice = "yellow" |  | ||||||
| python.slack.colorize_attachments = "prefix" |  | ||||||
| python.slack.colorize_private_chats = "false" |  | ||||||
| python.slack.debug_level = "3" |  | ||||||
| python.slack.debug_mode = "false" |  | ||||||
| python.slack.distracting_channels = "" |  | ||||||
| python.slack.external_user_suffix = "*" |  | ||||||
| python.slack.files_download_location = "" |  | ||||||
| python.slack.group_name_prefix = "&" |  | ||||||
| python.slack.history_fetch_count = "200" |  | ||||||
| python.slack.map_underline_to = "_" |  | ||||||
| python.slack.migrated = "true" |  | ||||||
| python.slack.muted_channels_activity = "personal_highlights" |  | ||||||
| python.slack.never_away = "false" |  | ||||||
| python.slack.notify_subscribed_threads = "auto" |  | ||||||
| python.slack.notify_usergroup_handle_updated = "false" |  | ||||||
| python.slack.record_events = "false" |  | ||||||
| python.slack.render_bold_as = "bold" |  | ||||||
| python.slack.render_emoji_as_string = "false" |  | ||||||
| python.slack.render_italic_as = "italic" |  | ||||||
| python.slack.send_typing_notice = "true" |  | ||||||
| python.slack.server_aliases = "" |  | ||||||
| python.slack.shared_name_prefix = "%" |  | ||||||
| python.slack.short_buffer_names = "false" |  | ||||||
| python.slack.show_buflist_presence = "true" |  | ||||||
| python.slack.show_reaction_nicks = "false" |  | ||||||
| python.slack.slack_api_token = "${sec.data.remotesslacktoken}" |  | ||||||
| python.slack.slack_timeout = "20000" |  | ||||||
| python.slack.switch_buffer_on_join = "true" |  | ||||||
| python.slack.thread_messages_in_channel = "false" |  | ||||||
| python.slack.unfurl_auto_link_display = "both" |  | ||||||
| python.slack.unfurl_ignore_alt_text = "false" |  | ||||||
| python.slack.unhide_buffers_with_activity = "false" |  | ||||||
| python.slack.use_full_names = "false" |  | ||||||
| python.topicdiff_alt.color_del = "darkgray" |  | ||||||
| python.topicdiff_alt.color_ins = "lightcyan" |  | ||||||
| ruby.check_license = "off" | ruby.check_license = "off" | ||||||
| tcl.check_license = "off" | tcl.check_license = "off" | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1 +0,0 @@ | |||||||
| ../buffer_autoset.py |  | ||||||
| @ -1,351 +0,0 @@ | |||||||
| # -*- coding: utf-8 -*- |  | ||||||
| # |  | ||||||
| # Copyright (C) 2010-2017 Sébastien Helleu <flashcode@flashtux.org> |  | ||||||
| # |  | ||||||
| # This program is free software; you can redistribute it and/or modify |  | ||||||
| # it under the terms of the GNU General Public License as published by |  | ||||||
| # the Free Software Foundation; either version 3 of the License, or |  | ||||||
| # (at your option) any later version. |  | ||||||
| # |  | ||||||
| # This program is distributed in the hope that it will be useful, |  | ||||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
| # GNU General Public License for more details. |  | ||||||
| # |  | ||||||
| # You should have received a copy of the GNU General Public License |  | ||||||
| # along with this program.  If not, see <http://www.gnu.org/licenses/>. |  | ||||||
| # |  | ||||||
| 
 |  | ||||||
| # |  | ||||||
| # Auto-set buffer properties when a buffer is opened. |  | ||||||
| # (this script requires WeeChat 1.0 or newer) |  | ||||||
| # |  | ||||||
| # History: |  | ||||||
| # |  | ||||||
| # 2021-06-02, Sébastien Helleu <flashcode@flashtux.org>: |  | ||||||
| #     version 1.2: fix /help buffer_autoset |  | ||||||
| # 2018-04-14, Kim B. Heino: |  | ||||||
| #     version 1.1: on startup apply settings to already opened buffers |  | ||||||
| # 2017-06-21, Sébastien Helleu <flashcode@flashtux.org>: |  | ||||||
| #     version 1.0: rename command /autosetbuffer to /buffer_autoset |  | ||||||
| # 2015-09-28, Simmo Saan <simmo.saan@gmail.com>: |  | ||||||
| #     version 0.9: instantly apply properties |  | ||||||
| # 2015-07-12, Sébastien Helleu <flashcode@flashtux.org>: |  | ||||||
| #     version 0.8: add option buffer_autoset.look.timer to add a small timer |  | ||||||
| #                  before setting buffer properties |  | ||||||
| # 2015-04-05, Nils Görs <libera@#weechat>: |  | ||||||
| #     version 0.7: increase priority of hook_signal('buffer_opened') |  | ||||||
| # 2012-12-09, Nils Görs <libera@#weechat>: |  | ||||||
| #     version 0.6: add support of core buffer |  | ||||||
| # 2012-03-09, Sébastien Helleu <flashcode@flashtux.org>: |  | ||||||
| #     version 0.5: fix reload of config file |  | ||||||
| # 2012-01-03, Sébastien Helleu <flashcode@flashtux.org>: |  | ||||||
| #     version 0.4: make script compatible with Python 3.x |  | ||||||
| # 2010-12-02, Sébastien Helleu <flashcode@flashtux.org>: |  | ||||||
| #     version 0.3: "no_highlight_nicks" replaced by "hotlist_max_level_nicks" |  | ||||||
| # 2010-10-11, Sébastien Helleu <flashcode@flashtux.org>: |  | ||||||
| #     version 0.2: add example in /help autosetbuffer with new buffer |  | ||||||
| #                  property "no_highlight_nicks" |  | ||||||
| # 2010-04-19, Sébastien Helleu <flashcode@flashtux.org>: |  | ||||||
| #     version 0.1: initial release |  | ||||||
| # |  | ||||||
| 
 |  | ||||||
| SCRIPT_NAME = "buffer_autoset" |  | ||||||
| SCRIPT_AUTHOR = "Sébastien Helleu <flashcode@flashtux.org>" |  | ||||||
| SCRIPT_VERSION = "1.2" |  | ||||||
| SCRIPT_LICENSE = "GPL3" |  | ||||||
| SCRIPT_DESC = "Auto-set buffer properties when a buffer is opened" |  | ||||||
| 
 |  | ||||||
| SCRIPT_COMMAND = SCRIPT_NAME |  | ||||||
| 
 |  | ||||||
| import_ok = True |  | ||||||
| 
 |  | ||||||
| try: |  | ||||||
|     import weechat |  | ||||||
| except ImportError: |  | ||||||
|     print("This script must be run under WeeChat.") |  | ||||||
|     print("Get WeeChat now at: http://www.weechat.org/") |  | ||||||
|     import_ok = False |  | ||||||
| 
 |  | ||||||
| CONFIG_FILE_NAME = "buffer_autoset" |  | ||||||
| 
 |  | ||||||
| # config file / options |  | ||||||
| bas_config_file = "" |  | ||||||
| bas_options = {} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # =================================[ config ]================================= |  | ||||||
| 
 |  | ||||||
| def bas_config_init(): |  | ||||||
|     """ |  | ||||||
|     Initialization of configuration file. |  | ||||||
|     Sections: buffer. |  | ||||||
|     """ |  | ||||||
|     global bas_config_file, bas_options |  | ||||||
|     bas_config_file = weechat.config_new(CONFIG_FILE_NAME, |  | ||||||
|                                          "bas_config_reload_cb", "") |  | ||||||
|     if bas_config_file == "": |  | ||||||
|         return |  | ||||||
| 
 |  | ||||||
|     # section "look" |  | ||||||
|     section_look = weechat.config_new_section( |  | ||||||
|         bas_config_file, "look", 0, 0, "", "", "", "", "", "", "", "", "", "") |  | ||||||
|     if not section_look: |  | ||||||
|         weechat.config_free(bas_config_file) |  | ||||||
|         return |  | ||||||
| 
 |  | ||||||
|     # options in section "look" |  | ||||||
|     bas_options["look_timer"] = weechat.config_new_option( |  | ||||||
|         bas_config_file, section_look, "timer", "integer", |  | ||||||
|         "Timer used to delay the set of properties (in milliseconds, " |  | ||||||
|         "0 = don't use a timer)", |  | ||||||
|         "", 0, 2147483647, "1", "1", 0, "", "", "", "", "", "") |  | ||||||
| 
 |  | ||||||
|     bas_options["look_instant"] = weechat.config_new_option( |  | ||||||
|         bas_config_file, section_look, "instant", "boolean", |  | ||||||
|         "Instantly apply properties to buffers affected", |  | ||||||
|         "", 0, 0, "on", "on", 0, "", "", "", "", "", "") |  | ||||||
| 
 |  | ||||||
|     # section "buffer" |  | ||||||
|     section_buffer = weechat.config_new_section( |  | ||||||
|         bas_config_file, "buffer", 1, 1, "", "", "", "", "", "", |  | ||||||
|         "bas_config_buffer_create_option_cb", "", "", "") |  | ||||||
|     if not section_buffer: |  | ||||||
|         weechat.config_free(bas_config_file) |  | ||||||
|         return |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def bas_config_buffer_create_option_cb(data, config_file, section, option_name, |  | ||||||
|                                        value): |  | ||||||
|     option = weechat.config_search_option(config_file, section, option_name) |  | ||||||
|     if option: |  | ||||||
|         return weechat.config_option_set(option, value, 1) |  | ||||||
|     else: |  | ||||||
|         option = weechat.config_new_option(config_file, section, option_name, |  | ||||||
|                                            "string", "", "", 0, 0, "", |  | ||||||
|                                            value, 0, "", "", "", "", "", "") |  | ||||||
|         if not option: |  | ||||||
|             return weechat.WEECHAT_CONFIG_OPTION_SET_ERROR |  | ||||||
|         return weechat.WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def bas_config_reload_cb(data, config_file): |  | ||||||
|     """Reload configuration file.""" |  | ||||||
|     return weechat.config_reload(config_file) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def bas_config_read(): |  | ||||||
|     """Read configuration file.""" |  | ||||||
|     global bas_config_file |  | ||||||
|     return weechat.config_read(bas_config_file) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def bas_config_write(): |  | ||||||
|     """Write configuration file.""" |  | ||||||
|     global bas_config_file |  | ||||||
|     return weechat.config_write(bas_config_file) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # ================================[ command ]================================= |  | ||||||
| 
 |  | ||||||
| def bas_cmd(data, buffer, args): |  | ||||||
|     """Callback for /buffer_autoset command.""" |  | ||||||
|     args = args.strip() |  | ||||||
|     if args == "": |  | ||||||
|         weechat.command("", "/set %s.buffer.*" % CONFIG_FILE_NAME) |  | ||||||
|         return weechat.WEECHAT_RC_OK |  | ||||||
|     argv = args.split(None, 3) |  | ||||||
|     if len(argv) > 0: |  | ||||||
|         if argv[0] == "add": |  | ||||||
|             if len(argv) < 4: |  | ||||||
|                 weechat.command("", "/help %s" % SCRIPT_COMMAND) |  | ||||||
|                 return weechat.WEECHAT_RC_OK |  | ||||||
|             weechat.command("", "/set %s.buffer.%s.%s \"%s\"" |  | ||||||
|                             % (CONFIG_FILE_NAME, argv[1], argv[2], argv[3])) |  | ||||||
|         elif argv[0] == "del": |  | ||||||
|             if len(argv) < 2: |  | ||||||
|                 weechat.command("", "/help %s" % SCRIPT_COMMAND) |  | ||||||
|                 return weechat.WEECHAT_RC_OK |  | ||||||
|             weechat.command("", "/unset %s.buffer.%s" |  | ||||||
|                             % (CONFIG_FILE_NAME, argv[1])) |  | ||||||
|         else: |  | ||||||
|             weechat.command("", "/help %s" % SCRIPT_COMMAND) |  | ||||||
|             return weechat.WEECHAT_RC_OK |  | ||||||
|     return weechat.WEECHAT_RC_OK |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def bas_completion_current_buffer_cb(data, completion_item, buffer, |  | ||||||
|                                      completion): |  | ||||||
|     """ |  | ||||||
|     Complete with current buffer name (plugin.name), |  | ||||||
|     for command '/buffer_autoset'. |  | ||||||
|     """ |  | ||||||
|     name = "%s.%s" % (weechat.buffer_get_string(buffer, "plugin"), |  | ||||||
|                       weechat.buffer_get_string(buffer, "name")) |  | ||||||
|     weechat.hook_completion_list_add(completion, name, |  | ||||||
|                                      0, weechat.WEECHAT_LIST_POS_BEGINNING) |  | ||||||
|     return weechat.WEECHAT_RC_OK |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def bas_completion_options_cb(data, completion_item, buffer, completion): |  | ||||||
|     """Complete with config options, for command '/buffer_autoset'.""" |  | ||||||
|     options = weechat.infolist_get("option", "", |  | ||||||
|                                    "%s.buffer.*" % CONFIG_FILE_NAME) |  | ||||||
|     if options: |  | ||||||
|         while weechat.infolist_next(options): |  | ||||||
|             weechat.hook_completion_list_add( |  | ||||||
|                 completion, |  | ||||||
|                 weechat.infolist_string(options, "option_name"), |  | ||||||
|                 0, weechat.WEECHAT_LIST_POS_SORT) |  | ||||||
|         weechat.infolist_free(options) |  | ||||||
|     return weechat.WEECHAT_RC_OK |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # ==========================[ timer/signal/option ]=========================== |  | ||||||
| 
 |  | ||||||
| def bas_apply_options_for_buffer(buffer): |  | ||||||
|     full_name = weechat.buffer_get_string(buffer, "full_name") |  | ||||||
|     options = weechat.infolist_get("option", "", |  | ||||||
|                                    "%s.buffer.*" % CONFIG_FILE_NAME) |  | ||||||
|     if not options: |  | ||||||
|         return |  | ||||||
| 
 |  | ||||||
|     while weechat.infolist_next(options): |  | ||||||
|         option = weechat.infolist_string(options, "option_name") |  | ||||||
|         value = weechat.infolist_string(options, "value") |  | ||||||
|         if option: |  | ||||||
|             pos = option.rfind(".") |  | ||||||
|             if pos > 0: |  | ||||||
|                 buffer_mask = option[0:pos] |  | ||||||
|                 property = option[pos+1:] |  | ||||||
|                 if buffer_mask and property: |  | ||||||
|                     if weechat.string_match(full_name, buffer_mask, 1): |  | ||||||
|                         weechat.buffer_set(buffer, property, value) |  | ||||||
| 
 |  | ||||||
|     weechat.infolist_free(options) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def bas_timer_buffer_opened_cb(data, remaining_calls): |  | ||||||
|     full_name = data |  | ||||||
|     buffer = weechat.buffer_search("==", full_name) |  | ||||||
|     if not buffer: |  | ||||||
|         return weechat.WEECHAT_RC_OK |  | ||||||
|     bas_apply_options_for_buffer(buffer) |  | ||||||
|     return weechat.WEECHAT_RC_OK |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def bas_signal_buffer_opened_cb(data, signal, signal_data): |  | ||||||
|     global bas_options |  | ||||||
|     buffer = signal_data |  | ||||||
|     timer = weechat.config_integer(bas_options["look_timer"]) |  | ||||||
|     if timer == 0: |  | ||||||
|         bas_apply_options_for_buffer(buffer) |  | ||||||
|     else: |  | ||||||
|         weechat.hook_timer(timer, 0, 1, |  | ||||||
|                            "bas_timer_buffer_opened_cb", |  | ||||||
|                            weechat.buffer_get_string(buffer, "full_name")) |  | ||||||
|     return weechat.WEECHAT_RC_OK |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def bas_config_option_cb(data, option, value): |  | ||||||
|     if not weechat.config_boolean(bas_options["look_instant"]): |  | ||||||
|         return weechat.WEECHAT_RC_OK |  | ||||||
| 
 |  | ||||||
|     if not weechat.config_get(option):  # option was deleted |  | ||||||
|         return weechat.WEECHAT_RC_OK |  | ||||||
| 
 |  | ||||||
|     option = option[len("%s.buffer." % CONFIG_FILE_NAME):] |  | ||||||
| 
 |  | ||||||
|     pos = option.rfind(".") |  | ||||||
|     if pos > 0: |  | ||||||
|         buffer_mask = option[0:pos] |  | ||||||
|         property = option[pos+1:] |  | ||||||
|         if buffer_mask and property: |  | ||||||
|             buffers = weechat.infolist_get("buffer", "", buffer_mask) |  | ||||||
| 
 |  | ||||||
|             if not buffers: |  | ||||||
|                 return weechat.WEECHAT_RC_OK |  | ||||||
| 
 |  | ||||||
|             while weechat.infolist_next(buffers): |  | ||||||
|                 buffer = weechat.infolist_pointer(buffers, "pointer") |  | ||||||
|                 weechat.buffer_set(buffer, property, value) |  | ||||||
| 
 |  | ||||||
|             weechat.infolist_free(buffers) |  | ||||||
| 
 |  | ||||||
|     return weechat.WEECHAT_RC_OK |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # ==================================[ main ]================================== |  | ||||||
| 
 |  | ||||||
| if __name__ == "__main__" and import_ok: |  | ||||||
|     if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, |  | ||||||
|                         SCRIPT_LICENSE, SCRIPT_DESC, "bas_unload_script", ""): |  | ||||||
|         version = weechat.info_get("version_number", "") or 0 |  | ||||||
|         if int(version) < 0x01000000: |  | ||||||
|             weechat.prnt("", "%s%s: WeeChat 1.0 is required for this script." |  | ||||||
|                          % (weechat.prefix("error"), SCRIPT_NAME)) |  | ||||||
|         else: |  | ||||||
|             bas_config_init() |  | ||||||
|             bas_config_read() |  | ||||||
|             weechat.hook_command( |  | ||||||
|                 SCRIPT_COMMAND, |  | ||||||
|                 "Auto-set buffer properties when a buffer is opened", |  | ||||||
|                 "[add buffer property value] | [del option]", |  | ||||||
|                 "     add: add a buffer/property/value in configuration file\n" |  | ||||||
|                 "     del: delete an option from configuration file\n" |  | ||||||
|                 "  buffer: name of a buffer (wildcard \"*\" is allowed)\n" |  | ||||||
|                 "property: buffer property\n" |  | ||||||
|                 "   value: value for property\n" |  | ||||||
|                 "  option: name of option from configuration file\n\n" |  | ||||||
|                 "Examples:\n" |  | ||||||
|                 "  disable timestamp on channel #weechat:\n" |  | ||||||
|                 "    /" + SCRIPT_COMMAND + " add irc.libera.#weechat " |  | ||||||
|                 "time_for_each_line 0\n" |  | ||||||
|                 "  add word \"weechat\" in highlight list on channel " |  | ||||||
|                 "#savannah:\n" |  | ||||||
|                 "    /" + SCRIPT_COMMAND + " add irc.libera.#savannah " |  | ||||||
|                 "highlight_words_add weechat\n" |  | ||||||
|                 "  disable highlights from nick \"mike\" on libera server, " |  | ||||||
|                 "channel #weechat (requires WeeChat >= 0.3.4):\n" |  | ||||||
|                 "    /" + SCRIPT_COMMAND + " add irc.libera.#weechat " |  | ||||||
|                 "hotlist_max_level_nicks_add mike:2\n" |  | ||||||
|                 "  disable hotlist changes for nick \"bot\" on libera " |  | ||||||
|                 "server (all channels) (requires WeeChat >= 0.3.4):\n" |  | ||||||
|                 "    /" + SCRIPT_COMMAND + " add irc.libera.* " |  | ||||||
|                 "hotlist_max_level_nicks_add bot:-1", |  | ||||||
|                 "add %(buffers_plugins_names)|" |  | ||||||
|                 "%(buffer_autoset_current_buffer) " |  | ||||||
|                 "%(buffer_properties_set)" |  | ||||||
|                 " || del %(buffer_autoset_options)", |  | ||||||
|                 "bas_cmd", "") |  | ||||||
|             weechat.hook_completion( |  | ||||||
|                 "buffer_autoset_current_buffer", |  | ||||||
|                 "current buffer name for buffer_autoset", |  | ||||||
|                 "bas_completion_current_buffer_cb", "") |  | ||||||
|             weechat.hook_completion( |  | ||||||
|                 "buffer_autoset_options", |  | ||||||
|                 "list of options for buffer_autoset", |  | ||||||
|                 "bas_completion_options_cb", "") |  | ||||||
|             weechat.hook_signal("9000|buffer_opened", |  | ||||||
|                                 "bas_signal_buffer_opened_cb", "") |  | ||||||
|             weechat.hook_config("%s.buffer.*" % CONFIG_FILE_NAME, |  | ||||||
|                                 "bas_config_option_cb", "") |  | ||||||
| 
 |  | ||||||
|             # apply settings to all already opened buffers |  | ||||||
|             buffers = weechat.infolist_get("buffer", "", "") |  | ||||||
|             if buffers: |  | ||||||
|                 while weechat.infolist_next(buffers): |  | ||||||
|                     buffer = weechat.infolist_pointer(buffers, "pointer") |  | ||||||
|                     bas_signal_buffer_opened_cb("", "", buffer) |  | ||||||
|                 weechat.infolist_free(buffers) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # ==================================[ end ]=================================== |  | ||||||
| 
 |  | ||||||
| def bas_unload_script(): |  | ||||||
|     """ Function called when script is unloaded. """ |  | ||||||
|     global bas_config_file |  | ||||||
| 
 |  | ||||||
|     if bas_config_file: |  | ||||||
|         bas_config_write() |  | ||||||
|     return weechat.WEECHAT_RC_OK |  | ||||||
| @ -1,74 +0,0 @@ | |||||||
| from typing import Iterator, Tuple |  | ||||||
| import weechat |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| SCRIPT_NAME = "fzf" |  | ||||||
| SCRIPT_AUTHOR = "Trygve Aaberge <trygveaa@gmail.com>" |  | ||||||
| SCRIPT_VERSION = "0.1.0" |  | ||||||
| SCRIPT_LICENSE = "MIT" |  | ||||||
| SCRIPT_DESC = "Switch buffer using fzf (currently only works inside tmux)" |  | ||||||
| REPO_URL = "https://github.com/trygveaa/weechat-fzf" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def print_error(message: str) -> None: |  | ||||||
|     weechat.prnt("", weechat.prefix("error") + message) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def fzf_process_cb( |  | ||||||
|     data: str, command: str, return_code: int, out: str, err: str |  | ||||||
| ) -> int: |  | ||||||
|     if return_code == weechat.WEECHAT_HOOK_PROCESS_ERROR or return_code == 2 or err: |  | ||||||
|         print_error("Error running fzf (code {}): {}".format(return_code, err)) |  | ||||||
|         return weechat.WEECHAT_RC_OK |  | ||||||
|     if out != "": |  | ||||||
|         pointer, _ = out.split("\t", 1) |  | ||||||
|         weechat.buffer_set(pointer, "display", "1") |  | ||||||
|     return weechat.WEECHAT_RC_OK |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def fzf_command_cb(data: str, buffer: str, args: str) -> int: |  | ||||||
|     cmd = ( |  | ||||||
|         "fzf-tmux -- --delimiter='\t' --with-nth=3.. " |  | ||||||
|         "--preview='tail -$LINES {2} 2>/dev/null'" |  | ||||||
|     ) |  | ||||||
|     hook = weechat.hook_process_hashtable(cmd, {"stdin": "1"}, 0, "fzf_process_cb", "") |  | ||||||
|     for buffer_info in buffers(): |  | ||||||
|         weechat.hook_set(hook, "stdin", "\t".join(buffer_info) + "\n") |  | ||||||
|     weechat.hook_set(hook, "stdin_close", "") |  | ||||||
|     return weechat.WEECHAT_RC_OK |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def buffers() -> Iterator[Tuple[str, str, str, str]]: |  | ||||||
|     logger_filenames = {} |  | ||||||
|     logger_infolist = weechat.infolist_get("logger_buffer", "", "") |  | ||||||
|     while weechat.infolist_next(logger_infolist): |  | ||||||
|         buffer = weechat.infolist_pointer(logger_infolist, "buffer") |  | ||||||
|         filename = weechat.infolist_string(logger_infolist, "log_filename") |  | ||||||
|         logger_filenames[buffer] = filename |  | ||||||
|     weechat.infolist_free(logger_infolist) |  | ||||||
| 
 |  | ||||||
|     buffer_infolist = weechat.infolist_get("buffer", "", "") |  | ||||||
|     while weechat.infolist_next(buffer_infolist): |  | ||||||
|         pointer = weechat.infolist_pointer(buffer_infolist, "pointer") |  | ||||||
|         number = weechat.infolist_integer(buffer_infolist, "number") |  | ||||||
|         name = weechat.infolist_string(buffer_infolist, "name") |  | ||||||
|         yield (pointer, logger_filenames.get(pointer, ""), str(number), name) |  | ||||||
|     weechat.infolist_free(buffer_infolist) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def main() -> None: |  | ||||||
|     if not weechat.register( |  | ||||||
|         SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", "" |  | ||||||
|     ): |  | ||||||
|         return |  | ||||||
| 
 |  | ||||||
|     tmux = weechat.string_eval_expression("${env:TMUX}", {}, {}, {}) |  | ||||||
|     if not tmux: |  | ||||||
|         print_error("Error: fzf.py currently only supports being run inside tmux") |  | ||||||
|         return |  | ||||||
| 
 |  | ||||||
|     weechat.hook_command(SCRIPT_NAME, SCRIPT_DESC, "", "", "", "fzf_command_cb", "") |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| if __name__ == "__main__": |  | ||||||
|     main() |  | ||||||
							
								
								
									
										760
									
								
								weechat/.weechat/python/signal.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										760
									
								
								weechat/.weechat/python/signal.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,760 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | import weechat | ||||||
|  | import logging | ||||||
|  | import socket | ||||||
|  | import json | ||||||
|  | import os | ||||||
|  | import random | ||||||
|  | import textwrap | ||||||
|  | import datetime | ||||||
|  | 
 | ||||||
|  | """ | ||||||
|  | For completion to work, you need to set option | ||||||
|  | weechat.completion.default_template to include signal_contact_or_group, e.g. | ||||||
|  | 
 | ||||||
|  | %{nicks}|%(irc_channels)|%(signal_contact_or_group) | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | try: | ||||||
|  |     import emoji | ||||||
|  | except ImportError: | ||||||
|  |     emoji = None | ||||||
|  | 
 | ||||||
|  | SCRIPT_NAME = 'signal' | ||||||
|  | SCRIPT_AUTHOR = 'Finn Herzfeld <finn@finn.io>' | ||||||
|  | SCRIPT_VERSION = '0.1' | ||||||
|  | SCRIPT_LICENSE = 'GPL3' | ||||||
|  | SCRIPT_DESC = 'Send and receive messages via Signal with weechat' | ||||||
|  | 
 | ||||||
|  | SCRIPT_COMMAND = 'signal' | ||||||
|  | SCRIPT_BUFFER = 'signal' | ||||||
|  | 
 | ||||||
|  | useragent = "%s v%s by %s" % (SCRIPT_NAME, SCRIPT_VERSION, SCRIPT_AUTHOR) | ||||||
|  | 
 | ||||||
|  | active_line = None | ||||||
|  | highlight = weechat.color("_bold") | ||||||
|  | own_uuid = None | ||||||
|  | 
 | ||||||
|  | def get_groupinfo(dictionary): | ||||||
|  |     groupInfo = None | ||||||
|  |     if 'group' in dictionary.keys(): | ||||||
|  |         groupInfo = dictionary['group'] | ||||||
|  |     elif 'groupV2' in dictionary.keys(): | ||||||
|  |         groupInfo = dictionary['groupV2'] | ||||||
|  |     return groupInfo | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def get_groupid(groupinfo): | ||||||
|  |     if groupinfo is None: | ||||||
|  |         return None | ||||||
|  |     if 'groupId' in groupinfo: | ||||||
|  |         return groupinfo['groupId'] | ||||||
|  |     elif 'id' in groupinfo: | ||||||
|  |         return groupinfo['id'] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def get_groupname(groupinfo): | ||||||
|  |     if 'title' in groupinfo: | ||||||
|  |         return groupinfo['title'] | ||||||
|  |     if 'name' in groupinfo: | ||||||
|  |         return groupinfo['name'] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def get_logfile(): | ||||||
|  |     weechat_dir = weechat.info_get("weechat_data_dir", "") or weechat.info_get("weechat_dir", "") or "~/.weechat" | ||||||
|  |     return os.path.join(os.path.expanduser(weechat_dir), "logs", "signal.log") | ||||||
|  | 
 | ||||||
|  | default_options = { | ||||||
|  |     "socket": "/var/run/signald/signald.sock", | ||||||
|  |     "loglevel": "WARN", | ||||||
|  |     "sentry_dsn": "", | ||||||
|  |     "number": "" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | options = {} | ||||||
|  | buffers = {} | ||||||
|  | 
 | ||||||
|  | callbacks = {} | ||||||
|  | contacts = {} | ||||||
|  | groups = {} | ||||||
|  | 
 | ||||||
|  | signald_hook = None | ||||||
|  | signald_socket = None | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def prnt(text): | ||||||
|  |     logger.info(text) | ||||||
|  |     weechat.prnt("", "signal\t%s" % text) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def show_msg(uuid, group, message, incoming, tags=[]): | ||||||
|  |     identifier = uuid if group is None else group | ||||||
|  |     buf = get_buffer(identifier, group is not None) | ||||||
|  |     name = "Me" | ||||||
|  |     if incoming: | ||||||
|  |         name = contact_name(uuid) | ||||||
|  |         if group is None: | ||||||
|  |             # 1:1 messages are private messages | ||||||
|  |             hotness = weechat.WEECHAT_HOTLIST_PRIVATE | ||||||
|  |             tags.append("notify_private") | ||||||
|  |         else: | ||||||
|  |             # group messages are treated as 'messages' | ||||||
|  |             hotness = weechat.WEECHAT_HOTLIST_MESSAGE | ||||||
|  |         weechat.buffer_set(buf, "hotlist", hotness) | ||||||
|  |     weechat.prnt_date_tags(buf, 0, ",".join(tags),  "%s\t%s" % (name, message)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def contact_name(uuid): | ||||||
|  |     if uuid == options["number"]: | ||||||
|  |         return 'Me' | ||||||
|  |     if uuid in contacts: | ||||||
|  |         name = contacts[uuid]\ | ||||||
|  |                 .get('name', uuid)\ | ||||||
|  |                 .strip() | ||||||
|  |         name = ''.join(x for x in name if x.isprintable()) | ||||||
|  |         return name | ||||||
|  |     else: | ||||||
|  |         return uuid | ||||||
|  | 
 | ||||||
|  | def init_config(): | ||||||
|  |     global default_options, options, logger | ||||||
|  |     logging.basicConfig(filename=get_logfile()) | ||||||
|  |     logger = logging.getLogger("weechat_script") | ||||||
|  |     for option, default_value in default_options.items(): | ||||||
|  |         if not weechat.config_is_set_plugin(option): | ||||||
|  |             weechat.config_set_plugin(option, default_value) | ||||||
|  |         options[option] = weechat.config_get_plugin(option) | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def welcome(version): | ||||||
|  |     prnt("") | ||||||
|  |     prnt("") | ||||||
|  |     if version != "": | ||||||
|  |         prnt("Welcome to Signal Weechat! You're running {name} version {version} ({commit}).".format(**version)) | ||||||
|  |         if len(options['number']) > 0: | ||||||
|  |             subscribe(options['number']) | ||||||
|  |         else: | ||||||
|  |             prnt("To begin, you must register or link to an existing device in signald.") | ||||||
|  |     else: | ||||||
|  |         prnt("You don't have signald running! See https://gitlab.com/thefinn93/signald") | ||||||
|  |     prnt("") | ||||||
|  |     prnt("") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def handle_version(payload): | ||||||
|  |     if "id" not in payload: | ||||||
|  |         welcome(payload) | ||||||
|  |     else: | ||||||
|  |         prnt("Connected to {name} version {version} ({commit})".format(**payload)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def receive(data, fd): | ||||||
|  |     global signald_socket | ||||||
|  |     try: | ||||||
|  |         # awesome. since data is a string, but .recv() gives us bytes (that we | ||||||
|  |         # don't necessarily want to decode, since they may be broken in the | ||||||
|  |         # middle of a unicode character or something), we have to shoehorn | ||||||
|  |         # bytes directly to a string. we use latin1 per: | ||||||
|  |         # https://stackoverflow.com/a/42795285 | ||||||
|  |         # so we can roundtrip every byte | ||||||
|  |         while not data.endswith("\n"): | ||||||
|  |             raw = signald_socket.recv(1).decode('latin1') | ||||||
|  |             if len(raw) == 0: | ||||||
|  |                 logger.info('signald socket disconnected, attempting to reconnect') | ||||||
|  |                 signald_socket.close() | ||||||
|  |                 close_socket() | ||||||
|  |                 init_socket() | ||||||
|  |                 return weechat.WEECHAT_RC_OK | ||||||
|  |             data += raw | ||||||
|  |     except socket.error: | ||||||
|  |         logger.exception("Failed to read from signald.") | ||||||
|  |         close_socket() | ||||||
|  |         init_socket() | ||||||
|  |         return weechat.WEECHAT_RC_OK | ||||||
|  |     logger.debug("Got message from signald: %s", data) | ||||||
|  |     payload = json.loads(data.encode('latin1')) | ||||||
|  |     signald_callbacks = { | ||||||
|  |         "version": handle_version, | ||||||
|  |         "IncomingMessage": message_cb, | ||||||
|  |         "list_contacts": contact_list_cb, | ||||||
|  |         "list_groups": group_list_cb, | ||||||
|  |         "send_results": noop_cb, | ||||||
|  |         "sync_requested": noop_cb, | ||||||
|  |         "listen_started": noop_cb, | ||||||
|  |         "listen_stopped": noop_cb, | ||||||
|  |         "account_refreshed": noop_cb, | ||||||
|  |         "ListenerState": noop_cb, | ||||||
|  |         "send": noop_cb, | ||||||
|  |         "request_sync": noop_cb, | ||||||
|  |         "ExceptionWrapper": noop_cb, | ||||||
|  |         "WebSocketConnectionState": noop_cb, | ||||||
|  |         "get_profile": noop_cb, | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     try: | ||||||
|  |         if "id" in payload and payload["id"] in callbacks: | ||||||
|  |             callback = callbacks.pop(payload["id"]) | ||||||
|  |             callback["func"](payload, *callback["args"], **callback["kwargs"]) | ||||||
|  |         elif payload.get('type') in signald_callbacks: | ||||||
|  |             signald_callbacks[payload.get('type')](payload.get('data')) | ||||||
|  |         else: | ||||||
|  |             prnt("Got unhandled {} message from signald, see debug log for more info".format(payload.get('type'))) | ||||||
|  |             logger.warning("Got unhandled message of type %s from signald", payload.get('type')) | ||||||
|  |     except: | ||||||
|  |         logger.exception("exception while handling payload %s", json.dumps(payload, indent="    ")) | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def send(msgtype, cb=None, cb_args=[], cb_kwargs={}, **kwargs): | ||||||
|  |     global signald_socket | ||||||
|  |     request_id = kwargs.get("request_id", get_request_id()) | ||||||
|  |     payload = kwargs | ||||||
|  |     payload['type'] = msgtype | ||||||
|  |     payload["id"] = request_id | ||||||
|  |     payload["version"] = "v1" | ||||||
|  |     if cb is not None: | ||||||
|  |         callbacks[request_id] = {"func": cb, "args": cb_args, "kwargs": cb_kwargs} | ||||||
|  |     msg = json.dumps(payload) | ||||||
|  |     logger.debug("Sending to signald: %s", msg) | ||||||
|  |     try: | ||||||
|  |         signald_socket.sendall((msg + "\n").encode('utf-8')) | ||||||
|  |     except (BrokenPipeError, OSError): | ||||||
|  |         close_socket() | ||||||
|  |         init_socket() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def subscribe(number): | ||||||
|  |     send("request_sync", account=number) | ||||||
|  |     send("list_contacts", account=number) | ||||||
|  |     send("list_groups", account=number) | ||||||
|  |     send("get_profile", account=number, address={"number": number}, cb=set_uuid) | ||||||
|  |     send("subscribe", account=number, cb=subscribe_cb, cb_kwargs={"number": number}) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def subscribe_cb(payload, number): | ||||||
|  |     prnt("Successfully subscribed to {}".format(number)) | ||||||
|  | 
 | ||||||
|  | def render_message(message): | ||||||
|  |     sticker = message.get('sticker') | ||||||
|  |     if sticker is not None: | ||||||
|  |         return "<sent sticker>" | ||||||
|  |     reaction = message.get('reaction') | ||||||
|  |     if reaction is not None: | ||||||
|  |         name = contact_name(reaction['targetAuthor']['uuid']) | ||||||
|  |         em = reaction["emoji"] | ||||||
|  |         if emoji is not None: | ||||||
|  |             em = emoji.demojize(em) | ||||||
|  |         return "<reacted with {} to a message from {}>".format(em, name) | ||||||
|  |     attachment_msg = "" | ||||||
|  |     attachments = message.get('attachments') | ||||||
|  |     if attachments is not None: | ||||||
|  |         types = [attach['contentType'] for attach in attachments] | ||||||
|  |         filenames = [attach['storedFilename'] for attach in attachments] | ||||||
|  |         attachment_msg = "<sent {}>: \n{}\n\n".format( | ||||||
|  |                 ', '.join(types), | ||||||
|  |                 '\n'.join(filenames)) | ||||||
|  | 
 | ||||||
|  |     quote = message.get('quote') | ||||||
|  |     quote_msg = "" | ||||||
|  |     if quote is not None: | ||||||
|  |         quote_msg = quote['text'] | ||||||
|  |         if quote_msg != "": | ||||||
|  |             wrapper = textwrap.TextWrapper( | ||||||
|  |                 width=64, | ||||||
|  |                 initial_indent="{}> ".format(weechat.color("lightgreen")), | ||||||
|  |                 subsequent_indent="{}> ".format(weechat.color("lightgreen")) | ||||||
|  |             ) | ||||||
|  |             quote_msg = wrapper.fill(weechat.string_remove_color(quote_msg, "")) + "\n" | ||||||
|  | 
 | ||||||
|  |     body = message.get('body', "") | ||||||
|  |     mentions = message.get('mentions', []) | ||||||
|  |     for mention in mentions[::-1]: | ||||||
|  |         mentioned = contact_name(mention["uuid"]) | ||||||
|  |         body = "{first_part}{start_highlight}{name}{stop_highlight}{second_part}".format( | ||||||
|  |                 first_part=body[:mention["start"]], | ||||||
|  |                 start_highlight=weechat.color("lightgreen"), | ||||||
|  |                 name=mentioned, | ||||||
|  |                 stop_highlight=weechat.color("chat"), | ||||||
|  |                 second_part=body[mention["start"] + mention["length"]:]) | ||||||
|  | 
 | ||||||
|  |     if emoji is not None: | ||||||
|  |         body = emoji.demojize(body) | ||||||
|  | 
 | ||||||
|  |     message_string = attachment_msg + quote_msg + body | ||||||
|  |     if message_string.strip() == "": | ||||||
|  |         return None | ||||||
|  |     else: | ||||||
|  |         return message_string | ||||||
|  | 
 | ||||||
|  | def message_cb(payload): | ||||||
|  |     if payload.get('data_message') is not None: | ||||||
|  |         message = render_message(payload['data_message']) | ||||||
|  |         timestamp = get_timestamp(payload) | ||||||
|  |         author = get_author(payload) | ||||||
|  |         tags = [ | ||||||
|  |             "author_{}".format(author), | ||||||
|  |             "timestamp_{}".format(timestamp), | ||||||
|  |         ] | ||||||
|  |         if message is not None: | ||||||
|  |             groupInfo = get_groupinfo(payload['data_message']) | ||||||
|  |             group = get_groupid(groupInfo) | ||||||
|  |             show_msg(payload['source']['uuid'], group, message, True, tags) | ||||||
|  |     elif payload.get('syncMessage') is not None: | ||||||
|  |         # some syncMessages are to synchronize read receipts; we ignore these | ||||||
|  |         if payload['syncMessage'].get('readMessages') is not None: | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  |         # if contactsComplete is present, the contact sync from initial plugin | ||||||
|  |         # load (or someone else triggering a contacts sync on signald) is | ||||||
|  |         # complete, and we should update our contacts list. | ||||||
|  |         if payload['syncMessage'].get('contactsComplete', False): | ||||||
|  |             send("list_contacts", account=options['number']) | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  |         # we don't know how to render anything besides sync messags with actual | ||||||
|  |         # 'sent' info. | ||||||
|  |         if 'sent' not in payload['syncMessage']: | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  |         message = render_message(payload['syncMessage']['sent']['message']) | ||||||
|  |         timestamp = get_timestamp(payload) | ||||||
|  |         author = get_author(payload) | ||||||
|  |         tags = [ | ||||||
|  |             "author_{}".format(author), | ||||||
|  |             "timestamp_{}".format(timestamp), | ||||||
|  |         ] | ||||||
|  |         groupInfo = get_groupinfo(payload['syncMessage']['sent']['message']) | ||||||
|  |         group = get_groupid(groupInfo) | ||||||
|  |         dest = payload['syncMessage']['sent']['destination']['uuid'] if groupInfo is None else None | ||||||
|  |         show_msg(dest, group, message, False, tags) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def noop_cb(payload): | ||||||
|  |     pass | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def contact_list_cb(payload): | ||||||
|  |     global contacts | ||||||
|  | 
 | ||||||
|  |     for contact in payload['profiles']: | ||||||
|  |         uuid = contact['address']['uuid'] | ||||||
|  |         contacts[uuid] = contact | ||||||
|  |         logger.debug("Checking for buffers with contact %s", contact) | ||||||
|  |         if uuid in buffers: | ||||||
|  |             b = buffers[uuid] | ||||||
|  |             name = contact_name(uuid) | ||||||
|  |             set_buffer_name(b, name) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def set_buffer_name(b, name): | ||||||
|  |     logger.info("Setting buffer name to %s", name) | ||||||
|  |     weechat.buffer_set(b, "title", name) | ||||||
|  |     weechat.buffer_set(b, "name", name) | ||||||
|  |     weechat.buffer_set(b, "shortname", name) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def group_list_cb(payload): | ||||||
|  |     global groups | ||||||
|  |     for group in payload.get('groups', []): | ||||||
|  |         groups[get_groupid(group)] = group | ||||||
|  |     for group in payload.get('groupsv2', []): | ||||||
|  |         groups[get_groupid(group)] = group | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def setup_group_buffer(groupId): | ||||||
|  |     global groups | ||||||
|  |     group = groups[groupId] | ||||||
|  |     buffer = get_buffer(groupId, True) | ||||||
|  |     set_buffer_name(buffer, get_groupname(group)) | ||||||
|  |     weechat.buffer_set(buffer, "nicklist", "1") | ||||||
|  |     weechat.buffer_set(buffer, "nicklist_display_groups", "0") | ||||||
|  |     for member in group['members']: | ||||||
|  |         uuid = member['uuid'] | ||||||
|  |         member_name = contact_name(uuid) | ||||||
|  |         entry = weechat.nicklist_search_nick(buffer, "", member_name) | ||||||
|  |         if len(entry) == 0: | ||||||
|  |             logger.debug("Adding %s to group %s", member_name, groupId) | ||||||
|  |             weechat.nicklist_add_nick(buffer, "", member_name, "", "", "", 1) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def buffer_close_cb(identifier, buffer): | ||||||
|  |     del buffers[identifier] | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def get_buffer(identifier, isGroup): | ||||||
|  |     if identifier not in buffers: | ||||||
|  |         cb = "buffer_input_group" if isGroup else "buffer_input" | ||||||
|  |         logger.debug("Creating buffer for identifier %s (%s)", identifier, "group" if isGroup else "contact") | ||||||
|  |         buffers[identifier] = weechat.buffer_new(identifier, cb, identifier, "buffer_close_cb", identifier) | ||||||
|  |         if not isGroup and identifier in contacts: | ||||||
|  |             name = contact_name(identifier) | ||||||
|  |             weechat.buffer_set(buffers[identifier], "localvar_set_type", "private") | ||||||
|  |             set_buffer_name(buffers[identifier], name) | ||||||
|  |         if isGroup: | ||||||
|  |             setup_group_buffer(identifier) | ||||||
|  |         weechat.hook_signal_send("logger_backlog", weechat.WEECHAT_HOOK_SIGNAL_POINTER, buffers[identifier]) | ||||||
|  |     return buffers[identifier] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def encode_message(message): | ||||||
|  |     if emoji is not None: | ||||||
|  |         message = emoji.emojize(message, use_aliases=True) | ||||||
|  |     return message | ||||||
|  | 
 | ||||||
|  | def send_message(uuid, message, **kwargs): | ||||||
|  |     encoded = encode_message(message) | ||||||
|  |     request_id = get_request_id() | ||||||
|  |     show_msg(uuid, None, message, False) | ||||||
|  |     _, message_pointer = get_last_line() | ||||||
|  |     send( | ||||||
|  |         "send", | ||||||
|  |         username=options["number"], | ||||||
|  |         messageBody=encoded, | ||||||
|  |         request_id=request_id, | ||||||
|  |         cb=send_cb, | ||||||
|  |         cb_args=[message_pointer,], | ||||||
|  |         **kwargs | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  | def buffer_input(uuid, buffer, message): | ||||||
|  |     send_message(uuid, message, recipientAddress={"uuid": uuid}) | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | def buffer_input_group(groupId, buffer, message): | ||||||
|  |     send_message(groupId, message, recipientGroupId=groupId) | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | def close_socket(): | ||||||
|  |     global signald_socket | ||||||
|  |     global signald_hook | ||||||
|  | 
 | ||||||
|  |     if signald_socket is not None: | ||||||
|  |         signald_socket.close() | ||||||
|  |     if signald_hook is not None: | ||||||
|  |         weechat.unhook(signald_hook) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def init_socket(): | ||||||
|  |     global signald_socket | ||||||
|  |     global signald_hook | ||||||
|  |     signald_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | ||||||
|  |     try: | ||||||
|  |         signald_socket.connect(options["socket"]) | ||||||
|  |         # weechat really wants the last argument to be a string, but we really | ||||||
|  |         # want it to be bytes. so we end up having to do a bunch of gnarly | ||||||
|  |         # decoding and stuff in receive(). c'est la vie. | ||||||
|  |         signald_hook = weechat.hook_fd(signald_socket.fileno(), 1, 0, 0, 'receive', '') | ||||||
|  |     except Exception: | ||||||
|  |         logger.exception("Failed to connect to signald socket") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def set_log_level(): | ||||||
|  |     level = logging.getLevelName(options['loglevel'].upper()) | ||||||
|  |     logger.setLevel(level) | ||||||
|  |     logger.info("Log level set to %s", logging.getLevelName(level)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def config_changed(data, option, value): | ||||||
|  |     global options | ||||||
|  |     logger.debug('Config option %s changed to %s', option, value) | ||||||
|  |     option = option.split("plugins.var.python.signal.")[-1] | ||||||
|  |     options[option] = value | ||||||
|  |     if option == 'loglevel': | ||||||
|  |         set_log_level() | ||||||
|  |     if option == 'number': | ||||||
|  |         if len(value) == 0: | ||||||
|  |             prnt("Set your number with /set plugins.var.python.signal.number +12024561414") | ||||||
|  |         else: | ||||||
|  |             logger.debug("Number is '%s'", value) | ||||||
|  |             subscribe(value) | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def shutdown(): | ||||||
|  |     logger.info("Shutdown called, closing signald socket") | ||||||
|  |     close_socket() | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def smsg_cmd_cb(data, buffer, args): | ||||||
|  |     identifier = None | ||||||
|  |     if len(args) == 0: | ||||||
|  |         prnt("Usage: /smsg [number | group]") | ||||||
|  |     else: | ||||||
|  |         for uuid in contacts: | ||||||
|  |             if uuid == args or contact_name(uuid).lower() == args.lower(): | ||||||
|  |                 identifier = uuid | ||||||
|  |                 group = None | ||||||
|  |         if not identifier: | ||||||
|  |             for group in groups: | ||||||
|  |                 if get_groupname(groups[group]) == args: | ||||||
|  |                     identifier = group | ||||||
|  |         if identifier: | ||||||
|  |             buf = get_buffer(identifier, group is not None) | ||||||
|  | 
 | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def signal_cmd_cb(data, buffer, args): | ||||||
|  |     if args == 'list groups': | ||||||
|  |         prnt('List of all available Signal groups:') | ||||||
|  |         for group in groups: | ||||||
|  |             prnt(get_groupname(groups[group])) | ||||||
|  |         prnt('') | ||||||
|  |     elif args == 'list contacts': | ||||||
|  |         prnt('List of all available contacts:') | ||||||
|  |         for uuid in contacts: | ||||||
|  |             if contact_name(uuid) != options['number']: | ||||||
|  |                 prnt('{name}, {uuid}\n'.format(name=contact_name(uuid), uuid=uuid)) | ||||||
|  |         prnt('') | ||||||
|  |     elif args.startswith('attach'): | ||||||
|  |         attach_cmd_cb(data, buffer, args.lstrip("attach")) | ||||||
|  |     elif args.startswith('reply'): | ||||||
|  |         reply_cmd_cb(data, buffer, args.lstrip("reply")) | ||||||
|  |     elif args.startswith('up'): | ||||||
|  |         up_cmd_cb(data, buffer, "") | ||||||
|  |     elif args.startswith('down'): | ||||||
|  |         down_cmd_cb(data, buffer, "") | ||||||
|  |     else: pass | ||||||
|  | 
 | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | def get_signal_uuid(buffer): | ||||||
|  |     # check if buffer is a valid signal buffer and can be found in contacts | ||||||
|  |     uuid = [n for n in buffers if buffers[n] == buffer] | ||||||
|  |     if len(uuid) != 1: | ||||||
|  |         prnt("{} uuids for buffer {} found".format(len(uuid), buffer)) | ||||||
|  |         return None | ||||||
|  |     else: | ||||||
|  |         return uuid[0] | ||||||
|  | 
 | ||||||
|  | def attach_cmd_cb(data, buffer, args): | ||||||
|  |     # check if files exist | ||||||
|  |     files = [f.strip() for f in args.split(",")] | ||||||
|  |     for f in files: | ||||||
|  |         if not os.path.exists(f): | ||||||
|  |             prnt('Could not send attachment: file "{}" could not be found'.format(f)) | ||||||
|  |             return weechat.WEECHAT_RC_ERROR | ||||||
|  | 
 | ||||||
|  |     # check if buffer is a valid signal buffer and can be found in contacts | ||||||
|  |     uuid = get_signal_uuid(buffer) | ||||||
|  |     if uuid is None: | ||||||
|  |         prnt('Could not send attachment: buffer {} is no signal'.format(buffer)) | ||||||
|  |         return weechat.WEECHAT_RC_ERROR | ||||||
|  | 
 | ||||||
|  |     # determine if it's a group or contact, | ||||||
|  |     # send files and show confirmation message | ||||||
|  |     if uuid in groups: | ||||||
|  |         send("send", username=options["number"], recipientGroupId=uuid, attachments=files) | ||||||
|  |     else: | ||||||
|  |         send("send", username=options["number"], recipientAddress={"uuid": uuid}, attachments=files) | ||||||
|  | 
 | ||||||
|  |     msg = "sent file(s):\n{}".format(files) | ||||||
|  |     show_msg(uuid, None, msg, False) | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | def completion_cb(data, completion_item, buffer, completion): | ||||||
|  |     for uuid in contacts: | ||||||
|  |         weechat.completion_list_add(completion, contact_name(uuid).lower(), 0, weechat.WEECHAT_LIST_POS_SORT) | ||||||
|  |         weechat.completion_list_add(completion, contact_name(uuid), 0, weechat.WEECHAT_LIST_POS_SORT) | ||||||
|  |     for group in groups: | ||||||
|  |         weechat.completion_list_add(completion, get_groupname(groups[group]).lower(), 0, weechat.WEECHAT_LIST_POS_SORT) | ||||||
|  |         weechat.completion_list_add(completion, get_groupname(groups[group]), 0, weechat.WEECHAT_LIST_POS_SORT) | ||||||
|  | 
 | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | def get_author(payload): | ||||||
|  |     source = payload.get('source', None) | ||||||
|  |     if source is not None: | ||||||
|  |         return source.get('uuid', '') | ||||||
|  |     else: | ||||||
|  |         return '' | ||||||
|  | 
 | ||||||
|  | def get_timestamp(payload): | ||||||
|  |     data_message = payload.get('data_message', None) | ||||||
|  |     if data_message is not None: | ||||||
|  |         return data_message.get('timestamp', '') | ||||||
|  |     else: | ||||||
|  |         return '' | ||||||
|  | 
 | ||||||
|  | def get_tags(line_data): | ||||||
|  |     hdata = weechat.hdata_get("line_data") | ||||||
|  |     tags_count = weechat.hdata_get_var_array_size(hdata, line_data, "tags_array") | ||||||
|  | 
 | ||||||
|  |     tags = [ | ||||||
|  |         weechat.hdata_string(hdata, line_data, "%d|tags_array" % i) | ||||||
|  |         for i in range(tags_count) | ||||||
|  |     ] | ||||||
|  |     return tags | ||||||
|  | 
 | ||||||
|  | def get_last_line(): | ||||||
|  |     hdata = weechat.hdata_get("line_data") | ||||||
|  |     own_lines = weechat.hdata_pointer(weechat.hdata_get("buffer"), weechat.current_buffer(), "own_lines") | ||||||
|  |     if own_lines: | ||||||
|  |         line = weechat.hdata_pointer(weechat.hdata_get("lines"), own_lines, "last_line") | ||||||
|  |         if line: | ||||||
|  |             line_data = weechat.hdata_pointer(weechat.hdata_get("line"), line, "data") | ||||||
|  |             return (line, line_data) | ||||||
|  |     return None | ||||||
|  | 
 | ||||||
|  | def move_active_line(previous=True): | ||||||
|  |     global active_line | ||||||
|  |     if active_line is None: | ||||||
|  |         active_line = get_last_line() | ||||||
|  |         return | ||||||
|  |     other_line = "prev_line" if previous else "next_line" | ||||||
|  |     line, _ = active_line | ||||||
|  |     line = weechat.hdata_pointer(weechat.hdata_get("line"), line, other_line) | ||||||
|  |     if line: | ||||||
|  |         line_data = weechat.hdata_pointer(weechat.hdata_get("line"), line, "data") | ||||||
|  |         active_line = (line, line_data) | ||||||
|  | 
 | ||||||
|  | def active_line_toggle_highlight(on=True): | ||||||
|  |     global active_line | ||||||
|  |     hdata = weechat.hdata_get("line_data") | ||||||
|  |     if active_line is None: | ||||||
|  |         return | ||||||
|  |     line, line_data = active_line | ||||||
|  |     tags = get_tags(line_data) | ||||||
|  |     message = weechat.hdata_string(hdata, line_data, "message") | ||||||
|  |     if "signal_highlight" in tags and on is False: | ||||||
|  |         message = message[len(highlight):] | ||||||
|  |         tags.remove("signal_highlight") | ||||||
|  |     elif "signal_highlight" not in tags and on is True: | ||||||
|  |         message = "{}{}".format(highlight, message) | ||||||
|  |         tags.append("signal_highlight") | ||||||
|  |     weechat.hdata_update(hdata, line_data, {"message": message}) | ||||||
|  |     weechat.hdata_update(hdata, line_data, {"tags_array": ",".join(tags)}) | ||||||
|  | 
 | ||||||
|  | def reset_active_line_cb(data, signal, signal_data): | ||||||
|  |     global active_line | ||||||
|  |     if active_line is None: | ||||||
|  |         return weechat.WEECHAT_RC_OK | ||||||
|  |     active_line_toggle_highlight(on=False) | ||||||
|  |     active_line = None | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | def up_cmd_cb(data, buffer, args): | ||||||
|  |     if get_signal_uuid(buffer) is None: | ||||||
|  |         return weechat.WEECHAT_RC_ERROR | ||||||
|  |     active_line_toggle_highlight(on=False) | ||||||
|  |     move_active_line(previous=True) | ||||||
|  |     active_line_toggle_highlight(on=True) | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | def down_cmd_cb(data, buffer, args): | ||||||
|  |     if get_signal_uuid(buffer) is None: | ||||||
|  |         return weechat.WEECHAT_RC_ERROR | ||||||
|  |     active_line_toggle_highlight(on=False) | ||||||
|  |     move_active_line(previous=False) | ||||||
|  |     active_line_toggle_highlight(on=True) | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | def reply_cmd_cb(data, buffer, args): | ||||||
|  |     hdata = weechat.hdata_get("line_data") | ||||||
|  | 
 | ||||||
|  |     if active_line is None: | ||||||
|  |         prnt("No line for reply selected") | ||||||
|  |         return weechat.WEECHAT_RC_ERROR | ||||||
|  | 
 | ||||||
|  |     line, line_data = active_line | ||||||
|  |     tags = get_tags(line_data) | ||||||
|  |     author = [t for t in tags if t.startswith("author_")] | ||||||
|  |     timestamp = [t for t in tags if t.startswith("timestamp_")] | ||||||
|  |     if len(author) != 1 or len(timestamp) != 1: | ||||||
|  |         prnt("Could not reply: Found {} authors and {} timestamps".format( | ||||||
|  |             len(author), | ||||||
|  |             len(timestamp)) | ||||||
|  |         ) | ||||||
|  |         return weechat.WEECHAT_RC_ERROR | ||||||
|  |     timestamp = timestamp[0].replace("timestamp_", "") | ||||||
|  |     author = author[0].replace("author_", "") | ||||||
|  | 
 | ||||||
|  |     uuid = get_signal_uuid(buffer) | ||||||
|  |     if uuid is None: | ||||||
|  |         prnt('Could not send reply: buffer {} is no signal'.format(buffer)) | ||||||
|  |         return weechat.WEECHAT_RC_ERROR | ||||||
|  | 
 | ||||||
|  |     old_message = weechat.hdata_string(hdata, line_data, "message") | ||||||
|  |     if len(old_message) > 20: | ||||||
|  |         old_message = old_message[:20] + "..." | ||||||
|  |     show_msg(uuid, None, "{}> reply to: {}{}".format( | ||||||
|  |         weechat.color("green"), old_message, weechat.color("chat") | ||||||
|  |     ), False) | ||||||
|  | 
 | ||||||
|  |     quote = { | ||||||
|  |         "id": timestamp, | ||||||
|  |         "author": { | ||||||
|  |             "uuid": author, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if uuid in groups: | ||||||
|  |         send_message( | ||||||
|  |             uuid, | ||||||
|  |             args, | ||||||
|  |             recipientGroupId=uuid, | ||||||
|  |             quote=quote | ||||||
|  |         ) | ||||||
|  |     else: | ||||||
|  |         send_message( | ||||||
|  |             uuid, | ||||||
|  |             args, | ||||||
|  |             recipientAddress={"uuid": uuid}, | ||||||
|  |             quote=quote | ||||||
|  |         ) | ||||||
|  |     return weechat.WEECHAT_RC_OK | ||||||
|  | 
 | ||||||
|  | def get_request_id(): | ||||||
|  |     # returns timestamp in milliseconds, as used by signal | ||||||
|  |     timestamp = str(int(datetime.datetime.now().timestamp() * 1000)) | ||||||
|  |     return "weechat-signal-{}-{}".format(timestamp, random.randint(0, 1000)) | ||||||
|  | 
 | ||||||
|  | def set_uuid(payload): | ||||||
|  |     # set own uuid from get_profile request | ||||||
|  |     global own_uuid | ||||||
|  |     if own_uuid is not None: | ||||||
|  |         return | ||||||
|  |     address = payload['data'].get('address', None) | ||||||
|  |     if address is not None: | ||||||
|  |         if address.get('number', None) == options["number"]: | ||||||
|  |             own_uuid = address.get('uuid', None) | ||||||
|  |             prnt("set own_uuid to {}".format(own_uuid)) | ||||||
|  | 
 | ||||||
|  | def send_cb(payload, line_data): | ||||||
|  |     global own_uuid | ||||||
|  |     hdata = weechat.hdata_get("line_data") | ||||||
|  |     timestamp = payload['data'].get('timestamp', None) | ||||||
|  |     if timestamp is None or own_uuid is None: | ||||||
|  |         return | ||||||
|  |     tags = get_tags(line_data) | ||||||
|  |     tags.append("author_{}".format(own_uuid)) | ||||||
|  |     tags.append("timestamp_{}".format(timestamp)) | ||||||
|  |     weechat.hdata_update(hdata, line_data, {"tags_array": ",".join(tags)}) | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__": | ||||||
|  |     try: | ||||||
|  |         if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, 'shutdown', ''): | ||||||
|  |             weechat.hook_config('plugins.var.python.%s.*' % SCRIPT_NAME, 'config_changed', '') | ||||||
|  |             init_config() | ||||||
|  |             set_log_level() | ||||||
|  |             smsg_help = [ | ||||||
|  |                 "number: the full e164 number (including country code) for the contact", | ||||||
|  |             ] | ||||||
|  |             signal_help = [ | ||||||
|  |                 "contacts: list all contact names and numbers", | ||||||
|  |                 "groups: list all group names", | ||||||
|  |                 "attach: one or multiple comma-separated filenames to send as attachment to the conversation of the active buffer", | ||||||
|  |             ] | ||||||
|  |             logger.debug("Registering command...") | ||||||
|  |             weechat.hook_completion('signal_contact_or_group','Script to complete numbers','completion_cb', '') | ||||||
|  |             weechat.hook_command("smsg", "Open a buffer to message someone (or some group) on signal", "[<number or group name>]", | ||||||
|  |                                  "\n".join(smsg_help), "%(number)", "smsg_cmd_cb", "") | ||||||
|  |             weechat.hook_command("signal", "List contacts or group names, or send attachments", "list [contacts | groups | attach]", | ||||||
|  |                                  "\n".join(signal_help), "%(list)", "signal_cmd_cb", "") | ||||||
|  |             weechat.hook_signal("buffer_switch", "reset_active_line_cb", "") | ||||||
|  |             init_socket() | ||||||
|  |     except Exception: | ||||||
|  |         logger.exception("Failed to initialize plugin.") | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -15,7 +15,7 @@ diff_color = on | |||||||
| diff_command = "auto" | diff_command = "auto" | ||||||
| display_source = on | display_source = on | ||||||
| quiet_actions = on | quiet_actions = on | ||||||
| sort = "i,p,n" | sort = "i,u" | ||||||
| translate_description = on | translate_description = on | ||||||
| use_keys = on | use_keys = on | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -280,7 +280,7 @@ buflist.position = left | |||||||
| buflist.priority = 100 | buflist.priority = 100 | ||||||
| buflist.separator = on | buflist.separator = on | ||||||
| buflist.size = 0 | buflist.size = 0 | ||||||
| buflist.size_max = 20 | buflist.size_max = 23 | ||||||
| buflist.type = root | buflist.type = root | ||||||
| fset.color_bg = default | fset.color_bg = default | ||||||
| fset.color_bg_inactive = default | fset.color_bg_inactive = default | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user