Compare commits

...

10 Commits

Author SHA1 Message Date
Alexander Popov f637a97fc2 use EditorConfig 2021-07-25 15:32:55 +03:00
Alexander Popov f6f3a653df use black library for code 2020-10-05 02:32:15 +03:00
Alexander Popov b63e1f1536
Merge pull request #3 from Nitemice/fix/export-formats
Fix/export formats
2020-10-04 13:25:09 +03:00
Nitemice f799d31052 Improved README
Fixed some spelling mistakes
Added info on export formats
2020-10-04 18:09:15 +11:00
Nitemice abbf9df872 Minor export improvements
Added album field to CSV.
Write all records to CSV at once.
Renamed "is as" export mode to "dump". It's more accurate and nicer with
a single word.
2020-10-04 17:59:57 +11:00
Nitemice a0a84a212f Added field names to export
Added header row to CSV.
Added field names for simple export.
2020-10-04 17:09:41 +11:00
Nitemice 679bcdd633 Fix simple and csv export
JSON needs an array to append into.

CSV was misspelt.
Also fixed extra newlines being added to CSV file on Windows.
2020-10-04 17:04:43 +11:00
Alexander Popov 029af27ea2 add export more format 2020-07-02 04:03:07 +03:00
Alexander Popov 4c1480be4c new version 2020-07-02 02:24:51 +03:00
Alexander Popov f2d7ad058c add link to web service 2019-08-30 02:04:45 +03:00
8 changed files with 189 additions and 80 deletions

14
.editorconfig Normal file
View File

@ -0,0 +1,14 @@
# EditorConfig is awesome: https://EditorConfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{*.json,config.json.example}]
indent_style = tab
indent_size = 4

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
*.json
*.csv
*.pyc
build/
dist/

View File

@ -1,19 +1,26 @@
![Version](https://img.shields.io/pypi/v/lastfm-backup.svg?style=flat-square)
![License](https://img.shields.io/pypi/l/lastfm-backup.svg?style=flat-square)
![PyVersion](https://img.shields.io/pypi/pyversions/lastfm-backup.svg?style=flat-square)
# Last.fm Backup
**How to use:**
--------------
* [Get](http://www.last.fm/api/account/create) API Key.
![Version](https://img.shields.io/pypi/v/lastfm-backup.svg?style=for-the-badge)
![License](https://img.shields.io/pypi/l/lastfm-backup.svg?style=for-the-badge)
![PyVersion](https://img.shields.io/pypi/pyversions/lastfm-backup.svg?style=for-the-badge)
### Features:
* Simple
* Three formats for export data:
1. `dump` - JSON, direct from API
2. `simple` - Artist, track name, album & date as JSON
3. `csv` - Artist, track name, album & date as comma separated values
### How to use:
* Stop scrobbling!
* Rename `config.json.example` to `config.json` and edit.
* Run script `lastfm_backup.py`.
* Modify `config.json`.
* [Get API Key](http://www.last.fm/api/account/create).
* Run `lastfm_backup.py`.
* WAIT =)
**TODO:**
--------
- [ ] web service
- [ ] more output types (sqlite, csv)
- [ ] confirugurabled output
### TODO:
- [ ] web service [see lfmbak](https://github.com/iiiypuk/lfmbak)
- [x] more output types (sqlite, csv)
- [ ] configurable output
- [ ] continue backup
- [ ] multithreading
- [ ] multi-threading

View File

@ -1,4 +1,5 @@
{
"username" : "",
"api_key" : ""
"username" : "",
"api_key" : "",
"export_format": "dump, simple, csv"
}

View File

@ -1,61 +1,138 @@
#!/usr/bin/env python3
import json
import urllib.request
import csv
import os.path
import requests
__author__ = 'Alexander Popov'
__version__ = '1.0.1'
__license__ = 'Unlicense'
__author__ = "Alexander Popov"
__version__ = "2.1.0"
__license__ = "Unlicense"
def get_pages(username, api_key):
response = urllib.request.urlopen(
'http://ws.audioscrobbler.com/2.0/'
'?method=user.getrecenttracks&user={0}&api_key={1}&format=json'
'&limit=200'.format(username, api_key)).read().decode("utf8")
pages = int(json.loads(response)['recenttracks']['@attr']['totalPages'])
def get_pages(username, api_key, limit=200):
""" Getting the number of pages with scrobbling data """
return(pages)
response = requests.get(
"https://ws.audioscrobbler.com/2.0/"
"?method=user.getrecenttracks&user="
"{0}&api_key={1}&format=json&limit={2}".format(username, api_key, limit)
)
data = json.loads(response.content.decode("utf8"))
return int(data["recenttracks"]["@attr"]["totalPages"])
def get_scrobbles(username, api_key, page):
response = json.loads(urllib.request.urlopen(
'http://ws.audioscrobbler.com/2.0/'
'?method=user.getrecenttracks&user={0}&api_key={1}&format=json'
'&limit=200&page={2}'.format(username, api_key, page)
).read().decode("utf8"))['recenttracks']['track']
def get_page(username, api_key, page, limit=200):
""" Getting scrobbling data from a page """
return(response)
response = requests.get(
"https://ws.audioscrobbler.com/2.0/"
"?method=user.getrecenttracks&user={0}&api_key={1}&format=json"
"&limit={2}&page={3}".format(username, api_key, limit, page)
)
if __name__ == '__main__':
CFG = dict()
data = json.loads(response.content.decode("utf8"))
if os.path.exists('./config.json'):
with open('./config.json') as f:
CFG = json.loads(f.read())
return data["recenttracks"]["track"]
def get_now_scrobbling(username, api_key):
""" Getting now scrobbling track """
response = requests.get(
"https://ws.audioscrobbler.com/2.0/"
"?method=user.getrecenttracks&user={0}"
"&api_key={1}&format=json&limit=1".format(username, api_key)
)
data = json.loads(response.content.decode("utf-8"))
if "@attr" in data["recenttracks"]["track"][0]:
return True
else:
CFG['api_key'] = input('API Key: ')
CFG['username'] = input('Username: ')
return False
PAGES = get_pages(CFG['username'], CFG['api_key'])
curPage = 1
tracks = []
while curPage <= PAGES:
print('\r{0}% [{1} of {2}]'.format((curPage * 100 / PAGES), curPage, PAGES), end='')
response = get_scrobbles(CFG['username'], CFG['api_key'], curPage)
def scrobbling_export(tracks, username, export_format="dump"):
""" Save scrobbled track via various format """
if export_format == "dump":
with open("%s.json" % (username), "w", encoding="utf-8") as f:
data = json.dumps(tracks, indent=4, sort_keys=True, ensure_ascii=False)
f.write(data)
elif export_format == "simple":
_ = []
for track in tracks:
_.append(
{
"artist": track["artist"]["#text"],
"name": track["name"],
"album": track["album"]["#text"],
"date": int(track["date"]["uts"]),
}
)
with open("%s.json" % (username), "w", encoding="utf-8") as f:
data = json.dumps(_, indent=4, sort_keys=True, ensure_ascii=False)
f.write(data)
elif export_format == "csv":
_ = []
for track in tracks:
_.append(
[
track["artist"]["#text"],
track["name"],
track["album"]["#text"],
int(track["date"]["uts"]),
]
)
with open("%s.csv" % (username), "w", encoding="utf-8", newline="") as f:
data = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC, delimiter=",")
data.writerow(["artist", "track", "album", "date"])
data.writerows(_)
return 1
if __name__ == "__main__":
_ = dict()
if os.path.exists("./config.json"):
with open("./config.json") as f:
_ = json.loads(f.read())
else:
_["api_key"] = input("API Key: ")
_["username"] = input("Username: ")
api_key, username = _["api_key"], _["username"]
total_pages = get_pages(username, api_key)
current_page = 1
scrobbled = []
while current_page <= total_pages:
print(
"\r{0:.2f}% [{1} of {2}]".format(
(current_page * 100 / total_pages), current_page, total_pages
),
end="",
)
response = get_page(username, api_key, current_page)
for track in response:
tracks.append({'artist': track['artist']['#text'],
'name': track['name'],
'album': track['album']['#text'],
'date': track['date']['uts']})
scrobbled.append(track)
curPage += 1
current_page += 1
with open('%s.json' % (CFG['username']), 'w+', encoding='utf-8') as f:
f.write(
json.dumps(tracks, indent=4, sort_keys=True, ensure_ascii=False))
# if get_now_scrobbling(username, api_key):
# scrobbled.pop(0)
print('\n{0} tracks saved in {1}.json!'.format(
len(tracks), CFG['username'],))
if scrobbling_export(scrobbled, username, _["export_format"]):
print("\n{0} tracks saved!".format(len(scrobbled), username))

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
requests==2.24.0

View File

@ -2,18 +2,24 @@
import lastfm_backup as lfm
API_KEY = '0'
USERNAME = 'admin'
API_KEY = "0"
USERNAME = "admin"
if __name__ == '__main__':
pages = lfm.get_pages(USERNAME, API_KEY)
count = 0
if __name__ == "__main__":
pages = lfm.get_pages(USERNAME, API_KEY)
count = 0
for page in range(1, pages + 1):
tracks = lfm.get_scrobbles(USERNAME, API_KEY, page)
for page in range(1, pages + 1):
tracks = lfm.get_scrobbles(USERNAME, API_KEY, page)
for track in tracks:
print('%s - %s' % (track['artist']['#text'], track['name'],))
count = count + 1
for track in tracks:
print(
"%s - %s"
% (
track["artist"]["#text"],
track["name"],
)
)
count = count + 1
print('\nTotal scrobbling tracks: %d' % count)
print("\nTotal scrobbling tracks: %d" % count)

View File

@ -3,19 +3,21 @@ import setuptools
import lastfm_backup
setuptools.setup(
name='lastfm-backup',
name="lastfm-backup",
version=lastfm_backup.__version__,
description='Last.fm scrobbles backup',
description="Last.fm scrobbling backup",
author=lastfm_backup.__author__,
author_email='iiiypuk@fastmail.fm',
url='https://github.com/iiiypuk/lastfm-backup',
py_modules=['lastfm_backup'],
scripts=['lastfm_backup.py'],
author_email="iiiypuk@fastmail.fm",
url="https://github.com/iiiypuk/lastfm-backup",
py_modules=["lastfm_backup"],
scripts=["lastfm_backup.py"],
license=lastfm_backup.__license__,
platforms='any',
keywords=['last.fm', 'lastfm', 'backup'],
classifiers=['License :: Public Domain',
'Programming Language :: Python :: 3',
'Operating System :: OS Independent'],
python_requires='>=3.0'
platforms="any",
keywords=["last.fm", "lastfm", "backup"],
classifiers=[
"License :: Public Domain",
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
],
python_requires=">=3.2",
)