?

Log in

No account? Create an account
Using Python and XMLRPC to post to LJ - LiveJournal Client Discussions — LiveJournal [entries|archive|friends|userinfo]
LiveJournal Client Discussions

[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Using Python and XMLRPC to post to LJ [May. 1st, 2006|04:05 am]
LiveJournal Client Discussions

lj_clients

[fallen_x_ashes]
[mood |curiouscurious]

I'm VERY new at this. (Both to using XMLRPC and Python, infact I wouldn't say I really know what I'm doing, merely coding from imitation and some basic knowledge of the general syntax of most programming languages.) Basically I started doing this when it seemed like the Blogger API had been removed from Livejournal. I couldn't make a post using it. So, I set about altering my application to use the LiveJournal XMLRPC. It's a very quick and dirty hack, I'm passing passwords in the clear essentially. I'm VERY close, it works for LJ.XMLRPC.login, but when I try LJ.XMLRPC.postevent I get the following error message:

XML-RPC Fault: ServerCan't use string ("1") as a HASH ref while "strict refs" in use at /home/lj/cgi-bin/ljprotocol.pl line 2527, [anglebracket]GEN2[anglebracket] line 41.

I added the [anglebracket] thing there. The line number following Gen2 changes with each try, so I'm not sure if it really matters. Here's the Code for the function responsible for creating the post:


def newPostLiveJournal(logger, audioFilePath, cgiAudioFilePath, AuthMethod, LineEndings,
xmlrpcServer, blogID, userName, password, publish, useNewMediaObject, nmoDestPath):
"""Adds a new post to a LiveJournal"""

logger.write('In newPostLiveJournal\n')
logger.flush()
postID = {}
postID['itemid'] = -1
LJEvent = {}
LJEvent['username'] = userName
LJEvent['auth_method'] = AuthMethod
LJEvent['password'] = password
LJEvent['event'] = '

This post was created with PhoneBlogger. ' \
+ 'Click to listen to the ' \
+ 'recorded message.

'
LJEvent['lineendings'] = LineEndings
LJEvent['subject'] = 'Post from PhoneBlogger'
LJEvent['year'] = time.localtime()[0]
LJEvent['mon'] = time.localtime()[1]
LJEvent['day'] = time.localtime()[2]
LJEvent['hour'] = time.localtime()[3]
LJEvent['min'] = time.localtime()[4]
logger.write('Set LJEvent\n')
logger.flush()
try:
postID = xmlrpcServer.LJ.XMLRPC.postevent(LJEvent and xmlrpclib.True or xmlrpclib.False)
except xmlrpclib.Fault, fault:
logger.write('XML-RPC Fault: ' + fault.faultCode + fault.faultString + '\n')
logger.flush()
return postID['itemid']


Does anyone have any ideas as to what could be wrong, or how I can go about debugging this?
linkReply

Comments:
[User Picture]From: fallen_x_ashes
2006-05-02 04:22 am (UTC)

Re: And I have no idea what I'm doing there either.

Argh! The indentation has been stripped! Rest assured that this stuff is being indented as it should, with the first two lines after the try: and except: lines indented.

The problem occurs on logger.write(itemid), the script fails right there.
(Reply) (Parent) (Thread)
[User Picture]From: vulture23
2006-05-02 04:56 am (UTC)

Re: And I have no idea what I'm doing there either.

The move into html (as it gets posted to LJ) will likely eat any leading spaces. This is a common issue when posting Python code. :)

How that would look as an explicit if statement kinda depends on what the intention is. "X and Y or Z" is a well-known Python hack that's intended to emulate C's ternary operator (x ? y : z , if I'm remembering my C syntax correctly). However, it has some gotchas that C doesn't have, and it's really not obvious how it works until the trick has been pointed out to you -- and nonobvious code is dangerous code, because you *will* make mistakes with it sooner or later.

Here, if LJEvent is not an empty dict, then "LJEvent and xmlrpclib.True" evaluates to true, and takes on the value of the second operand. If LJEvent *is* empty, then the 'and' is false and evaluates to LJEvent, at which point "LJEvent or xmlrpclib.False" is evaluated. If we're here, LJEvent is false, so the 'or' evaluates to the second operand. Thus, in any case, "X and Y or Z" will evaluate to either Y or Z, but never X. Your code has this expression as the argument for postevent(), meaning that you will always submit either True or False as an argument, but never LJEvent. I can't guess what was intended by the original author of this code, but... in general this construct is better rendered as:

if X:
....return Y
else:
....return Z

(or using assignment or function call or whatever instead of return.)

Not sure where you're having problems with the itemid -- my LJ xmlrpclib code looks pretty similar at that point, and I haven't had any problems. When it terminates, are you getting a stack trace? If so, copy & paste the whole thing here; there's a lot of useful info in those stack traces.
(Reply) (Parent) (Thread)