Wikipaste

What it does

It sends your graphical clipboard data to your wiki and copies a now valid {{attachment:...}} line to your clipboard so you can paste it in your wiki.

So now you can:

  1. take a screenshot and store it on your clipboard
  2. run wikipaste
  3. paste from the clipboard the wiki embed code in your moin editing session!

This might also help when migrating documents which contain images like word documents:

  1. copy the image from the source document
  2. run wikipaste
  3. paste the embed code in the wiki page where you are migrating the document.

Or, you could use this to locally store images you find on the web and not be depending on the original website to host them for eternity.

How it works

First it will try to find graphical clipboard data and if found will store that in a temporary PNG file, upload that file to your wiki using remote procedure calling and it will print the resulting wiki embed attachment text as well as start clip on windows to copy this text to your clipboard.

Requirements

Hints/configuration

Disclaimer and license

Though i have done my best to write clean code, it isn't. In fact, it's a bunch of code munched together in a few minutes to get it working and i didn't do any thing afterwards to improve it. You can use it as it is, it has the GPL2+ license applied (in accordance with Moin itself) and you are free to use it on your own risk. Don't shoot or sue me if it brakes anything, be aware. But it's GPL2+, so you can check to validate it, or improve when you have the time and patience. Feel free to reuse and republish but leave my name somewhere in your product and code. Also, in addition, i'd love to see a line here or in my mailbox when you do anything with it.

Leave me a note

The code

# VERSIE 1.0
# 2012-10-25
# Copyright Remco Boerma, Drenthecollege.nl
# GPL2+ license applies
#
from PIL import ImageGrab
import random, os.path, os, xmlrpclib


class CONFIG(object):
    verbose = False
    username = 'srvcMoinhulpproces'
    password = 'somethingverydifficult'
    url = "http://your-server-here/?action=xmlrpc2"
    retrycount = 5
    retrysleep = 1 

class Server(object):
    "A Server proxy for the xmlrpc with user validation and multicall."
    def __init__(self, url, username, password):
        self.url = url
        self.username = username
        self.password = password
        self.auth_token = None
        self.proxy = xmlrpclib.ServerProxy(self.url,
                                           allow_none = True,
                                           verbose = CONFIG.verbose)
        self.auth_token = self.get_auth_token()
        self.cached_calls = []
        
    def get_auth_token(self):
        if self.auth_token:
            # we're done
            return
        retry = 0
        while retry <CONFIG.retrycount:
            try:
                return self.proxy.getAuthToken(self.username,self.password)
            except xmlrpclib.ProtocolError:
                retry += 1
                time.sleep(CONFIG.retrysleep)
        raise Exception,'Problem connecting'

    def get_multi_call(self):
        mc = xmlrpclib.MultiCall(self.proxy)
        mc.applyAuthToken(self.auth_token)
        return mc

    def call(self,method,params=()):
        # get a new multicall
        mc = self.get_multi_call()
        # create a new call and evalute it to place the call in the
        # multicall queue
        #eval('mc.'+method+repr(params))
        callable_method = getattr(mc,method)
        callable_method(*params)
        # apply the call
        retry = 0
        result = None
        while retry <5:
            try:
                result = mc()
                retry = 10
            except xmlrpclib.ProtocolError:
                print '#fail'
                retry += 1
                time.sleep(1)
        if result: 
            # get the results, iterate over the results
            result = [x for x in result]
            # result 0 is success or not
            # result 1 is the result of the cal
            return result[1]
        else:
            return None

    def flush_cached_calls(self):
        # get a new multicall
        mc = self.get_multi_call()
        # create a new call and evaluate it to place the call in the
        # multicall queue, do this for all cached calls
        for method,params in self.cached_calls:
            eval('mc.'+method+repr(params))
        # apply the call
        retry = 0
        result = None
        while retry <5:
            try:
                result = mc()
                retry = 10
            except xmlrpclib.ProtocolError:
                print '#fail'
                retry += 1
                time.sleep(1)
        self.cached_calls = []
        if result: 
            # get the results, iterate over the results
            result = [x for x in result]
            # result 0 is success or not
            # result 1 is the result of the cal
            return result[1]
        else:
            return None        

    def searchPages(self, query):
        return self.call('searchPages',(query, ))

    def getPage(self, pagename):
        return self.call('getPage', (pagename, ))

    def putAttachment(self,pagename, attachname, payload):
        return self.call('putAttachment',
                         (pagename,
                          attachname,
                          xmlrpclib.Binary(payload) ))

    def putPage(self,pagename, patched):
        return self.cached_call('putPage',(pagename, patched))

    def cached_call(self, name, params):
        self.cached_calls.append((name, params))

## this is where the fun starts

def main():
    filename = grab_clipboard()
    if not filename:
        print 'No image data found on the clipboard'
        return
    wikiembedcode = send_image(filename)
    print wikiembedcode
    os.system('echo %s | clip.exe' % wikiembedcode)
    
def send_image(filename):
    if CONFIG.verbose:
        print 'Using username:',CONFIG.username
    server = Server(CONFIG.url, CONFIG.username, CONFIG.password)
    print filename
    attachname = os.path.split(filename)[-1]
    f = open(filename,'rb')
    payload = f.read()
    f.close()
    server.putAttachment('Attachments',attachname,payload)
    os.unlink(filename)
    return '{{attachment:Attachments/%s}}' % attachname 
    
def grab_clipboard():
    image = ImageGrab.grabclipboard()
    if image is None:
        return 
    rnd = 100000000000000000000
    fname = os.path.join(os.environ['temp'],str(random.randint(rnd,rnd*10-1))+'.png')
    print fname
    image.save(fname,'PNG')
    return fname
    

if __name__== '__main__':
    main()        

MoinMoin: RemcoBoerma/WikiPaste (last edited 2013-07-16 15:13:00 by 195)