mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 19:02:26 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			55 lines
		
	
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			55 lines
		
	
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/env python3
 | 
						|
import argparse
 | 
						|
import os
 | 
						|
import pathlib
 | 
						|
import sys
 | 
						|
 | 
						|
def main():
 | 
						|
	cli = argparse.ArgumentParser(
 | 
						|
		prog="media-to-borg-patterns",
 | 
						|
		description="""Generate Borg patterns to backup media and emoji files belonging to
 | 
						|
		this instance. You can pass the output to Borg or Borgmatic as a patterns file.
 | 
						|
		
 | 
						|
		For example: gotosocial admin media list-attachments --local-only | media-to-borg-patterns
 | 
						|
		<storage-local-base-path>. You can pass a second argument, the destination file, to
 | 
						|
		write the patterns in. If it's ommitted the patterns will be emitted on stdout
 | 
						|
		instead and you can redirect the output to a file yourself.
 | 
						|
 | 
						|
		For emojis, use gotosocial admin media list-emojis --local-only | media-to-borg-patterns
 | 
						|
		instead.
 | 
						|
		""",
 | 
						|
		epilog="Be gay, do backups. Trans rights!"
 | 
						|
	)
 | 
						|
	cli.add_argument("storageroot", type=pathlib.Path, help="same value as storage-local-base-path in your GoToSocial configuration")
 | 
						|
	cli.add_argument("destination", nargs="?", type=pathlib.Path, help="file to write patterns to, or stdout if ommitted")
 | 
						|
	args = cli.parse_args()
 | 
						|
 | 
						|
	output = open(args.destination, 'w') if args.destination else sys.stdout
 | 
						|
	# Start recursing from the storage root, including the storage root itself
 | 
						|
	output.write("R "+str(args.storageroot)+"\n")
 | 
						|
 | 
						|
	prefixes=set()
 | 
						|
 | 
						|
	for line in sys.stdin:
 | 
						|
		# Skip any log lines
 | 
						|
		if "msg=" in line:
 | 
						|
			continue
 | 
						|
		# Reduce the path to the storage path plus the account ID. By
 | 
						|
		# doing this we can emit path-prefix patterns, one for each account,
 | 
						|
		# instead of a path-file pattern for each file.
 | 
						|
		prefixes.add(os.path.join(*line.split("/")[:-3]))
 | 
						|
 | 
						|
	for prefix in prefixes:
 | 
						|
		# Add a path-prefix, pp:, for each path we want to include.
 | 
						|
		output.write("+ pp:"+os.path.join(os.path.sep, prefix)+"\n")
 | 
						|
 | 
						|
	# Exclude every file and directory under the storage root. This excludes
 | 
						|
	# everything that wasn't matched by any of our prior patterns. This turns
 | 
						|
	# the emitted patterns into an "include only" list.
 | 
						|
	output.write("- "+os.path.join(args.storageroot, "*")+"\n")
 | 
						|
 | 
						|
	if output is not sys.stdout:
 | 
						|
		output.close()
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
	main()
 |