- formatting with black
- added YAML files in case I ever want to use the saved favs as entries in my site - some tiny amount of code refactoring
This commit is contained in:
parent
c7f4aaf8dc
commit
5e5f2e2cf7
10 changed files with 350 additions and 389 deletions
|
@ -161,13 +161,6 @@ class ASLike(common.ImgFav):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
|
||||||
def exists(self):
|
|
||||||
maybe = glob.glob("%s*" % self.targetprefix)
|
|
||||||
if len(maybe):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def published(self):
|
def published(self):
|
||||||
return arrow.get(self.like.get("published_at"))
|
return arrow.get(self.like.get("published_at"))
|
||||||
|
@ -193,10 +186,6 @@ class ASLike(common.ImgFav):
|
||||||
cntr = cntr + 1
|
cntr = cntr + 1
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def run(self):
|
|
||||||
if not self.exists:
|
|
||||||
self.fetch_images()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
t = ASFavs()
|
t = ASFavs()
|
||||||
|
|
104
DeviantArt.py
104
DeviantArt.py
|
@ -9,39 +9,39 @@ import settings
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
class DAFavs(common.Favs):
|
class DAFavs(common.Favs):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__('deviantart')
|
super().__init__("deviantart")
|
||||||
self.client = deviantart.Api(
|
self.client = deviantart.Api(
|
||||||
keys.deviantart.get('key'),
|
keys.deviantart.get("key"), keys.deviantart.get("secret"), scope="user"
|
||||||
keys.deviantart.get('secret'),
|
|
||||||
scope='user'
|
|
||||||
)
|
)
|
||||||
self.favfolder = None
|
self.favfolder = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def feeds(self):
|
def feeds(self):
|
||||||
logging.info('Generating OPML feeds for DeviantArt')
|
logging.info("Generating OPML feeds for DeviantArt")
|
||||||
feeds = []
|
feeds = []
|
||||||
offset = 0
|
offset = 0
|
||||||
has_more = True
|
has_more = True
|
||||||
while has_more:
|
while has_more:
|
||||||
logging.info('Generating OPML feeds for DeviantArt: offset %d' % offset)
|
logging.info("Generating OPML feeds for DeviantArt: offset %d" % offset)
|
||||||
try:
|
try:
|
||||||
following = self.client.get_friends(
|
following = self.client.get_friends(
|
||||||
username=keys.deviantart.get('username'),
|
username=keys.deviantart.get("username"), offset=offset, limit=24
|
||||||
offset=offset,
|
|
||||||
limit=24
|
|
||||||
)
|
)
|
||||||
offset = following.get('next_offset')
|
offset = following.get("next_offset")
|
||||||
for follow in following.get('results'):
|
for follow in following.get("results"):
|
||||||
u = follow.get('user').username.lower()
|
u = follow.get("user").username.lower()
|
||||||
feeds.append({
|
feeds.append(
|
||||||
'text': u,
|
{
|
||||||
'xmlUrl': "https://backend.deviantart.com/rss.xml?q=gallery%%3A%s" % u,
|
"text": u,
|
||||||
'htmlUrl': "https://www.deviantart.com/%s" % u
|
"xmlUrl": "https://backend.deviantart.com/rss.xml?q=gallery%%3A%s"
|
||||||
})
|
% u,
|
||||||
has_more = following.get('has_more')
|
"htmlUrl": "https://www.deviantart.com/%s" % u,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
has_more = following.get("has_more")
|
||||||
except deviantart.api.DeviantartError as e:
|
except deviantart.api.DeviantartError as e:
|
||||||
print(e)
|
print(e)
|
||||||
break
|
break
|
||||||
|
@ -50,18 +50,16 @@ class DAFavs(common.Favs):
|
||||||
def run(self):
|
def run(self):
|
||||||
offset = 0
|
offset = 0
|
||||||
while not self.favfolder:
|
while not self.favfolder:
|
||||||
logging.info('fetching for DeviantArt: offset %d' % offset)
|
logging.info("fetching for DeviantArt: offset %d" % offset)
|
||||||
try:
|
try:
|
||||||
folders = self.client.get_collections(
|
folders = self.client.get_collections(
|
||||||
username=keys.deviantart.get('username'),
|
username=keys.deviantart.get("username"), offset=offset, limit=24
|
||||||
offset=offset,
|
|
||||||
limit=24
|
|
||||||
)
|
)
|
||||||
offset = folders.get('next_offset')
|
offset = folders.get("next_offset")
|
||||||
for r in folders.get('results'):
|
for r in folders.get("results"):
|
||||||
if r.get('name') == 'Featured':
|
if r.get("name") == "Featured":
|
||||||
self.favfolder = r.get('folderid')
|
self.favfolder = r.get("folderid")
|
||||||
if (folders.get('has_more') == False):
|
if folders.get("has_more") == False:
|
||||||
break
|
break
|
||||||
except deviantart.api.DeviantartError as e:
|
except deviantart.api.DeviantartError as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
@ -73,17 +71,17 @@ class DAFavs(common.Favs):
|
||||||
try:
|
try:
|
||||||
fetched = self.client.get_collection(
|
fetched = self.client.get_collection(
|
||||||
self.favfolder,
|
self.favfolder,
|
||||||
username=keys.deviantart.get('username'),
|
username=keys.deviantart.get("username"),
|
||||||
offset=offset,
|
offset=offset,
|
||||||
limit=24,
|
limit=24,
|
||||||
#mature_content=True
|
# mature_content=True
|
||||||
)
|
)
|
||||||
for r in fetched.get('results'):
|
for r in fetched.get("results"):
|
||||||
fav = DAFav(r)
|
fav = DAFav(r)
|
||||||
fav.run()
|
fav.run()
|
||||||
offset = fetched.get('next_offset')
|
offset = fetched.get("next_offset")
|
||||||
has_more = fetched.get('has_more')
|
has_more = fetched.get("has_more")
|
||||||
if (has_more == False):
|
if has_more == False:
|
||||||
break
|
break
|
||||||
except deviantart.api.DeviantartError as e:
|
except deviantart.api.DeviantartError as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
@ -91,7 +89,7 @@ class DAFavs(common.Favs):
|
||||||
|
|
||||||
|
|
||||||
class DAFav(common.ImgFav):
|
class DAFav(common.ImgFav):
|
||||||
def __init__(self, deviation, ):
|
def __init__(self, deviation):
|
||||||
self.deviation = deviation
|
self.deviation = deviation
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -100,8 +98,10 @@ class DAFav(common.ImgFav):
|
||||||
@property
|
@property
|
||||||
def author(self):
|
def author(self):
|
||||||
return {
|
return {
|
||||||
'name': self.deviation.author,
|
"name": self.deviation.author.username,
|
||||||
'url': 'http://%s.deviantart.com' % self.deviation.author
|
"id": self.deviation.author.userid,
|
||||||
|
"image": self.deviation.author.usericon,
|
||||||
|
"url": "http://%s.deviantart.com" % self.deviation.author.username,
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -116,7 +116,7 @@ class DAFav(common.ImgFav):
|
||||||
def content(self):
|
def content(self):
|
||||||
if self.deviation.excerpt:
|
if self.deviation.excerpt:
|
||||||
return "%s" % self.deviation.excerpt
|
return "%s" % self.deviation.excerpt
|
||||||
return ''
|
return ""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def title(self):
|
def title(self):
|
||||||
|
@ -128,22 +128,16 @@ class DAFav(common.ImgFav):
|
||||||
@property
|
@property
|
||||||
def targetprefix(self):
|
def targetprefix(self):
|
||||||
return os.path.join(
|
return os.path.join(
|
||||||
settings.paths.get('archive'),
|
settings.paths.get("archive"),
|
||||||
'favorite',
|
"favorite",
|
||||||
"deviantart_%s_%s_%s" % (
|
"deviantart_%s_%s_%s"
|
||||||
common.slugfname('%s' % self.deviation.author),
|
% (
|
||||||
|
common.slugfname("%s" % self.deviation.author),
|
||||||
self.id,
|
self.id,
|
||||||
common.slugfname('%s' % self.title)
|
common.slugfname("%s" % self.title),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
|
||||||
def exists(self):
|
|
||||||
maybe = glob.glob("%s*" % self.targetprefix)
|
|
||||||
if len(maybe):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def published(self):
|
def published(self):
|
||||||
return arrow.get(self.deviation.published_time)
|
return arrow.get(self.deviation.published_time)
|
||||||
|
@ -155,15 +149,9 @@ class DAFav(common.ImgFav):
|
||||||
@property
|
@property
|
||||||
def images(self):
|
def images(self):
|
||||||
f = "%s%s" % (self.targetprefix, common.TMPFEXT)
|
f = "%s%s" % (self.targetprefix, common.TMPFEXT)
|
||||||
return {
|
return {f: self.deviation.content.get("src")}
|
||||||
f: self.deviation.content.get('src')
|
|
||||||
}
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
if not self.exists:
|
|
||||||
self.fetch_images()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
t = DAFavs()
|
t = DAFavs()
|
||||||
t.run()
|
t.run()
|
||||||
|
|
91
Flickr.py
91
Flickr.py
|
@ -10,36 +10,34 @@ import settings
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
#class FlickrFollows(common.Follows):
|
# class FlickrFollows(common.Follows):
|
||||||
|
|
||||||
|
|
||||||
class FlickrFavs(common.Favs):
|
class FlickrFavs(common.Favs):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__('flickr')
|
super().__init__("flickr")
|
||||||
flickr_api.set_keys(
|
flickr_api.set_keys(
|
||||||
api_key = keys.flickr.get('key'),
|
api_key=keys.flickr.get("key"), api_secret=keys.flickr.get("secret")
|
||||||
api_secret = keys.flickr.get('secret')
|
|
||||||
)
|
|
||||||
self.user = flickr_api.Person.findByUserName(
|
|
||||||
keys.flickr.get('username')
|
|
||||||
)
|
)
|
||||||
|
self.user = flickr_api.Person.findByUserName(keys.flickr.get("username"))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def feeds(self):
|
def feeds(self):
|
||||||
logging.info('Generating OPML feeds for Flickr')
|
logging.info("Generating OPML feeds for Flickr")
|
||||||
feeds = []
|
feeds = []
|
||||||
pages = 1
|
pages = 1
|
||||||
page = 1
|
page = 1
|
||||||
while page <= pages:
|
while page <= pages:
|
||||||
fetched = self.user.getPublicContacts(
|
fetched = self.user.getPublicContacts(page=page)
|
||||||
page=page
|
|
||||||
)
|
|
||||||
for u in fetched:
|
for u in fetched:
|
||||||
feeds.append({
|
feeds.append(
|
||||||
'text': u.username,
|
{
|
||||||
'xmlUrl': "https://api.flickr.com/services/feeds/photos_public.gne?lang=en-us&format=rss_200&id=%s" % u.id,
|
"text": u.username,
|
||||||
'htmlUrl': "https://www.flickr.com/photos/%s" % u.id
|
"xmlUrl": "https://api.flickr.com/services/feeds/photos_public.gne?lang=en-us&format=rss_200&id=%s"
|
||||||
})
|
% u.id,
|
||||||
|
"htmlUrl": "https://www.flickr.com/photos/%s" % u.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
pages = fetched.info.pages
|
pages = fetched.info.pages
|
||||||
page = page + 1
|
page = page + 1
|
||||||
return feeds
|
return feeds
|
||||||
|
@ -48,11 +46,9 @@ class FlickrFavs(common.Favs):
|
||||||
pages = 1
|
pages = 1
|
||||||
page = 1
|
page = 1
|
||||||
while page <= pages:
|
while page <= pages:
|
||||||
logging.info('fetching for Flickr: page %d' % page)
|
logging.info("fetching for Flickr: page %d" % page)
|
||||||
fetched = self.user.getFavorites(
|
fetched = self.user.getFavorites(
|
||||||
user_id=self.user.id,
|
user_id=self.user.id, page=page, min_fave_date=self.since
|
||||||
page=page,
|
|
||||||
min_fave_date=self.since
|
|
||||||
)
|
)
|
||||||
for p in fetched:
|
for p in fetched:
|
||||||
photo = FlickrFav(p)
|
photo = FlickrFav(p)
|
||||||
|
@ -70,7 +66,7 @@ class FlickrFav(common.ImgFav):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def owner(self):
|
def owner(self):
|
||||||
return self.info.get('owner')
|
return self.info.get("owner")
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def info(self):
|
def info(self):
|
||||||
|
@ -79,82 +75,63 @@ class FlickrFav(common.ImgFav):
|
||||||
@property
|
@property
|
||||||
def author(self):
|
def author(self):
|
||||||
return {
|
return {
|
||||||
'name': "%s" % self.owner.username,
|
"name": "%s" % self.owner.username,
|
||||||
'url': "%s" % self.owner.getProfileUrl(),
|
"url": "%s" % self.owner.getProfileUrl(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self):
|
def id(self):
|
||||||
return "%s" % self.info.get('id')
|
return "%s" % self.info.get("id")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
return "https://www.flickr.com/photos/%s/%s/" % (
|
return "https://www.flickr.com/photos/%s/%s/" % (self.owner.id, self.id)
|
||||||
self.owner.id,
|
|
||||||
self.id
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def content(self):
|
def content(self):
|
||||||
return "%s" % self.info.get('description')
|
return "%s" % self.info.get("description")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def geo(self):
|
def geo(self):
|
||||||
if 'location' not in self.info:
|
if "location" not in self.info:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
lat = self.info.get('location').get('latitude', None)
|
lat = self.info.get("location").get("latitude", None)
|
||||||
lon = self.info.get('location').get('longitude', None)
|
lon = self.info.get("location").get("longitude", None)
|
||||||
return (lat, lon)
|
return (lat, lon)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def title(self):
|
def title(self):
|
||||||
return clean(''.strip("%s" % self.info.get('title')))
|
return clean("".strip("%s" % self.info.get("title")))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def targetprefix(self):
|
def targetprefix(self):
|
||||||
return os.path.join(
|
return os.path.join(
|
||||||
settings.paths.get('archive'),
|
settings.paths.get("archive"),
|
||||||
'favorite',
|
"favorite",
|
||||||
"flickr_%s_%s" % (
|
"flickr_%s_%s" % (common.slugfname("%s" % self.owner.id), self.id),
|
||||||
common.slugfname('%s' % self.owner.id),
|
|
||||||
self.id,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
|
||||||
def exists(self):
|
|
||||||
maybe = glob.glob("%s*" % self.targetprefix)
|
|
||||||
if len(maybe):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def published(self):
|
def published(self):
|
||||||
return arrow.get(self.info.get('dateuploaded'))
|
return arrow.get(self.info.get("dateuploaded"))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tags(self):
|
def tags(self):
|
||||||
tags = []
|
tags = []
|
||||||
for t in self.info.get('tags'):
|
for t in self.info.get("tags"):
|
||||||
tags.append("%s" % t.text)
|
tags.append("%s" % t.text)
|
||||||
return tags
|
return tags
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def images(self):
|
def images(self):
|
||||||
sizes = self.flickrphoto.getSizes()
|
sizes = self.flickrphoto.getSizes()
|
||||||
for maybe in ['Original', 'Large 2048', 'Large 1600', 'Large', 'Medium']:
|
for maybe in ["Original", "Large 2048", "Large 1600", "Large", "Medium"]:
|
||||||
if maybe in sizes:
|
if maybe in sizes:
|
||||||
f = "%s%s" % (self.targetprefix, common.TMPFEXT)
|
f = "%s%s" % (self.targetprefix, common.TMPFEXT)
|
||||||
return {
|
return {f: sizes.get(maybe).get("source")}
|
||||||
f: sizes.get(maybe).get('source')
|
|
||||||
}
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
if not self.exists:
|
|
||||||
self.fetch_images()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
t = FlickrFavs()
|
t = FlickrFavs()
|
||||||
t.run()
|
t.run()
|
||||||
|
|
69
LastFM.py
69
LastFM.py
|
@ -11,8 +11,7 @@ import keys
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
Track = namedtuple(
|
Track = namedtuple(
|
||||||
'Track',
|
"Track", ["timestamp", "artist", "album", "title", "artistid", "albumid", "img"]
|
||||||
['timestamp', 'artist', 'album', 'title', 'artistid', 'albumid', 'img']
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,37 +35,34 @@ class cached_property(object):
|
||||||
|
|
||||||
|
|
||||||
class LastFM(object):
|
class LastFM(object):
|
||||||
url = 'http://ws.audioscrobbler.com/2.0/'
|
url = "http://ws.audioscrobbler.com/2.0/"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.params = {
|
self.params = {
|
||||||
'method': 'user.getrecenttracks',
|
"method": "user.getrecenttracks",
|
||||||
'user': keys.lastfm.get('username'),
|
"user": keys.lastfm.get("username"),
|
||||||
'api_key': keys.lastfm.get('key'),
|
"api_key": keys.lastfm.get("key"),
|
||||||
'format': 'json',
|
"format": "json",
|
||||||
'limit': '200'
|
"limit": "200",
|
||||||
}
|
}
|
||||||
if os.path.isfile(self.target):
|
if os.path.isfile(self.target):
|
||||||
mtime = os.path.getmtime(self.target)
|
mtime = os.path.getmtime(self.target)
|
||||||
self.params.update({'from': mtime})
|
self.params.update({"from": mtime})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target(self):
|
def target(self):
|
||||||
return os.path.join(
|
return os.path.join(settings.paths.get("archive"), "lastfm.csv")
|
||||||
settings.paths.get('archive'),
|
|
||||||
'lastfm.csv'
|
|
||||||
)
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def existing(self):
|
def existing(self):
|
||||||
timestamps = []
|
timestamps = []
|
||||||
with open(self.target, 'r') as f:
|
with open(self.target, "r") as f:
|
||||||
r = csv.reader(f)
|
r = csv.reader(f)
|
||||||
for row in r:
|
for row in r:
|
||||||
try:
|
try:
|
||||||
timestamps.append(arrow.get(row[0]).timestamp)
|
timestamps.append(arrow.get(row[0]).timestamp)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error('arrow failed on row %s', row)
|
logging.error("arrow failed on row %s", row)
|
||||||
continue
|
continue
|
||||||
return timestamps
|
return timestamps
|
||||||
|
|
||||||
|
@ -78,38 +74,37 @@ class LastFM(object):
|
||||||
tracks = []
|
tracks = []
|
||||||
if not data:
|
if not data:
|
||||||
return tracks
|
return tracks
|
||||||
for track in data.get('track', []):
|
for track in data.get("track", []):
|
||||||
if 'date' not in track:
|
if "date" not in track:
|
||||||
continue
|
continue
|
||||||
ts = arrow.get(int(track.get('date').get('uts')))
|
ts = arrow.get(int(track.get("date").get("uts")))
|
||||||
if ts.timestamp in self.existing:
|
if ts.timestamp in self.existing:
|
||||||
continue
|
continue
|
||||||
entry = Track(
|
entry = Track(
|
||||||
ts.format('YYYY-MM-DDTHH:mm:ssZ'),
|
ts.format("YYYY-MM-DDTHH:mm:ssZ"),
|
||||||
track.get('artist').get('#text', ''),
|
track.get("artist").get("#text", ""),
|
||||||
track.get('album').get('#text', ''),
|
track.get("album").get("#text", ""),
|
||||||
track.get('name', ''),
|
track.get("name", ""),
|
||||||
track.get('artist').get('mbid', ''),
|
track.get("artist").get("mbid", ""),
|
||||||
track.get('album').get('mbid', ''),
|
track.get("album").get("mbid", ""),
|
||||||
track.get('image', [])[-1].get('#text', ''),
|
track.get("image", [])[-1].get("#text", ""),
|
||||||
)
|
)
|
||||||
tracks.append(entry)
|
tracks.append(entry)
|
||||||
return tracks
|
return tracks
|
||||||
|
|
||||||
def fetch(self):
|
def fetch(self):
|
||||||
r = requests.get(self.url, params=self.params)
|
r = requests.get(self.url, params=self.params)
|
||||||
return json.loads(r.text).get('recenttracks')
|
return json.loads(r.text).get("recenttracks")
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
data = self.fetch()
|
data = self.fetch()
|
||||||
tracks = self.extracttracks(data)
|
tracks = self.extracttracks(data)
|
||||||
total = int(data.get('@attr').get('totalPages'))
|
total = int(data.get("@attr").get("totalPages"))
|
||||||
current = int(data.get('@attr').get('page'))
|
current = int(data.get("@attr").get("page"))
|
||||||
cntr = total - current
|
cntr = total - current
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error('Something went wrong: %s', e)
|
logging.error("Something went wrong: %s", e)
|
||||||
return
|
return
|
||||||
|
|
||||||
if not len(tracks):
|
if not len(tracks):
|
||||||
|
@ -118,24 +113,22 @@ class LastFM(object):
|
||||||
while cntr > 0:
|
while cntr > 0:
|
||||||
current = current + 1
|
current = current + 1
|
||||||
cntr = total - current
|
cntr = total - current
|
||||||
logging.info('requesting page #%d of paginated results', current)
|
logging.info("requesting page #%d of paginated results", current)
|
||||||
self.params.update({
|
self.params.update({"page": current})
|
||||||
'page': current
|
|
||||||
})
|
|
||||||
data = self.fetch()
|
data = self.fetch()
|
||||||
tracks = tracks + self.extracttracks(data)
|
tracks = tracks + self.extracttracks(data)
|
||||||
|
|
||||||
if not self.exists:
|
if not self.exists:
|
||||||
with open(self.target, 'w') as f:
|
with open(self.target, "w") as f:
|
||||||
writer = csv.DictWriter(f, fieldnames=Track._fields)
|
writer = csv.DictWriter(f, fieldnames=Track._fields)
|
||||||
writer.writeheader()
|
writer.writeheader()
|
||||||
|
|
||||||
if len(tracks):
|
if len(tracks):
|
||||||
with open(self.target, 'a') as f:
|
with open(self.target, "a") as f:
|
||||||
writer = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC)
|
writer = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC)
|
||||||
writer.writerows(sorted(tracks, key=attrgetter('timestamp')))
|
writer.writerows(sorted(tracks, key=attrgetter("timestamp")))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
lfm = LastFM()
|
lfm = LastFM()
|
||||||
lfm.run()
|
lfm.run()
|
||||||
|
|
1
Pipfile
1
Pipfile
|
@ -14,6 +14,7 @@ bleach = "*"
|
||||||
deviantart = "*"
|
deviantart = "*"
|
||||||
flickr-api = "*"
|
flickr-api = "*"
|
||||||
pytumblr = "*"
|
pytumblr = "*"
|
||||||
|
pyyaml = "*"
|
||||||
|
|
||||||
[requires]
|
[requires]
|
||||||
python_version = "3.7"
|
python_version = "3.7"
|
||||||
|
|
128
Pipfile.lock
generated
128
Pipfile.lock
generated
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "bcf7b4826cf074e5bbb52fdccf3cec966ce0eeded6c38dfd39f530f3aa223cde"
|
"sha256": "654f2f42d6d9e3dd3aaf13b371369e3943573472fc93786661eff68d965dcb8b"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -18,10 +18,11 @@
|
||||||
"default": {
|
"default": {
|
||||||
"arrow": {
|
"arrow": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:9cb4a910256ed536751cd5728673bfb53e6f0026e240466f90c2a92c0b79c895"
|
"sha256:03404b624e89ac5e4fc19c52045fa0f3203419fd4dd64f6e8958c522580a574a",
|
||||||
|
"sha256:41be7ea4c53c2cf57bf30f2d614f60c411160133f7a0a8c49111c30fb7e725b5"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.13.0"
|
"version": "==0.14.2"
|
||||||
},
|
},
|
||||||
"bleach": {
|
"bleach": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -33,10 +34,10 @@
|
||||||
},
|
},
|
||||||
"certifi": {
|
"certifi": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7",
|
"sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939",
|
||||||
"sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033"
|
"sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695"
|
||||||
],
|
],
|
||||||
"version": "==2018.11.29"
|
"version": "==2019.6.16"
|
||||||
},
|
},
|
||||||
"chardet": {
|
"chardet": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -54,10 +55,11 @@
|
||||||
},
|
},
|
||||||
"flickr-api": {
|
"flickr-api": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:57ba6845ad891f32144791d9be1e44a9d76afe9b8e32f1034b956dd38718aa79"
|
"sha256:2ff036ce4ca6f9be71a90310be80916b44feaeb95df5c1a9e5f57d49b64032c9",
|
||||||
|
"sha256:b9782c06315946b395d7f1b1e051fa2ff6aab4b21c5e82b1d95c04d7295f5f24"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.6.1"
|
"version": "==0.7.3"
|
||||||
},
|
},
|
||||||
"future": {
|
"future": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -67,9 +69,10 @@
|
||||||
},
|
},
|
||||||
"httplib2": {
|
"httplib2": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:f61fb838a94ce3b349aa32c92fd8430f7e3511afdb18bf9640d647e30c90a6d6"
|
"sha256:158fbd0ffbba536829d664bf3f32c4f45df41f8f791663665162dfaf21ffd075",
|
||||||
|
"sha256:d1146939d270f1f1eb8cbf8f5aa72ff37d897faccca448582bb1e180aeb4c6b2"
|
||||||
],
|
],
|
||||||
"version": "==0.12.0"
|
"version": "==0.13.0"
|
||||||
},
|
},
|
||||||
"idna": {
|
"idna": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -80,35 +83,33 @@
|
||||||
},
|
},
|
||||||
"lxml": {
|
"lxml": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:0dd6589fa75d369ba06d2b5f38dae107f76ea127f212f6a7bee134f6df2d1d21",
|
"sha256:06c7616601430aa140a69f97e3116308fffe0848f543b639a5ec2e8920ae72fd",
|
||||||
"sha256:1afbac344aa68c29e81ab56c1a9411c3663157b5aee5065b7fa030b398d4f7e0",
|
"sha256:177202792f9842374a8077735c69c41a4282183f7851443d2beb8ee310720819",
|
||||||
"sha256:1baad9d073692421ad5dbbd81430aba6c7f5fdc347f03537ae046ddf2c9b2297",
|
"sha256:19317ad721ceb9e39847d11131903931e2794e447d4751ebb0d9236f1b349ff2",
|
||||||
"sha256:1d8736421a2358becd3edf20260e41a06a0bf08a560480d3a5734a6bcbacf591",
|
"sha256:36d206e62f3e5dbaafd4ec692b67157e271f5da7fd925fda8515da675eace50d",
|
||||||
"sha256:1e1d9bddc5afaddf0de76246d3f2152f961697ad7439c559f179002682c45801",
|
"sha256:387115b066c797c85f9861a9613abf50046a15aac16759bc92d04f94acfad082",
|
||||||
"sha256:1f179dc8b2643715f020f4d119d5529b02cd794c1c8f305868b73b8674d2a03f",
|
"sha256:3ce1c49d4b4a7bc75fb12acb3a6247bb7a91fe420542e6d671ba9187d12a12c2",
|
||||||
"sha256:241fb7bdf97cb1df1edfa8f0bcdfd80525d4023dac4523a241907c8b2f44e541",
|
"sha256:4d2a5a7d6b0dbb8c37dab66a8ce09a8761409c044017721c21718659fa3365a1",
|
||||||
"sha256:2f9765ee5acd3dbdcdc0d0c79309e01f7c16bc8d39b49250bf88de7b46daaf58",
|
"sha256:58d0a1b33364d1253a88d18df6c0b2676a1746d27c969dc9e32d143a3701dda5",
|
||||||
"sha256:312e1e1b1c3ce0c67e0b8105317323e12807955e8186872affb667dbd67971f6",
|
"sha256:62a651c618b846b88fdcae0533ec23f185bb322d6c1845733f3123e8980c1d1b",
|
||||||
"sha256:3273db1a8055ca70257fd3691c6d2c216544e1a70b673543e15cc077d8e9c730",
|
"sha256:69ff21064e7debc9b1b1e2eee8c2d686d042d4257186d70b338206a80c5bc5ea",
|
||||||
"sha256:34dfaa8c02891f9a246b17a732ca3e99c5e42802416628e740a5d1cb2f50ff49",
|
"sha256:7060453eba9ba59d821625c6af6a266bd68277dce6577f754d1eb9116c094266",
|
||||||
"sha256:3aa3f5288af349a0f3a96448ebf2e57e17332d99f4f30b02093b7948bd9f94cc",
|
"sha256:7d26b36a9c4bce53b9cfe42e67849ae3c5c23558bc08363e53ffd6d94f4ff4d2",
|
||||||
"sha256:51102e160b9d83c1cc435162d90b8e3c8c93b28d18d87b60c56522d332d26879",
|
"sha256:83b427ad2bfa0b9705e02a83d8d607d2c2f01889eb138168e462a3a052c42368",
|
||||||
"sha256:56115fc2e2a4140e8994eb9585119a1ae9223b506826089a3ba753a62bd194a6",
|
"sha256:923d03c84534078386cf50193057aae98fa94cace8ea7580b74754493fda73ad",
|
||||||
"sha256:69d83de14dbe8fe51dccfd36f88bf0b40f5debeac763edf9f8325180190eba6e",
|
"sha256:b773715609649a1a180025213f67ffdeb5a4878c784293ada300ee95a1f3257b",
|
||||||
"sha256:99fdce94aeaa3ccbdfcb1e23b34273605c5853aa92ec23d84c84765178662c6c",
|
"sha256:baff149c174e9108d4a2fee192c496711be85534eab63adb122f93e70aa35431",
|
||||||
"sha256:a7c0cd5b8a20f3093ee4a67374ccb3b8a126743b15a4d759e2a1bf098faac2b2",
|
"sha256:bca9d118b1014b4c2d19319b10a3ebed508ff649396ce1855e1c96528d9b2fa9",
|
||||||
"sha256:abe12886554634ed95416a46701a917784cb2b4c77bfacac6916681d49bbf83d",
|
"sha256:ce580c28845581535dc6000fc7c35fdadf8bea7ccb57d6321b044508e9ba0685",
|
||||||
"sha256:b4f67b5183bd5f9bafaeb76ad119e977ba570d2b0e61202f534ac9b5c33b4485",
|
"sha256:d34923a569e70224d88e6682490e24c842907ba2c948c5fd26185413cbe0cd96",
|
||||||
"sha256:bdd7c1658475cc1b867b36d5c4ed4bc316be8d3368abe03d348ba906a1f83b0e",
|
"sha256:dd9f0e531a049d8b35ec5e6c68a37f1ba6ec3a591415e6804cbdf652793d15d7",
|
||||||
"sha256:c6f24149a19f611a415a51b9bc5f17b6c2f698e0d6b41ffb3fa9f24d35d05d73",
|
"sha256:ecb805cbfe9102f3fd3d2ef16dfe5ae9e2d7a7dfbba92f4ff1e16ac9784dbfb0",
|
||||||
"sha256:d1e111b3ab98613115a208c1017f266478b0ab224a67bc8eac670fa0bad7d488",
|
"sha256:ede9aad2197a0202caff35d417b671f5f91a3631477441076082a17c94edd846",
|
||||||
"sha256:d6520aa965773bbab6cb7a791d5895b00d02cf9adc93ac2bf4edb9ac1a6addc5",
|
"sha256:ef2d1fc370400e0aa755aab0b20cf4f1d0e934e7fd5244f3dd4869078e4942b9",
|
||||||
"sha256:dd185cde2ccad7b649593b0cda72021bc8a91667417001dbaf24cd746ecb7c11",
|
"sha256:f2fec194a49bfaef42a548ee657362af5c7a640da757f6f452a35da7dd9f923c"
|
||||||
"sha256:de2e5b0828a9d285f909b5d2e9d43f1cf6cf21fe65bc7660bdaa1780c7b58298",
|
|
||||||
"sha256:f726444b8e909c4f41b4fde416e1071cf28fa84634bfb4befdf400933b6463af"
|
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==4.3.0"
|
"version": "==4.3.4"
|
||||||
},
|
},
|
||||||
"oauth2": {
|
"oauth2": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -119,33 +120,50 @@
|
||||||
},
|
},
|
||||||
"oauthlib": {
|
"oauthlib": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:0ce32c5d989a1827e3f1148f98b9085ed2370fc939bf524c9c851d8714797298",
|
"sha256:40a63637707e9163eda62d0f5345120c65e001a790480b8256448543c1f78f66",
|
||||||
"sha256:3e1e14f6cde7e5475128d30e97edc3bfb4dc857cb884d8714ec161fdbb3b358e"
|
"sha256:b4d99ae8ccfb7d33ba9591b59355c64eef5241534aa3da2e4c0435346b84bc8e"
|
||||||
],
|
],
|
||||||
"version": "==3.0.1"
|
"version": "==3.0.2"
|
||||||
},
|
},
|
||||||
"python-dateutil": {
|
"python-dateutil": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93",
|
"sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
|
||||||
"sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02"
|
"sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"
|
||||||
],
|
],
|
||||||
"version": "==2.7.5"
|
"version": "==2.8.0"
|
||||||
},
|
},
|
||||||
"pytumblr": {
|
"pytumblr": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:ce0ba73f27237d1ef7374950b46bb8c4b13d68e6529f733ebc63799c4607ffec",
|
"sha256:a3774d3978bcff2db98f36a2e5d17bb8496ac21157b1b518089adad86d0dca72",
|
||||||
"sha256:d7496f966c0b42e8d8598c60b01a089d89670deb1f80d6b557168d706a428712"
|
"sha256:eaa4d98217df7ab6392fa5d8801f4a2bdcba35bf0fd49328aa3c98e3b231b6f2"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.0.8"
|
"version": "==0.1.0"
|
||||||
|
},
|
||||||
|
"pyyaml": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3",
|
||||||
|
"sha256:588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043",
|
||||||
|
"sha256:68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7",
|
||||||
|
"sha256:70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265",
|
||||||
|
"sha256:86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391",
|
||||||
|
"sha256:a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778",
|
||||||
|
"sha256:a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225",
|
||||||
|
"sha256:b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955",
|
||||||
|
"sha256:cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e",
|
||||||
|
"sha256:ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190",
|
||||||
|
"sha256:fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==5.1.1"
|
||||||
},
|
},
|
||||||
"requests": {
|
"requests": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e",
|
"sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
|
||||||
"sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"
|
"sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==2.21.0"
|
"version": "==2.22.0"
|
||||||
},
|
},
|
||||||
"requests-oauthlib": {
|
"requests-oauthlib": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -177,17 +195,17 @@
|
||||||
},
|
},
|
||||||
"unidecode": {
|
"unidecode": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:092cdf7ad9d1052c50313426a625b717dab52f7ac58f859e09ea020953b1ad8f",
|
"sha256:1d7a042116536098d05d599ef2b8616759f02985c85b4fef50c78a5aaf10822a",
|
||||||
"sha256:8b85354be8fd0c0e10adbf0675f6dc2310e56fda43fa8fe049123b6c475e52fb"
|
"sha256:2b6aab710c2a1647e928e36d69c21e76b453cd455f4e2621000e54b2a9b8cce8"
|
||||||
],
|
],
|
||||||
"version": "==1.0.23"
|
"version": "==1.1.1"
|
||||||
},
|
},
|
||||||
"urllib3": {
|
"urllib3": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39",
|
"sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1",
|
||||||
"sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"
|
"sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
|
||||||
],
|
],
|
||||||
"version": "==1.24.1"
|
"version": "==1.25.3"
|
||||||
},
|
},
|
||||||
"webencodings": {
|
"webencodings": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
|
93
Tumblr.py
93
Tumblr.py
|
@ -12,50 +12,56 @@ from pprint import pprint
|
||||||
|
|
||||||
class TumblrFavs(common.Favs):
|
class TumblrFavs(common.Favs):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__('tumblr')
|
super().__init__("tumblr")
|
||||||
self.client = pytumblr.TumblrRestClient(
|
self.client = pytumblr.TumblrRestClient(
|
||||||
keys.tumblr.get('key'),
|
keys.tumblr.get("key"),
|
||||||
keys.tumblr.get('secret'),
|
keys.tumblr.get("secret"),
|
||||||
keys.tumblr.get('oauth_token'),
|
keys.tumblr.get("oauth_token"),
|
||||||
keys.tumblr.get('oauth_secret')
|
keys.tumblr.get("oauth_secret"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def feeds(self):
|
def feeds(self):
|
||||||
logging.info('Generating OPML feeds for Tumblr')
|
logging.info("Generating OPML feeds for Tumblr")
|
||||||
feeds = []
|
feeds = []
|
||||||
offset = 0
|
offset = 0
|
||||||
has_more = True
|
has_more = True
|
||||||
while has_more:
|
while has_more:
|
||||||
fetched = self.client.following(offset=offset)
|
fetched = self.client.following(offset=offset)
|
||||||
if '_links' in fetched and 'next' in fetched['_links'] and len(fetched):
|
if "_links" in fetched and "next" in fetched["_links"] and len(fetched):
|
||||||
offset = fetched.get('_links').get('next').get('query_params').get('offset')
|
offset = (
|
||||||
|
fetched.get("_links").get("next").get("query_params").get("offset")
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
has_more = False
|
has_more = False
|
||||||
|
|
||||||
for u in fetched.get('blogs'):
|
for u in fetched.get("blogs"):
|
||||||
feeds.append({
|
feeds.append(
|
||||||
'text': u.get('name'),
|
{
|
||||||
'xmlUrl': "%srss" % u.get('url'),
|
"text": u.get("name"),
|
||||||
'htmlUrl': u.get('url')
|
"xmlUrl": "%srss" % u.get("url"),
|
||||||
})
|
"htmlUrl": u.get("url"),
|
||||||
|
}
|
||||||
|
)
|
||||||
return feeds
|
return feeds
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
has_more = True
|
has_more = True
|
||||||
after = self.since
|
after = self.since
|
||||||
while has_more:
|
while has_more:
|
||||||
logging.info('fetching for Tumblr: after %d' % after)
|
logging.info("fetching for Tumblr: after %d" % after)
|
||||||
fetched = self.client.likes(after=after)
|
fetched = self.client.likes(after=after)
|
||||||
if 'liked_posts' not in fetched:
|
if "liked_posts" not in fetched:
|
||||||
has_more = False
|
has_more = False
|
||||||
elif '_links' in fetched and 'prev' in fetched['_links'] and len(fetched):
|
elif "_links" in fetched and "prev" in fetched["_links"] and len(fetched):
|
||||||
after = fetched.get('_links').get('prev').get('query_params').get('after')
|
after = (
|
||||||
|
fetched.get("_links").get("prev").get("query_params").get("after")
|
||||||
|
)
|
||||||
after = int(after)
|
after = int(after)
|
||||||
else:
|
else:
|
||||||
has_more = False
|
has_more = False
|
||||||
|
|
||||||
for like in fetched.get('liked_posts'):
|
for like in fetched.get("liked_posts"):
|
||||||
fav = TumblrFav(like)
|
fav = TumblrFav(like)
|
||||||
fav.run()
|
fav.run()
|
||||||
|
|
||||||
|
@ -69,25 +75,25 @@ class TumblrFav(common.ImgFav):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def blogname(self):
|
def blogname(self):
|
||||||
return self.data.get('blog_name')
|
return self.data.get("blog_name")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self):
|
def id(self):
|
||||||
return self.data.get('id')
|
return self.data.get("id")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
return self.data.get('post_url')
|
return self.data.get("post_url")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def content(self):
|
def content(self):
|
||||||
return "%s" % self.data.get('caption', '')
|
return "%s" % self.data.get("caption", "")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def title(self):
|
def title(self):
|
||||||
title = self.data.get('summary', '')
|
title = self.data.get("summary", "")
|
||||||
if not len(title):
|
if not len(title):
|
||||||
title = self.data.get('slug', '')
|
title = self.data.get("slug", "")
|
||||||
if not len(title):
|
if not len(title):
|
||||||
title = common.slugfname(self.url)
|
title = common.slugfname(self.url)
|
||||||
return clean(title.strip())
|
return clean(title.strip())
|
||||||
|
@ -95,56 +101,39 @@ class TumblrFav(common.ImgFav):
|
||||||
@property
|
@property
|
||||||
def targetprefix(self):
|
def targetprefix(self):
|
||||||
return os.path.join(
|
return os.path.join(
|
||||||
settings.paths.get('archive'),
|
settings.paths.get("archive"),
|
||||||
'favorite',
|
"favorite",
|
||||||
"tumblr_%s_%s" % (self.blogname, self.id)
|
"tumblr_%s_%s" % (self.blogname, self.id),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
|
||||||
def exists(self):
|
|
||||||
maybe = glob.glob("%s*" % self.targetprefix)
|
|
||||||
if len(maybe):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def published(self):
|
def published(self):
|
||||||
maybe = self.data.get('liked_timestamp', False)
|
maybe = self.data.get("liked_timestamp", False)
|
||||||
if not maybe:
|
if not maybe:
|
||||||
maybe = self.data.get('date', False)
|
maybe = self.data.get("date", False)
|
||||||
if not maybe:
|
if not maybe:
|
||||||
maybe = arrow.utcnow().timestamp
|
maybe = arrow.utcnow().timestamp
|
||||||
return arrow.get(maybe)
|
return arrow.get(maybe)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tags(self):
|
def tags(self):
|
||||||
return self.data.get('tags', [])
|
return self.data.get("tags", [])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def author(self):
|
def author(self):
|
||||||
return {
|
return {"name": self.blogname, "url": "http://%s.tumblr.com" % self.blogname}
|
||||||
'name': self.blogname,
|
|
||||||
'url': 'http://%s.tumblr.com' % self.blogname
|
|
||||||
}
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def images(self):
|
def images(self):
|
||||||
r = {}
|
r = {}
|
||||||
cntr = 0
|
cntr = 0
|
||||||
for p in self.data.get('photos', []):
|
for p in self.data.get("photos", []):
|
||||||
f = "%s_%d%s" % (self.targetprefix, cntr, common.TMPFEXT)
|
f = "%s_%d%s" % (self.targetprefix, cntr, common.TMPFEXT)
|
||||||
r.update({
|
r.update({f: p.get("original_size").get("url")})
|
||||||
f: p.get('original_size').get('url')
|
|
||||||
})
|
|
||||||
cntr = cntr + 1
|
cntr = cntr + 1
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
if __name__ == "__main__":
|
||||||
if not self.exists:
|
|
||||||
self.fetch_images()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
t = TumblrFavs()
|
t = TumblrFavs()
|
||||||
t.run()
|
t.run()
|
||||||
|
|
202
common.py
202
common.py
|
@ -14,16 +14,23 @@ from requests.auth import HTTPBasicAuth
|
||||||
import arrow
|
import arrow
|
||||||
import settings
|
import settings
|
||||||
import keys
|
import keys
|
||||||
|
import yaml
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
TMPFEXT = '.xyz'
|
TMPFEXT = ".xyz"
|
||||||
|
MDFEXT = ".md"
|
||||||
|
|
||||||
|
|
||||||
|
def utfyamldump(data):
|
||||||
|
""" dump YAML with actual UTF-8 chars """
|
||||||
|
return yaml.dump(data, default_flow_style=False, indent=4, allow_unicode=True)
|
||||||
|
|
||||||
|
|
||||||
def slugfname(url):
|
def slugfname(url):
|
||||||
return slugify(
|
return slugify(re.sub(r"^https?://(?:www)?", "", url), only_ascii=True, lower=True)[
|
||||||
re.sub(r"^https?://(?:www)?", "", url),
|
:200
|
||||||
only_ascii=True,
|
]
|
||||||
lower=True
|
|
||||||
)[:200]
|
|
||||||
|
|
||||||
class cached_property(object):
|
class cached_property(object):
|
||||||
""" extermely simple cached_property decorator:
|
""" extermely simple cached_property decorator:
|
||||||
|
@ -31,6 +38,7 @@ class cached_property(object):
|
||||||
result is calculated, then the class method is overwritten to be
|
result is calculated, then the class method is overwritten to be
|
||||||
a property, contaning the result from the method
|
a property, contaning the result from the method
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, method, name=None):
|
def __init__(self, method, name=None):
|
||||||
self.method = method
|
self.method = method
|
||||||
self.name = name or method.__name__
|
self.name = name or method.__name__
|
||||||
|
@ -42,52 +50,42 @@ class cached_property(object):
|
||||||
setattr(inst, self.name, result)
|
setattr(inst, self.name, result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class Follows(dict):
|
class Follows(dict):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.auth = HTTPBasicAuth(
|
self.auth = HTTPBasicAuth(
|
||||||
keys.miniflux.get('username'),
|
keys.miniflux.get("username"), keys.miniflux.get("token")
|
||||||
keys.miniflux.get('token')
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def subscriptions(self):
|
def subscriptions(self):
|
||||||
feeds = []
|
feeds = []
|
||||||
params = {
|
params = {"jsonrpc": "2.0", "method": "getFeeds", "id": keys.miniflux.get("id")}
|
||||||
'jsonrpc': '2.0',
|
|
||||||
'method': 'getFeeds',
|
|
||||||
'id': keys.miniflux.get('id')
|
|
||||||
}
|
|
||||||
r = requests.post(
|
r = requests.post(
|
||||||
keys.miniflux.get('url'),
|
keys.miniflux.get("url"), data=json.dumps(params), auth=self.auth
|
||||||
data=json.dumps(params),
|
|
||||||
auth=self.auth
|
|
||||||
)
|
)
|
||||||
return r.json().get('result', [])
|
return r.json().get("result", [])
|
||||||
|
|
||||||
|
|
||||||
def sync(self):
|
def sync(self):
|
||||||
current = []
|
current = []
|
||||||
for feed in self.subscriptions:
|
for feed in self.subscriptions:
|
||||||
try:
|
try:
|
||||||
current.append(feed['feed_url'])
|
current.append(feed["feed_url"])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error('problem with feed entry: %s', feed)
|
logging.error("problem with feed entry: %s", feed)
|
||||||
for silo, feeds in self.items():
|
for silo, feeds in self.items():
|
||||||
for feed in feeds:
|
for feed in feeds:
|
||||||
xmlurl = feed.get('xmlUrl')
|
xmlurl = feed.get("xmlUrl")
|
||||||
if len(xmlurl) and xmlurl not in current:
|
if len(xmlurl) and xmlurl not in current:
|
||||||
logging.info('creating subscription for: %s', feed)
|
logging.info("creating subscription for: %s", feed)
|
||||||
params = {
|
params = {
|
||||||
'jsonrpc': '2.0',
|
"jsonrpc": "2.0",
|
||||||
'method': 'createFeed',
|
"method": "createFeed",
|
||||||
'id': keys.miniflux.get('id'),
|
"id": keys.miniflux.get("id"),
|
||||||
'params': {
|
"params": {"url": xmlurl, "group_name": silo},
|
||||||
'url': xmlurl,
|
|
||||||
'group_name': silo
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
r = requests.post(
|
r = requests.post(
|
||||||
keys.miniflux.get('url'),
|
keys.miniflux.get("url"),
|
||||||
data=json.dumps(params),
|
data=json.dumps(params),
|
||||||
auth=self.auth,
|
auth=self.auth,
|
||||||
)
|
)
|
||||||
|
@ -98,59 +96,52 @@ class Follows(dict):
|
||||||
opml.addprevious(
|
opml.addprevious(
|
||||||
etree.ProcessingInstruction(
|
etree.ProcessingInstruction(
|
||||||
"xml-stylesheet",
|
"xml-stylesheet",
|
||||||
'type="text/xsl" href="%s"' % (settings.opml.get('xsl'))
|
'type="text/xsl" href="%s"' % (settings.opml.get("xsl")),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
head = etree.SubElement(opml, "head")
|
head = etree.SubElement(opml, "head")
|
||||||
title = etree.SubElement(head, "title").text = settings.opml.get('title')
|
title = etree.SubElement(head, "title").text = settings.opml.get("title")
|
||||||
dt = etree.SubElement(head, "dateCreated").text = arrow.utcnow().format('ddd, DD MMM YYYY HH:mm:ss UTC')
|
dt = etree.SubElement(head, "dateCreated").text = arrow.utcnow().format(
|
||||||
owner = etree.SubElement(head, "ownerName").text = settings.opml.get('owner')
|
"ddd, DD MMM YYYY HH:mm:ss UTC"
|
||||||
email = etree.SubElement(head, "ownerEmail").text = settings.opml.get('email')
|
)
|
||||||
|
owner = etree.SubElement(head, "ownerName").text = settings.opml.get("owner")
|
||||||
|
email = etree.SubElement(head, "ownerEmail").text = settings.opml.get("email")
|
||||||
|
|
||||||
body = etree.SubElement(opml, "body")
|
body = etree.SubElement(opml, "body")
|
||||||
groups = {}
|
groups = {}
|
||||||
for feed in self.subscriptions:
|
for feed in self.subscriptions:
|
||||||
# contains sensitive data, skip it
|
# contains sensitive data, skip it
|
||||||
if 'sessionid' in feed.get('feed_url') or 'sessionid' in feed.get('site_url'):
|
if "sessionid" in feed.get("feed_url") or "sessionid" in feed.get(
|
||||||
|
"site_url"
|
||||||
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
fgroup = feed.get('groups',None)
|
fgroup = feed.get("groups", None)
|
||||||
if not fgroup:
|
if not fgroup:
|
||||||
fgroup = [{
|
fgroup = [{"title": "Unknown", "id": -1}]
|
||||||
'title': 'Unknown',
|
|
||||||
'id': -1
|
|
||||||
}]
|
|
||||||
fgroup = fgroup.pop()
|
fgroup = fgroup.pop()
|
||||||
# some groups need to be skipped
|
# some groups need to be skipped
|
||||||
if fgroup['title'].lower() in ['private']:
|
if fgroup["title"].lower() in ["private"]:
|
||||||
continue
|
continue
|
||||||
if fgroup['title'] not in groups.keys():
|
if fgroup["title"] not in groups.keys():
|
||||||
groups[fgroup['title']] = etree.SubElement(
|
groups[fgroup["title"]] = etree.SubElement(
|
||||||
body,
|
body, "outline", text=fgroup["title"]
|
||||||
"outline",
|
)
|
||||||
text=fgroup['title']
|
|
||||||
)
|
|
||||||
entry = etree.SubElement(
|
entry = etree.SubElement(
|
||||||
groups[fgroup['title']],
|
groups[fgroup["title"]],
|
||||||
"outline",
|
"outline",
|
||||||
type="rss",
|
type="rss",
|
||||||
text=feed.get('title'),
|
text=feed.get("title"),
|
||||||
xmlUrl=feed.get('feed_url'),
|
xmlUrl=feed.get("feed_url"),
|
||||||
htmlUrl=feed.get('site_url')
|
htmlUrl=feed.get("site_url"),
|
||||||
)
|
)
|
||||||
|
|
||||||
opmlfile = os.path.join(
|
opmlfile = os.path.join(settings.paths.get("content"), "following.opml")
|
||||||
settings.paths.get('content'),
|
|
||||||
'following.opml'
|
|
||||||
)
|
|
||||||
|
|
||||||
with open(opmlfile, 'wb') as f:
|
with open(opmlfile, "wb") as f:
|
||||||
f.write(
|
f.write(
|
||||||
etree.tostring(
|
etree.tostring(
|
||||||
xmldoc,
|
xmldoc, encoding="utf-8", xml_declaration=True, pretty_print=True
|
||||||
encoding='utf-8',
|
|
||||||
xml_declaration=True,
|
|
||||||
pretty_print=True
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -165,11 +156,7 @@ class Favs(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def since(self):
|
def since(self):
|
||||||
d = os.path.join(
|
d = os.path.join(settings.paths.get("archive"), "favorite", "%s*" % self.silo)
|
||||||
settings.paths.get('archive'),
|
|
||||||
'favorite',
|
|
||||||
"%s*" % self.silo
|
|
||||||
)
|
|
||||||
files = glob.glob(d)
|
files = glob.glob(d)
|
||||||
if len(files):
|
if len(files):
|
||||||
mtime = max([int(os.path.getmtime(f)) for f in files])
|
mtime = max([int(os.path.getmtime(f)) for f in files])
|
||||||
|
@ -182,6 +169,33 @@ class ImgFav(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if not self.exists:
|
||||||
|
self.fetch_images()
|
||||||
|
self.save_txt()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def exists(self):
|
||||||
|
maybe = glob.glob("%s*" % self.targetprefix)
|
||||||
|
if len(maybe):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def save_txt(self):
|
||||||
|
attachments = [os.path.basename(fn) for fn in glob.glob("%s*" % self.targetprefix)
|
||||||
|
if not os.path.basename(fn).endswith('.md')]
|
||||||
|
meta = {
|
||||||
|
"title": self.title,
|
||||||
|
"favorite-of": self.url,
|
||||||
|
"date": str(self.published),
|
||||||
|
"sources": list(self.images.values()),
|
||||||
|
"attachments": attachments,
|
||||||
|
"author": self.author,
|
||||||
|
}
|
||||||
|
r = "---\n%s\n---\n\n" % (utfyamldump(meta))
|
||||||
|
with open("%s%s" % (self.targetprefix, MDFEXT), "wt") as fpath:
|
||||||
|
fpath.write(r)
|
||||||
|
|
||||||
def fetch_images(self):
|
def fetch_images(self):
|
||||||
for fpath, url in self.images.items():
|
for fpath, url in self.images.items():
|
||||||
self.fetch_image(fpath, url)
|
self.fetch_image(fpath, url)
|
||||||
|
@ -190,7 +204,7 @@ class ImgFav(object):
|
||||||
logging.info("pulling image %s to %s", url, fpath)
|
logging.info("pulling image %s to %s", url, fpath)
|
||||||
r = requests.get(url, stream=True)
|
r = requests.get(url, stream=True)
|
||||||
if r.status_code == 200:
|
if r.status_code == 200:
|
||||||
with open(fpath, 'wb') as f:
|
with open(fpath, "wb") as f:
|
||||||
r.raw.decode_content = True
|
r.raw.decode_content = True
|
||||||
shutil.copyfileobj(r.raw, f)
|
shutil.copyfileobj(r.raw, f)
|
||||||
|
|
||||||
|
@ -198,58 +212,60 @@ class ImgFav(object):
|
||||||
if not imgtype:
|
if not imgtype:
|
||||||
os.remove(fpath)
|
os.remove(fpath)
|
||||||
return
|
return
|
||||||
if imgtype in ['jpg', 'jpeg', 'png']:
|
if imgtype in ["jpg", "jpeg", "png"]:
|
||||||
self.write_exif(fpath)
|
self.write_exif(fpath)
|
||||||
os.rename(fpath, fpath.replace(TMPFEXT, ".%s" % (imgtype)))
|
os.rename(fpath, fpath.replace(TMPFEXT, ".%s" % (imgtype)))
|
||||||
|
|
||||||
def write_exif(self, fpath):
|
def write_exif(self, fpath):
|
||||||
logging.info('populating EXIF data of %s' % fpath)
|
logging.info("populating EXIF data of %s" % fpath)
|
||||||
|
|
||||||
geo_lat = False
|
geo_lat = False
|
||||||
geo_lon = False
|
geo_lon = False
|
||||||
|
|
||||||
if hasattr(self, 'geo') and self.geo != None:
|
if hasattr(self, "geo") and self.geo != None:
|
||||||
lat, lon = self.geo
|
lat, lon = self.geo
|
||||||
if lat and lon and 'null' != lat and 'null' != lon:
|
if lat and lon and "null" != lat and "null" != lon:
|
||||||
geo_lat = lat
|
geo_lat = lat
|
||||||
geo_lon = lon
|
geo_lon = lon
|
||||||
|
|
||||||
params = [
|
params = [
|
||||||
'exiftool',
|
"exiftool",
|
||||||
'-overwrite_original',
|
"-overwrite_original",
|
||||||
'-XMP:Copyright=Copyright %s %s (%s)' % (
|
"-XMP:Copyright=Copyright %s %s (%s)"
|
||||||
self.published.to('utc').format('YYYY'),
|
% (
|
||||||
self.author.get('name'),
|
self.published.to("utc").format("YYYY"),
|
||||||
self.author.get('url'),
|
self.author.get("name"),
|
||||||
|
self.author.get("url"),
|
||||||
),
|
),
|
||||||
'-XMP:Source=%s' % self.url,
|
"-XMP:Source=%s" % self.url,
|
||||||
'-XMP:ReleaseDate=%s' % self.published.to('utc').format('YYYY:MM:DD HH:mm:ss'),
|
"-XMP:ReleaseDate=%s"
|
||||||
'-XMP:Headline=%s' % self.title,
|
% self.published.to("utc").format("YYYY:MM:DD HH:mm:ss"),
|
||||||
'-XMP:Description=%s' % self.content,
|
"-XMP:Headline=%s" % self.title,
|
||||||
|
"-XMP:Description=%s" % self.content,
|
||||||
]
|
]
|
||||||
|
|
||||||
for t in self.tags:
|
for t in self.tags:
|
||||||
params.append('-XMP:HierarchicalSubject+=%s' % t)
|
params.append("-XMP:HierarchicalSubject+=%s" % t)
|
||||||
params.append('-XMP:Subject+=%s' % t)
|
params.append("-XMP:Subject+=%s" % t)
|
||||||
|
|
||||||
if geo_lat and geo_lon:
|
if geo_lat and geo_lon:
|
||||||
geo_lat = round(float(geo_lat), 6)
|
geo_lat = round(float(geo_lat), 6)
|
||||||
geo_lon = round(float(geo_lon), 6)
|
geo_lon = round(float(geo_lon), 6)
|
||||||
|
|
||||||
if geo_lat < 0:
|
if geo_lat < 0:
|
||||||
GPSLatitudeRef = 'S'
|
GPSLatitudeRef = "S"
|
||||||
else:
|
else:
|
||||||
GPSLatitudeRef = 'N'
|
GPSLatitudeRef = "N"
|
||||||
|
|
||||||
if geo_lon < 0:
|
if geo_lon < 0:
|
||||||
GPSLongitudeRef = 'W'
|
GPSLongitudeRef = "W"
|
||||||
else:
|
else:
|
||||||
GPSLongitudeRef = 'E'
|
GPSLongitudeRef = "E"
|
||||||
|
|
||||||
params.append('-GPSLongitude=%s' % abs(geo_lon))
|
params.append("-GPSLongitude=%s" % abs(geo_lon))
|
||||||
params.append('-GPSLatitude=%s' % abs(geo_lat))
|
params.append("-GPSLatitude=%s" % abs(geo_lat))
|
||||||
params.append('-GPSLongitudeRef=%s' % GPSLongitudeRef)
|
params.append("-GPSLongitudeRef=%s" % GPSLongitudeRef)
|
||||||
params.append('-GPSLatitudeRef=%s' % GPSLatitudeRef)
|
params.append("-GPSLatitudeRef=%s" % GPSLatitudeRef)
|
||||||
|
|
||||||
params.append(fpath)
|
params.append(fpath)
|
||||||
|
|
||||||
|
@ -261,6 +277,6 @@ class ImgFav(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
_original = '%s_original' % fpath
|
_original = "%s_original" % fpath
|
||||||
if os.path.exists(_original):
|
if os.path.exists(_original):
|
||||||
os.unlink(_original)
|
os.unlink(_original)
|
||||||
|
|
6
run.py
6
run.py
|
@ -7,8 +7,8 @@ import Flickr
|
||||||
import Artstation
|
import Artstation
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
lfm = LastFM.LastFM()
|
# lfm = LastFM.LastFM()
|
||||||
lfm.run()
|
# lfm.run()
|
||||||
|
|
||||||
opml = common.Follows()
|
opml = common.Follows()
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ silos = [
|
||||||
DeviantArt.DAFavs(),
|
DeviantArt.DAFavs(),
|
||||||
Flickr.FlickrFavs(),
|
Flickr.FlickrFavs(),
|
||||||
Tumblr.TumblrFavs(),
|
Tumblr.TumblrFavs(),
|
||||||
Artstation.ASFavs()
|
Artstation.ASFavs(),
|
||||||
]
|
]
|
||||||
|
|
||||||
for silo in silos:
|
for silo in silos:
|
||||||
|
|
34
settings.py
34
settings.py
|
@ -3,37 +3,27 @@ import re
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
base = os.path.abspath(os.path.expanduser('~/Projects/petermolnar.net'))
|
base = os.path.abspath(os.path.expanduser("~/Projects/petermolnar.net"))
|
||||||
|
|
||||||
opml = {
|
opml = {
|
||||||
'owner': 'Peter Molnar',
|
"owner": "Peter Molnar",
|
||||||
'email': 'mail@petermolnar.net',
|
"email": "mail@petermolnar.net",
|
||||||
'title': 'feeds followed by petermolnar.net',
|
"title": "feeds followed by petermolnar.net",
|
||||||
'xsl': 'https://petermolnar.net/following.xsl'
|
"xsl": "https://petermolnar.net/following.xsl",
|
||||||
}
|
}
|
||||||
|
|
||||||
paths = {
|
paths = {
|
||||||
'archive': os.path.join(base, 'archive'),
|
"archive": os.path.join(base, "archive"),
|
||||||
'content': os.path.join(base, 'content'),
|
"content": os.path.join(base, "content"),
|
||||||
}
|
}
|
||||||
|
|
||||||
loglevels = {
|
loglevels = {"critical": 50, "error": 40, "warning": 30, "info": 20, "debug": 10}
|
||||||
'critical': 50,
|
|
||||||
'error': 40,
|
|
||||||
'warning': 30,
|
|
||||||
'info': 20,
|
|
||||||
'debug': 10
|
|
||||||
}
|
|
||||||
|
|
||||||
_parser = argparse.ArgumentParser(description='Parameters for silo.pasta')
|
_parser = argparse.ArgumentParser(description="Parameters for silo.pasta")
|
||||||
_parser.add_argument(
|
_parser.add_argument("--loglevel", default="debug", help="change loglevel")
|
||||||
'--loglevel',
|
|
||||||
default='debug',
|
|
||||||
help='change loglevel'
|
|
||||||
)
|
|
||||||
|
|
||||||
args = vars(_parser.parse_args())
|
args = vars(_parser.parse_args())
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=loglevels[args.get('loglevel')],
|
level=loglevels[args.get("loglevel")],
|
||||||
format='%(asctime)s - %(levelname)s - %(message)s'
|
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue