From fe208339288ea96a6d9fe6cd46b52c7775cb5823 Mon Sep 17 00:00:00 2001 From: Ian Adam Naval Date: Thu, 22 May 2014 04:34:23 -0700 Subject: [PATCH] Initial commit --- .gitignore | 2 + README.md | 1 + daemon.py | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++ filesd.py | 93 +++++++++++++++++++++++++++++++++++++ main.py | 93 +++++++++++++++++++++++++++++++++++++ shutdown.sh | 3 ++ startup.sh | 3 ++ 7 files changed, 324 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 daemon.py create mode 100755 filesd.py create mode 100644 main.py create mode 100755 shutdown.sh create mode 100755 startup.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17ce5e8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +screenshots/ +*.pyc diff --git a/README.md b/README.md new file mode 100644 index 0000000..40cfebe --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +This is a place for me to make my screenshots public. diff --git a/daemon.py b/daemon.py new file mode 100644 index 0000000..f371720 --- /dev/null +++ b/daemon.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python + +import sys, os, time, atexit +from signal import SIGTERM + +class Daemon: + """ + A generic daemon class. + + Usage: subclass the Daemon class and override the run() method + """ + def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): + self.stdin = stdin + self.stdout = stdout + self.stderr = stderr + self.pidfile = pidfile + + def daemonize(self): + """ + do the UNIX double-fork magic, see Stevens' "Advanced + Programming in the UNIX Environment" for details (ISBN 0201563177) + http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 + """ + try: + pid = os.fork() + if pid > 0: + # exit first parent + sys.exit(0) + except OSError, e: + sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) + sys.exit(1) + + # decouple from parent environment + os.chdir("/") + os.setsid() + os.umask(0) + + # do second fork + try: + pid = os.fork() + if pid > 0: + # exit from second parent + sys.exit(0) + except OSError, e: + sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) + sys.exit(1) + + # redirect standard file descriptors + sys.stdout.flush() + sys.stderr.flush() + si = file(self.stdin, 'r') + so = file(self.stdout, 'a+') + se = file(self.stderr, 'a+', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + + # write pidfile + atexit.register(self.delpid) + pid = str(os.getpid()) + file(self.pidfile,'w+').write("%s\n" % pid) + + def delpid(self): + os.remove(self.pidfile) + + def start(self): + """ + Start the daemon + """ + # Check for a pidfile to see if the daemon already runs + try: + pf = file(self.pidfile,'r') + pid = int(pf.read().strip()) + pf.close() + except IOError: + pid = None + + if pid: + message = "pidfile %s already exist. Daemon already running?\n" + sys.stderr.write(message % self.pidfile) + sys.exit(1) + + # Start the daemon + self.daemonize() + self.run() + + def stop(self): + """ + Stop the daemon + """ + # Get the pid from the pidfile + try: + pf = file(self.pidfile,'r') + pid = int(pf.read().strip()) + pf.close() + except IOError: + pid = None + + if not pid: + message = "pidfile %s does not exist. Daemon not running?\n" + sys.stderr.write(message % self.pidfile) + return # not an error in a restart + + # Try killing the daemon process + try: + while 1: + os.kill(pid, SIGTERM) + time.sleep(0.1) + except OSError, err: + err = str(err) + if err.find("No such process") > 0: + if os.path.exists(self.pidfile): + os.remove(self.pidfile) + else: + print str(err) + sys.exit(1) + + def restart(self): + """ + Restart the daemon + """ + self.stop() + self.start() + + def run(self): + """ + You should override this method when you subclass Daemon. It will be called after the process has been + daemonized by start() or restart(). + """ diff --git a/filesd.py b/filesd.py new file mode 100755 index 0000000..f095308 --- /dev/null +++ b/filesd.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python2 + +import gtk +import pygtk +import time +import sys +from os import listdir as ls, rename +from os.path import exists, isfile, join, splitext +from random import choice +from string import ascii_letters, digits +from subprocess import call +from daemon import Daemon +pygtk.require('2.0') + + +# Config +SSH_PORT = 22 +PATH = "/home/ian/Pictures" +BASE_URL = "http://files.ianonavy.com/" +SCP_PATH = "files.ianonavy.com:sites/ianonavy.com/files" +WAIT_INTERVAL = 1 + + +class FilesDaemon(Daemon): + + def run(self): + """ + Constantly loops checking for a new file. It's not very efficient, but + it gets the job done. + + """ + + print "Loading list of all files..." + # Get list of all files. + files = [f for f in ls(PATH) if isfile(join(PATH, f))] + print "Done! Waiting for some new files." + + while 1: + for f in ls(PATH): + filename = join(PATH, f) # Get the full file path. + + if isfile(filename): + if f not in files: + #print f, files + + base, extension = splitext(f) + new_filename = self.random_filename(extension=extension) + rename(filename, join(PATH, new_filename)) + files.append(new_filename) + + self.upload(join(PATH, new_filename)) + image_url = "%s%s" % (BASE_URL, new_filename) + self.copy_to_clipboard(image_url) + + time.sleep(WAIT_INTERVAL) + + def upload(self, filename): + """ Uploads a file to the remote host. """ + print "scp -P %d %s %s" % (SSH_PORT, filename, SCP_PATH) + call("scp -P %d %s %s" % (SSH_PORT, filename, SCP_PATH), shell=True) + + def copy_to_clipboard(self, text): + """ Copies the passed argument to the clipboard. """ + clipboard = gtk.clipboard_get() + clipboard.set_text(text) + clipboard.store() # Let other programs use it. + + def random_filename(self, length=4, extension='', attempts=10): + """ Generates a random filename and verifies that it doesn't exist. """ + chars = ''.join([ascii_letters, digits]) + for attempt in range(attempts): + filename = ''.join([choice(chars) for i in range(length)]) + filename = filename + extension + if not exists(filename): + return filename + + +if __name__ == "__main__": + daemon = FilesDaemon('/tmp/filesd.pid') + if len(sys.argv) == 2: + if 'start' == sys.argv[1]: + daemon.start() + elif 'stop' == sys.argv[1]: + daemon.stop() + elif 'restart' == sys.argv[1]: + daemon.restart() + else: + print "Unknown command" + sys.exit(2) + sys.exit(0) + else: + print "usage: %s {start|stop|restart}" % sys.argv[0] + sys.exit(2) diff --git a/main.py b/main.py new file mode 100644 index 0000000..fd1869b --- /dev/null +++ b/main.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +import gtk +import pygtk +import time +import sys +from daemon import Daemon +from subprocess import call +from random import choice +from string import ascii_letters, digits +from os import listdir as ls, rename +from os.path import exists, isfile, join, splitext +pygtk.require('2.0') + + +# Config +SSH_PORT = 1337 +PATH = "/home/ian/Dropbox/projects/files/screenshots" +BASE_URL = "http://files.ianonavy.com/" +SCP_PATH = "vpn.ianonavy.com:sites/ianonavy.com/files" +WAIT_INTERVAL = 1 + + +class FilesDaemon(Daemon): + + def run(self): + """ + Constantly loops checking for a new file. It's not very efficient, but + it gets the job done. + + """ + + print "Loading list of all files..." + # Get list of all files. + files = [f for f in ls(PATH) if isfile(join(PATH, f))] + print "Done! Waiting for some new files." + + while 1: + for f in ls(PATH): + filename = join(PATH, f) # Get the full file path. + + if isfile(filename): + if f not in files: + #print f, files + + base, extension = splitext(f) + new_filename = self.random_filename(extension=extension) + rename(filename, join(PATH, new_filename)) + files.append(new_filename) + + self.upload(join(PATH, new_filename)) + image_url = "%s%s" % (BASE_URL, new_filename) + self.copy_to_clipboard(image_url) + + time.sleep(WAIT_INTERVAL) + + def upload(self, filename): + """ Uploads a file to the remote host. """ + print "scp -P %d %s %s" % (SSH_PORT, filename, SCP_PATH) + call("scp -P %d %s %s" % (SSH_PORT, filename, SCP_PATH), shell=True) + + def copy_to_clipboard(self, text): + """ Copies the passed argument to the clipboard. """ + clipboard = gtk.clipboard_get() + clipboard.set_text(text) + clipboard.store() # Let other programs use it. + + def random_filename(self, length=4, extension='', attempts=10): + """ Generates a random filename and verifies that it doesn't exist. """ + chars = ''.join([ascii_letters, digits]) + for attempt in range(attempts): + filename = ''.join([choice(chars) for i in range(length)]) + filename = filename + extension + if not exists(filename): + return filename + + +if __name__ == "__main__": + daemon = FilesDaemon('/tmp/filesd.pid') + if len(sys.argv) == 2: + if 'start' == sys.argv[1]: + daemon.start() + elif 'stop' == sys.argv[1]: + daemon.stop() + elif 'restart' == sys.argv[1]: + daemon.restart() + else: + print "Unknown command" + sys.exit(2) + sys.exit(0) + else: + print "usage: %s {start|stop|restart}" % sys.argv[0] + sys.exit(2) diff --git a/shutdown.sh b/shutdown.sh new file mode 100755 index 0000000..db94e9a --- /dev/null +++ b/shutdown.sh @@ -0,0 +1,3 @@ +#/bin/bash +kill `pgrep -f "python main.py"` +kill `pgrep -f "ssh -nNR 52398:localhost:52398 -p 1337 ian@208.110.86.98"` diff --git a/startup.sh b/startup.sh new file mode 100755 index 0000000..cca289f --- /dev/null +++ b/startup.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd "$( dirname "${BASH_SOURCE[0]}" )" +python main.py >/dev/null &