cli.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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. stations_parser = subparsers.add_parser('station')
  52. stations_parser.add_argument('action')
  53. args = parser.parse_args()
  54. action = args.action
  55. with open('/etc/fourier-config.json', 'r') as fp:
  56. config = json.loads(fp.read())
  57. device_id = config['device_id']
  58. dbpath = '/var/fourier/{}/files.db'.format(device_id)
  59. if args.entity == 'db':
  60. if action == 'stats':
  61. conn = sqlite3.connect(dbpath)
  62. cursor = conn.cursor()
  63. cursor.execute("select count(*), count(uploaded) from file")
  64. total, uploaded, = cursor.fetchone()
  65. print("total: {}".format(total))
  66. print("uploaded: {}".format(uploaded))
  67. print("pending: {}".format(total - uploaded))
  68. elif action == 'index-files':
  69. counter = 0
  70. already_indexed = 0
  71. conn = sqlite3.connect(dbpath)
  72. path = os.path.join('/var/fourier', device_id)
  73. if args.station:
  74. path = os.path.join(path, args.station)
  75. for folder, folders, files in os.walk(path):
  76. for file in files:
  77. if not file.endswith('.mp3'):
  78. continue
  79. filename = os.path.join(folder, file)
  80. dt = datetime.strptime(
  81. file[:19],
  82. '%Y-%m-%dT%H-%M-%S'
  83. )
  84. try:
  85. if args.from_date:
  86. do_insert = dt >= args.from_date
  87. else:
  88. do_insert = True
  89. if do_insert:
  90. thehash = hash_file(filename)
  91. insert_file(thehash, filename, dt, db=conn)
  92. counter += 1
  93. print(dt)
  94. except sqlite3.IntegrityError:
  95. already_indexed += 1
  96. print('already indexed: {}'.format(filename))
  97. if not args.dry_run:
  98. conn.commit()
  99. else:
  100. conn.rollback()
  101. print('\n[WARNING] DRY RUN FINISHED')
  102. print('----------------------------------')
  103. print('total files indexed: {}'.format(counter))
  104. print('total files in existence: {}'.format(already_indexed))
  105. print('----------------------------------')
  106. elif action == 'setup':
  107. if not os.path.isfile(dbpath):
  108. conn = sqlite3.connect(dbpath)
  109. cursor = conn.cursor()
  110. sentences = [
  111. """create table file(
  112. hash text primary key,
  113. station text,
  114. timestamp int,
  115. filename text,
  116. uploaded int
  117. )""",
  118. "create index timestamp_index_desc on file (timestamp desc)",
  119. "create index timestamp_index_asc on file (timestamp desc)",
  120. ]
  121. for query in sentences:
  122. cursor.execute(query)
  123. conn.commit()
  124. else:
  125. print('database already installed')
  126. sys.exit(1)
  127. elif args.entity == 'station':
  128. if action == 'list':
  129. stations_path = os.path.join('/var/fourier', device_id)
  130. dirs = os.listdir(stations_path)
  131. for dr in dirs:
  132. if '.' not in dr:
  133. print(dr)
  134. if __name__ == '__main__':
  135. main()