Skip to content

Commit

Permalink
Merge pull request #12 from perrinjerome/fix/win
Browse files Browse the repository at this point in the history
Fix windows compatibility because of : in filenames and missing encoding
  • Loading branch information
perrinjerome committed Apr 23, 2024
2 parents 057b9cd + 628bb60 commit ddb7027
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 56 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python: ["3.8", "3.9", "3.10", "3.11"]
python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Setup Python
Expand Down
9 changes: 5 additions & 4 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -17,15 +17,16 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pylint mypy yapf isort .
pip install pylint mypy ruff isort .
- name: Analysing the code with pylint
run: |
pylint `ls -R|grep .py$|xargs`
- name: Analysing the code with mypy
run: |
mypy --strict `ls -R|grep .py$|xargs`
- name: Check formatting with yapf
- name: Check with ruff
run: |
yapf --diff `ls -R|grep .py$|xargs`
ruff check `ls -R|grep .py$|xargs`
ruff format --diff `ls -R|grep .py$|xargs`
- name: Check import order with isort
uses: jamescurtin/isort-action@master
99 changes: 52 additions & 47 deletions mitene_download.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Download medias from https://mitene.us/ or https://family-album.com/
"""
__version__ = '0.2.0'
"""Download medias from https://mitene.us/ or https://family-album.com/"""

__version__ = "0.2.1"

import argparse
import asyncio
Expand All @@ -9,6 +9,7 @@
import json
import mimetypes
import os
import platform
import sys
import urllib.parse
from typing import Awaitable
Expand All @@ -17,8 +18,7 @@


async def gather_with_concurrency(n: int, *tasks: Awaitable[None]) -> None:
"""Like asyncio.gather but limit the number of concurent tasks.
"""
"""Like asyncio.gather but limit the number of concurent tasks."""
semaphore = asyncio.Semaphore(n)

async def sem_task(task: Awaitable[None]) -> None:
Expand All @@ -29,11 +29,11 @@ async def sem_task(task: Awaitable[None]) -> None:


async def download_media(
session: aiohttp.ClientSession,
url: str,
destination_filename: str,
media_name: str,
verbose: bool,
session: aiohttp.ClientSession,
url: str,
destination_filename: str,
media_name: str,
verbose: bool,
) -> None:
"""Download one media from URL"""
if not os.path.exists(destination_filename):
Expand All @@ -50,10 +50,10 @@ async def download_media(


async def async_main() -> None:
parser = argparse.ArgumentParser(prog='mitene_download', description=__doc__)
parser = argparse.ArgumentParser(prog="mitene_download", description=__doc__)
parser.add_argument(
"album_url",
help="""
"album_url",
help="""
URL of the album.
This is the URL obtained by inviting a family member for the web version.
Expand All @@ -72,70 +72,75 @@ async def async_main() -> None:
os.unlink(tmp_file)

download_coroutines = []
async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(
total=datetime.timedelta(minutes=30).total_seconds())) as session:

async with aiohttp.ClientSession(
timeout=aiohttp.ClientTimeout(total=datetime.timedelta(minutes=30).total_seconds())
) as session:
page = 1
while True:
r = await session.get(f"{args.album_url}?page={page}")
response_text = await r.text()
if page == 1 and 'Please enter your password' in response_text:
if page == 1 and "Please enter your password" in response_text:
if not args.password:
print(
'Album is password protected, please specify password with --password',
file=sys.stderr)
"Album is password protected, please specify password with --password",
file=sys.stderr,
)
sys.exit(1)
authenticity_token = response_text.split(
'name="authenticity_token" value="')[1].split('"')[0]
authenticity_token = response_text.split('name="authenticity_token" value="')[
1
].split('"')[0]
assert authenticity_token, "Could not parse authenticity token"
r = await session.post(
f"{args.album_url}/login",
data={
'session[password]': args.password,
'authenticity_token': authenticity_token
},
f"{args.album_url}/login",
data={
"session[password]": args.password,
"authenticity_token": authenticity_token,
},
)
if r.url.path.endswith('/login'):
print('Could not authenticate, maybe password is incorrect',
file=sys.stderr)
if r.url.path.endswith("/login"):
print("Could not authenticate, maybe password is incorrect", file=sys.stderr)
sys.exit(1)
continue

page_text = response_text.split("//<![CDATA[\nwindow.gon={};gon.media=")[
1].split(";gon.familyUserIdToColorMap=")[0]
page_text = response_text.split("//<![CDATA[\nwindow.gon={};gon.media=")[1].split(
";gon.familyUserIdToColorMap="
)[0]
data = json.loads(page_text)

page += 1
if not data["mediaFiles"]:
break
for media in data["mediaFiles"]:
filename = urllib.parse.urlparse(
media.get("expiringVideoUrl",
media["expiringUrl"])).path.split("/")[-1]
media.get("expiringVideoUrl", media["expiringUrl"])
).path.split("/")[-1]
filename = f'{media["tookAt"]}-{filename}'
if platform.system() == "Windows":
filename = filename.replace(":", "")
if not os.path.splitext(filename)[1]:
filename = filename + mimetypes.guess_extension(media['contentType'])
filename = filename + mimetypes.guess_extension(media["contentType"])
destination_filename = os.path.join(
args.destination_directory,
filename,
args.destination_directory,
filename,
)

download_coroutines.append(
download_media(
session,
f"{args.album_url}/media_files/{media['uuid']}/download",
destination_filename,
media['uuid'],
args.verbose,
))
download_media(
session,
f"{args.album_url}/media_files/{media['uuid']}/download",
destination_filename,
media["uuid"],
args.verbose,
)
)

if media["comments"]:
comment_filename = os.path.splitext(destination_filename)[0] + ".md"
with open(comment_filename + ".tmp", "w") as comment_f:
with open(comment_filename + ".tmp", "w", encoding="utf-8") as comment_f:
for comment in media["comments"]:
if not comment["isDeleted"]:
comment_f.write(
f'**{comment["user"]["nickname"]}**: {comment["body"]}\n\n'
f'**{comment["user"]["nickname"]}**: {comment["body"]}\n\n'
)
os.rename(comment_filename + ".tmp", comment_filename)

Expand All @@ -148,5 +153,5 @@ def main() -> None:
loop.run_until_complete(async_main())


if __name__ == '__main__':
main()
if __name__ == "__main__":
main()
9 changes: 5 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,20 @@ Source = "https://github.com/perrinjerome/mitene_download"
[[project.authors]]
name = "Jérome Perrin"

[tool.yapf]
based_on_style = "pep8"
indent_width = 2

[tool.pylint.messages_control]
disable = "all"
enable = [
"E",
"unused-variable",
"unused-import",
"unspecified-encoding",
"unreachable",
"duplicate-key",
]

[tool.ruff]
indent-width = 2

[tool.tox]
legacy_tox_ini = """
[tox]
Expand All @@ -43,6 +43,7 @@ legacy_tox_ini = """
py311
py310
py39
py38
[testenv]
commands = mitene_download --help
Expand Down

0 comments on commit ddb7027

Please sign in to comment.