Compare commits

...
Author SHA1 Message Date
Alexander Graf fdcf2e1367 Release of Version 4.8.4 2022-01-15 17:11:45 +01:00
Alexander Graf ca78fee307 Revert date_utc and date_local being timezone aware
Fixes #1379.

Revert "Make {Post,StoryItem}.date_utc timezone aware"
d864ce08ff.

Revert "Remove unnecessary conversion to timezone aware timestamp (#1372)"
555c86633c.

Revert "Timezone option for datetime style formatting (#1316)"
21365ec668.
2022-01-15 17:08:04 +01:00
Alexander Graf d6e5e31005 Release of Version 4.8.3 2022-01-07 14:56:40 +01:00
Alexander Graf d864ce08ff Make {Post,StoryItem}.date_utc timezone aware
Also simplify {Post,StoryItem}.date_local.

Discussed in #1316.
2022-01-07 14:53:23 +01:00
Eduardo Kalinowski 555c86633c Remove unnecessary conversion to timezone aware timestamp (#1372)
Post.date_local now already returns a timestamp with the appropriate
timezone.
2022-01-07 14:31:41 +01:00
Misael 21365ec668 Timezone option for datetime style formatting (#1316)
Add timezone awareness for datetime objects returned by `date_local` and `date_utc`.
Fixes #1305.
2021-12-31 16:50:16 +01:00
Alexander Graf 6343e9a69d Release of Version 4.8.2 2021-11-27 16:25:12 +01:00
Alexander Graf 06574eb428 Fix KeyError on attempt to get incomplete location
Fixes #1349.
2021-11-27 16:25:12 +01:00
JeremyKj87 815ba83d77 avoid comments endless loop - check if query_response is always the same (#1347) 2021-11-27 15:47:32 +01:00
fireattack 470fc0d905 Fix KeyError for video_url, and better workflow (#1321)
Fixes #1320.
2021-11-12 15:21:33 +01:00
Alexander Graf 0300d8a4f1 Fix CI for Python 3.10 2021-11-12 14:32:15 +01:00
7 changed files with 42 additions and 32 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.8, 3.9]
python-version: ["3.8", "3.9", "3.10"]
steps:
- name: Checkout Instaloader Repository
uses: actions/checkout@v2
+2 -2
View File
@@ -10,9 +10,9 @@ jobs:
- name: Checkout Instaloader repository
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v1
uses: actions/setup-python@v2
with:
python-version: 3.9
python-version: "3.9"
architecture: x64
- name: Get the tagged version
id: get_version
+1 -1
View File
@@ -45,7 +45,7 @@ with open('__main__.py', 'w+') as f:
# install dependencies and invoke PyInstaller
commands = ["pip install pipenv==2020.11.15",
"pipenv sync --dev",
f"pipenv --python {sys.version_info.major}.{sys.version_info.minor} sync --dev",
"pipenv run pyinstaller --log-level=DEBUG instaloader.spec"]
for command in commands:
+1 -1
View File
@@ -1,7 +1,7 @@
"""Download pictures (or videos) along with their captions and other metadata from Instagram."""
__version__ = '4.8.1'
__version__ = '4.8.4'
try:
+6 -3
View File
@@ -453,9 +453,12 @@ class Instaloader:
def save_location(self, filename: str, location: PostLocation, mtime: datetime) -> None:
"""Save post location name and Google Maps link."""
filename += '_location.txt'
location_string = (location.name + "\n" +
"https://maps.google.com/maps?q={0},{1}&ll={0},{1}\n".format(location.lat,
location.lng))
if location.lat is not None and location.lng is not None:
location_string = (location.name + "\n" +
"https://maps.google.com/maps?q={0},{1}&ll={0},{1}\n".format(location.lat,
location.lng))
else:
location_string = location.name
with open(filename, 'wb') as text_file:
with BytesIO(location_string.encode()) as bio:
shutil.copyfileobj(cast(IO, bio), text_file)
+9 -8
View File
@@ -133,14 +133,15 @@ class NodeIterator(Iterator[T]):
return item
if self._data['page_info']['has_next_page']:
query_response = self._query(self._data['page_info']['end_cursor'])
page_index, data = self._page_index, self._data
try:
self._page_index = 0
self._data = query_response
except KeyboardInterrupt:
self._page_index, self._data = page_index, data
raise
return self.__next__()
if self._data['edges'] != query_response['edges']:
page_index, data = self._page_index, self._data
try:
self._page_index = 0
self._data = query_response
except KeyboardInterrupt:
self._page_index, self._data = page_index, data
raise
return self.__next__()
raise StopIteration()
@property
+22 -16
View File
@@ -35,8 +35,8 @@ PostLocation.id.__doc__ = "ID number of location."
PostLocation.name.__doc__ = "Location name."
PostLocation.slug.__doc__ = "URL friendly variant of location name."
PostLocation.has_public_page.__doc__ = "Whether location has a public page."
PostLocation.lat.__doc__ = "Latitude (:class:`float`)."
PostLocation.lng.__doc__ = "Longitude (:class:`float`)."
PostLocation.lat.__doc__ = "Latitude (:class:`float` or None)."
PostLocation.lng.__doc__ = "Longitude (:class:`float` or None)."
class Post:
@@ -377,20 +377,23 @@ class Post:
def video_url(self) -> Optional[str]:
"""URL of the video, or None."""
if self.is_video:
version_urls = [self._field('video_url')]
version_urls = []
try:
version_urls.append(self._field('video_url'))
except (InstaloaderException, KeyError, IndexError) as err:
self._context.error(f"Warning: Unable to fetch video from graphql of {self}: {err}")
if self._context.iphone_support and self._context.is_logged_in:
try:
version_urls.extend(version['url'] for version in self._iphone_struct['video_versions'])
except (InstaloaderException, KeyError, IndexError) as err:
self._context.error(f"Unable to fetch high-quality video version of {self}: {err}")
return version_urls[0]
else:
version_urls = list(dict.fromkeys(version_urls))
if len(version_urls) == 0:
return None
if len(version_urls) == 1:
return version_urls[0]
url_candidates: List[Tuple[int, str]] = []
for idx, version_url in enumerate(version_urls):
if any(url_candidate[1] == version_url for url_candidate in url_candidates):
# Skip duplicates
continue
try:
url_candidates.append((
int(self._context.head(version_url, allow_redirects=True).headers.get('Content-Length', 0)),
@@ -578,7 +581,7 @@ class Post:
loc.update(self._context.get_json("explore/locations/{0}/".format(location_id),
params={'__a': 1})['native_location_data']['location_info'])
self._location = PostLocation(location_id, loc['name'], loc['slug'], loc['has_public_page'],
loc['lat'], loc['lng'])
loc.get('lat'), loc.get('lng'))
return self._location
@@ -1129,20 +1132,23 @@ class StoryItem:
def video_url(self) -> Optional[str]:
"""URL of the video, or None."""
if self.is_video:
version_urls = [self._node['video_resources'][-1]['src']]
version_urls = []
try:
version_urls.append(self._node['video_resources'][-1]['src'])
except (InstaloaderException, KeyError, IndexError) as err:
self._context.error(f"Warning: Unable to fetch video from graphql of {self}: {err}")
if self._context.iphone_support and self._context.is_logged_in:
try:
version_urls.extend(version['url'] for version in self._iphone_struct['video_versions'])
except (InstaloaderException, KeyError, IndexError) as err:
self._context.error(f"Unable to fetch high-quality video version of {self}: {err}")
return version_urls[0]
else:
version_urls = list(dict.fromkeys(version_urls))
if len(version_urls) == 0:
return None
if len(version_urls) == 1:
return version_urls[0]
url_candidates: List[Tuple[int, str]] = []
for idx, version_url in enumerate(version_urls):
if any(url_candidate[1] == version_url for url_candidate in url_candidates):
# Skip duplicates
continue
try:
url_candidates.append((
int(self._context.head(version_url, allow_redirects=True).headers.get('Content-Length', 0)),
@@ -1553,7 +1559,7 @@ class TopSearchResults:
place = location.get('place', {})
slug = place.get('slug')
loc = place.get('location', {})
yield PostLocation(int(loc['pk']), loc['name'], slug, None, loc['lat'], loc['lng'])
yield PostLocation(int(loc['pk']), loc['name'], slug, None, loc.get('lat'), loc.get('lng'))
def get_hashtag_strings(self) -> Iterator[str]:
"""