Open andreasscherbaum opened 4 years ago
Looks like it's not a bug, but an expected behaviour, there is a different response now:
{
"purchaseId": "d67b790c25fd2203c4ee36617f6141a1",
"purchaseDate": 1597765436,
"purchasePrice": 10,
"id": "streak_freeze",
"itemName": "streak_freeze",
"quantity": 3
}
The quantity is just increasing, I assume it's like buying "in advance".
I think getting /2017-06-30/users/{userID}?fields=shopItems
and checking for streak_freeze
quantity before initiating a purchase is a solution.
So I can buy streaks in advance for as long as I have Lingots? ;-)
Hmmm
Well, it's still not what I expect buy_streak_freeze() to do ...
So I can buy streaks in advance for as long as I have Lingots? ;-)
I suppose so. I mean, why not? It might be useful in some cases, one can plan few days away in advance. Although, I am not sure if it works this way, it is just my assumption.
Well, it's still not what I expect buy_streak_freeze() to do ...
In my opinion it does what it says. It buys a streak freeze :) You can think about some additional method like restore_streak_freeze()
, but it's some additional feature, not API related.
The question is more to Duolingo API developers rather to this library.
Ok, i've tested it more. It does not go more than 3
purchased items, although lingots are charged..
@igorskh So basically "quantity" is only known after a purchase?
@igorskh So basically "quantity" is only known after a purchase?
No, it's not, you can always check current quantity here:
https://www.duolingo.com/2017-06-30/users/{userID}?fields=shopItems
It returns all purchased items including streak_freeze
:
[
{
"quantity": 3,
"purchaseDate": 1597768970,
"id": "streak_freeze",
"purchaseId": "2abbdba95ae154068f9202a37529e141",
"itemName": "streak_freeze",
"purchasePrice": 0
}
]
Looking at the documentation for this library, I don't see a method to retrieve that information. Am I correct?
I can confirm the behavior of the API has changed. It buys the streak regardless of whether or not you already have one purchased and deducts additional lingots. It does not appear to give you extra "freezes", just burns through lingots faster. I suggest adding a get_streak_freeze() method that returns True or False if the streak is active (assuming that's possible) or something similar.
I've a workaround until the API/library is fixed -
def item_already_equipped(lingo, item):
if item == 'streak_freeze':
return lingo.__dict__['user_data'].__dict__['tracking_properties']['num_item_streak_freeze'] > 0
if item == 'rupee_wager':
return lingo.__dict__['user_data'].__dict__['tracking_properties']['has_item_rupee_wager']
def process_single_user(username, password):
import duolingo
try:
lingo = duolingo.Duolingo(username, password)
except ValueError:
raise Exception("Username Invalid")
stuff_to_purchase = ['streak_freeze', 'rupee_wager']
for item in stuff_to_purchase:
if(item_already_equipped(lingo, item)):
print("Item "+ item + " already equipped! Skipping...")
continue
try:
print("Trying to Buy " + item + " for " + username)
lingo.buy_item(item, 'en')
print("Bought " + item + " for " + username)
except duolingo.AlreadyHaveStoreItemException: # no longer triggered AFAIK
print("Item Already Equipped")
except Exception:
raise ValueError("Unable to buy " + item)
Did anyone test that quantity
of streak_freeze
decreases after being used?
I am not entirely sure, but I think I could increase it from 1 to 3.
Planning to keep my streak on line today for testing. Will report back if it reduces to less than 3
I can confirm that quantity increases
> GET /2017-06-30/users/665585457?fields=shopItems
> Host: www.duolingo.com
> user-agent: insomnia/2020.3.3
< HTTP/2 200
< date: Fri, 21 Aug 2020 19:20:39 GMT
< content-type: application/json
{
"shopItems": [
{
"quantity": 1,
"purchaseDate": 1598037464,
"id": "streak_freeze",
"itemName": "streak_freeze",
"purchasePrice": 0
}
]
}
> POST /2017-06-30/users/665585457/shop-items HTTP/2
> Host: www.duolingo.com
> user-agent: insomnia/2020.3.3
| {
| "itemName": "streak_freeze",
| "learningLanguage": "es"
| }
< HTTP/2 200
< date: Fri, 21 Aug 2020 19:44:30 GMT
< content-type: application/json
{
"purchaseDate": 1598039070,
"purchasePrice": 10,
"id": "streak_freeze",
"itemName": "streak_freeze",
"quantity": 2
}
> GET /2017-06-30/users/665585457?fields=shopItems
> Host: www.duolingo.com
> user-agent: insomnia/2020.3.3
< HTTP/2 200
< date: Fri, 21 Aug 2020 19:47:19 GMT
< content-type: application/json
{
"shopItems": [
{
"quantity": 2,
"purchaseDate": 1598039070,
"id": "streak_freeze",
"itemName": "streak_freeze",
"purchasePrice": 0
}
]
}
From what I see, this is also not returned anymore:
It just doesn't return anything now, and script crashes
simplejson.errors.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Quantity is decreasing as well, so it makes sense to allow buying more than 1 streak, even current limit to 3 is maybe just a bug in the API, or they are testing, at the end it is not an official feature.
It appears that if you purchase multiple freezes, the freeze is extended for multiple days. My current quantity is now at 2 (was 3 yesterday), but the UI still showed the freeze in place. It looks like they might be adding a multi day streak feature (or at least it appears to be a hidden feature).
@alexsanjoseph how can we use your work around. Could you please explain where we need to paste it and what we need to call to make it happen.
@TiloGit - I run this as a Lambda function in AWS (https://github.com/alexsanjoseph/duolingo-save-streak).
The issue is that Duolingo keeps buying streak freeze even when it has reached the limit. Before this was enforced as a limit from their API and hence we could do EAFP and catch the error without an issue. However, the lingo class already has info on whether to buy it or not, and so you purchase it only when you check and identify that you don't have the particular item in your bag.
def item_already_equipped(lingo, item):
if item == 'streak_freeze':
return lingo.__dict__['user_data'].__dict__['tracking_properties']['num_item_streak_freeze'] > 0
if item == 'rupee_wager':
return lingo.__dict__['user_data'].__dict__['tracking_properties']['has_item_rupee_wager']
This function does the checking.
here my hack for other ppl info. (not pretty but seem to do the job) https://gist.github.com/TiloGit/51367aca5a4df726a7061288d8430828
Started a couple days ago: every time I run buy_streak_freeze(), I don't get a AlreadyHaveStoreItemException exception anymore, but it started "charging" me Lingots every time - even though I already have a streak equipped.
Anyone knows what's wrong there, or how to fix/prevent that?