PsTwit.ps1

Есть такая интересная система микро-блогов – Twitter. Я периодически ею пользуюсь, но постоянно обновлять страницу twitter.com/home – надоедает. А добавлять в общий RSS ридер эту штуку жирновато будет – всё таки мини блоги🙂 Для Twitter’а вообще есть много всевозможных клиентов, но я не нашел такого чтобы понравился мне по всем параметрам, и поэтому написал своего🙂 На PowerShell🙂

Он выводит свежие сообщения с помощью уведомления в трее🙂

PSTwitter

Разумеется у него есть контекстное меню🙂

PSTwitter_menu

Можно вывести последние записи в виде списка. Двойной щелчок на записи откроет её в Internet Explorer.

PSTwitter_list

Ну и следующие фичи:

  • В PowerShell 2.0 можно запускать в невидимом окне PowerShell. То есть просто сделать ярлык со строкой:
    powershell -NoProfile -WindowStyle Hidden -File c:\pstwit.ps1
    В 1.0 скрыть окно командной строки будет сложнее, но тоже возможно. Напишу об этом как-нибудь в другой раз🙂
  • При первом запуске запрашивается пароль для подключения к твиттеру. Затем он сохраняется в реестре в зашифрованном виде, и при следующем запуске расшифровывается.
  • Можно указать учетные данные для подключения к прокси-серверу. Для этого нужно просто дописать к командной строке ключ –proxy (get-credential) и сценарий их запросит. Я решил не делать автосохранения, но желающие смогут это сделать на основе кода сохраняющего пароль твиттера.
  • Запуск нескольких экземпляров для проверки разных учеток на твиттере – надо просто при запуске указать в качестве аргумента другое имя журнала, ну и можно другой значок. Все настройки будут сохраняться в реестре отдельно.
  • Интервал проверки ленты, и время отображения новых сообщений настраиваются с помощью переменных $Interval и $NotifyTimeout в блоке param. Ну и конечно их можно задать как параметры при вызове сценария.
  • Вообще сценарий является просто простеньким RSS ридером, так что при желании его можно адаптировать для слежения за любым RSS каналом. В частности я, возможно попробую приспособить его для чтения http://home.live.com/whatsnew.aspx но уже не в этот раз😉

Текст сценария ниже, и на всякий случай еще в виде файла. UPD: брать только из файла, wordpress так вфигачил в код смайлик😉

PS: Перед запуском измените в блоке Param переменные $Name и $Icon чтобы они указывали на имя вашего аккаунта в твиттере, и путь к значку для трея соответственно.

PPS: Если вы вдруг завершите сценарий не с помощью функции Exit в меню, а например нажав Ctrl+C в консоли PowerShell, то вам придётся убить процесс powershell’а для окончательного завершения.

###############################################################################
#
# Script for checking updates on Twitter, using RSS feed. Can be adapted to 
# work with any other RSS feed as well.
# New entries shown in notification baloon. Window with recent updates can be 
# displayed by doubleclicking on notification icon, or using context menu.
#
# Copyright (C) Vasily Gusev, 2009 (http://windowspowershell.ru)
#
# Requres PowerShell v2
# Usage:
# powershell -NoProfile -WindowStyle Hidden -File c:\pstwit.ps1
# powershell -NoProfile -WindowStyle Hidden -Command c:\pstwit.ps1 -proxy (get-credential)
# powershell -NoProfile -WindowStyle Hidden -Command c:\pstwit.ps1 -Name Xaegr -Icon c:\icon.ico
#
##############################################################################
Param (
    $Name = "Xaegr", #Имя пользователя twitter'а
    $Icon = "C:\Root\Data\Check.Ico", #Значок который будет показываться в области уведомлений
    $Interval = 60, #Интервал проверки в секундах
    $NotifyTimeout = 10, #Время показа уведомления
    $ProxyCredential = $null # Учетные данные для подключения к прокси если нужны.
)
#Добавляем сборку для работы с графическим интерфейсом
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null

#Создаём элементы управления: пустую форму, значок области уведомлений, контекстное меню для него, таймер
$form = new-object System.Windows.Forms.form 
$ni = new-object System.Windows.Forms.NotifyIcon 
$niMenu = new-object System.Windows.Forms.ContextMenu 
$t = New-Object system.windows.forms.timer

#Устанавливаем свойства элементов управления
$t.Interval = $Interval * 1000
$form.ShowInTaskbar = $False 
$form.WindowState = "minimized"
$form.Visible = $false
$ni.Icon = New-object System.Drawing.Icon($Icon)
$ni.ContextMenu = $niMenu
$ni.Text = "Monitoring Twitter $Name"

#Создаем ключ реестра для хранения данных
New-Item -Path "HKCU:\Software\PSTwitter\" -ea 0
New-Item -Path "HKCU:\Software\PSTwitter\$Name" -ea 0

#Создаем элементы меню - Exit
$miExit = new-object System.Windows.Forms.MenuItem 
$miExit.Text = "Exit" #Текст меню
$miExit.Add_Click({ #Действие выполняемое при щелчке на элементе
    $ni.Visible = $False 
    $form.close() #При закрытии этой формы, выполнение нашего сценария завершиться
    })

#При выборе этого пункта будет вызвана функция Check (см. ниже)
$miCheck = new-object System.Windows.Forms.MenuItem 
$miCheck.Text = "Check now!"
$miCheck.Add_Click({Check})

#Вызовет функцию List
$miList = new-object System.Windows.Forms.MenuItem 
$miList.Text = "View list"
$miList.Add_Click({List})

#Добавляем элементы в меню
$niMenu.MenuItems.AddRange(@($miList,$miCheck,$miExit)) 

#Привязываем к двойному щелчку на значке в области уведомлений вызов функции List
$ni.add_DoubleClick({List})

#Пробуем прочитать сохранённый пароль из реестра
if ((gp HKCU:\Software\PSTwitter\$Name).Password)
{
    #Преобразовываем пароль, и создаем объект PSCredential
    $Password = (gp "HKCU:\Software\PSTwitter\$Name").Password | ConvertTo-SecureString
    $Username = (gp "HKCU:\Software\PSTwitter\$Name").Username
    $cred = New-Object System.Management.Automation.PSCredential($username,$password)
}
else
{
    #Запрашиваем имя и пароль у пользователя
    $Cred = Get-Credential
    #Сохраняем в реестр
    Set-ItemProperty -Path "HKCU:\Software\PSTwitter\$Name" -Name "Password" -Value ($Cred.Password | ConvertFrom-SecureString)
    Set-ItemProperty -Path "HKCU:\Software\PSTwitter\$Name" -Name "Username" -Value ($Cred.UserName -replace "^.*\\")
}

#Создаем объект WebClient для загрузки данных по Http
$wc = New-Object net.webclient
#Устанавливаем ему учетные данные для использования
$wc.Credentials = $Cred.GetNetworkCredential()
#При необходимости задаем учетные данные для прокси.
if ($ProxyCredential) {$wc.Proxy.Credentials = $ProxyCredential.GetNetworkCredential()}

#В этой переменной будут храниться uid'ы уже показанных записей, чтоб не показать их второй раз, 
#если например время на сервере Twitter'а и в локальной системе расходится.
$global:Uids = @()

#Если дата последней проверки уже была сохранена в реестре...
if ((gp "HKCU:\Software\PSTwitter\$Name").CheckDate)
{
    #Помещаем её в переменную CheckDate
    $global:CheckDate = [datetime]::FromFileTimeUTC((gp "HKCU:\Software\PSTwitter\$Name").CheckDate)
}
else
{
    #Иначе, устанавливаем дату на 1 день назад, чтобы посмотреть записи за это время.
    $global:CheckDate = (Get-date).AddDays(-1)
}

#Функция проверки записей
Function Check
{
    write-host "Checking feed $(get-date)"
    #Загружаем ленту, и сразу преобразоываем её в xml
    $global:timeline = [xml]($wc.DownloadString("http://twitter.com/statuses/friends_timeline.rss"))
    
    #Обрабатываем элементы ленты которые были созданы раньше последней даты проверки, и не содержатся в $Uids
    $global:timeline.rss.channel.item | 
    where {$CheckDate -le [datetime]($_.pubdate) -and $global:Uids -notcontains $_.guid} | 
    sort {[datetime]($_.pubdate)} |
    foreach {
        $Title = ($_.title -replace ":.+$") + " @ " + [datetime]($_.pubdate)
        $Desc = $_.Description -replace "^.+?: "
        $global:Uids+=$_.guid
        #Выводим уведомление (время показа, заголовок, текст, значок)
        $NI.ShowBalloonTip($NotifyTimeout,$Title,$Desc,[system.windows.forms.ToolTipIcon]"Info") 
        #Ждем $NotifyTimeout секунд, на случай если добавилось сразу несколько твитов.
        Sleep $NotifyTimeout 
    }
    #Помещаем в $CheckDate время
    $global:CheckDate = Get-Date
    #И сохраняем его в реестре
    Set-ItemProperty -Path "HKCU:\Software\PSTwitter\$Name" -Name "CheckDate" -Value ($global:CheckDate).ToFileTimeUtc()
    Write-host "Done $(get-date)"
}

#Функция отобращающая список записей
Function List
{
    #Создаем элементы
    $formList = New-Object system.windows.forms.form
    $list = New-Object system.windows.forms.listview
    #Задаём их свойства
    $formList.controls.add($list)
    $formList.width = 840
    $formList.height = 350
    $list.dock="fill"
    $List.View = "Details"
    $List.MultiSelect = $false
    $List.FullRowSelect = $True
    $List.Columns.Add("Name").width = 70
    $List.Columns.Add("Time").width = 130
    $List.Columns.Add("Message").width = 600
    #Добавляем записи
    $global:timeline.rss.channel.item | 
    foreach {        
        $I = $List.Items.Add($_.title -replace ":.+$")
        $I.SubItems.Add([datetime]($_.pubdate)) | Out-Null
        $I.SubItems.Add($_.Description -replace "^.+?: ") | Out-Null
        $I.SubItems.Add($_.Link) | Out-Null
    }
    #Указываем что делать при двойном щелчке на списке
    $List.Add_DoubleClick({
        if($List.SelectedItems.Count -ge 1)
        {
            Write-Host ($list.SelectedItems[0].subitems[3].text)
            #Открываем Internet Explorer и передаем url выбранного элемента как аргумент
            & "$env:ProgramFiles\Internet Explorer\iexplore.exe" $list.SelectedItems[0].subitems[3].text
        }
    })
    #Показываем форму
    $formList.ShowDialog()
}

#Указываем что при каждом тике таймера, вызывать функцию Check
$t.add_tick({Check})
#Включаем таймер
$t.start()
#Показываем значок в области уведомлений
$NI.Visible = $True
#"Показываем" невидимую форму (когда она закроется - сценарий завершиться)
$form.showdialog()

комментария 4 to “PsTwit.ps1”

  1. Oleg Says:

    Скрипт интересный, но непонятен вот этото момент
    «PPS: Если вы вдруг завершите сценарий не с помощью функции Exit в меню, а например нажав Ctrl+C в консоли PowerShell, то вам придётся убить процесс powershell’а для окончательного завершения»
    Разве по Ctrl+C процесс не должен «умирать»?

  2. Xaegr Says:

    2 Oleg: Нет, не должен. Сценарии PowerShell выполняются в процессе хоста, в данном случае PowerShell.exe. Я думаю вы бы расстроились если бы по Ctrl+C закрывалась консоль🙂
    Этот же сценарий многопоточный, и по нажатию Ctrl-C закрывается лишь один поток, остальные (в частности отвечающий за обработку событий значка, или тот который проверяет ленту по событию таймера) предполагают что всё на месте🙂

  3. GUI на PowerShell « IT записки Says:

    […] А вот тут можно найти хороший пример уже полноценного GUI […]

  4. NARKOZ Says:

    Отличный скрипт, python отдыхает. Самое то для Windows 7.


Обсуждение закрыто.

%d такие блоггеры, как: