PageRenderTime 29ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/net/sourceforge/filebot/web/SublightSubtitleClient.java

https://github.com/gpeev/relman
Java | 375 lines | 223 code | 107 blank | 45 comment | 31 complexity | e6aec5fd35843be65e6d54fb651a93cd MD5 | raw file
  1. package net.sourceforge.filebot.web;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.net.URI;
  5. import java.util.ArrayList;
  6. import java.util.Collections;
  7. import java.util.HashMap;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.Map.Entry;
  11. import java.util.concurrent.TimeUnit;
  12. import javax.swing.Icon;
  13. import javax.xml.ws.Holder;
  14. import javax.xml.ws.WebServiceException;
  15. import net.sourceforge.filebot.ResourceManager;
  16. import net.sourceforge.tuned.Timer;
  17. import net.sublight.webservice.ArrayOfGenre;
  18. import net.sublight.webservice.ArrayOfIMDB;
  19. import net.sublight.webservice.ArrayOfRelease;
  20. import net.sublight.webservice.ArrayOfString;
  21. import net.sublight.webservice.ArrayOfSubtitle;
  22. import net.sublight.webservice.ArrayOfSubtitleLanguage;
  23. import net.sublight.webservice.ClientInfo;
  24. import net.sublight.webservice.Genre;
  25. import net.sublight.webservice.IMDB;
  26. import net.sublight.webservice.Release;
  27. import net.sublight.webservice.Sublight;
  28. import net.sublight.webservice.SublightSoap;
  29. import net.sublight.webservice.Subtitle;
  30. import net.sublight.webservice.SubtitleLanguage;
  31. public class SublightSubtitleClient implements SubtitleProvider, VideoHashSubtitleService {
  32. private static final String iid = "42cc1701-3752-49e2-a148-332960073452";
  33. private final ClientInfo clientInfo = new ClientInfo();
  34. private SublightSoap webservice;
  35. private String session;
  36. public SublightSubtitleClient(String clientIdentity, String apikey) {
  37. clientInfo.setClientId(clientIdentity);
  38. clientInfo.setApiKey(apikey);
  39. }
  40. @Override
  41. public String getName() {
  42. return "Sublight";
  43. }
  44. @Override
  45. public URI getLink() {
  46. return URI.create("http://www.sublight.si");
  47. }
  48. @Override
  49. public Icon getIcon() {
  50. return ResourceManager.getIcon("search.sublight");
  51. }
  52. @Override
  53. public List<SearchResult> search(String query) throws WebServiceException {
  54. // require login
  55. login();
  56. Holder<ArrayOfIMDB> response = new Holder<ArrayOfIMDB>();
  57. Holder<String> error = new Holder<String>();
  58. webservice.findIMDB(query, null, null, response, error);
  59. // abort if something went wrong
  60. checkError(error);
  61. List<SearchResult> results = new ArrayList<SearchResult>();
  62. if (response.value != null) {
  63. for (IMDB imdb : response.value.getIMDB()) {
  64. // remove classifier (e.g. tt0436992 -> 0436992)
  65. int id = Integer.parseInt(imdb.getId().substring(2));
  66. results.add(new MovieDescriptor(imdb.getTitle(), imdb.getYear(), id));
  67. }
  68. }
  69. return results;
  70. }
  71. @Override
  72. public List<SubtitleDescriptor> getSubtitleList(SearchResult searchResult, String languageName) throws WebServiceException {
  73. MovieDescriptor movie = (MovieDescriptor) searchResult;
  74. List<SubtitleDescriptor> subtitles = new ArrayList<SubtitleDescriptor>();
  75. // retrieve subtitles by name and year
  76. for (Subtitle subtitle : getSubtitleList(null, movie.getName(), movie.getYear(), languageName)) {
  77. subtitles.add(new SublightSubtitleDescriptor(subtitle, this));
  78. }
  79. return subtitles;
  80. }
  81. public Map<File, List<SubtitleDescriptor>> getSubtitleList(File[] files, final String languageName) throws Exception {
  82. Map<File, List<SubtitleDescriptor>> subtitles = new HashMap<File, List<SubtitleDescriptor>>(files.length);
  83. for (final File file : files) {
  84. subtitles.put(file, getSubtitleList(file, languageName));
  85. }
  86. return subtitles;
  87. }
  88. public List<SubtitleDescriptor> getSubtitleList(File videoFile, String languageName) throws WebServiceException, IOException {
  89. List<SubtitleDescriptor> subtitles = new ArrayList<SubtitleDescriptor>();
  90. try {
  91. // retrieve subtitles by video hash
  92. for (Subtitle subtitle : getSubtitleList(SublightVideoHasher.computeHash(videoFile), null, null, languageName)) {
  93. // only keep linked subtitles
  94. if (subtitle.isIsLinked()) {
  95. subtitles.add(new SublightSubtitleDescriptor(subtitle, this));
  96. }
  97. }
  98. } catch (LinkageError e) {
  99. // MediaInfo native lib not available
  100. throw new UnsupportedOperationException(e.getMessage(), e);
  101. }
  102. return subtitles;
  103. }
  104. protected List<Subtitle> getSubtitleList(String videoHash, String name, Integer year, String languageName) throws WebServiceException {
  105. // require login
  106. login();
  107. // given language or all languages
  108. ArrayOfSubtitleLanguage languages = new ArrayOfSubtitleLanguage();
  109. if (languageName != null) {
  110. // given language
  111. languages.getSubtitleLanguage().add(getSubtitleLanguage(languageName));
  112. } else {
  113. // all languages
  114. Collections.addAll(languages.getSubtitleLanguage(), SubtitleLanguage.values());
  115. }
  116. // hash singleton array
  117. ArrayOfString videoHashes = new ArrayOfString();
  118. videoHashes.getString().add(videoHash);
  119. // all genres
  120. ArrayOfGenre genres = new ArrayOfGenre();
  121. Collections.addAll(genres.getGenre(), Genre.values());
  122. // response holders
  123. Holder<ArrayOfSubtitle> subtitles = new Holder<ArrayOfSubtitle>();
  124. Holder<ArrayOfRelease> releases = new Holder<ArrayOfRelease>();
  125. Holder<String> error = new Holder<String>();
  126. webservice.searchSubtitles4(session, videoHashes, name, year, null, null, languages, genres, null, null, null, subtitles, releases, null, error);
  127. // abort if something went wrong
  128. checkError(error);
  129. // return empty list if response is empty
  130. if (subtitles.value == null) {
  131. return Collections.emptyList();
  132. }
  133. // map all release names by subtitle id
  134. if (releases.value != null) {
  135. Map<String, String> releaseNameBySubtitleID = new HashMap<String, String>();
  136. // map release names by subtitle id
  137. for (Release release : releases.value.getRelease()) {
  138. releaseNameBySubtitleID.put(release.getSubtitleID(), release.getName());
  139. }
  140. // set release names
  141. for (Subtitle subtitle : subtitles.value.getSubtitle()) {
  142. subtitle.setRelease(releaseNameBySubtitleID.get(subtitle.getSubtitleID()));
  143. }
  144. }
  145. return subtitles.value.getSubtitle();
  146. }
  147. @Override
  148. public boolean publishSubtitle(int imdbid, String languageName, File videoFile, File subtitleFile) throws Exception {
  149. //TODO implement upload feature
  150. return false;
  151. }
  152. public void publishSubtitle(int imdbid, String videoHash, String languageName, String releaseName, byte[] data) {
  153. // require login
  154. login();
  155. Subtitle subtitle = new Subtitle();
  156. subtitle.setIMDB(String.format("http://www.imdb.com/title/tt%07d", imdbid));
  157. subtitle.setLanguage(getSubtitleLanguage(languageName));
  158. subtitle.setRelease(releaseName);
  159. Holder<Boolean> result = new Holder<Boolean>();
  160. Holder<String> subid = new Holder<String>();
  161. Holder<String> error = new Holder<String>();
  162. // upload subtitle
  163. webservice.publishSubtitle2(session, subtitle, data, result, subid, null, error);
  164. // abort if something went wrong
  165. checkError(error);
  166. // link subtitle to video file
  167. webservice.addHashLink3(session, subid.value, videoHash, null, null, error);
  168. // abort if something went wrong
  169. checkError(error);
  170. }
  171. protected Map<String, SubtitleLanguage> getLanguageAliasMap() {
  172. Map<String, SubtitleLanguage> languages = new HashMap<String, SubtitleLanguage>(4);
  173. // insert special some additional special handling
  174. languages.put("Brazilian", SubtitleLanguage.PORTUGUESE_BRAZIL);
  175. languages.put("Bosnian", SubtitleLanguage.BOSNIAN_LATIN);
  176. languages.put("Serbian", SubtitleLanguage.SERBIAN_LATIN);
  177. return languages;
  178. }
  179. protected SubtitleLanguage getSubtitleLanguage(String languageName) {
  180. // check subtitle language enum
  181. for (SubtitleLanguage language : SubtitleLanguage.values()) {
  182. if (language.value().equalsIgnoreCase(languageName))
  183. return language;
  184. }
  185. // check alias list
  186. for (Entry<String, SubtitleLanguage> alias : getLanguageAliasMap().entrySet()) {
  187. if (alias.getKey().equalsIgnoreCase(languageName))
  188. return alias.getValue();
  189. }
  190. // illegal language name
  191. throw new IllegalArgumentException("Illegal language: " + languageName);
  192. }
  193. protected String getLanguageName(SubtitleLanguage language) {
  194. // check alias list first
  195. for (Entry<String, SubtitleLanguage> alias : getLanguageAliasMap().entrySet()) {
  196. if (language == alias.getValue())
  197. return alias.getKey();
  198. }
  199. // use language value by default
  200. return language.value();
  201. }
  202. protected byte[] getZipArchive(Subtitle subtitle) throws WebServiceException, InterruptedException {
  203. // require login
  204. login();
  205. Holder<String> ticket = new Holder<String>();
  206. Holder<Short> que = new Holder<Short>();
  207. Holder<byte[]> data = new Holder<byte[]>();
  208. Holder<String> error = new Holder<String>();
  209. webservice.getDownloadTicket2(session, null, subtitle.getSubtitleID(), null, ticket, que, null, error);
  210. // abort if something went wrong
  211. checkError(error);
  212. // wait x seconds as specified by the download ticket response, download ticket is not valid until then
  213. Thread.sleep(que.value * 1000);
  214. webservice.downloadByID4(session, subtitle.getSubtitleID(), -1, false, ticket.value, null, data, null, error);
  215. // abort if something went wrong
  216. checkError(error);
  217. // return zip file bytes
  218. return data.value;
  219. }
  220. @Override
  221. public URI getSubtitleListLink(SearchResult searchResult, String languageName) {
  222. // note that sublight can only be accessed via the soap API
  223. return URI.create("http://www.sublight.si/SearchSubtitles.aspx");
  224. }
  225. protected synchronized void login() throws WebServiceException {
  226. if (webservice == null) {
  227. // lazy initialize because all the JAX-WS class loading can take quite some time
  228. webservice = new Sublight().getSublightSoap();
  229. }
  230. if (session == null) {
  231. // args contains only iid
  232. ArrayOfString args = new ArrayOfString();
  233. args.getString().add(iid);
  234. Holder<String> session = new Holder<String>();
  235. Holder<String> error = new Holder<String>();
  236. webservice.logInAnonymous4(clientInfo, args, session, null, error);
  237. // abort if something went wrong
  238. checkError(error);
  239. // start session
  240. this.session = session.value;
  241. }
  242. // reset timer
  243. logoutTimer.set(10, TimeUnit.MINUTES, true);
  244. }
  245. protected synchronized void logout() throws WebServiceException {
  246. if (session != null) {
  247. Holder<String> error = new Holder<String>();
  248. webservice.logOut(session, null, error);
  249. // abort if something went wrong
  250. checkError(error);
  251. // stop session
  252. this.session = null;
  253. // cancel timer
  254. logoutTimer.cancel();
  255. }
  256. }
  257. protected void checkError(Holder<?> error) throws WebServiceException {
  258. if (error.value != null) {
  259. throw new WebServiceException("Response indicates error: " + error.value);
  260. }
  261. }
  262. protected final Timer logoutTimer = new Timer() {
  263. @Override
  264. public void run() {
  265. logout();
  266. }
  267. };
  268. }