前回の続きです。
前回でブックマークの一覧を取得できるようにしましたが、あのままではURLがわかってもブラウザで開くという作業が面倒なので、その辺を簡略化できるように与えられたURLを既定のブラウザで開くコマンドレットを作っておきます。
「Commands」というフォルダを作成して、その中に「BrowseObjectCommand.vb」というファイル名でクラスファイルを追加します。
Commands\BrowseObjectCommand.vb
Namespace Commands
<Cmdlet("Browse", "Object")> _
Public Class BrowseObjectCommand
Inherits PSCmdlet
Private _url As String
<Parameter(Mandatory:=True, Position:=0, ValueFromPipelineByPropertyName:=True)> _
Public Property Url() As String
Get
Return _url
End Get
Set(ByVal value As String)
_url = value
End Set
End Property
Protected Overrides Sub ProcessRecord()
Process.Start(Me.Url)
End Sub
End Class
End Namespace
PSCmdletクラスを継承します。コマンドレットである事を示す為にCmdletAttribute属性でマークしておきます。引数にはコマンドレットの動詞と名詞を指定します(Browse-Objectという書式になる)。
コマンドレットが実行されるとProcessRecordメソッドが呼び出されるので、これをオーバーライドして、その中ではURLプロパティをシェルで呼び出すだけです。
URLプロパティはParameterAttribute属性でマークして、必須属性(Mandatory:=True)、位置が0(Position:=0)、値をパイプラインから取得し、そのオブジェクトのプロパティと結びつけます(ValueFromPipelineByPropertyName:=True)。
このコマンドレットを使うと以下のようにして、URLをブラウザで開くことができるようになります。
PS delicious:\> dir -Count 1 | Browse-Object
ブックマークの追加・編集
ブックマークの追加・編集機能を実装します。
DeliciousクラスにAddBookmarkという名前で引数にDeliciousBookmark型を受け取るメソッドを定義します。
Delicious.vb
Sub AddBookmark(ByVal bookmark As DeliciousBookmark, _
Optional ByVal share As Boolean = False, Optional ByVal replace As Boolean = False)
Dim address = "https://api.del.icio.us/v1/posts/add"
Dim queries = New Dictionary(Of String, Object)()
If String.IsNullOrEmpty(bookmark.Url) Then Throw New ArgumentException("[Url]を指定して下さい。")
If String.IsNullOrEmpty(bookmark.Title) Then Throw New ArgumentException("[Title]を指定して下さい。")
queries.Add("url", bookmark.Url)
queries.Add("description", bookmark.Title)
' optional
If Not String.IsNullOrEmpty(bookmark.Comment) Then queries.Add("extended", bookmark.Comment)
If Not bookmark.Tags Is Nothing AndAlso bookmark.Tags.Length > 0 Then
queries.Add("tags", String.Join(" ", bookmark.Tags))
End If
If Not bookmark.Date Is Nothing Then
queries.Add("dt", bookmark.Date.Value.ToString("yyyy-MM-ddTHH:mm:ssZ"))
End If
queries.Add("shared", IIf(share, "yes", "no"))
queries.Add("replace", IIf(replace, "yes", "no"))
Dim wc = New Net.WebClient()
wc.Credentials = _credential
wc.Encoding = Text.Encoding.UTF8
Dim contents = wc.DownloadString(JoinQueries(address, queries))
Dim result = Text.RegularExpressions.Regex.Match( _
contents, "<result code=""(?<msg>.*?)"" />", Text.RegularExpressions.RegexOptions.Multiline _
)
If result.Success Then
Dim msg = result.Groups("msg").Value
' replaceを指定してね!
If msg <> "done" Then Throw New ArgumentException(msg)
End If
End Sub
Private Shared Function JoinQueries(ByVal address As String, ByVal queries As IDictionary(Of String, Object))
If queries.Count = 0 Then Return address
Return address + "?" + String.Join( _
"&", queries.Select( _
Function(q) String.Format("{0}={1}", q.Key, Web.HttpUtility.UrlEncode(q.Value)) _
).ToArray() _
)
End Function
特に説明する必要は無いでしょう。単に「https://api.del.icio.us/v1/posts/add」というURLにリクエストを送っているだけです。
後、JoinQueriesメソッドのq.Valueを取得する部分をHttpUtilityクラスを使ってURLエンコードしておきました(System.Webアセンブリへの参照が必要です)。
使うとしたら、以下のようになるでしょうか。
Program.vb
Sub Main()
Dim obj = New Delicious(New Net.NetworkCredential("ユーザ名", "パスワード"))
Dim bookmark = New DeliciousBookmark With { _
.Title = "google", _
.Url = "http://www.google.co.jp" _
}
' 共有して、上書きする。
obj.AddBookmark(bookmark, share:=True, replace:=True)
End Sub
では、このメソッドをプロバイダークラスから呼び出すように変更しましょう。
このメソッドを呼び出すには山ほどパラメータが必要になるので 、(インナークラスで)パラメータクラスを作っておきます。
Delicious.vb
Private Class NewItemParameters
Private _url As String
<Parameter(Mandatory:=True, Position:=0)> _
Public Property Url() As String
Get
Return _url
End Get
Set(ByVal value As String)
_url = value
End Set
End Property
Private _tags As String()
<Parameter(Position:=1)> _
Public Property Tags() As String()
Get
Return _tags
End Get
Set(ByVal value As String())
_tags = value
End Set
End Property
Private _comment As String
<Parameter(Position:=2)> _
Public Property Comment() As String
Get
Return _comment
End Get
Set(ByVal value As String)
_comment = value
End Set
End Property
Private _date As DateTime?
<Parameter(Position:=3)> _
Public Property [Date]() As DateTime?
Get
Return _date
End Get
Set(ByVal value As DateTime?)
_date = value
End Set
End Property
Private _share As SwitchParameter
<Parameter()> _
Public Property Share() As SwitchParameter
Get
Return _share
End Get
Set(ByVal value As SwitchParameter)
_share = value
End Set
End Property
End Class
URL、Tags、Comment、Date、Shareというプロパティを定義しています。それぞれParameterAttribute属性でマークして、必須属性にはMandatory:=TrueをPostion:=nで順番を指定しています。
後はNewItem(New-Itemコマンドレットに対応)メソッドをオーバーライドして、その中でAddBookmarkメソッドを呼び出すだけです。
NewItemDynamicParametersメソッドをオーバーライドして、NewItemParametersクラスのインスタンスを返しておく事をお忘れなく。
Delicious.vb
Protected Overrides Sub NewItem(ByVal path As String, ByVal itemTypeName As String, ByVal newItemValue As Object)
Dim dynaParams = CType(Me.DynamicParameters, NewItemParameters)
Dim bookmark = New DeliciousBookmark With { _
.Title = path, _
.Url = dynaParams.Url, _
.Tags = dynaParams.Tags, _
.Comment = dynaParams.Comment, _
.Date = dynaParams.Date _
}
Me.Delicious.AddBookmark( _
bookmark, replace:=Me.Force, share:=dynaParams.Share.IsPresent _
)
WriteItemObject(bookmark, path, False)
End Sub
Protected Overrides Function NewItemDynamicParameters(ByVal path As String, ByVal itemTypeName As String, ByVal newItemValue As Object) As Object
Return New NewItemParameters()
End Function
追加に成功すれば(例外が投げられなければ)、DeliciousBookmarkオブジェクトをパイプラインに出力しておきます。
これで、以下のようにしてブックマークを追加する事ができるようになります。
PS delicious:\> ni google http://www.google.co.jp -Tags google -Comment テストです。
タイトル : google
URL : http://www.google.co.jp
コメント : テストです。
タグ : {google}
更新日付 :
PS delicious:\> dir -Count 1
タイトル : google
URL : http://www.google.co.jp/
コメント : テストです。
タグ : {google}
更新日付 : 2009/03/12 4:30:46
次はブックマークを編集できるようにしておきます。
まずはSet-Itemコマンドレットのパラメータクラスをインナークラスで定義しておきます。
Delicious.vb
Private Class SetItemParameters
Private _bookmark As DeliciousBookmark
<Parameter(Mandatory:=True, Position:=0, ValueFromPipeline:=True)> _
Public Property Bookmark() As DeliciousBookmark
Get
Return _bookmark
End Get
Set(ByVal value As DeliciousBookmark)
_bookmark = value
End Set
End Property
Private _share As SwitchParameter
<Parameter(Position:=1)> _
Public Property Share() As SwitchParameter
Get
Return _share
End Get
Set(ByVal value As SwitchParameter)
_share = value
End Set
End Property
End Class
BookmarkとShareというプロパティを定義しています。BookmarkプロパティはValueFromPipeline:=Trueにする事でパイプラインから取得できるようにしておきます。
後はSetItemメソッド(Set-Itemコマンドレットに対応)をオーバーライドして、その中でAddBookmarkメソッドをreplace:=Trueで呼び出しています。
Delicious.vb
Protected Overrides Sub SetItem(ByVal path As String, ByVal value As Object)
Dim dynaParams = CType(Me.DynamicParameters, SetItemParameters)
Me.Delicious.AddBookmark( _
dynaParams.Bookmark, replace:=True, share:=dynaParams.Share.IsPresent _
)
End Sub
Protected Overrides Function SetItemDynamicParameters(ByVal path As String, ByVal value As Object) As Object
Return New SetItemParameters()
End Function
あと、Deliciousプロパティに一部不具合があったので、以下のように修正しておいて下さい。
Delicious.vb
Private _delicious As Delicious
Public ReadOnly Property Delicious() As Delicious
Get
If _delicious Is Nothing Then
' Me.PSDriveInfoプロパティでは駄目!!
Dim driveInfo = Me.SessionState.Drive.Current
_delicious = New Delicious(driveInfo.Credential.GetNetworkCredential())
End If
Return _delicious
End Get
End Property
これで、以下のようにしてブックマークの情報を編集する事ができるようになります。
PS delicious:\> $bookmark = dir -Count 1
PS delicious:\> $bookmark.Title = "google.co.jp"
PS delicious:\> $bookmark | si
更新系のコマンドレットには、他にもRename-ItemとMove-Itemがありますが、これらには対応しない事にします。
次はブックマークの削除機能を実装します。
次回に続く
ソース
目次