Skip to content

Instantly share code, notes, and snippets.

@noqqe
Created December 16, 2015 12:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save noqqe/5420d1d95aad95d4f66c to your computer and use it in GitHub Desktop.
Save noqqe/5420d1d95aad95d4f66c to your computer and use it in GitHub Desktop.
commandline bookmark manager in python and mongodb
#!/usr/bin/env python2.7
""" bm 1.0.0
Usage:
bm list
bm search <pattern>
bm add <url> <tags>... [--date=<date>]
bm stats
bm tags
Options:
--date=<date> specifiy date manually
--version show version
--help show help
"""
import re
import datetime
import urllib2
import ssl
import pymongo
from dateutil.parser import parse
from bs4 import BeautifulSoup
from docopt import docopt
from bson.objectid import ObjectId
from termcolor import cprint
# LOL SECURITY
ssl._create_default_https_context = ssl._create_unverified_context
class Links(object):
"""Docstring for Links. """
def __init__(self):
self.db = self._mcon()
# private
def _mcon(self):
""" Initialize MongoDB Connection
:returns: collection object
"""
c = pymongo.MongoClient('localhost', 27017)
db = c.links.links
return db
def _display(self, r):
""" Display an MongoDB document """
cprint("title: ", end='')
cprint(r["title"], 'green', attrs=['bold'])
print(" url: " + r["url"])
print(" tags: "),
for e in r["tags"]:
cprint(e, 'white', attrs=['bold'], end=' ')
print("")
print(" date: " + r["date"].strftime('%Y-%m-%d %H:%M'))
print("")
return True
def _fetchtitle(self, url):
""" Fetch <title> of a html site for title element
:returns: string
"""
try:
h = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9'}
u = urllib2.Request(url, headers=h)
u = urllib2.urlopen(u)
soup = BeautifulSoup(u)
s = soup.title.string.replace('\n', ' ').replace('\r', '')
return s
except (AttributeError, MemoryError, ssl.CertificateError, IOError) as e:
return "No title"
def _checkdup(self, url):
""" Check if url already exists in db
:returns: bool
"""
db = self.db
if db.find({"url": url}).count() > 0:
return True
else:
return False
# public
def add(self, url, tags, date):
""" Add bookmark to MongoDB
:returns: bool
"""
db = self.db
if self._checkdup(url) is True:
cprint("INFO: Duplicate found", 'yellow')
return False
title = self._fetchtitle(url)
if title is not False:
item = {"url": url,
"title": title,
"tags": tags,
"date": date}
objid = db.insert_one(item).inserted_id
print("")
for r in db.find({"_id": ObjectId(objid)}):
self._display(r)
else:
cprint("Error: Failed fetching " + url, 'red')
return True
def list(self):
""" list bookmarks in MongoDB
:returns: bool
"""
db = self.db
print("")
for r in db.find().sort("date", 1):
self._display(r)
return True
def search(self, pattern):
""" search for bookmarks in MongoDB
:returns: bool
"""
db = self.db
p = re.compile(pattern, re.IGNORECASE)
query = {"$or":
[{"title": {"$regex": p}},
{"url": {"$regex": p}},
{"tags": p}
]
}
print("")
for r in db.find(query).sort("date", 1):
self._display(r)
return True
def stats(self):
""" Show statistics about bookmarks
:returns: True
"""
db = self.db
num = db.find().count()
print("Links total: %s" % num)
tags = db.find({},{"tags": 1})
mlist = []
tagcount = 0
for t in tags:
mlist = list(set(mlist + t["tags"]))
tagcount += len(t["tags"])
print("Tags Total: %s" % tagcount)
print("Unique Tags: %s" % len(mlist))
print("Links per year:")
for x in range(2010,2018):
start = datetime.datetime(x, 1, 1, 0, 0, 0, 557000);
end = datetime.datetime(x + 1, 1, 1, 0, 0, 0, 557000);
y = db.find({"date": {'$gt': start, '$lt': end}}).count()
if y > 0:
print(" %s: %s" % (x,y))
return True
def tags(self):
""" Show all of the tags
:returns: True
"""
db = self.db
tags = db.find({},{"tags": 1})
mlist = []
for t in tags:
mlist = list(set(mlist + t["tags"]))
cprint("Tags:", 'green', attrs={"bold"})
for m in mlist:
print(m)
return True
if __name__ == '__main__':
args = docopt(__doc__, version='bm')
if args['--date'] is not None:
d = parse(args['--date'])
else:
d = datetime.datetime.now()
if args['list'] is True:
Links().list()
if args['add'] is True:
Links().add(url=args['<url>'], tags=args['<tags>'], date=d)
if args['search'] is True:
Links().search(args['<pattern>'])
if args['stats'] is True:
Links().stats()
if args['tags'] is True:
Links().tags()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment