Support importing sticker packs from Telegram

This commit is contained in:
Travis Ralston 2018-12-22 17:37:31 -07:00
parent e2bbe71d06
commit 32a639ef95
14 changed files with 548 additions and 16 deletions

View File

@ -62,6 +62,12 @@ goneb:
circleci: "mxc://t2bot.io/cf7d875845a82a6b21f5f66de78f6bee"
jira: "mxc://t2bot.io/f4a38ebcc4280ba5b950163ca3e7c329"
# Settings for interacting with Telegram. Currently only applies for importing
# sticker packs from Telegram.
telegram:
# Talk to @BotFather on Telegram to get a token
botToken: "YourTokenHere"
# Settings for controlling how logging works
logging:
file: logs/dimension.log

326
package-lock.json generated
View File

@ -998,6 +998,20 @@
"integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==",
"dev": true
},
"bindings": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz",
"integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew=="
},
"bl": {
"version": "1.2.2",
"resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
"requires": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
}
},
"block-stream": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@ -1245,6 +1259,25 @@
"isarray": "^1.0.0"
}
},
"buffer-alloc": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
"integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
"requires": {
"buffer-alloc-unsafe": "^1.1.0",
"buffer-fill": "^1.0.0"
}
},
"buffer-alloc-unsafe": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
"integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
},
"buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
"integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw="
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
@ -1443,8 +1476,7 @@
"chownr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz",
"integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=",
"dev": true
"integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE="
},
"chrome-trace-event": {
"version": "1.0.0",
@ -2308,6 +2340,14 @@
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
"dev": true
},
"decompress-response": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
"integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
"requires": {
"mimic-response": "^1.0.0"
}
},
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
@ -2705,7 +2745,6 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
"integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
"dev": true,
"requires": {
"once": "^1.4.0"
}
@ -2999,6 +3038,11 @@
}
}
},
"expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="
},
"express": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
@ -3341,6 +3385,16 @@
"readable-stream": "^2.0.0"
}
},
"fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
"fs-copy-file-sync": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz",
"integrity": "sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ=="
},
"fs-extra": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz",
@ -4005,6 +4059,11 @@
}
}
},
"github-from-package": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
},
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
@ -5492,6 +5551,11 @@
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
"dev": true
},
"mimic-response": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
},
"mini-css-extract-plugin": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz",
@ -5733,6 +5797,11 @@
"to-regex": "^3.0.1"
}
},
"napi-build-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.1.tgz",
"integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA=="
},
"needle": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz",
@ -5792,6 +5861,14 @@
"lower-case": "^1.1.1"
}
},
"node-abi": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.5.1.tgz",
"integrity": "sha512-oDbFc7vCFx0RWWCweTer3hFm1u+e60N5FtGnmRV6QqvgATGFH/XRR6vqWIeBVosCYCqt6YdIr2L0exLZuEdVcQ==",
"requires": {
"semver": "^5.4.1"
}
},
"node-fetch": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
@ -5993,6 +6070,11 @@
}
}
},
"noop-logger": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
"integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI="
},
"nopt": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
@ -9297,6 +9379,46 @@
"uniqs": "^2.0.0"
}
},
"prebuild-install": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.2.2.tgz",
"integrity": "sha512-4e8VJnP3zJdZv/uP0eNWmr2r9urp4NECw7Mt1OSAi3rcLrbBRxGiAkfUFtre2MhQ5wfREAjRV+K1gubvs/GPsA==",
"requires": {
"detect-libc": "^1.0.3",
"expand-template": "^2.0.3",
"github-from-package": "0.0.0",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"napi-build-utils": "^1.0.1",
"node-abi": "^2.2.0",
"noop-logger": "^0.1.1",
"npmlog": "^4.0.1",
"os-homedir": "^1.0.1",
"pump": "^2.0.1",
"rc": "^1.2.7",
"simple-get": "^2.7.0",
"tar-fs": "^1.13.0",
"tunnel-agent": "^0.6.0",
"which-pm-runs": "^1.0.0"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
},
"simple-get": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz",
"integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==",
"requires": {
"decompress-response": "^3.3.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
}
}
},
"prepend-http": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
@ -9393,7 +9515,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
"integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
"dev": true,
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
@ -10076,6 +10197,11 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sandwich-stream": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/sandwich-stream/-/sandwich-stream-2.0.2.tgz",
"integrity": "sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ=="
},
"sass-graph": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
@ -10353,6 +10479,91 @@
}
}
},
"sharp": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.21.1.tgz",
"integrity": "sha512-XPRi/nosSHk2GG6Zl+uquJ8vZ+00TpNjzrSKah4DGBHYXRxw7nixBBBewJtw3jetUJi0Oaw/n6AO3/myDVVqFg==",
"requires": {
"bindings": "^1.3.1",
"color": "^3.1.0",
"detect-libc": "^1.0.3",
"fs-copy-file-sync": "^1.1.1",
"nan": "^2.11.1",
"npmlog": "^4.1.2",
"prebuild-install": "^5.2.2",
"semver": "^5.6.0",
"simple-get": "^3.0.3",
"tar": "^4.4.8",
"tunnel-agent": "^0.6.0"
},
"dependencies": {
"chownr": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
"integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g=="
},
"color": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/color/-/color-3.1.0.tgz",
"integrity": "sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg==",
"requires": {
"color-convert": "^1.9.1",
"color-string": "^1.5.2"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"requires": {
"color-name": "1.1.3"
}
},
"color-string": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
"integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"nan": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
"integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw=="
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"semver": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
},
"tar": {
"version": "4.4.8",
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz",
"integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
"requires": {
"chownr": "^1.1.1",
"fs-minipass": "^1.2.5",
"minipass": "^2.3.4",
"minizlib": "^1.1.1",
"mkdirp": "^0.5.0",
"safe-buffer": "^5.1.2",
"yallist": "^3.0.2"
}
},
"yallist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
}
}
},
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@ -10389,11 +10600,25 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
},
"simple-concat": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
"integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY="
},
"simple-get": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.0.3.tgz",
"integrity": "sha512-Wvre/Jq5vgoz31Z9stYWPLn0PqRqmBDpFSdypAnHu5AvRVCYPRYGnvryNLiXu8GOBNDH82J2FRHUGMjjHUpXFw==",
"requires": {
"decompress-response": "^3.3.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
"dev": true,
"requires": {
"is-arrayish": "^0.3.1"
},
@ -10401,8 +10626,7 @@
"is-arrayish": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.1.tgz",
"integrity": "sha1-wt/DhquqDD4zxI2z/ocFnmkGXv0=",
"dev": true
"integrity": "sha1-wt/DhquqDD4zxI2z/ocFnmkGXv0="
}
}
},
@ -11095,6 +11319,84 @@
"inherits": "2"
}
},
"tar-fs": {
"version": "1.16.3",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz",
"integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==",
"requires": {
"chownr": "^1.0.1",
"mkdirp": "^0.5.1",
"pump": "^1.0.0",
"tar-stream": "^1.1.2"
},
"dependencies": {
"pump": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
"integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
}
}
},
"tar-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
"integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==",
"requires": {
"bl": "^1.0.0",
"buffer-alloc": "^1.2.0",
"end-of-stream": "^1.0.0",
"fs-constants": "^1.0.0",
"readable-stream": "^2.3.0",
"to-buffer": "^1.1.1",
"xtend": "^4.0.0"
}
},
"telegraf": {
"version": "3.25.5",
"resolved": "https://registry.npmjs.org/telegraf/-/telegraf-3.25.5.tgz",
"integrity": "sha512-gGyyAl5b+jVwR8L2YXxUYCgDqF3LUlXIlt2+sWozdKiVuWliPgATmdk/dp9I0Rw+fIePJVX/lQfgd8MfuSSwRA==",
"requires": {
"@types/node": "^10.1.2",
"debug": "^4.0.1",
"node-fetch": "^2.2.0",
"sandwich-stream": "^2.0.1",
"telegram-typings": "^3.6.0"
},
"dependencies": {
"@types/node": {
"version": "10.12.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
"integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ=="
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
},
"node-fetch": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz",
"integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA=="
}
}
},
"telegram-typings": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/telegram-typings/-/telegram-typings-3.6.1.tgz",
"integrity": "sha512-njVv1EAhIZnmQVLocZEADYUyqA1WIXuVcDYlsp+mXua/XB0pxx+PKtMSPeZ/EE4wPWTw9h/hA9ASTT6yQelkiw=="
},
"terraformer": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/terraformer/-/terraformer-1.0.9.tgz",
@ -11335,6 +11637,11 @@
"integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
"dev": true
},
"to-buffer": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
"integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
},
"to-object-path": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
@ -12629,6 +12936,11 @@
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
"dev": true
},
"which-pm-runs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs="
},
"wide-align": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",

View File

@ -40,8 +40,10 @@
"require-dir-all": "^0.4.15",
"sequelize": "^4.39.1",
"sequelize-typescript": "^0.6.6",
"sharp": "^0.21.1",
"spotify-uri": "^1.0.0",
"sqlite3": "^4.0.4",
"telegraf": "^3.25.5",
"typescript": "^2.9.2",
"typescript-rest": "^1.7.0",
"umzug": "^2.1.0",

View File

@ -4,11 +4,21 @@ import StickerPack from "../../db/models/StickerPack";
import { ApiError } from "../ApiError";
import { DimensionStickerService, MemoryStickerPack } from "../dimension/DimensionStickerService";
import { Cache, CACHE_STICKERS } from "../../MemoryCache";
import { TelegramBot } from "../../utils/TelegramBot";
import { MatrixLiteClient } from "../../matrix/MatrixLiteClient";
import config from "../../config";
import Sticker from "../../db/models/Sticker";
import { LogService } from "matrix-js-snippets";
import * as sharp from "sharp";
interface SetEnabledRequest {
isEnabled: boolean;
}
interface ImportTelegramRequest {
packUrl: string;
}
/**
* Administrative API for configuring stickers
*/
@ -35,4 +45,79 @@ export class AdminStickerService {
return {}; // 200 OK
}
@POST
@Path("packs/import/telegram")
public async importFromTelegram(@QueryParam("scalar_token") scalarToken: string, request: ImportTelegramRequest): Promise<MemoryStickerPack> {
const userId = await AdminService.validateAndGetAdminTokenOwner(scalarToken);
if (!request.packUrl || (!request.packUrl.startsWith("https://t.me/addstickers/") && !request.packUrl.startsWith("https://telegram.me/addstickers/"))) {
throw new ApiError(400, "Invalid pack URL");
}
const tg = new TelegramBot();
const mx = new MatrixLiteClient(config.homeserver.accessToken);
LogService.info("AdminStickerService", "Importing " + request.packUrl + " from Telegram for " + userId);
const tgPack = await tg.getStickerPack(request.packUrl);
const pack = await StickerPack.create({
type: "stickerpack",
name: tgPack.name,
description: tgPack.description,
avatarUrl: "mxc://localhost/NotYetLoaded",
isEnabled: false,
isPublic: true,
authorType: "telegram",
authorName: "Telegram",
authorReference: request.packUrl,
license: "Telegram",
licensePath: "/licenses/telegram-imported.txt",
});
const stickers = [];
try {
let avatarUrl = null;
for (const tgSticker of tgPack.stickers) {
LogService.info("AdminStickerService", "Importing sticker from " + tgSticker.url);
const buffer = await mx.downloadFromUrl(tgSticker.url);
console.log(typeof(buffer));
const png = await sharp(buffer).png().toBuffer();
const mxc = await mx.upload(png, "image/png");
const serverName = mxc.substring("mxc://".length).split("/")[0];
const contentId = mxc.substring("mxc://".length).split("/")[1];
const thumbMxc = await mx.uploadFromUrl(await mx.getThumbnailUrl(serverName, contentId, 512, 512, "crop", false), "image/png");
stickers.push(await Sticker.create({
packId: pack.id,
name: tgSticker.emoji,
description: tgSticker.emoji,
imageMxc: mxc,
thumbnailMxc: thumbMxc,
thumbnailWidth: 512,
thumbnailHeight: 512,
mimetype: "image/png",
}));
if (!avatarUrl) avatarUrl = mxc;
}
pack.avatarUrl = avatarUrl;
await pack.save();
} catch (e) {
LogService.error("AdminStickerService", e);
const thingsToDelete = [pack, ...stickers];
for (const item of thingsToDelete) {
try {
await item.destroy();
} catch (e2) {
LogService.error("AdminStickerService", e2);
}
}
throw new ApiError(500, "Error importing stickers");
}
Cache.for(CACHE_STICKERS).clear();
return DimensionStickerService.packToMemory(pack);
}
}

View File

@ -119,7 +119,7 @@ export class DimensionStickerService {
return {}; // 200 OK
}
private static async packToMemory(pack: StickerPack): Promise<MemoryStickerPack> {
public static async packToMemory(pack: StickerPack): Promise<MemoryStickerPack> {
const stickers = await Sticker.findAll({where: {packId: pack.id}});
return {
id: pack.id,

View File

@ -23,6 +23,9 @@ export interface DimensionConfig {
[botType: string]: string; // mxc
};
};
telegram: {
botToken: string;
};
logging: LogConfig;
}

View File

@ -1,5 +1,7 @@
import { doClientApiCall } from "./helpers";
import config from "../config";
import * as request from "request";
import { LogService } from "matrix-js-snippets";
export interface MatrixUrlPreview {
// This is really the only parameter we care about
@ -93,4 +95,40 @@ export class MatrixLiteClient {
{avatar_url: newUrl},
);
}
public async upload(content: Buffer, contentType: string): Promise<string> {
return doClientApiCall(
"POST",
"/_matrix/media/r0/upload",
{access_token: this.accessToken},
content,
contentType,
).then(r => r["content_uri"]);
}
public async uploadFromUrl(url: string, contentType: string): Promise<string> {
const buffer = await this.downloadFromUrl(url);
return this.upload(buffer, contentType);
}
public async downloadFromUrl(url: string): Promise<any> {
return new Promise((resolve, reject) => {
request({
method: "GET",
url: url,
encoding: null,
}, (err, res, _body) => {
if (err) {
LogService.error("MatrixLiteClient", "Error downloading file from " + url);
LogService.error("MatrixLiteClient", err);
reject(err);
} else if (res.statusCode !== 200) {
LogService.error("MatrixLiteClient", "Got status code " + res.statusCode + " while calling url " + url);
reject(new Error("Error in request: invalid status code"));
} else {
resolve(res.body);
}
});
});
}
}

View File

@ -79,18 +79,27 @@ export async function doFederatedApiCall(method: string, serverName: string, end
});
}
export async function doClientApiCall(method: string, endpoint: string, query?: object, body?: object): Promise<any> {
export async function doClientApiCall(method: string, endpoint: string, query?: object, body?: object | Buffer, contentType: string = "application/octet-stream"): Promise<any> {
let url = config.homeserver.clientServerUrl;
if (url.endsWith("/")) url = url.substring(0, url.length - 1);
LogService.info("matrix", "Doing client API call: " + url + endpoint);
const requestOptions = {
method: method,
url: url + endpoint,
qs: query,
};
if (Buffer.isBuffer(body)) {
requestOptions["body"] = body;
requestOptions["headers"] = {
"Content-Type": contentType,
};
} else {
requestOptions["json"] = body;
}
return new Promise((resolve, reject) => {
request({
method: method,
url: url + endpoint,
qs: query,
json: body,
}, (err, res, _body) => {
request(requestOptions, (err, res, _body) => {
if (err) {
LogService.error("matrix", "Error calling " + endpoint);
LogService.error("matrix", err);

40
src/utils/TelegramBot.ts Normal file
View File

@ -0,0 +1,40 @@
import Telegraf, { Telegram } from "telegraf";
import config from "../config";
import * as path from "path";
export interface TelegramStickerPack {
name: string;
description: string;
stickers: {
url: string;
emoji: string;
}[];
}
export class TelegramBot {
private bot: Telegram;
constructor() {
const tg = new Telegraf(config.telegram.botToken);
this.bot = tg.telegram;
}
public async getStickerPack(packUrl: string): Promise<TelegramStickerPack> {
const set = await this.bot.getStickerSet(path.basename(packUrl));
const pack: TelegramStickerPack = {
name: set.name,
description: set.title,
stickers: [],
};
for (const tgSticker of set.stickers) {
pack.stickers.push({
url: await this.bot.getFileLink(tgSticker.file_id),
emoji: tgSticker.emoji,
});
}
return pack;
}
}

View File

@ -10,6 +10,17 @@
then the 'sticker picker' widget will be disabled.
</p>
<div class="input-group input-group-sm telegram-import">
<input type="text" class="form-control" [(ngModel)]="tgUrl" placeholder="https://t.me/addstickers/YourPackID"
[disabled]="isImporting" />
<span class="input-group-btn">
<button class="btn btn-primary" (click)="startTelegramImport()" [disabled]="!tgUrl || isImporting">
<i class="fa fa-download"></i>
Import from Telegram
</button>
</span>
</div>
<table class="table table-striped table-condensed table-bordered">
<thead>
<tr>

View File

@ -5,4 +5,8 @@ tr td:last-child {
.previewButton {
cursor: pointer;
vertical-align: text-bottom;
}
}
.telegram-import {
margin-bottom: 15px;
}

View File

@ -14,6 +14,8 @@ export class AdminStickerPacksComponent implements OnInit {
public isLoading = true;
public isUpdating = false;
public packs: FE_StickerPack[];
public tgUrl: string;
public isImporting = false;
constructor(private adminStickers: AdminStickersApiService,
private toaster: ToasterService,
@ -52,4 +54,18 @@ export class AdminStickerPacksComponent implements OnInit {
size: 'lg',
}, StickerPackPreviewDialogContext));
}
public startTelegramImport() {
this.isImporting = true;
this.adminStickers.importFromTelegram(this.tgUrl).then(pack => {
this.isImporting = false;
this.tgUrl = "";
this.packs.push(pack);
this.toaster.pop("success", "Telegram sticker pack imported");
}).catch(err => {
console.error(err);
this.isImporting = false;
this.toaster.pop("error", "Error importing sticker pack");
});
}
}

View File

@ -17,4 +17,9 @@ export class AdminStickersApiService extends AuthedApi {
return this.authedPost("/api/v1/dimension/admin/stickers/packs/" + packId + "/enabled", {isEnabled: isEnabled})
.map(r => r.json()).toPromise();
}
public importFromTelegram(packUrl: string): Promise<FE_StickerPack> {
return this.authedPost("/api/v1/dimension/admin/stickers/packs/import/telegram", {packUrl: packUrl})
.map(r => r.json()).toPromise();
}
}

View File

@ -0,0 +1 @@
The sticker pack was imported from Telegram, and therefore a license is unavailable, sorry.