Add support for uploading avatars (#767)
* Add uploading configured avatar images * Add avatar assets * Update docs and sample config * Add changelog * Fix sample config * Add removing avatars when none configured
@ -42,6 +42,7 @@ RUN yarn --network-timeout 600000 --production --pure-lockfile && yarn cache cle
|
||||
|
||||
COPY --from=builder /src/lib ./
|
||||
COPY --from=builder /src/public ./public
|
||||
COPY --from=builder /src/assets ./assets
|
||||
|
||||
VOLUME /data
|
||||
EXPOSE 9993
|
||||
|
BIN
assets/feeds_avatar.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
assets/figma_avatar.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
assets/github_avatar.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/gitlab_avatar.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
assets/jira_avatar.png
Normal file
After Width: | Height: | Size: 12 KiB |
67
assets/src/feeds_avatar.svg
Normal file
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 0.33333333 0.33333333"
|
||||
version="1.1"
|
||||
id="svg1630"
|
||||
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
|
||||
sodipodi:docname="feeds_avatar.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1632"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="in"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4.28125"
|
||||
inkscape:cx="94.715328"
|
||||
inkscape:cy="-14.014599"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1302"
|
||||
inkscape:window-x="2560"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs1627" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#f8991d;stroke-width:0.000783981;fill-opacity:1"
|
||||
id="rect16036"
|
||||
width="0.33333334"
|
||||
height="0.33333334"
|
||||
x="0"
|
||||
y="0" />
|
||||
<ellipse
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0113383;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path5270"
|
||||
cx="0.10655722"
|
||||
cy="0.22619501"
|
||||
rx="0.023283437"
|
||||
ry="0.022608556" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.00108608px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0.08347222,0.16973219 -7.942e-5,-0.032879 c 0.070275,0.00367 0.10927918,0.0539491 0.11023648,0.11071368 h -0.032928 c -5.4632e-4,-0.049895 -0.034473,-0.07602 -0.07722906,-0.0778347 z"
|
||||
id="path5805"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.00108608px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 0.08434684,0.11703641 0.0833928,0.08363142 c 0.10798627,0.0050099 0.16581867,0.08337597 0.16654766,0.16607045 l -0.0338827,-4.7761e-4 c 0.001483,-0.052895 -0.0376492,-0.13061767 -0.13171092,-0.13218785 z"
|
||||
id="path5807"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
88
assets/src/figma_avatar.svg
Normal file
@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 0.33333333 0.33333333"
|
||||
version="1.1"
|
||||
id="svg1630"
|
||||
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
|
||||
sodipodi:docname="figma_avatar.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1632"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="in"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4.2812503"
|
||||
inkscape:cx="62.715324"
|
||||
inkscape:cy="56.525544"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1274"
|
||||
inkscape:window-x="2560"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs1627" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.000783981;fill-opacity:1"
|
||||
id="rect16036"
|
||||
width="0.33333334"
|
||||
height="0.33333334"
|
||||
x="0"
|
||||
y="0" />
|
||||
<g
|
||||
id="g482"
|
||||
transform="translate(0.01500414)">
|
||||
<rect
|
||||
width="0.11111087"
|
||||
height="0.16666642"
|
||||
fill="#000000"
|
||||
fill-opacity="0"
|
||||
id="rect240"
|
||||
x="0.096107043"
|
||||
y="0.083333619"
|
||||
style="stroke-width:0.00116931" />
|
||||
<path
|
||||
d="m 0.15166251,0.16666672 c 0,-0.0153406 0.0124364,-0.027778 0.0277778,-0.027778 v 0 c 0.015341,0 0.0277777,0.0124366 0.0277777,0.027778 v 0 c 0,0.0153413 -0.0124368,0.0277779 -0.0277777,0.0277779 v 0 c -0.0153414,0 -0.0277778,-0.0124366 -0.0277778,-0.0277779 z"
|
||||
fill="#1abcfe"
|
||||
id="path242"
|
||||
style="stroke-width:0.000389771" />
|
||||
<path
|
||||
d="m 0.09610705,0.22222216 c 0,-0.0153406 0.0124365,-0.027778 0.0277777,-0.027778 h 0.0277778 v 0.027778 c 0,0.0153413 -0.0124364,0.027778 -0.0277778,0.027778 v 0 c -0.0153412,0 -0.0277777,-0.0124366 -0.0277777,-0.027778 z"
|
||||
fill="#0acf83"
|
||||
id="path244"
|
||||
style="stroke-width:0.000389771" />
|
||||
<path
|
||||
d="m 0.15166251,0.08333365 v 0.05555524 h 0.0277778 c 0.0153414,0 0.0277777,-0.0124366 0.0277777,-0.0277773 v 0 c 0,-0.01534131 -0.0124364,-0.02777796 -0.0277777,-0.02777796 z"
|
||||
fill="#ff7262"
|
||||
id="path246"
|
||||
style="stroke-width:0.000389771" />
|
||||
<path
|
||||
d="m 0.09610705,0.11111141 c 0,0.0153413 0.0124365,0.0277773 0.0277777,0.0277773 h 0.0277778 V 0.08333345 h -0.0277778 c -0.0153412,0 -0.0277777,0.01243665 -0.0277777,0.02777796 z"
|
||||
fill="#f24e1e"
|
||||
id="path248"
|
||||
style="stroke-width:0.000389771" />
|
||||
<path
|
||||
d="m 0.09610705,0.16666672 c 0,0.0153413 0.0124365,0.0277779 0.0277777,0.0277779 h 0.0277778 v -0.0555552 h -0.0277778 c -0.0153412,0 -0.0277777,0.0124366 -0.0277777,0.0277773 z"
|
||||
fill="#a259ff"
|
||||
id="path250"
|
||||
style="stroke-width:0.000389771" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
57
assets/src/github_avatar.svg
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 0.33333333 0.33333333"
|
||||
version="1.1"
|
||||
id="svg1630"
|
||||
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
|
||||
sodipodi:docname="github_avatar.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1632"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="in"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.109204"
|
||||
inkscape:cx="39.350233"
|
||||
inkscape:cy="8.0104357"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1302"
|
||||
inkscape:window-x="2560"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs1627" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.000783981;fill-opacity:1"
|
||||
id="rect16036"
|
||||
width="0.33333334"
|
||||
height="0.33333334"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="m 0.16677043,0.04375549 c -0.0691789,0 -0.1251031,0.0563338 -0.1251031,0.12602641 0,0.055709 0.03583264,0.10286558 0.085542,0.11955571 0.006214,0.001255 0.008491,-0.002712 0.008491,-0.006048 0,-0.002922 -2.0487e-4,-0.012936 -2.0487e-4,-0.0233708 -0.0348006,0.007513 -0.0420475,-0.0150232 -0.0420475,-0.0150232 -0.005592,-0.0146055 -0.0138795,-0.0183596 -0.0138795,-0.0183596 -0.0113895,-0.00772 8.2964e-4,-0.00772 8.2964e-4,-0.00772 0.0126345,8.3481e-4 0.0192646,0.0129359 0.0192646,0.0129359 0.0111825,0.0191945 0.0292028,0.0137715 0.0364524,0.0104325 0.001034,-0.008137 0.004351,-0.0137715 0.007872,-0.0169001 -0.0277559,-0.002922 -0.0569588,-0.0137715 -0.0569588,-0.0621797 0,-0.0137715 0.004968,-0.0250378 0.01284,-0.0338003 -0.001242,-0.003129 -0.005593,-0.0160681 0.001245,-0.0333854 0,0 0.010563,-0.003339 0.0343806,0.012936 a 0.12027864,0.12027267 0 0 1 0.031277,-0.004173 c 0.010563,0 0.0213311,0.001463 0.0312744,0.004173 0.0238202,-0.0162752 0.0343833,-0.012936 0.0343833,-0.012936 0.006837,0.0173176 0.002484,0.0302564 0.001241,0.0333854 0.008079,0.008763 0.012843,0.0200291 0.012843,0.0338003 0,0.0484087 -0.0292028,0.059048 -0.0571663,0.0621797 0.004558,0.003964 0.008491,0.0114735 0.008491,0.0233683 0,0.0169001 -2.0484e-4,0.0304638 -2.0484e-4,0.034635 0,0.003339 0.002279,0.007305 0.008491,0.006054 0.0497094,-0.0166952 0.085542,-0.0638492 0.085542,-0.11955826 2.0433e-4,-0.0696935 -0.0559249,-0.12602732 -0.12489634,-0.12602731 z"
|
||||
fill="#24292f"
|
||||
id="path361"
|
||||
style="stroke-width:0.00256072" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.0 KiB |
74
assets/src/gitlab_avatar.svg
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 0.33333333 0.33333333"
|
||||
version="1.1"
|
||||
id="svg1630"
|
||||
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
|
||||
sodipodi:docname="gitlab_avatar.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1632"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="in"
|
||||
showgrid="false"
|
||||
inkscape:zoom="17.125001"
|
||||
inkscape:cx="28.992699"
|
||||
inkscape:cy="10.218978"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1302"
|
||||
inkscape:window-x="2560"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs1627" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.000783981;fill-opacity:1"
|
||||
id="rect16036"
|
||||
width="0.33333334"
|
||||
height="0.33333334"
|
||||
x="0"
|
||||
y="0" />
|
||||
<g
|
||||
id="LOGO"
|
||||
transform="matrix(0.00130172,0,0,0.00130172,-0.08066014,-0.08067311)">
|
||||
<path
|
||||
class="cls-1"
|
||||
d="m 282.83,170.73 -0.27,-0.69 -26.14,-68.22 a 6.81,6.81 0 0 0 -2.69,-3.24 7,7 0 0 0 -8,0.43 7,7 0 0 0 -2.32,3.52 l -17.65,54 h -71.47 l -17.65,-54 a 6.86,6.86 0 0 0 -2.32,-3.53 7,7 0 0 0 -8,-0.43 6.87,6.87 0 0 0 -2.69,3.24 L 97.44,170 l -0.26,0.69 a 48.54,48.54 0 0 0 16.1,56.1 l 0.09,0.07 0.24,0.17 39.82,29.82 19.7,14.91 12,9.06 a 8.07,8.07 0 0 0 9.76,0 l 12,-9.06 19.7,-14.91 40.06,-30 0.1,-0.08 a 48.56,48.56 0 0 0 16.08,-56.04 z"
|
||||
id="path695"
|
||||
style="fill:#e24329" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 282.83,170.73 -0.27,-0.69 a 88.3,88.3 0 0 0 -35.15,15.8 L 190,229.25 c 19.55,14.79 36.57,27.64 36.57,27.64 l 40.06,-30 0.1,-0.08 a 48.56,48.56 0 0 0 16.1,-56.08 z"
|
||||
id="path697"
|
||||
style="fill:#fc6d26" />
|
||||
<path
|
||||
class="cls-3"
|
||||
d="m 153.43,256.89 19.7,14.91 12,9.06 a 8.07,8.07 0 0 0 9.76,0 l 12,-9.06 19.7,-14.91 c 0,0 -17.04,-12.89 -36.59,-27.64 -19.55,14.75 -36.57,27.64 -36.57,27.64 z"
|
||||
id="path699"
|
||||
style="fill:#fca326" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M 132.58,185.84 A 88.19,88.19 0 0 0 97.44,170 l -0.26,0.69 a 48.54,48.54 0 0 0 16.1,56.1 l 0.09,0.07 0.24,0.17 39.82,29.82 c 0,0 17,-12.85 36.57,-27.64 z"
|
||||
id="path701"
|
||||
style="fill:#fc6d26" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
90
assets/src/jira_avatar.svg
Normal file
@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 32 32"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg22"
|
||||
sodipodi:docname="jira_avatar.svg"
|
||||
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview24"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="11.346854"
|
||||
inkscape:cx="12.999198"
|
||||
inkscape:cy="14.453345"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1302"
|
||||
inkscape:window-x="2560"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg22" />
|
||||
<rect
|
||||
style="opacity:1;fill:#0052cc;fill-opacity:1;stroke-width:0.941893"
|
||||
id="rect332"
|
||||
width="32"
|
||||
height="32"
|
||||
x="0"
|
||||
y="-1.3125472e-07" />
|
||||
<path
|
||||
d="M23.7199 7.64001H15.6399C15.6399 9.64001 17.2799 11.28 19.2799 11.28H20.7599V12.72C20.7599 14.72 22.3999 16.36 24.3999 16.36V8.32001C24.4399 7.96001 24.1199 7.64001 23.7199 7.64001Z"
|
||||
fill="white"
|
||||
id="path4" />
|
||||
<path
|
||||
d="M19.7199 11.64H11.6399C11.6399 13.64 13.2799 15.28 15.2799 15.28H16.7599V16.72C16.7599 18.72 18.3999 20.36 20.3999 20.36V12.36C20.4399 11.96 20.1199 11.64 19.7199 11.64Z"
|
||||
fill="url(#paint0_linear)"
|
||||
id="path6" />
|
||||
<path
|
||||
d="M15.7199 15.6801H7.63989C7.63989 17.6801 9.27988 19.3201 11.2799 19.3201H12.7599V20.7601C12.7599 22.7601 14.3999 24.4001 16.3999 24.4001V16.4001C16.4399 16.0001 16.1199 15.6801 15.7199 15.6801Z"
|
||||
fill="url(#paint1_linear)"
|
||||
id="path8" />
|
||||
<defs
|
||||
id="defs20">
|
||||
<linearGradient
|
||||
id="paint0_linear"
|
||||
x1="20.2597"
|
||||
y1="11.6708"
|
||||
x2="16.8183"
|
||||
y2="15.2196"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0.176"
|
||||
stop-color="white"
|
||||
stop-opacity="0.4"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="white"
|
||||
id="stop12" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint1_linear"
|
||||
x1="16.4844"
|
||||
y1="15.7246"
|
||||
x2="12.5054"
|
||||
y2="19.596"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0.176"
|
||||
stop-color="white"
|
||||
stop-opacity="0.4"
|
||||
id="stop15" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="white"
|
||||
id="stop17" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
79
assets/src/webhooks_avatar.svg
Normal file
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 0.33333333 0.33333333"
|
||||
version="1.1"
|
||||
id="svg1630"
|
||||
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
|
||||
sodipodi:docname="webhooks_avatar.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1632"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="in"
|
||||
showgrid="false"
|
||||
inkscape:zoom="6.0546022"
|
||||
inkscape:cx="90.096753"
|
||||
inkscape:cy="-17.011853"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1302"
|
||||
inkscape:window-x="2560"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs1627" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.000783981;fill-opacity:1"
|
||||
id="rect16036"
|
||||
width="0.33333334"
|
||||
height="0.33333334"
|
||||
x="0"
|
||||
y="0" />
|
||||
<g
|
||||
id="g346"
|
||||
transform="matrix(0.015625,0,0,0.015625,-2.4512961,-2.5012285)">
|
||||
<g
|
||||
id="OvHZFw.tif"
|
||||
transform="matrix(0.12401029,0,0,0.12401029,159.54955,163.29764)">
|
||||
<g
|
||||
id="g325">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fill="#231f20"
|
||||
d="m 60.467,50.345 c -5.367,9.022 -10.509,17.759 -15.758,26.43 -1.348,2.226 -2.015,4.039 -0.938,6.869 2.973,7.817 -1.221,15.424 -9.104,17.489 C 27.233,103.081 19.99,98.195 18.515,90.236 17.208,83.191 22.675,76.285 30.442,75.184 31.093,75.091 31.757,75.08 32.851,74.998 36.657,68.616 40.556,62.079 44.666,55.186 37.235,47.797 32.812,39.159 33.791,28.456 34.483,20.89 37.458,14.352 42.896,8.993 53.311,-1.269 69.2,-2.931 81.463,4.946 93.241,12.512 98.635,27.25 94.037,39.864 90.57,38.924 87.079,37.976 83.241,36.935 84.685,29.922 83.617,23.624 78.887,18.229 75.762,14.667 71.752,12.8 67.192,12.112 58.051,10.731 49.076,16.604 46.413,25.576 43.39,35.759 47.965,44.077 60.467,50.345 Z"
|
||||
id="path319" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fill="#231f20"
|
||||
d="m 75.794,39.676 c 3.781,6.67 7.62,13.441 11.425,20.15 19.232,-5.95 33.732,4.696 38.934,16.094 6.283,13.768 1.988,30.075 -10.352,38.569 -12.666,8.72 -28.684,7.23 -39.906,-3.971 2.86,-2.394 5.734,-4.799 8.805,-7.368 11.084,7.179 20.778,6.841 27.975,-1.66 6.137,-7.252 6.004,-18.065 -0.311,-25.165 -7.288,-8.193 -17.05,-8.443 -28.85,-0.578 -4.895,-8.684 -9.875,-17.299 -14.615,-26.046 -1.598,-2.948 -3.363,-4.658 -6.965,-5.282 -6.016,-1.043 -9.9,-6.209 -10.133,-11.997 -0.229,-5.724 3.143,-10.898 8.414,-12.914 5.221,-1.997 11.348,-0.385 14.86,4.054 2.87,3.627 3.782,7.709 2.272,12.182 -0.42,1.247 -0.964,2.454 -1.553,3.932 z"
|
||||
id="path321" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fill="#231f20"
|
||||
d="m 84.831,94.204 c -7.605,0 -15.238,0 -23.152,0 -2.219,9.127 -7.012,16.496 -15.271,21.182 -6.42,3.642 -13.34,4.877 -20.705,3.688 C 12.143,116.887 1.055,104.68 0.079,90.934 -1.026,75.363 9.677,61.522 23.943,58.413 c 0.985,3.577 1.98,7.188 2.965,10.756 -13.089,6.678 -17.619,15.092 -13.956,25.613 3.225,9.259 12.385,14.334 22.331,12.371 10.157,-2.004 15.278,-10.445 14.653,-23.992 9.629,0 19.266,-0.1 28.896,0.049 3.76,0.059 6.663,-0.331 9.496,-3.646 4.664,-5.455 13.248,-4.963 18.271,0.189 5.133,5.265 4.887,13.737 -0.545,18.78 -5.241,4.866 -13.521,4.606 -18.424,-0.637 -1.008,-1.081 -1.802,-2.364 -2.799,-3.692 z"
|
||||
id="path323" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/webhooks_avatar.png
Normal file
After Width: | Height: | Size: 26 KiB |
1
changelog.d/767.feature
Normal file
@ -0,0 +1 @@
|
||||
Add support for uploading bot avatar images.
|
@ -107,7 +107,7 @@ serviceBots:
|
||||
|
||||
- localpart: feeds
|
||||
displayname: Feeds
|
||||
avatar: mxc://half-shot.uk/2876e89ccade4cb615e210c458e2a7a6883fe17d
|
||||
avatar: ./assets/feeds_avatar.png
|
||||
prefix: "!feeds"
|
||||
service: feeds
|
||||
metrics:
|
||||
|
@ -20,7 +20,7 @@ For example with this configuration:
|
||||
serviceBots:
|
||||
- localpart: feeds
|
||||
displayname: Feeds
|
||||
avatar: mxc://half-shot.uk/2876e89ccade4cb615e210c458e2a7a6883fe17d
|
||||
avatar: "./assets/feeds_avatar.png"
|
||||
prefix: "!feeds"
|
||||
service: feeds
|
||||
```
|
||||
|
@ -1,3 +1,6 @@
|
||||
import { promises as fs } from "fs";
|
||||
import axios from "axios";
|
||||
import mime from "mime";
|
||||
import { Appservice, Intent } from "matrix-bot-sdk";
|
||||
import { Logger } from "matrix-appservice-bridge";
|
||||
|
||||
@ -84,22 +87,122 @@ export default class BotUsersManager {
|
||||
log.debug(`Ensuring bot user ${botUser.userId} is registered`);
|
||||
await botUser.intent.ensureRegistered();
|
||||
|
||||
// Set up the bot profile
|
||||
let profile;
|
||||
await this.ensureProfile(botUser);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the bot user profile display name and avatar image are updated.
|
||||
*
|
||||
* @returns Promise resolving when the user profile has been ensured.
|
||||
*/
|
||||
private async ensureProfile(botUser: BotUser): Promise<void> {
|
||||
log.debug(`Ensuring profile for ${botUser.userId} is updated`);
|
||||
|
||||
let profile: {
|
||||
avatar_url?: string,
|
||||
displayname?: string,
|
||||
};
|
||||
try {
|
||||
profile = await botUser.intent.underlyingClient.getUserProfile(botUser.userId);
|
||||
} catch {
|
||||
profile = {}
|
||||
}
|
||||
if (botUser.avatar && profile.avatar_url !== botUser.avatar) {
|
||||
log.info(`Setting avatar for "${botUser.userId}" to ${botUser.avatar}`);
|
||||
await botUser.intent.underlyingClient.setAvatarUrl(botUser.avatar);
|
||||
} catch (e) {
|
||||
log.error(`Failed to get user profile for ${botUser.userId}:`, e);
|
||||
profile = {};
|
||||
}
|
||||
|
||||
// Update display name if necessary
|
||||
if (botUser.displayname && profile.displayname !== botUser.displayname) {
|
||||
log.info(`Setting displayname for "${botUser.userId}" to ${botUser.displayname}`);
|
||||
try {
|
||||
await botUser.intent.underlyingClient.setDisplayName(botUser.displayname);
|
||||
log.info(`Updated displayname for "${botUser.userId}" to ${botUser.displayname}`);
|
||||
} catch (e) {
|
||||
log.error(`Failed to set displayname for ${botUser.userId}:`, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!botUser.avatar) {
|
||||
// Unset any avatar
|
||||
if (profile.avatar_url) {
|
||||
await botUser.intent.underlyingClient.setAvatarUrl('');
|
||||
log.info(`Removed avatar for "${botUser.userId}"`);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (botUser.avatar.startsWith("mxc://")) {
|
||||
// Configured avatar is a Matrix content URL
|
||||
if (profile.avatar_url === botUser.avatar) {
|
||||
// Avatar is current, no need to update
|
||||
log.debug(`Avatar for ${botUser.userId} is already updated`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await botUser.intent.underlyingClient.setAvatarUrl(botUser.avatar);
|
||||
log.info(`Updated avatar for ${botUser.userId} to ${botUser.avatar}`);
|
||||
} catch (e) {
|
||||
log.error(`Failed to set avatar for ${botUser.userId}:`, e);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise assume configured avatar is a file path
|
||||
let avatarImage: {
|
||||
image: Buffer,
|
||||
contentType: string,
|
||||
};
|
||||
try {
|
||||
const contentType = mime.getType(botUser.avatar);
|
||||
if (!contentType) {
|
||||
throw new Error("Could not determine content type");
|
||||
}
|
||||
// File path
|
||||
avatarImage = {
|
||||
image: await fs.readFile(botUser.avatar),
|
||||
contentType,
|
||||
};
|
||||
} catch (e) {
|
||||
log.error(`Failed to load avatar at ${botUser.avatar}:`, e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine if an avatar update is needed
|
||||
if (profile.avatar_url) {
|
||||
try {
|
||||
const res = await axios.get(
|
||||
botUser.intent.underlyingClient.mxcToHttp(profile.avatar_url),
|
||||
{ responseType: "arraybuffer" },
|
||||
);
|
||||
const currentAvatarImage = {
|
||||
image: Buffer.from(res.data),
|
||||
contentType: res.headers["content-type"],
|
||||
};
|
||||
if (
|
||||
currentAvatarImage.image.equals(avatarImage.image)
|
||||
&& currentAvatarImage.contentType === avatarImage.contentType
|
||||
) {
|
||||
// Avatar is current, no need to update
|
||||
log.debug(`Avatar for ${botUser.userId} is already updated`);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
log.error(`Failed to get current avatar image for ${botUser.userId}:`, e);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the avatar
|
||||
try {
|
||||
const uploadedAvatarMxcUrl = await botUser.intent.underlyingClient.uploadContent(
|
||||
avatarImage.image,
|
||||
avatarImage.contentType,
|
||||
);
|
||||
await botUser.intent.underlyingClient.setAvatarUrl(uploadedAvatarMxcUrl);
|
||||
log.info(`Updated avatar for ${botUser.userId} to ${uploadedAvatarMxcUrl}`);
|
||||
} catch (e) {
|
||||
log.error(`Failed to set avatar for ${botUser.userId}:`, e);
|
||||
}
|
||||
}
|
||||
|
||||
private async getJoinedRooms(): Promise<void> {
|
||||
|
@ -53,7 +53,7 @@ export const DefaultConfigRoot: BridgeConfigRoot = {
|
||||
{
|
||||
localpart: "feeds",
|
||||
displayname: "Feeds",
|
||||
avatar: "mxc://half-shot.uk/2876e89ccade4cb615e210c458e2a7a6883fe17d",
|
||||
avatar: "./assets/feeds_avatar.png",
|
||||
prefix: "!feeds",
|
||||
service: "feeds",
|
||||
},
|
||||
|