├── .gitignore ├── www1 ├── slidocli-web-interface.png ├── post.php ├── README.md └── index.html ├── www2 ├── slidocli-web-interface.png ├── README.md ├── vote.php ├── index.html ├── index.php └── fetch.php ├── terraform ├── outputs.tf ├── userdata.tpl ├── variables.tf ├── README.md ├── main.tf └── Makefile ├── docker ├── default.conf ├── docker-compose.yml └── README.md ├── LICENSE ├── README.md └── slidocli /.gitignore: -------------------------------------------------------------------------------- 1 | terraform.tfvars 2 | terraform.tfstate* 3 | .terraform/ 4 | -------------------------------------------------------------------------------- /www1/slidocli-web-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cytopia/slidocli/master/www1/slidocli-web-interface.png -------------------------------------------------------------------------------- /www2/slidocli-web-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cytopia/slidocli/master/www2/slidocli-web-interface.png -------------------------------------------------------------------------------- /terraform/outputs.tf: -------------------------------------------------------------------------------- 1 | output "public_ip" { 2 | description = "Public IP address of EC2 instance containing slidocli web interface" 3 | value = aws_instance.web.public_ip 4 | } 5 | 6 | output "slidocli_web_uri" { 7 | description = "Slidocli web interface uri" 8 | value = "http://${aws_instance.web.public_ip}:${var.slidocli_port}" 9 | } 10 | -------------------------------------------------------------------------------- /docker/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | root /var/www/html/site; 4 | index index.html index.php; 5 | location ~ \.php$ { 6 | fastcgi_pass php-fpm:9000; 7 | fastcgi_index index.php; 8 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 9 | include fastcgi_params; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /www1/post.php: -------------------------------------------------------------------------------- 1 | 14 | ## Inputs 15 | 16 | | Name | Description | Type | Default | Required | 17 | |------|-------------|:----:|:-----:|:-----:| 18 | | instance\_type | AWS EC2 instance type to use for slidocli server | string | `"t3.nano"` | no | 19 | | slidocli\_port | Port for slidocli web interface | string | `"8080"` | no | 20 | | tags | Tags to add to all resources | map | `{ "Name": "slidocli" }` | no | 21 | | vpc\_cidr | VPC CIDR | string | `"10.0.0.0/16"` | no | 22 | | vpc\_subnet\_cidr | Subnet CIDR | string | `"10.0.1.0/24"` | no | 23 | 24 | ## Outputs 25 | 26 | | Name | Description | 27 | |------|-------------| 28 | | public\_ip | Public IP address of EC2 instance containing slidocli web interface | 29 | | slidocli\_web\_uri | Slidocli web interface uri | 30 | 31 | 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 cytopia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /www2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | 15 |
16 |

slidocli web interface

17 | Enter sli.do url and hit fire to retrieve the voting pannel.
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
sli.do url
29 |
30 | 31 |
32 |
33 | 34 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /www1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |

slidocli web interface

6 | Enter sli.do url and hit fire to retrieve questions and their ids.
7 | Once you have the id of your question, enter the sli.do url and the corresponding
8 | question id to upvote your question. Unlimited upvotes supported for any question.
9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
sli.do url
sli.do question id
24 | 25 |

Log

26 |

27 | 
28 | 
29 | 30 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /www2/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | 15 |
16 |

slidocli web interface

17 | Enter sli.do url and hit fire to retrieve the voting pannel.
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
sli.do url
29 |
30 | 31 |
32 |
33 | 34 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /www2/fetch.php: -------------------------------------------------------------------------------- 1 | '; 62 | echo ''; 63 | echo 'Action'; 64 | echo 'Qid'; 65 | echo 'Score'; 66 | echo 'Question'; 67 | echo ''; 68 | foreach ($array as $q) { 69 | echo ''; 70 | echo ''; 71 | echo ''.$q['qid'].''; 72 | echo '
'.$q['vote'].'
'; 73 | echo ''.$q['question'].''; 74 | echo ''; 75 | } 76 | echo ''; 77 | } else { 78 | printf("Error, url is missing\n"); 79 | } 80 | -------------------------------------------------------------------------------- /terraform/main.tf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- 2 | # Networking Infrastructure 3 | # -------------------------------------------------------------------------------- 4 | resource "aws_vpc" "main" { 5 | cidr_block = var.vpc_cidr 6 | 7 | tags = var.tags 8 | } 9 | 10 | resource "aws_subnet" "main" { 11 | vpc_id = aws_vpc.main.id 12 | cidr_block = var.vpc_subnet_cidr 13 | 14 | tags = var.tags 15 | } 16 | 17 | resource "aws_internet_gateway" "igw" { 18 | vpc_id = aws_vpc.main.id 19 | tags = var.tags 20 | } 21 | 22 | # -------------------------------------------------------------------------------- 23 | # Networking Routing 24 | # -------------------------------------------------------------------------------- 25 | resource "aws_route_table" "main" { 26 | vpc_id = aws_vpc.main.id 27 | route { 28 | cidr_block = "0.0.0.0/0" 29 | gateway_id = aws_internet_gateway.igw.id 30 | } 31 | tags = var.tags 32 | } 33 | 34 | resource "aws_route_table_association" "main_rt_assoc" { 35 | subnet_id = aws_subnet.main.id 36 | route_table_id = aws_route_table.main.id 37 | } 38 | 39 | # -------------------------------------------------------------------------------- 40 | # Security 41 | # -------------------------------------------------------------------------------- 42 | resource "aws_security_group" "web" { 43 | name_prefix = "slidocli" 44 | vpc_id = aws_vpc.main.id 45 | 46 | ingress { 47 | from_port = var.slidocli_port 48 | to_port = var.slidocli_port 49 | protocol = "tcp" 50 | cidr_blocks = ["0.0.0.0/0"] 51 | } 52 | egress { 53 | from_port = 0 54 | to_port = 0 55 | protocol = "-1" 56 | cidr_blocks = ["0.0.0.0/0"] 57 | } 58 | tags = var.tags 59 | 60 | lifecycle { 61 | create_before_destroy = true 62 | } 63 | } 64 | 65 | # -------------------------------------------------------------------------------- 66 | # EC2 instance 67 | # -------------------------------------------------------------------------------- 68 | data "aws_ami" "ubuntu" { 69 | most_recent = true 70 | 71 | filter { 72 | name = "name" 73 | values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] 74 | } 75 | 76 | filter { 77 | name = "virtualization-type" 78 | values = ["hvm"] 79 | } 80 | 81 | owners = ["099720109477"] # Canonical 82 | } 83 | 84 | data "template_file" "user_data" { 85 | template = file("${path.module}/userdata.tpl") 86 | 87 | vars = { 88 | slido_port = var.slidocli_port 89 | } 90 | } 91 | 92 | resource "aws_instance" "web" { 93 | ami = data.aws_ami.ubuntu.id 94 | instance_type = var.instance_type 95 | 96 | user_data = data.template_file.user_data.rendered 97 | 98 | associate_public_ip_address = true 99 | vpc_security_group_ids = [aws_security_group.web.id] 100 | subnet_id = aws_subnet.main.id 101 | 102 | tags = var.tags 103 | } 104 | -------------------------------------------------------------------------------- /terraform/Makefile: -------------------------------------------------------------------------------- 1 | ifneq (,) 2 | .error This Makefile requires GNU Make. 3 | endif 4 | 5 | .PHONY: help gen lint test _lint_files _lint_fmt _pull-tf _pull-tf-docs 6 | 7 | CURRENT_DIR = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) 8 | TF_EXAMPLES = $(sort $(dir $(wildcard $(CURRENT_DIR)examples/*/))) 9 | TF_MODULES = $(sort $(dir $(wildcard $(CURRENT_DIR)modules/*/))) 10 | 11 | TF_VERSION = light 12 | TF_DOCS_VERSION = 0.6.0 13 | 14 | # Adjust your delimiter here or overwrite via make arguments 15 | DELIM_START = 16 | DELIM_CLOSE = 17 | 18 | help: 19 | @echo "gen Generate terraform-docs output and replace in all README.md's" 20 | @echo "lint Static source code analysis" 21 | @echo "test Integration tests" 22 | 23 | gen: _pull-tf-docs 24 | @echo "################################################################################" 25 | @echo "# Terraform-docs generate" 26 | @echo "################################################################################" 27 | @if docker run --rm \ 28 | -v $(CURRENT_DIR):/data \ 29 | -e DELIM_START='$(DELIM_START)' \ 30 | -e DELIM_CLOSE='$(DELIM_CLOSE)' \ 31 | cytopia/terraform-docs:$(TF_DOCS_VERSION) \ 32 | terraform-docs-replace-012 --sort-inputs-by-required --with-aggregate-type-defaults md README.md; then \ 33 | echo "OK"; \ 34 | else \ 35 | echo "Failed"; \ 36 | exit 1; \ 37 | fi 38 | 39 | lint: _pull-tf 40 | @$(MAKE) --no-print-directory _lint_files 41 | @$(MAKE) --no-print-directory _lint_fmt 42 | 43 | test: _pull-tf 44 | @$(foreach example,\ 45 | $(TF_EXAMPLES),\ 46 | DOCKER_PATH="/t/examples/$(notdir $(patsubst %/,%,$(example)))"; \ 47 | echo "################################################################################"; \ 48 | echo "# examples/$$( basename $${DOCKER_PATH} )"; \ 49 | echo "################################################################################"; \ 50 | echo; \ 51 | echo "------------------------------------------------------------"; \ 52 | echo "# Terraform init"; \ 53 | echo "------------------------------------------------------------"; \ 54 | if docker run -it --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" hashicorp/terraform:$(TF_VERSION) \ 55 | init \ 56 | -verify-plugins=true \ 57 | -lock=false \ 58 | -upgrade=true \ 59 | -reconfigure \ 60 | -input=false \ 61 | -get-plugins=true \ 62 | -get=true \ 63 | .; then \ 64 | echo "OK"; \ 65 | else \ 66 | echo "Failed"; \ 67 | docker run -it --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" --entrypoint=rm hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \ 68 | exit 1; \ 69 | fi; \ 70 | echo; \ 71 | echo "------------------------------------------------------------"; \ 72 | echo "# Terraform validate"; \ 73 | echo "------------------------------------------------------------"; \ 74 | if docker run -it --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" hashicorp/terraform:$(TF_VERSION) \ 75 | validate \ 76 | $(ARGS) \ 77 | .; then \ 78 | echo "OK"; \ 79 | docker run -it --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" --entrypoint=rm hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \ 80 | else \ 81 | echo "Failed"; \ 82 | docker run -it --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" --entrypoint=rm hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \ 83 | exit 1; \ 84 | fi; \ 85 | echo; \ 86 | ) 87 | 88 | _lint_files: 89 | @# Lint all non-binary files for trailing spaces 90 | @echo "################################################################################" 91 | @echo "# Lint files" 92 | @echo "################################################################################" 93 | @echo 94 | @echo "------------------------------------------------------------" 95 | @echo "# Trailing spaces" 96 | @echo "------------------------------------------------------------" 97 | find . -type f -not \( -path "*/.git/*" -o -path "*/.github/*" -o -path "*/.terraform/*" \) -print0 \ 98 | | xargs -0 -n1 grep -Il '' \ 99 | | tr '\n' '\0' \ 100 | | xargs -0 -n1 \ 101 | sh -c 'if [ -f "$${1}" ]; then if LC_ALL=C grep --color=always -inHE "^.*[[:blank:]]+$$" "$${1}";then false; else true; fi; fi' -- 102 | @echo 103 | @echo "------------------------------------------------------------" 104 | @echo "# Windows line feeds (CRLF)" 105 | @echo "------------------------------------------------------------" 106 | find . -type f -not \( -path "*/.git/*" -o -path "*/.github/*" -o -path "*/.terraform/*" \) -print0 \ 107 | | xargs -0 -n1 grep -Il '' \ 108 | | tr '\n' '\0' \ 109 | | xargs -0 -n1 \ 110 | sh -c 'if [ -f "$${1}" ]; then if file "$${1}" | grep --color=always -E "[[:space:]]CRLF[[:space:]].*line"; then false; else true; fi; fi' -- 111 | @echo 112 | @echo "------------------------------------------------------------" 113 | @echo "# Single trailing newline" 114 | @echo "------------------------------------------------------------" 115 | find . -type f -not \( -path "*/.git/*" -o -path "*/.github/*" -o -path "*/.terraform/*" \) -print0 \ 116 | | xargs -0 -n1 grep -Il '' \ 117 | | tr '\n' '\0' \ 118 | | xargs -0 -n1 \ 119 | sh -c 'if [ -f "$${1}" ]; then if ! (tail -c 1 "$${1}" | grep -Eq "^$$" && tail -c 2 "$${1}" | grep -Eqv "^$$"); then echo "$${1}"; false; else true; fi; fi' -- 120 | @echo 121 | 122 | _lint_fmt: 123 | @# Lint all Terraform files 124 | @echo "################################################################################" 125 | @echo "# Terraform fmt" 126 | @echo "################################################################################" 127 | @echo 128 | @echo "------------------------------------------------------------" 129 | @echo "# *.tf files" 130 | @echo "------------------------------------------------------------" 131 | @if docker run --rm -v "$(CURRENT_DIR):/t:ro" --workdir "/t" hashicorp/terraform:$(TF_VERSION) \ 132 | fmt -check=true -diff=true -write=false -list=true /t; then \ 133 | echo "OK"; \ 134 | else \ 135 | echo "Failed"; \ 136 | exit 1; \ 137 | fi; 138 | @echo 139 | @echo "------------------------------------------------------------" 140 | @echo "# *.tfvars files" 141 | @echo "------------------------------------------------------------" 142 | @if docker run --rm --entrypoint=/bin/sh -v "$(CURRENT_DIR)/terraform:/t:ro" hashicorp/terraform:$(TF_VERSION) \ 143 | -c "find . -name '*.tfvars' -type f -print0 | xargs -0 -n1 terraform fmt -check=true -write=false -diff=true -list=true"; then \ 144 | echo "OK"; \ 145 | else \ 146 | echo "Failed"; \ 147 | exit 1; \ 148 | fi; 149 | @echo 150 | 151 | _pull-tf: 152 | docker pull hashicorp/terraform:$(TF_VERSION) 153 | 154 | _pull-tf-docs: 155 | docker pull cytopia/terraform-docs:$(TF_DOCS_VERSION) 156 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # slidocli 2 | 3 | Command line utility to list available questions on sli.do and 4 | automatically upvote any question specified by their id. 5 | 6 | ``` 7 | 8 | ██████ ██▓ ██▓▓█████▄ ▒█████ ▄████▄ ██▓ ██▓ 9 | ▒██ ▒ ▓██▒ ▓██▒▒██▀ ██▌▒██▒ ██▒▒██▀ ▀█ ▓██▒ ▓██▒ 10 | ░ ▓██▄ ▒██░ ▒██▒░██ █▌▒██░ ██▒▒▓█ ▄ ▒██░ ▒██▒ 11 | ▒ ██▒▒██░ ░██░░▓█▄ ▌▒██ ██░▒▓▓▄ ▄██▒▒██░ ░██░ 12 | ▒██████▒▒░██████▒░██░░▒████▓ ░ ████▓▒░▒ ▓███▀ ░░██████▒░██░ 13 | ▒ ▒▓▒ ▒ ░░ ▒░▓ ░░▓ ▒▒▓ ▒ ░ ▒░▒░▒░ ░ ░▒ ▒ ░░ ▒░▓ ░░▓ 14 | ░ ░▒ ░ ░░ ░ ▒ ░ ▒ ░ ░ ▒ ▒ ░ ▒ ▒░ ░ ▒ ░ ░ ▒ ░ ▒ ░ 15 | ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░ 16 | ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ 17 | ░ ░ 18 | ``` 19 | 20 | 21 | ## Usage 22 | ``` 23 | USAGE: slidocli [-v] [-d] [-q question-id] SLIDO-URL 24 | slidocli -h 25 | 26 | DESCRIPTION: 27 | Command line utility to list available questions on sli.do and 28 | automatically upvote any question specified by their id. 29 | If only the SLIDO-URL is specified, this tool lists available questions 30 | and their according ids. To upvote a question, use -q. 31 | 32 | ARGUMENTS: 33 | -v Be verbose: show curl requests. 34 | -d Dump curl output to file for later inspection. 35 | -q question-id The question to upvote. 36 | 37 | DISCLAIMER: 38 | This tool is for educational purposes only and must not be used to 39 | upvote any questions on sli.do, as it most likely violates their 40 | terms and services. Use at your own risk. 41 | https://www.sli.do/acceptable-use 42 | 43 | EXAMPLES: 44 | List all questions of an event: 45 | $ slidocli https://app.sli.do/event/abcdef123 46 | 47 | Upvote a specific question of an event: 48 | $ slidocli -q '1234567' https://app.sli.do/event/abcdef123 49 | 50 | Upvote 3 times: 51 | $ for i in `seq 3`; do slidocli -q '1234567' https://app.sli.do/event/abcdef123; done 52 | 53 | Upvote 3 times with 10 sec break in between: 54 | $ for i in `seq 3`; do slidocli -q '1234567' https://app.sli.do/event/abcdef123; sleep 10; done 55 | ``` 56 | 57 | 58 | ## Examples 59 | 60 | ### List questions 61 | ``` 62 | $ slidocli https://app.sli.do/event/abcdef123 63 | 64 | ██████ ██▓ ██▓▓█████▄ ▒█████ ▄████▄ ██▓ ██▓ 65 | ▒██ ▒ ▓██▒ ▓██▒▒██▀ ██▌▒██▒ ██▒▒██▀ ▀█ ▓██▒ ▓██▒ 66 | ░ ▓██▄ ▒██░ ▒██▒░██ █▌▒██░ ██▒▒▓█ ▄ ▒██░ ▒██▒ 67 | ▒ ██▒▒██░ ░██░░▓█▄ ▌▒██ ██░▒▓▓▄ ▄██▒▒██░ ░██░ 68 | ▒██████▒▒░██████▒░██░░▒████▓ ░ ████▓▒░▒ ▓███▀ ░░██████▒░██░ 69 | ▒ ▒▓▒ ▒ ░░ ▒░▓ ░░▓ ▒▒▓ ▒ ░ ▒░▒░▒░ ░ ░▒ ▒ ░░ ▒░▓ ░░▓ 70 | ░ ░▒ ░ ░░ ░ ▒ ░ ▒ ░ ░ ▒ ▒ ░ ▒ ▒░ ░ ▒ ░ ░ ▒ ░ ▒ ░ 71 | ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░ 72 | ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ 73 | ░ ░ 74 | 75 | Use at your own risk and adhere to sli.do terms and services 76 | 77 | v0.1 (2019-09-13) 78 | https://github.com/cytopia/slidocli 79 | By cytopia 80 | 81 | ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 82 | 83 | 84 | INITIALIZING 85 | 86 | Request URL: https://app.sli.do/event/abcdef123 87 | Slido URL: https://app.sli.do/event/abcdef123 88 | Slido hash: abcdef123 89 | Random UA: Mozilla/5.0 (Linux; U; Android-4.0.3; en-us; Galaxy Nexus Buil... 90 | Random DNT: 1 91 | Cookie path: /tmp/tmp.dUC38JcZ12 92 | Dump path: not set 93 | 94 | GATHERING EVENT DATA 95 | 96 | Slido event URL: https://app.sli.do/api/v0.5/events?hash=abcdef123 97 | Name: Name of the room 98 | Code: AB123 99 | Event ID: 12345678 100 | Event Group ID: 333333 101 | UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx 102 | 103 | AUTHENTICATING USER 104 | 105 | Slido auth URL: https://app.sli.do/api/v0.5/events/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/auth 106 | Acess Token: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 107 | Event User ID: 44444444 108 | 109 | AUTHENTICATING EVENT 110 | 111 | Slido auth URL: https://app.sli.do/api/v0.5/events/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx 112 | Event Sect ID: 1234567 113 | Room: Room 1 114 | 115 | LISTING QUESTIONS 116 | 117 | [ 118 | "aaaaaaa", 119 | "26", 120 | "I like sli.do, do others use it as well?" 121 | ] 122 | [ 123 | "bbbbbbb", 124 | "13", 125 | "Do I like sli.do the most?" 126 | ] 127 | ``` 128 | 129 | ### Upvote a question 130 | ``` 131 | $ slidocli -q 'aaaaaaa' https://app.sli.do/event/abcdef123 132 | 133 | ██████ ██▓ ██▓▓█████▄ ▒█████ ▄████▄ ██▓ ██▓ 134 | ▒██ ▒ ▓██▒ ▓██▒▒██▀ ██▌▒██▒ ██▒▒██▀ ▀█ ▓██▒ ▓██▒ 135 | ░ ▓██▄ ▒██░ ▒██▒░██ █▌▒██░ ██▒▒▓█ ▄ ▒██░ ▒██▒ 136 | ▒ ██▒▒██░ ░██░░▓█▄ ▌▒██ ██░▒▓▓▄ ▄██▒▒██░ ░██░ 137 | ▒██████▒▒░██████▒░██░░▒████▓ ░ ████▓▒░▒ ▓███▀ ░░██████▒░██░ 138 | ▒ ▒▓▒ ▒ ░░ ▒░▓ ░░▓ ▒▒▓ ▒ ░ ▒░▒░▒░ ░ ░▒ ▒ ░░ ▒░▓ ░░▓ 139 | ░ ░▒ ░ ░░ ░ ▒ ░ ▒ ░ ░ ▒ ▒ ░ ▒ ▒░ ░ ▒ ░ ░ ▒ ░ ▒ ░ 140 | ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░ 141 | ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ 142 | ░ ░ 143 | 144 | Use at your own risk and adhere to sli.do terms and services 145 | 146 | v0.1 (2019-09-13) 147 | https://github.com/cytopia/slidocli 148 | By cytopia 149 | 150 | ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 151 | 152 | 153 | INITIALIZING 154 | 155 | Request URL: https://app.sli.do/event/abcdef123 156 | Slido URL: https://app.sli.do/event/abcdef123 157 | Slido hash: abcdef123 158 | Random UA: Mozilla/5.0 (Linux; U; Android-4.0.3; en-us; Galaxy Nexus Buil... 159 | Random DNT: 1 160 | Cookie path: /tmp/tmp.dUC38JcZ12 161 | Dump path: not set 162 | 163 | GATHERING EVENT DATA 164 | 165 | Slido event URL: https://app.sli.do/api/v0.5/events?hash=abcdef123 166 | Name: Name of the room 167 | Code: AB123 168 | Event ID: 12345678 169 | Event Group ID: 333333 170 | UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx 171 | 172 | AUTHENTICATING USER 173 | 174 | Slido auth URL: https://app.sli.do/api/v0.5/events/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/auth 175 | Acess Token: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 176 | Event User ID: 44444444 177 | 178 | UPVOTING 179 | 180 | Voted question: aaaaaaa 181 | New score: 27 182 | ``` 183 | 184 | 185 | ## Web interface 186 | 187 | There are also two web interfaces available which make it easier to use it from mobile phones or 188 | tablets. Find them here: [www1](www1/) (more geeky) and [www2](www2/) (more usable). 189 | 190 | In order to quickly spin them up, you can use the bundled [Docker Compose setup](docker/). 191 | 192 | 193 | ## Deploy on AWS with Terraform 194 | 195 | Just for the sake... the whole stack can also be deployed easily on AWS. Check the bundled 196 | [Terraform module](terraform/) 197 | 198 | 199 | ## Disclaimer 200 | 201 | This tool is for educational purposes only and must not be used to 202 | upvote any questions on sli.do, as it most likely violates their 203 | terms and services. Use at your own risk. 204 | https://www.sli.do/acceptable-use 205 | 206 | 207 | ## License 208 | 209 | **[MIT License](LICENSE)** 210 | 211 | Copyright (c) 2019 [cytopia](https://github.com/cytopia) 212 | -------------------------------------------------------------------------------- /slidocli: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -u 5 | set -o pipefail 6 | 7 | 8 | # ------------------------------------------------------------------------------------------------- 9 | # VARIABLES 10 | # ------------------------------------------------------------------------------------------------- 11 | 12 | ### 13 | ### Version information 14 | ### 15 | VERSION_DATE="2019-09-13" 16 | VERSION_NUMBER="v0.1" 17 | VERSION_GITHUB="https://github.com/cytopia/slidocli" 18 | VERSION_AUTHOR="cytopia" 19 | 20 | ### 21 | ### Command line arguments 22 | ### 23 | ARG_QID= 24 | ARG_VERBOSE=0 25 | ARG_DUMP=0 26 | 27 | ### 28 | ### Slido URLs 29 | ### 30 | SLIDO_EVENT_API_URL="https://app.sli.do/api/v0.5/events?hash=__HASH__" 31 | SLIDO_AUTH_USER_URL="https://app.sli.do/api/v0.5/events/__UUID__/auth" 32 | SLIDO_AUTH_EVENT_URL="https://app.sli.do/api/v0.5/events/__UUID__" 33 | SLIDO_QUESTIONS_URL="https://app.sli.do/api/v0.5/events/__UUID__/questions?path=%2Fquestions&eventSectionId=__EVENT_SEC_ID__&sort=top&highlighted_first=true&limit=30" 34 | SLIDO_UPVOTE_URL="https://app.sli.do/api/v0.5/events/__UUID__/questions/__QID__/like" 35 | 36 | 37 | 38 | # ------------------------------------------------------------------------------------------------- 39 | # FUNCTIONS 40 | # ------------------------------------------------------------------------------------------------- 41 | 42 | ### 43 | ### Print usage/help screen 44 | ### 45 | print_usage() { 46 | echo "USAGE: slidocli [-v] [-d] [-q question-id] SLIDO-URL" 47 | echo " slidocli -h" 48 | echo 49 | echo "DESCRIPTION:" 50 | echo " Command line utility to list available questions on sli.do and" 51 | echo " automatically upvote any question specified by their id." 52 | echo " If only the SLIDO-URL is specified, this tool lists available questions" 53 | echo " and their according ids. To upvote a question, use -q." 54 | echo 55 | echo "ARGUMENTS:" 56 | echo " -v Be verbose: show curl requests." 57 | echo " -d Dump curl output to file for later inspection." 58 | echo " -q question-id The question to upvote." 59 | echo 60 | echo "DISCLAIMER:" 61 | echo " This tool is for educational purposes only and must not be used to" 62 | echo " upvote any questions on sli.do, as it most likely violates their" 63 | echo " terms and services. Use at your own risk." 64 | echo " https://www.sli.do/acceptable-use" 65 | echo 66 | echo "EXAMPLES:" 67 | echo " List all questions of an event:" 68 | echo " \$ slidocli https://app.sli.do/event/abcdef123" 69 | echo 70 | echo " Upvote a specific question of an event:" 71 | echo " \$ slidocli -q '1234567' https://app.sli.do/event/abcdef123" 72 | echo 73 | echo " Upvote 3 times:" 74 | echo " \$ for i in \`seq 3\`; do slidocli -q '1234567' https://app.sli.do/event/abcdef123; done" 75 | echo 76 | echo " Upvote 3 times with 10 sec break in between:" 77 | echo " \$ for i in \`seq 3\`; do slidocli -q '1234567' https://app.sli.do/event/abcdef123; sleep 10; done" 78 | } 79 | 80 | 81 | ### 82 | ### Get a random useragent 83 | ### 84 | get_random_ua() { 85 | local ua=( 86 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)" 87 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FSL 7.0.5.01003)" 88 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FSL 7.0.6.01001)" 89 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FSL 7.0.7.01001)" 90 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" 91 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Media Center PC" 92 | "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)" 93 | "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)" 94 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)" 95 | "Mozilla/5.0 (Linux; Android 5.0; SAMSUNG SM-N900 Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36" 96 | "Mozilla/5.0 (Linux; Android 6.0.1; SAMSUNG SM-N910F Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile Safari/537.36" 97 | "Mozilla/5.0 (Linux; U; Android-4.0.3; en-us; Galaxy Nexus Build/IML74K) AppleWebKit/535.7 (KHTML, like Gecko) CrMo/16.0.912.75 Mobile Safari/535.7" 98 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:34.0) Gecko/20100101 Firefox/34.0" 99 | "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-en) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4" 100 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393" 101 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36" 102 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:53.0) Gecko/20100101 Firefox/53.0" 103 | "Mozilla/5.0 (Windows NT 5.1; rv:13.0) Gecko/20100101 Firefox/13.0.1" 104 | "Mozilla/5.0 (Windows NT 5.1; rv:5.0.1) Gecko/20100101 Firefox/5.0.1" 105 | "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.112 Safari/535.1" 106 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36" 107 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko/20100101 Firefox/11.0" 108 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0" 109 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0.1" 110 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.85 Safari/537.36" 111 | "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.02" 112 | "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36" 113 | "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0" 114 | "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)" 115 | "Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.8) Gecko/20100723 Ubuntu/10.04 (lucid) Firefox/3.6.8" 116 | "Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko" 117 | "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)" 118 | "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0; MDDCJS)" 119 | "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/5.0)" 120 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; Trident/5.0)" 121 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" 122 | "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Mobile/15E148 Safari/604.1" 123 | "Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4" 124 | "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1" 125 | "Mozilla/5.0 (iPhone; CPU iPhone OS 11_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1" 126 | "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1" 127 | "Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 Mobile/15E148 Safari/604.1" 128 | "Opera/9.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.01" 129 | ) 130 | 131 | cnt="${#ua[@]}" 132 | ind="$(( RANDOM % cnt ))" 133 | echo "${ua[${ind}]}" 134 | } 135 | 136 | 137 | ### 138 | ### Get random DNT value (0 or 1) 139 | ### 140 | get_random_dnt() { 141 | # Get either '0' or '1' 142 | echo "$(( RANDOM % 2 ))" 143 | } 144 | 145 | 146 | ### 147 | ### Get temporary cookie file 148 | ### 149 | get_tmp_file() { 150 | if ! command -v mktemp >/dev/null 2>&1; then 151 | if [ -n "${XDG_CACHE_HOME}" ] && [ -d "${XDG_CACHE_HOME}" ] && [ -w "${XDG_CACHE_HOME}" ]; then 152 | touch "${XDG_CACHE_HOME}/sldio.cookie" 153 | echo "${XDG_CACHE_HOME}/slido.cookie" 154 | else 155 | touch /tmp/slido.cookie 156 | echo "/tmp/slido.cookie" 157 | fi 158 | else 159 | mktemp 160 | fi 161 | } 162 | 163 | 164 | ### 165 | ### Get dump dir 166 | ### 167 | get_dump_dir() { 168 | if ! command -v mktemp >/dev/null 2>&1; then 169 | if [ -n "${XDG_CACHE_HOME}" ] && [ -d "${XDG_CACHE_HOME}" ] && [ -w "${XDG_CACHE_HOME}" ]; then 170 | mkdir -p "${XDG_CACHE_HOME}/slido/dumps" 171 | echo "${XDG_CACHE_HOME}/slido/dumps" 172 | else 173 | mkdir -p /tmp/slido/dumps 174 | echo "/tmp/slido/dumps" 175 | fi 176 | else 177 | mktemp -d 178 | fi 179 | } 180 | 181 | 182 | ### 183 | ### Wrapper for curl requests 184 | ### 185 | ### @param method string GET or POST 186 | ### @param url string URL to request 187 | ### @param cookie string (optional) File to load/save cookie 188 | ### @param data string (optional) Data to submit to request 189 | ### @param headers array (optional) Array of headers to append to request 190 | request() { 191 | local method="${1}" 192 | local url="${2}" 193 | local cookie="${3:-}" 194 | local data="${4:-}" 195 | shift; shift; shift; shift 196 | # Everything else is headers to append 197 | local headers=("${@}") 198 | 199 | # Base command 200 | local cmd="curl -sS" 201 | 202 | # Setup request method 203 | if [ "${method}" = "GET" ]; then 204 | cmd="${cmd} -XGET" 205 | elif [ "${method}" = "POST" ]; then 206 | cmd="${cmd} -XPOST" 207 | else 208 | >&2 echo "Error, unsupported method specified: ${method}" 209 | exit 1 210 | fi 211 | 212 | # Append cookie 213 | if [ -n "${cookie}" ]; then 214 | cmd="${cmd} -c ${cookie} -b ${cookie}" 215 | fi 216 | 217 | # Append data 218 | if [ -n "${data}" ]; then 219 | cmd="${cmd} -d '${data}'" 220 | fi 221 | 222 | # Append request headers 223 | for header in "${headers[@]}"; do 224 | cmd="${cmd} -H '${header}'" 225 | done 226 | 227 | # Append URL 228 | cmd="${cmd} '${url}'" 229 | 230 | # Output and execute 231 | if [ "${ARG_VERBOSE}" = "1" ]; then 232 | echo >&2 "${cmd}" 233 | echo >&2 234 | fi 235 | eval "${cmd}" 236 | } 237 | 238 | 239 | ### 240 | ### Get final URL after redirects 241 | ### 242 | get_effective_url() { 243 | local url="${1}" 244 | curl -Ls -o /dev/null -w '%{url_effective}' "${url}" 245 | } 246 | 247 | 248 | ### 249 | ### Wrapper for slido requests 250 | ### 251 | ### Required global variables: 252 | ### VALUE_UA 253 | ### VALUE_DNT 254 | ### VALUE_REFERER 255 | ### 256 | ### @param method string GET or POST 257 | ### @param url string URL to request 258 | ### @param cookie string File to load/save cookie 259 | ### @param auth_token string (optional) Slido Auth token to add to request headers 260 | ### @param data string (optional) Data to submit to request 261 | slido_request() { 262 | local method="${1}" 263 | local url="${2}" 264 | local cookie="${3}" 265 | local auth_token="${4:-}" 266 | local data="${5:-}" 267 | local headers=() 268 | 269 | headers+=( 270 | "User-Agent: ${VALUE_UA}" 271 | "DNT: ${VALUE_DNT}" 272 | "Referer: ${VALUE_REFERER}" 273 | "Cache-Control: no-cache, no-store" 274 | "Accept: application/json, text/plain, */*" 275 | ) 276 | if [ -n "${auth_token}" ]; then 277 | headers+=("Authorization: Bearer ${auth_token}") 278 | fi 279 | 280 | if [ "${method}" = "POST" ];then 281 | request "POST" "${url}" "${cookie}" "${data}" "${headers[@]}" 282 | else 283 | request "GET" "${url}" "${cookie}" "${data}" "${headers[@]}" 284 | fi 285 | } 286 | 287 | 288 | 289 | # ------------------------------------------------------------------------------------------------- 290 | # ARGUMENT ENTRYPOINT 291 | # ------------------------------------------------------------------------------------------------- 292 | 293 | # Parse input args with getopts 294 | while getopts ":vdq:h-:" options; do 295 | # ----- long options 296 | if [ "${options}" = "-" ]; then 297 | options="${OPTARG}" 298 | [ -z "${options}" ] && break # "--" terminates argument processing 299 | fi 300 | case "${options}" in 301 | # ---- Help / version 302 | h) 303 | print_usage 304 | exit 305 | ;; 306 | # ----- Options 307 | q) 308 | ARG_QID="${OPTARG}" 309 | ;; 310 | v) 311 | ARG_VERBOSE=1 312 | ;; 313 | d) 314 | ARG_DUMP=1 315 | ;; 316 | :) 317 | >&2 echo "Error: -${OPTARG} requires an argument." 318 | exit 1 319 | ;; 320 | \?) 321 | >&2 echo "Error: Unknown option1 -${OPTARG}, see -h for help." 322 | exit 1 323 | ;; 324 | *) >&2 echo "Error: Unknown option2 --${options}, see -h for help." 325 | exit 1 326 | ;; 327 | esac 328 | done 329 | shift $((OPTIND-1)) # remove parsed options and args from $@ list 330 | 331 | if [ "${#}" -ne "1" ]; then 332 | >&2 echo "Error: argument is required, see -h for help." 333 | exit 1 334 | fi 335 | 336 | 337 | 338 | # ------------------------------------------------------------------------------------------------- 339 | # PRE-FLIGHT-CHECK ENTRYPOINT 340 | # ------------------------------------------------------------------------------------------------- 341 | 342 | if ! command -v curl >/dev/null 2>&1; then 343 | echo "Error, curl binary required" 344 | exit 1 345 | fi 346 | if ! command -v jq >/dev/null 2>&1; then 347 | echo "Error, jq binary required" 348 | exit 1 349 | fi 350 | 351 | 352 | 353 | # ------------------------------------------------------------------------------------------------- 354 | # MAIN ENTRYPOINT 355 | # ------------------------------------------------------------------------------------------------- 356 | 357 | echo 358 | echo " ██████ ██▓ ██▓▓█████▄ ▒█████ ▄████▄ ██▓ ██▓" 359 | echo " ▒██ ▒ ▓██▒ ▓██▒▒██▀ ██▌▒██▒ ██▒▒██▀ ▀█ ▓██▒ ▓██▒" 360 | echo " ░ ▓██▄ ▒██░ ▒██▒░██ █▌▒██░ ██▒▒▓█ ▄ ▒██░ ▒██▒" 361 | echo " ▒ ██▒▒██░ ░██░░▓█▄ ▌▒██ ██░▒▓▓▄ ▄██▒▒██░ ░██░" 362 | echo " ▒██████▒▒░██████▒░██░░▒████▓ ░ ████▓▒░▒ ▓███▀ ░░██████▒░██░" 363 | echo " ▒ ▒▓▒ ▒ ░░ ▒░▓ ░░▓ ▒▒▓ ▒ ░ ▒░▒░▒░ ░ ░▒ ▒ ░░ ▒░▓ ░░▓" 364 | echo " ░ ░▒ ░ ░░ ░ ▒ ░ ▒ ░ ░ ▒ ▒ ░ ▒ ▒░ ░ ▒ ░ ░ ▒ ░ ▒ ░" 365 | echo " ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░" 366 | echo " ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░" 367 | echo " ░ ░" 368 | echo 369 | echo " Use at your own risk and adhere to sli.do terms and services" 370 | echo 371 | echo " ${VERSION_NUMBER} (${VERSION_DATE})" 372 | echo " ${VERSION_GITHUB}" 373 | echo " By ${VERSION_AUTHOR}" 374 | echo 375 | echo "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░" 376 | echo 377 | 378 | 379 | ### ------------------------------------------------------------ 380 | ### 01. Initialize 381 | ### ------------------------------------------------------------ 382 | echo 383 | echo " INITIALIZING" 384 | echo 385 | 386 | VALUE_REFERER="${1}" 387 | SLIDO_START_URL="$( get_effective_url "${VALUE_REFERER}" )" 388 | SLIDO_HASH="$( echo "${SLIDO_START_URL}" | sed 's|.*/event/||' )" 389 | SLIDO_HASH="${SLIDO_HASH%%/*}" 390 | VALUE_UA="$( get_random_ua )" 391 | VALUE_DNT="$( get_random_dnt )" 392 | COOKIE="$( get_tmp_file )" 393 | DUMP_DIR="" 394 | 395 | echo "Request URL: ${VALUE_REFERER}" 396 | echo "Slido URL: ${SLIDO_START_URL}" 397 | echo "Slido hash: ${SLIDO_HASH}" 398 | echo "Random UA: ${VALUE_UA:0:62}..." 399 | echo "Random DNT: ${VALUE_DNT}" 400 | echo "Cookie path: ${COOKIE}" 401 | if [ "${ARG_DUMP}" = "1" ]; then 402 | DUMP_DIR="$( get_dump_dir )" 403 | echo "Dump path: ${DUMP_DIR}" 404 | else 405 | echo "Dump path: not set" 406 | fi 407 | 408 | 409 | ### ------------------------------------------------------------ 410 | ### 02. Gather event 411 | ### ------------------------------------------------------------ 412 | echo 413 | echo " GATHERING EVENT DATA" 414 | echo 415 | 416 | VALUE_REFERER="${SLIDO_START_URL}" 417 | SLIDO_EVENT_API_URL="$( echo "${SLIDO_EVENT_API_URL}" | sed "s|__HASH__|${SLIDO_HASH}|" )" 418 | SLIDO_START_DATA="$( slido_request "GET" "${SLIDO_START_URL}" "${COOKIE}" )" 419 | if [ "${ARG_DUMP}" = "1" ]; then echo "${SLIDO_START_DATA}" > "${DUMP_DIR}/01-startpage.txt"; fi 420 | SLIDO_EVENT_DATA="$( slido_request "GET" "${SLIDO_EVENT_API_URL}" "${COOKIE}" )" 421 | if [ "${ARG_DUMP}" = "1" ]; then echo "${SLIDO_EVENT_DATA}" > "${DUMP_DIR}/02-eventpage.txt"; fi 422 | 423 | NAME="$( echo "${SLIDO_EVENT_DATA}" | jq -r '.[].name' )" 424 | CODE="$( echo "${SLIDO_EVENT_DATA}" | jq -r '.[].code' )" 425 | EVENT_ID="$( echo "${SLIDO_EVENT_DATA}" | jq -r '.[].event_id' )" 426 | EVENT_GROUP_ID="$( echo "${SLIDO_EVENT_DATA}" | jq -r '.[].event_group_id' )" 427 | UUID="$( echo "${SLIDO_EVENT_DATA}" | jq -r '.[].uuid' )" 428 | 429 | echo "Slido event URL: ${SLIDO_EVENT_API_URL}" 430 | echo "Name: ${NAME}" 431 | echo "Code: ${CODE}" 432 | echo "Event ID: ${EVENT_ID}" 433 | echo "Event Group ID: ${EVENT_GROUP_ID}" 434 | echo "UUID: ${UUID}" 435 | 436 | 437 | ### ------------------------------------------------------------ 438 | ### 03. Authenticating User 439 | ### ------------------------------------------------------------ 440 | echo 441 | echo " AUTHENTICATING USER" 442 | echo 443 | 444 | SLIDO_AUTH_USER_URL="https://app.sli.do/api/v0.5/events/__UUID__/auth" 445 | SLIDO_AUTH_USER_URL="$( echo "${SLIDO_AUTH_USER_URL}" | sed "s|__UUID__|${UUID}|" )" 446 | SLIDO_AUTH_USER_DATA="$( slido_request "POST" "${SLIDO_AUTH_USER_URL}" "${COOKIE}" )" 447 | if [ "${ARG_DUMP}" = "1" ]; then echo "${SLIDO_AUTH_USER_DATA}" > "${DUMP_DIR}/03-auth-user.txt"; fi 448 | 449 | ACCESS_TOKEN="$( echo "${SLIDO_AUTH_USER_DATA}" | jq -r '.access_token' )" 450 | EVENT_ID="$( echo "${SLIDO_AUTH_USER_DATA}" | jq -r '.event_id' )" 451 | EVENT_USER_ID="$( echo "${SLIDO_AUTH_USER_DATA}" | jq -r '.event_user_id' )" 452 | 453 | echo "Slido auth URL: ${SLIDO_AUTH_USER_URL}" 454 | echo "Acess Token: ${ACCESS_TOKEN}" 455 | echo "Event User ID: ${EVENT_USER_ID}" 456 | 457 | 458 | if [ -z "${ARG_QID}" ]; then 459 | ### ------------------------------------------------------------ 460 | ### 04. Authenticating Event 461 | ### ------------------------------------------------------------ 462 | echo 463 | echo " AUTHENTICATING EVENT" 464 | echo 465 | 466 | SLIDO_AUTH_EVENT_URL="$( echo "${SLIDO_AUTH_EVENT_URL}" | sed "s|__UUID__|${UUID}|" )" 467 | SLIDO_AUTH_EVENT_DATA="$( slido_request "GET" "${SLIDO_AUTH_EVENT_URL}" "${COOKIE}" "${ACCESS_TOKEN}" )" 468 | if [ "${ARG_DUMP}" = "1" ]; then echo "${SLIDO_AUTH_EVENT_DATA}" > "${DUMP_DIR}/04-auth-event.txt"; fi 469 | 470 | EVENT_SECTION_ID="$( echo "${SLIDO_AUTH_EVENT_DATA}" | jq -r '.sections[].event_section_id' )" 471 | ROOM="$( echo "${SLIDO_AUTH_EVENT_DATA}" | jq -r '.sections[].name' )" 472 | 473 | echo "Slido auth URL: ${SLIDO_AUTH_EVENT_URL}" 474 | echo "Event Sect ID: ${EVENT_SECTION_ID}" 475 | echo "Room: ${ROOM}" 476 | 477 | 478 | 479 | ### ------------------------------------------------------------ 480 | ### 05. Listing Questions 481 | ### ------------------------------------------------------------ 482 | echo 483 | echo " LISTING QUESTIONS" 484 | echo 485 | 486 | SLIDO_QUESTIONS_URL="$( echo "${SLIDO_QUESTIONS_URL}" | sed "s|__UUID__|${UUID}|" )" 487 | SLIDO_QUESTIONS_URL="$( echo "${SLIDO_QUESTIONS_URL}" | sed "s|__EVENT_SEC_ID__|${EVENT_SECTION_ID}|" )" 488 | SLIDO_QUESTIONS_DATA="$( slido_request "GET" "${SLIDO_QUESTIONS_URL}" "${COOKIE}" "${ACCESS_TOKEN}" )" 489 | if [ "${ARG_DUMP}" = "1" ]; then echo "${SLIDO_QUESTIONS_DATA}" > "${DUMP_DIR}/05-questions.txt"; fi 490 | echo "${SLIDO_QUESTIONS_DATA}" | jq -r '[[.[].event_question_id|tostring],[.[].score|tostring], [.[].text]] | transpose | . []' 491 | 492 | else 493 | 494 | ### ------------------------------------------------------------ 495 | ### 06. Upvoting 496 | ### ------------------------------------------------------------ 497 | echo 498 | echo " UPVOTING" 499 | echo 500 | 501 | SLIDO_UPVOTE_URL="$( echo "${SLIDO_UPVOTE_URL}" | sed "s|__UUID__|${UUID}|" )" 502 | SLIDO_UPVOTE_URL="$( echo "${SLIDO_UPVOTE_URL}" | sed "s|__QID__|${ARG_QID}|" )" 503 | SLIDO_UPVOTE_DATA="$( slido_request "POST" "${SLIDO_UPVOTE_URL}" "${COOKIE}" "${ACCESS_TOKEN}" '{"score":1}' )" 504 | if [ "${ARG_DUMP}" = "1" ]; then echo "${SLIDO_UPVOTE_DATA}" > "${DUMP_DIR}/06-upvote.txt"; fi 505 | NEW_SCORE="$( echo "${SLIDO_UPVOTE_DATA}" | jq -r '.event_question_score' )" 506 | 507 | echo "Voted question: ${ARG_QID}" 508 | echo "New score: ${NEW_SCORE}" 509 | fi 510 | 511 | 512 | 513 | # ------------------------------------------------------------------------------------------------- 514 | # Clean up 515 | # ------------------------------------------------------------------------------------------------- 516 | rm -f "${COOKIE}" 517 | --------------------------------------------------------------------------------