index.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import browser from 'webextension-polyfill';
  2. import { MessageListener } from '@/utils/message';
  3. import workflowState from './workflow-state';
  4. import WorkflowEngine from './workflow-engine';
  5. import CollectionEngine from './collection-engine';
  6. function getWorkflow(workflowId) {
  7. return new Promise((resolve) => {
  8. browser.storage.local.get('workflows').then(({ workflows }) => {
  9. const workflow = workflows.find(({ id }) => id === workflowId);
  10. resolve(workflow);
  11. });
  12. });
  13. }
  14. const runningWorkflows = {};
  15. const runningCollections = {};
  16. async function executeWorkflow(workflow, tabId) {
  17. try {
  18. const engine = new WorkflowEngine(workflow, { tabId });
  19. runningWorkflows[engine.id] = engine;
  20. engine.init();
  21. engine.on('destroyed', ({ id }) => {
  22. delete runningWorkflows[id];
  23. });
  24. return true;
  25. } catch (error) {
  26. console.error(error);
  27. return error;
  28. }
  29. }
  30. function executeCollection(collection) {
  31. const engine = new CollectionEngine(collection);
  32. runningCollections[engine.id] = engine;
  33. engine.init();
  34. engine.on('destroyed', (id) => {
  35. delete runningWorkflows[id];
  36. });
  37. return true;
  38. }
  39. browser.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
  40. if (changeInfo.status === 'complete') {
  41. const { visitWebTriggers } = await browser.storage.local.get(
  42. 'visitWebTriggers'
  43. );
  44. const trigger = visitWebTriggers.find(({ url, isRegex }) => {
  45. if (url.trim() === '') return false;
  46. return tab.url.match(isRegex ? new RegExp(url, 'g') : url);
  47. });
  48. const state = await workflowState.get((item) => item.state.tabId === tabId);
  49. if (trigger && state.length === 0) {
  50. const workflow = await getWorkflow(trigger.id);
  51. if (workflow) executeWorkflow(workflow, tabId);
  52. }
  53. }
  54. });
  55. browser.alarms.onAlarm.addListener(({ name }) => {
  56. getWorkflow(name).then((workflow) => {
  57. if (!workflow) return;
  58. executeWorkflow(workflow);
  59. });
  60. });
  61. chrome.runtime.onInstalled.addListener((details) => {
  62. if (details.reason === 'install') {
  63. browser.storage.local
  64. .set({
  65. logs: [],
  66. shortcuts: {},
  67. workflows: [],
  68. collections: [],
  69. workflowState: [],
  70. isFirstTime: true,
  71. visitWebTriggers: [],
  72. })
  73. .then(() => {
  74. browser.tabs
  75. .create({
  76. active: true,
  77. url: browser.runtime.getURL('newtab.html#/workflows'),
  78. })
  79. .catch((error) => {
  80. console.error(error);
  81. });
  82. });
  83. }
  84. });
  85. const message = new MessageListener('background');
  86. message.on('get:sender', (_, sender) => {
  87. return sender;
  88. });
  89. message.on('collection:execute', executeCollection);
  90. message.on('collection:stop', (id) => {
  91. const collection = runningCollections[id];
  92. if (!collection) {
  93. workflowState.delete(id);
  94. return;
  95. }
  96. collection.stop();
  97. });
  98. message.on('workflow:execute', (workflow) => executeWorkflow(workflow));
  99. message.on('workflow:stop', (id) => {
  100. const workflow = runningWorkflows[id];
  101. if (!workflow) {
  102. workflowState.delete(id);
  103. return;
  104. }
  105. workflow.stop();
  106. });
  107. browser.runtime.onMessage.addListener(message.listener());