]> Untitled Git - lemmy.git/commitdiff
Merge branch 'master' into federation_merge_from_master_2
authorDessalines <tyhou13@gmx.com>
Wed, 24 Jun 2020 01:11:38 +0000 (21:11 -0400)
committerDessalines <tyhou13@gmx.com>
Wed, 24 Jun 2020 01:11:38 +0000 (21:11 -0400)
21 files changed:
1  2 
docker/dev/test_deploy.sh
docker/federation/docker-compose.yml
docker/federation/nginx.conf
docker/federation/run-federation-test.bash
server/Cargo.lock
server/Cargo.toml
server/src/api/community.rs
server/src/api/mod.rs
server/src/api/post.rs
server/src/apub/activities.rs
server/src/apub/extensions/signatures.rs
server/src/apub/fetcher.rs
server/src/apub/mod.rs
server/src/lib.rs
ui/src/components/comment-node.tsx
ui/src/components/post-form.tsx
ui/src/components/post-listing.tsx
ui/src/components/private-message-form.tsx
ui/src/components/user-listing.tsx
ui/src/components/user.tsx
ui/src/utils.ts

index fb09e4f11588fc57c6fe7056f633e7ad049885c5,ce85f60c6f23f9e03beafd6361993ddc99a6a5ec..c2ecc0c897578f4837d9830fd57350e1265a5a62
@@@ -1,16 -1,15 +1,18 @@@
 -#!/bin/sh
 +#!/bin/bash
  set -e
  
- cd ../../
 +BRANCH=$1
 +
 +git checkout $BRANCH
++
+ export COMPOSE_DOCKER_CLI_BUILD=1
+ export DOCKER_BUILDKIT=1
  
  # Rebuilding dev docker
 -docker-compose build
 -docker tag dev_lemmy:latest dessalines/lemmy:test
 -docker push dessalines/lemmy:test
 +sudo docker build . -f "docker/dev/Dockerfile" -t "dessalines/lemmy:$BRANCH"
 +sudo docker push "dessalines/lemmy:$BRANCH"
  
  # Run the playbook
 -pushd ../../../lemmy-ansible
 -ansible-playbook -i test playbooks/site.yml --vault-password-file vault_pass
 +pushd ../lemmy-ansible
 +ansible-playbook -i test playbooks/site.yml
  popd
index 4379eb386c6b3db44468cb89848e6661e4c8a84d,0000000000000000000000000000000000000000..585f2b4b56f24af28a0bc9015f9d05389c0218a0
mode 100644,000000..100644
--- /dev/null
@@@ -1,129 -1,0 +1,132 @@@
-       - pictshare_alpha
 +version: '3.3'
 +
 +services:
 +  nginx:
 +    image: nginx:1.17-alpine
 +    ports:
 +      - "8540:8540"
 +      - "8550:8550"
 +      - "8560:8560"
 +    volumes:
 +      # Hack to make this work from both docker/federation/ and docker/federation-test/
 +      - ../federation/nginx.conf:/etc/nginx/nginx.conf
 +    depends_on:
 +      - lemmy_alpha
-       - pictshare_beta
++      - pictrs_alpha
 +      - lemmy_beta
-       - pictshare_gamma
++      - pictrs_beta
 +      - lemmy_gamma
-   pictshare_alpha:
-     image: shtripok/pictshare:latest
++      - pictrs_gamma
 +      - iframely
 +    restart: "always"
 +
 +  lemmy_alpha:
 +    image: lemmy-federation:latest
 +    environment:
 +      - LEMMY_HOSTNAME=lemmy_alpha:8540
 +      - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy
 +      - LEMMY_JWT_SECRET=changeme
 +      - LEMMY_FRONT_END_DIR=/app/dist
 +      - LEMMY_FEDERATION__ENABLED=true
 +      - LEMMY_FEDERATION__TLS_ENABLED=false
 +      - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy_beta,lemmy_gamma
 +      - LEMMY_PORT=8540
 +      - LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha
 +      - LEMMY_SETUP__ADMIN_PASSWORD=lemmy
 +      - LEMMY_SETUP__SITE_NAME=lemmy_alpha
 +      - RUST_BACKTRACE=1
 +      - RUST_LOG=debug
 +    restart: always
 +    depends_on:
 +      - postgres_alpha
 +  postgres_alpha:
 +    image: postgres:12-alpine
 +    environment:
 +      - POSTGRES_USER=lemmy
 +      - POSTGRES_PASSWORD=password
 +      - POSTGRES_DB=lemmy
 +    volumes:
 +      - ./volumes/postgres_alpha:/var/lib/postgresql/data
 +    restart: always
-       - ./volumes/pictshare_alpha:/usr/share/nginx/html/data
++  pictrs_alpha:
++    image: asonix/pictrs:v0.1.13-r0
++    user: 991:991
 +    volumes:
-   pictshare_beta:
-     image: shtripok/pictshare:latest
++      - ./volumes/pictrs_alpha:/mnt
 +    restart: always
 +
 +  lemmy_beta:
 +    image: lemmy-federation:latest
 +    environment:
 +      - LEMMY_HOSTNAME=lemmy_beta:8550
 +      - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta:5432/lemmy
 +      - LEMMY_JWT_SECRET=changeme
 +      - LEMMY_FRONT_END_DIR=/app/dist
 +      - LEMMY_FEDERATION__ENABLED=true
 +      - LEMMY_FEDERATION__TLS_ENABLED=false
 +      - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy_alpha,lemmy_gamma
 +      - LEMMY_PORT=8550
 +      - LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta
 +      - LEMMY_SETUP__ADMIN_PASSWORD=lemmy
 +      - LEMMY_SETUP__SITE_NAME=lemmy_beta
 +      - RUST_BACKTRACE=1
 +      - RUST_LOG=debug
 +    restart: always
 +    depends_on:
 +      - postgres_beta
 +  postgres_beta:
 +    image: postgres:12-alpine
 +    environment:
 +      - POSTGRES_USER=lemmy
 +      - POSTGRES_PASSWORD=password
 +      - POSTGRES_DB=lemmy
 +    volumes:
 +      - ./volumes/postgres_beta:/var/lib/postgresql/data
 +    restart: always
-       - ./volumes/pictshare_beta:/usr/share/nginx/html/data
++  pictrs_beta:
++    image: asonix/pictrs:v0.1.13-r0
++    user: 991:991
 +    volumes:
-   pictshare_gamma:
-     image: shtripok/pictshare:latest
++      - ./volumes/pictrs_beta:/mnt
 +    restart: always
 +
 +  lemmy_gamma:
 +    image: lemmy-federation:latest
 +    environment:
 +      - LEMMY_HOSTNAME=lemmy_gamma:8560
 +      - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_gamma:5432/lemmy
 +      - LEMMY_JWT_SECRET=changeme
 +      - LEMMY_FRONT_END_DIR=/app/dist
 +      - LEMMY_FEDERATION__ENABLED=true
 +      - LEMMY_FEDERATION__TLS_ENABLED=false
 +      - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy_alpha,lemmy_beta
 +      - LEMMY_PORT=8560
 +      - LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma
 +      - LEMMY_SETUP__ADMIN_PASSWORD=lemmy
 +      - LEMMY_SETUP__SITE_NAME=lemmy_gamma
 +      - RUST_BACKTRACE=1
 +      - RUST_LOG=debug
 +    restart: always
 +    depends_on:
 +      - postgres_gamma
 +  postgres_gamma:
 +    image: postgres:12-alpine
 +    environment:
 +      - POSTGRES_USER=lemmy
 +      - POSTGRES_PASSWORD=password
 +      - POSTGRES_DB=lemmy
 +    volumes:
 +      - ./volumes/postgres_gamma:/var/lib/postgresql/data
 +    restart: always
-       - ./volumes/pictshare_gamma:/usr/share/nginx/html/data
++  pictrs_gamma:
++    image: asonix/pictrs:v0.1.13-r0
++    user: 991:991
 +    volumes:
++      - ./volumes/pictrs_gamma:/mnt
 +    restart: always
 +
 +  iframely:
 +    image: dogbin/iframely:latest
 +    volumes:
 +      - ../iframely.config.local.js:/iframely/config.local.js:ro
 +    restart: always
index a73b0954e24fc18e7d4f0a005c783fb10a8de838,0000000000000000000000000000000000000000..25160eb6c497db913414efdf95df32b10f1ac17d
mode 100644,000000..100644
--- /dev/null
@@@ -1,110 -1,0 +1,125 @@@
-         location /pictshare/ {
-             proxy_pass http://pictshare_alpha:80/;
 +events {
 +    worker_connections 1024;
 +}
 +
 +http {
 +    server {
 +        listen 8540;
 +        server_name 127.0.0.1;
 +        access_log  off;
 +
 +        # Upload limit for pictshare
 +        client_max_body_size 50M;
 +
 +        location / {
 +            proxy_pass http://lemmy_alpha:8540;
 +            proxy_set_header X-Real-IP $remote_addr;
 +            proxy_set_header Host $host;
 +            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 +
 +            # WebSocket support
 +            proxy_http_version 1.1;
 +            proxy_set_header Upgrade $http_upgrade;
 +            proxy_set_header Connection "upgrade";
 +        }
 +
-         location /pictshare/ {
-             proxy_pass http://pictshare_beta:80/;
++        # pict-rs images
++        location /pictrs {
++          location /pictrs/image {
++            proxy_pass http://pictrs_alpha:8080/image;
 +            proxy_set_header X-Real-IP $remote_addr;
 +            proxy_set_header Host $host;
 +            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
++          }
++          # Block the import
++          return 403;
 +        }
 +
 +        location /iframely/ {
 +            proxy_pass http://iframely:80/;
 +            proxy_set_header X-Real-IP $remote_addr;
 +            proxy_set_header Host $host;
 +            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 +        }
 +    }
 +
 +    server {
 +        listen 8550;
 +        server_name 127.0.0.1;
 +        access_log off;
 +
 +        # Upload limit for pictshare
 +        client_max_body_size 50M;
 +
 +        location / {
 +            proxy_pass http://lemmy_beta:8550;
 +            proxy_set_header X-Real-IP $remote_addr;
 +            proxy_set_header Host $host;
 +            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 +
 +            # WebSocket support
 +            proxy_http_version 1.1;
 +            proxy_set_header Upgrade $http_upgrade;
 +            proxy_set_header Connection "upgrade";
 +        }
 +
-         location /pictshare/ {
-             proxy_pass http://pictshare_gamma:80/;
++        # pict-rs images
++        location /pictrs {
++          location /pictrs/image {
++            proxy_pass http://pictrs_beta:8080/image;
 +            proxy_set_header X-Real-IP $remote_addr;
 +            proxy_set_header Host $host;
 +            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
++          }
++          # Block the import
++          return 403;
 +        }
 +
 +        location /iframely/ {
 +            proxy_pass http://iframely:80/;
 +            proxy_set_header X-Real-IP $remote_addr;
 +            proxy_set_header Host $host;
 +            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 +        }
 +    }
 +
 +    server {
 +        listen 8560;
 +        server_name 127.0.0.1;
 +        access_log off;
 +
 +        # Upload limit for pictshare
 +        client_max_body_size 50M;
 +
 +        location / {
 +            proxy_pass http://lemmy_gamma:8560;
 +            proxy_set_header X-Real-IP $remote_addr;
 +            proxy_set_header Host $host;
 +            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 +
 +            # WebSocket support
 +            proxy_http_version 1.1;
 +            proxy_set_header Upgrade $http_upgrade;
 +            proxy_set_header Connection "upgrade";
 +        }
 +
++        # pict-rs images
++        location /pictrs {
++          location /pictrs/image {
++            proxy_pass http://pictrs_gamma:8080/image;
 +            proxy_set_header X-Real-IP $remote_addr;
 +            proxy_set_header Host $host;
 +            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
++          }
++          # Block the import
++          return 403;
 +        }
 +
 +        location /iframely/ {
 +            proxy_pass http://iframely:80/;
 +            proxy_set_header X-Real-IP $remote_addr;
 +            proxy_set_header Host $host;
 +            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 +        }
 +    }
 +}
index 206a324021b2dcb33b98f4249e7caecada50a70a,0000000000000000000000000000000000000000..bc73fff63140093df71368a67997f97de96f9b98
mode 100755,000000..100755
--- /dev/null
@@@ -1,23 -1,0 +1,28 @@@
 +#!/bin/bash
 +set -e
 +
 +# already start rust build in the background
 +pushd ../../server/ || exit
 +cargo build &
 +popd || exit
 +
 +if [ "$1" = "-yarn" ]; then
 +  pushd ../../ui/ || exit
 +  yarn
 +  yarn build
 +  popd || exit
 +fi
 +
 +# wait for rust build to finish
 +pushd ../../server/ || exit
 +cargo build
 +popd || exit
 +
 +sudo docker build ../../ --file Dockerfile -t lemmy-federation:latest
 +
++for Item in alpha beta gamma ; do
++  sudo mkdir -p volumes/pictrs_$Item
++  sudo chown -R 991:991 volumes/pictrs_$Item
++done
++
 +sudo docker-compose up
index 55ec0509b3a6b02e4e328413cfcecb182a1c9369,f91b665b89a2f28f6c42ff56e1f9960e67c38446..f124396b7e3200ab361bfbe9b4976cc4da9fa38b
@@@ -1,18 -1,16 +1,18 @@@
  # This file is automatically @generated by Cargo.
  # It is not intended for manual editing.
  [[package]]
 -name = "activitypub"
 -version = "0.2.0"
 +name = "activitystreams"
 +version = "0.6.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "464cb473bfb402b857cc15b1153974c203a43f1485da4dda15cd17a738548958"
  dependencies = [
 - "activitystreams-derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "activitystreams-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "activitystreams-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 + "activitystreams-derive",
 + "chrono",
 + "mime",
-  "serde 1.0.111",
-  "serde_json 1.0.53",
++ "serde 1.0.114",
++ "serde_json",
 + "thiserror",
 + "url",
  ]
  
  [[package]]
@@@ -27,49 -24,51 +27,49 @@@ dependencies = 
  ]
  
  [[package]]
 -name = "activitystreams-traits"
 -version = "0.2.0"
 -source = "registry+https://github.com/rust-lang/crates.io-index"
 +name = "activitystreams-ext"
 +version = "0.1.0"
 +source = "git+https://git.asonix.dog/asonix/activitystreams-ext#e5c97f4ea9f60e49bc7ff27fb0fb515d3190fd25"
  dependencies = [
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 - "thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
 + "activitystreams-new",
-  "serde 1.0.111",
-  "serde_json 1.0.53",
++ "serde 1.0.114",
++ "serde_json",
  ]
  
  [[package]]
 -name = "activitystreams-types"
 -version = "0.3.0"
 -source = "registry+https://github.com/rust-lang/crates.io-index"
 +name = "activitystreams-new"
 +version = "0.1.0"
- source = "git+https://git.asonix.dog/asonix/activitystreams-sketch#05a2bdc98d5595b0a74fd79b7e1b19f382ad3139"
++source = "git+https://git.asonix.dog/asonix/activitystreams-sketch#99c7e9aa5596eda846a1ebd5978ca72d11d4c08a"
  dependencies = [
 - "activitystreams-derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "activitystreams-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
 - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 + "activitystreams",
-  "serde 1.0.111",
-  "serde_json 1.0.53",
++ "serde 1.0.114",
++ "serde_json",
 + "typed-builder",
  ]
  
  [[package]]
  name = "actix"
  version = "0.9.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "a4af87564ff659dee8f9981540cac9418c45e910c8072fdedd643a262a38fcaf"
  dependencies = [
 - "actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-rt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix_derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "derive_more 0.99.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "pin-project 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
 - "smallvec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "tokio 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 - "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "trust-dns-resolver 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)",
 + "actix-http",
 + "actix-rt",
 + "actix_derive",
 + "bitflags",
 + "bytes",
 + "crossbeam-channel",
 + "derive_more",
 + "futures",
-  "lazy_static 1.4.0",
++ "lazy_static",
 + "log",
 + "parking_lot",
 + "pin-project",
 + "smallvec",
 + "tokio",
 + "tokio-util 0.2.0",
 + "trust-dns-proto",
 + "trust-dns-resolver",
  ]
  
  [[package]]
@@@ -131,47 -126,46 +131,47 @@@ dependencies = 
  name = "actix-http"
  version = "1.0.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 -dependencies = [
 - "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-connect 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-rt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
 - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
 - "copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "derive_more 0.99.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
 - "failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "flate2 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "h2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "pin-project 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
 - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
 +checksum = "c16664cc4fdea8030837ad5a845eb231fb93fc3c5c171edfefb52fad92ce9019"
 +dependencies = [
 + "actix-codec",
 + "actix-connect",
 + "actix-rt",
 + "actix-service",
 + "actix-threadpool",
 + "actix-utils",
 + "base64 0.11.0",
 + "bitflags",
 + "brotli2",
 + "bytes",
 + "chrono",
 + "copyless",
 + "derive_more",
 + "either",
 + "encoding_rs",
 + "failure",
 + "flate2",
 + "futures-channel",
 + "futures-core",
 + "futures-util",
 + "fxhash",
 + "h2",
 + "http",
 + "httparse",
 + "indexmap",
 + "language-tags",
-  "lazy_static 1.4.0",
++ "lazy_static",
 + "log",
 + "mime",
 + "percent-encoding",
 + "pin-project",
 + "rand 0.7.3",
-  "regex 1.3.9",
-  "serde 1.0.111",
-  "serde_json 1.0.53",
++ "regex",
++ "serde 1.0.114",
++ "serde_json",
 + "serde_urlencoded",
 + "sha1",
 + "slab",
 + "time",
  ]
  
  [[package]]
@@@ -188,13 -181,12 +188,13 @@@ dependencies = 
  name = "actix-router"
  version = "0.2.4"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "9d7a10ca4d94e8c8e7a87c5173aba1b97ba9a6563ca02b0e1cd23531093d3ec8"
  dependencies = [
 - "bytestring 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 + "bytestring",
 + "http",
 + "log",
-  "regex 1.3.9",
-  "serde 1.0.111",
++ "regex",
++ "serde 1.0.114",
  ]
  
  [[package]]
@@@ -258,17 -246,16 +258,17 @@@ dependencies = 
  
  [[package]]
  name = "actix-threadpool"
 -version = "0.3.1"
 +version = "0.3.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "91164716d956745c79dcea5e66d2aa04506549958accefcede5368c70f2fd4ff"
  dependencies = [
 - "derive_more 0.99.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 + "derive_more",
 + "futures-channel",
-  "lazy_static 1.4.0",
++ "lazy_static",
 + "log",
 + "num_cpus",
 + "parking_lot",
 + "threadpool",
  ]
  
  [[package]]
@@@ -309,36 -294,35 +309,36 @@@ dependencies = 
  name = "actix-web"
  version = "2.0.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 -dependencies = [
 - "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-router 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-rt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-server 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-testing 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-web-codegen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "awc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "derive_more 0.99.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 - "pin-project 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
 - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
 - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 +checksum = "3158e822461040822f0dbf1735b9c2ce1f95f93b651d7a7aded00b1efbb1f635"
 +dependencies = [
 + "actix-codec",
 + "actix-http",
 + "actix-macros",
 + "actix-router",
 + "actix-rt",
 + "actix-server",
 + "actix-service",
 + "actix-testing",
 + "actix-threadpool",
 + "actix-tls",
 + "actix-utils",
 + "actix-web-codegen",
 + "awc",
 + "bytes",
 + "derive_more",
 + "encoding_rs",
 + "futures",
 + "fxhash",
 + "log",
 + "mime",
 + "net2",
 + "pin-project",
-  "regex 1.3.9",
-  "serde 1.0.111",
-  "serde_json 1.0.53",
++ "regex",
++ "serde 1.0.114",
++ "serde_json",
 + "serde_urlencoded",
 + "time",
 + "url",
  ]
  
  [[package]]
@@@ -371,44 -353,23 +371,35 @@@ dependencies = 
  name = "actix_derive"
  version = "0.5.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "b95aceadaf327f18f0df5962fedc1bde2f870566a0b9f65c89508a3b1f79334c"
  dependencies = [
 - "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
 + "proc-macro2",
 + "quote",
 + "syn",
 +]
 +
 +[[package]]
 +name = "addr2line"
- version = "0.12.1"
++version = "0.12.2"
 +source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543"
++checksum = "602d785912f476e480434627e8732e6766b760c045bbf897d9dfaa9f4fbd399c"
 +dependencies = [
 + "gimli",
  ]
  
  [[package]]
  name = "adler32"
--version = "1.0.4"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
- [[package]]
- name = "aho-corasick"
- version = "0.5.3"
++version = "1.1.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
- dependencies = [
-  "memchr 0.1.11",
- ]
++checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d"
  
  [[package]]
  name = "aho-corasick"
--version = "0.7.10"
++version = "0.7.13"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
++checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
  dependencies = [
-  "memchr 2.3.3",
 - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
++ "memchr",
  ]
  
  [[package]]
@@@ -422,18 -382,16 +413,15 @@@ dependencies = 
  
  [[package]]
  name = "arc-swap"
- version = "0.4.6"
 -version = "0.4.5"
++version = "0.4.7"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62"
++checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
  
  [[package]]
  name = "arrayvec"
--version = "0.4.12"
++version = "0.5.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
--dependencies = [
-  "nodrop",
 - "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
--]
++checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
  
  [[package]]
  name = "ascii_utils"
@@@ -443,15 -400,27 +431,29 @@@ checksum = "71938f30533e4d95a6d17aa5309
  
  [[package]]
  name = "async-trait"
- version = "0.1.32"
 -version = "0.1.30"
++version = "0.1.36"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "0eb7f9ad01405feb3c1dac82463038945cf88eea4569acaf3ad662233496dd96"
++checksum = "a265e3abeffdce30b2e26b7a11b222fe37c6067404001b434101457d0385eb92"
  dependencies = [
 - "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
 + "proc-macro2",
 + "quote",
 + "syn",
  ]
  
 - "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "webpki-roots 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ [[package]]
+ name = "attohttpc"
+ version = "0.14.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "93610ce1c035e8a273fe56a19852e42798f3c019ca2726e52d2971197f116525"
+ dependencies = [
++ "http",
++ "log",
++ "rustls",
++ "url",
++ "webpki",
++ "webpki-roots",
+ ]
  [[package]]
  name = "atty"
  version = "0.2.14"
@@@ -479,36 -445,42 +481,37 @@@ checksum = "f8aac770f1885fd7e387acedd76
  name = "awc"
  version = "1.0.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "d7601d4d1d7ef2335d6597a41b5fe069f6ab799b85f53565ab390e7b7065aac5"
  dependencies = [
 - "actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-rt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "derive_more 0.99.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
 + "actix-codec",
 + "actix-http",
 + "actix-rt",
 + "actix-service",
 + "base64 0.11.0",
 + "bytes",
 + "derive_more",
 + "futures-core",
 + "log",
 + "mime",
 + "percent-encoding",
 + "rand 0.7.3",
-  "serde 1.0.111",
-  "serde_json 1.0.53",
++ "serde 1.0.114",
++ "serde_json",
 + "serde_urlencoded",
  ]
  
  [[package]]
  name = "backtrace"
- version = "0.3.48"
 -version = "0.3.46"
 -source = "registry+https://github.com/rust-lang/crates.io-index"
 -dependencies = [
 - "backtrace-sys 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
 - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 - "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
 -]
 -
 -[[package]]
 -name = "backtrace-sys"
 -version = "0.1.35"
++version = "0.3.49"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130"
++checksum = "05100821de9e028f12ae3d189176b41ee198341eb8f369956407fea2f5cc666c"
  dependencies = [
 - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
 - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 + "addr2line",
 + "cfg-if",
 + "libc",
++ "miniz_oxide",
 + "object",
 + "rustc-demangle",
  ]
  
  [[package]]
@@@ -538,20 -507,19 +541,20 @@@ checksum = "b41b7ea54a0c9d92199de89e20e
  
  [[package]]
  name = "base64"
- version = "0.12.1"
 -version = "0.12.0"
++version = "0.12.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42"
++checksum = "e223af0dc48c96d4f8342ec01a4974f139df863896b316681efd36742f22cc67"
  
  [[package]]
  name = "bcrypt"
 -version = "0.7.0"
 +version = "0.8.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "41b70db86f3c560199b0dada79a22b9a924622384abb2a756a9707ffcce077f2"
  dependencies = [
-  "base64 0.12.1",
 - "base64 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "blowfish 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
++ "base64 0.12.2",
 + "blowfish",
 + "byteorder",
 + "getrandom",
  ]
  
  [[package]]
@@@ -647,9 -604,8 +650,12 @@@ checksum = "08c48aae112d48ed9f069b33538
  
  [[package]]
  name = "bytes"
--version = "0.5.4"
++version = "0.5.5"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1"
++checksum = "118cf036fbb97d0816e3c34b2d7a1e8cfc60f68fcf63d550ddbe9bd5f59c213b"
++dependencies = [
++ "loom",
++]
  
  [[package]]
  name = "bytestring"
@@@ -676,12 -629,11 +682,12 @@@ checksum = "4785bdd1c96b2a846b2bd7cc02e
  name = "chrono"
  version = "0.4.11"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
  dependencies = [
 - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
 - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
 + "num-integer",
-  "num-traits 0.2.11",
-  "serde 1.0.111",
++ "num-traits 0.2.12",
++ "serde 1.0.114",
 + "time",
  ]
  
  [[package]]
@@@ -712,33 -662,27 +718,29 @@@ dependencies = 
  name = "comrak"
  version = "0.7.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "e17058cc536cf290563e88787d7b9e6030ce4742943017cc2ffb71f88034021c"
  dependencies = [
 - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "entities 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 - "twoway 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "typed-arena 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 + "clap",
 + "entities",
-  "lazy_static 1.4.0",
++ "lazy_static",
 + "pest",
 + "pest_derive",
-  "regex 1.3.9",
++ "regex",
 + "twoway",
 + "typed-arena",
 + "unicode_categories",
  ]
  
  [[package]]
  name = "config"
  version = "0.10.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3"
  dependencies = [
-  "lazy_static 1.4.0",
-  "nom 5.1.1",
-  "rust-ini",
-  "serde 1.0.111",
-  "serde-hjson 0.9.1",
-  "serde_json 1.0.53",
-  "toml",
-  "yaml-rust",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "nom 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde-hjson 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
++ "lazy_static",
++ "nom 5.1.2",
++ "serde 1.0.114",
++ "serde-hjson",
  ]
  
  [[package]]
@@@ -786,42 -725,10 +788,11 @@@ dependencies = 
  name = "crossbeam-utils"
  version = "0.7.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
  dependencies = [
 - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 + "autocfg 1.0.0",
 + "cfg-if",
-  "lazy_static 1.4.0",
- ]
- [[package]]
- name = "curl"
- version = "0.4.29"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "762e34611d2d5233a506a79072be944fddd057db2f18e04c0d6fa79e3fd466fd"
- dependencies = [
-  "curl-sys",
-  "libc",
-  "openssl-probe",
-  "openssl-sys",
-  "schannel",
-  "socket2",
-  "winapi 0.3.8",
- ]
- [[package]]
- name = "curl-sys"
- version = "0.4.31+curl-7.70.0"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "dcd62757cc4f5ab9404bc6ca9f0ae447e729a1403948ce5106bd588ceac6a3b0"
- dependencies = [
-  "cc",
-  "libc",
-  "libnghttp2-sys",
-  "libz-sys",
-  "openssl-sys",
-  "pkg-config",
-  "vcpkg",
-  "winapi 0.3.8",
++ "lazy_static",
  ]
  
  [[package]]
@@@ -886,28 -788,25 +857,28 @@@ dependencies = 
  
  [[package]]
  name = "derive_more"
- version = "0.99.7"
 -version = "0.99.5"
++version = "0.99.8"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "2127768764f1556535c01b5326ef94bd60ff08dcfbdc544d53e69ed155610f5d"
++checksum = "bc655351f820d774679da6cdc23355a93de496867d8203496675162e17b1d671"
  dependencies = [
 - "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
 + "proc-macro2",
 + "quote",
 + "syn",
  ]
  
  [[package]]
  name = "diesel"
--version = "1.4.4"
++version = "1.4.5"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "33d7ca63eb2efea87a7f56a283acc49e2ce4b2bd54adf7465dc1d81fef13d8fc"
++checksum = "3e2de9deab977a153492a1468d1b1c0662c1cf39e5ea87d0c060ecd59ef18d8c"
  dependencies = [
 - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
 - "diesel_derives 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "pq-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 - "r2d2 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)",
 + "bitflags",
 + "byteorder",
 + "chrono",
 + "diesel_derives",
 + "pq-sys",
 + "r2d2",
-  "serde_json 1.0.53",
++ "serde_json",
  ]
  
  [[package]]
@@@ -935,23 -832,10 +906,11 @@@ dependencies = 
  name = "digest"
  version = "0.8.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
  dependencies = [
 - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
 + "generic-array",
  ]
  
- [[package]]
- name = "docopt"
- version = "0.6.86"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "4a7ef30445607f6fc8720f0a0a2c7442284b629cf0d049286860fae23e71c4d9"
- dependencies = [
-  "lazy_static 0.2.11",
-  "regex 0.1.80",
-  "rustc-serialize",
-  "strsim 0.5.2",
- ]
  [[package]]
  name = "dotenv"
  version = "0.15.0"
@@@ -960,15 -843,8 +919,9 @@@ checksum = "77c90badedccf4105eca100756a
  
  [[package]]
  name = "dtoa"
- version = "0.2.2"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
- [[package]]
- name = "dtoa"
--version = "0.4.5"
++version = "0.4.6"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
++checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
  
  [[package]]
  name = "either"
@@@ -980,15 -855,14 +933,15 @@@ checksum = "bb1f6b1ce1c140482ea30ddd333
  name = "email"
  version = "0.0.20"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "91549a51bb0241165f13d57fc4c72cef063b4088fb078b019ecbf464a45f22e4"
  dependencies = [
 - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
 - "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
 - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 + "base64 0.9.3",
 + "chrono",
 + "encoding",
-  "lazy_static 1.4.0",
++ "lazy_static",
 + "rand 0.4.6",
 + "time",
 + "version_check 0.1.5",
  ]
  
  [[package]]
@@@ -1086,13 -950,12 +1039,13 @@@ dependencies = 
  name = "env_logger"
  version = "0.7.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
  dependencies = [
 - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
 - "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 - "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 + "atty",
 + "humantime",
 + "log",
-  "regex 1.3.9",
++ "regex",
 + "termcolor",
  ]
  
  [[package]]
@@@ -1264,33 -1105,30 +1217,46 @@@ dependencies = 
  
  [[package]]
  name = "futures-util"
 -version = "0.3.4"
 +version = "0.3.5"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6"
  dependencies = [
 - "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)",
 - "proc-macro-nested 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 + "futures-channel",
 + "futures-core",
 + "futures-io",
 + "futures-macro",
 + "futures-sink",
 + "futures-task",
-  "memchr 2.3.3",
++ "memchr",
 + "pin-project",
 + "pin-utils",
 + "proc-macro-hack",
 + "proc-macro-nested",
 + "slab",
  ]
  
  [[package]]
  name = "fxhash"
  version = "0.2.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
 +dependencies = [
 + "byteorder",
 +]
 +
++[[package]]
++name = "generator"
++version = "0.6.21"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "add72f17bb81521258fcc8a7a3245b1e184e916bfbe34f0ea89558f440df5c68"
+ dependencies = [
++ "cc",
++ "libc",
++ "log",
++ "rustc_version",
++ "winapi 0.3.8",
+ ]
  [[package]]
  name = "generic-array"
  version = "0.12.3"
@@@ -1347,25 -1175,12 +1313,13 @@@ dependencies = 
  
  [[package]]
  name = "hermit-abi"
- version = "0.1.13"
 -version = "0.1.11"
++version = "0.1.14"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
++checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
  dependencies = [
 - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 + "libc",
  ]
  
- [[package]]
- name = "hjson"
- version = "0.8.2"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "0849d73a64ec77d1c8354aff489cf31943c4b4d3716de1eabfba572c70fde530"
- dependencies = [
-  "docopt",
-  "serde 0.8.23",
-  "serde-hjson 0.8.2",
-  "serde_json 0.8.6",
- ]
  [[package]]
  name = "hostname"
  version = "0.1.5"
@@@ -1397,21 -1209,10 +1351,21 @@@ checksum = "e9025058dae765dee5070ec375f
  name = "http"
  version = "0.2.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
  dependencies = [
 - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
 - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 + "bytes",
 + "fnv",
-  "itoa 0.4.5",
++ "itoa",
 +]
 +
 +[[package]]
 +name = "http-signature-normalization"
 +version = "0.5.1"
 +source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "648233553603e7bb55bc1ea08a514661e212c09c10f6434507894273d8b5e773"
 +dependencies = [
 + "chrono",
 + "thiserror",
  ]
  
  [[package]]
@@@ -1466,61 -1261,19 +1420,30 @@@ dependencies = 
  
  [[package]]
  name = "ipconfig"
 -version = "0.2.1"
 +version = "0.2.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
  dependencies = [
 - "socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
 - "widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
 + "socket2",
 + "widestring",
 + "winapi 0.3.8",
 + "winreg",
 +]
 +
- [[package]]
- name = "isahc"
- version = "0.9.3"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "098c47b6176a9b667292810105999d6029d8338819f299584677e8a125e549c2"
- dependencies = [
-  "bytes",
-  "crossbeam-channel",
-  "crossbeam-utils",
-  "curl",
-  "curl-sys",
-  "encoding_rs",
-  "futures-channel",
-  "futures-io",
-  "futures-util",
-  "http",
-  "lazy_static 1.4.0",
-  "log",
-  "mime",
-  "slab",
-  "sluice",
-  "tracing",
-  "tracing-futures",
- ]
 +[[package]]
 +name = "itertools"
 +version = "0.9.0"
 +source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
 +dependencies = [
 + "either",
  ]
  
  [[package]]
  name = "itoa"
- version = "0.1.1"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
- [[package]]
- name = "itoa"
--version = "0.4.5"
++version = "0.4.6"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
++checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
  
  [[package]]
  name = "js-sys"
@@@ -1533,16 -1285,15 +1456,16 @@@ dependencies = 
  
  [[package]]
  name = "jsonwebtoken"
--version = "7.1.0"
++version = "7.1.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "d11f9e80a85927748a334df8e4f6782a04033517bb28f3863a563daad882da7f"
++checksum = "b1f325ae57ddcf609f02d891486ce740f5bbd0cc3e93f9bffaacdf6594b21404"
  dependencies = [
-  "base64 0.11.0",
 - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "pem 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 - "simple_asn1 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
++ "base64 0.12.2",
 + "pem",
 + "ring",
-  "serde 1.0.111",
-  "serde_json 1.0.53",
++ "serde 1.0.114",
++ "serde_json",
 + "simple_asn1",
  ]
  
  [[package]]
@@@ -1559,14 -1309,7 +1482,8 @@@ dependencies = 
  name = "language-tags"
  version = "0.2.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
  
- [[package]]
- name = "lazy_static"
- version = "0.2.11"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
  [[package]]
  name = "lazy_static"
  version = "1.4.0"
@@@ -1577,67 -1319,56 +1494,66 @@@ checksum = "e2abad23fbc42b3700f2f279844
  name = "lemmy_server"
  version = "0.0.1"
  dependencies = [
 - "activitypub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-rt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "actix-web-actors 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "attohttpc 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "bcrypt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
 - "comrak 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "diesel 1.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "jsonwebtoken 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lettre 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lettre_email 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 - "rss 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 - "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "strum 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "strum_macros 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "tokio 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 + "activitystreams",
 + "activitystreams-ext",
 + "activitystreams-new",
 + "actix",
 + "actix-files",
 + "actix-rt",
 + "actix-web",
 + "actix-web-actors",
-  "base64 0.12.1",
++ "attohttpc",
++ "base64 0.12.2",
 + "bcrypt",
 + "chrono",
 + "comrak",
 + "config",
 + "diesel",
 + "diesel_migrations",
 + "dotenv",
 + "env_logger",
 + "failure",
 + "futures",
-  "hjson",
 + "htmlescape",
 + "http",
 + "http-signature-normalization",
-  "isahc",
 + "itertools",
 + "jsonwebtoken",
-  "lazy_static 1.4.0",
++ "lazy_static",
 + "lettre",
 + "lettre_email",
 + "log",
 + "openssl",
 + "percent-encoding",
 + "rand 0.7.3",
-  "regex 1.3.9",
++ "regex",
 + "rss",
-  "serde 1.0.111",
-  "serde_json 1.0.53",
++ "serde 1.0.114",
++ "serde_json",
 + "sha2",
 + "strum",
 + "strum_macros",
 + "tokio",
 + "url",
 + "uuid 0.8.1",
  ]
  
  [[package]]
  name = "lettre"
  version = "0.9.3"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "bf43f3202a879fbdab4ecafec3349b0139f81d31c626246d53bcbb546253ffaa"
  dependencies = [
 - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "fast_chemail 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
 - "hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 + "base64 0.10.1",
 + "bufstream",
 + "fast_chemail",
 + "hostname 0.1.5",
 + "log",
 + "native-tls",
 + "nom 4.2.3",
-  "serde 1.0.111",
++ "serde 1.0.114",
 + "serde_derive",
-  "serde_json 1.0.53",
++ "serde_json",
  ]
  
  [[package]]
@@@ -1656,45 -1386,21 +1572,23 @@@ dependencies = 
  
  [[package]]
  name = "lexical-core"
--version = "0.6.2"
++version = "0.7.4"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "d7043aa5c05dd34fb73b47acb8c3708eac428de4545ea3682ed2f11293ebd890"
++checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
  dependencies = [
 - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
 - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "ryu 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 + "arrayvec",
++ "bitflags",
 + "cfg-if",
-  "rustc_version",
 + "ryu",
 + "static_assertions",
  ]
  
  [[package]]
  name = "libc"
 -version = "0.2.69"
 +version = "0.2.71"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
  
- [[package]]
- name = "libnghttp2-sys"
- version = "0.1.4+1.41.0"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "03624ec6df166e79e139a2310ca213283d6b3c30810c54844f307086d4488df1"
- dependencies = [
-  "cc",
-  "libc",
- ]
- [[package]]
- name = "libz-sys"
- version = "1.0.25"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
- dependencies = [
-  "cc",
-  "libc",
-  "pkg-config",
-  "vcpkg",
- ]
  [[package]]
  name = "linked-hash-map"
  version = "0.3.0"
@@@ -1724,11 -1427,10 +1618,22 @@@ dependencies = 
  name = "log"
  version = "0.4.8"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
  dependencies = [
 - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 + "cfg-if",
 +]
 +
++[[package]]
++name = "loom"
++version = "0.3.4"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "4ecc775857611e1df29abba5c41355cdf540e7e9d4acfdf0f355eefee82330b7"
++dependencies = [
++ "cfg-if",
++ "generator",
++ "scoped-tls",
+ ]
  [[package]]
  name = "lru-cache"
  version = "0.1.2"
@@@ -1760,17 -1458,7 +1665,8 @@@ checksum = "7ffc5c5338469d4d3ea17d269fa
  name = "maybe-uninit"
  version = "2.0.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
  
- [[package]]
- name = "memchr"
- version = "0.1.11"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
- dependencies = [
-  "libc",
- ]
  [[package]]
  name = "memchr"
  version = "2.3.3"
@@@ -1816,11 -1499,10 +1712,11 @@@ dependencies = 
  
  [[package]]
  name = "miniz_oxide"
--version = "0.3.6"
++version = "0.3.7"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5"
++checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
  dependencies = [
 - "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 + "adler32",
  ]
  
  [[package]]
@@@ -1869,119 -1548,97 +1765,113 @@@ dependencies = 
  name = "native-tls"
  version = "0.2.4"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d"
  dependencies = [
-  "lazy_static 1.4.0",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "openssl 0.10.29 (registry+https://github.com/rust-lang/crates.io-index)",
 - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)",
 - "schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
 - "security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
++ "lazy_static",
 + "libc",
 + "log",
 + "openssl",
 + "openssl-probe",
 + "openssl-sys",
 + "schannel",
 + "security-framework",
 + "security-framework-sys",
 + "tempfile",
  ]
  
  [[package]]
  name = "net2"
 -version = "0.2.33"
 +version = "0.2.34"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7"
  dependencies = [
 - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 + "cfg-if",
 + "libc",
 + "winapi 0.3.8",
  ]
  
--[[package]]
--name = "nodrop"
--version = "0.1.14"
--source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
--
  [[package]]
  name = "nom"
  version = "4.2.3"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
  dependencies = [
-  "memchr 2.3.3",
 - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
++ "memchr",
 + "version_check 0.1.5",
  ]
  
  [[package]]
  name = "nom"
--version = "5.1.1"
++version = "5.1.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6"
++checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
  dependencies = [
 - "lexical-core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
 + "lexical-core",
-  "memchr 2.3.3",
++ "memchr",
 + "version_check 0.9.2",
  ]
  
  [[package]]
  name = "num-bigint"
  version = "0.2.6"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
  dependencies = [
 - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
 - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
 + "autocfg 1.0.0",
 + "num-integer",
-  "num-traits 0.2.11",
++ "num-traits 0.2.12",
  ]
  
  [[package]]
  name = "num-integer"
--version = "0.1.42"
++version = "0.1.43"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
++checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
  dependencies = [
 - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
 + "autocfg 1.0.0",
-  "num-traits 0.2.11",
++ "num-traits 0.2.12",
  ]
  
  [[package]]
  name = "num-traits"
  version = "0.1.43"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
  dependencies = [
-  "num-traits 0.2.11",
 - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
++ "num-traits 0.2.12",
  ]
  
  [[package]]
  name = "num-traits"
--version = "0.2.11"
++version = "0.2.12"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
++checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
  dependencies = [
 - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 + "autocfg 1.0.0",
  ]
  
  [[package]]
  name = "num_cpus"
  version = "1.13.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
  dependencies = [
 - "hermit-abi 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
 - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 + "hermit-abi",
 + "libc",
  ]
  
- version = "0.19.0"
 +[[package]]
 +name = "object"
- checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2"
++version = "0.20.0"
 +source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
 +
 +[[package]]
 +name = "once_cell"
 +version = "1.4.0"
 +source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
 +
  [[package]]
  name = "opaque-debug"
  version = "0.2.3"
@@@ -1992,14 -1648,13 +1882,14 @@@ checksum = "2839e79665f131bdb5782e51f2c
  name = "openssl"
  version = "0.10.29"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "cee6d85f4cb4c4f59a6a85d5b68a233d280c82e29e822913b9c8b129fbf20bdd"
  dependencies = [
 - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 - "openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)",
 + "bitflags",
 + "cfg-if",
 + "foreign-types",
-  "lazy_static 1.4.0",
++ "lazy_static",
 + "libc",
 + "openssl-sys",
  ]
  
  [[package]]
@@@ -2010,15 -1664,14 +1900,15 @@@ checksum = "77af24da69f9d9341038eba93a0
  
  [[package]]
  name = "openssl-sys"
- version = "0.9.57"
+ version = "0.9.58"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "7410fef80af8ac071d4f63755c0ab89ac3df0fd1ea91f1d1f37cf5cec4395990"
++checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de"
  dependencies = [
 - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
 - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 - "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
 - "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 + "autocfg 1.0.0",
 + "cc",
 + "libc",
 + "pkg-config",
 + "vcpkg",
  ]
  
  [[package]]
@@@ -2047,13 -1698,12 +1937,13 @@@ dependencies = 
  
  [[package]]
  name = "pem"
--version = "0.7.0"
++version = "0.8.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "a1581760c757a756a41f0ee3ff01256227bdf64cb752839779b95ffb01c59793"
++checksum = "59698ea79df9bf77104aefd39cc3ec990cb9693fb59c3b0a70ddf2646fdffb4b"
  dependencies = [
-  "base64 0.11.0",
-  "lazy_static 1.4.0",
-  "regex 1.3.9",
 - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
++ "base64 0.12.2",
++ "once_cell",
++ "regex",
  ]
  
  [[package]]
@@@ -2107,29 -1752,26 +1997,29 @@@ dependencies = 
  
  [[package]]
  name = "pin-project"
- version = "0.4.17"
 -version = "0.4.9"
++version = "0.4.22"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "edc93aeee735e60ecb40cf740eb319ff23eab1c5748abfdb5c180e4ce49f7791"
++checksum = "12e3a6cdbfe94a5e4572812a0201f8c0ed98c1c452c7b8563ce2276988ef9c17"
  dependencies = [
 - "pin-project-internal 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
 + "pin-project-internal",
  ]
  
  [[package]]
  name = "pin-project-internal"
- version = "0.4.17"
 -version = "0.4.9"
++version = "0.4.22"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "e58db2081ba5b4c93bd6be09c40fd36cb9193a8336c384f3b40012e531aa7e40"
++checksum = "6a0ffd45cf79d88737d7cc85bfd5d2894bee1139b356e616fe85dc389c61aaf7"
  dependencies = [
 - "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
 + "proc-macro2",
 + "quote",
 + "syn",
  ]
  
  [[package]]
  name = "pin-project-lite"
- version = "0.1.6"
 -version = "0.1.4"
++version = "0.1.7"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "9df32da11d84f3a7d70205549562966279adb900e080fad3dccd8e64afccf0ad"
++checksum = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715"
  
  [[package]]
  name = "pin-utils"
@@@ -2166,9 -1803,8 +2056,9 @@@ checksum = "7e0456befd48169b9f13ef0f0ad
  
  [[package]]
  name = "proc-macro-nested"
--version = "0.1.4"
++version = "0.1.6"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694"
++checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
  
  [[package]]
  name = "proc-macro2"
@@@ -2189,19 -1823,17 +2079,19 @@@ checksum = "a1d01941d82fa2ab50be1e79e67
  name = "quick-xml"
  version = "0.17.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "fe1e430bdcf30c9fdc25053b9c459bb1a4672af4617b6c783d7d91dc17c6bbb0"
  dependencies = [
 - "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
 - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 + "encoding_rs",
-  "memchr 2.3.3",
++ "memchr",
  ]
  
  [[package]]
  name = "quote"
- version = "1.0.6"
 -version = "1.0.3"
++version = "1.0.7"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
++checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
  dependencies = [
 - "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 + "proc-macro2",
  ]
  
  [[package]]
@@@ -2388,52 -2003,29 +2278,33 @@@ dependencies = 
  name = "redox_syscall"
  version = "0.1.56"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
  
- [[package]]
- name = "regex"
- version = "0.1.80"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
- dependencies = [
-  "aho-corasick 0.5.3",
-  "memchr 0.1.11",
-  "regex-syntax 0.3.9",
-  "thread_local 0.2.7",
-  "utf8-ranges",
- ]
  [[package]]
  name = "regex"
 -version = "1.3.7"
 +version = "1.3.9"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
  dependencies = [
-  "aho-corasick 0.7.10",
-  "memchr 2.3.3",
-  "regex-syntax 0.6.18",
-  "thread_local 1.0.1",
 - "aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
 - "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
++ "aho-corasick",
++ "memchr",
++ "regex-syntax",
++ "thread_local",
  ]
  
- [[package]]
- name = "regex-syntax"
- version = "0.3.9"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
  [[package]]
  name = "regex-syntax"
 -version = "0.6.17"
 +version = "0.6.18"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
  
  [[package]]
  name = "remove_dir_all"
--version = "0.5.2"
++version = "0.5.3"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
++checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
  dependencies = [
 - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 + "winapi 0.3.8",
  ]
  
  [[package]]
@@@ -2448,61 -2039,56 +2319,62 @@@ dependencies = 
  
  [[package]]
  name = "ring"
- version = "0.16.14"
 -version = "0.16.12"
++version = "0.16.15"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "06b3fefa4f12272808f809a0af618501fdaba41a58963c5fb72238ab0be09603"
++checksum = "952cd6b98c85bbc30efa1ba5783b8abf12fec8b3287ffa52605b9432313e34e4"
  dependencies = [
 - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "web-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
 - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 + "cc",
 + "libc",
 + "once_cell",
 + "spin",
 + "untrusted",
 + "web-sys",
 + "winapi 0.3.8",
  ]
  
  [[package]]
  name = "rss"
  version = "1.9.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "99979205510c60f80a119dedbabd0b8426517384edf205322f8bcd51796bcef9"
  dependencies = [
 - "derive_builder 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "quick-xml 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
 + "derive_builder",
 + "quick-xml",
  ]
  
- [[package]]
- name = "rust-ini"
- version = "0.13.0"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
  [[package]]
  name = "rustc-demangle"
  version = "0.1.16"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
  
- [[package]]
- name = "rustc-serialize"
- version = "0.3.24"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
  [[package]]
  name = "rustc_version"
  version = "0.2.3"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
  dependencies = [
 - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 + "semver",
  ]
  
 - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)",
 - "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ [[package]]
+ name = "rustls"
+ version = "0.17.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1"
+ dependencies = [
++ "base64 0.11.0",
++ "log",
++ "ring",
++ "sct",
++ "webpki",
+ ]
  [[package]]
  name = "ryu"
 -version = "1.0.3"
 +version = "1.0.5"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
  
  [[package]]
  name = "safemem"
@@@ -2514,27 -2099,33 +2386,43 @@@ checksum = "ef703b7cb59335eae2eb93ceb66
  name = "schannel"
  version = "0.1.19"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
  dependencies = [
-  "lazy_static 1.4.0",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
++ "lazy_static",
 + "winapi 0.3.8",
  ]
  
  [[package]]
  name = "scheduled-thread-pool"
  version = "0.2.4"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "0988d7fdf88d5e5fcf5923a0f1e8ab345f3e98ab4bc6bc45a2d5ff7f7458fbf6"
  dependencies = [
 - "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 + "parking_lot",
  ]
  
++[[package]]
++name = "scoped-tls"
++version = "0.1.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
++
  [[package]]
  name = "scopeguard"
  version = "1.1.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
  
 - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)",
 - "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ [[package]]
+ name = "sct"
+ version = "0.6.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c"
+ dependencies = [
++ "ring",
++ "untrusted",
+ ]
  [[package]]
  name = "security-framework"
  version = "0.4.4"
@@@ -2581,72 -2167,42 +2469,47 @@@ checksum = "9dad3f759919b92c3068c696c15
  
  [[package]]
  name = "serde"
- version = "1.0.111"
 -version = "1.0.106"
++version = "1.0.114"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d"
++checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
  dependencies = [
 - "serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 + "serde_derive",
  ]
  
- [[package]]
- name = "serde-hjson"
- version = "0.8.2"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "0b833c5ad67d52ced5f5938b2980f32a9c1c5ef047f0b4fb3127e7a423c76153"
- dependencies = [
-  "lazy_static 0.2.11",
-  "linked-hash-map 0.3.0",
-  "num-traits 0.1.43",
-  "regex 1.3.9",
-  "serde 0.8.23",
- ]
  [[package]]
  name = "serde-hjson"
  version = "0.9.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8"
  dependencies = [
-  "lazy_static 1.4.0",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
 - "regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
++ "lazy_static",
 + "linked-hash-map 0.3.0",
 + "num-traits 0.1.43",
-  "regex 1.3.9",
++ "regex",
 + "serde 0.8.23",
  ]
  
  [[package]]
  name = "serde_derive"
- version = "1.0.111"
 -version = "1.0.106"
++version = "1.0.114"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
++checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e"
  dependencies = [
 - "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
 + "proc-macro2",
 + "quote",
 + "syn",
  ]
  
  [[package]]
  name = "serde_json"
- version = "0.8.6"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "67f7d2e9edc3523a9c8ec8cd6ec481b3a27810aafee3e625d311febd3e656b4c"
- dependencies = [
-  "dtoa 0.2.2",
-  "itoa 0.1.1",
-  "num-traits 0.1.43",
-  "serde 0.8.23",
- ]
- [[package]]
- name = "serde_json"
- version = "1.0.53"
 -version = "1.0.52"
++version = "1.0.55"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2"
++checksum = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226"
  dependencies = [
 - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "ryu 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 + "indexmap",
-  "itoa 0.4.5",
++ "itoa",
 + "ryu",
-  "serde 1.0.111",
++ "serde 1.0.114",
  ]
  
  [[package]]
@@@ -2662,12 -2217,11 +2525,12 @@@ dependencies = 
  name = "serde_urlencoded"
  version = "0.6.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
  dependencies = [
-  "dtoa 0.4.5",
-  "itoa 0.4.5",
-  "serde 1.0.111",
 - "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 - "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
 - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
++ "dtoa",
++ "itoa",
++ "serde 1.0.114",
 + "url",
  ]
  
  [[package]]
@@@ -2714,36 -2264,21 +2577,24 @@@ dependencies = 
  name = "simple_asn1"
  version = "0.4.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "2b25ecba7165254f0c97d6c22a64b1122a03634b18d20a34daf21e18f892e618"
  dependencies = [
 - "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
 - "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
 + "chrono",
 + "num-bigint",
-  "num-traits 0.2.11",
++ "num-traits 0.2.12",
  ]
  
  [[package]]
  name = "slab"
  version = "0.4.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
  
- [[package]]
- name = "sluice"
- version = "0.5.2"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "fed13b7cb46f13a15db2c4740f087a848acc8b31af89f95844d40137451f89b1"
- dependencies = [
-  "futures-channel",
-  "futures-core",
-  "futures-io",
-  "futures-util",
- ]
  [[package]]
  name = "smallvec"
 -version = "1.3.0"
 +version = "1.4.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
  
  [[package]]
  name = "socket2"
@@@ -2765,15 -2298,8 +2616,9 @@@ checksum = "6e63cff320ae2c57904679ba7cb
  
  [[package]]
  name = "static_assertions"
--version = "0.3.4"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3"
- [[package]]
- name = "strsim"
- version = "0.5.2"
++version = "1.1.0"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c"
++checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
  
  [[package]]
  name = "strsim"
@@@ -2807,25 -2329,23 +2652,25 @@@ dependencies = 
  
  [[package]]
  name = "syn"
- version = "1.0.30"
 -version = "1.0.17"
++version = "1.0.33"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2"
++checksum = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd"
  dependencies = [
 - "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 + "proc-macro2",
 + "quote",
 + "unicode-xid",
  ]
  
  [[package]]
  name = "synstructure"
--version = "0.12.3"
++version = "0.12.4"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
++checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
  dependencies = [
 - "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
 - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 + "proc-macro2",
 + "quote",
 + "syn",
 + "unicode-xid",
  ]
  
  [[package]]
@@@ -2862,50 -2379,28 +2707,31 @@@ dependencies = 
  
  [[package]]
  name = "thiserror"
--version = "1.0.19"
++version = "1.0.20"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "b13f926965ad00595dd129fa12823b04bbf866e9085ab0a5f2b05b850fbfc344"
++checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08"
  dependencies = [
 - "thiserror-impl 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
 + "thiserror-impl",
  ]
  
  [[package]]
  name = "thiserror-impl"
--version = "1.0.19"
++version = "1.0.20"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479"
++checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793"
  dependencies = [
 - "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
 + "proc-macro2",
 + "quote",
 + "syn",
  ]
  
- [[package]]
- name = "thread-id"
- version = "2.0.0"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
- dependencies = [
-  "kernel32-sys",
-  "libc",
- ]
- [[package]]
- name = "thread_local"
- version = "0.2.7"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
- dependencies = [
-  "thread-id",
- ]
  [[package]]
  name = "thread_local"
  version = "1.0.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
  dependencies = [
-  "lazy_static 1.4.0",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
++ "lazy_static",
  ]
  
  [[package]]
@@@ -2919,33 -2413,32 +2745,39 @@@ dependencies = 
  
  [[package]]
  name = "time"
 -version = "0.1.42"
 +version = "0.1.43"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
  dependencies = [
 - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
 - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 + "libc",
 + "winapi 0.3.8",
  ]
  
++[[package]]
++name = "tinyvec"
++version = "0.3.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed"
++
  [[package]]
  name = "tokio"
 -version = "0.2.20"
 +version = "0.2.21"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "d099fa27b9702bed751524694adbe393e18b36b204da91eb1cbbbbb4a5ee2d58"
  dependencies = [
 - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
 - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
 - "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 + "bytes",
 + "fnv",
 + "futures-core",
 + "iovec",
-  "lazy_static 1.4.0",
++ "lazy_static",
 + "libc",
-  "memchr 2.3.3",
++ "memchr",
 + "mio",
 + "mio-uds",
 + "pin-project-lite",
 + "signal-hook-registry",
 + "slab",
 + "winapi 0.3.8",
  ]
  
  [[package]]
@@@ -2966,114 -2458,59 +2798,63 @@@ dependencies = 
  name = "tokio-util"
  version = "0.3.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
  dependencies = [
 - "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "tokio 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 + "bytes",
 + "futures-core",
 + "futures-sink",
 + "log",
 + "pin-project-lite",
 + "tokio",
  ]
  
- [[package]]
- name = "toml"
- version = "0.5.6"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
- dependencies = [
-  "serde 1.0.111",
- ]
- [[package]]
- name = "tracing"
- version = "0.1.15"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "a41f40ed0e162c911ac6fcb53ecdc8134c46905fdbbae8c50add462a538b495f"
- dependencies = [
-  "cfg-if",
-  "log",
-  "tracing-attributes",
-  "tracing-core",
- ]
- [[package]]
- name = "tracing-attributes"
- version = "0.1.8"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "99bbad0de3fd923c9c3232ead88510b783e5a4d16a6154adffa3d53308de984c"
- dependencies = [
-  "proc-macro2",
-  "quote",
-  "syn",
- ]
- [[package]]
- name = "tracing-core"
- version = "0.1.10"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "0aa83a9a47081cd522c09c81b31aec2c9273424976f922ad61c053b58350b715"
- dependencies = [
-  "lazy_static 1.4.0",
- ]
- [[package]]
- name = "tracing-futures"
- version = "0.2.4"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c"
- dependencies = [
-  "pin-project",
-  "tracing",
- ]
  [[package]]
  name = "trust-dns-proto"
  version = "0.18.0-alpha.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f"
  dependencies = [
 - "async-trait 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
 - "enum-as-inner 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "smallvec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
 - "tokio 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 + "async-trait",
 + "enum-as-inner",
 + "failure",
 + "futures",
 + "idna",
-  "lazy_static 1.4.0",
++ "lazy_static",
 + "log",
 + "rand 0.7.3",
 + "smallvec",
 + "socket2",
 + "tokio",
 + "url",
  ]
  
  [[package]]
  name = "trust-dns-resolver"
  version = "0.18.0-alpha.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f"
  dependencies = [
 - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 - "ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 - "resolv-conf 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "smallvec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "tokio 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 - "trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)",
 + "cfg-if",
 + "failure",
 + "futures",
 + "ipconfig",
-  "lazy_static 1.4.0",
++ "lazy_static",
 + "log",
 + "lru-cache",
 + "resolv-conf",
 + "smallvec",
 + "tokio",
 + "trust-dns-proto",
  ]
  
  [[package]]
  name = "twoway"
  version = "0.2.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "6b40075910de3a912adbd80b5d8bad6ad10a23eeb1f5bf9d4006839e899ba5bc"
  dependencies = [
-  "memchr 2.3.3",
 - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "unchecked-index 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
++ "memchr",
 + "unchecked-index",
  ]
  
  [[package]]
@@@ -3131,11 -2551,10 +2912,11 @@@ dependencies = 
  
  [[package]]
  name = "unicode-normalization"
--version = "0.1.12"
++version = "0.1.13"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4"
++checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
  dependencies = [
-  "smallvec",
 - "smallvec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
++ "tinyvec",
  ]
  
  [[package]]
@@@ -3172,37 -2586,18 +2953,31 @@@ checksum = "a156c684c91ea7d62626509bce3
  name = "url"
  version = "2.1.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
  dependencies = [
 - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 + "idna",
 + "matches",
 + "percent-encoding",
-  "serde 1.0.111",
++ "serde 1.0.114",
  ]
  
- [[package]]
- name = "utf8-ranges"
- version = "0.1.3"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
  [[package]]
  name = "uuid"
  version = "0.7.4"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
 +dependencies = [
 + "rand 0.6.5",
 +]
 +
 +[[package]]
 +name = "uuid"
 +version = "0.8.1"
 +source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
  dependencies = [
 - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 + "rand 0.7.3",
-  "serde 1.0.111",
++ "serde 1.0.114",
  ]
  
  [[package]]
@@@ -3238,9 -2630,8 +3013,9 @@@ dependencies = 
  
  [[package]]
  name = "vcpkg"
- version = "0.2.9"
 -version = "0.2.8"
++version = "0.2.10"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "55d1e41d56121e07f1e223db0a4def204e45c85425f6a16d462fd07c8d10d74c"
++checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c"
  
  [[package]]
  name = "vec_map"
@@@ -3278,17 -2664,16 +3053,17 @@@ dependencies = 
  
  [[package]]
  name = "wasm-bindgen-backend"
 -version = "0.2.60"
 +version = "0.2.63"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "ded84f06e0ed21499f6184df0e0cb3494727b0c5da89534e0fcc55c51d812101"
  dependencies = [
 - "bumpalo 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 - "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
 - "wasm-bindgen-shared 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
 + "bumpalo",
-  "lazy_static 1.4.0",
++ "lazy_static",
 + "log",
 + "proc-macro2",
 + "quote",
 + "syn",
 + "wasm-bindgen-shared",
  ]
  
  [[package]]
@@@ -3322,19 -2704,34 +3097,38 @@@ checksum = "c9ba19973a58daf4db6f352eda7
  
  [[package]]
  name = "web-sys"
 -version = "0.3.37"
 +version = "0.3.40"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17"
  dependencies = [
 - "js-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
 - "wasm-bindgen 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
 + "js-sys",
 + "wasm-bindgen",
  ]
  
 -version = "0.21.2"
+ [[package]]
+ name = "webpki"
 - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)",
 - "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
++version = "0.21.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "ab146130f5f790d45f82aeeb09e55a256573373ec64409fc19a6fb82fb1032ae"
+ dependencies = [
 - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
++ "ring",
++ "untrusted",
+ ]
+ [[package]]
+ name = "webpki-roots"
+ version = "0.19.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739"
+ dependencies = [
++ "webpki",
+ ]
  [[package]]
  name = "widestring"
--version = "0.4.0"
++version = "0.4.2"
  source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6"
++checksum = "a763e303c0e0f23b0da40888724762e802a8ffefbc22de4127ef42493c2ea68c"
  
  [[package]]
  name = "winapi"
@@@ -3401,17 -2790,315 +3195,8 @@@ dependencies = 
  name = "ws2_32-sys"
  version = "0.2.1"
  source = "registry+https://github.com/rust-lang/crates.io-index"
 +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
  dependencies = [
 - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 -]
 -
 -[metadata]
 -"checksum activitypub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d538a21b137ec0f63cc579ef4afa4ab13aa85b4f8af15a033683edd97c50718d"
 -"checksum activitystreams-derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65608fdeae5eb05485d5b71a3d2242d76b2b7413608c196d47eb4dff3eed7b85"
 -"checksum activitystreams-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c2a3958d240f40eff1f31b5f679a6e0d4ce2a16812886a3ec0164f3a2ca517"
 -"checksum activitystreams-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0598820663a59e5eaafeeedd3a7f7efc93db4ed6172905baec05503095ba5c0e"
 -"checksum actix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4af87564ff659dee8f9981540cac9418c45e910c8072fdedd643a262a38fcaf"
 -"checksum actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380"
 -"checksum actix-connect 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c95cc9569221e9802bf4c377f6c18b90ef10227d787611decf79fd47d2a8e76c"
 -"checksum actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "301482841d3d74483a446ead63cb7d362e187d2c8b603f13d91995621ea53c46"
 -"checksum actix-http 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c16664cc4fdea8030837ad5a845eb231fb93fc3c5c171edfefb52fad92ce9019"
 -"checksum actix-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21705adc76bbe4bc98434890e73a89cd00c6015e5704a60bb6eea6c3b72316b6"
 -"checksum actix-router 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d7a10ca4d94e8c8e7a87c5173aba1b97ba9a6563ca02b0e1cd23531093d3ec8"
 -"checksum actix-rt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227"
 -"checksum actix-server 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "582a7173c281a4f46b5aa168a11e7f37183dcb71177a39312cc2264da7a632c9"
 -"checksum actix-service 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3e4fc95dfa7e24171b2d0bb46b85f8ab0e8499e4e3caec691fc4ea65c287564"
 -"checksum actix-testing 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48494745b72d0ea8ff0cf874aaf9b622a3ee03d7081ee0c04edea4f26d32c911"
 -"checksum actix-threadpool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4082192601de5f303013709ff84d81ca6a1bc4af7fb24f367a500a23c6e84e"
 -"checksum actix-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4e5b4faaf105e9a6d389c606c298dcdb033061b00d532af9df56ff3a54995a8"
 -"checksum actix-utils 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fcf8f5631bf01adec2267808f00e228b761c60c0584cc9fa0b5364f41d147f4e"
 -"checksum actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3158e822461040822f0dbf1735b9c2ce1f95f93b651d7a7aded00b1efbb1f635"
 -"checksum actix-web-actors 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc1bd41bd66c4e9b5274cec87aac30168e63d64e96fd19db38edef6b46ba2982"
 -"checksum actix-web-codegen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f00371942083469785f7e28c540164af1913ee7c96a4534acb9cea92c39f057"
 -"checksum actix_derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b95aceadaf327f18f0df5962fedc1bde2f870566a0b9f65c89508a3b1f79334c"
 -"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
 -"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
 -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 -"checksum arc-swap 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825"
 -"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
 -"checksum ascii_utils 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
 -"checksum async-trait 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "da71fef07bc806586090247e971229289f64c210a278ee5ae419314eb386b31d"
 -"checksum attohttpc 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "93610ce1c035e8a273fe56a19852e42798f3c019ca2726e52d2971197f116525"
 -"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
 -"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
 -"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
 -"checksum awc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7601d4d1d7ef2335d6597a41b5fe069f6ab799b85f53565ab390e7b7065aac5"
 -"checksum backtrace 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)" = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e"
 -"checksum backtrace-sys 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118"
 -"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
 -"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
 -"checksum base64 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3"
 -"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
 -"checksum bcrypt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f02d7d008a57bcb2251ba115b803934e02315edbde9a861c88713493e381b63"
 -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 -"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
 -"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774"
 -"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
 -"checksum blowfish 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6aeb80d00f2688459b8542068abd974cfb101e7a82182414a99b5026c0d85cc3"
 -"checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd"
 -"checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e"
 -"checksum bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8"
 -"checksum bumpalo 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187"
 -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
 -"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
 -"checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1"
 -"checksum bytestring 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fc7c05fa5172da78a62d9949d662d2ac89d4cc7355d7b49adee5163f1fb3f363"
 -"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
 -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
 -"checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
 -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
 -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
 -"checksum comrak 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e17058cc536cf290563e88787d7b9e6030ce4742943017cc2ffb71f88034021c"
 -"checksum config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3"
 -"checksum copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127"
 -"checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
 -"checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
 -"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
 -"checksum crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061"
 -"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
 -"checksum darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
 -"checksum darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
 -"checksum darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
 -"checksum derive_builder 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
 -"checksum derive_builder_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
 -"checksum derive_more 0.99.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2323f3f47db9a0e77ce7a300605d8d2098597fc451ed1a97bb1f6411bb550a7"
 -"checksum diesel 1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "33d7ca63eb2efea87a7f56a283acc49e2ce4b2bd54adf7465dc1d81fef13d8fc"
 -"checksum diesel_derives 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
 -"checksum diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c"
 -"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
 -"checksum dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
 -"checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
 -"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
 -"checksum email 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "91549a51bb0241165f13d57fc4c72cef063b4088fb078b019ecbf464a45f22e4"
 -"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
 -"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
 -"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
 -"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
 -"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
 -"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
 -"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
 -"checksum encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28"
 -"checksum entities 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca"
 -"checksum enum-as-inner 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4bfcfacb61d231109d1d55202c1f33263319668b168843e02ad4652725ec9c"
 -"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
 -"checksum failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
 -"checksum failure_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231"
 -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
 -"checksum fast_chemail 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "495a39d30d624c2caabe6312bfead73e7717692b44e0b32df168c275a2e8e9e4"
 -"checksum flate2 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42"
 -"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
 -"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
 -"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
 -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
 -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
 -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
 -"checksum futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780"
 -"checksum futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8"
 -"checksum futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a"
 -"checksum futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba"
 -"checksum futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6"
 -"checksum futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7"
 -"checksum futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6"
 -"checksum futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27"
 -"checksum futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5"
 -"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
 -"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
 -"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
 -"checksum h2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "377038bf3c89d18d6ca1431e7a5027194fbd724ca10592b9487ede5e8e144f42"
 -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
 -"checksum hermit-abi 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15"
 -"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e"
 -"checksum hostname 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
 -"checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163"
 -"checksum http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
 -"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
 -"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
 -"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 -"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
 -"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292"
 -"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
 -"checksum ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f"
 -"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
 -"checksum js-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055"
 -"checksum jsonwebtoken 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d11f9e80a85927748a334df8e4f6782a04033517bb28f3863a563daad882da7f"
 -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 -"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
 -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 -"checksum lettre 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bf43f3202a879fbdab4ecafec3349b0139f81d31c626246d53bcbb546253ffaa"
 -"checksum lettre_email 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fd02480f8dcf48798e62113974d6ccca2129a51d241fa20f1ea349c8a42559d5"
 -"checksum lexical-core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d7043aa5c05dd34fb73b47acb8c3708eac428de4545ea3682ed2f11293ebd890"
 -"checksum libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
 -"checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
 -"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
 -"checksum lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
 -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
 -"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
 -"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
 -"checksum match_cfg 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
 -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
 -"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
 -"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
 -"checksum migrations_internals 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4fc84e4af020b837029e017966f86a1c2d5e83e64b589963d5047525995860"
 -"checksum migrations_macros 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c"
 -"checksum mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
 -"checksum mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
 -"checksum miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5"
 -"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
 -"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
 -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
 -"checksum native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d"
 -"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
 -"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
 -"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
 -"checksum nom 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6"
 -"checksum num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
 -"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
 -"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
 -"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
 -"checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
 -"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
 -"checksum openssl 0.10.29 (registry+https://github.com/rust-lang/crates.io-index)" = "cee6d85f4cb4c4f59a6a85d5b68a233d280c82e29e822913b9c8b129fbf20bdd"
 -"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
 -"checksum openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)" = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de"
 -"checksum parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
 -"checksum parking_lot_core 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb"
 -"checksum pem 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1581760c757a756a41f0ee3ff01256227bdf64cb752839779b95ffb01c59793"
 -"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
 -"checksum pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
 -"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
 -"checksum pest_generator 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
 -"checksum pest_meta 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
 -"checksum pin-project 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6f6a7f5eee6292c559c793430c55c00aea9d3b3d1905e855806ca4d7253426a2"
 -"checksum pin-project-internal 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "8988430ce790d8682672117bc06dda364c0be32d3abd738234f19f3240bad99a"
 -"checksum pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae"
 -"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
 -"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
 -"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
 -"checksum pq-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac25eee5a0582f45a67e837e350d784e7003bd29a5f460796772061ca49ffda"
 -"checksum proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63"
 -"checksum proc-macro-nested 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694"
 -"checksum proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
 -"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
 -"checksum quick-xml 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fe1e430bdcf30c9fdc25053b9c459bb1a4672af4617b6c783d7d91dc17c6bbb0"
 -"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
 -"checksum r2d2 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1497e40855348e4a8a40767d8e55174bce1e445a3ac9254ad44ad468ee0485af"
 -"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
 -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
 -"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
 -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
 -"checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
 -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
 -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
 -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
 -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
 -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
 -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
 -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
 -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
 -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
 -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
 -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
 -"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
 -"checksum regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692"
 -"checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
 -"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
 -"checksum resolv-conf 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "11834e137f3b14e309437a8276714eed3a80d1ef894869e510f2c0c0b98b9f4a"
 -"checksum ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c"
 -"checksum rss 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99979205510c60f80a119dedbabd0b8426517384edf205322f8bcd51796bcef9"
 -"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
 -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
 -"checksum rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1"
 -"checksum ryu 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
 -"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
 -"checksum schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
 -"checksum scheduled-thread-pool 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0988d7fdf88d5e5fcf5923a0f1e8ab345f3e98ab4bc6bc45a2d5ff7f7458fbf6"
 -"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 -"checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c"
 -"checksum security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535"
 -"checksum security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405"
 -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
 -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 -"checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
 -"checksum serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
 -"checksum serde-hjson 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8"
 -"checksum serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
 -"checksum serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)" = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd"
 -"checksum serde_test 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5"
 -"checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
 -"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
 -"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
 -"checksum sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0"
 -"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
 -"checksum simple_asn1 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b25ecba7165254f0c97d6c22a64b1122a03634b18d20a34daf21e18f892e618"
 -"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
 -"checksum smallvec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a"
 -"checksum socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
 -"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 -"checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3"
 -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 -"checksum strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
 -"checksum strum 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
 -"checksum strum_macros 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
 -"checksum syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
 -"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
 -"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
 -"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
 -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
 -"checksum thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b13f926965ad00595dd129fa12823b04bbf866e9085ab0a5f2b05b850fbfc344"
 -"checksum thiserror-impl 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479"
 -"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
 -"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
 -"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
 -"checksum tokio 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "05c1d570eb1a36f0345a5ce9c6c6e665b70b73d11236912c0b477616aeec47b1"
 -"checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930"
 -"checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
 -"checksum trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f"
 -"checksum trust-dns-resolver 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f"
 -"checksum twoway 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6b40075910de3a912adbd80b5d8bad6ad10a23eeb1f5bf9d4006839e899ba5bc"
 -"checksum typed-arena 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d"
 -"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
 -"checksum ucd-trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
 -"checksum unchecked-index 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c"
 -"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
 -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 -"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4"
 -"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
 -"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
 -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
 -"checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
 -"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece"
 -"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
 -"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
 -"checksum v_escape 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "660b101c07b5d0863deb9e7fb3138777e858d6d2a79f9e6049a27d1cc77c6da6"
 -"checksum v_escape_derive 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae"
 -"checksum v_htmlescape 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41"
 -"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
 -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
 -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
 -"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
 -"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
 -"checksum wasm-bindgen 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f"
 -"checksum wasm-bindgen-backend 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd"
 -"checksum wasm-bindgen-macro 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4"
 -"checksum wasm-bindgen-macro-support 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931"
 -"checksum wasm-bindgen-shared 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639"
 -"checksum web-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb"
 -"checksum webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef"
 -"checksum webpki-roots 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739"
 -"checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6"
 -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
 -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 -"checksum winapi-util 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e"
 -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 -"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
 -"checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e"
 -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
 + "winapi 0.2.8",
 + "winapi-build",
 +]
- [[package]]
- name = "yaml-rust"
- version = "0.4.4"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"
- dependencies = [
-  "linked-hash-map 0.5.3",
- ]
index 47be3239ebd3f12c317d573c0b0800fc0438ff41,43933e5318225890ad4e3c657b1232fac1e6cb12..52a9bae8e9e041a986a5faf250597931bbf1b198
@@@ -4,18 -4,19 +4,21 @@@ version = "0.0.1
  authors = ["Dessalines <tyhou13@gmx.com>"]
  edition = "2018"
  
+ [profile.release]
+ lto = true
  [dependencies]
 -diesel = { version = "1.4.2", features = ["postgres","chrono", "r2d2", "64-column-tables"] }
 +diesel = { version = "1.4.4", features = ["postgres","chrono","r2d2","64-column-tables","serde_json"] }
  diesel_migrations = "1.4.0"
  dotenv = "0.15.0"
 -bcrypt = "0.7.0"
 -activitypub = "0.2.0"
 -chrono = "0.4.7"
 +activitystreams = "0.6.2"
 +activitystreams-new = { git = "https://git.asonix.dog/asonix/activitystreams-sketch" }
 +activitystreams-ext = { git = "https://git.asonix.dog/asonix/activitystreams-ext" }
 +bcrypt = "0.8.0"
 +chrono = { version = "0.4.7", features = ["serde"] }
- serde_json = { version = "1.0.48", features = ["preserve_order"]}
++serde_json = { version = "1.0.52", features = ["preserve_order"]}
  failure = "0.1.8"
 -serde_json = "1.0.52"
 -serde = "1.0.105"
 +serde = { version = "1.0.105", features = ["derive"] }
  actix = "0.9.0"
  actix-web = "2.0.0"
  actix-files = "0.2.1"
@@@ -34,17 -35,9 +37,16 @@@ lettre_email = "0.9.4
  sha2 = "0.8.1"
  rss = "1.9.0"
  htmlescape = "0.3.1"
- config = "0.10.1"
- hjson = "0.8.2"
 +url = { version = "2.1.1", features = ["serde"] }
+ config = {version = "0.10.1", default-features = false, features = ["hjson"] }
  percent-encoding = "2.1.0"
- isahc = "0.9.2"
+ attohttpc = { version = "0.14.0", default-features = false, features = ["tls-rustls"] }
  comrak = "0.7"
 -tokio = "0.2.20"
 -futures = "0.3.4"
 +openssl = "0.10"
 +http = "0.2.1"
 +http-signature-normalization = "0.5.1"
 +base64 = "0.12.1"
 +tokio = "0.2.21"
 +futures = "0.3.5"
 +itertools = "0.9.0"
 +uuid = { version = "0.8", features = ["serde", "v4"] }
index cb412fccade6b45174f3a72b81fac99cd1064cb3,618122b9868a1aab8c1a32ef16e455f974b732ae..3fc67eb348f766905ea14e0b701bed2e9009a50d
@@@ -1,41 -1,5 +1,31 @@@
 -use crate::is_valid_community_name;
+ use super::*;
-   db::{
-     community::*,
-     community_view::*,
-     moderator::*,
-     site::*,
-     user::*,
-     user_view::*,
-     Bannable,
-     Crud,
-     Followable,
-     Joinable,
-     SortType,
-   },
 +use crate::{
 +  api::{APIError, Oper, Perform},
 +  apub::{
 +    extensions::signatures::generate_actor_keypair,
 +    make_apub_endpoint,
 +    ActorType,
 +    EndpointType,
 +  },
++  db::{Bannable, Crud, Followable, Joinable, SortType},
++  is_valid_community_name,
 +  naive_from_unix,
 +  naive_now,
 +  slur_check,
 +  slurs_vec_to_str,
 +  websocket::{
 +    server::{JoinCommunityRoom, SendCommunityRoomMessage},
 +    UserOperation,
 +    WebsocketInfo,
 +  },
 +};
 +use diesel::{
 +  r2d2::{ConnectionManager, Pool},
 +  PgConnection,
 +};
 +use failure::Error;
 +use serde::{Deserialize, Serialize};
 +use std::str::FromStr;
  
  #[derive(Serialize, Deserialize)]
  pub struct GetCommunity {
index 5120e9bc949fb5b9bc9cbe54a082f015802423ad,4f11b3278e72bbbc8294b8bff49a9fc9710d557e..afd62aff8011a524cb45e0b748fb96c3af8c5c81
@@@ -1,9 -1,42 +1,12 @@@
- use crate::websocket::WebsocketInfo;
 -use crate::db::category::*;
 -use crate::db::comment::*;
 -use crate::db::comment_view::*;
 -use crate::db::community::*;
 -use crate::db::community_view::*;
 -use crate::db::moderator::*;
 -use crate::db::moderator_views::*;
 -use crate::db::password_reset_request::*;
 -use crate::db::post::*;
 -use crate::db::post_view::*;
 -use crate::db::private_message::*;
 -use crate::db::private_message_view::*;
 -use crate::db::site::*;
 -use crate::db::site_view::*;
 -use crate::db::user::*;
 -use crate::db::user_mention::*;
 -use crate::db::user_mention_view::*;
 -use crate::db::user_view::*;
 -use crate::db::*;
+ use crate::{
 -  extract_usernames, fetch_iframely_and_pictrs_data, generate_random_string, naive_from_unix,
 -  naive_now, remove_slurs, send_email, slur_check, slurs_vec_to_str,
++  db::{community::*, community_view::*, moderator::*, site::*, user::*, user_view::*},
++  websocket::WebsocketInfo,
+ };
 -
 -use crate::settings::Settings;
 -use crate::websocket::UserOperation;
 -use crate::websocket::{
 -  server::{
 -    JoinCommunityRoom, JoinPostRoom, JoinUserRoom, SendAllMessage, SendComment,
 -    SendCommunityRoomMessage, SendPost, SendUserRoomMessage,
 -  },
 -  WebsocketInfo,
 +use diesel::{
 +  r2d2::{ConnectionManager, Pool},
 +  PgConnection,
  };
 -use diesel::r2d2::{ConnectionManager, Pool};
 -use diesel::PgConnection;
  use failure::Error;
 -use log::{error, info};
 -use serde::{Deserialize, Serialize};
 -use std::str::FromStr;
  
  pub mod comment;
  pub mod community;
index 9bbde791977b8f4f16b2010b85a66616f311473b,9eeb5158085a842b6a6901967eec66e91322052f..420bef1f6211e648fe449b1f876c7a8e94d22c27
@@@ -1,41 -1,6 +1,41 @@@
 -use super::*;
 -
 -#[derive(Serialize, Deserialize)]
 +use crate::{
 +  api::{APIError, Oper, Perform},
 +  apub::{ApubLikeableType, ApubObjectType},
 +  db::{
 +    comment_view::*,
 +    community_view::*,
 +    moderator::*,
 +    post::*,
 +    post_view::*,
 +    site::*,
 +    site_view::*,
 +    user::*,
 +    user_view::*,
 +    Crud,
 +    Likeable,
 +    ListingType,
 +    Saveable,
 +    SortType,
 +  },
-   fetch_iframely_and_pictshare_data,
++  fetch_iframely_and_pictrs_data,
 +  naive_now,
 +  slur_check,
 +  slurs_vec_to_str,
 +  websocket::{
 +    server::{JoinCommunityRoom, JoinPostRoom, SendPost},
 +    UserOperation,
 +    WebsocketInfo,
 +  },
 +};
 +use diesel::{
 +  r2d2::{ConnectionManager, Pool},
 +  PgConnection,
 +};
 +use failure::Error;
 +use serde::{Deserialize, Serialize};
 +use std::str::FromStr;
 +
 +#[derive(Serialize, Deserialize, Debug)]
  pub struct CreatePost {
    name: String,
    url: Option<String>,
@@@ -171,10 -135,7 +171,10 @@@ impl Perform for Oper<CreatePost> 
        embed_title: iframely_title,
        embed_description: iframely_description,
        embed_html: iframely_html,
-       thumbnail_url: pictshare_thumbnail,
+       thumbnail_url: pictrs_thumbnail,
 +      ap_id: "changeme".into(),
 +      local: true,
 +      published: None,
      };
  
      let inserted_post = match Post::create(&conn, &post_form) {
@@@ -507,12 -450,10 +507,12 @@@ impl Perform for Oper<EditPost> 
        return Err(APIError::err("site_ban").into());
      }
  
-     // Fetch Iframely and Pictshare cached image
-     let (iframely_title, iframely_description, iframely_html, pictshare_thumbnail) =
-       fetch_iframely_and_pictshare_data(data.url.to_owned());
+     // Fetch Iframely and Pictrs cached image
+     let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
+       fetch_iframely_and_pictrs_data(data.url.to_owned());
  
 +    let read_post = Post::read(&conn, data.edit_id)?;
 +
      let post_form = PostForm {
        name: data.name.to_owned(),
        url: data.url.to_owned(),
        embed_title: iframely_title,
        embed_description: iframely_description,
        embed_html: iframely_html,
-       thumbnail_url: pictshare_thumbnail,
+       thumbnail_url: pictrs_thumbnail,
 +      ap_id: read_post.ap_id,
 +      local: read_post.local,
 +      published: None,
      };
  
 -    let _updated_post = match Post::update(&conn, data.edit_id, &post_form) {
 +    let updated_post = match Post::update(&conn, data.edit_id, &post_form) {
        Ok(post) => post,
        Err(e) => {
          let err_type = if e.to_string() == "value too long for type character varying(200)" {
index b5bb9d76c7dffff589c05e65186f0e3514d1c05a,0000000000000000000000000000000000000000..3c4034c96979718254f147b51395cb3a44b1c937
mode 100644,000000..100644
--- /dev/null
@@@ -1,73 -1,0 +1,74 @@@
- use isahc::prelude::*;
 +use crate::{
 +  apub::{extensions::signatures::sign, is_apub_id_valid, ActorType},
 +  db::{activity::insert_activity, community::Community, user::User_},
 +};
 +use activitystreams::{context, object::properties::ObjectProperties, public, Activity, Base};
 +use diesel::PgConnection;
 +use failure::{Error, _core::fmt::Debug};
-       debug!("Not sending activity to {} (invalid or blocklisted)", t);
 +use log::debug;
 +use serde::Serialize;
 +use url::Url;
 +
 +pub fn populate_object_props(
 +  props: &mut ObjectProperties,
 +  addressed_ccs: Vec<String>,
 +  object_id: &str,
 +) -> Result<(), Error> {
 +  props
 +    .set_context_xsd_any_uri(context())?
 +    // TODO: the activity needs a seperate id from the object
 +    .set_id(object_id)?
 +    // TODO: should to/cc go on the Create, or on the Post? or on both?
 +    // TODO: handle privacy on the receiving side (at least ignore anything thats not public)
 +    .set_to_xsd_any_uri(public())?
 +    .set_many_cc_xsd_any_uris(addressed_ccs)?;
 +  Ok(())
 +}
 +
 +pub fn send_activity_to_community<A>(
 +  creator: &User_,
 +  conn: &PgConnection,
 +  community: &Community,
 +  to: Vec<String>,
 +  activity: A,
 +) -> Result<(), Error>
 +where
 +  A: Activity + Base + Serialize + Debug,
 +{
 +  insert_activity(&conn, creator.id, &activity, true)?;
 +
 +  // if this is a local community, we need to do an announce from the community instead
 +  if community.local {
 +    Community::do_announce(activity, &community, creator, conn)?;
 +  } else {
 +    send_activity(&activity, creator, to)?;
 +  }
 +  Ok(())
 +}
 +
 +/// Send an activity to a list of recipients, using the correct headers etc.
 +pub fn send_activity<A>(activity: &A, actor: &dyn ActorType, to: Vec<String>) -> Result<(), Error>
 +where
 +  A: Serialize + Debug,
 +{
 +  let json = serde_json::to_string(&activity)?;
 +  debug!("Sending activitypub activity {} to {:?}", json, to);
 +  for t in to {
 +    let to_url = Url::parse(&t)?;
 +    if !is_apub_id_valid(&to_url) {
-     let request = Request::post(t).header("Host", to_url.domain().unwrap());
-     let signature = sign(&request, actor)?;
++      debug!("Not sending activity to {} (invalid or blacklisted)", t);
 +      continue;
 +    }
-       .body(json.to_owned())?
-       .send()?;
++    let mut request = attohttpc::post(t).header("Host", to_url.domain().unwrap());
++    let signature = sign(&mut request, actor)?;
 +    let res = request
 +      .header("Signature", signature)
 +      .header("Content-Type", "application/json")
++      .text(json.to_owned())
++      .send()?
++      .text()?;
++
 +    debug!("Result for activity send: {:?}", res);
 +  }
 +  Ok(())
 +}
index 4156f0b3f84a567e67db063cfe81d002bfc9c1e2,0000000000000000000000000000000000000000..7aa9489c3cf432b921755ccea522dd5345cc0306
mode 100644,000000..100644
--- /dev/null
@@@ -1,136 -1,0 +1,137 @@@
- use http::request::Builder;
 +use crate::apub::ActorType;
 +use activitystreams::ext::Extension;
 +use actix_web::HttpRequest;
++use attohttpc::RequestBuilder;
 +use failure::Error;
- pub fn sign(request: &Builder, actor: &dyn ActorType) -> Result<String, Error> {
 +use http_signature_normalization::Config;
 +use log::debug;
 +use openssl::{
 +  hash::MessageDigest,
 +  pkey::PKey,
 +  rsa::Rsa,
 +  sign::{Signer, Verifier},
 +};
 +use serde::{Deserialize, Serialize};
 +use std::collections::BTreeMap;
 +
 +lazy_static! {
 +  static ref HTTP_SIG_CONFIG: Config = Config::new();
 +}
 +
 +pub struct Keypair {
 +  pub private_key: String,
 +  pub public_key: String,
 +}
 +
 +/// Generate the asymmetric keypair for ActivityPub HTTP signatures.
 +pub fn generate_actor_keypair() -> Result<Keypair, Error> {
 +  let rsa = Rsa::generate(2048)?;
 +  let pkey = PKey::from_rsa(rsa)?;
 +  let public_key = pkey.public_key_to_pem()?;
 +  let private_key = pkey.private_key_to_pem_pkcs8()?;
 +  Ok(Keypair {
 +    private_key: String::from_utf8(private_key)?,
 +    public_key: String::from_utf8(public_key)?,
 +  })
 +}
 +
++// TODO is it possible to create this signature, with just the url and actor?
 +/// Signs request headers with the given keypair.
-     .headers_ref()
-     .unwrap()
++pub fn sign(request: &mut RequestBuilder, actor: &dyn ActorType) -> Result<String, Error> {
 +  let signing_key_id = format!("{}#main-key", actor.actor_id());
 +
 +  let headers = request
-       request.method_ref().unwrap().as_str(),
-       request
-         .uri_ref()
-         .unwrap()
-         .path_and_query()
-         .unwrap()
-         .as_str(),
++    .inspect()
++    .headers()
 +    .iter()
 +    .map(|h| -> Result<(String, String), Error> {
 +      Ok((h.0.as_str().to_owned(), h.1.to_str()?.to_owned()))
 +    })
 +    .collect::<Result<BTreeMap<String, String>, Error>>()?;
 +
++  let mut path_and_query = request.inspect().url().path().to_owned();
++  if let Some(query) = request.inspect().url().query() {
++    path_and_query.push_str(query);
++  }
++
 +  let signature_header_value = HTTP_SIG_CONFIG
 +    .begin_sign(
++      request.inspect().method().as_str(),
++      &path_and_query,
 +      headers,
 +    )?
 +    .sign(signing_key_id, |signing_string| {
 +      let private_key = PKey::private_key_from_pem(actor.private_key().as_bytes())?;
 +      let mut signer = Signer::new(MessageDigest::sha256(), &private_key).unwrap();
 +      signer.update(signing_string.as_bytes()).unwrap();
 +      Ok(base64::encode(signer.sign_to_vec()?)) as Result<_, Error>
 +    })?
 +    .signature_header();
 +
 +  Ok(signature_header_value)
 +}
 +
 +pub fn verify(request: &HttpRequest, actor: &dyn ActorType) -> Result<(), Error> {
 +  let headers = request
 +    .headers()
 +    .iter()
 +    .map(|h| -> Result<(String, String), Error> {
 +      Ok((h.0.as_str().to_owned(), h.1.to_str()?.to_owned()))
 +    })
 +    .collect::<Result<BTreeMap<String, String>, Error>>()?;
 +
 +  let verified = HTTP_SIG_CONFIG
 +    .begin_verify(
 +      request.method().as_str(),
 +      request.uri().path_and_query().unwrap().as_str(),
 +      headers,
 +    )?
 +    .verify(|signature, signing_string| -> Result<bool, Error> {
 +      debug!(
 +        "Verifying with key {}, message {}",
 +        &actor.public_key(),
 +        &signing_string
 +      );
 +      let public_key = PKey::public_key_from_pem(actor.public_key().as_bytes())?;
 +      let mut verifier = Verifier::new(MessageDigest::sha256(), &public_key).unwrap();
 +      verifier.update(&signing_string.as_bytes()).unwrap();
 +      Ok(verifier.verify(&base64::decode(signature)?)?)
 +    })?;
 +
 +  if verified {
 +    debug!("verified signature for {}", &request.uri());
 +    Ok(())
 +  } else {
 +    Err(format_err!(
 +      "Invalid signature on request: {}",
 +      &request.uri()
 +    ))
 +  }
 +}
 +
 +// The following is taken from here:
 +// https://docs.rs/activitystreams/0.5.0-alpha.17/activitystreams/ext/index.html
 +
 +#[derive(Clone, Debug, Default, Deserialize, Serialize)]
 +#[serde(rename_all = "camelCase")]
 +pub struct PublicKey {
 +  pub id: String,
 +  pub owner: String,
 +  pub public_key_pem: String,
 +}
 +
 +#[derive(Clone, Debug, Default, Deserialize, Serialize)]
 +#[serde(rename_all = "camelCase")]
 +pub struct PublicKeyExtension {
 +  pub public_key: PublicKey,
 +}
 +
 +impl PublicKey {
 +  pub fn to_ext(&self) -> PublicKeyExtension {
 +    PublicKeyExtension {
 +      public_key: self.to_owned(),
 +    }
 +  }
 +}
 +
 +impl<T> Extension<T> for PublicKeyExtension where T: activitystreams::Actor {}
index 7f7a3f971751821ee3e6de66ac2120ac92ebdbff,0000000000000000000000000000000000000000..20bab4e2636648f84f493a30fa7b6201f32fa424
mode 100644,000000..100644
--- /dev/null
@@@ -1,327 -1,0 +1,326 @@@
- use isahc::prelude::*;
 +use activitystreams::object::Note;
 +use actix_web::Result;
 +use diesel::{result::Error::NotFound, PgConnection};
 +use failure::{Error, _core::fmt::Debug};
-   let text = Request::get(url.as_str())
 +use log::debug;
 +use serde::Deserialize;
 +use std::time::Duration;
 +use url::Url;
 +
 +use crate::{
 +  api::site::SearchResponse,
 +  db::{
 +    comment::{Comment, CommentForm},
 +    comment_view::CommentView,
 +    community::{Community, CommunityForm, CommunityModerator, CommunityModeratorForm},
 +    community_view::CommunityView,
 +    post::{Post, PostForm},
 +    post_view::PostView,
 +    user::{UserForm, User_},
 +    Crud,
 +    Joinable,
 +    SearchType,
 +  },
 +  naive_now,
 +  routes::nodeinfo::{NodeInfo, NodeInfoWellKnown},
 +};
 +
 +use crate::{
 +  apub::{
 +    get_apub_protocol_string,
 +    is_apub_id_valid,
 +    FromApub,
 +    GroupExt,
 +    PageExt,
 +    PersonExt,
 +    APUB_JSON_CONTENT_TYPE,
 +  },
 +  db::user_view::UserView,
 +};
 +use chrono::NaiveDateTime;
 +
 +static ACTOR_REFETCH_INTERVAL_SECONDS: i64 = 24 * 60 * 60;
 +
 +// Fetch nodeinfo metadata from a remote instance.
 +fn _fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
 +  let well_known_uri = Url::parse(&format!(
 +    "{}://{}/.well-known/nodeinfo",
 +    get_apub_protocol_string(),
 +    domain
 +  ))?;
 +  let well_known = fetch_remote_object::<NodeInfoWellKnown>(&well_known_uri)?;
 +  Ok(fetch_remote_object::<NodeInfo>(&well_known.links.href)?)
 +}
 +
 +/// Fetch any type of ActivityPub object, handling things like HTTP headers, deserialisation,
 +/// timeouts etc.
 +pub fn fetch_remote_object<Response>(url: &Url) -> Result<Response, Error>
 +where
 +  Response: for<'de> Deserialize<'de>,
 +{
 +  if !is_apub_id_valid(&url) {
 +    return Err(format_err!("Activitypub uri invalid or blocked: {}", url));
 +  }
 +  // TODO: this function should return a future
 +  let timeout = Duration::from_secs(60);
-     .body(())?
++  let text: String = attohttpc::get(url.as_str())
 +    .header("Accept", APUB_JSON_CONTENT_TYPE)
 +    .connect_timeout(timeout)
 +    .timeout(timeout)
++    // .body(())
 +    .send()?
 +    .text()?;
 +  let res: Response = serde_json::from_str(&text)?;
 +  Ok(res)
 +}
 +
 +/// The types of ActivityPub objects that can be fetched directly by searching for their ID.
 +#[serde(untagged)]
 +#[derive(serde::Deserialize, Debug)]
 +pub enum SearchAcceptedObjects {
 +  Person(Box<PersonExt>),
 +  Group(Box<GroupExt>),
 +  Page(Box<PageExt>),
 +  Comment(Box<Note>),
 +}
 +
 +/// Attempt to parse the query as URL, and fetch an ActivityPub object from it.
 +///
 +/// Some working examples for use with the docker/federation/ setup:
 +/// http://lemmy_alpha:8540/c/main, or !main@lemmy_alpha:8540
 +/// http://lemmy_alpha:8540/u/lemmy_alpha, or @lemmy_alpha@lemmy_alpha:8540
 +/// http://lemmy_alpha:8540/post/3
 +/// http://lemmy_alpha:8540/comment/2
 +pub fn search_by_apub_id(query: &str, conn: &PgConnection) -> Result<SearchResponse, Error> {
 +  // Parse the shorthand query url
 +  let query_url = if query.contains('@') {
 +    debug!("{}", query);
 +    let split = query.split('@').collect::<Vec<&str>>();
 +
 +    // User type will look like ['', username, instance]
 +    // Community will look like [!community, instance]
 +    let (name, instance) = if split.len() == 3 {
 +      (format!("/u/{}", split[1]), split[2])
 +    } else if split.len() == 2 {
 +      if split[0].contains('!') {
 +        let split2 = split[0].split('!').collect::<Vec<&str>>();
 +        (format!("/c/{}", split2[1]), split[1])
 +      } else {
 +        return Err(format_err!("Invalid search query: {}", query));
 +      }
 +    } else {
 +      return Err(format_err!("Invalid search query: {}", query));
 +    };
 +
 +    let url = format!("{}://{}{}", get_apub_protocol_string(), instance, name);
 +    Url::parse(&url)?
 +  } else {
 +    Url::parse(&query)?
 +  };
 +
 +  let mut response = SearchResponse {
 +    type_: SearchType::All.to_string(),
 +    comments: vec![],
 +    posts: vec![],
 +    communities: vec![],
 +    users: vec![],
 +  };
 +  match fetch_remote_object::<SearchAcceptedObjects>(&query_url)? {
 +    SearchAcceptedObjects::Person(p) => {
 +      let user_uri = p.inner.object_props.get_id().unwrap().to_string();
 +      let user = get_or_fetch_and_upsert_remote_user(&user_uri, &conn)?;
 +      response.users = vec![UserView::read(conn, user.id)?];
 +    }
 +    SearchAcceptedObjects::Group(g) => {
 +      let community_uri = g.inner.object_props.get_id().unwrap().to_string();
 +      let community = get_or_fetch_and_upsert_remote_community(&community_uri, &conn)?;
 +      // TODO Maybe at some point in the future, fetch all the history of a community
 +      // fetch_community_outbox(&c, conn)?;
 +      response.communities = vec![CommunityView::read(conn, community.id, None)?];
 +    }
 +    SearchAcceptedObjects::Page(p) => {
 +      let p = upsert_post(&PostForm::from_apub(&p, conn)?, conn)?;
 +      response.posts = vec![PostView::read(conn, p.id, None)?];
 +    }
 +    SearchAcceptedObjects::Comment(c) => {
 +      let post_url = c
 +        .object_props
 +        .get_many_in_reply_to_xsd_any_uris()
 +        .unwrap()
 +        .next()
 +        .unwrap()
 +        .to_string();
 +      // TODO: also fetch parent comments if any
 +      let post = fetch_remote_object(&Url::parse(&post_url)?)?;
 +      upsert_post(&PostForm::from_apub(&post, conn)?, conn)?;
 +      let c = upsert_comment(&CommentForm::from_apub(&c, conn)?, conn)?;
 +      response.comments = vec![CommentView::read(conn, c.id, None)?];
 +    }
 +  }
 +  Ok(response)
 +}
 +
 +/// Check if a remote user exists, create if not found, if its too old update it.Fetch a user, insert/update it in the database and return the user.
 +pub fn get_or_fetch_and_upsert_remote_user(
 +  apub_id: &str,
 +  conn: &PgConnection,
 +) -> Result<User_, Error> {
 +  match User_::read_from_actor_id(&conn, &apub_id) {
 +    Ok(u) => {
 +      // If its older than a day, re-fetch it
 +      if !u.local && should_refetch_actor(u.last_refreshed_at) {
 +        debug!("Fetching and updating from remote user: {}", apub_id);
 +        let person = fetch_remote_object::<PersonExt>(&Url::parse(apub_id)?)?;
 +        let mut uf = UserForm::from_apub(&person, &conn)?;
 +        uf.last_refreshed_at = Some(naive_now());
 +        Ok(User_::update(&conn, u.id, &uf)?)
 +      } else {
 +        Ok(u)
 +      }
 +    }
 +    Err(NotFound {}) => {
 +      debug!("Fetching and creating remote user: {}", apub_id);
 +      let person = fetch_remote_object::<PersonExt>(&Url::parse(apub_id)?)?;
 +      let uf = UserForm::from_apub(&person, &conn)?;
 +      Ok(User_::create(conn, &uf)?)
 +    }
 +    Err(e) => Err(Error::from(e)),
 +  }
 +}
 +
 +/// Determines when a remote actor should be refetched from its instance. In release builds, this is
 +/// ACTOR_REFETCH_INTERVAL_SECONDS after the last refetch, in debug builds always.
 +///
 +/// TODO it won't pick up new avatars, summaries etc until a day after.
 +/// Actors need an "update" activity pushed to other servers to fix this.
 +fn should_refetch_actor(last_refreshed: NaiveDateTime) -> bool {
 +  if cfg!(debug_assertions) {
 +    true
 +  } else {
 +    let update_interval = chrono::Duration::seconds(ACTOR_REFETCH_INTERVAL_SECONDS);
 +    last_refreshed.lt(&(naive_now() - update_interval))
 +  }
 +}
 +
 +/// Check if a remote community exists, create if not found, if its too old update it.Fetch a community, insert/update it in the database and return the community.
 +pub fn get_or_fetch_and_upsert_remote_community(
 +  apub_id: &str,
 +  conn: &PgConnection,
 +) -> Result<Community, Error> {
 +  match Community::read_from_actor_id(&conn, &apub_id) {
 +    Ok(c) => {
 +      if !c.local && should_refetch_actor(c.last_refreshed_at) {
 +        debug!("Fetching and updating from remote community: {}", apub_id);
 +        let group = fetch_remote_object::<GroupExt>(&Url::parse(apub_id)?)?;
 +        let mut cf = CommunityForm::from_apub(&group, conn)?;
 +        cf.last_refreshed_at = Some(naive_now());
 +        Ok(Community::update(&conn, c.id, &cf)?)
 +      } else {
 +        Ok(c)
 +      }
 +    }
 +    Err(NotFound {}) => {
 +      debug!("Fetching and creating remote community: {}", apub_id);
 +      let group = fetch_remote_object::<GroupExt>(&Url::parse(apub_id)?)?;
 +      let cf = CommunityForm::from_apub(&group, conn)?;
 +      let community = Community::create(conn, &cf)?;
 +
 +      // Also add the community moderators too
 +      let creator_and_moderator_uris = group
 +        .inner
 +        .object_props
 +        .get_many_attributed_to_xsd_any_uris()
 +        .unwrap();
 +      let creator_and_moderators = creator_and_moderator_uris
 +        .map(|c| get_or_fetch_and_upsert_remote_user(&c.to_string(), &conn).unwrap())
 +        .collect::<Vec<User_>>();
 +
 +      for mod_ in creator_and_moderators {
 +        let community_moderator_form = CommunityModeratorForm {
 +          community_id: community.id,
 +          user_id: mod_.id,
 +        };
 +        CommunityModerator::join(&conn, &community_moderator_form)?;
 +      }
 +
 +      Ok(community)
 +    }
 +    Err(e) => Err(Error::from(e)),
 +  }
 +}
 +
 +fn upsert_post(post_form: &PostForm, conn: &PgConnection) -> Result<Post, Error> {
 +  let existing = Post::read_from_apub_id(conn, &post_form.ap_id);
 +  match existing {
 +    Err(NotFound {}) => Ok(Post::create(conn, &post_form)?),
 +    Ok(p) => Ok(Post::update(conn, p.id, &post_form)?),
 +    Err(e) => Err(Error::from(e)),
 +  }
 +}
 +
 +pub fn get_or_fetch_and_insert_remote_post(
 +  post_ap_id: &str,
 +  conn: &PgConnection,
 +) -> Result<Post, Error> {
 +  match Post::read_from_apub_id(conn, post_ap_id) {
 +    Ok(p) => Ok(p),
 +    Err(NotFound {}) => {
 +      debug!("Fetching and creating remote post: {}", post_ap_id);
 +      let post = fetch_remote_object::<PageExt>(&Url::parse(post_ap_id)?)?;
 +      let post_form = PostForm::from_apub(&post, conn)?;
 +      Ok(Post::create(conn, &post_form)?)
 +    }
 +    Err(e) => Err(Error::from(e)),
 +  }
 +}
 +
 +fn upsert_comment(comment_form: &CommentForm, conn: &PgConnection) -> Result<Comment, Error> {
 +  let existing = Comment::read_from_apub_id(conn, &comment_form.ap_id);
 +  match existing {
 +    Err(NotFound {}) => Ok(Comment::create(conn, &comment_form)?),
 +    Ok(p) => Ok(Comment::update(conn, p.id, &comment_form)?),
 +    Err(e) => Err(Error::from(e)),
 +  }
 +}
 +
 +pub fn get_or_fetch_and_insert_remote_comment(
 +  comment_ap_id: &str,
 +  conn: &PgConnection,
 +) -> Result<Comment, Error> {
 +  match Comment::read_from_apub_id(conn, comment_ap_id) {
 +    Ok(p) => Ok(p),
 +    Err(NotFound {}) => {
 +      debug!(
 +        "Fetching and creating remote comment and its parents: {}",
 +        comment_ap_id
 +      );
 +      let comment = fetch_remote_object::<Note>(&Url::parse(comment_ap_id)?)?;
 +      let comment_form = CommentForm::from_apub(&comment, conn)?;
 +      Ok(Comment::create(conn, &comment_form)?)
 +    }
 +    Err(e) => Err(Error::from(e)),
 +  }
 +}
 +
 +// TODO It should not be fetching data from a community outbox.
 +// All posts, comments, comment likes, etc should be posts to our community_inbox
 +// The only data we should be periodically fetching (if it hasn't been fetched in the last day
 +// maybe), is community and user actors
 +// and user actors
 +// Fetch all posts in the outbox of the given user, and insert them into the database.
 +// fn fetch_community_outbox(community: &Community, conn: &PgConnection) -> Result<Vec<Post>, Error> {
 +//   let outbox_url = Url::parse(&community.get_outbox_url())?;
 +//   let outbox = fetch_remote_object::<OrderedCollection>(&outbox_url)?;
 +//   let items = outbox.collection_props.get_many_items_base_boxes();
 +
 +//   Ok(
 +//     items
 +//       .unwrap()
 +//       .map(|obox: &BaseBox| -> Result<PostForm, Error> {
 +//         let page = obox.clone().to_concrete::<Page>()?;
 +//         PostForm::from_page(&page, conn)
 +//       })
 +//       .map(|pf| upsert_post(&pf?, conn))
 +//       .collect::<Result<Vec<Post>, Error>>()?,
 +//   )
 +// }
index 6a2d6cffb385b7a12a427fff7a9170a5c50125aa,e224e2591636c033da7a4f65d0c02554b8cf2543..7d2aee65c9101afc113ed27487489ac5218a2910
 +pub mod activities;
 +pub mod comment;
  pub mod community;
 +pub mod community_inbox;
 +pub mod extensions;
 +pub mod fetcher;
  pub mod post;
 +pub mod private_message;
 +pub mod shared_inbox;
  pub mod user;
 -use crate::Settings;
 -
 -use std::fmt::Display;
 -
 -#[cfg(test)]
 -mod tests {
 -  use crate::db::community::Community;
 -  use crate::db::post::Post;
 -  use crate::db::user::User_;
 -  use crate::db::{ListingType, SortType};
 -  use crate::{naive_now, Settings};
 -
 -  #[test]
 -  fn test_person() {
 -    let user = User_ {
 -      id: 52,
 -      name: "thom".into(),
 -      fedi_name: "rrf".into(),
 -      preferred_username: None,
 -      password_encrypted: "here".into(),
 -      email: None,
 -      matrix_user_id: None,
 -      avatar: None,
 -      published: naive_now(),
 -      admin: false,
 -      banned: false,
 -      updated: None,
 -      show_nsfw: false,
 -      theme: "darkly".into(),
 -      default_sort_type: SortType::Hot as i16,
 -      default_listing_type: ListingType::Subscribed as i16,
 -      lang: "browser".into(),
 -      show_avatars: true,
 -      send_notifications_to_email: false,
 -    };
 -
 -    let person = user.as_person();
 -    assert_eq!(
 -      format!("https://{}/federation/u/thom", Settings::get().hostname),
 -      person.object_props.id_string().unwrap()
 -    );
 +pub mod user_inbox;
 +
 +use crate::{
 +  apub::extensions::{
 +    group_extensions::GroupExtension,
 +    page_extension::PageExtension,
 +    signatures::{PublicKey, PublicKeyExtension},
 +  },
 +  convert_datetime,
 +  db::user::User_,
 +  routes::webfinger::WebFingerResponse,
 +  MentionData,
 +  Settings,
 +};
 +use activitystreams::{
 +  actor::{properties::ApActorProperties, Group, Person},
 +  object::Page,
 +};
 +use activitystreams_ext::{Ext1, Ext2, Ext3};
 +use activitystreams_new::{activity::Follow, object::Tombstone, prelude::*};
 +use actix_web::{body::Body, HttpResponse, Result};
 +use chrono::NaiveDateTime;
 +use diesel::PgConnection;
 +use failure::Error;
- use isahc::prelude::*;
 +use log::debug;
 +use serde::Serialize;
 +use url::Url;
 +
 +type GroupExt = Ext3<Group, GroupExtension, ApActorProperties, PublicKeyExtension>;
 +type PersonExt = Ext2<Person, ApActorProperties, PublicKeyExtension>;
 +type PageExt = Ext1<Page, PageExtension>;
 +
 +pub static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json";
 +
 +pub enum EndpointType {
 +  Community,
 +  User,
 +  Post,
 +  Comment,
 +  PrivateMessage,
 +}
 +
 +/// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
 +/// headers.
 +fn create_apub_response<T>(data: &T) -> HttpResponse<Body>
 +where
 +  T: Serialize,
 +{
 +  HttpResponse::Ok()
 +    .content_type(APUB_JSON_CONTENT_TYPE)
 +    .json(data)
 +}
 +
 +fn create_apub_tombstone_response<T>(data: &T) -> HttpResponse<Body>
 +where
 +  T: Serialize,
 +{
 +  HttpResponse::Gone()
 +    .content_type(APUB_JSON_CONTENT_TYPE)
 +    .json(data)
 +}
 +
 +/// Generates the ActivityPub ID for a given object type and ID.
 +pub fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url {
 +  let point = match endpoint_type {
 +    EndpointType::Community => "c",
 +    EndpointType::User => "u",
 +    EndpointType::Post => "post",
 +    EndpointType::Comment => "comment",
 +    EndpointType::PrivateMessage => "private_message",
 +  };
 +
 +  Url::parse(&format!(
 +    "{}://{}/{}/{}",
 +    get_apub_protocol_string(),
 +    Settings::get().hostname,
 +    point,
 +    name
 +  ))
 +  .unwrap()
 +}
 +
 +pub fn get_apub_protocol_string() -> &'static str {
 +  if Settings::get().federation.tls_enabled {
 +    "https"
 +  } else {
 +    "http"
 +  }
 +}
 +
 +// Checks if the ID has a valid format, correct scheme, and is in the allowed instance list.
 +fn is_apub_id_valid(apub_id: &Url) -> bool {
 +  if apub_id.scheme() != get_apub_protocol_string() {
 +    return false;
    }
  
 -  #[test]
 -  fn test_community() {
 -    let community = Community {
 -      id: 42,
 -      name: "Test".into(),
 -      title: "Test Title".into(),
 -      description: Some("Test community".into()),
 -      category_id: 32,
 -      creator_id: 52,
 -      removed: false,
 -      published: naive_now(),
 -      updated: Some(naive_now()),
 -      deleted: false,
 -      nsfw: false,
 -    };
 -
 -    let group = community.as_group();
 -    assert_eq!(
 -      format!("https://{}/federation/c/Test", Settings::get().hostname),
 -      group.object_props.id_string().unwrap()
 -    );
 +  let allowed_instances: Vec<String> = Settings::get()
 +    .federation
 +    .allowed_instances
 +    .split(',')
 +    .map(|d| d.to_string())
 +    .collect();
 +  match apub_id.domain() {
 +    Some(d) => allowed_instances.contains(&d.to_owned()),
 +    None => false,
    }
 +}
 +
 +pub trait ToApub {
 +  type Response;
 +  fn to_apub(&self, conn: &PgConnection) -> Result<Self::Response, Error>;
 +  fn to_tombstone(&self) -> Result<Tombstone, Error>;
 +}
  
 -  #[test]
 -  fn test_post() {
 -    let post = Post {
 -      id: 62,
 -      name: "A test post".into(),
 -      url: None,
 -      body: None,
 -      creator_id: 52,
 -      community_id: 42,
 -      published: naive_now(),
 -      removed: false,
 -      locked: false,
 -      stickied: false,
 -      nsfw: false,
 -      deleted: false,
 -      updated: None,
 -      embed_title: None,
 -      embed_description: None,
 -      embed_html: None,
 -      thumbnail_url: None,
 -    };
 -
 -    let page = post.as_page();
 -    assert_eq!(
 -      format!("https://{}/federation/post/62", Settings::get().hostname),
 -      page.object_props.id_string().unwrap()
 -    );
 +/// Updated is actually the deletion time
 +fn create_tombstone(
 +  deleted: bool,
 +  object_id: &str,
 +  updated: Option<NaiveDateTime>,
 +  former_type: String,
 +) -> Result<Tombstone, Error> {
 +  if deleted {
 +    if let Some(updated) = updated {
 +      let mut tombstone = Tombstone::new();
 +      tombstone.set_id(object_id.parse()?);
 +      tombstone.set_former_type(former_type);
 +      tombstone.set_deleted(convert_datetime(updated).into());
 +      Ok(tombstone)
 +    } else {
 +      Err(format_err!(
 +        "Cant convert to tombstone because updated time was None."
 +      ))
 +    }
 +  } else {
 +    Err(format_err!(
 +      "Cant convert object to tombstone if it wasnt deleted"
 +    ))
    }
  }
  
 -pub fn make_apub_endpoint<S: Display, T: Display>(point: S, value: T) -> String {
 +pub trait FromApub {
 +  type ApubType;
 +  fn from_apub(apub: &Self::ApubType, conn: &PgConnection) -> Result<Self, Error>
 +  where
 +    Self: Sized;
 +}
 +
 +pub trait ApubObjectType {
 +  fn send_create(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>;
 +  fn send_update(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>;
 +  fn send_delete(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>;
 +  fn send_undo_delete(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>;
 +  fn send_remove(&self, mod_: &User_, conn: &PgConnection) -> Result<(), Error>;
 +  fn send_undo_remove(&self, mod_: &User_, conn: &PgConnection) -> Result<(), Error>;
 +}
 +
 +pub trait ApubLikeableType {
 +  fn send_like(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>;
 +  fn send_dislike(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>;
 +  fn send_undo_like(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>;
 +}
 +
 +pub fn get_shared_inbox(actor_id: &str) -> String {
 +  let url = Url::parse(actor_id).unwrap();
    format!(
 -    "https://{}/federation/{}/{}",
 -    Settings::get().hostname,
 -    point,
 -    value
 +    "{}://{}{}/inbox",
 +    &url.scheme(),
 +    &url.host_str().unwrap(),
 +    if let Some(port) = url.port() {
 +      format!(":{}", port)
 +    } else {
 +      "".to_string()
 +    },
    )
  }
-   let text = isahc::get(&fetch_url)?.text()?;
 +
 +pub trait ActorType {
 +  fn actor_id(&self) -> String;
 +
 +  fn public_key(&self) -> String;
 +  fn private_key(&self) -> String;
 +
 +  // These two have default impls, since currently a community can't follow anything,
 +  // and a user can't be followed (yet)
 +  #[allow(unused_variables)]
 +  fn send_follow(&self, follow_actor_id: &str, conn: &PgConnection) -> Result<(), Error>;
 +  fn send_unfollow(&self, follow_actor_id: &str, conn: &PgConnection) -> Result<(), Error>;
 +
 +  #[allow(unused_variables)]
 +  fn send_accept_follow(&self, follow: &Follow, conn: &PgConnection) -> Result<(), Error>;
 +
 +  fn send_delete(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>;
 +  fn send_undo_delete(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>;
 +
 +  fn send_remove(&self, mod_: &User_, conn: &PgConnection) -> Result<(), Error>;
 +  fn send_undo_remove(&self, mod_: &User_, conn: &PgConnection) -> Result<(), Error>;
 +
 +  /// For a given community, returns the inboxes of all followers.
 +  fn get_follower_inboxes(&self, conn: &PgConnection) -> Result<Vec<String>, Error>;
 +
 +  // TODO move these to the db rows
 +  fn get_inbox_url(&self) -> String {
 +    format!("{}/inbox", &self.actor_id())
 +  }
 +
 +  fn get_shared_inbox_url(&self) -> String {
 +    get_shared_inbox(&self.actor_id())
 +  }
 +
 +  fn get_outbox_url(&self) -> String {
 +    format!("{}/outbox", &self.actor_id())
 +  }
 +
 +  fn get_followers_url(&self) -> String {
 +    format!("{}/followers", &self.actor_id())
 +  }
 +
 +  fn get_following_url(&self) -> String {
 +    format!("{}/following", &self.actor_id())
 +  }
 +
 +  fn get_liked_url(&self) -> String {
 +    format!("{}/liked", &self.actor_id())
 +  }
 +
 +  fn get_public_key_ext(&self) -> PublicKeyExtension {
 +    PublicKey {
 +      id: format!("{}#main-key", self.actor_id()),
 +      owner: self.actor_id(),
 +      public_key_pem: self.public_key(),
 +    }
 +    .to_ext()
 +  }
 +}
 +
 +pub fn fetch_webfinger_url(mention: &MentionData) -> Result<String, Error> {
 +  let fetch_url = format!(
 +    "{}://{}/.well-known/webfinger?resource=acct:{}@{}",
 +    get_apub_protocol_string(),
 +    mention.domain,
 +    mention.name,
 +    mention.domain
 +  );
 +  debug!("Fetching webfinger url: {}", &fetch_url);
++  let text: String = attohttpc::get(&fetch_url).send()?.text()?;
 +  let res: WebFingerResponse = serde_json::from_str(&text)?;
 +  let link = res
 +    .links
 +    .iter()
 +    .find(|l| l.type_.eq(&Some("application/activity+json".to_string())))
 +    .ok_or_else(|| format_err!("No application/activity+json link found."))?;
 +  link
 +    .href
 +    .to_owned()
 +    .ok_or_else(|| format_err!("No href found."))
 +}
index 32c374390e8bc37769cdbaa30ec2e0d5136393e4,ebfe17d9c9ef803c3863a2ab52ca83ca4e45f937..2391449caf818155ebc3c500c6d15537030259d8
@@@ -36,21 -34,12 +36,20 @@@ pub mod settings
  pub mod version;
  pub mod websocket;
  
 +use crate::settings::Settings;
  use actix_web::dev::ConnectionInfo;
 -use chrono::{DateTime, NaiveDateTime, Utc};
 -use lettre::smtp::authentication::{Credentials, Mechanism};
 -use lettre::smtp::extension::ClientId;
 -use lettre::smtp::ConnectionReuseParameters;
 -use lettre::{ClientSecurity, SmtpClient, Transport};
 +use chrono::{DateTime, FixedOffset, Local, NaiveDateTime, Utc};
- use isahc::prelude::*;
 +use itertools::Itertools;
 +use lettre::{
 +  smtp::{
 +    authentication::{Credentials, Mechanism},
 +    extension::ClientId,
 +    ConnectionReuseParameters,
 +  },
 +  ClientSecurity,
 +  SmtpClient,
 +  Transport,
 +};
  use lettre_email::Email;
  use log::error;
  use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
@@@ -301,25 -290,10 +315,26 @@@ pub fn is_valid_community_name(name: &s
  #[cfg(test)]
  mod tests {
    use crate::{
 -    extract_usernames, is_email_regex, is_image_content_type, is_valid_community_name,
 -    is_valid_username, remove_slurs, slur_check, slurs_vec_to_str,
 +    is_email_regex,
 +    is_image_content_type,
++    is_valid_community_name,
 +    is_valid_username,
 +    remove_slurs,
 +    scrape_text_for_mentions,
 +    slur_check,
 +    slurs_vec_to_str,
    };
  
 +  #[test]
 +  fn test_mentions_regex() {
 +    let text = "Just read a great blog post by [@tedu@honk.teduangst.com](/u/test). And another by !test_community@fish.teduangst.com . Another [@lemmy@lemmy_alpha:8540](/u/fish)";
 +    let mentions = scrape_text_for_mentions(text);
 +
 +    assert_eq!(mentions[0].name, "tedu".to_string());
 +    assert_eq!(mentions[0].domain, "honk.teduangst.com".to_string());
 +    assert_eq!(mentions[1].domain, "lemmy_alpha:8540".to_string());
 +  }
 +
    #[test]
    fn test_image() {
      assert!(is_image_content_type("https://1734811051.rsc.cdn77.org/data/images/full/365645/as-virus-kills-navajos-in-their-homes-tribal-women-provide-lifeline.jpg?w=600?w=650").is_ok());
@@@ -398,8 -388,6 +422,9 @@@ lazy_static! 
    static ref EMAIL_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$").unwrap();
    static ref SLUR_REGEX: Regex = RegexBuilder::new(r"(fag(g|got|tard)?|maricos?|cock\s?sucker(s|ing)?|nig(\b|g?(a|er)?(s|z)?)\b|dindu(s?)|mudslime?s?|kikes?|mongoloids?|towel\s*heads?|\bspi(c|k)s?\b|\bchinks?|niglets?|beaners?|\bnips?\b|\bcoons?\b|jungle\s*bunn(y|ies?)|jigg?aboo?s?|\bpakis?\b|rag\s*heads?|gooks?|cunts?|bitch(es|ing|y)?|puss(y|ies?)|twats?|feminazis?|whor(es?|ing)|\bslut(s|t?y)?|\btrann?(y|ies?)|ladyboy(s?)|\b(b|re|r)tard(ed)?s?)").case_insensitive(true).build().unwrap();
    static ref USERNAME_MATCHES_REGEX: Regex = Regex::new(r"/u/[a-zA-Z][0-9a-zA-Z_]*").unwrap();
 +  // TODO keep this old one, it didn't work with port well tho
 +  // static ref WEBFINGER_USER_REGEX: Regex = Regex::new(r"@(?P<name>[\w.]+)@(?P<domain>[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)").unwrap();
 +  static ref WEBFINGER_USER_REGEX: Regex = Regex::new(r"@(?P<name>[\w.]+)@(?P<domain>[a-zA-Z0-9._:-]+)").unwrap();
    static ref VALID_USERNAME_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9_]{3,20}$").unwrap();
+   static ref VALID_COMMUNITY_NAME_REGEX: Regex = Regex::new(r"^[a-z0-9_]{3,20}$").unwrap();
  }
Simple merge
index 22224c344af941f312ed08fab90864b57e0dbe93,c507ab3e700378c83bfb82916276c61aa032ae03..9f5aa363e63726d0566c00acd6407033b70be185
@@@ -35,7 -35,7 +35,8 @@@ import 
    setupTribute,
    setupTippy,
    emojiPicker,
 +  hostname,
+   pictrsDeleteToast,
  } from '../utils';
  import autosize from 'autosize';
  import Tribute from 'tributejs/src/Tribute.js';
index def42e3c3688d2e0a22ef0431bf0a32db439d463,7d10acf72139bd41586fa5e3299fa3b548498175..b4cc4f928298e82549fc8f395c66fdea751aa6d3
@@@ -29,9 -28,8 +29,9 @@@ import 
    isImage,
    isVideo,
    getUnixTime,
-   pictshareImage,
+   pictrsImage,
    setupTippy,
 +  hostname,
    previewLines,
  } from '../utils';
  import { i18n } from '../i18next';
index 903aa1a7550638da52250f2399eedc963afbb4cf,ea87fd3aae778d8313853abe0ffbccc8d053fcc6..0e150b9420d3468d61cadd01ea229ab2dca01c54
@@@ -1,7 -1,7 +1,7 @@@
  import { Component } from 'inferno';
  import { Link } from 'inferno-router';
  import { UserView } from '../interfaces';
- import { pictshareAvatarThumbnail, showAvatars, hostname } from '../utils';
 -import { pictrsAvatarThumbnail, showAvatars } from '../utils';
++import { pictrsAvatarThumbnail, showAvatars, hostname } from '../utils';
  
  interface UserOther {
    name: string;
Simple merge
diff --cc ui/src/utils.ts
Simple merge