Moved all python related scripts to app directory

This commit is contained in:
2017-08-14 22:42:48 +02:00
parent d2bed84ecb
commit ea97a0b4af
17 changed files with 0 additions and 0 deletions

223
app/classedStray.py Executable file
View File

@@ -0,0 +1,223 @@
#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-04-05 18:40:11
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-06-18 21:49:33
import os.path, hashlib, time, glob, sqlite3, re, json, tweepy
import logging
from functools import reduce
from fuzzywuzzy import process
from langdetect import detect
from time import sleep
import env_variables as env
dirHash = None
class twitter(object):
def __init__(self):
if '' in [env.consumer_key, env.consumer_secret, env.access_token, env.access_token_secret]:
logging.warning('Twitter api keys not set!')
self.consumer_key = env.consumer_key
self.consumer_secret = env.consumer_secret
self.access_token = env.access_token
self.access_token_secret = env.access_token_secret
self.authenticate()
def authenticate(self):
auth = tweepy.OAuthHandler(self.consumer_key, self.consumer_secret)
auth.set_access_token(self.access_token, self.access_token_secret)
self.api_token = tweepy.API(auth)
def api(self):
return self.api_token
def dm(self, message, user='kevinmidboe'):
response = self.api_token.send_direct_message(user, text=message)
class strayEpisode(object):
def __init__(self, parent, childrenList):
self.parent = parent
self.children = childrenList
self._id = self.getUniqueID()
self.showName = self.findSeriesName()
self.season = self.getSeasonNumber()
self.episode = self.getEpisodeNumber()
self.videoFiles = []
self.subtitles = []
self.trash = []
self.sortMediaItems()
if self.saveToDB():
self.notifyInsert()
def getUniqueID(self):
# conn = sqlite3.connect(env.db_path)
# c = conn.cursor()
# c.execute("SELECT id FROM stray_eps WHERE id is " + )
return hashlib.md5("b'{}'".format(self.parent).encode()).hexdigest()[:8]
def findSeriesName(self):
find = re.compile("^[a-zA-Z. ]*")
m = re.match(find, self.parent)
if m:
name, hit = process.extractOne(m.group(0), getShowNames().keys())
if hit >= 60:
return name
else:
# This should be logged or handled somehow
return 'Unmatched!'
def getSeasonNumber(self):
m = re.search('[sS][0-9]{1,2}', self.parent)
if m:
return re.sub('[sS]', '', m.group(0))
def getEpisodeNumber(self):
m = re.search('[eE][0-9]{1,2}', self.parent)
if m:
return re.sub('[eE]', '', m.group(0))
def removeUploadSign(self, file):
match = re.search('-[a-zA-Z\[\]\-]*.[a-z]{3}', file)
if match:
uploader = match.group(0)[:-4]
return re.sub(uploader, '', file)
return file
def analyseSubtitles(self, subFile):
# TODO verify that it is a file
try:
subtitlePath = os.path.join([env.show_dir, self.parent, subFile])
except TypeError:
# TODO don't get a list in subtitlePath
return self.removeUploadSign(subFile)
f = open(subtitlesPath, 'r', encoding='ISO-8859-15')
language = detect(f.read())
f.close()
file = self.removeUploadSign(subFile)
if 'sdh' in subFile.lower():
return '.'.join([file[:-4], 'sdh', language, file[-3:]])
return '.'.join([file[:-4], language, file[-3:]])
def sortMediaItems(self):
for child in self.children:
if child[-3:] in env.mediaExt and child[:-4] not in env.mediaExcluders:
self.videoFiles.append([child, self.removeUploadSign(child)])
elif child[-3:] in env.subExt:
self.subtitles.append([child, self.analyseSubtitles(child)])
else:
self.trash.append(child)
def notifyInsert(self):
# Send unique id. (time)
tweetObj = twitter()
if self.showName is None:
message = 'Error adding ep: ' + self._id
else:
message = 'Added episode:\n' + self.showName + ' S' + self.season\
+ 'E' + self.episode + '\nDetails: \n https://kevinmidboe.com/seasoned/verified.html?id=' + self._id
tweetObj.dm(message)
def saveToDB(self):
# TODO Setup script
conn = sqlite3.connect(env.db_path)
c = conn.cursor()
path = '/'.join([env.show_dir, self.parent])
video_files = json.dumps(self.videoFiles)
subtitles = json.dumps(self.subtitles)
trash = json.dumps(self.trash)
try:
c.execute("INSERT INTO stray_eps ('id', 'parent', 'path', 'name', 'season', 'episode', 'video_files', 'subtitles', 'trash') VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", \
[self._id, self.parent, path, self.showName, self.season, self.episode, video_files, subtitles, trash])
except sqlite3.IntegrityError:
logging.info(self._id + ': episode already registered')
return False
conn.commit()
conn.close()
return True
def getDirContent(dir=env.show_dir):
# TODO What if item in db is not in this list?
try:
return [d for d in os.listdir(dir) if d[0] != '.']
except FileNotFoundError:
# TODO Log to error file
logging.info('Error: "' + dir + '" is not a directory.')
# Hashes the contents of media folder to easily check for changes.
def directoryChecksum():
dirList = getDirContent()
# Creates a string of all the list items.
dirConcat = reduce(lambda x, y: x + y, dirList, "")
m = hashlib.md5()
m.update(bytes(dirConcat, 'utf-16be')) # String to byte conversion.
global dirHash
if dirHash != m.digest():
dirHash = m.digest()
return True
return False
def getShowNames():
conn = sqlite3.connect(env.db_path)
c = conn.cursor()
c.execute('SELECT show_names, date_added, date_modified FROM shows')
returnList = {}
for name, added, modified in c.fetchall():
returnList[name] = [added, modified]
conn.close()
return returnList
def XOR(list1, list2):
return set(list1) ^ set(list2)
def filterChildItems(parent):
try:
children = getDirContent('/'.join([env.show_dir, parent]))
if children:
strayEpisode(parent, children)
except FileNotFoundError:
# TODO Log to error file
logging.info('Error: "' + '/'.join([env.show_dir, parent]) + '" is not a valid directory.')
def getNewItems():
newItems = XOR(getDirContent(), getShowNames())
for item in newItems:
filterChildItems(item)
def main():
# TODO Verify env variables (showDir)
start_time = time.time()
if directoryChecksum():
getNewItems()
logging.debug("--- %s seconds ---" % '{0:.4f}'.format((time.time() - start_time)))
if __name__ == '__main__':
if (os.path.exists(env.logfile)):
logging.basicConfig(filename=env.logfile, level=logging.DEBUG)
else:
print('Logfile could not be found at ' + env.logfile + '. Verifiy presence or disable logging in config.')
exit(0)
while True:
main()
sleep(30)

View File

26
app/modules/addSubLanguage.py Executable file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-03-04 13:46:28
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-03-04 14:03:57
from langdetect import detect
from removeUploader import removeUploader
testFiles = ['subs/The.Man.from.U.N.C.L.E.2015.1080p-[eztv].srt',
'subs/The.Man.from.U.N.C.L.E.2015.1080p-[eztv]ENGLUISH.srt']
def detectLanguage(file):
f = open(file, 'r', encoding= 'ISO-8859-15')
language = detect(f.read())
f.close()
return removeUploader(file)[:-3] + language + '.srt'
def addLangExtension():
for file in testFiles:
print(detectLanguage(file))
if __name__ == '__main__':
addLangExtension()

16
app/modules/createPasteee.py Executable file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-02-23 21:41:40
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-03-05 19:35:10
from pasteee import Paste
def createPasteee():
paste = Paste('Test pastee', views=10)
print(paste)
print(paste['raw'])
if __name__ == '__main__':
createPasteee()

23
app/modules/dirHash.py Executable file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-04-05 15:24:17
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-04-05 18:22:13
import os, hashlib
from functools import reduce
hashDir = '/Volumes/media/tv'
def main():
dirList = os.listdir(hashDir)
concat = reduce(lambda x, y: x + y, dirList, "")
m = hashlib.md5()
m.update(bytes(concat, 'utf-16be'))
return m.digest()
if __name__ == '__main__':
print(main())
# TODO The hash value should be saved in a global manner

125
app/modules/folderCreator.py Executable file
View File

@@ -0,0 +1,125 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-03-05 13:52:45
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-03-05 17:14:25
import sqlite3, json, os, tweepy
from re import sub
dbPath = 'shows.db'
consumer_key, consumer_secret = 'yvVTrxNtVsLkoHxKWxh4xvgjg', '39OW6Q8fIKDXvTPPCaEJDULcYaHC5XZ3fe7HHCGtdepBKui2jK'
access_token, access_token_secret = '3214835117-OXVVLYeqUScRAPMqfVw5hS8NI63zPnWOVK63C5I', 'ClcGnF8vW6DbvgRgjwU6YjDc9f2oxMzOvUAN8kzpsmbcL'
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
def newnameMediaitems(media_items):
# media_items = [['New.Girl.S06E18.720p.HDTV.x264-EZTV.srt', '-EZTV', 'nl'], ['New.Girl.S06E18.720p.HDTV.x264-FLEET.srt', '-FLEET', 'en']]
media_items = json.loads(media_items)
returnList = []
for item in media_items:
returnList.append([item[0], item[0].replace(item[1], '')])
return returnList
def newnameSubtitles(subtitles):
subtitles = json.loads(subtitles)
returnList = []
for item in subtitles:
returnList.append([item[0], item[0].replace(item[1], '.' + item[2])])
return returnList
def updateMovedStatus(episodeDict):
conn = sqlite3.connect(dbPath)
c = conn.cursor()
c.execute('UPDATE stray_episodes SET moved = 1 WHERE original is "' + episodeDict['original'] + '"')
conn.commit()
conn.close()
def unpackEpisodes():
conn = sqlite3.connect(dbPath)
c = conn.cursor()
cursor = c.execute('SELECT * FROM stray_episodes WHERE verified = 1 AND moved = 0')
episodeList = []
for row in c.fetchall():
columnNames = [description[0] for description in cursor.description]
episodeDict = dict.fromkeys(columnNames)
for i, key in enumerate(episodeDict.keys()):
episodeDict[key] = row[i]
episodeList.append(episodeDict)
conn.close()
return episodeList
def createFolders(episode):
showDir = '/media/hdd1/tv/%s/'% episode['name']
episodeFormat = '%s S%sE%s/'% (episode['name'], episode['season'], episode['episode'])
seasonFormat = '%s Season %s/'% (episode['name'], episode['season'])
if not os.path.isdir(showDir + seasonFormat):
os.makedirs(showDir + seasonFormat)
if not os.path.isdir(showDir + seasonFormat + episodeFormat):
os.makedirs(showDir + seasonFormat + episodeFormat)
def moveFiles(episode):
# TODO All this should be imported from config file
showDir = '/media/hdd1/tv/'
episodeFormat = '%s S%sE%s/'% (episode['name'], episode['season'], episode['episode'])
seasonFormat = '%s/%s Season %s/'% (episode['name'], episode['name'], episode['season'])
# TODO All this is pretty ballsy to do this hard/stict.
newMediaitems = newnameMediaitems(episode['media_items'])
for item in newMediaitems:
old_location = showDir + episode['original'] + '/' + item[0]
new_location = showDir + seasonFormat + episodeFormat + item[1]
os.rename(old_location, new_location)
if episode['subtitles']:
newSubtitles = newnameSubtitles(episode['subtitles'])
for item in newSubtitles:
old_location = showDir + episode['original'] + '/' + item[0]
new_location = showDir + seasonFormat + episodeFormat + item[1]
os.rename(old_location, new_location)
# shutil.rmtree(showDir + episode['original'])
if episode['trash']:
for trash in json.loads(episode['trash']):
os.remove(showDir + episode['original'] + '/'+ trash)
# TODO Maybe move to delete folder instead, than user can dump.
os.rmdir(showDir + episode['original'])
updateMovedStatus(episode)
api.create_favorite(episode['response_id'])
def findVerified():
episodes = unpackEpisodes()
if episodes:
for episode in episodes:
createFolders(episode)
moveFiles(episode)
if __name__ == '__main__':
findVerified()

57
app/modules/pasteee.py Normal file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
pasteee module
Allows pasting to https://paste.ee
https://github.com/i-ghost/pasteee
"""
# 2 <-> 3
from urllib.request import urlopen
from urllib.request import Request as urlrequest
from urllib.parse import urlencode
from urllib import error as urlerror
import json
class PasteError(Exception):
"""Exception class for this module"""
pass
class Paste(object):
def __new__(cls, paste,
private=True, lang="plain",
key="public", desc="",
expire=0, views=0, encrypted=False):
if not paste:
raise PasteError("No paste provided")
if expire and views:
# API incorrectly returns success so we raise error locally
raise PasteError("Options 'expire' and 'views' are mutually exclusive")
request = urlrequest(
"http://paste.ee/api",
data=urlencode(
{
'paste': paste,
'private': bool(private),
'language': lang,
'key': key,
'description': desc,
'expire': expire,
'views': views,
'encrypted': bool(encrypted),
'format': "json"
}
).encode("utf-8"),
headers={'User-Agent': 'Mozilla/5.0'}
)
try:
result = json.loads(urlopen(request).read().decode("utf-8"))
return result["paste"]
except urlerror.HTTPError:
print("Couldn't send paste")
raise
except KeyError:
raise PasteError("Invalid paste option: %s" % (result["error"]))

30
app/modules/readDB.py Executable file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-03-03 22:35:38
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-03-04 11:09:09
import sqlite3
from fuzzywuzzy import process
path = "/Users/KevinMidboe/Dropbox/python/seasonedShows/shows.db"
def main():
conn = sqlite3.connect(path)
c = conn.cursor()
c.execute('SELECT show_names, date_added, date_modified FROM shows')
returnList = {}
for name, added, modified in c.fetchall():
returnList[name] = [added, modified]
while True:
query = input('Query: ')
print(process.extractOne(query, returnList.keys()))
conn.close()
main()

24
app/modules/removeUploader.py Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-03-04 13:47:32
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-03-04 13:53:12
import re
testFile = '/Volumes/media/tv/New Girl/New Girl Season 06/New Girl S06E18/New.Girl.S06E18.Young.Adult.1080p.WEB-DL.DD5.1.H264-[eztv]-horse.mkv'
def removeUploader(file=testFile):
match = re.search('-[a-zA-Z\[\]\-]*.[a-z]{3}', file)
if match and input('Remove uploader:\t' + match.group(0)[:-4] + ' [Y/n] ') != 'n':
uploader, ext = match.group(0).split('.')
# if ext not in subExtensions:
# file = file.replace(uploader, '')
# else:
# file = file.replace(uploader, '.eng')
file = file.replace(uploader, '')
return file
if __name__ == '__main__':
print(removeUploader())

22
app/modules/seasonedFolders.py Executable file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-03-05 15:55:16
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-03-05 17:25:50
from time import sleep
from findStray import findStray
from tweetNewEpisodes import tweetNewEpisodes
from folderCreator import findVerified
def main():
while True:
findStray()
tweetNewEpisodes()
findVerified()
sleep(10)
if __name__ == '__main__':
main()

12
app/modules/subLangfinder.py Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from langdetect import detect
def main():
f = open('/Volumes/media/movies/The Man from UNCLE (2015)/The.Man.from.U.N.C.L.E.2015.1080p.nl.srt', 'r', encoding = "ISO-8859-15")
print(detect(f.read()))
f.close()
print(f.close())
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

137
app/modules/tweetNewEpisodes.py Executable file
View File

@@ -0,0 +1,137 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-03-04 16:50:09
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-03-05 16:51:35
import tweepy, sqlite3
from pasteee import Paste
from pprint import pprint
dbPath = "shows.db"
consumer_key, consumer_secret = 'yvVTrxNtVsLkoHxKWxh4xvgjg', '39OW6Q8fIKDXvTPPCaEJDULcYaHC5XZ3fe7HHCGtdepBKui2jK'
access_token, access_token_secret = '3214835117-OXVVLYeqUScRAPMqfVw5hS8NI63zPnWOVK63C5I', 'ClcGnF8vW6DbvgRgjwU6YjDc9f2oxMzOvUAN8kzpsmbcL'
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
def unpackEpisode(episode):
conn = sqlite3.connect(dbPath)
c = conn.cursor()
cursor = c.execute('SELECT * FROM stray_episodes')
columnNames = [description[0] for description in cursor.description]
conn.close()
episodeDict = dict.fromkeys(columnNames)
for i, key in enumerate(episodeDict.keys()):
episodeDict[key] = episode[i]
return episodeDict
def prettifyEpisode(episode):
returnString = ''
for key, value in episode.items():
returnString += key + ': ' + str(value) + '\n'
return returnString
def createPasteee(episode):
return Paste(prettifyEpisode(episode), private=False, desc="My first paste", views=10)
def tweetString(episode):
print(type(episode['episode']), episode)
tweetString = '@KevinMidboe\nAdded episode:\n' + episode['name'] + ' S' + str(episode['season'])\
+ 'E' + str(episode['episode']) + '\nDetails: '
return tweetString
# TODO What if error when tweeting, no id_str
def tweet(tweetString):
response = api.update_status(status=tweetString)
return response.id_str
def updateTweetID(episodeDict, id):
conn = sqlite3.connect(dbPath)
c = conn.cursor()
c.execute('UPDATE stray_episodes SET tweet_id = ' + id + ' WHERE original is "' + episodeDict['original'] + '"')
conn.commit()
conn.close()
def tweetEpisode(episode):
pasteee = createPasteee(episode)
tweet_id = tweet(tweetString(episode) + pasteee['raw'])
updateTweetID(episode, tweet_id)
def getLastTweets(user, count=1):
return api.user_timeline(screen_name=user,count=count)
def verifyByID(id, reponse_id):
conn = sqlite3.connect(dbPath)
c = conn.cursor()
c.execute('UPDATE stray_episodes SET verified = 1, response_id = ' + reponse_id + ' WHERE tweet_id is "' + id + '"')
conn.commit()
conn.close()
# TODO Add more parsing than confirm
def parseReply(tweet):
if b'\xf0\x9f\x91\x8d' in tweet.text.encode('utf-8'):
print('Verified!')
verifyByID(tweet.in_reply_to_status_id_str, tweet.id_str)
def getReply(tweet):
conn = sqlite3.connect(dbPath)
c = conn.cursor()
tweetID = tweet.in_reply_to_status_id_str
c.execute('SELECT * FROM stray_episodes WHERE tweet_id is ' + tweetID + ' AND verified is 0')
row = c.fetchone()
if row:
episode = unpackEpisode(row)
conn.close()
parseReply(tweet)
conn.close()
def lookForNewEpisodes():
conn = sqlite3.connect(dbPath)
c = conn.cursor()
c.execute('SELECT * FROM stray_episodes WHERE tweet_id is NULL')
for row in c.fetchall():
episode = unpackEpisode(row)
tweetEpisode(episode)
conn.close()
def checkForReply():
for tweet in getLastTweets('KevinMidboe', 10):
if tweet.in_reply_to_status_id_str != None:
getReply(tweet)
def tweetNewEpisodes():
lookForNewEpisodes()
checkForReply()
if __name__ == '__main__':
tweetNewEpisodes()

View File

@@ -0,0 +1,104 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-03-04 14:06:53
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-03-05 11:48:47
import tweepy, sqlite3
from pasteee import Paste
from pprint import pprint
dbPath = "shows.db"
consumer_key, consumer_secret = 'yvVTrxNtVsLkoHxKWxh4xvgjg', '39OW6Q8fIKDXvTPPCaEJDULcYaHC5XZ3fe7HHCGtdepBKui2jK'
access_token, access_token_secret = '3214835117-OXVVLYeqUScRAPMqfVw5hS8NI63zPnWOVK63C5I', 'ClcGnF8vW6DbvgRgjwU6YjDc9f2oxMzOvUAN8kzpsmbcL'
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
apiUser = api.me()
apiUsername, apiUserID = apiUser.screen_name, apiUser.id_str
def tweetNewEpisode(episode):
createPasteee()
def unpackEpisode(episode):
episodeDict = dict.fromkeys(['original', 'full_path', 'name', 'season', 'episode',\
'media_items', 'subtitles', 'trash', 'tweet_id', 'verified'])
for i, key in enumerate(episodeDict.keys()):
episodeDict[key] = episode[i]
return episodeDict
def
def updateTweetID(episodeDict, id):
conn = sqlite3.connect(dbPath)
c = conn.cursor()
c.execute('UPDATE stray_episodes SET tweet_id = ' + id + ' WHERE original is ' + episodeDict['original'])
conn.commit()
conn.close()
def getUntweetedEpisodes():
conn = sqlite3.connect(dbPath)
c = conn.cursor()
c.execute('SELECT * FROM stray_episodes WHERE tweet_id is NULL')
for episode in c.fetchall():
tweetNewEpisode(episode)
conn.close()
exit(0)
return episode
def lastTweet(user, count=1):
return api.user_timeline(screen_name=user,count=count)
def checkReply():
originalTweet = lastTweet('pi_midboe')[0]
originalID, lastText = originalTweet.id_str, originalTweet.text
tweets = lastTweet('KevinMidboe', 10)
for tweet in tweets:
tweetID = tweet.in_reply_to_status_id_str
if tweetID == originalID:
print(tweet.text)
def unpackEpisodes():
conn = sqlite3.connect(dbPath)
c = conn.cursor()
c.execute('SELECT * FROM stray_episodes WHERE tweet_id IS NULL and verified IS 0')
content = c.fetchall()
conn.close()
return content
def tweet(tweetString):
if not lastTweet('pi_midboe')[0].text.startswith(tweetString):
paste = Paste(unpackEpisodes(), private=False, desc="My first paste", views=2)
tweetString += paste['raw']
response = api.update_status(status=tweetString)
print('\n', response.id_str)
def main():
episode = getUntweetedEpisodes()
print(episode)
tweet('@KevinMidboe\nAdded episode: \nNew Girl S06E16\n\nDetails: ')
# unpackEpisodes()
checkReply()
if __name__ == '__main__':
main()

97
app/moveSeasoned.py Executable file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-04-12 23:27:51
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-06-27 15:58:09
import sys, sqlite3, json, os.path
import logging
import env_variables as env
class episode(object):
def __init__(self, id):
self.id = id
self.getVarsFromDB()
def getVarsFromDB(self):
c = sqlite3.connect(env.db_path).cursor()
c.execute('SELECT parent, name, season, episode, video_files, subtitles, trash FROM stray_eps WHERE id = ?', (self.id,))
returnMsg = c.fetchone()
self.parent = returnMsg[0]
self.name = returnMsg[1]
self.season = returnMsg[2]
self.episode = returnMsg[3]
self.video_files = json.loads(returnMsg[4])
self.subtitles = json.loads(returnMsg[5])
self.trash = json.loads(returnMsg[6])
c.close()
self.queries = {
'parent': [env.show_dir, self.parent],
'season': [env.show_dir, self.name, self.name + ' Season ' + "%02d" % self.season],
'episode': [env.show_dir, self.name, self.name + ' Season ' + "%02d" % self.season, \
self.name + ' S' + "%02d" % self.season + 'E' + "%02d" % self.episode],
}
def typeDir(self, dType, create=False, mergeItem=None):
url = '/'.join(self.queries[dType])
if create and not os.path.isdir(url):
os.makedirs(url)
fix_ownership(url)
if mergeItem:
return '/'.join([url, str(mergeItem)])
return url
def fix_ownership(path):
# TODO find this from username from config
uid = 1000
gid = 113
os.chown(path, uid, gid)
def moveStray(strayId):
ep = episode(strayId)
for item in ep.video_files:
try:
old_dir = ep.typeDir('parent', mergeItem=item[0])
new_dir = ep.typeDir('episode', mergeItem=item[1], create=True)
os.rename(old_dir, new_dir)
except FileNotFoundError:
logging.warning(old_dir + ' does not exits, cannot be moved.')
for item in ep.subtitles:
try:
old_dir = ep.typeDir('parent', mergeItem=item[0])
new_dir = ep.typeDir('episode', mergeItem=item[1], create=True)
os.rename(old_dir, new_dir)
except FileNotFoundError:
logging.warning(old_dir + ' does not exits, cannot be moved.')
for item in ep.trash:
try:
os.remove(ep.typeDir('parent', mergeItem=item))
except FileNotFoundError:
logging.warning(ep.typeDir('parent', mergeItem=item) + 'does not exist, cannot be removed.')
fix_ownership(ep.typeDir('episode'))
for root, dirs, files in os.walk(ep.typeDir('episode')):
for item in files:
fix_ownership(os.path.join(ep.typeDir('episode'), item))
# TODO because we might jump over same files, the dir might no longer
# be empty and cannot remove dir like this.
try:
os.rmdir(ep.typeDir('parent'))
except FileNotFoundError:
logging.warning('Cannot remove ' + ep.typeDir('parent') + ', file no longer exists.')
if __name__ == '__main__':
if (os.path.exists(env.logfile)):
logging.basicConfig(filename=env.logfile, level=logging.INFO)
else:
print('Logfile could not be found at ' + env.logfile + '. Verifiy presence or disable logging in config.')
moveStray(sys.argv[-1])

57
app/seasonMover.py Executable file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: KevinMidboe
# @Date: 2017-07-11 19:16:23
# @Last Modified by: KevinMidboe
# @Last Modified time: 2017-07-11 19:16:23
import fire, re, os
class seasonMover(object):
''' Moving multiple files to multiple folders with
identifer '''
workingDir = os.getcwd()
def create(self, name, interval):
pass
def move(self, fileSyntax, folderName):
episodeRange = self.findInterval(fileSyntax)
self.motherMover(fileSyntax, folderName, episodeRange)
def findInterval(self, item):
if (re.search(r'\((.*)\)', item) is None):
raise ValueError('Need to declare an identifier e.g. (1..3) in: \n\t' + item)
start = int(re.search('\((\d+)\.\.', item).group(1))
end = int(re.search('\.\.(\d+)\)', item).group(1))
return list(range(start, end+1))
def removeUploadSign(self, file):
match = re.search('-[a-zA-Z\[\]\-]*.[a-z]{3}', file)
if match:
uploader = match.group(0)[:-4]
return re.sub(uploader, '', file)
return file
def motherMover(self, fileSyntax, folderName, episodeRange):
# Call for sub of fileList
# TODO check if range is same as folderContent
for episode in episodeRange:
leadingZeroNumber = "%02d" % episode
fileName = re.sub(r'\((.*)\)', leadingZeroNumber, fileSyntax)
oldPath = os.path.join(self.workingDir,fileName)
newFolder = os.path.join(self.workingDir, folderName + leadingZeroNumber)
newPath = os.path.join(newFolder, self.removeUploadSign(fileName))
os.makedirs(newFolder)
os.rename(oldPath, newPath)
# print(newFolder)
# print(oldPath + ' --> ' + newPath)
if __name__ == '__main__':
fire.Fire(seasonMover)