-Музыка

 -Подписка по e-mail

 

 -Поиск по дневнику

Поиск сообщений в Flashr

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 26.02.2007
Записей:
Комментариев:
Написано: 6574


BlogEngine - MultiPost

Вторник, 23 Декабря 2008 г. 16:33 + в цитатник

Как вы знаете, я транслирую свои записи в несколько популярных блогомест в интернете (за исключением ЖЖ). И это я делаю не с помощью встроенных средств копирования постов, а с помощью самописного модуля (Extension) для движка BlogEngine.Net, работающем под ASP.NET. Почему так? Да потому, что часто при задании копирования постов с помощью сторонних средств, таких как трансляции на Ya.ru, посты помещаемые в блог выпадают из поискового индекса и ссылки в них не учитываются.


1) Модуль получился расширяемый, что позволяет дописать копирование постов куда вам только захочется. В вышеуказанный архив я вложил только два класса, которые позволяют копировать посты на Хабр и на Ярушечку. Так как ярушечка имеет херовый интерфейс, и код выглядит очень сложным (и, кстати, не рабовает, если Вы недавно заходили под своим же аккаунтом с другой машины), а также придется добавить следующие строчки в web.config:
  1. <system.net>

  2.    <settings>

  3.      <httpWebRequest useUnsafeHeaderParsing="true" />

  4.      <servicePointManager expect100Continue="false"/>

  5.    </settings>

  6.  </system.net>





2) Далее, в настройках интерфейса у Вас появится такая вот картинка, позволяющая настроить копирование постов:


Отмечу, что все селективные значения прописываются вручную, так как в текущей версии BlogEngine нет возможностей задавать параметр группы настроек модуля в виде выбора из списка. Надеюсь это сделают в следующей версии, которую обещают в конце Января. Итак, первый параметр отвечает за копирование постов (bool=true/false). Второй за название категории, только из которой , если она указана, будут копироваться посты. Третий - BlogType - название класса отвечающего за копирование. Далее логин-пароль в удаленной системе. BlogParam - это дополнительный параметр, который может понадобиться для определенный систем. В частности для Яндекса я передаю номер моего блога, чтобы не извлекать его каждый раз. MaxAttempts(int) - количество попыток кпирования поста, если неуспех, то бросаем это дело. Последний - PostType(Public/Private/OnlyFriends) - тип записи. Как видим, для хабра стоит Private, что означает, что я планирую подредактировать запись и вставить в нее кат, прежде чем делать общедоступной хабрачанцам.


3) Из внутренностей работы модуля рассмотрю класс MultiPost:
  1. namespace MultiPost

  2. {

  3.     /// <summary>

  4.     /// Copy all your posts to blog at http://wow.ya.ru

  5.     /// You have to assign an login and password inside constructor

  6.     /// </summary>

  7.     /// <remarks>

  8.     /// Based on pure code - http://ya.topbot.ru

  9.     /// </remarks>

  10.     [Extension("Copy all your posts to blogs", "0.1.1", "http://ya.topbot.ru")]

  11.     public class MultiPost

  12.     {

  13.         /// <summary>

  14.         /// Name of Module

  15.         /// </summary>

  16.         private static String sExtensionName = "MultiPost";

  17.  

  18.         static protected ExtensionSettings _settings = null;

  19.         /*....*/

  20.     }

  21. }


Как видим к атрибутах класса задаются настройки модуля, чтобы BlogEngine его воспринял как расширение.
Конструктор достаточно простой, подписываемся на событие о размещении нового поста:
  1. static MultiPost()

  2. {

  3.     // create settings object. You need to pass exactly your

  4.     // extension class name (case sencitive)

  5.     ExtensionSettings settings = new ExtensionSettings(sExtensionName);

  6.     /*.......*/

  7.     ExtensionManager.ImportSettings(settings);            

  8.     _settings = ExtensionManager.GetSettings(sExtensionName);

  9.     Post.Saved += new EventHandler<SavedEventArgs>(Post_Saved);

  10. }


И кода происходит новый пост, то обрабатываем его создавая новый поток для этих целей
  1. /// <summary>

  2.  /// Occurs on new post

  3.  /// <remarks>

  4.  /// It opens a new thread and executes

  5.  /// because it takes some time to complete.

  6.  /// </remarks>

  7.  /// </summary>

  8.  private static void Post_Saved(object sender, SavedEventArgs e)

  9.  {

  10.      if (e.Action != SaveAction.Insert)

  11.          return;

  12.  

  13.      IPublishable item = (IPublishable)sender;

  14.  

  15.      //(HttpContext.Current == null || !HttpContext.Current.Request.IsLocal)

  16.      if (item.IsVisible)

  17.      {

  18.          //getting new thread to do all crap

  19.           ThreadPool.QueueUserWorkItem(delegate {

  20.               PostCycle(item);

  21.           });

  22.      }

  23.  }

  24.  

  25.  /// <summary>

  26.  /// Main process to post

  27.  /// </summary>

  28.  /// <param name="item"></param>

  29.  public static void PostCycle(IPublishable item){

  30.      //перечисляем все блоги, что активны...

  31.      DataTable dt = _settings.GetDataTable();

  32.      //pure code, coz i cant change Categories class

  33.      string catsline = "";

  34.      foreach (Category c in item.Categories)

  35.      {

  36.          catsline += c.Title + ",";

  37.      }

  38.      for (int i = dt.Rows.Count - 1; i >= 0; i--)

  39.      {

  40.          SettingsCollection sets = new SettingsCollection(dt.Rows[i].ItemArray);

  41.          if (!sets.Enabled ||

  42.              (!String.IsNullOrEmpty(sets.CopyOnTags.Trim())

  43.              && catsline.Contains(sets.CopyOnTags))

  44.              )

  45.          {//not allowed to post

  46.              dt.Rows.RemoveAt(i);

  47.          }

  48.      }

  49.      //lets finish the others

  50.      for (int i = dt.Rows.Count - 1; dt.Rows.Count > 0; i--)

  51.      {

  52.          Thread.Sleep(5000);

  53.          if (i < 0)//new cycle...bad...bad

  54.          {

  55.              i = dt.Rows.Count;                    

  56.          }

  57.          try

  58.          {

  59.              SettingsCollection sets = new SettingsCollection(dt.Rows[i].ItemArray);

  60.              Type tBlog = Type.GetType("MultiPost.Blogs."+sets.BlogType);

  61.              Object theBlog = Activator.CreateInstance(tBlog,

  62.                  new object[1] { sets });

  63.              Type[] paramTypes = {

  64.                      typeof(IPublishable)

  65.                        };

  66.              Object[] ps = new object[1] { item };

  67.              MethodInfo mDefaults = tBlog.GetMethod("ProcessItem", paramTypes);

  68.              if ((Boolean)mDefaults.Invoke(theBlog, ps))//if success

  69.              {

  70.                  dt.Rows.RemoveAt(i);

  71.              }

  72.              //failed, lets continue

  73.          }

  74.          catch(Exception e)//toomanyattempts

  75.          {

  76.              dt.Rows.RemoveAt(i);

  77.          }

  78.  

  79.      }

  80.  }


В основном цикле, мы создаем объект класса, и вызываем нужную функцию размещения поста, передавая ей настройки. Как видно попытка разместить пост происходит каждые 5 секунд. Обработка объектов идет на объекте Rows, что некрасиво, но просто. Остальное Вы можете найти внутри выложенного архива.
PS: Чтобы иметь возможность править настройки рекомендую заменить компонент admin/Extension Manager/Settings.ascx.cs на файл, вложенный архив. Там исправлена некоторая ошибка в функции редактирования настроек.






http://flashr.ya.ru/replies.xml?item_no=1251
Метки:  

 

Добавить комментарий:
Текст комментария: смайлики

Проверка орфографии: (найти ошибки)

Прикрепить картинку:

 Переводить URL в ссылку
 Подписаться на комментарии
 Подписать картинку