In Elm (0.18) I'm calling one http DELETE endpoint that if successful responds with 200 and an empty body.
In this case (of success) I need to pass back a message with the initial id (OnDelete playerId). But as the body is empty i can't parse it from there.
Currently I'm doing it like this, but is there a more elegant way to write the expect part of Http.Request:
Http.expectStringResponse (\response -> Ok playerId)
?
This reflects my current code:
deletePlayer : PlayerId -> Cmd Msg
deletePlayer playerId =
deleteRequest playerId
|> Http.send OnDelete
deleteRequest : PlayerId -> Http.Request PlayerId
deleteRequest playerId =
Http.request
{ body = Http.emptyBody
, expect = Http.expectStringResponse (\response -> Ok playerId)
, headers = []
, method = "DELETE"
, timeout = Nothing
, url = "http://someHost/players/" ++ playerId
, withCredentials = False
}
type alias PlayerId =
String
Elm v0.19 added expectWhatever. It behaves slightly different with the Result being checked for errors, but a similar effect.
I've created a helper expectUnit for "empty" 200 responses.
expectUnit : Expect ()
expectUnit =
Http.expectStringResponse << always <| Ok ()
deleteThing : String -> Request ()
deleteThing path =
Http.request
{ method = "DELETE"
, headers = []
, url = "http://localhost/api"
, body = Http.jsonBody <| Encode.object [ ( "path", Encode.string path ) ]
, expect = expectUnit
, timeout = Nothing
, withCredentials = False
}
But for you, the best you could get is.
{ ...
, expect = Http.expectStringResponse << always <| Ok playerId
...
}
Or you could create a helper (which is actually the singleton or pure for Expect)
alwaysExpect : a -> Expect a
alwaysExpect =
Http.expectStringResponse << always << Ok
Which could be used like
{ ...
, expect = alwaysExpect playerId
...
}
Related
I have written the following code:
require "http/client"
require "myhtml"
puts "Give me the URL of the page to be scraped."
url = gets
html=<<-HTML
[Here goes the html of the website to be scraped]
HTML
myhtml = Myhtml::Parser.new(html)
myhtml.nodes(:div).each do |node|
id = node.attribute_by("id")
if first_link = node.scope.nodes(:a).first?
href = first_link.attribute_by("href")
link_text = first_link.inner_text
puts "div with id #{id} have link [#{link_text}](#{href})"
else
puts "div with id #{id} have no links"
end
end
How do I get the html from the webpage that I am trying to scrape in a string so that I can replace
html=<<-HTML
[Here goes the html of the website to be scraped]
HTML
with something like
response = requests.get(url)
html = BeautifulSoup(response.text, 'html.parser')
from the following Python code:
url = input("What is the address of the web page in question?\n")
response = requests.get(url)
html = BeautifulSoup(response.text, 'html.parser')
or let html = reqwest::get(url).await?.text().await?; from the following Rust code:
println!("Give me the URL of the page to be scraped.");
let mut url = String::new();
io::stdin().read_line(&mut url).expect("Failed to read line");
let html = reqwest::get(url).await?.text().await?;
The documentation of the shard myhtml does not provide enough
examples for me to figure this out.
Can it be done with Crystal's HTTP client from their
standard library?
When I replaced
html=<<-HTML
[Here goes the html of the website to be scraped]
HTML
with
response = HTTP::Client.get url
html = response.body
I get the following error:
response = HTTP::Client.get url #no overload matches 'HTTP::Client.get' with type (String | Nil)
^--
Error: no overload matches 'HTTP::Client.get' with type (String | Nil)
Overloads are:
- HTTP::Client.get(url : String | URI, headers : HTTP::Headers | ::Nil = nil, body : BodyType = nil, tls : TLSContext = nil)
- HTTP::Client.get(url : String | URI, headers : HTTP::Headers | ::Nil = nil, body : BodyType = nil, tls : TLSContext = nil, &block)
- HTTP::Client.get(url, headers : HTTP::Headers | ::Nil = nil, tls : TLSContext = nil, *, form : String | IO | Hash)
- HTTP::Client.get(url, headers : HTTP::Headers | ::Nil = nil, tls : TLSContext = nil, *, form : String | IO | Hash, &block)
Couldn't find overloads for these types:
- HTTP::Client.get(Nil)
I am able to get the text from the web page
by hard coding it, e.g. response = HTTP::Client.get "https://github.com/monero-project/monero/releases"
but that would no suffice as I want the app to be interactive.
You are close, it is the type system that is complaining. HTTP::Client.get expects a String (or rather String | URL). However, in your code your url variable can also be nil and is of type String?, which is short for String | Nil. If you hard-code the URL, it cannot be nil but is always of type String. Therefore the HTTP::Client.get call works.
Check out the documentation of the get function:
def gets(chomp = true) : String?
Reads a line from this IO. A line is terminated by the \n character. Returns nil if called at the end of this IO.
There are multiple ways to address it, but the basic idea is that you have to make sure that url cannot be nil when you make the HTTP call. For example:
url = gets
if url
# now url cannot be nil
response = HTTP::Client.get url
html = response.body
puts html
end
Further reading: if var
First of all, this is the /data/data/com.android.providers.tv/databases/tv.db
Then in my code I applied this code snippet to retrieve the channels:
TvInputManager tv = (TvInputManager)getApplicationContext().getSystemService(Context.TV_INPUT_SERVICE);
List<TvInputInfo> list = tv.getTvInputList();
ContentResolver cr = getContentResolver();
Iterator<TvInputInfo> it = list.iterator();
while(it.hasNext()) {
TvInputInfo aux = it.next();
Uri uri = TvContract.buildChannelsUriForInput(aux.getId());
Cursor cur = cr.query(uri, projection, null, null ,null);
cur.moveToFirst();
do {
val channel = Channel.fromCursor(channelCursor)
Log.d("Log", "New channel ${channel.id} : ${channel.displayName} : ${channel.packageName}"}
} while (channelCursor.moveToNext() && channelCursor.isLast.not())
}
Unfortunately, I get as input_id for TvInputInfo aux only
com.google.android.videos/.tv.usecase.tvinput.playback.TvInputService
thus my cursor returns only 1 Channel with _id = 4.
Despite, I did neither got the input_id's _id=22 for amazon nor _id=25 for netflix, as listed in the screenshot above, I would like to get all above shown 18 Channels.
How can I query all Channels, also those with an empty input_id?
You get restricted by TvContract.buildChannelsUriForInput(aux.getId()); what depends on input_id. When you take TvContractCompat.Channels.CONTENT_URI for Uri, you will get:
Uri uri = TvContractCompat.Channels.CONTENT_URI;
Cursor cur = getContentResolver().query(uri, projection, null, null ,null);
cur.moveToFirst();
do {
val channel = Channel.fromCursor(channelCursor)
Log.d("Log", "New channel ${channel.id} : ${channel.displayName} : ${channel.packageName}"}
} while (channelCursor.moveToNext())
I'm trying to get audienc name aduience id etc we' ve created on our google analytics account. We have around 2,4k audiences list but I can just get 999 of them. I can't find any soultions. Code is below
function main() {
var spreadsheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadshe');
var sheet = spreadsheet.getSheetByName('Sh');
function listRemarketingAudiences(accountId, propertyId) {
var request = Analytics.Management.RemarketingAudience.list(
accountId,
propertyId
);
var leno = Object.keys(request).length
console.log(leno);
sheet.getRange(1,1).setValue("audianceName");
sheet.getRange(1,2).setValue("audianceId");
sheet.getRange(1,3).setValue("audianceDefinition");
sheet.getRange(1,4).setValue("audianceDescription");
for ( var i = 2; i <3000; i++) {
var audianceName = request.items[i+154].name ;
Logger.log(audianceName);
console.log(i);
sheet.getRange(i,1).setValue("elo")
var audianceId = request.items[i].id ;
sheet.getRange(i,2).setValue(audianceId);
// var audianceId = request.items[i].
var audienceDefinition = request.items[i].audienceDefinition ;
sheet.getRange(i,3).setValue(audienceDefinition);
var audienceDescription = request.items[i].description ;
sheet.getRange(i,4).setValue(audienceDescription);
};
}
listRemarketingAudiences('xxxxx', 'UA-xxxxx-1');
}
Currently you are supplying only the required parameters: accountId and webPropertyId. These are necessary to identify the Analytics property, where you are looking for the data.
Based on the documentation, optional parameters can be passed, which are actually in connection with the pagination, which you are trying to achieve.
As the developer guide is not mentioning the absolute limit of the result, you could experiment with higher limits, with a code something like this:
request = gapi.client.analytics.management.remarketingAudience.list(
{
'accountId': accountId,
'webPropertyId': propertyId,
'max-results': 5000
}
If you can't get all the data at once, you need to implement paging yourself, where an other paramerer, start-index will be necessary. You need to call the function several times, preferably from a loop, where start index is continuously increased.
request = gapi.client.analytics.management.remarketingAudience.list(
{
'accountId': accountId,
'webPropertyId': propertyId,
'start-index': 999,
'max-results': 1000
}
I wrote sth like this:
var optional = {'startIndex': 12,
'maxresults': 212};
function listRemarketingAudiences (accountId, propertyId, optional){
var request = Analytics.Management.RemarketingAudience.list(
accountId,
propertyId,
optional.maxresults
);
and an error occure:
We're sorry, a server error occurred. Please wait a bit and try again. (line 9, file "Code")
I am trying to update my bitcoin price field in my List Token Model in my update function. This is my code I cannot seem to get it to only update the price field. Do I need to access the list elements seeing as my model is list? Is this possible to do using record syntax in elm?
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Bass exposing (style, center, h1)
import Http
import Json.Decode as Decode
main =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
------------- MODEL
type alias Model =
{ tokens : List Token
}
init : (Model, Cmd Msg)
init =
(initialModel , Cmd.none)
initialModel : Model
initialModel =
{ tokens = [Token "Bitcoin" "150" "11000.00"]
}
type alias Token =
{ name : String
, holdings : String
, price : String
}
------------- UPDATE
type Msg
= FetchDatabasePrice | FetchLivePrice (Result Http.Error String)
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
FetchDatabasePrice ->
(model, getPrice )
FetchLivePrice (Ok newPrice) ->
( { model | price = newPrice }, Cmd.none )
FetchLivePrice (Err _) ->
(model,Cmd.none)
getPrice : Cmd Msg
getPrice =
let
url = "https://api.coinmarketcap.com/v1/ticker/bitcoin/"
request = Http.get url decodedUrl
in
Http.send FetchLivePrice request
decodedUrl : Decode.Decoder String
decodedUrl = Decode.at ["price_usd"] Decode.string
------------- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
------------- VIEW
view : Model -> Html Msg
view model =
div []
[nav
, div [] [list model.tokens]
, div [] [ button [onClick (FetchDatabasePrice) ] [text "Fetch Price"] ]
]
------BROKEN INTO PIECES---------
nav : Html Msg
nav = div [Bass.style
[center
, Bass.h1
, [("background-color", "black")
, ("color", "white")
]
]
]
[ div [] [text "Crypto Nutshell"]]
list : List Token -> Html Msg
list tokens =
div [Bass.style
[Bass.left_align
]
]
[div [ class "p1"]
[ table []
[ thead []
[ tr []
[ th [] [text "Name"]
, th [] [text "Holdings"]
, th [] [text "Price"]
, th [] [text "Actions"]
]
]
, tbody [] (List.map tokenRow tokens)
]
]
]
tokenRow : Token -> Html Msg
tokenRow token =
tr []
[ td [] [ text token.name ]
, td [] [ text token.holdings ]
, td [] [ text token.price ]
]
This is my error:
-- TYPE MISMATCH ------------------------------------------------------ test.elm
The definition of `update` does not match its type annotation.
50| update : Msg -> Model -> (Model, Cmd Msg)
51| update msg model =
52|> case msg of
53|> FetchDatabasePrice ->
54|> (model, getPrice )
55|> FetchLivePrice (Ok newPrice) ->
56|> ( { model | price = newPrice }, Cmd.none )
57|> FetchLivePrice (Err _) ->
58|> (model,Cmd.none)
The type annotation for `update` says it always returns:
( Model, Cmd Msg )
But the returned value (shown above) is a:
( { b | price : String }, Cmd Msg )
Hint: The record fields do not match up. One has tokens. The other has price.
-- TYPE MISMATCH ------------------------------------------------------ test.elm
`model` is being used in an unexpected way.
56| ( { model | price = newPrice }, Cmd.none )
^^^^^
Based on its definition, `model` has this type:
Model
But you are trying to use it as:
{ b | price : a }
Hint: The record fields do not match up. One has tokens. The other has price.
The type errors are fundamentally telling you your issue - you are trying to work on a Token, but you don't have one - you have a Model.
How do we get from one to the other? Well. We start with a model, and we can do model.tokens to get a List Token. We then want to modify that list to contain the new tokens, updated. The normal way to do this is with List.map. This operates on each Token and gives us the updated list. Following these steps:
FetchLivePrice (Ok newPrice) ->
let
updatePrice = (\token -> { token | price = newPrice })
updated = List.map updatePrice model.tokens
in
({ model | tokens = updated }, Cmd.none )
Now, the solution I've given is a simple one that will fall apart when you have multiple different tokens (they will all get changed at the same time). As you only have one right now, the same thing could be achieved just by simplifying the model to take only a single token, not a list.
You will need to start identifying which token you are getting the price for so you can update the right one, if you want to be able to use the ability to have multiple tokens.
In reality, you probably want this to end up looking something like:
FetchLivePrice tokenId (Ok newPrice) ->
({ model | tokens = tokenUpdatePrice tokenId newPrice model.tokens, Cmd.none)
Where tokenUpdatePrice is a function that manipulates your list (or other data structure - a dictionary might be appropriate, although you might need to store a separate order for presentation) to update the appropriate records. tokenId will be something used to identify the token.
I have a collection with over 1000 json documents. I want to now delete all the documents in that collection.
Is there any way of doing it from the portal using a query?
PS: I know I can delete the collection and re-create it or use a c# application to do it.
No, there is no equivalent to the SQL DELETE expression in DocumentDB so there is no way to do it with a query. Here is a stored procedure (CoffeeScript) that does this for me when I want to delete based upon a query.
deleteSomeDocuments = (memo) ->
collection = getContext().getCollection()
unless memo?
memo = {}
if memo.returnDeleted
unless memo.deleted?
memo.deleted = []
else
memo.returnDeleted = false
stillQueuingOperations = true
query = () ->
if stillQueuingOperations
responseOptions =
pageSize: memo.remaining
setBody()
if memo.filterQuery?
memo.stillQueueing = collection.queryDocuments(collection.getSelfLink(), memo.filterQuery, responseOptions, onReadDocuments)
else
memo.stillQueueing = collection.readDocuments(collection.getSelfLink(), responseOptions, onReadDocuments)
onReadDocuments = (err, resources, options) ->
if err
throw err
if resources.length isnt memo.remaining
throw new Error("Expected memo.remaining (#{memo.remaining}) and the number of rows returned (#{resources.length}) to match. They don't.")
memo.stillQueueing = true
while memo.remaining > 0 and memo.stillQueueing
oldDocument = resources[memo.remaining - 1]
documentLink = oldDocument._self
etag = oldDocument._etag
options = {etag} # Sending the etag per best practice, but not handling it if there is conflict.
getContext().getResponse().setBody(memo)
memo.stillQueueing = collection.deleteDocument(documentLink, options)
if memo.stillQueueing
if memo.returnDeleted
memo.deleted.push(oldDocument)
memo.remaining--
setBody = () ->
getContext().getResponse().setBody(memo)
query()
return memo
exports.deleteSomeDocuments = deleteSomeDocuments