BloggerAPI XML RPC.NET desde Mono

Bueno, voy a reescribir el post perdido. Comentaba que esta noche he estado jugando casi de casualidad con XML RPC.NET para acceder a mi blog usando la BloggerAPI, es decir, sin usar el navegador y desde un programa escrito en C#.

Después de buscar información sobre BloggerAPI he encontrado MetaWeblog, un futuro estándar para este tipo de aplicaciones. Por desgracia wordpress no parece entenderlo correctamente a pesar de estar soportado, asi que decidí decantarme por intentar usar BloggerAPI.

Las librerias XML RPC.NET no me compilaron a la primera y tuve que hacer una pequeña modificación del archivo “src/XmlRpcAsyncResult.cs”, la linea 163 cambié “userCallback.Invoke(this);” por “userCallback(this);” y a continuación compile ejecutando desde el directorio “src/”: mcs /target:library /out:CookComputing.XmlRpc.dll *.cs -r System.Web.dll -r System.Web.Services. Esto genera el archivo CookComputing.XmlRpc.dll el cual lo copié a otro directorio donde crearia las clases C# para poder hacer las pruebas.

A continuación miré como hacer un cliente usando XML RPC e implementé una clase que permite acceder a blogs usando BloggerAPI desde C#. Es bastante sencillo ya que me funciono la primera llamada (newPost) a la primera. La clase en cuestión la tengo en el fichero BloggerApi.cs (sólo estan testeadas las funciones newPost y getRecentPosts):

Actualización Corregido pequeño error en el código test producido al copiar/pegar y añadida la sentencia de como compilar el código.

using System;
using CookComputing.XmlRpc;

struct blog {
   public string url;
   public string blogid;
   public string blogName;
}
                                                                                                      
struct user {
   public string nickname;
   public string userid;
   public string url;
   public string email;
   public string lastname;
   public string firstname;
}
                                                                                                      
struct post {
   public string userid;
   public DateTime dateCreated;
   public string content;
   public string postid;
}
                                                                                                      
struct postList{
   public string authorName;
   public string userid;
   public DateTime dateCreated;
   public string content;
   public string postid;
   public string category;
}
                                                                                                      
                                                                                                      
//[XmlRpcUrl("http://saturno/~marble/marblestation/blog/xmlrpc.php")]
class BloggerApi: XmlRpcClientProtocol {
                                                                                                      
   [XmlRpcMethod("blogger.newPost")]
   public string newPost(string appkey, string blogid, string username, string password, string content, bool publish) {
      return (string)Invoke("newPost", new Object[]{appkey, blogid, username, password, content, publish});
   }
                                                                                                      
   [XmlRpcMethod("blogger.editPost")]
   public string editPost(string appkey, string postid, string username, string password, string content, bool publish) {
      return (string)Invoke("editPost", new Object[]{appkey, postid, username, password, content, publish});
   }
                                                                                                      
   [XmlRpcMethod("blogger.getUsersBlogs")]
   public blog[] getUsersBlog(string appkey, string username, string password) {
      return (blog [])Invoke("getUsersBlogs", new Object[]{appkey, username, password});
   }
   [XmlRpcMethod("blogger.getUserInfo")]
   public user getUserInfo(string appkey, string username, string password) {
      return (user)Invoke("getUserInfo", new Object[]{appkey, username, password});
   }
                                                                                                      
   [XmlRpcMethod("blogger.getTemplate")]
   public string getTemplate(string appkey, string blogid, string username, string password, string templateType) {
      return (string)Invoke("getTemplate", new Object[]{appkey, blogid, username, password, templateType});
   }
                                                                                                      
   [XmlRpcMethod("blogger.setTemplate")]
   public bool setTemplate(string appkey, string blogid, string username, string password, string template, string templateType) {
      return (bool)Invoke("setTemplate", new Object[]{appkey, blogid, username, password, template, templateType});
   }
   // Extra wordpress
                                                                                                      
   // unknown, newcontent & publish => ignored
   [XmlRpcMethod("blogger.deletePost")]
   public bool deletePost(bool unknown, string postid, string username, string password, string newcontent, bool publish) {
      return (bool)Invoke("deletePost",new Object[]{unknown, postid, username, password, newcontent, publish});
   }
                                                                                                      
   // 5 element?
   [XmlRpcMethod("blogger.getPost")]
   public post getPost(string appkey, string postid, string username, string password){
      return (post)Invoke("getPost", new Object[]{appkey, postid, username, password});
   }
                                                                                                      
   [XmlRpcMethod("blogger.getRecentPosts")]
   public postList[] getRecentPosts(string appkey, string blogid, string username, string password, int numposts){
      return (postList[])Invoke("getRecentPosts", new Object[]{appkey, blogid, username, password, numposts});
   }
}

A continuación cree un archivo de prueba que usase la clase BloggerApi:

using System;
                                                                                                      
class Test {
   public static void Main() {
      string appkey = "";
      BloggerApi blogger = new BloggerApi();
      blogger.Url = "http://saturno/~marble/marblestation/blog/xmlrpc.php";
      postList[] list = blogger.getRecentPosts(appkey, "0", "user", "secret", 20);
      foreach(postList p in list) {
         Console.WriteLine("{0}", p.content);
      }
   }
}

La compilación se realiza con: “mcs /out:test.exe *.cs /r:CookComputing.XmlRpc.dll”. Esto genera un ejecutable llamado test.exe. Tambien podriamos compilar el BloggerApi.cs como libreria con “mcs /t:library BloggerApi.cs” y despues compilar el test con “mcs test.cs /r:CookComputing.XmlRpc.dll /r:BloggerApi.dll”.

Para depurar las únicas 2 funciones que he testeado (me falta tiempo) he usado el sniffer etherreal. Una de las cosas que pueden hacer que se produzca una excepción es que tengamos apache configurado para que muestre los errores/warnings en el output de las páginas web, ya que por lo visto en la ejecución de xmlrpc.php salen un par de warnings que destrozan la devolución del resultado de la llamada XML RPC.

No se como evolucionará este código que he implementado, de hecho no tengo tiempo para dedicarme intensamente ya que tengo muchas cosas que hacer de la uni y de los cursos de software libre. Eso si, me lo he pasado bien mientras jugaba 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *