cli.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from __future__ import print_function
  2. from argparse import ArgumentParser
  3. from hashlib import md5
  4. from datetime import datetime
  5. import sqlite3
  6. import time
  7. import json
  8. import os
  9. strptime = datetime.strptime
  10. ARG_DATE_FMT = '%Y-%m-%d %H:%M:%S'
  11. simple_date = lambda s: strptime(s, ARG_DATE_FMT)
  12. def find_hash(hsh, db=None):
  13. cursor = db.cursor()
  14. cursor.execute("select * from file where hash = ?",
  15. (hsh, ),
  16. )
  17. return cursor.fetchone()
  18. def insert_file(hsh, filename, timestamp, db=None):
  19. cursor = db.cursor()
  20. cursor.execute("""
  21. insert into file(hash, filename, timestamp)
  22. values(?, ?, ?)
  23. """,
  24. (hsh, filename, int(time.mktime(timestamp.timetuple())), )
  25. )
  26. def hash_file(filename):
  27. ahash = md5()
  28. with open(filename, 'rb') as fp:
  29. while True:
  30. data = fp.read(4096)
  31. if data:
  32. ahash.update(data)
  33. else:
  34. break
  35. return ahash.hexdigest()
  36. def main():
  37. parser = ArgumentParser()
  38. subparsers = parser.add_subparsers(dest='entity')
  39. dbparser = subparsers.add_parser('db')
  40. dbparser.add_argument('action')
  41. dbparser.add_argument('-from-date', dest='from_date',
  42. type=simple_date,
  43. )
  44. dbparser.add_argument('--dry-run', dest='dry_run',
  45. action='store_const',
  46. const=True,
  47. default=False
  48. )
  49. args = parser.parse_args()
  50. action = args.action
  51. with open('/etc/fourier-config.json', 'r') as fp:
  52. config = json.loads(fp.read())
  53. device_id = config['device_id']
  54. dbpath = '/var/fourier/{}/files.db'.format(device_id)
  55. if action == 'stats':
  56. conn = sqlite3.connect(dbpath)
  57. cursor = conn.cursor()
  58. cursor.execute("select count(*), count(uploaded) from file")
  59. total, uploaded, = cursor.fetchone()
  60. print("total: {}".format(total))
  61. print("uploaded: {}".format(uploaded))
  62. print("pending: {}".format(total - uploaded))
  63. elif action == 'index-files':
  64. counter = 0
  65. already_indexed = 0
  66. conn = sqlite3.connect(dbpath)
  67. path = os.path.join('/var/fourier', device_id)
  68. for folder, folders, files in os.walk(path):
  69. for file in files:
  70. if not file.endswith('.mp3'):
  71. continue
  72. filename = os.path.join(folder, file)
  73. dt = datetime.strptime(
  74. file[:19],
  75. '%Y-%m-%dT%H-%M-%S'
  76. )
  77. try:
  78. if args.from_date:
  79. do_insert = dt >= args.from_date
  80. else:
  81. do_insert = True
  82. if do_insert:
  83. thehash = hash_file(filename)
  84. insert_file(thehash, filename, dt, db=conn)
  85. counter += 1
  86. print(dt)
  87. except sqlite3.IntegrityError:
  88. already_indexed += 1
  89. print('already indexed: {}'.format(filename))
  90. if not args.dry_run:
  91. conn.commit()
  92. else:
  93. conn.rollback()
  94. print('\n[WARNING] DRY RUN FINISHED')
  95. print('----------------------------------')
  96. print('total files indexed: {}'.format(counter))
  97. print('total files in existence: {}'.format(already_indexed))
  98. print('----------------------------------')
  99. if __name__ == '__main__':
  100. main()