-
Notifications
You must be signed in to change notification settings - Fork 3
/
vdbapi3.py
189 lines (164 loc) · 5.74 KB
/
vdbapi3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import json
import re
import urllib
import treq
from twisted.internet import reactor, task, defer
from twisted.web.http_headers import Headers
from tools import clog, getTime
from conf import config
from connections import apiClient
import database
syst = 'vdbapi'
u_agent_str = config['UserAgent']['vocadb'].encode('utf-8')
HEADERS = Headers({'User-Agent': [u_agent_str]})
def getRes(res):
try:
return res[0][0]
except(TypeError, IndexError):
return
def setVocadbBySongId(mType, mId, songId, nameLower, isReg, refresh=False):
"""
Used for $vocadb {vocadb_songID} command
Search song in database,
if not in database, request data from vocadb, and save it to local db.
If refresh=True, skip database lookup and get info from vocadb.
This is used when the db cache is out of date.
Returns deferred of vocadb data, or None
"""
if not refresh:
d = database.getVocadbBySongId(songId)
d.addCallback(getRes)
d.addCallback(conditionSetVocadbSongId, songId)
elif refresh:
d = conditionSetVocadbSongId(None, songId)
# 4 is manual entry
d.addCallback(saveSongResults, mType, mId, nameLower, isReg, 4)
return d
def conditionSetVocadbSongId(result, songId):
if result is not None:
return result
elif result is None:
return getVdbBySongId(songId)
def lookupSongInDb(mType, mId):
"""
Return deferred of results of DB lookup (dict),
Return None if there is no record on the local db.
"""
d = database.getVocadbData(mType, mId)
d.addCallback(getRes)
return d
def obtainSong(mType, mId, nameLower, isReg):
"""
Return deferred of result of vocadb (including
yt desc lookup)
Deferred results in None when no match is found.
Results are saved to the database.
"""
d = getVdbByPvId(mType, mId)
d.addCallback(conditionVocadbYtPvResult, mType, mId, nameLower, isReg)
d.addErrback(err)
return d
def conditionVocadbYtPvResult(result, mType, mId, nameLower, isReg):
"""If result is None,
search YT description for a nico ID"""
if not result and mType == 'yt':
d = apiClient.requestYtApi(mId, 'desc')
d.addCallback(_cbYtDesc, mType, mId, nameLower, isReg)
return d
else:
saveSongResults(result, mType, mId, nameLower, isReg, 0)
return result
def _cbYtDesc(result, mType, mId, nameLower, isReg):
items = result['items']
if not items:
clog.error('no youtube description', syst)
saveSongResults(None, mType, mId, nameLower, isReg, 1)
return
desc = items[0]['snippet']['description']
rx = r'sm[0-9]{6,9}|nm[0-9]{6,9}'
m = re.search(rx, desc)
clog.info('looking for smid in yt desc', syst)
if m:
nicoId = m.group(0)
clog.info('found nicoid: %s' % nicoId, syst)
d = getVdbByPvId('nico', nicoId)
d.addCallback(saveSongResults, mType, mId, nameLower, isReg, 1)
return d
else:
clog.info('did not find nicoid in description', syst)
return saveSongResults(None, mType, mId, nameLower, isReg, 0)
def saveSongResults(results, mType, mId, nameLower, isReg, method):
"""
Save song to DB, update mediasong and pass through results.
"""
if not results:
print "save with 0"
songId = 0
d = database.upsertMediaSong(songId, mType, mId, nameLower, isReg,
getTime(), 1)
d.addErrback(err)
elif results.get('message') or not results.get('id'):
print "bad request"
songId = -1
d = database.upsertMediaSong(songId, mType, mId, nameLower, isReg,
getTime(), 1)
d.addErrback(err)
else:
# save song data to song table, then update/insert MediaSong
songId = results.get('id')
data = json.dumps(results)
d = database.upsertSong(songId, data, getTime())
d.addErrback(err)
d.addCallback(database.upsertMediaSong, mType, mId, nameLower, isReg,
getTime(), method)
d.addErrback(err)
return defer.succeed(results)
def getVdbByPvId(mType, mId):
"""Return a deferred of the json response of vocadb song result"""
if mType == 'yt':
service = 'Youtube'
else:
service = 'NicoNicoDouga'
args = {'pvId': mId,
'pvService': service,
'fields': 'Artists,Names',
'lang': 'romaji',
}
url = 'https://vocadb.net/api/songs/byPv?{}'.format(urllib.urlencode(args))
clog.info('requesting vocadb API by pv search: {}'.format(url), syst)
d = treq.get(url, headers=HEADERS)
d.addCallback(cbResponse)
return d
def getVdbBySongId(songId):
"""Return a deferred of the json response of vocadb song result"""
args = {
'fields': 'Artists,Names',
'lang': 'romaji',
}
url = 'https://vocadb.net/api/songs/{}?{}'.format(songId,
urllib.urlencode(args))
clog.info('requesting vocadb API by song id : {}'.format(url), syst)
d = treq.get(url, headers=HEADERS)
d.addCallback(cbResponse)
return d
def cbResponse(response):
if response.code == 200:
return treq.json_content(response)
else:
clog.error(response.code, syst)
return treq.json_content(response)
def err(err):
print dir(err)
err.printDetailedTraceback()
print err.getTraceback()
if __name__ == '__main__':
from twisted.internet import reactor
#d= lookupSongInDb('yt', 'TAYZgVEk_hA')
#d.addCallback(pprint)
a = obtainSong('yt', 'TAYZgVEk_hA', 'yukari', True)
a.addErrback(err)
a.addCallback(pprint)
a.addErrback(err)
a.addCallback(lambda x: reactor.stop)
a.addErrback(err)
reactor.run()