presence.ts 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. import { Assets } from 'premid'
  2. const presence = new Presence({
  3. clientId: '684124119146692619',
  4. })
  5. // Timestamp
  6. function getTimeStamp() {
  7. return Math.floor(Date.now() / 1000)
  8. }
  9. // Variables
  10. let Routes: string[],
  11. Queries
  12. presence.on('UpdateData', async () => {
  13. // Presence Data
  14. const presenceData: PresenceData = {
  15. largeImageKey: 'https://cdn.rcd.gg/PreMiD/websites/M/Mangalib/assets/logo.png',
  16. }
  17. // Setup Routes & Query
  18. Routes = document.location.href
  19. .replace(document.location.search, '')
  20. .split('/')
  21. .splice(3)
  22. Queries = Object.fromEntries(
  23. document.location.search
  24. .slice(1)
  25. .split('&')
  26. .map((k, _, a) => {
  27. const item: string[] = k.replace(/\[(.*?)\]+/g, '').split('=')
  28. const Keys = a
  29. .map(i => i.replace(/\[(.*?)\]+/g, '').split('='))
  30. .filter(i => i[0] === item[0])
  31. if (Keys.length === 1)
  32. return item
  33. else return [item[0], Keys.map(i => i[1])]
  34. }),
  35. )
  36. // Website Pages
  37. switch (Routes[0]) {
  38. case '': {
  39. // Homepage
  40. presenceData.smallImageText = 'reading'
  41. presenceData.smallImageKey = Assets.Search
  42. presenceData.details = 'Главная'
  43. presenceData.startTimestamp = 0
  44. // Page Section
  45. if (Queries.section === 'my-updates')
  46. presenceData.state = 'Мои обновления'
  47. else presenceData.state = 'Все обновления'
  48. break
  49. }
  50. case 'manga-list': {
  51. // List of mangas
  52. presenceData.smallImageText = 'reading'
  53. presenceData.smallImageKey = Assets.Search
  54. presenceData.details = 'Каталог манги'
  55. if (!Array.isArray(Queries.types))
  56. Queries.types = [Queries.types]
  57. // Search Types
  58. if (Queries.types && Queries.types.length === 1) {
  59. // Types size === 1
  60. switch (Queries.types[0]) {
  61. case '4':
  62. presenceData.state = 'Ищет OEL-мангу'
  63. break
  64. case '5':
  65. presenceData.state = 'Ищет Манхву'
  66. break
  67. case '6':
  68. presenceData.state = 'Ищет Маньхуа'
  69. break
  70. case '8':
  71. presenceData.state = 'Ищет Румангу'
  72. break
  73. case '9':
  74. presenceData.state = 'Ищет Западный комикс'
  75. break
  76. default:
  77. presenceData.state = 'Ищет Мангу'
  78. break
  79. }
  80. }
  81. else if (Queries.types && Queries.types.length > 1) {
  82. // Types size > 1
  83. const mangas: string[] = []
  84. for (const item in Queries.types.sort()) {
  85. switch (item) {
  86. case '4':
  87. mangas.push('OEL-мангу')
  88. break
  89. case '5':
  90. mangas.push('Манхву')
  91. break
  92. case '6':
  93. mangas.push('Маньхуа')
  94. break
  95. case '8':
  96. mangas.push('Румангу')
  97. break
  98. case '9':
  99. mangas.push('Западный комикс')
  100. break
  101. default:
  102. mangas.push('Мангу')
  103. break
  104. }
  105. }
  106. presenceData.state = `Ищет: ${mangas.join(', ')}`
  107. }
  108. else {
  109. presenceData.state = 'Ищет Мангу'
  110. }
  111. break
  112. }
  113. case 'forum': {
  114. // Forum page
  115. presenceData.details = 'Форум'
  116. // Subpages of forums
  117. switch (Routes[1]) {
  118. case '': {
  119. // Main forum page
  120. presenceData.smallImageText = 'Читает'
  121. presenceData.smallImageKey = Assets.Reading
  122. if (Queries.subscription)
  123. presenceData.state = 'Мои подписки'
  124. if (Queries.user_id)
  125. presenceData.state = 'Мои темы'
  126. switch (Queries.category) {
  127. case 'all':
  128. presenceData.state = 'Все категории'
  129. break
  130. case '1':
  131. presenceData.state = 'Баги и проблемы'
  132. break
  133. case '2':
  134. presenceData.state = 'Предложения для сайта'
  135. break
  136. case '3':
  137. presenceData.state = 'Поиск тайтлов'
  138. break
  139. case '4':
  140. presenceData.state = 'Поиск кадров'
  141. break
  142. case '5':
  143. presenceData.state = 'Обсуждение Манги'
  144. break
  145. case '6':
  146. presenceData.state = 'Обсуждение Аниме'
  147. break
  148. case '7':
  149. presenceData.state = 'Обсуждение Ранобэ'
  150. break
  151. case '8':
  152. presenceData.state = 'Видеоигры'
  153. break
  154. case '9':
  155. presenceData.state = 'Переводчикам'
  156. break
  157. case '10':
  158. presenceData.state = 'Как переводить мангу'
  159. break
  160. case '11':
  161. presenceData.state = 'Как рисовать мангу'
  162. break
  163. case '12':
  164. presenceData.state = 'Общение'
  165. break
  166. case '13':
  167. presenceData.state = 'Другое'
  168. break
  169. }
  170. break
  171. }
  172. case 'discussion-create': {
  173. // Discussion create
  174. presenceData.smallImageText = 'Пишет'
  175. presenceData.smallImageKey = Assets.Writing
  176. presenceData.state = 'Создает новую тему'
  177. break
  178. }
  179. case 'discussion': {
  180. const titleElement = document.querySelector(
  181. '.discussion .discussion__title',
  182. )
  183. const DiscussionTitle = titleElement?.textContent
  184. // Discussion page
  185. if (Routes[2] && !Routes[3]) {
  186. // Opened discussion
  187. presenceData.smallImageText = 'Читает'
  188. presenceData.smallImageKey = Assets.Reading
  189. const authorElement = document.querySelector(
  190. '.discussion .discussion-creator__username',
  191. )
  192. const DiscussionAuthor = authorElement?.textContent
  193. if (DiscussionAuthor && DiscussionTitle)
  194. presenceData.state = `Тема: ${DiscussionTitle}| Автор: ${DiscussionAuthor}`
  195. }
  196. else if (Routes[3] && Routes[3] === 'edit') {
  197. // Editor discussion
  198. presenceData.smallImageText = 'Пишет'
  199. presenceData.smallImageKey = Assets.Writing
  200. presenceData.state = DiscussionTitle
  201. ? `Редактирует тему: ${DiscussionTitle}`
  202. : 'Редактирует тему'
  203. }
  204. break
  205. }
  206. }
  207. break
  208. }
  209. case 'faq': {
  210. // Faq page
  211. if (Routes[1] === 'article') {
  212. // Faq Editor
  213. presenceData.details = 'Faq'
  214. presenceData.smallImageText = 'Редактирует'
  215. presenceData.smallImageKey = Assets.Writing
  216. presenceData.state = `Редактирует: ${Queries.article} вопрос`
  217. }
  218. else {
  219. // Faq Sections
  220. presenceData.details = 'Faq'
  221. presenceData.smallImageText = 'Читает'
  222. presenceData.smallImageKey = Assets.Reading
  223. switch (Queries.section) {
  224. case '1':
  225. presenceData.state = 'Манга'
  226. break
  227. case '2':
  228. presenceData.state = 'Общие вопросы'
  229. break
  230. case '3':
  231. presenceData.state = 'Профиль пользователя'
  232. break
  233. case '4':
  234. presenceData.state = 'Чтение манги'
  235. break
  236. case '5':
  237. presenceData.state = 'Комментарии'
  238. break
  239. case '6':
  240. presenceData.state = 'Мини-чат'
  241. break
  242. case '7':
  243. presenceData.state = 'Решение проблем'
  244. break
  245. case '8':
  246. presenceData.state = 'Правила'
  247. break
  248. case '9':
  249. presenceData.state = 'Форум'
  250. break
  251. }
  252. }
  253. break
  254. }
  255. case 'news': {
  256. // News page
  257. presenceData.details = 'Новости'
  258. presenceData.smallImageText = 'Читает'
  259. presenceData.smallImageKey = Assets.Reading
  260. if (Routes[1]) {
  261. // Opened News
  262. const titleElement = document.querySelector('.news__title')
  263. const NewsTitle = titleElement?.textContent
  264. if (NewsTitle)
  265. presenceData.state = NewsTitle
  266. }
  267. else {
  268. // News List
  269. presenceData.details = 'Новости'
  270. presenceData.smallImageText = 'Читает'
  271. presenceData.smallImageKey = Assets.Reading
  272. presenceData.state = 'Список новостей'
  273. }
  274. break
  275. }
  276. case 'notification': {
  277. // Notification list
  278. presenceData.details = 'Уведомления'
  279. presenceData.smallImageText = 'Читает'
  280. presenceData.smallImageKey = Assets.Reading
  281. switch (Queries.type) {
  282. case 'chapter':
  283. presenceData.state = 'Главы'
  284. break
  285. case 'comments':
  286. presenceData.state = 'Комментарии'
  287. break
  288. case 'message':
  289. presenceData.state = 'Сообщения'
  290. break
  291. case 'friend':
  292. presenceData.state = 'Заявки в друзья'
  293. break
  294. case 'other':
  295. presenceData.state = 'Другое'
  296. break
  297. case 'all':
  298. presenceData.state = 'Все'
  299. break
  300. }
  301. break
  302. }
  303. case 'contact-us': {
  304. // Contact page
  305. presenceData.details = 'Контакты'
  306. presenceData.smallImageText = 'Пишет'
  307. presenceData.smallImageKey = Assets.Writing
  308. presenceData.state = 'info@mangalib.me'
  309. break
  310. }
  311. case 'messages': {
  312. // Messages page
  313. presenceData.details = 'Личные сообщения'
  314. presenceData.smallImageText = 'Пишет'
  315. presenceData.smallImageKey = Assets.Writing
  316. presenceData.startTimestamp = getTimeStamp()
  317. break
  318. }
  319. case 'people': {
  320. // Authors (Moderation) page
  321. if (Routes[1] === 'create') {
  322. presenceData.details = 'Добавляет автора'
  323. presenceData.smallImageText = 'Добавляет автора'
  324. presenceData.smallImageKey = Assets.Writing
  325. const PeopleName = document.querySelector('#name')?.textContent
  326. if (PeopleName && PeopleName.length > 1)
  327. presenceData.state = PeopleName
  328. else presenceData.state = 'Имя автора не задано'
  329. }
  330. break
  331. }
  332. case 'team': {
  333. // Team page
  334. if (Routes[1] === 'create') {
  335. // Create New Team
  336. presenceData.details = 'Добавляет команду'
  337. presenceData.smallImageText = 'Добавляет команду'
  338. presenceData.smallImageKey = Assets.Writing
  339. const TeamName = document.querySelector('#name')?.textContent
  340. if (TeamName && TeamName.length > 1)
  341. presenceData.state = TeamName
  342. else presenceData.state = 'Имя команды не задано'
  343. }
  344. else if (!Routes[2]) {
  345. presenceData.details = 'Команда перевода'
  346. presenceData.smallImageText = 'Смотрит переводчика'
  347. presenceData.smallImageKey = Assets.Reading
  348. const title = document.querySelector('.team-profile__name')
  349. const TeamName = title?.textContent?.replace('редактировать', '')
  350. if (TeamName)
  351. presenceData.state = TeamName
  352. }
  353. else if (Routes[2] === 'edit') {
  354. presenceData.details = 'Команда перевода'
  355. presenceData.smallImageText = 'Редактирует переводчика'
  356. presenceData.smallImageKey = Assets.Writing
  357. switch (Queries.section) {
  358. case 'info':
  359. presenceData.state = 'Редактирует информацию команды'
  360. break
  361. case 'users':
  362. presenceData.state = 'Редактирует участников команды'
  363. break
  364. }
  365. }
  366. break
  367. }
  368. case 'moderation': {
  369. // Moderation page
  370. presenceData.details = 'Модерация'
  371. presenceData.smallImageText = 'Управляет сайтом'
  372. presenceData.smallImageKey = Assets.Reading
  373. if (!Routes[1]) {
  374. presenceData.state = 'Модерация глав'
  375. }
  376. else {
  377. switch (Routes[1]) {
  378. case 'manga': {
  379. if (Routes[2] === 'rejected')
  380. presenceData.state = 'Отклоненные манги'
  381. else presenceData.state = 'Модерация манги'
  382. break
  383. }
  384. case 'manga-edit': {
  385. presenceData.state = 'Изменения манги'
  386. break
  387. }
  388. case 'author': {
  389. presenceData.state = 'Новые Авторы'
  390. break
  391. }
  392. case 'publisher': {
  393. presenceData.state = 'Новые Издательства'
  394. break
  395. }
  396. case 'comments': {
  397. presenceData.state = 'Жалобы на комментарии'
  398. break
  399. }
  400. case 'forum-posts': {
  401. presenceData.state = 'Жалобы на форуме'
  402. break
  403. }
  404. case 'comments-list': {
  405. if (Routes[2] === 'all')
  406. presenceData.state = 'Список комментариев'
  407. else if (Routes[2] === 'sticky')
  408. presenceData.state = 'Закрепленные комментарии'
  409. break
  410. }
  411. case 'ban-list': {
  412. presenceData.state = 'Баны'
  413. break
  414. }
  415. case 'other': {
  416. presenceData.state = 'Другое'
  417. break
  418. }
  419. }
  420. }
  421. break
  422. }
  423. case 'user': {
  424. // User page
  425. presenceData.smallImageText = 'Смотрит профиль пользователя'
  426. presenceData.smallImageKey = Assets.Reading
  427. const username = document.querySelector('.profile-user__username span')
  428. const UserName = username?.textContent
  429. if (UserName)
  430. presenceData.details = `Профиль:${UserName}`
  431. if (Routes[1] === 'content') {
  432. presenceData.details = 'Мои добавления'
  433. presenceData.smallImageText = 'Пишет'
  434. presenceData.smallImageKey = Assets.Writing
  435. presenceData.startTimestamp = 0
  436. if (!Routes[2]) {
  437. presenceData.state = 'Добавленные тайтлы'
  438. }
  439. else {
  440. switch (Routes[2]) {
  441. case 'moderation': {
  442. presenceData.state = 'Тайтлы на модерации'
  443. break
  444. }
  445. case 'rejected': {
  446. presenceData.state = 'Тайтлы не прошедшие модерацию'
  447. break
  448. }
  449. case 'chapters': {
  450. presenceData.state = 'Главы на модерации'
  451. break
  452. }
  453. }
  454. }
  455. }
  456. else if (Routes[1] === 'edit') {
  457. presenceData.details = 'Мои настройки'
  458. presenceData.smallImageText = 'Настраивает'
  459. presenceData.smallImageKey = Assets.Writing
  460. presenceData.startTimestamp = 0
  461. switch (Queries.section) {
  462. case 'info':
  463. presenceData.state = 'Информация'
  464. break
  465. case 'site-settings':
  466. presenceData.state = 'Настройки сайта'
  467. break
  468. case 'notifications':
  469. presenceData.state = 'Уведомления'
  470. break
  471. case 'password':
  472. presenceData.state = 'Безопасность'
  473. break
  474. }
  475. }
  476. else if (!Routes[2]) {
  477. // Main user page
  478. const size = document.querySelector(
  479. '.bookmark-menu .menu__item.is-active .bookmark-menu__label',
  480. )
  481. const title = document.querySelector(
  482. '.bookmark-menu .menu__item.is-active .bookmark-menu__name',
  483. )
  484. const BookmarkSize = size?.textContent
  485. const BookmarkType = `${title?.textContent?.charAt(0).toUpperCase()}${title?.textContent?.slice(1)}`
  486. presenceData.details = `Закладки ${UserName}`
  487. presenceData.state = `${BookmarkType.trim()}: ${BookmarkSize}`
  488. presenceData.smallImageText = 'Читает'
  489. presenceData.smallImageKey = Assets.Reading
  490. presenceData.startTimestamp = 0
  491. }
  492. else {
  493. switch (Routes[2]) {
  494. case 'comment': {
  495. presenceData.details = `Профиль: ${UserName}`
  496. let commentType
  497. switch (Queries.commentType) {
  498. case 'manga': {
  499. commentType = 'Комментарии к манге'
  500. break
  501. }
  502. case 'chapter': {
  503. commentType = 'Комментарии к главам'
  504. break
  505. }
  506. case 'post': {
  507. commentType = 'Комментарии к новостям'
  508. break
  509. }
  510. default:
  511. commentType = 'Все комментарии'
  512. }
  513. presenceData.state = commentType
  514. break
  515. }
  516. case 'following': {
  517. presenceData.details = `Профиль: ${UserName}`
  518. presenceData.state = 'Список друзей'
  519. break
  520. }
  521. case 'mutual-friends': {
  522. presenceData.details = `Профиль: ${UserName}`
  523. presenceData.state = 'Общие друзья'
  524. break
  525. }
  526. case 'ignore': {
  527. presenceData.details = `Профиль: ${UserName}`
  528. presenceData.state = 'Игнор-лист'
  529. break
  530. }
  531. case 'ban': {
  532. presenceData.details = 'Мой профиль'
  533. presenceData.state = 'История банов'
  534. break
  535. }
  536. }
  537. }
  538. break
  539. }
  540. case 'manga': {
  541. // Manga page
  542. if (Routes[1] === 'create') {
  543. // create new manga
  544. presenceData.details = 'Добавляет мангу'
  545. presenceData.smallImageText = 'Пишет'
  546. presenceData.smallImageKey = Assets.Writing
  547. const title = <HTMLInputElement>document.querySelector('#rus_name')
  548. if (title.value.length > 1)
  549. presenceData.state = title.value
  550. else presenceData.state = 'Имя тайтла не задано'
  551. }
  552. else {
  553. switch (Routes[2]) {
  554. case 'edit': {
  555. // edit
  556. presenceData.smallImageText = 'Редактирует'
  557. presenceData.smallImageKey = Assets.Writing
  558. presenceData.details = document.querySelector(
  559. '.section__header .breadcrumb a',
  560. )?.textContent
  561. switch (Queries.section) {
  562. case 'media-edit':
  563. presenceData.state = 'Редактирование'
  564. break
  565. case 'changes':
  566. presenceData.state = 'Список изменений'
  567. break
  568. case 'related-items':
  569. presenceData.state = 'Связанные тайтлы'
  570. break
  571. }
  572. break
  573. }
  574. case 'bulk-create': {
  575. // bulk create
  576. presenceData.details = 'Добавляет главы'
  577. presenceData.smallImageText = 'Добавляет'
  578. presenceData.smallImageKey = Assets.Uploading
  579. presenceData.state = `Манга: ${
  580. document.querySelector('.section__header .breadcrumb a')
  581. ?.textContent
  582. }`
  583. break
  584. }
  585. case 'add-chapter': {
  586. // add chapter
  587. presenceData.details = 'Добавляет главу'
  588. presenceData.smallImageText = 'Добавляет'
  589. presenceData.smallImageKey = Assets.Uploading
  590. presenceData.state = `Манга: ${
  591. document.querySelector('.section__header .breadcrumb a')
  592. ?.textContent
  593. }`
  594. break
  595. }
  596. default: {
  597. presenceData.details = 'Редактирует главу'
  598. presenceData.smallImageText = 'Пишет'
  599. presenceData.smallImageKey = Assets.Writing
  600. presenceData.state = `Манга: ${
  601. document.querySelector('.section__header .breadcrumb a')
  602. ?.textContent
  603. }`
  604. }
  605. }
  606. }
  607. break
  608. }
  609. default:
  610. if (document.querySelector('.reader')) {
  611. presenceData.details = 'Читает тайтл'
  612. presenceData.state = document.title.split(' ').slice(2, -4).join(' ')
  613. presenceData.smallImageText = 'Читает'
  614. presenceData.smallImageKey = Assets.Reading
  615. presenceData.startTimestamp = getTimeStamp()
  616. }
  617. else {
  618. presenceData.details = 'Смотрит тайтл'
  619. presenceData.state = document.title
  620. .split('/')[0]
  621. ?.split(' ')
  622. .slice(1)
  623. .join(' ')
  624. presenceData.smallImageText = 'Читает'
  625. presenceData.smallImageKey = Assets.Reading
  626. }
  627. }
  628. presence.setActivity(presenceData, true)
  629. })