PowerShellで作るdeliciousクライアント ラスト
前回の続きです。
タグの一覧を取得
タグの一覧を取得する機能を実装します。
まずは「DeliciousTag.vb」というファイル名でクラスファイルを追加します。
DeliciousTag.vb
Public Class DeliciousTag Private _name As String Public Property Name() As String Get Return _name End Get Set(ByVal value As String) _name = value End Set End Property Private _count As Integer Public Property Count() As Integer Get Return _count End Get Set(ByVal value As Integer) _count = value End Set End Property End Class
このクラスはタグの情報を格納します。
DeliciousクラスにGetTagsという名前でメソッドを定義します。
Delicious.vb
Function GetTags() As List(Of DeliciousTag) Dim address = "https://api.del.icio.us/v1/tags/get" Dim contents = GetContents(address) Dim xml = XDocument.Parse(contents) Dim results = From ele In xml.Descendants("tag") _ Select New DeliciousTag With { _ .Name = ele.Attribute("tag"), _ .Count = ele.Attribute("count") _ } Return results.ToList() End Function Private Function GetContents(ByVal address As String) Dim wc = New Net.WebClient() wc.Credentials = _credential wc.Encoding = Text.Encoding.UTF8 Return wc.DownloadString(address) End Function
処理的には特に説明する必要がありませんね。
ちなみにWebClientを使ってリクエストを送る処理をGetContentsというメソッドに分離しておきました。
後は、このメソッドをプロバイダークラスから呼び出すように変更します。
GetChildItemsParametersクラスにTagOnlyというプロパティを追加します。 このパラメータが指定された時だけタグ一覧を出力するという感じです。
DeliciousProvider.vb
Private Class GetChildItemsParameters Private _start As Integer = 0 <Parameter(Position:=0)> _ Public Property Start() As Integer Get Return _start End Get Set(ByVal value As Integer) _start = value End Set End Property Private _count As Integer = 20 <Parameter(Position:=1)> _ Public Property Count() As Integer Get Return _count End Get Set(ByVal value As Integer) _count = value End Set End Property Private _tag As String() <Parameter(Position:=2)> _ Public Property Tag() As String() Get Return _tag End Get Set(ByVal value As String()) _tag = value End Set End Property Private _tagOnly As SwitchParameter <Parameter()> _ Public Property TagOnly() As SwitchParameter Get Return _tagOnly End Get Set(ByVal value As SwitchParameter) _tagOnly = value End Set End Property End Class
GetChildItemsメソッドを以下のように変更します。
DeliciousProvider.vb
Protected Overrides Sub GetChildItems(ByVal path As String, ByVal recurse As Boolean) Dim dynaParams = CType(DynamicParameters, GetChildItemsParameters) If dynaParams.TagOnly.IsPresent Then For Each tag In Me.Delicious.GetTags() WriteItemObject(tag, path, False) Next Else For Each bookmark In Me.Delicious.GetBookmarks(dynaParams.Start, dynaParams.Count, dynaParams.Tag) WriteItemObject(bookmark, path, False) Next End If End Sub
TagOnlyプロパティが指定された時だけタグを取得して、出力していますね。
タグの情報を見易く表示する為に書式設定ファイルにDeliciousTagクラスの設定を追加しておきます。
psdelicious.format.ps1xml
<?xml version="1.0" encoding="utf-8" ?> <Configuration> <ViewDefinitions> <View> <Name>Tags</Name> <ViewSelectedBy> <TypeName>PSDelicious.DeliciousTag</TypeName> </ViewSelectedBy> <TableControl> <TableHeaders> <TableColumnHeader> <Label>タグ名</Label> </TableColumnHeader> <TableColumnHeader> <Label>タグ数</Label> </TableColumnHeader> </TableHeaders> <TableRowEntries> <TableRowEntry> <TableColumnItems> <TableColumnItem> <PropertyName>Name</PropertyName> </TableColumnItem> <TableColumnItem> <PropertyName>Count</PropertyName> </TableColumnItem> </TableColumnItems> </TableRowEntry> </TableRowEntries> </TableControl> </View> <View> <Name>Tags</Name> <ViewSelectedBy> <TypeName>PSDelicious.DeliciousBookmark</TypeName> </ViewSelectedBy> <ListControl> <ListEntries> <ListEntry> <ListItems> <ListItem> <Label>タイトル</Label> <PropertyName>Title</PropertyName> </ListItem> <ListItem> <Label>URL</Label> <PropertyName>Url</PropertyName> </ListItem> <ListItem> <Label>コメント</Label> <PropertyName>Comment</PropertyName> </ListItem> <ListItem> <Label>タグ</Label> <PropertyName>Tags</PropertyName> </ListItem> <ListItem> <Label>更新日付</Label> <PropertyName>Date</PropertyName> </ListItem> </ListItems> </ListEntry> </ListEntries> </ListControl> </View> </ViewDefinitions> </Configuration>
これで、以下のようにするとタグの一覧を表示することができます。
PS > dir -TagOnly タグ名 タグ数 ------ ------ .NET 67 ADO.NET 3 AIR 2 AOP 1 API 2 ASP.NET 19 ActionScript 1 Ajax 2 Apache 3 AppEngine 4
残りの機能を一気に実装します。
タグの編集と削除
DeliciousクラスにDeleteTagとRenameTagというメソッドを追加します。
Delicious.vb
Sub DeleteTag(ByVal tag As String) Dim address = "https://api.del.icio.us/v1/tags/delete?tag=" + Web.HttpUtility.UrlEncode(tag) Dim contents = GetContents(address) Dim result = GetResult(contents) If result <> "done" Then Throw New ArgumentException(result) End Sub Sub RenameTag(ByVal oldValue As String, ByVal newValue As String) Dim address = String.Format( _ "https://api.del.icio.us/v1/tags/rename?old={0}&new={1}", _ Web.HttpUtility.UrlEncode(oldValue), Web.HttpUtility.UrlEncode(newValue) _ ) Dim contents = GetContents(address) Dim result = GetResult(contents) If result <> "done" Then Throw New ArgumentException(result) End Sub Private Shared Function GetResult(ByVal contents As String) As String Dim result = Text.RegularExpressions.Regex.Match( _ contents, "<result>(?<msg>.*?)</result>", Text.RegularExpressions.RegexOptions.Multiline _ ) Return IIf(result.Success, result.Groups("msg").Value, String.Empty) End Function
見たまんまですね。
RemoveItemParametersクラスにTagNameというプロパティを追加します。 このパラメータが指定されたらタグを削除するようにします。
DeliciousProvider.vb
Private Class RemoveItemParameters Private _bookmark As DeliciousBookmark <Parameter(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 _tagName As String <Parameter()> _ Public Property TagName() As String Get Return _tagName End Get Set(ByVal value As String) _tagName = value End Set End Property End Class
RemoveItemメソッドを以下のように変更します。
DeliciousProvider.vb
Protected Overrides Sub RemoveItem(ByVal path As String, ByVal recurse As Boolean) Dim dynaParams = CType(Me.DynamicParameters, RemoveItemParameters) If String.IsNullOrEmpty(dynaParams.TagName) Then Me.Delicious.DeleteBookmark(dynaParams.Bookmark.Url) Else Me.Delicious.DeleteTag(dynaParams.TagName) End If End Sub
これで以下のようにして、タグを削除する事ができます。
PS delicious:\> del -Tag .NET
SetItemParametersクラスにTagというプロパティを追加します。このパラメータが指定されたらタグ名を変更するようにします。
DeliciousProvider.vb
Private Class SetItemParameters Private _bookmark As DeliciousBookmark <Parameter(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 Private _tag As SwitchParameter <Parameter()> _ Public Property Tag() As SwitchParameter Get Return _tag End Get Set(ByVal value As SwitchParameter) _tag = value End Set End Property End Class
SetItemメソッドを以下のように変更します。
DeliciousProvider.vb
Protected Overrides Sub SetItem(ByVal path As String, ByVal value As Object) Dim dynaParams = CType(Me.DynamicParameters, SetItemParameters) If dynaParams.Tag.IsPresent Then Me.Delicious.RenameTag(path, value.ToString()) ElseIf Not value Is Nothing Then Me.Delicious.AddBookmark( _ dynaParams.Bookmark, replace:=True, share:=dynaParams.Share.IsPresent _ ) End If End Sub
これで以下のようにして、タグ名を変更することができます。
PS delicious:\> si -Tag .net .net-framework
これでだいたい当初予定していた機能は実装できたはずです。インターフェースはまだまだ煮詰める余地がありますが、普通に使えると思います。
最後の方は駆け足になってしまいましたが、PowerShellでのプロバイダ開発の実際のやり方がなんとなくつかめたのではないでしょうか。今回は基本的な機能しか実装していませんが、アイデア次第でいくらでも便利にする事ができます。
こういった拡張性の高さもPowerShellのプロバイダ開発の魅力だと思います。皆さんも試しに作ってみて下さい。楽しいですよ!!