cli.py 4.5 KB

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