You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

database.py 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import sqlite3
  2. from datetime import datetime
  3. conn, username, db = None, None, None
  4. def connect(database, user):
  5. global conn, username, db
  6. conn = sqlite3.connect(database)
  7. username = user
  8. db = database # For reconnecting;
  9. c = conn.cursor()
  10. # Create tables if they do not exist.
  11. c.execute('''
  12. CREATE TABLE IF NOT EXISTS file (
  13. hash text,
  14. filename text,
  15. size integer,
  16. fid integer,
  17. aid integer,
  18. crc32 text,
  19. ep_no text,
  20. group_name text,
  21. file_type text,
  22. updated text
  23. )
  24. ''')
  25. c.execute('''
  26. CREATE TABLE IF NOT EXISTS file_status (
  27. fid integer,
  28. username text,
  29. watched boolean,
  30. mylist_id integer,
  31. updated text
  32. );
  33. ''')
  34. c.execute('''
  35. CREATE TABLE IF NOT EXISTS anime (
  36. aid integer,
  37. total_eps integer,
  38. name text,
  39. type text,
  40. updated text
  41. );
  42. ''')
  43. conn.commit()
  44. def _check_connection():
  45. c = conn.cursor()
  46. try:
  47. c.execute('select 1 from file')
  48. c.fetchall()
  49. except sqlite3.OperationalError:
  50. conn.close()
  51. connect(db, username)
  52. def load(thing):
  53. _check_connection()
  54. c = conn.cursor()
  55. # Lookup thing by name
  56. if not thing.hash:
  57. c.execute('''
  58. SELECT hash, fid, aid, crc32, ep_no, group_name, file_type, updated
  59. FROM file
  60. WHERE filename = ? AND size = ?
  61. ''', (thing.name, thing.size))
  62. r = c.fetchone()
  63. if r:
  64. thing.hash, thing.fid, thing.aid, thing.crc32, thing.ep_no, \
  65. thing.group_name, thing.file_type = r[:7]
  66. thing.updated = datetime.strptime(r[7], '%Y-%m-%d %H:%M:%S.%f')
  67. # Lookup thing by hash
  68. if thing.hash:
  69. c.execute('''
  70. SELECT
  71. filename, fid, aid, crc32, ep_no, group_name, file_type, updated
  72. FROM file
  73. WHERE hash = ? AND size = ?
  74. ''', (thing.hash, thing.size))
  75. r = c.fetchone()
  76. if not r:
  77. # This is a new thing
  78. thing.dirty = True
  79. return
  80. if r[0] != thing.name:
  81. thing.dirty = True
  82. thing.fid, thing.aid, thing.crc32, thing.ep_no, thing.group_name, \
  83. thing.file_type = r[1:7]
  84. thing.updated = datetime.strptime(r[7], '%Y-%m-%d %H:%M:%S.%f')
  85. if thing.fid:
  86. # Look up the status.
  87. c.execute('''
  88. SELECT watched, mylist_id, updated
  89. FROM file_status
  90. WHERE fid = ? AND username = ?
  91. ''', (thing.fid, username))
  92. r = c.fetchone()
  93. if r:
  94. thing.mylist_id = r[0]
  95. thing.added = bool(r[0])
  96. thing.watched = bool(r[1])
  97. thing.updated = min(
  98. thing.updated,
  99. datetime.strptime(r[2], '%Y-%m-%d %H:%M:%S.%f'))
  100. if thing.aid:
  101. c.execute('''
  102. SELECT total_eps, name, type, updated
  103. FROM anime
  104. WHERE aid = ?
  105. ''', (thing.aid, ))
  106. r = c.fetchone()
  107. if r:
  108. thing.anime_total_eps, thing.anime_name, thing.anime_type = r[:3]
  109. thing.updated = min(
  110. thing.updated,
  111. datetime.strptime(r[3], '%Y-%m-%d %H:%M:%S.%f'))
  112. def save(thing):
  113. _check_connection()
  114. if thing.dirty:
  115. c = conn.cursor()
  116. c.execute('''
  117. DELETE FROM file
  118. WHERE hash = ? AND size = ? OR fid = ?
  119. ''', (thing.hash, thing.size, thing.fid))
  120. c.execute('''
  121. INSERT INTO file (
  122. hash, filename, size, fid, aid, crc32, ep_no,
  123. group_name, file_type, updated)
  124. VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  125. ''', (
  126. thing.hash, thing.name, thing.size, thing.fid, thing.aid,
  127. thing.crc32, thing.ep_no, thing.group_name, thing.file_type,
  128. str(thing.updated)))
  129. c.execute('''
  130. DELETE FROM file_status
  131. WHERE fid = ? AND username = ?
  132. ''', (thing.fid, username))
  133. if thing.added:
  134. c.execute('''
  135. INSERT INTO file_status (
  136. fid, username, watched, mylist_id, updated)
  137. VALUES (?, ?, ?, ?, ?)
  138. ''', (
  139. thing.fid, username, thing.watched, thing.mylist_id,
  140. str(thing.updated)))
  141. c.execute('''
  142. DELETE FROM anime
  143. WHERE aid = ?
  144. ''', (thing.aid, ))
  145. c.execute('''
  146. INSERT INTO anime (aid, total_eps, name, type, updated)
  147. VALUES (?, ?, ?, ?, ?)
  148. ''', (
  149. thing.aid, thing.anime_total_eps, thing.anime_name,
  150. thing.anime_type, str(thing.updated)))
  151. conn.commit()
  152. def find_duplicates():
  153. _check_connection()
  154. c = conn.cursor()
  155. f = conn.cursor()
  156. c.execute('''
  157. SELECT DISTINCT a.aid, anime.name, a.ep_no
  158. FROM file a, file b, anime
  159. WHERE
  160. a.aid = b.aid AND
  161. a.aid = anime.aid AND
  162. a.ep_no = b.ep_no AND
  163. a.hash != b.hash AND (
  164. (a.file_type ISNULL) OR
  165. (b.file_type ISNULL) OR
  166. a.file_type = b.file_type
  167. )
  168. ''')
  169. for aid, name, ep in c.fetchall():
  170. yield ['status', 'dups_for', name, str(ep)]
  171. f.execute('''
  172. SELECT fid, filename, file_type
  173. FROM file
  174. WHERE aid = ? and ep_no = ?
  175. ''', (aid, ep))
  176. for fid, name, type in f.fetchall():
  177. if not type:
  178. yield ['status', 'dup_no_type', str(fid), name]
  179. else:
  180. yield ['status', 'dup', str(fid), name, type]
  181. def forget(fid):
  182. _check_connection()
  183. c = conn.cursor()
  184. c.execute(
  185. 'DELETE FROM file_status WHERE fid = ? AND username = ?',
  186. (fid, username))
  187. c.execute(
  188. 'SELECT count(*) FROM file_status WHERE fid = ?',
  189. (fid,))
  190. if c.fetchone() != (0,):
  191. yield ['error', 'dups_forget_in_use']
  192. else:
  193. c.execute('DELETE FROM file WHERE fid = ?', (fid,))
  194. yield ['status', 'dups_forgot', str(fid)]
  195. conn.commit()