popup.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. const IS_FIREFOX = (typeof chrome === "undefined");
  2. const IS_CHROME = (typeof browser === "undefined");
  3. class DomManager {
  4. constructor() {
  5. this.elements = {
  6. lastActivityItemDate: document.getElementById("last-activity-item-date"),
  7. status: document.getElementById("status"),
  8. netflixManagerStatus: document.getElementById("netflixmanager-status"),
  9. mainManagerStatus: document.getElementById("mainmanager-status"),
  10. backend: document.getElementById("backend"),
  11. buildIdentifier: document.getElementById("build-identifier"),
  12. authUrl: document.getElementById("auth-url"),
  13. lastActivityItemTitle: document.getElementById("last-activity-item-title"),
  14. pagesGot: document.getElementById("pages-got"),
  15. itemsGot: document.getElementById("items-got"),
  16. firstItemTitle: document.getElementById("first-item-title"),
  17. firstItemDate: document.getElementById("first-item-date"),
  18. lastItemTitle: document.getElementById("last-item-title"),
  19. lastItemDate: document.getElementById("last-item-date"),
  20. button: document.getElementById("button"),
  21. };
  22. this.buttonClickHandlers = [];
  23. this.elements.button.onclick = () => {
  24. this._handleButtonClick();
  25. };
  26. }
  27. setLastActivityDate(date) {
  28. this.elements.lastActivityItemDate.innerText = date;
  29. }
  30. setLastActivityTitle(title) {
  31. this.elements.lastActivityItemTitle.innerText = title;
  32. }
  33. setStatus(status) {
  34. this.elements.status.innerText = status;
  35. if (status === "Ready") this.elements.button.disabled = false;
  36. else this.elements.button.disabled = true;
  37. }
  38. setNetflixManagerStatus(status) {
  39. this.elements.netflixManagerStatus.innerText = status;
  40. }
  41. setMainManagerStatus(status) {
  42. this.elements.mainManagerStatus.innerText = status;
  43. }
  44. setAuthUrl(authUrl) {
  45. this.elements.authUrl.innerText = authUrl;
  46. }
  47. setBuildIdentifier(buildIdentifier) {
  48. this.elements.buildIdentifier.innerText = buildIdentifier;
  49. }
  50. setBackend(backend) {
  51. this.elements.backend.innerText = backend;
  52. }
  53. setPagesGot(pagesGot) {
  54. this.elements.pagesGot.innerText = pagesGot;
  55. }
  56. setItemsGot(itemsGot) {
  57. this.elements.itemsGot.innerText = itemsGot;
  58. }
  59. setFirstItemTitle(firstItemTitle) {
  60. this.elements.firstItemTitle.innerText = firstItemTitle;
  61. }
  62. setFirstItemDate(firstItemDate) {
  63. this.elements.firstItemDate.innerText = firstItemDate;
  64. }
  65. setLastItemTitle(lastItemTitle) {
  66. this.elements.lastItemTitle.innerText = lastItemTitle;
  67. }
  68. setLastItemDate(lastItemDate) {
  69. this.elements.lastItemDate.innerText = lastItemDate;
  70. }
  71. onButtonClick(cb) {
  72. this.buttonClickHandlers.push(cb);
  73. }
  74. _handleButtonClick() {
  75. this.buttonClickHandlers.forEach(cb => {
  76. cb();
  77. });
  78. }
  79. }
  80. class NetflixManager {
  81. constructor() {
  82. this.page = 0;
  83. domManager.setNetflixManagerStatus("Waiting for authUrl and buildIdentifier");
  84. this.fetchAuthUrl();
  85. this.fetchBuildIdentifier();
  86. this.gotAuthUrlFromBackground = false;
  87. this.gotBuildIdentifierFromBackground = false;
  88. }
  89. async fetchAuthUrl() {
  90. if (IS_FIREFOX) this.authUrl = await browser.runtime.sendMessage({ type: `getAuthUrl` });
  91. if (IS_CHROME) this.authUrl = await new Promise(resolve => {
  92. chrome.runtime.sendMessage({ type: `getAuthUrl` }, response => {
  93. resolve(response);
  94. })
  95. });
  96. domManager.setAuthUrl(this.authUrl);
  97. this.gotAuthUrlFromBackground = true;
  98. if (this.gotBuildIdentifierFromBackground && this.gotAuthUrlFromBackground && !this.buildIdentifier && !this.authUrl)
  99. domManager.setNetflixManagerStatus("Background does not have auth url and build identifier yet. Please reload the Netflix page on the correct profile.");
  100. }
  101. async fetchBuildIdentifier() {
  102. if (IS_FIREFOX) this.buildIdentifier = await browser.runtime.sendMessage({ type: `getBuildIdentifier` });
  103. if (IS_CHROME) this.buildIdentifier = await new Promise(resolve => {
  104. chrome.runtime.sendMessage({ type: `getBuildIdentifier` }, response => {
  105. resolve(response);
  106. });
  107. });
  108. domManager.setBuildIdentifier(this.buildIdentifier);
  109. this.gotBuildIdentifierFromBackground = true;
  110. if (this.gotBuildIdentifierFromBackground && this.gotAuthUrlFromBackground && !this.buildIdentifier && !this.authUrl)
  111. domManager.setNetflixManagerStatus("Background does not have auth url and build identifier yet. Please reload the Netflix page on the correct profile.");
  112. }
  113. isReady() {
  114. return new Promise(resolve => {
  115. let intervalId = setInterval(() => {
  116. if (this.authUrl && this.buildIdentifier) {
  117. clearInterval(intervalId);
  118. domManager.setNetflixManagerStatus("Ready");
  119. resolve();
  120. } else console.log("Auth URL or build identifier not set yet in NetflixManager");
  121. }, 250);
  122. });
  123. }
  124. getURL() {
  125. return `https://www.netflix.com/api/shakti/${this.buildIdentifier}/viewingactivity?language=en-US&authURL=${this.authUrl}&pg=${this.page}`;
  126. }
  127. getPage() {
  128. console.log(`Getting page ${this.page}`);
  129. domManager.setNetflixManagerStatus(`Getting page ${this.page}`);
  130. return new Promise(resolve => {
  131. setTimeout(() => {
  132. const URL = this.getURL();
  133. fetch(new Request(URL))
  134. .then(response => {
  135. if (response.status === 200) {
  136. return response.json();
  137. } else {
  138. throw new Error("Something went wrong with the API.");
  139. }
  140. })
  141. .then(response => {
  142. resolve(response);
  143. })
  144. .catch(error => {
  145. console.error(error);
  146. });
  147. }, Math.floor(Math.random() * 750) + 250);
  148. });
  149. }
  150. }
  151. class MainManager {
  152. constructor() {
  153. this.items = [];
  154. domManager.setMainManagerStatus("Fetching last activity item");
  155. this.fetchLastActivityItem();
  156. }
  157. async fetchLastActivityItem() {
  158. socket.emit("getLastActivityItem", lastActivityItem => {
  159. this.lastActivityItem = lastActivityItem;
  160. let date = (new Date(this.lastActivityItem.date)).toLocaleString();
  161. let title = this.lastActivityItem.seriesTitle ? `${this.lastActivityItem.seriesTitle} - ${this.lastActivityItem.episodeTitle}` : `${this.lastActivityItem.title}`;
  162. domManager.setLastActivityDate(date);
  163. domManager.setLastActivityTitle(title);
  164. });
  165. }
  166. isReady() {
  167. return new Promise(resolve => {
  168. let intervalId = setInterval(() => {
  169. if (this.lastActivityItem) {
  170. clearInterval(intervalId);
  171. domManager.setMainManagerStatus("Ready");
  172. resolve();
  173. }
  174. }, 250);
  175. });
  176. }
  177. getMore() {
  178. return new Promise(async resolve => {
  179. let activityPage = await netflixManager.getPage();
  180. domManager.setPagesGot(netflixManager.page + 1);
  181. netflixManager.page++;
  182. let resolved = false;
  183. activityPage.viewedItems.forEach(activityItem => {
  184. if (activityItem.date > this.lastActivityItem.date) {
  185. this.items.push(activityItem);
  186. } else {
  187. resolved = true;
  188. }
  189. });
  190. domManager.setItemsGot(this.items.length);
  191. const firstItem = (this.items.length > 0) ? this.items[this.items.length - 1] : null;
  192. const lastItem = (this.items.length > 0) ? this.items[0] : null;
  193. if (firstItem) {
  194. let firstItemDate = (new Date(firstItem.date)).toLocaleString();
  195. let firstItemTitle = firstItem.seriesTitle ? `${firstItem.seriesTitle} - ${firstItem.episodeTitle}` : `${firstItem.title}`;
  196. domManager.setFirstItemDate(firstItemDate);
  197. domManager.setFirstItemTitle(firstItemTitle);
  198. } else {
  199. domManager.setFirstItemDate("No item");
  200. domManager.setFirstItemTitle("No item");
  201. }
  202. if (lastItem) {
  203. let lastItemDate = (new Date(lastItem.date)).toLocaleString();
  204. let lastItemTitle = lastItem.seriesTitle ? `${lastItem.seriesTitle} - ${lastItem.episodeTitle}` : `${lastItem.title}`;
  205. domManager.setLastItemDate(lastItemDate);
  206. domManager.setLastItemTitle(lastItemTitle);
  207. } else {
  208. domManager.setLastItemDate("No item");
  209. domManager.setLastItemTitle("No item");
  210. }
  211. if (activityPage.viewedItems.length === 0) resolved = true;
  212. if (resolved) return resolve();
  213. else this.getMore().then(() => {
  214. resolve();
  215. });
  216. });
  217. }
  218. }
  219. let domManager;
  220. let netflixManager;
  221. let mainManager;
  222. let socket;
  223. let init = async () => {
  224. let backend;
  225. if (IS_FIREFOX) backend = (await browser.storage.local.get("backend")).backend;
  226. if (IS_CHROME) backend = await new Promise((resolve, reject) => {
  227. chrome.storage.local.get("backend", response => {
  228. resolve(response.backend);
  229. });
  230. });
  231. socket = io(backend);
  232. domManager = new DomManager();
  233. domManager.setBackend(backend);
  234. domManager.setStatus("Initializing NetflixManager");
  235. netflixManager = new NetflixManager();
  236. domManager.setStatus("Waiting for NetflixManager");
  237. await netflixManager.isReady();
  238. domManager.setStatus("Initializing MainManager");
  239. mainManager = new MainManager();
  240. domManager.setStatus("Waiting for MainManager");
  241. await mainManager.isReady();
  242. domManager.setStatus("Ready");
  243. domManager.onButtonClick(async () => {
  244. console.log("On button click, gonna get the items");
  245. domManager.setStatus("Starting to get items");
  246. await mainManager.getMore();
  247. domManager.setNetflixManagerStatus(`Ready`);
  248. domManager.setStatus("Sending items to backend");
  249. console.log("Should be done now!");
  250. console.log(mainManager.items);
  251. socket.emit("importNewItems", mainManager.items);
  252. domManager.setStatus("Sent items to backend");
  253. });
  254. }
  255. init();