s3scrot.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import subprocess
  2. import shlex
  3. import ConfigParser
  4. import tempfile
  5. import os, os.path
  6. import uuid
  7. import argparse
  8. import subprocess
  9. import webbrowser
  10. from boto.s3.connection import S3Connection
  11. from boto.s3.key import Key
  12. try:
  13. use_libnotify = True
  14. from gi.repository import Notify
  15. Notify.init('s3scrot')
  16. except ImportError:
  17. use_libnotify = False
  18. # Default config file to write to ~/.s3scrot:
  19. default_config = """# s3scrot config file
  20. #
  21. # Enter your S3 bucket information and credentials below.
  22. # It's recommended that you create a bucket and access key specifically for
  23. # s3scrot and never use your root AWS keys. That way if these keys get stolen
  24. # they will only have access to your screenshot bucket.
  25. #
  26. # You can create a new bucket and access key through the AWS console:
  27. # https://console.aws.amazon.com - select the IAM console, and create a new group,
  28. # call it whatever you like, and add a Custom Policy to limit it's access to just
  29. # the screenshot bucket. If your bucket is called foobar-screenshots, an example
  30. # Custom Policy would look like:
  31. #
  32. # {
  33. # "Statement": [
  34. # {
  35. # "Action": "s3:*",
  36. # "Effect": "Allow",
  37. # "Resource": [
  38. # "arn:aws:s3:::foobar-screenshots",
  39. # "arn:aws:s3:::foobar-screenshots/*"
  40. # ]
  41. # }
  42. # ]
  43. # }
  44. #
  45. # Create a new user and assign him to the group you created. Be sure to enter the
  46. # access key and secret key for this user below :
  47. [s3]
  48. bucket = YOUR_BUCKET
  49. access_key = YOUR_ACCESS_KEY
  50. secret_key = YOUR_SECRET_KEY
  51. """
  52. def read_config(config_path=None):
  53. if not config_path:
  54. config_path = os.path.join(os.path.expanduser("~"), '.s3scrot')
  55. if not os.path.exists(config_path):
  56. print("Config file not found.")
  57. with open(config_path, "w") as f:
  58. f.write(default_config)
  59. os.chmod(config_path, 0o600)
  60. print("New config file created at {config_path}. You must edit this file with your own Amazon S3 settings.".format(**locals()))
  61. exit(1)
  62. config = ConfigParser.ConfigParser()
  63. config.read(config_path)
  64. # Validate config:
  65. sections = ['s3']
  66. fields = ['bucket', 'access_key', 'secret_key']
  67. validated = {}
  68. for s in sections:
  69. validated[s] = {}
  70. for f in fields:
  71. try:
  72. validated[s][f] = config.get('s3', f)
  73. except ConfigParser.NoOptionError:
  74. print("Config file ({config_path}) is missing required field: {f}".format(**locals()))
  75. print("See comments in the config file for more details.")
  76. exit(1)
  77. except ConfigParser.NoSectionError:
  78. print("Config file({config_path}) is missing section: s3".format(**locals()))
  79. print("See comments in the config file for more details.")
  80. exit(1)
  81. if validated['s3']['bucket'] == "YOUR_BUCKET":
  82. print("You still need to edit your config file with your Amazon S3 settings: {config_path}".format(**locals()))
  83. exit(1)
  84. return validated
  85. def take_screenshot(non_interactive=False, img_format='png', quality='75'):
  86. """Take a screenshot with the scrot tool. Return the path of the screenshot.
  87. If non_interactive==True, capture the whole screen, rather than a mouse selection"""
  88. select = "-s"
  89. if non_interactive:
  90. select = ""
  91. quality = "-q {quality}".format(quality=quality)
  92. ss = tempfile.mktemp("."+img_format)
  93. proc = subprocess.Popen(shlex.split("scrot {select} {quality} {ss}".format(**locals())))
  94. proc.communicate()
  95. return ss
  96. def upload_to_s3(path, config):
  97. conn = S3Connection(config['s3']['access_key'], config['s3']['secret_key'])
  98. bucket = conn.get_bucket(config['s3']['bucket'])
  99. key = Key(bucket, str(uuid.uuid1())+"."+path.split(".")[-1])
  100. key.set_contents_from_filename(path)
  101. key.set_canned_acl('public-read')
  102. return key.generate_url(0, query_auth=False, force_http=True)
  103. def copy_to_clipboard(text):
  104. c = subprocess.Popen(shlex.split("xclip -selection clipboard"), stdin=subprocess.PIPE)
  105. c.communicate(input=text.encode('utf-8'))
  106. def main():
  107. parser = argparse.ArgumentParser(description='s3scrot')
  108. parser.add_argument('-n', '--non-interactive', dest='non_interactive',
  109. action="store_true",
  110. help='Capture the whole screen, don\'t wait for mouse selection')
  111. parser.add_argument('-c', '--no-clipboard', dest='no_clipboard',
  112. action="store_true",
  113. help='Do not copy URL to clipboard')
  114. parser.add_argument('-b', '--open-browser', dest='open_browser',
  115. action="store_true",
  116. help='Open browser to screenshot URL')
  117. parser.add_argument('-p', '--print-url', dest='print_url',
  118. action="store_true",
  119. help='Print URL')
  120. parser.add_argument('-j', '--jpeg', dest='use_jpeg',
  121. action="store_true",
  122. help='Use JPEG compression instead of PNG')
  123. parser.add_argument('-q', '--quality', dest='quality',
  124. default='75',
  125. help='Image quality (1-100) high value means high size, low compression. Default: 75. For lossless png, low quality means high compression.')
  126. args = parser.parse_args()
  127. img_format = "png"
  128. if args.use_jpeg:
  129. img_format = "jpg"
  130. config = read_config()
  131. ss = take_screenshot(args.non_interactive, img_format, args.quality)
  132. url = upload_to_s3(ss, config)
  133. os.remove(ss)
  134. if not args.no_clipboard:
  135. copy_to_clipboard(url)
  136. notification = Notify.Notification.new("s3scrot","Screenshot URL copied to clipboard","network-transmit")
  137. notification.show()
  138. if args.open_browser:
  139. webbrowser.open(url)
  140. if args.print_url:
  141. print(url)
  142. if __name__ == "__main__":
  143. main()