Maxim Moiseev avatar Maxim Moiseev committed 3e541dc

moved old implementation to UserAPI folder

Comments (0)

Files changed (36)

src/Common/Api.fs

-namespace Linq2vk.Core.Implementation
-
-open Linq2vk.Core
-
-module Api =
-
-    let WindowWidth = 10
-
-    open DataKind
-
-    // q -- initial query (See Query module)
-    // w -- window size
-    // s -- initial index
-    let getWindowedFrom s w q =
-        let rec loop a b =
-            seq {
-                let url = q |> Query.addFrom a |> Query.addTo b |> Query.toUrl
-                printfn "Url: %s" url
-                let text = Net.requestTextSync url
-                match text with
-                | JsonArr arr ->
-                    yield! Seq.map string arr
-                    if arr.Count <> 0 then
-                        yield! loop (b+1) (b+w)
-                | JsonData o ->
-                    let (ok, dict) = o.TryGetValue("d")
-                    if ok then
-                        yield! Seq.map string dict
-                | JsonReturnCode c -> ()
-            }
-
-        loop s (w-1)
-    
-    let getAll =
-        getWindowedFrom 0 WindowWidth
-    
-    let getAllFrom s =
-        getWindowedFrom s WindowWidth
-        
-    let getOne q =
-        let url = q |> Query.toUrl
-        printfn "Url: %s" url
-        Net.requestTextSync url

src/Common/Conversions.fs

-namespace Linq2vk.Core
-
-[<RequireQualifiedAccess>] 
-module Conversions =
-    open System
-    open JsonParser
-    open Linq2vk.Core.Implementation.DataKind
-    
-    let apply parser xs =
-        JsonParser.parse parser (Seq.toArray xs)
-    
-    let toFriend = function
-        | JsonArr arr -> apply Parsers.friend arr
-        | _ -> raise <| NotSupportedException "Conversion only supported for JsonArr"
-        
-    let toItemArray conv = function
-        |JsonArr arr -> arr |> Seq.map (string >> conv) |> Seq.toArray
-        | _ -> raise <| NotSupportedException "Conversion only supported for JsonArr"
-
-    let toStatus = function
-        | JsonArr arr ->
-            apply Parsers.status arr
-        | JsonData o ->
-            apply Parsers.status (o.PropertyValues())
-        | _ -> raise <| NotSupportedException "Conversion only supported for JsonArr or JsonData"
-
-    let toPhoto = function
-        | JsonArr arr -> apply Parsers.photo arr
-        | _ -> raise <| NotSupportedException "Conversion only supported for JsonArr"
-
-    // TODO: implement a Json Object parsers equivalent to Json Array parsers to handle this kind of situation
-    open Tools
-    let toUserProfile = function
-        | JsonData o ->
-            { new IUserProfile with
-                override this.UserId = o.["id"] |> int64
-                override this.FirstName = o.["fn"] |> string'
-                override this.LastName = o.["ln"] |> string'
-                override this.MaidenName = o.["mn"] |> string'
-                override this.CurrentStatus = o.["actv"] |> string |> toStatus
-                override this.CountryId = o.["ht"].["coi"] |> int64
-                override this.ISOCountryCode = o.["ht"].["con"] |> string'
-                override this.CityId = o.["ht"].["cii"] |> int64
-                override this.CityName = o.["ht"].["cin"] |> string'
-                override this.Gender = o.["sx"] |> int |> enum<Gender>
-                override this.PhotoUrl = o.["bp"] |> string'
-                override this.BirthdayDay = o.["bd"] |> int
-                override this.BirthdayMonth = o.["bm"] |> int
-                override this.BirthdayYear = o.["by"] |> int
-                override this.MaritalStatus = o.["fs"] |> int |> enum<MaritalStatus>
-                override this.PoliticalViews = o.["pv"] |> int |> enum<PoliticalViews>
-                override this.Friends = o.["fr"].["d"] |> string |> toItemArray toFriend
-                override this.FriendsOnline = o.["fro"].["d"] |> string |> toItemArray toFriend
-                override this.FriendsMutual = o.["frm"].["d"] |> string |> toItemArray toFriend
-                override this.UploadedPhotos = o.["ph"].["d"] |> string |> toItemArray toPhoto
-                override this.PhotosWith = o.["phw"].["d"] |> string |> toItemArray toPhoto
-            }
-        | _ -> raise <| NotSupportedException "Conversion only supported for JsonData"
-        
-    let toMessage = function
-        | JsonArr arr -> apply Parsers.message arr
-        | _ -> raise <| NotSupportedException "Conversion only supported for JsonArr"

src/Common/Data.fs

-namespace Linq2vk.Core
-
-open System
-
-type Action =
-    | Profile
-
-    | Friends
-    | FriendsMutual
-    | FriendsOnline
-    | FriendsNew
-    
-    | Photos
-    | PhotosWith
-    | PhotosNew
-    
-    | Activity
-    
-    | Fave
-    | FaveOnline
-    | Faved
-    
-    | UpdatesActivity
-    | UpdatesFriends
-    | UpdatesPhotos
-    | UpdatesTaggedPhotos
-    
-    | Message
-    | Inbox
-    | Outbox
-    
-    
-type IFriend =
-    abstract Id : int64
-    abstract Name : string
-    abstract PhotoUrl : string
-    abstract IsOnline : bool
-    
-type IStatus =
-    abstract Id : string
-    abstract UserId : int64
-    abstract StatusId : int64
-    abstract Reserved : int
-    abstract Name : string
-    abstract Timestamp : DateTime
-    abstract Text : string
-    
-type IPhoto =
-    abstract Id : string
-    abstract OwnerId : int64
-    abstract PhotoId : int64
-    abstract ThumbnailUrl : string
-    abstract ImageUrl : string
-    
-type Gender =
-    | Female = 1
-    | Male   = 2
-
-type MaritalStatus =
-    | Single            = 1
-    | InRelationships   = 2
-    | Engaged           = 3
-    | Married           = 4
-    | Complicated       = 5
-    | LookingFor        = 6
-    
-type PoliticalViews =
-    | Communist         = 1
-    | Socialist         = 2
-    | Moderate          = 3
-    | Liberal           = 4
-    | Conservative      = 5
-    | Monarchist        = 6
-    | Ultraconservative = 7
-    | Apathetic         = 8
-    
-type IUserProfile =
-    abstract UserId : int64
-    abstract FirstName : string
-    abstract LastName : string
-    abstract MaidenName : string
-    abstract CurrentStatus : IStatus
-    abstract CountryId : int64
-    abstract ISOCountryCode : string
-    abstract CityId : int64
-    abstract CityName : string
-    abstract Gender : Gender
-    abstract PhotoUrl : string
-    abstract BirthdayDay : int
-    abstract BirthdayMonth : int
-    abstract BirthdayYear : int
-    abstract MaritalStatus : MaritalStatus
-    abstract PoliticalViews : PoliticalViews
-    abstract Friends : IFriend[]
-    abstract FriendsOnline : IFriend[]
-    abstract FriendsMutual : IFriend[]
-    abstract UploadedPhotos : IPhoto[]
-    abstract PhotosWith : IPhoto[]
-    
-    
-type IUserDescriptor =
-    abstract UserId : int64
-    abstract UserName : string
-    abstract PhotoUrl : string
-    abstract ThumbnailFileName : string
-    abstract Gender : Gender
-    abstract IsOnline : bool
-    
-type IMessage =
-    abstract MessageId : int64
-    abstract Timestamp : DateTime
-    abstract Text : string
-    abstract Sender : IUserDescriptor
-    abstract Recipient : IUserDescriptor
-    abstract IsRead : bool

src/Common/DataKind.fs

-namespace Linq2vk.Core.Implementation
-
-module DataKind =
-
-    open Newtonsoft.Json.Linq
-    
-    let (|JsonData|JsonArr|JsonReturnCode|) (s:string) =
-//        printfn "(%s)" s
-        if s.[0] = '{' then
-            let jo = JObject.Parse s
-            let (b, d) = jo.TryGetValue("ok")
-            if b then
-                JsonReturnCode (int d)
-            else
-                JsonData jo
-        else
-            JsonArr (JArray.Parse s)

src/Common/JsonParser.fs

-namespace Linq2vk.Core
-
-module JsonParserImpl =
-    open Newtonsoft.Json.Linq
-
-    type JsonArrayParser<'a> =
-        JsonArrayParser of (JToken[] -> ('a * JToken[]) list)
-
-    let runParser (JsonArrayParser p) tokens =
-        p tokens
-
-    exception JsonParserException of string  
-    
-    let getParsingResult = function
-        | [] -> raise <| JsonParserException("Parsing failed")
-        | [(res, _)] -> res
-        | _ -> raise <| System.NotSupportedException("This should not normally happen")
-
-    type JsonArrayBuilder() = 
-        member this.Return(x) =
-            JsonArrayParser (fun ts -> [(x, ts)])
-        member this.Bind(p, f) =
-            JsonArrayParser (fun ts ->
-                match runParser p ts with
-                | [(r, ts')] -> runParser (f r) ts'
-                | _ -> []
-            )
-
-module JsonParser =             
-    open JsonParserImpl
-    
-    let jarr = JsonArrayBuilder()
-    
-    let at idx =
-        JsonArrayParser (fun ts ->
-            if ts.Length <> 0 && idx < ts.Length then
-                [(ts.[idx]), ts]
-            else
-                []
-        )
-        
-    let parse parser tokens =
-        runParser parser tokens
-            |> getParsingResult
-    
-    let parseOrDefault parser defaultValue =
-        JsonArrayParser (fun ts ->
-            match runParser parser ts with
-            | [] -> [(defaultValue, ts)]
-            | res -> res
-        )
-        
-    let (<|>) = parseOrDefault
-    
-    let parseOrFail condition parser =
-        JsonArrayParser (fun ts ->
-            if condition then
-                runParser parser ts
-            else
-                []
-        )
-        
-    let (<?>) = parseOrFail
-    
-    let tokenAtAs idx converter =
-        jarr {
-            let! t = at idx
-            return (converter t)
-        }
-        
-    let (<@>) converter idx =
-        tokenAtAs idx converter
-        
-        
-#if DEBUG
-// simple tests to be used in REPL
-//
-module JsonParserTests =
-    open JsonParser
-    open Newtonsoft.Json.Linq
-
-    let singleItemParser =        
-        jarr {
-            let! a =  int <@> 0
-            let! c = (string <@> 2) <|> "default"
-            return (a,c)
-        }
-
-    let tokens = JArray.Parse("[1,2]") |> Seq.toArray
-    let a = parse singleItemParser tokens
-#endif

src/Common/Net.fs

-namespace Linq2vk.Core.Implementation
-
-module Net =
-    open System
-    open System.IO
-    open System.Net
-
-#if ASYNC    
-    let getUrlResponse (url:string) =
-        async {
-            let req = HttpWebRequest.Create(url)
-            let! resp = req.AsyncGetResponse()
-            return resp :?> HttpWebResponse
-        }
-   
-    let processUrlResponse (url:string) f =
-        async {
-            let! resp = getUrlResponse url
-            return f resp
-        }
-        
-    let requestStream url =
-        async {
-            let! resp = getUrlResponse url
-            return resp.GetResponseStream()
-        }
-        
-    let requestText url =
-        async {
-            let! resp = getUrlResponse url
-            use stream = resp.GetResponseStream()
-            use reader = new StreamReader(stream)
-            return reader.ReadToEnd()
-        }
-#endif
-
-    let getUrlResponseSync (url:string) =
-        let req = HttpWebRequest.Create(url) :?> HttpWebRequest
-        use allDone = new System.Threading.AutoResetEvent(false)
-        
-        let (resp:WebResponse ref) = ref null
-        let onResponse (asyncRes:IAsyncResult) =
-            resp := req.EndGetResponse(asyncRes)
-            
-            let httpResp = !resp :?> HttpWebResponse
-            printfn "%A" httpResp.ResponseUri
-            
-            allDone.Set() |> ignore
-            ()
-            
-        let asyncRes = req.BeginGetResponse(AsyncCallback(onResponse), null)
-        
-        // TODO: Possible problems with infinite lock.
-        allDone.WaitOne() |> ignore
-        !resp :?> HttpWebResponse
-   
-    let processUrlResponseSync (url:string) f =
-        let resp = getUrlResponseSync url
-        f resp
-        
-    let requestTextSync url =
-        let resp = getUrlResponseSync url
-        use stream = resp.GetResponseStream()
-        use reader = new StreamReader(stream)
-        reader.ReadToEnd()

src/Common/Parsers.fs

-namespace Linq2vk.Core
-
-open Linq2vk.Core.JsonParser
-
-module Tools =
-    open System
-    open Newtonsoft.Json.Linq        
-    open System.Text.RegularExpressions
-    
-    let unquote (s:string) =
-        s.[1..(s.Length-2)]
-        
-    let string' = unquote << string
-    
-    let anyString (token:JToken) =
-        if token.Type = JTokenType.String then
-            token |> string |> unquote
-        else
-            token |> string
-    
-    let intBool (token:JToken) =
-        0 <> (token |> int)
-
-    let UnixTimeStart = DateTime(1970, 1, 1)
-    let fromUnixtime (x:int64) = 
-         UnixTimeStart + TimeSpan.FromSeconds(x |> float)
-
-    let parseTimestamp (token:JToken) =
-        anyString token |> int64 |> fromUnixtime
-
-    let parseComplexId id =
-        let idRx = Regex("([0-9]+)_([\-0-9]+)")
-        let m = idRx.Match(id)
-        let parseGroup (i:int) =
-            m.Groups.[i].Value |> int64
-        
-        if m.Success then 
-            (parseGroup 1, parseGroup 2)
-        else
-            raise <| ArgumentException(sprintf "Invalid complex id format: %s" id)
-            
-    let asArray (token:JToken) =
-        Seq.toArray token
-    let childToken idx (token:JToken) =
-        (asArray token).[idx]
-            
-
-[<RequireQualifiedAccess>]
-module Parsers =
-    open System
-    open Tools
-
-    let friend =
-        jarr {
-            let! id = int64 <@> 0
-            let! name = string' <@> 1
-            let! photo = string' <@> 2
-            let! isOnline = intBool <@> 3
-
-            return {
-                new IFriend with 
-                    override this.Id = id
-                    override this.Name = name
-                    override this.PhotoUrl = photo
-                    override this.IsOnline = isOnline
-            }
-        }
-        
-    let status =
-        jarr {
-            let! id = string <@> 0
-            let! userId = int64 <@> 1
-            let! (_, statusId) = (parseComplexId << string) <@> 0
-            let! name = string' <@> 3
-            let! timestamp = (statusId <> -1L) <?> (parseTimestamp <@> 4) <|> DateTime.MinValue
-            let! text = string' <@> 5
-            return {
-                new IStatus with
-                    override this.Id = id
-                    override this.UserId = userId
-                    override this.StatusId = statusId
-                    override this.Reserved = 0
-                    override this.Name = name
-                    override this.Timestamp = timestamp
-                    override this.Text = text
-              }
-        }
-        
-    let photo =
-        jarr {
-            let! id = string <@> 0
-            let! (ownerId, photoId) = (parseComplexId << string) <@> 0
-            let! thumbnailUrl = string' <@> 1
-            let! imageUrl = string' <@> 2
-            return {
-                new IPhoto with
-                    override this.Id = id
-                    override this.OwnerId = ownerId
-                    override this.PhotoId = photoId
-                    override this.ThumbnailUrl = thumbnailUrl
-                    override this.ImageUrl = imageUrl
-            }
-        }
-    
-    let userDescription =
-        jarr {
-            let! userId = (int64 << anyString) <@> 0
-            let! name = string' <@> 1 <|> String.Empty
-            let! photoUrl = anyString <@> 2 <|> String.Empty
-            let! thumbnailFileName = anyString <@> 3 <|> String.Empty
-            let! gender = (enum<Gender> << int) <@> 4 <|> Gender.Male
-            let! isOnline = intBool <@> 5 <|> false
-            return {
-                new IUserDescriptor with
-                    override this.UserId = userId
-                    override this.UserName = name
-                    override this.PhotoUrl = photoUrl
-                    override this.ThumbnailFileName = thumbnailFileName
-                    override this.Gender = gender
-                    override this.IsOnline = isOnline
-            }
-        }
-        
-    let message =
-        jarr {
-            let! messageId = (int64 << anyString) <@> 0
-            let! timestamp = parseTimestamp <@> 1
-            let! text = (childToken 0 >> string) <@> 2
-            let! sender = (parse userDescription << asArray) <@> 3
-            let! recipient = (parse userDescription << asArray) <@> 4
-            let! isRead = intBool <@> 5
-            return {
-                new IMessage with
-                    override this.MessageId = messageId
-                    override this.Timestamp = timestamp
-                    override this.Text = text
-                    override this.Sender = sender
-                    override this.Recipient = recipient
-                    override this.IsRead = isRead
-                }
-        }
-        

src/Common/Query.fs

-namespace Linq2vk.Core.Implementation
-
-open System.Collections.Generic
-open Linq2vk.Core
-
-module Query =
-    
-    let init (sid:string) =
-        [("sid", sid)]
-        
-    let add (k:string) (v:'a) q =
-        (k, v.ToString()) :: q
-        
-    let toUrl q =
-        let prefix = "http://userapi.com/data?"
-        let makepair (k, v) =
-            sprintf "%s=%s" k v
-        let urlQuery = q |> (Seq.map makepair >> Seq.toArray >> (fun xs -> System.String.Join("&", xs)))
-        prefix + urlQuery
-
-    let addAction (act:Action) =
-        add "act" <|
-            match act with
-            | Friends               -> "friends"
-            | UpdatesActivity       -> "updates_activity"
-            | UpdatesFriends        -> "updates_friends"
-            | UpdatesPhotos         -> "updates_photos"
-            | UpdatesTaggedPhotos   -> "updates_tagged_photos"
-            | Profile               -> "profile"
-            | Inbox                 -> "inbox"
-            | Outbox                -> "outbox"
-            | _                     -> failwith "Not implemented"
-            
-    // TODO: why does not point-free style work here?
-    let addId id = add "id" id
-    let addTo toVal = add "to" toVal
-    let addFrom from = add "from" from

src/Common/UserAPI.fs

-namespace Linq2vk.Core
-
-open System
-open System.Net
-open System.Text.RegularExpressions
-open Linq2vk.Core.Implementation
-
-type UserAPI (prjId:int64) =
-    let WindowSize = 10
-    
-    let mutable _sid = String.Empty
-    
-    let query act =
-        Query.init _sid |> Query.addAction act
-        
-    let userQuery uid act =
-        query act |> Query.addId uid
-        
-    let getItem conv q =
-        q |> Api.getOne |> conv
-        
-    let getAllItems conv q =
-        q |> Api.getAll |> Seq.map conv
-    
-    member this.LoggedIn
-        with get () = String.IsNullOrEmpty(_sid)
-        
-    member this.Login(usr:string, pwd:string) =
-        let query =
-            sprintf "http://login.userapi.com/auth?login=force&site=%d&email=%s&pass=%s" prjId usr pwd
-            
-        let getSid (resp:HttpWebResponse) =        
-            let sidRx = Regex("sid=([a-z0-9]+)")
-            
-            let getMatchedGroup (rx:Regex) =
-                rx.Match >> (fun m -> m.Groups.[1].Value)
-
-            let sid =
-                resp.ResponseUri.AbsoluteUri |> getMatchedGroup sidRx                   
-            sid
-            
-        let sid =
-            Net.processUrlResponseSync query getSid
-        
-        _sid <- sid
-        this.LoggedIn
-
-    member private this.GetFriendsFrom(queryF) =
-        queryF Action.Friends
-        |> getAllItems Conversions.toFriend
-    
-    member private this.GetFriends(uid:int64) =
-        this.GetFriendsFrom (userQuery uid)
-            
-    member this.MyFriends
-        with get () =
-            this.GetFriendsFrom query
-        
-    member this.StatusUpdates
-        with get () =
-            query Action.UpdatesActivity
-            |> getAllItems Conversions.toStatus
-                
-    member this.FriendsOfFriends
-        with get () =
-            query Action.UpdatesFriends
-            |> getAllItems Conversions.toFriend
-            
-    member this.FriendsPhotos
-        with get () =
-            query Action.UpdatesPhotos
-            |> getAllItems Conversions.toPhoto
-            
-    member this.FriendsTaggedPhotos
-        with get () =
-            query Action.UpdatesTaggedPhotos
-            |> getAllItems Conversions.toPhoto
-
-    member private this.GetProfileFrom(queryF) =
-        queryF Action.Profile
-        |> getItem Conversions.toUserProfile
-    
-    member this.GetUserProfile (uid:int64) =
-        this.GetProfileFrom (userQuery uid)
-        
-    member this.MyProfile
-        with get () = 
-            this.GetProfileFrom query
-            
-    member private this.GetMessagesFor(action) =
-        match action with
-        | Action.Inbox | Action.Outbox //| Action.Message
-            -> query action 
-               |> getAllItems Conversions.toMessage
-        | _ -> raise <| NotSupportedException()
-            
-    member this.Inbox
-        with get () = this.GetMessagesFor Action.Inbox
-                
-    member this.Outbox 
-        with get () = this.GetMessagesFor Action.Outbox
-        

src/Linq2vk.Core.Silverlight/Linq2vk.Core.Silverlight.2010.fsproj

-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>8.0.30703</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{05d5ede1-5b6f-48d3-b627-e9bf498773ec}</ProjectGuid>
-    <OutputType>Library</OutputType>
-    <AssemblyName>Linq2vk.Core.Silverlight.2010</AssemblyName>
-    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
-    <SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
-    <FileAlignment>512</FileAlignment>
-    <AllowCrossTargeting>true</AllowCrossTargeting>
-    <ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{f2a71f9b-5d33-465a-a702-920d77279786}</ProjectTypeGuids>
-    <Name>Linq2vk.Core.Silverlight.2010</Name>
-    <TargetFrameworkIdentifier>Silverlight</TargetFrameworkIdentifier>
-    <SilverlightApplication>false</SilverlightApplication>
-    <ValidateXaml>true</ValidateXaml>
-    <ThrowErrorsInValidation>false</ThrowErrorsInValidation>
-    <RootNamespace>Linq2vk.Core.Silverlight.2010</RootNamespace>
-    <TargetFrameworkProfile />
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE;SILVERLIGHT</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>3</WarningLevel>
-    <DocumentationFile>bin\Debug\Linq2vk.Core.Silverlight.2010.XML</DocumentationFile>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>3</WarningLevel>
-    <DocumentationFile>bin\Release\Linq2vk.Core.Silverlight.2010.XML</DocumentationFile>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="mscorlib" />
-    <Reference Include="FSharp.Core">
-      <HintPath>$(ProgramFiles)\Microsoft F#\Silverlight\Libraries\Client\$(SilverlightVersion)\FSharp.Core.dll</HintPath>
-    </Reference>
-    <Reference Include="Newtonsoft.Json.Silverlight">
-      <HintPath>..\..\lib\jsonnet\Silverlight\Newtonsoft.Json.Silverlight.dll</HintPath>
-    </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Net" />
-    <Reference Include="System.Windows" />
-    <Reference Include="System.Windows.Browser" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="..\Common\DataKind.fs">
-      <Link>DataKind.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\JsonParser.fs">
-      <Link>JsonParser.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Data.fs">
-      <Link>Data.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Parsers.fs">
-      <Link>Parsers.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Conversions.fs">
-      <Link>Conversions.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Net.fs">
-      <Link>Net.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Query.fs">
-      <Link>Query.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Api.fs">
-      <Link>Api.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\UserAPI.fs">
-      <Link>UserAPI.fs</Link>
-    </Compile>
-  </ItemGroup>
-  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
-  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
-  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.Common.targets" />
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-	     Other similar extension points exist, see Microsoft.Common.targets.
-	<Target Name="BeforeBuild">
-	</Target>
-	<Target Name="AfterBuild">
-	</Target>
-	-->
-</Project>

src/Linq2vk.Core.Silverlight/Linq2vk.Core.Silverlight.fsproj

-<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>9.0.30729</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{FDE76813-F32B-46F5-8688-6FFCB103E5AE}</ProjectGuid>
-    <ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
-    <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>Linq2vk.Core.Silverlight</RootNamespace>
-    <AssemblyName>Linq2vk.Core.Silverlight</AssemblyName>
-    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
-    <SilverlightApplication>false</SilverlightApplication>
-    <ValidateXaml>true</ValidateXaml>
-    <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>Bin\Debug</OutputPath>
-    <DefineConstants>DEBUG;TRACE;SILVERLIGHT</DefineConstants>
-    <NoStdLib>true</NoStdLib>
-    <NoConfig>true</NoConfig>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>Bin\Release</OutputPath>
-    <DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
-    <NoStdLib>true</NoStdLib>
-    <NoConfig>true</NoConfig>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="FSharp.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=a19089b1c74d0809, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>C:\Program Files\FSharp\silverlight\2.0\bin\FSharp.Core.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-    <Reference Include="mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, processorArchitecture=x86">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>C:\Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v3.0\mscorlib.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-    <Reference Include="Newtonsoft.Json.Silverlight, Version=3.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-      <HintPath>..\..\lib\jsonnet\Silverlight\Newtonsoft.Json.Silverlight.dll</HintPath>
-      <SpecificVersion>False</SpecificVersion>
-    </Reference>
-    <Reference Include="system, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>C:\Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v3.0\system.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-    <Reference Include="System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>C:\Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v3.0\System.Core.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-    <Reference Include="System.Net, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>C:\Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v3.0\System.Net.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-    <Reference Include="System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>C:\Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v3.0\System.Windows.dll</HintPath>
-      <Private>False</Private>
-    </Reference>
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="..\Common\DataKind.fs">
-      <Link>DataKind.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\JsonParser.fs">
-      <Link>JsonParser.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Data.fs">
-      <Link>Data.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Parsers.fs">
-      <Link>Parsers.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Conversions.fs">
-      <Link>Conversions.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Net.fs">
-      <Link>Net.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Query.fs">
-      <Link>Query.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Api.fs">
-      <Link>Api.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\UserAPI.fs">
-      <Link>UserAPI.fs</Link>
-    </Compile>
-  </ItemGroup>
-  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" />
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
-  -->
-  <ProjectExtensions>
-    <VisualStudio>
-      <FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
-        <SilverlightProjectProperties />
-      </FlavorProperties>
-    </VisualStudio>
-  </ProjectExtensions>
-</Project>

src/Linq2vk.Core.Tests/Linq2vk.Core.Tests.csproj

-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>9.0.30729</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{9DE8B3D9-45A2-44F3-8849-76041606C6BE}</ProjectGuid>
-    <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>Linq2vk.Core.Tests</RootNamespace>
-    <AssemblyName>Linq2vk.Core.Tests</AssemblyName>
-    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="nunit.framework, Version=2.2.7.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\..\lib\nunit.framework.dll</HintPath>
-    </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Core">
-      <RequiredTargetFramework>3.5</RequiredTargetFramework>
-    </Reference>
-    <Reference Include="System.Drawing" />
-    <Reference Include="System.Xml.Linq">
-      <RequiredTargetFramework>3.5</RequiredTargetFramework>
-    </Reference>
-    <Reference Include="System.Data.DataSetExtensions">
-      <RequiredTargetFramework>3.5</RequiredTargetFramework>
-    </Reference>
-    <Reference Include="System.Data" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Settings.local.cs" />
-    <Compile Include="SimpleTests.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\Linq2vk.Core\Linq2vk.Core.fsproj">
-      <Project>{C89BDE8B-95D3-4900-922F-764055ADA46B}</Project>
-      <Name>Linq2vk.Core</Name>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
-  -->
-</Project>

src/Linq2vk.Core.Tests/Properties/AssemblyInfo.cs

-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Linq2vk.Core.Tests")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Linq2vk.Core.Tests")]
-[assembly: AssemblyCopyright("")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("cb03135c-39e4-4dbf-91aa-5907be5d9ee5")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.1.*")]
-[assembly: AssemblyFileVersion("0.1.*.*")]

src/Linq2vk.Core.Tests/SimpleTests.cs

-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using NUnit.Framework;
-using Linq2vk.Core;
-using System.Drawing;
-
-namespace Linq2vk.Core.Tests {
-
-    [TestFixture]
-    public class SimpleTests {
-
-        private UserAPI _api;
-
-        [SetUp]
-        public void SetUp() {
-            _api = new UserAPI(Settings.SiteId);
-            _api.Login(Settings.EMail, Settings.Pwd);
-        }
-
-        [Test, Explicit]
-        public void NotATest() {
-            var friends = from f in _api.MyFriends
-                          where f.IsOnline
-                          select f;
-            foreach (var f in friends) {
-                Console.WriteLine(f.Name);
-            };
-
-            var updates = _api.StatusUpdates.Take(20).ToArray();
-            foreach (var u in updates) {
-                Console.WriteLine("{0} says: '{1}' ({2}, {3})", u.Name, u.Text, u.StatusId, u.UserId);
-            }
-
-            //var photos = _api.FriendsPhotos.Take(10).ToArray();
-            //foreach (var photo in photos) {
-            //    Console.WriteLine("User #{0} added photo '{1}'", photo.OwnerId, photo.ThumbnailUrl);
-            //}
-
-            var profile = _api.MyProfile;
-            Console.WriteLine("My name is: {0} {1} ({2})", profile.FirstName, profile.LastName, profile.MaidenName);
-            Console.WriteLine("My current status is: '{0}' ({1})", profile.CurrentStatus.Text, profile.CurrentStatus.Timestamp);
-            Console.WriteLine(profile.CityName);
-            Console.WriteLine(profile.Gender);
-            Console.WriteLine(profile.MaritalStatus);
-            Console.WriteLine(profile.PhotoUrl);
-            foreach (var f in profile.Friends) {
-                Console.WriteLine(f.Name);
-            };
-        }
-
-        [Test, Explicit]
-        public void InboxTest() {
-            var messages = _api.Inbox.Take(5);
-            foreach (var msg in messages) {
-                Console.WriteLine("Message: {0}, From: {1}, To: {3}, Text:'{2}'", msg.MessageId, msg.Sender.UserName, msg.Text, msg.Recipient.UserName);
-                Console.WriteLine("Sent at: {0}", msg.Timestamp);
-            }
-        }
-
-        [Test, Explicit]
-        public void OutboxTest() {
-            var messages = _api.Outbox.Take(5);
-            foreach (var msg in messages) {
-                Console.WriteLine("Message: {0}, From: {1}, To: {3}, Text:'{2}'", msg.MessageId, msg.Sender.UserName, msg.Text, msg.Recipient.UserName);
-                Console.WriteLine("Sent at: {0}", msg.Timestamp);
-            }
-        }
-
-
-    }
-}

src/Linq2vk.Core/Linq2vk.Core.2010.fsproj

-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>8.0.30703</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{219f29d7-c41a-4c66-a740-8f20d724fd2b}</ProjectGuid>
-    <OutputType>Library</OutputType>
-    <RootNamespace>Linq2vk.Core.2010</RootNamespace>
-    <AssemblyName>Linq2vk.Core.2010</AssemblyName>
-    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
-    <Name>Linq2vk.Core.2010</Name>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <Tailcalls>false</Tailcalls>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <WarningLevel>3</WarningLevel>
-    <DocumentationFile>bin\Debug\Linq2vk.Core.2010.XML</DocumentationFile>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <Tailcalls>true</Tailcalls>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <WarningLevel>3</WarningLevel>
-    <DocumentationFile>bin\Release\Linq2vk.Core.2010.XML</DocumentationFile>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="mscorlib" />
-    <Reference Include="FSharp.Core" />
-    <Reference Include="Newtonsoft.Json">
-      <HintPath>..\..\lib\jsonnet\DotNet\Newtonsoft.Json.dll</HintPath>
-    </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Numerics" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="..\Common\DataKind.fs">
-      <Link>DataKind.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\JsonParser.fs">
-      <Link>JsonParser.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Data.fs">
-      <Link>Data.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Parsers.fs">
-      <Link>Parsers.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Conversions.fs">
-      <Link>Conversions.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Net.fs">
-      <Link>Net.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Query.fs">
-      <Link>Query.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Api.fs">
-      <Link>Api.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\UserAPI.fs">
-      <Link>UserAPI.fs</Link>
-    </Compile>
-  </ItemGroup>
-  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
-  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-	     Other similar extension points exist, see Microsoft.Common.targets.
-	<Target Name="BeforeBuild">
-	</Target>
-	<Target Name="AfterBuild">
-	</Target>
-	-->
-</Project>

src/Linq2vk.Core/Linq2vk.Core.fsproj

-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>8.0.30703</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{c89bde8b-95d3-4900-922f-764055ada46b}</ProjectGuid>
-    <OutputType>Library</OutputType>
-    <RootNamespace>Linq2vk.Core</RootNamespace>
-    <AssemblyName>Linq2vk.Core</AssemblyName>
-    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
-    <Name>Linq2vk.Core</Name>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <Tailcalls>false</Tailcalls>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <WarningLevel>4</WarningLevel>
-    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
-    <WarningsAsErrors>
-    </WarningsAsErrors>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <Tailcalls>true</Tailcalls>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <WarningLevel>3</WarningLevel>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="mscorlib" />
-    <Reference Include="FSharp.Core" />
-    <Reference Include="Newtonsoft.Json">
-      <HintPath>..\..\lib\jsonnet\DotNet\Newtonsoft.Json.dll</HintPath>
-    </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Core">
-      <RequiredTargetFramework>3.5</RequiredTargetFramework>
-    </Reference>
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="..\Common\DataKind.fs">
-      <Link>DataKind.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\JsonParser.fs">
-      <Link>JsonParser.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Data.fs">
-      <Link>Data.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Parsers.fs">
-      <Link>Parsers.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Conversions.fs">
-      <Link>Conversions.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Net.fs">
-      <Link>Net.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Query.fs">
-      <Link>Query.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\Api.fs">
-      <Link>Api.fs</Link>
-    </Compile>
-    <Compile Include="..\Common\UserAPI.fs">
-      <Link>UserAPI.fs</Link>
-    </Compile>
-  </ItemGroup>
-  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" />
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-	     Other similar extension points exist, see Microsoft.Common.targets.
-	<Target Name="BeforeBuild">
-	</Target>
-	<Target Name="AfterBuild">
-	</Target>
-	-->
-</Project>

src/Linq2vk.sln

-
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
-Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Linq2vk.Core", "Linq2vk.Core\Linq2vk.Core.fsproj", "{C89BDE8B-95D3-4900-922F-764055ADA46B}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Linq2vk.Core.Tests", "Linq2vk.Core.Tests\Linq2vk.Core.Tests.csproj", "{9DE8B3D9-45A2-44F3-8849-76041606C6BE}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Linq2vk.Core.Silverlight", "Linq2vk.Core.Silverlight\Linq2vk.Core.Silverlight.fsproj", "{FDE76813-F32B-46F5-8688-6FFCB103E5AE}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{C89BDE8B-95D3-4900-922F-764055ADA46B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{C89BDE8B-95D3-4900-922F-764055ADA46B}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{C89BDE8B-95D3-4900-922F-764055ADA46B}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{C89BDE8B-95D3-4900-922F-764055ADA46B}.Release|Any CPU.Build.0 = Release|Any CPU
-		{9DE8B3D9-45A2-44F3-8849-76041606C6BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{9DE8B3D9-45A2-44F3-8849-76041606C6BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{9DE8B3D9-45A2-44F3-8849-76041606C6BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{9DE8B3D9-45A2-44F3-8849-76041606C6BE}.Release|Any CPU.Build.0 = Release|Any CPU
-		{FDE76813-F32B-46F5-8688-6FFCB103E5AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{FDE76813-F32B-46F5-8688-6FFCB103E5AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{FDE76813-F32B-46F5-8688-6FFCB103E5AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{FDE76813-F32B-46F5-8688-6FFCB103E5AE}.Release|Any CPU.Build.0 = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal

src/Linq2vk.vs2010.sln

-
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
-Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Linq2vk.Core.2010", "Linq2vk.Core\Linq2vk.Core.2010.fsproj", "{219F29D7-C41A-4C66-A740-8F20D724FD2B}"
-EndProject
-Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Linq2vk.Core.Silverlight.2010", "Linq2vk.Core.Silverlight\Linq2vk.Core.Silverlight.2010.fsproj", "{05D5EDE1-5B6F-48D3-B627-E9BF498773EC}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{219F29D7-C41A-4C66-A740-8F20D724FD2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{219F29D7-C41A-4C66-A740-8F20D724FD2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{219F29D7-C41A-4C66-A740-8F20D724FD2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{219F29D7-C41A-4C66-A740-8F20D724FD2B}.Release|Any CPU.Build.0 = Release|Any CPU
-		{05D5EDE1-5B6F-48D3-B627-E9BF498773EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{05D5EDE1-5B6F-48D3-B627-E9BF498773EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{05D5EDE1-5B6F-48D3-B627-E9BF498773EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{05D5EDE1-5B6F-48D3-B627-E9BF498773EC}.Release|Any CPU.Build.0 = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal

src/UserAPI/Common/Api.fs

+namespace Linq2vk.Core.Implementation
+
+open Linq2vk.Core
+
+module Api =
+
+    let WindowWidth = 10
+
+    open DataKind
+
+    // q -- initial query (See Query module)
+    // w -- window size
+    // s -- initial index
+    let getWindowedFrom s w q =
+        let rec loop a b =
+            seq {
+                let url = q |> Query.addFrom a |> Query.addTo b |> Query.toUrl
+                printfn "Url: %s" url
+                let text = Net.requestTextSync url
+                match text with
+                | JsonArr arr ->
+                    yield! Seq.map string arr
+                    if arr.Count <> 0 then
+                        yield! loop (b+1) (b+w)
+                | JsonData o ->
+                    let (ok, dict) = o.TryGetValue("d")
+                    if ok then
+                        yield! Seq.map string dict
+                | JsonReturnCode c -> ()
+            }
+
+        loop s (w-1)
+    
+    let getAll =
+        getWindowedFrom 0 WindowWidth
+    
+    let getAllFrom s =
+        getWindowedFrom s WindowWidth
+        
+    let getOne q =
+        let url = q |> Query.toUrl
+        printfn "Url: %s" url
+        Net.requestTextSync url

src/UserAPI/Common/Conversions.fs

+namespace Linq2vk.Core
+
+[<RequireQualifiedAccess>] 
+module Conversions =
+    open System
+    open JsonParser
+    open Linq2vk.Core.Implementation.DataKind
+    
+    let apply parser xs =
+        JsonParser.parse parser (Seq.toArray xs)
+    
+    let toFriend = function
+        | JsonArr arr -> apply Parsers.friend arr
+        | _ -> raise <| NotSupportedException "Conversion only supported for JsonArr"
+        
+    let toItemArray conv = function
+        |JsonArr arr -> arr |> Seq.map (string >> conv) |> Seq.toArray
+        | _ -> raise <| NotSupportedException "Conversion only supported for JsonArr"
+
+    let toStatus = function
+        | JsonArr arr ->
+            apply Parsers.status arr
+        | JsonData o ->
+            apply Parsers.status (o.PropertyValues())
+        | _ -> raise <| NotSupportedException "Conversion only supported for JsonArr or JsonData"
+
+    let toPhoto = function
+        | JsonArr arr -> apply Parsers.photo arr
+        | _ -> raise <| NotSupportedException "Conversion only supported for JsonArr"
+
+    // TODO: implement a Json Object parsers equivalent to Json Array parsers to handle this kind of situation
+    open Tools
+    let toUserProfile = function
+        | JsonData o ->
+            { new IUserProfile with
+                override this.UserId = o.["id"] |> int64
+                override this.FirstName = o.["fn"] |> string'
+                override this.LastName = o.["ln"] |> string'
+                override this.MaidenName = o.["mn"] |> string'
+                override this.CurrentStatus = o.["actv"] |> string |> toStatus
+                override this.CountryId = o.["ht"].["coi"] |> int64
+                override this.ISOCountryCode = o.["ht"].["con"] |> string'
+                override this.CityId = o.["ht"].["cii"] |> int64
+                override this.CityName = o.["ht"].["cin"] |> string'
+                override this.Gender = o.["sx"] |> int |> enum<Gender>
+                override this.PhotoUrl = o.["bp"] |> string'
+                override this.BirthdayDay = o.["bd"] |> int
+                override this.BirthdayMonth = o.["bm"] |> int
+                override this.BirthdayYear = o.["by"] |> int
+                override this.MaritalStatus = o.["fs"] |> int |> enum<MaritalStatus>
+                override this.PoliticalViews = o.["pv"] |> int |> enum<PoliticalViews>
+                override this.Friends = o.["fr"].["d"] |> string |> toItemArray toFriend
+                override this.FriendsOnline = o.["fro"].["d"] |> string |> toItemArray toFriend
+                override this.FriendsMutual = o.["frm"].["d"] |> string |> toItemArray toFriend
+                override this.UploadedPhotos = o.["ph"].["d"] |> string |> toItemArray toPhoto
+                override this.PhotosWith = o.["phw"].["d"] |> string |> toItemArray toPhoto
+            }
+        | _ -> raise <| NotSupportedException "Conversion only supported for JsonData"
+        
+    let toMessage = function
+        | JsonArr arr -> apply Parsers.message arr
+        | _ -> raise <| NotSupportedException "Conversion only supported for JsonArr"

src/UserAPI/Common/Data.fs

+namespace Linq2vk.Core
+
+open System
+
+type Action =
+    | Profile
+
+    | Friends
+    | FriendsMutual
+    | FriendsOnline
+    | FriendsNew
+    
+    | Photos
+    | PhotosWith
+    | PhotosNew
+    
+    | Activity
+    
+    | Fave
+    | FaveOnline
+    | Faved
+    
+    | UpdatesActivity
+    | UpdatesFriends
+    | UpdatesPhotos
+    | UpdatesTaggedPhotos
+    
+    | Message
+    | Inbox
+    | Outbox
+    
+    
+type IFriend =
+    abstract Id : int64
+    abstract Name : string
+    abstract PhotoUrl : string
+    abstract IsOnline : bool
+    
+type IStatus =
+    abstract Id : string
+    abstract UserId : int64
+    abstract StatusId : int64
+    abstract Reserved : int
+    abstract Name : string
+    abstract Timestamp : DateTime
+    abstract Text : string
+    
+type IPhoto =
+    abstract Id : string
+    abstract OwnerId : int64
+    abstract PhotoId : int64
+    abstract ThumbnailUrl : string
+    abstract ImageUrl : string
+    
+type Gender =
+    | Female = 1
+    | Male   = 2
+
+type MaritalStatus =
+    | Single            = 1
+    | InRelationships   = 2
+    | Engaged           = 3
+    | Married           = 4
+    | Complicated       = 5
+    | LookingFor        = 6
+    
+type PoliticalViews =
+    | Communist         = 1
+    | Socialist         = 2
+    | Moderate          = 3
+    | Liberal           = 4
+    | Conservative      = 5
+    | Monarchist        = 6
+    | Ultraconservative = 7
+    | Apathetic         = 8
+    
+type IUserProfile =
+    abstract UserId : int64
+    abstract FirstName : string
+    abstract LastName : string
+    abstract MaidenName : string
+    abstract CurrentStatus : IStatus
+    abstract CountryId : int64
+    abstract ISOCountryCode : string
+    abstract CityId : int64
+    abstract CityName : string
+    abstract Gender : Gender
+    abstract PhotoUrl : string
+    abstract BirthdayDay : int
+    abstract BirthdayMonth : int
+    abstract BirthdayYear : int
+    abstract MaritalStatus : MaritalStatus
+    abstract PoliticalViews : PoliticalViews
+    abstract Friends : IFriend[]
+    abstract FriendsOnline : IFriend[]
+    abstract FriendsMutual : IFriend[]
+    abstract UploadedPhotos : IPhoto[]
+    abstract PhotosWith : IPhoto[]
+    
+    
+type IUserDescriptor =
+    abstract UserId : int64
+    abstract UserName : string
+    abstract PhotoUrl : string
+    abstract ThumbnailFileName : string
+    abstract Gender : Gender
+    abstract IsOnline : bool
+    
+type IMessage =
+    abstract MessageId : int64
+    abstract Timestamp : DateTime
+    abstract Text : string
+    abstract Sender : IUserDescriptor
+    abstract Recipient : IUserDescriptor
+    abstract IsRead : bool

src/UserAPI/Common/DataKind.fs

+namespace Linq2vk.Core.Implementation
+
+module DataKind =
+
+    open Newtonsoft.Json.Linq
+    
+    let (|JsonData|JsonArr|JsonReturnCode|) (s:string) =
+//        printfn "(%s)" s
+        if s.[0] = '{' then
+            let jo = JObject.Parse s
+            let (b, d) = jo.TryGetValue("ok")
+            if b then
+                JsonReturnCode (int d)
+            else
+                JsonData jo
+        else
+            JsonArr (JArray.Parse s)

src/UserAPI/Common/JsonParser.fs

+namespace Linq2vk.Core
+
+module JsonParserImpl =
+    open Newtonsoft.Json.Linq
+
+    type JsonArrayParser<'a> =
+        JsonArrayParser of (JToken[] -> ('a * JToken[]) list)
+
+    let runParser (JsonArrayParser p) tokens =
+        p tokens
+
+    exception JsonParserException of string  
+    
+    let getParsingResult = function
+        | [] -> raise <| JsonParserException("Parsing failed")
+        | [(res, _)] -> res
+        | _ -> raise <| System.NotSupportedException("This should not normally happen")
+
+    type JsonArrayBuilder() = 
+        member this.Return(x) =
+            JsonArrayParser (fun ts -> [(x, ts)])
+        member this.Bind(p, f) =
+            JsonArrayParser (fun ts ->
+                match runParser p ts with
+                | [(r, ts')] -> runParser (f r) ts'
+                | _ -> []
+            )
+
+module JsonParser =             
+    open JsonParserImpl
+    
+    let jarr = JsonArrayBuilder()
+    
+    let at idx =
+        JsonArrayParser (fun ts ->
+            if ts.Length <> 0 && idx < ts.Length then
+                [(ts.[idx]), ts]
+            else
+                []
+        )
+        
+    let parse parser tokens =
+        runParser parser tokens
+            |> getParsingResult
+    
+    let parseOrDefault parser defaultValue =
+        JsonArrayParser (fun ts ->
+            match runParser parser ts with
+            | [] -> [(defaultValue, ts)]
+            | res -> res
+        )
+        
+    let (<|>) = parseOrDefault
+    
+    let parseOrFail condition parser =
+        JsonArrayParser (fun ts ->
+            if condition then
+                runParser parser ts
+            else
+                []
+        )
+        
+    let (<?>) = parseOrFail
+    
+    let tokenAtAs idx converter =
+        jarr {
+            let! t = at idx
+            return (converter t)
+        }
+        
+    let (<@>) converter idx =
+        tokenAtAs idx converter
+        
+        
+#if DEBUG
+// simple tests to be used in REPL
+//
+module JsonParserTests =
+    open JsonParser
+    open Newtonsoft.Json.Linq
+
+    let singleItemParser =        
+        jarr {
+            let! a =  int <@> 0
+            let! c = (string <@> 2) <|> "default"
+            return (a,c)
+        }
+
+    let tokens = JArray.Parse("[1,2]") |> Seq.toArray
+    let a = parse singleItemParser tokens
+#endif

src/UserAPI/Common/Net.fs

+namespace Linq2vk.Core.Implementation
+
+module Net =
+    open System
+    open System.IO
+    open System.Net
+
+#if ASYNC    
+    let getUrlResponse (url:string) =
+        async {
+            let req = HttpWebRequest.Create(url)
+            let! resp = req.AsyncGetResponse()
+            return resp :?> HttpWebResponse
+        }
+   
+    let processUrlResponse (url:string) f =
+        async {
+            let! resp = getUrlResponse url
+            return f resp
+        }
+        
+    let requestStream url =
+        async {
+            let! resp = getUrlResponse url
+            return resp.GetResponseStream()
+        }
+        
+    let requestText url =
+        async {
+            let! resp = getUrlResponse url
+            use stream = resp.GetResponseStream()
+            use reader = new StreamReader(stream)
+            return reader.ReadToEnd()
+        }
+#endif
+
+    let getUrlResponseSync (url:string) =
+        let req = HttpWebRequest.Create(url) :?> HttpWebRequest
+        use allDone = new System.Threading.AutoResetEvent(false)
+        
+        let (resp:WebResponse ref) = ref null
+        let onResponse (asyncRes:IAsyncResult) =
+            resp := req.EndGetResponse(asyncRes)
+            
+            let httpResp = !resp :?> HttpWebResponse
+            printfn "%A" httpResp.ResponseUri
+            
+            allDone.Set() |> ignore
+            ()
+            
+        let asyncRes = req.BeginGetResponse(AsyncCallback(onResponse), null)
+        
+        // TODO: Possible problems with infinite lock.
+        allDone.WaitOne() |> ignore
+        !resp :?> HttpWebResponse
+   
+    let processUrlResponseSync (url:string) f =
+        let resp = getUrlResponseSync url
+        f resp
+        
+    let requestTextSync url =
+        let resp = getUrlResponseSync url
+        use stream = resp.GetResponseStream()
+        use reader = new StreamReader(stream)
+        reader.ReadToEnd()

src/UserAPI/Common/Parsers.fs

+namespace Linq2vk.Core
+
+open Linq2vk.Core.JsonParser
+
+module Tools =
+    open System
+    open Newtonsoft.Json.Linq        
+    open System.Text.RegularExpressions
+    
+    let unquote (s:string) =
+        s.[1..(s.Length-2)]
+        
+    let string' = unquote << string
+    
+    let anyString (token:JToken) =
+        if token.Type = JTokenType.String then
+            token |> string |> unquote
+        else
+            token |> string
+    
+    let intBool (token:JToken) =
+        0 <> (token |> int)
+
+    let UnixTimeStart = DateTime(1970, 1, 1)
+    let fromUnixtime (x:int64) = 
+         UnixTimeStart + TimeSpan.FromSeconds(x |> float)
+
+    let parseTimestamp (token:JToken) =
+        anyString token |> int64 |> fromUnixtime
+
+    let parseComplexId id =
+        let idRx = Regex("([0-9]+)_([\-0-9]+)")
+        let m = idRx.Match(id)
+        let parseGroup (i:int) =
+            m.Groups.[i].Value |> int64
+        
+        if m.Success then 
+            (parseGroup 1, parseGroup 2)
+        else
+            raise <| ArgumentException(sprintf "Invalid complex id format: %s" id)
+            
+    let asArray (token:JToken) =
+        Seq.toArray token
+    let childToken idx (token:JToken) =
+        (asArray token).[idx]
+            
+
+[<RequireQualifiedAccess>]
+module Parsers =
+    open System
+    open Tools
+
+    let friend =
+        jarr {
+            let! id = int64 <@> 0
+            let! name = string' <@> 1
+            let! photo = string' <@> 2
+            let! isOnline = intBool <@> 3
+
+            return {
+                new IFriend with 
+                    override this.Id = id
+                    override this.Name = name
+                    override this.PhotoUrl = photo
+                    override this.IsOnline = isOnline
+            }
+        }
+        
+    let status =
+        jarr {
+            let! id = string <@> 0
+            let! userId = int64 <@> 1
+            let! (_, statusId) = (parseComplexId << string) <@> 0
+            let! name = string' <@> 3
+            let! timestamp = (statusId <> -1L) <?> (parseTimestamp <@> 4) <|> DateTime.MinValue
+            let! text = string' <@> 5
+            return {
+                new IStatus with
+                    override this.Id = id
+                    override this.UserId = userId
+                    override this.StatusId = statusId
+                    override this.Reserved = 0
+                    override this.Name = name
+                    override this.Timestamp = timestamp
+                    override this.Text = text
+              }
+        }
+        
+    let photo =
+        jarr {
+            let! id = string <@> 0
+            let! (ownerId, photoId) = (parseComplexId << string) <@> 0
+            let! thumbnailUrl = string' <@> 1
+            let! imageUrl = string' <@> 2
+            return {
+                new IPhoto with
+                    override this.Id = id
+                    override this.OwnerId = ownerId
+                    override this.PhotoId = photoId
+                    override this.ThumbnailUrl = thumbnailUrl
+                    override this.ImageUrl = imageUrl
+            }
+        }
+    
+    let userDescription =
+        jarr {
+            let! userId = (int64 << anyString) <@> 0
+            let! name = string' <@> 1 <|> String.Empty
+            let! photoUrl = anyString <@> 2 <|> String.Empty
+            let! thumbnailFileName = anyString <@> 3 <|> String.Empty
+            let! gender = (enum<Gender> << int) <@> 4 <|> Gender.Male
+            let! isOnline = intBool <@> 5 <|> false
+            return {
+                new IUserDescriptor with
+                    override this.UserId = userId
+                    override this.UserName = name
+                    override this.PhotoUrl = photoUrl
+                    override this.ThumbnailFileName = thumbnailFileName
+                    override this.Gender = gender
+                    override this.IsOnline = isOnline
+            }
+        }
+        
+    let message =
+        jarr {
+            let! messageId = (int64 << anyString) <@> 0
+            let! timestamp = parseTimestamp <@> 1
+            let! text = (childToken 0 >> string) <@> 2
+            let! sender = (parse userDescription << asArray) <@> 3
+            let! recipient = (parse userDescription << asArray) <@> 4
+            let! isRead = intBool <@> 5
+            return {
+                new IMessage with
+                    override this.MessageId = messageId
+                    override this.Timestamp = timestamp
+                    override this.Text = text
+                    override this.Sender = sender
+                    override this.Recipient = recipient
+                    override this.IsRead = isRead
+                }
+        }
+        

src/UserAPI/Common/Query.fs

+namespace Linq2vk.Core.Implementation
+
+open System.Collections.Generic
+open Linq2vk.Core
+
+module Query =
+    
+    let init (sid:string) =
+        [("sid", sid)]
+        
+    let add (k:string) (v:'a) q =
+        (k, v.ToString()) :: q
+        
+    let toUrl q =
+        let prefix = "http://userapi.com/data?"
+        let makepair (k, v) =
+            sprintf "%s=%s" k v
+        let urlQuery = q |> (Seq.map makepair >> Seq.toArray >> (fun xs -> System.String.Join("&", xs)))
+        prefix + urlQuery
+
+    let addAction (act:Action) =
+        add "act" <|
+            match act with
+            | Friends               -> "friends"
+            | UpdatesActivity       -> "updates_activity"
+            | UpdatesFriends        -> "updates_friends"
+            | UpdatesPhotos         -> "updates_photos"
+            | UpdatesTaggedPhotos   -> "updates_tagged_photos"
+            | Profile               -> "profile"
+            | Inbox                 -> "inbox"
+            | Outbox                -> "outbox"
+            | _                     -> failwith "Not implemented"
+            
+    // TODO: why does not point-free style work here?
+    let addId id = add "id" id
+    let addTo toVal = add "to" toVal
+    let addFrom from = add "from" from

src/UserAPI/Common/UserAPI.fs

+namespace Linq2vk.Core
+
+open System
+open System.Net
+open System.Text.RegularExpressions
+open Linq2vk.Core.Implementation
+
+type UserAPI (prjId:int64) =
+    let WindowSize = 10
+    
+    let mutable _sid = String.Empty
+    
+    let query act =
+        Query.init _sid |> Query.addAction act
+        
+    let userQuery uid act =
+        query act |> Query.addId uid
+        
+    let getItem conv q =
+        q |> Api.getOne |> conv
+        
+    let getAllItems conv q =
+        q |> Api.getAll |> Seq.map conv
+    
+    member this.LoggedIn
+        with get () = String.IsNullOrEmpty(_sid)
+        
+    member this.Login(usr:string, pwd:string) =
+        let query =
+            sprintf "http://login.userapi.com/auth?login=force&site=%d&email=%s&pass=%s" prjId usr pwd
+            
+        let getSid (resp:HttpWebResponse) =        
+            let sidRx = Regex("sid=([a-z0-9]+)")
+            
+            let getMatchedGroup (rx:Regex) =
+                rx.Match >> (fun m -> m.Groups.[1].Value)
+
+            let sid =
+                resp.ResponseUri.AbsoluteUri |> getMatchedGroup sidRx                   
+            sid
+            
+        let sid =
+            Net.processUrlResponseSync query getSid
+        
+        _sid <- sid
+        this.LoggedIn
+
+    member private this.GetFriendsFrom(queryF) =
+        queryF Action.Friends
+        |> getAllItems Conversions.toFriend
+    
+    member private this.GetFriends(uid:int64) =
+        this.GetFriendsFrom (userQuery uid)
+            
+    member this.MyFriends
+        with get () =
+            this.GetFriendsFrom query
+        
+    member this.StatusUpdates
+        with get () =
+            query Action.UpdatesActivity
+            |> getAllItems Conversions.toStatus
+                
+    member this.FriendsOfFriends
+        with get () =
+            query Action.UpdatesFriends
+            |> getAllItems Conversions.toFriend
+            
+    member this.FriendsPhotos
+        with get () =
+            query Action.UpdatesPhotos
+            |> getAllItems Conversions.toPhoto
+            
+    member this.FriendsTaggedPhotos
+        with get () =
+            query Action.UpdatesTaggedPhotos
+            |> getAllItems Conversions.toPhoto
+
+    member private this.GetProfileFrom(queryF) =
+        queryF Action.Profile
+        |> getItem Conversions.toUserProfile
+    
+    member this.GetUserProfile (uid:int64) =
+        this.GetProfileFrom (userQuery uid)
+        
+    member this.MyProfile
+        with get () = 
+            this.GetProfileFrom query
+            
+    member private this.GetMessagesFor(action) =
+        match action with
+        | Action.Inbox | Action.Outbox //| Action.Message
+            -> query action 
+               |> getAllItems Conversions.toMessage
+        | _ -> raise <| NotSupportedException()
+            
+    member this.Inbox
+        with get () = this.GetMessagesFor Action.Inbox
+                
+    member this.Outbox 
+        with get () = this.GetMessagesFor Action.Outbox
+        

src/UserAPI/Linq2vk.Core.Silverlight/Linq2vk.Core.Silverlight.2010.fsproj

+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{05d5ede1-5b6f-48d3-b627-e9bf498773ec}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AssemblyName>Linq2vk.Core.Silverlight.2010</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
+    <FileAlignment>512</FileAlignment>
+    <AllowCrossTargeting>true</AllowCrossTargeting>
+    <ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{f2a71f9b-5d33-465a-a702-920d77279786}</ProjectTypeGuids>
+    <Name>Linq2vk.Core.Silverlight.2010</Name>
+    <TargetFrameworkIdentifier>Silverlight</TargetFrameworkIdentifier>
+    <SilverlightApplication>false</SilverlightApplication>
+    <ValidateXaml>true</ValidateXaml>
+    <ThrowErrorsInValidation>false</ThrowErrorsInValidation>
+    <RootNamespace>Linq2vk.Core.Silverlight.2010</RootNamespace>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;SILVERLIGHT</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>3</WarningLevel>
+    <DocumentationFile>bin\Debug\Linq2vk.Core.Silverlight.2010.XML</DocumentationFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>3</WarningLevel>
+    <DocumentationFile>bin\Release\Linq2vk.Core.Silverlight.2010.XML</DocumentationFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="mscorlib" />
+    <Reference Include="FSharp.Core">
+      <HintPath>$(ProgramFiles)\Microsoft F#\Silverlight\Libraries\Client\$(SilverlightVersion)\FSharp.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json.Silverlight">
+      <HintPath>..\..\lib\jsonnet\Silverlight\Newtonsoft.Json.Silverlight.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Net" />
+    <Reference Include="System.Windows" />
+    <Reference Include="System.Windows.Browser" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Common\DataKind.fs">
+      <Link>DataKind.fs</Link>
+    </Compile>
+    <Compile Include="..\Common\JsonParser.fs">
+      <Link>JsonParser.fs</Link>