diff --git a/.DEREK.yml b/.DEREK.yml new file mode 100644 index 00000000..c63d9d15 --- /dev/null +++ b/.DEREK.yml @@ -0,0 +1,10 @@ +maintainers: + - evilsocket + - caquino + - dadav + - justin-p + +features: + - comments + - pr_description_required + diff --git a/.gitignore b/.gitignore index 1ed12070..7d065ae9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.img +*.img.bmap *.pcap __pycache__ _backups diff --git a/.travis.yml b/.travis.yml index b1737097..6a7249ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,52 @@ dist: bionic -language: generic +language: go + +go: + - 1.x + env: global: - - LANG=C - - LC_ALL=C -before_cache: -- mountpoint -q $TRAVIS_BUILD_DIR/tmp/mnt && sudo umount -R $TRAVIS_BUILD_DIR/tmp/mnt -- sudo find $TRAVIS_BUILD_DIR/tmp/ -name '*.img' -delete + - LANG=C + - LC_ALL=C + +deploy: + provider: releases + api_key: + secure: "vBUokTv94n8s65STUgTiD6I0Iy8KXbBRvQUrAof8XG+U4ZMsH5PmDTpS+wz+SaxI6o0PRkfyOiPVdARhiKAFnfatG3q9EHllMQwqRR2YIju51A3aCxgEJ5uWDoybwQdipERUMMYwUO/8XZaRRpwFD2bdQBFWkBtQyMcAkrEL8BXckwQQ531oDN2hK5gAiTllqsOswV2idwUlBRU9jOtStzff+UgUYsp/ZebsRodyOYkEB2Ev15yARo2HTXbyZ2icwHPtMbx5zmNUSRtxs9a4hfzaK3m6ctK8qLYYUdQvXub/ruuACapdw4Ez88LY1agTecbZhFYmJzv8oANH1e4VUI4owuHnZCpU6LRutS4wOhglrkOrGo6lSUlJeA+RtQjyjBugjej9DDtDyyIlRU1ZaBF3qWR9N5EXKuquf0olOfmUR67ap1NykE9VUpzkYjkoVRTiPs/e2onM/nRNOvAQcIt75FD13u+Y/DcYQ8r7KpMIu1HNdtbVx8gMeq76bRhP1YdDg2jm+DdJ21KWjf5QHsbyoXDfJzdKlCloLIlAU3EPJhMoXsnNzre0/FXeUl6dfteR1axNS6U7e/vKsQ9rlUFZWIQaeVPjfXmFKblNNVQ5uFrrsB/EGHcJl7IUx5fvcRT5hMMNwC660YxVkBXDbRb5fxMW5/+K0BOi9cP6en8=" + skip_cleanup: true + file_glob: true + file: pwnagotchi-*.zip + on: + tags: true + repo: evilsocket/pwnagotchi + +branches: + only: + - /^v[0-9]+\.[0-9]+\.[0-9]+[A-Za-z0-9]+?$/ + cache: apt: true - directories: - - tmp/ -before_script: -- sudo apt-get -y update -- sudo apt-get -y install qemu-user-static binfmt-support qemu -- sudo update-binfmts --display -- unset GOROOT -script: -- sudo ./scripts/create_sibling.sh -n pwnagotchi -o pwnagotchi.img -s 4 -- zip -s 2g pwnagotchi.zip pwnagotchi.img -# TODO: deploy! +before_script: + - wget https://download.qemu.org/qemu-4.1.0.tar.xz + - tar xvJf qemu-4.1.0.tar.xz + - cd qemu-4.1.0 + - ./configure --target-list=arm-softmmu + - make -j$(nproc) + - sudo make install + - cd $TRAVIS_BUILD_DIR + - sudo apt-get -y update + - sudo apt-get -y install qemu-user-static binfmt-support bmap-tools kpartx + - sudo update-binfmts --display + +script: + - sudo make clean + - sudo -E env "PATH=$PATH" make install + - sudo make image -e PWN_HOSTNAME=pwnagotchi VERSION=$TRAVIS_TAG + +before_deploy: + # Set up git user name and tag this commit + - git config --local user.name "evilsocket" + - git config --local user.email "evilsocket@gmail.com" + - export TRAVIS_TAG=${TRAVIS_TAG:-$(date +'%Y%m%d%H%M%S')-$(git log --format=%h -1)} + - git tag $TRAVIS_TAG diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..0d898ddb --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +PWN_HOSTNAME=pwnagotchi +PWN_VERSION=master + +all: install image clean + +install: + curl https://releases.hashicorp.com/packer/1.3.5/packer_1.3.5_linux_amd64.zip -o /tmp/packer.zip + unzip /tmp/packer.zip -d /tmp + mv /tmp/packer /usr/bin/packer + git clone https://github.com/solo-io/packer-builder-arm-image /tmp/packer-builder-arm-image + cd /tmp/packer-builder-arm-image && go get -d ./... && go build + cp /tmp/packer-builder-arm-image/packer-builder-arm-image /usr/bin + +image: + cd builder && sudo /usr/bin/packer build pwnagotchi.json + mv builder/output-pwnagotchi/image pwnagotchi-raspbian-lite-$(PWN_VERSION).img + zip pwnagotchi-raspbian-lite-$(PWN_VERSION).zip pwnagotchi-raspbian-lite-$(PWN_VERSION).img + +clean: + rm -rf /tmp/packer-builder-arm-image + rm -f pwnagotchi-raspbian-lite.img + rm -rf builder/output-pwnagotchi builder/packer_cache diff --git a/README.md b/README.md index a24bb052..30ec48b5 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,24 @@ The supported models are: - [Pimoroni Inky pHAT](https://shop.pimoroni.com/products/inky-phat) - [PaPiRus eInk Screen](https://uk.pi-supply.com/products/papirus-zero-epaper-screen-phat-pi-zero) +The only kind of displays supported are the ones listed above, but we are always happy to receive pull requests supporting new displays. + +You need to configure the display type in `config.yml` where you can find `ui.display.type`. + +One thing to note, not all displays are created equaly, TFT displays for example work similar to an HDMI display, and they are not supported, currently all the displays supported are I2C displays. + +### Color and Black & White displays + +Some of the supported displays support Black & White and Coloured versions, one common question is regarding refresh speed of said displays. + +Color displays have a much slower refresh rate, in some cases it can take up to 15 seconds, if slow refresh rates is something that you want to avoid we advise you to use Black & White displays + +### FPS + +You can configure the refresh interval of the display on config.yml, we advise to use a slow refresh to not shorten the lifetime of your display. + +Another option is to change fps to 0, which will only refresh when changes are made to the screen. + ### Software - Raspbian + [nexmon patches](https://re4son-kernel.com/re4son-pi-kernel/) for monitor mode, or any Linux with a monitor mode enabled interface (if you tune config.yml). @@ -80,6 +98,23 @@ usage: ./scripts/create_sibling.sh [OPTIONS] If you connect to the unit via `usb0` (thus using the data port), you might want to use the `scripts/linux_connection_share.sh` script to bring the interface up on your end and share internet connectivity from another interface, so you can update the unit and generally download things from the internet on it. +#### Update your pwnagotchi + +You can use the `scripts/update_pwnagotchi.sh` script to update to the most recent version of pwnagotchi. + +```shell +usage: ./update_pwnagitchi.sh [OPTIONS] + + Options: + -v # Version to update to, can be a branch or commit. (default: master) + -u # Url to clone from. (default: https://github.com/evilsocket/pwnagotchi) + -m # Mode to restart to. (Supported: auto manual; default: auto) + -b # Backup the current pwnagotchi config. + -r # Restore the current pwnagotchi config. -b will be enabled. + -h # Shows this help. Shows this help. + +``` + ### UI The UI is available either via display if installed, or via http://pwnagotchi.local:8080/ if you connect to the unit via `usb0` and set a static address on the network interface (change `pwnagotchi` with the hostname of your unit). @@ -100,7 +135,9 @@ Pwnagotchi is able to speak multiple languages!! Currently supported are: * german * dutch * greek +* macedonian * italian +* french If you want to add a language use the `language.sh` script. If you want to add for example the language **italian** you would type: @@ -130,6 +167,64 @@ Now you can use the `preview.py`-script to preview the changes: # Now open http://localhost:8080 and http://localhost:8081 ``` +### Plugins + +Pwnagotchi has a simple plugins system that you can use to customize your unit and its behaviour. You can place your plugins anywhere +as python files and then edit the `config.yml` file (`main.plugins` value) to point to their containing folder. Check the [plugins folder](https://github.com/evilsocket/pwnagotchi/tree/master/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/) for a list of default +plugins and all the callbacks that you can define for your own customizations. + +Here's as an example the GPS plugin: + +```python +__author__ = 'evilsocket@gmail.com' +__version__ = '1.0.0' +__name__ = 'gps' +__license__ = 'GPL3' +__description__ = 'Save GPS coordinates whenever an handshake is captured.' +__enabled__ = True # set to false if you just don't use GPS + +import core +import json +import os + +device = '/dev/ttyUSB0' +speed = 19200 +running = False + + +def on_loaded(): + core.log("GPS plugin loaded for %s" % device) + + +def on_ready(agent): + global running + + if os.path.exists(device): + core.log("enabling GPS bettercap's module for %s" % device) + try: + agent.run('gps off') + except: + pass + + agent.run('set gps.device %s' % device) + agent.run('set gps.speed %d' % speed) + agent.run('gps on') + running = True + else: + core.log("no GPS detected") + + +def on_handshake(agent, filename, access_point, client_station): + if running: + info = agent.session() + gps = info['gps'] + gps_filename = filename.replace('.pcap', '.gps.json') + + core.log("saving GPS to %s (%s)" % (gps_filename, gps)) + with open(gps_filename, 'w+t') as fp: + json.dump(gps, fp) +``` + ### Random Info - `hostname` sets the unit name. @@ -143,7 +238,7 @@ the `PARTUUID`s for `rootfs` and `boot` partitions are the same in `/etc/fstab`. ## License -`pwnagotchi` is made with ♥ by [@evilsocket](https://twitter.com/evilsocket) and it's released under the GPL3 license. +`pwnagotchi` is made with ♥ by [@evilsocket](https://twitter.com/evilsocket) and the [amazing dev team](https://github.com/evilsocket/pwnagotchi/graphs/contributors). It's released under the GPL3 license. diff --git a/builder/pwnagotchi.json b/builder/pwnagotchi.json new file mode 100644 index 00000000..beac17b7 --- /dev/null +++ b/builder/pwnagotchi.json @@ -0,0 +1,33 @@ +{ + "variables": { + "home": "{{env `HOME`}}" + }, + "builders": [{ + "name": "pwnagotchi", + "type": "arm-image", + "iso_url" : "https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-07-12/2019-07-10-raspbian-buster-lite.zip", + "iso_checksum_type":"sha256", + "iso_checksum":"9e5cf24ce483bb96e7736ea75ca422e3560e7b455eee63dd28f66fa1825db70e", + "last_partition_extra_size" : 3221225472 + }], + "provisioners": [ + { + "type": "shell", + "inline": [ + "sed -i 's/^\\([^#]\\)/#\\1/g' /etc/ld.so.preload", + "apt-get -y update", + "apt-get install -y ansible" + ] + }, + { + "type":"ansible-local", + "playbook_file": "pwnagotchi.yml" + }, + { + "type": "shell", + "inline": [ + "sed -i 's/^#\\(.+\\)/\\1/g' /etc/ld.so.preload" + ] + } + ] +} diff --git a/builder/pwnagotchi.yml b/builder/pwnagotchi.yml new file mode 100644 index 00000000..279dcf53 --- /dev/null +++ b/builder/pwnagotchi.yml @@ -0,0 +1,306 @@ +--- +- hosts: + - 127.0.0.1 + become: yes + vars: + pwn_hostname: "pwnagotchi" + pwn_version: "master" + + tasks: + + - name: selected hostname + debug: + msg: "{{ pwn_hostname }}" + + - name: build version + debug: + msg: "{{ pwn_version }}" + + - name: change hostname + hostname: + name: "{{pwn_hostname}}" + + - name: add hostname to /etc/hosts + lineinfile: + dest: /etc/hosts + regexp: '^127\.0\.0\.1[ \t]+localhost' + line: '127.0.0.1 localhost {{pwn_hostname}} {{pwn_hostname}}.local' + state: present + + - name: Add re4son-kernel repo key + apt_key: + url: https://re4son-kernel.com/keys/http/archive-key.asc + state: present + + - name: Add re4son-kernel repository + apt_repository: + repo: deb http://http.re4son-kernel.com/re4son/ kali-pi main + state: present + + - name: update apt package cache + apt: + update_cache: yes + + - name: upgrade apt distro + apt: + upgrade: dist + + - name: install packages + apt: + name: "{{ packages }}" + state: present + vars: + packages: + - vim + - screen + - golang + - git + - build-essential + - python3-pip + - gawk + - libopenmpi-dev + - libatlas-base-dev + - libjasper-dev + - libqtgui4 + - libqt4-test + - libopenjp2-7 + - tcpdump + - lsof + - libilmbase23 + - libopenexr23 + - libgstreamer1.0-0 + - libavcodec58 + - libavformat58 + - libswscale5 + - libpcap-dev + - libusb-1.0-0-dev + - libnetfilter-queue-dev + - dphys-swapfile + - kalipi-kernel + - kalipi-bootloader + - kalipi-re4son-firmware + - kalipi-kernel-headers + - libraspberrypi0 + - libraspberrypi-dev + - libraspberrypi-doc + - libraspberrypi-bin + - fonts-dejavu + - fonts-dejavu-core + - fonts-dejavu-extra + + - name: configure dphys-swapfile + file: + path: /etc/dphys-swapfile + content: "CONF_SWAPSIZE=1024" + + - name: disable unecessary services + systemd: + name: "{{services}}" + state: stopped + enabled: no + vars: + services: + - apt-daily.timer + - apt-daily.service + - apt-daily-upgrade.timer + - apt-daily-upgrade.service + - bluetooth.service + - triggerhappy.service + + - name: enable dphys-swapfile service + systemd: + name: dphys-swapfile.service + state: started + enabled: yes + + - name: build bettercap + command: go get -u github.com/bettercap/bettercap + environment: + GOPATH: /root/go + GOROOT: /usr/lib/go + + - name: install bettercap + copy: + src: /root/go/bin/bettercap + dest: /usr/bin/bettercap + mode: 0755 + + - name: clone bettercap caplets + git: + repo: https://github.com/bettercap/caplets.git + dest: /tmp/caplets + + - name: install bettercap caplets + make: + chdir: /tmp/caplets + target: install + + - name: clone pwnagotchi repository + git: + repo: https://github.com/evilsocket/pwnagotchi.git + dest: /tmp/pwnagotchi + + - name: copy pwnagotchi files to final destination + copy: + src: /tmp/pwnagotchi/sdcard/rootfs/root/pwnagotchi/ + dest: /root/pwnagotchi/ + mode: preserve + + - name: remove pwnagotchi files from temporary repository + file: + path: /tmp/pwnagotchi + state: absent + + - name: install python modules + pip: + requirements: /root/pwnagotchi/scripts/requirements.txt + + - name: create cpuusage script + copy: + dest: /usr/bin/cpuusage + mode: 0755 + content: | + #!/usr/bin/env bash + while true + do + top -b -n1 | awk '/Cpu\(s\)/ { printf("%d %", $2 + $4 + 0.5) }' + sleep 3 + done + + - name: create memusage script + copy: + dest: /usr/bin/memusage + mode: 0755 + content: | + #!/usr/bin/env + free -m | awk '/Mem/ { printf( "%d %", $3 / $2 * 100 + 0.5 ) }' + + - name: create monstart script + copy: + dest: /usr/bin/monstart + mode: 0755 + content: | + #!/usr/bin/env bash + iw phy phy0 interface add mon0 type monitor && ifconfig mon0 up + + - name: create monstop script + copy: + dest: /usr/bin/monstop + mode: 0755 + content: | + #!/usr/bin/env bash + ifconfig mon0 down && iw dev mon0 del + + - name: configure rc.local + blockinfile: + path: /etc/rc.local + insertbefore: "exit 0" + block: | + if ! /opt/vc/bin/tvservice -s | grep HDMI; then + /opt/vc/bin/tvservice -o + fi + /root/pwnagotchi/scripts/startup.sh & + + - name: configure lo interface + blockinfile: + path: /etc/network/interfaces.d/lo-cfg + create: yes + block: | + auto lo + iface lo inet loopback + + - name: configure wlan interface + blockinfile: + path: /etc/network/interfaces.d/wlan0-cfg + create: yes + block: | + allow-hotplug wlan0 + iface wlan0 inet static + + - name: configure usb interface + blockinfile: + path: /etc/network/interfaces.d/usb0-cfg + create: yes + block: | + allow-hotplug usb0 + iface usb0 inet static + address 10.0.0.2 + netmask 255.255.255.0 + network 10.0.0.0 + broadcast 10.0.0.255 + gateway 10.0.0.1 + + - name: configure eth0 interface (pi2/3/4) + blockinfile: + path: /etc/network/interfaces.d/eth0-cfg + create: yes + block: | + allow-hotplug eth0 + iface eth0 inet dhcp + + - name: enable ssh on boot + file: + path: /boot/ssh + state: touch + + - name: adjust /boot/config.txt + lineinfile: + dest: /boot/config.txt + insertafter: EOF + line: '{{ item }}' + with_items: + - "dtoverlay=dwc2" + - "dtparam=spi=on" + - "dtoverlay=spi1-3cs" + - "dtoverlay=pi3-disable-bt" + - "dtparam=audio=off" + + - name: change root partition + replace: + dest: /boot/cmdline.txt + backup: no + regexp: "root=PARTUUID=[a-zA-Z0-9\\-]+" + replace: "root=/dev/mmcblk0p2" + + - name: configure /boot/cmdline.txt + lineinfile: + path: /boot/cmdline.txt + backrefs: True + state: present + backup: no + regexp: '(.*)$' + line: '\1 modules-load=dwc2,g_ether' + + - name: configure ssh + lineinfile: + dest: /etc/ssh/sshd_config + backup: no + regexp: '#?PermitRootLogin (.*)$' + line: 'PermitRootLogin yes' + + - name: configure motd + copy: + dest: /etc/motd + content: "(◕‿‿◕) {{pwn_hostname}} (pwnagotchi-{{pwn_version}})" + + - name: clean apt cache + apt: + autoclean: yes + + - name: remove dependencies that are no longer required + apt: + autoremove: yes + + - name: remove ssh keys + file: + state: absent + path: "{{item}}" + with_items: + - /etc/ssh/ssh_host_rsa_key + - /etc/ssh/ssh_host_rsa_key.pub + - /etc/ssh/ssh_host_dsa_key + - /etc/ssh/ssh_host_dsa_key.pub + - /etc/ssh/ssh_host/ecdsa_key + - /etc/ssh/ssh_host/ecdsa_key.pub + - /etc/ssh/ssh_host_ed25519_key + - /etc/ssh/ssh_host_ed25519_key.pub diff --git a/scripts/changelog.sh b/scripts/changelog.sh new file mode 100755 index 00000000..1c2f28a6 --- /dev/null +++ b/scripts/changelog.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +NEW=() +FIXES=() +MISC=() + +echo "@ Fetching remote tags ..." +git fetch --tags >/dev/null +printf "\n\n" + +CURTAG=$(git describe --tags --abbrev=0) +OUTPUT=$(git log $CURTAG..HEAD --oneline) +IFS=$'\n' LINES=($OUTPUT) + +for LINE in "${LINES[@]}"; do + LINE=$(echo "$LINE" | sed -E "s/^[[:xdigit:]]+\s+//") + if [[ $LINE == *"new:"* ]]; then + LINE=$(echo "$LINE" | sed -E "s/^new: //") + NEW+=("$LINE") + elif [[ $LINE == *"fix:"* ]]; then + LINE=$(echo "$LINE" | sed -E "s/^fix: //") + FIXES+=("$LINE") + elif [[ $LINE != *"i did not bother commenting"* ]] && [[ $LINE != *"Merge "* ]]; then + echo " MISC LINE =$LINE" + LINE=$(echo "$LINE" | sed -E "s/^[a-z]+: //") + MISC+=("$LINE") + fi +done + +if [ -n "$NEW" ]; then + echo + echo "**New Features**" + echo + for l in "${NEW[@]}"; do + echo "* $l" + done +fi + +if [ -n "$FIXES" ]; then + echo + echo "**Fixes**" + echo + for l in "${FIXES[@]}"; do + echo "* $l" + done +fi + +if [ -n "$MISC" ]; then + echo + echo "**Misc**" + echo + for l in "${MISC[@]}"; do + echo "* $l" + done +fi + +echo diff --git a/scripts/create_sibling.sh b/scripts/create_sibling.sh index c69ff848..55b784f4 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -5,18 +5,22 @@ set -eu REQUIREMENTS=( wget gunzip git dd e2fsck resize2fs parted losetup qemu-system-x86_64 ) +DEBREQUIREMENTS=( wget gzip git parted qemu-system-x86 qemu-user-static bmap-tools ) REPO_DIR="$(dirname "$(dirname "$(realpath "$0")")")" TMP_DIR="${REPO_DIR}/tmp" MNT_DIR="${TMP_DIR}/mnt" +THIS_DIR=$(pwd) PWNI_NAME="pwnagotchi" PWNI_OUTPUT="pwnagotchi.img" -PWNI_SIZE="4" +PWNI_SIZE="8" +OPT_SPARSE=0 OPT_PROVISION_ONLY=0 OPT_CHECK_DEPS_ONLY=0 OPT_IMAGE_PROVIDED=0 OPT_RASPBIAN_VERSION='latest' +OPT_APTPROXY="" SUPPORTED_RASPBIAN_VERSIONS=( 'latest' 'buster' 'stretch' ) @@ -26,6 +30,18 @@ if [[ "$EUID" -ne 0 ]]; then fi function check_dependencies() { + if [ -f /etc/debian_version ]; + then + echo "[+] Checking Debian dependencies" + + for REQ in "${DEBREQUIREMENTS[@]}"; do + if ! dpkg -s "$REQ" >/dev/null 2>&1; then + echo "Dependency check failed for ${REQ}; use 'apt-get install ${REQ}' to install" + exit 1 + fi + done + fi + echo "[+] Checking dependencies" for REQ in "${REQUIREMENTS[@]}"; do if ! type "$REQ" >/dev/null 2>&1; then @@ -76,8 +92,31 @@ function provide_raspbian() { } function setup_raspbian(){ - echo "[+] Resize image" - dd if=/dev/zero bs=1G count="$PWNI_SIZE" >> "${TMP_DIR}/raspbian.img" + # Detect the ability to create sparse files + if [ "${OPT_SPARSE}" -eq 0 ]; + then + which bmaptool >/dev/null 2>&1 + if [ $? -eq 0 ]; + then + echo "[+] Defaulting to sparse image generation as bmaptool is available" + OPT_SPARSE=1 + else + echo "[!] bmaptool not available, not creating a sparse image" + fi + fi + + # Note that we 'extend' the raspbian.img + if [ "${OPT_SPARSE}" -eq 1 ]; + then + # Resize sparse (so that we can use bmaptool later) + echo "[+] Resizing sparse image of ${PWNI_SIZE}GB (1000s)" + truncate -s ${PWNI_SIZE}GB "${TMP_DIR}/raspbian.img" + else + echo "[+] Resizing full image to ${PWNI_SIZE}G" + # Full disk-space using image (appends to raspbian image) + dd if=/dev/zero bs=1G count="${PWNI_SIZE}" >> "${TMP_DIR}/raspbian.img" + fi + echo "[+] Setup loop device" mkdir -p "${MNT_DIR}" LOOP_PATH="$(losetup --find --partscan --show "${TMP_DIR}/raspbian.img")" @@ -107,10 +146,16 @@ function provision_raspbian() { cd "${MNT_DIR}" sed -i'' 's/^\([^#]\)/#\1/g' etc/ld.so.preload # add comments echo "[+] Run chroot commands" - LANG=C chroot . bin/bash -x </etc/apt/apt.conf.d/99pwnagotchi_proxy + fi + uname -a apt-get -y update @@ -160,7 +205,7 @@ function provision_raspbian() { # install bettercap export GOPATH=/root/go - go get -u github.com/bettercap/bettercap + taskset -c 1 go get -u github.com/bettercap/bettercap mv "\$GOPATH/bin/bettercap" /usr/bin/bettercap # install bettercap caplets (cant run bettercap in chroot) @@ -203,7 +248,11 @@ EOF cd "${REPO_DIR}" umount -R "${MNT_DIR}" losetup -D "$(losetup -l | awk '/raspbian\.img/{print $1}')" - mv "${TMP_DIR}/raspbian.img" "$PWNI_OUTPUT" + mv "${TMP_DIR}/raspbian.img" "${PWNI_OUTPUT}" + if [ "${OPT_SPARSE}" -eq 1 ]; + then + bmaptool create -o "${PWNI_OUTPUT}.bmap" "${PWNI_OUTPUT}" + fi } function usage() { @@ -226,8 +275,11 @@ EOF exit 0 } -while getopts ":n:i:o:s:v:dph" o; do +while getopts "A:n:i:o:s:v:dph" o; do case "${o}" in + A) + OPT_APTPROXY="${OPTARG}" + ;; n) PWNI_NAME="${OPTARG}" ;; @@ -283,4 +335,14 @@ fi setup_raspbian provision_raspbian -echo -ne "[+] Congratz, it's a boy (⌐■_■)!\n[+] One more step: dd if=../$PWNI_OUTPUT of= bs=4M status=progress" +echo -e "[+] Congratz, it's a boy (⌐■_■)!" +echo -e "[+] One more step: dd if=../${PWNI_OUTPUT} of= bs=4M status=progress" + +if [ "${OPT_SPARSE}" -eq 1 ]; +then + echo -e "[t] To transfer use: rsync -vaS --progress $(whoami)@$(hostname -f):${THIS_DIR}/../${PWNI_OUTPUT} " + echo -e "[t] To burn with bmaptool: bmaptool copy ~/${PWNI_OUTPUT} /dev/" +fi + +# Helpful OSX reminder +echo -e "[t] Mac: use 'diskutil list' to figure out which device to burn to; 'diskutil unmountDisk' to unmount that disk'; then use /dev/rdiskX (note the 'r') for faster transfer" diff --git a/scripts/preview.py b/scripts/preview.py index 8ca53594..261448ea 100755 --- a/scripts/preview.py +++ b/scripts/preview.py @@ -152,6 +152,19 @@ def main(): time.sleep(args.sleep) DISPLAY.on_deauth({'mac': 'DE:AD:BE:EF:CA:FE'}) DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_miss('test') + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_lonely() + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_handshakes(1) + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_rebooting() + DISPLAY.update() + time.sleep(args.sleep) if __name__ == '__main__': diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 00000000..8b8d8cd8 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# nothing to see here, just a utility i use to create new releases ^_^ + +VERSION_FILE=$(dirname "${BASH_SOURCE[0]}")/../sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/version.py +echo "version file is $VERSION_FILE" +CURRENT_VERSION=$(cat $VERSION_FILE | grep version | cut -d"'" -f2) +TO_UPDATE=( + $VERSION_FILE +) + +echo -n "current version is $CURRENT_VERSION, select new version: " +read NEW_VERSION +echo "creating version $NEW_VERSION ...\n" + +for file in "${TO_UPDATE[@]}"; do + echo "patching $file ..." + sed -i.bak "s/$CURRENT_VERSION/$NEW_VERSION/g" "$file" + rm -rf "$file.bak" + git add $file +done + +git commit -m "releasing v$NEW_VERSION" +git push +git tag -a v$NEW_VERSION -m "release v$NEW_VERSION" +git push origin v$NEW_VERSION + +echo +echo "All done, v$NEW_VERSION released ^_^" \ No newline at end of file diff --git a/scripts/update_pwnagotchi.sh b/scripts/update_pwnagotchi.sh new file mode 100644 index 00000000..97b8a89a --- /dev/null +++ b/scripts/update_pwnagotchi.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# Default variables +GIT_FOLDER="/tmp/pwnagotchi" +GIT_URL="https://github.com/evilsocket/pwnagotchi/" +VERSION="master" +SUPPORTED_RESTART_MODES=( 'auto' 'manual' ) +MODE="auto" +BACKUPCONFIG=0 +RESTORECONFIG=0 + +# Functions +function usage() { + cat </sys/class/leds/led0/brightness -sleep 0.3 - -# Powersave options -# Disable power LED ~30ma -echo none >/sys/class/leds/led0/trigger -echo 1 >/sys/class/leds/led0/brightness +sleep 0.3 \ No newline at end of file diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/main.py b/sdcard/rootfs/root/pwnagotchi/scripts/main.py index 10e0490e..09f6ec30 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/main.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/main.py @@ -5,7 +5,7 @@ import time import traceback import core -import pwnagotchi +import pwnagotchi, pwnagotchi.plugins as plugins from pwnagotchi.log import SessionParser from pwnagotchi.voice import Voice @@ -25,39 +25,49 @@ args = parser.parse_args() if args.do_clear: print("clearing the display ...") with open(args.config, 'rt') as fp: - config = yaml.safe_load(fp) - cleardisplay=config['ui']['display']['type'] - if cleardisplay in ('inkyphat', 'inky'): - print("inky display") - from inky import InkyPHAT - epd = InkyPHAT(config['ui']['display']['color']) - epd.set_border(InkyPHAT.BLACK) - self._render_cb = self._inky_render - elif cleardisplay in ('papirus', 'papi'): - print("papirus display") - from pwnagotchi.ui.papirus.epd import EPD - os.environ['EPD_SIZE'] = '2.0' - epd = EPD() - epd.clear() - elif cleardisplay in ('waveshare_1', 'ws_1', 'waveshare1', 'ws1'): - print("waveshare v1 display") - from pwnagotchi.ui.waveshare.v1.epd2in13 import EPD - epd = EPD() - epd.init(epd.lut_full_update) - epd.Clear(0xFF) - elif cleardisplay in ('waveshare_2', 'ws_2', 'waveshare2', 'ws2'): - print("waveshare v2 display") - from pwnagotchi.ui.waveshare.v2.waveshare import EPD - epd = EPD() - epd.init(epd.FULL_UPDATE) - epd.Clear(0xff) - else: - print("unknown display type %s" % cleardisplay) - quit() + config = yaml.safe_load(fp) + cleardisplay = config['ui']['display']['type'] + if cleardisplay in ('inkyphat', 'inky'): + print("inky display") + from inky import InkyPHAT + + epd = InkyPHAT(config['ui']['display']['color']) + epd.set_border(InkyPHAT.BLACK) + self._render_cb = self._inky_render + elif cleardisplay in ('papirus', 'papi'): + print("papirus display") + from pwnagotchi.ui.papirus.epd import EPD + + os.environ['EPD_SIZE'] = '2.0' + epd = EPD() + epd.clear() + elif cleardisplay in ('waveshare_1', 'ws_1', 'waveshare1', 'ws1'): + print("waveshare v1 display") + from pwnagotchi.ui.waveshare.v1.epd2in13 import EPD + + epd = EPD() + epd.init(epd.lut_full_update) + epd.Clear(0xFF) + elif cleardisplay in ('waveshare_2', 'ws_2', 'waveshare2', 'ws2'): + print("waveshare v2 display") + from pwnagotchi.ui.waveshare.v2.waveshare import EPD + + epd = EPD() + epd.init(epd.FULL_UPDATE) + epd.Clear(0xff) + else: + print("unknown display type %s" % cleardisplay) + quit() with open(args.config, 'rt') as fp: config = yaml.safe_load(fp) +plugins.load_from_path(plugins.default_path) +if 'plugins' in config['main'] and config['main']['plugins'] is not None: + plugins.load_from_path(config['main']['plugins']) + +plugins.on('loaded') + display = Display(config=config, state={'name': '%s>' % pwnagotchi.name()}) agent = Agent(view=display, config=config) @@ -65,6 +75,9 @@ core.log("%s@%s (v%s)" % (pwnagotchi.name(), agent._identity, pwnagotchi.version # for key, value in config['personality'].items(): # core.log(" %s: %s" % (key, value)) +for _, plugin in plugins.loaded.items(): + core.log("plugin '%s' v%s loaded from %s" % (plugin.__name__, plugin.__version__, plugin.__file__)) + if args.do_manual: core.log("entering manual mode ...") @@ -112,13 +125,15 @@ core.logfile = config['main']['log'] agent.start_ai() agent.setup_events() -agent.set_ready() +agent.set_starting() agent.start_monitor_mode() agent.start_event_polling() # print initial stats agent.next_epoch() +agent.set_ready() + while True: try: # recon on all channels diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py index ff434946..dacb09c6 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py @@ -1,7 +1,5 @@ import subprocess -version = '1.0.0a' - _name = None diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py index 1fa5112b..9dcb7fb1 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py @@ -8,6 +8,7 @@ import _thread import core +import pwnagotchi.plugins as plugins from bettercap.client import Client from pwnagotchi.mesh.utils import AsyncAdvertiser from pwnagotchi.ai.train import AsyncTrainer @@ -44,32 +45,41 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): pass return False + def config(self): + return self._config + def supported_channels(self): return self._supported_channels - def on_ai_ready(self): - self._view.on_ai_ready() + def set_starting(self): + self._view.on_starting() def set_ready(self): - self._view.on_starting() + plugins.on('ready', self) def set_free_channel(self, channel): self._view.on_free_channel(channel) + plugins.on('free_channel', self, channel) def set_bored(self): self._view.on_bored() + plugins.on('bored', self) def set_sad(self): self._view.on_sad() + plugins.on('sad', self) def set_excited(self): self._view.on_excited() + plugins.on('excited', self) def set_lonely(self): self._view.on_lonely() + plugins.on('lonely', self) def set_rebooting(self): self._view.on_rebooting() + plugins.on('rebooting', self) def setup_events(self): core.log("connecting to %s ..." % self.url) @@ -128,6 +138,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): self.start_advertising() def wait_for(self, t, sleeping=True): + plugins.on('sleep' if sleeping else 'wait', self, t) self._view.wait(t, sleeping) self._epoch.track(sleep=True, inc=t) @@ -179,6 +190,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): def set_access_points(self, aps): self._access_points = aps + plugins.on('wifi_update', self, aps) self._epoch.observe(aps, self._advertiser.peers() if self._advertiser is not None else ()) return self._access_points @@ -327,6 +339,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): try: for h in [e for e in self.events() if e['tag'] == 'wifi.client.handshake']: + filename = h['data']['file'] sta_mac = h['data']['station'] ap_mac = h['data']['ap'] key = "%s -> %s" % (sta_mac, ap_mac) @@ -334,18 +347,20 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): if key not in self._handshakes: self._handshakes[key] = h new_shakes += 1 - apsta = self._find_ap_sta_in(sta_mac, ap_mac, s) - if apsta is None: + ap_and_station = self._find_ap_sta_in(sta_mac, ap_mac, s) + if ap_and_station is None: core.log("!!! captured new handshake: %s !!!" % key) self._last_pwnd = ap_mac + plugins.on('handshake', self, filename, ap_mac, sta_mac) else: - (ap, sta) = apsta + (ap, sta) = ap_and_station self._last_pwnd = ap['hostname'] if ap['hostname'] != '' and ap[ 'hostname'] != '' else ap_mac core.log("!!! captured new handshake on channel %d: %s (%s) -> %s [%s (%s)] !!!" % ( \ ap['channel'], sta['mac'], sta['vendor'], ap['hostname'], ap['mac'], ap['vendor'])) + plugins.on('handshake', self, filename, ap, sta) except Exception as e: core.log("error: %s" % e) @@ -419,6 +434,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): except Exception as e: self._on_error(ap['mac'], e) + plugins.on('association', self, ap) if throttle > 0: time.sleep(throttle) self._view.on_normal() @@ -439,6 +455,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): except Exception as e: self._on_error(sta['mac'], e) + plugins.on('deauthentication', self, ap, sta) if throttle > 0: time.sleep(throttle) self._view.on_normal() @@ -470,6 +487,9 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): self._current_channel = channel self._epoch.track(hop=True) self._view.set('channel', '%d' % channel) + + plugins.on('channel_hop', self, channel) + except Exception as e: core.log("error: %s" % e) @@ -509,6 +529,8 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): core.log("%d epochs with activity -> excited" % self._epoch.active_for) self.set_excited() + plugins.on('epoch', self, self._epoch.epoch - 1, self._epoch.data()) + if self._epoch.blind_for >= self._config['main']['mon_max_blind_epochs']: core.log("%d epochs without visible access points -> rebooting ..." % self._epoch.blind_for) self._reboot() diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py index bdd8c2e1..8508eb97 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py @@ -7,6 +7,7 @@ import pwnagotchi.mesh.wifi as wifi from pwnagotchi.ai.reward import RewardFunction + class Epoch(object): def __init__(self, config): self.epoch = 0 @@ -92,7 +93,8 @@ class Epoch(object): try: peers_per_chan[peer.last_channel - 1] += 1.0 except IndexError as e: - core.log("got peer data on channel %d, we can store %d channels" % (peer.last_channel, wifi.NumChannels)) + core.log( + "got peer data on channel %d, we can store %d channels" % (peer.last_channel, wifi.NumChannels)) # normalize aps_per_chan = [e / num_aps for e in aps_per_chan] diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py index 1312715c..34140dd8 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py @@ -7,6 +7,7 @@ import json import core +import pwnagotchi.plugins as plugins import pwnagotchi.ai as ai from pwnagotchi.ai.epoch import Epoch @@ -68,14 +69,14 @@ class Stats(object): core.log("[ai] saving %s" % self.path) data = json.dumps({ - 'born_at': self.born_at, - 'epochs_lived': self.epochs_lived, - 'epochs_trained': self.epochs_trained, - 'rewards': { - 'best': self.best_reward, - 'worst': self.worst_reward - } - }) + 'born_at': self.born_at, + 'epochs_lived': self.epochs_lived, + 'epochs_trained': self.epochs_trained, + 'rewards': { + 'best': self.best_reward, + 'worst': self.worst_reward + } + }) temp = "%s.tmp" % self.path with open(temp, 'wt') as fp: @@ -98,6 +99,11 @@ class AsyncTrainer(object): self._is_training = training self._training_epochs = for_epochs + if training: + plugins.on('ai_training_start', self, for_epochs) + else: + plugins.on('ai_training_end', self) + def is_training(self): return self._is_training @@ -123,8 +129,10 @@ class AsyncTrainer(object): def on_ai_training_step(self, _locals, _globals): self._model.env.render() + plugins.on('ai_training_step', self, _locals, _globals) def on_ai_policy(self, new_params): + plugins.on('ai_policy', self, new_params) core.log("[ai] setting new policy:") for name, value in new_params.items(): if name in self._config['personality']: @@ -139,13 +147,19 @@ class AsyncTrainer(object): self.run('set wifi.sta.ttl %d' % self._config['personality']['sta_ttl']) self.run('set wifi.rssi.min %d' % self._config['personality']['min_rssi']) + def on_ai_ready(self): + self._view.on_ai_ready() + plugins.on('ai_ready', self) + def on_ai_best_reward(self, r): core.log("[ai] best reward so far: %s" % r) self._view.on_motivated(r) + plugins.on('ai_best_reward', self, r) def on_ai_worst_reward(self, r): core.log("[ai] worst reward so far: %s" % r) self._view.on_demotivated(r) + plugins.on('ai_worst_reward', self, r) def _ai_worker(self): self._model = ai.load(self._config, self, self._epoch) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.mo index e78a76aa..9a26d44b 100644 Binary files a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.mo and b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.mo differ diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po index 95393cb1..676a8bb0 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po @@ -1,14 +1,13 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. +# German language +# Copyright (C) 2019 +# This file is distributed under the same license as the pwnagotchi package. +# dadav <33197631+dadav@users.noreply.github.com>, 2019. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-29 13:34+0200\n" +"POT-Creation-Date: 2019-10-03 12:22+0200\n" "PO-Revision-Date: 2019-09-29 14:00+0200\n" "Last-Translator: dadav <33197631+dadav@users.noreply.github.com>\n" "Language-Team: DE <33197631+dadav@users.noreply.github.com>\n" @@ -17,28 +16,19 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: voice.py:16 +#: voice.py:18 msgid "ZzzzZZzzzzZzzz" msgstr "" -#: voice.py:21 -msgid "" -"Hi, I'm Pwnagotchi!\n" -"Starting ..." -msgstr "" -"Hi, ich bin\n" -"ein Pwnagotchi!\n" -"Starte ..." - #: voice.py:22 -msgid "" -"New day, new hunt,\n" -"new pwns!" -msgstr "" -"Neuer Tag, neue Jagd,\n" -"neue Pwns!" +msgid "Hi, I'm Pwnagotchi! Starting ..." +msgstr "Hi, ich bin ein Pwnagotchi! Starte ..." #: voice.py:23 +msgid "New day, new hunt, new pwns!" +msgstr "Neuer Tag, neue Jagd, neue Pwns!" + +#: voice.py:24 msgid "Hack the Planet!" msgstr "Hack den Planet!" @@ -47,298 +37,202 @@ msgid "AI ready." msgstr "KI bereit." #: voice.py:29 -msgid "" -"The neural network\n" -"is ready." -msgstr "" -"Das neurale Netz\n" -"ist bereit." +msgid "The neural network is ready." +msgstr "Das neurale Netz ist bereit." -#: voice.py:39 +#: voice.py:37 #, python-brace-format -msgid "" -"Hey, channel {channel} is\n" -"free! Your AP will\n" -"say thanks." -msgstr "" -"Hey, Channel {channel} ist\n" -"frei! Dein AP wird\n" -"es dir danken." +msgid "Hey, channel {channel} is free! Your AP will say thanks." +msgstr "Hey, Channel {channel} ist frei! Dein AP wir des dir danken." -#: voice.py:44 +#: voice.py:41 msgid "I'm bored ..." msgstr "Mir ist langweilig..." -#: voice.py:45 +#: voice.py:42 msgid "Let's go for a walk!" msgstr "Lass uns laufen gehen!" -#: voice.py:49 -msgid "" -"This is the best\n" -"day of my life!" -msgstr "" -"Das ist der beste\n" -"Tag meines Lebens." +#: voice.py:45 +msgid "This is the best day of my life!" +msgstr "Das ist der beste Tag meines Lebens." -#: voice.py:53 +#: voice.py:48 msgid "Shitty day :/" msgstr "Scheis Tag :/" -#: voice.py:58 +#: voice.py:52 msgid "I'm extremely bored ..." msgstr "Mir ist sau langweilig..." -#: voice.py:59 +#: voice.py:53 msgid "I'm very sad ..." msgstr "Ich bin sehr traurig..." -#: voice.py:60 +#: voice.py:54 msgid "I'm sad" msgstr "Ich bin traurig" -#: voice.py:66 +#: voice.py:59 msgid "I'm living the life!" msgstr "Ich lebe das Leben!" -#: voice.py:67 +#: voice.py:60 msgid "I pwn therefore I am." msgstr "Ich pwne, also bin ich." -#: voice.py:68 +#: voice.py:61 msgid "So many networks!!!" msgstr "So viele Netwerke!!!" -#: voice.py:69 -msgid "" -"I'm having so much\n" -"fun!" -msgstr "" -"Ich habe sooo viel\n" -"Spaß!" +#: voice.py:62 +msgid "I'm having so much fun!" +msgstr "Ich habe sooo viel Spaß!" -#: voice.py:70 -msgid "" -"My crime is that of\n" -"curiosity ..." -msgstr "" -"Mein Verbrechen ist\n" -"das der Neugier ..." +#: voice.py:63 +msgid "My crime is that of curiosity ..." +msgstr "Mein Verbrechen ist das der Neugier ..." -#: voice.py:75 +#: voice.py:67 #, python-brace-format -msgid "" -"Hello\n" -"{name}!\n" -"Nice to meet you. {name}" -msgstr "" -"Hallo {name},\n" -"Nett Dich\n" -"kennenzulernen." +msgid "Hello {name}! Nice to meet you. {name}" +msgstr "Hallo {name}, nett Dich kennenzulernen." -#: voice.py:76 +#: voice.py:68 #, python-brace-format -msgid "" -"Unit\n" -"{name}\n" -"is nearby! {name}" -msgstr "" -"Gerät {name}\n" -"ist in der\n" -"nähe!!" +msgid "Unit {name} is nearby! {name}" +msgstr "Gerät {name} ist in der nähe!!" -#: voice.py:81 +#: voice.py:72 #, python-brace-format -msgid "" -"Uhm ...\n" -"goodbye\n" -"{name}" -msgstr "" -"Uhm ...\n" -"tschüß\n" -"{name}" +msgid "Uhm ... goodbye {name}" +msgstr "Uhm ...tschüß {name}" -#: voice.py:82 +#: voice.py:73 #, python-brace-format -msgid "" -"{name}\n" -"is gone ..." -msgstr "" -"{name}\n" -"ist weg ..." +msgid "{name} is gone ..." +msgstr "{name} ist weg ..." -#: voice.py:87 +#: voice.py:77 #, python-brace-format -msgid "" -"Whoops ...\n" -"{name}\n" -"is gone." -msgstr "" -"Whoops ...\n" -"{name}\n" -"ist weg." +msgid "Whoops ... {name} is gone." +msgstr "Whoops ...{name} ist weg." -#: voice.py:88 +#: voice.py:78 #, python-brace-format -msgid "" -"{name}\n" -"missed!" -msgstr "" -"{name}\n" -"verpasst!" +msgid "{name} missed!" +msgstr "{name} verpasst!" -#: voice.py:89 +#: voice.py:79 msgid "Missed!" msgstr "Verpasst!" -#: voice.py:94 -msgid "" -"Nobody wants to\n" -"play with me ..." -msgstr "" -"Niemand will mit\n" -"mir spielen ..." +#: voice.py:83 +msgid "Nobody wants to play with me ..." +msgstr "Niemand will mit mir spielen ..." -#: voice.py:95 +#: voice.py:84 msgid "I feel so alone ..." -msgstr "" -"Ich fühl mich\n" -"so alleine ..." +msgstr "Ich fühl michso alleine ..." -#: voice.py:96 +#: voice.py:85 msgid "Where's everybody?!" msgstr "Wo sind denn alle?" -#: voice.py:101 +#: voice.py:89 #, python-brace-format msgid "Napping for {secs}s ..." msgstr "Schlafe für {secs}s" -#: voice.py:102 +#: voice.py:90 msgid "Zzzzz" msgstr "" -#: voice.py:103 +#: voice.py:91 #, python-brace-format msgid "ZzzZzzz ({secs}s)" msgstr "" -#: voice.py:112 +#: voice.py:98 #, python-brace-format msgid "Waiting for {secs}s ..." msgstr "Warte für {secs}s ..." -#: voice.py:114 +#: voice.py:100 #, python-brace-format msgid "Looking around ({secs}s)" msgstr "Schaue mich um ({secs}s)" +#: voice.py:106 +#, python-brace-format +msgid "Hey {what} let's be friends!" +msgstr "Hey {what}, lass uns Freunde sein!" + +#: voice.py:107 +#, python-brace-format +msgid "Associating to {what}" +msgstr "Verbinde mit {what}" + +#: voice.py:108 +#, python-brace-format +msgid "Yo {what}!" +msgstr "" + +#: voice.py:112 +#, python-brace-format +msgid "Just decided that {mac} needs no WiFi!" +msgstr "Ich denke, dass {mac} kein WiFi brauch!" + +#: voice.py:113 +#, python-brace-format +msgid "Deauthenticating {mac}" +msgstr "Deauthentifiziere {mac}" + +#: voice.py:114 +#, python-brace-format +msgid "Kickbanning {mac}!" +msgstr "Kicke {mac}!" + +#: voice.py:118 +#, python-brace-format +msgid "Cool, we got {num} new handshake{plural}!" +msgstr "Cool, wir haben {num} neue Handshake{plural}!" + #: voice.py:121 -#, python-brace-format -msgid "" -"Hey\n" -"{what}\n" -"let's be friends!" -msgstr "" -"Hey\n" -"{what}\n" -"lass uns Freunde sein!" +msgid "Ops, something went wrong ... Rebooting ..." +msgstr "Ops, da ist etwas schief gelaufen ...Starte neu ..." -#: voice.py:122 -#, python-brace-format -msgid "" -"Associating to\n" -"{what}" -msgstr "" -"Verbinde mit\n" -"{what}" - -#: voice.py:123 -#, python-brace-format -msgid "" -"Yo\n" -"{what}!" -msgstr "" - -#: voice.py:128 -#, python-brace-format -msgid "" -"Just decided that\n" -"{mac}\n" -"needs no WiFi!" -msgstr "" -"Ich denke,\n" -"dass {mac}\n" -"kein WiFi brauch!" - -#: voice.py:129 -#, python-brace-format -msgid "" -"Deauthenticating\n" -"{mac}" -msgstr "" -"Deauthentifiziere\n" -"{mac}" - -#: voice.py:130 -#, python-brace-format -msgid "" -"Kickbanning\n" -"{mac}!" -msgstr "" -"Kicke\n" -"{mac}!" - -#: voice.py:135 -#, python-brace-format -msgid "" -"Cool, we got {num}\n" -"new handshake{plural}!" -msgstr "" -"Cool, wir haben {num}\n" -"neue Handshake{plural}!" - -#: voice.py:139 -msgid "" -"Ops, something\n" -"went wrong ...\n" -"Rebooting ..." -msgstr "" -"Ops, da ist etwas\n" -"schief gelaufen ...\n" -"Starte neu ..." - -#: voice.py:143 +#: voice.py:124 #, python-brace-format msgid "Kicked {num} stations\n" msgstr "{num} Stationen gekicked\n" -#: voice.py:144 +#: voice.py:125 #, python-brace-format msgid "Made {num} new friends\n" msgstr "{num} Freunde gefunden\n" -#: voice.py:145 +#: voice.py:126 #, python-brace-format msgid "Got {num} handshakes\n" msgstr "{num} Handshakes aufgez.\n" -#: voice.py:147 +#: voice.py:128 msgid "Met 1 peer" msgstr "1 Peer getroffen." -#: voice.py:149 +#: voice.py:130 #, python-brace-format msgid "Met {num} peers" msgstr "{num} Peers getroffen" -#: voice.py:154 +#: voice.py:135 #, python-brace-format msgid "" "I've been pwning for {duration} and kicked {deauthed} clients! I've also met " "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "#pwnlog #pwnlife #hacktheplanet #skynet" msgstr "" -"Ich war {duration} am Pwnen und habe {deauthed} Clients gekickt! Außerdem habe ich " -"{associated} neue Freunde getroffen und {handshakes} Handshakes gefressen! #pwnagotchi " -"#pwnlog #pwnlife #hacktheplanet #skynet" +"Ich war {duration} am Pwnen und habe {deauthed} Clients gekickt! Außerdem " +"habe ich {associated} neue Freunde getroffen und {handshakes} Handshakes " +"gefressen! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/el/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/el/LC_MESSAGES/voice.mo new file mode 100644 index 00000000..f5c4d5ab Binary files /dev/null and b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/el/LC_MESSAGES/voice.mo differ diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/el/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/el/LC_MESSAGES/voice.po new file mode 100644 index 00000000..46f90c27 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/el/LC_MESSAGES/voice.po @@ -0,0 +1,247 @@ +# pwnigotchi voice data +# Copyright (C) 2019 +# This file is distributed under the same license as the pwnagotchi package. +# FIRST AUTHOR Periklis Fregkos , 2019. +# CO AUTHOR Panos Vasilopoulos , 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-10-03 12:22+0200\n" +"PO-Revision-Date: 2019-10-03 08:00+0000\n" +"Last-Translator: Periklis Fregkos \n" +"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: voice.py:18 +msgid "ZzzzZZzzzzZzzz" +msgstr "" + +#: voice.py:22 +#, fuzzy +msgid "Hi, I'm Pwnagotchi! Starting ..." +msgstr "Γειά, είμαι το Pwnagotchi!Εκκινούμαι ..." + +#: voice.py:23 +#, fuzzy +msgid "New day, new hunt, new pwns!" +msgstr "Νέα μέρα, νέο κυνήγι,νέα pwns!" + +#: voice.py:24 +msgid "Hack the Planet!" +msgstr "Hackαρε τον πλανήτη!" + +#: voice.py:28 +msgid "AI ready." +msgstr "ΤΝ έτοιμη." + +#: voice.py:29 +#, fuzzy +msgid "The neural network is ready." +msgstr "Το νευρωνικό δίκτυοείναι έτοιμο." + +#: voice.py:37 +#, fuzzy, python-brace-format +msgid "Hey, channel {channel} is free! Your AP will say thanks." +msgstr "Ε, το κανάλι {channel} είναιελεύθερο! Το AP σου θαείναι ευγνώμων." + +#: voice.py:41 +msgid "I'm bored ..." +msgstr "Βαριέμαι ..." + +#: voice.py:42 +msgid "Let's go for a walk!" +msgstr "Ας πάμε μια βόλτα!" + +#: voice.py:45 +#, fuzzy +msgid "This is the best day of my life!" +msgstr "Είναι η καλύτερημέρα της ζωής μου!" + +#: voice.py:48 +msgid "Shitty day :/" +msgstr "Σκατένια μέρα :/" + +#: voice.py:52 +msgid "I'm extremely bored ..." +msgstr "Βαριέμαι πάρα πολύ ..." + +#: voice.py:53 +msgid "I'm very sad ..." +msgstr "Είμαι πολύ λυπημένο ..." + +#: voice.py:54 +msgid "I'm sad" +msgstr "Είμαι λυπημένο" + +#: voice.py:59 +msgid "I'm living the life!" +msgstr "Ζω την ζωή μου!" + +#: voice.py:60 +msgid "I pwn therefore I am." +msgstr "Pwnάρω, άρα υπάρχω." + +#: voice.py:61 +msgid "So many networks!!!" +msgstr "Τόσα πολλά δίκτυα!!!" + +#: voice.py:62 +#, fuzzy +msgid "I'm having so much fun!" +msgstr "Περνάω τέλεια!" + +#: voice.py:63 +#, fuzzy +msgid "My crime is that of curiosity ..." +msgstr "Η περιέργεια είναιτο μόνο έγκλημά μου ..." + +#: voice.py:67 +#, fuzzy, python-brace-format +msgid "Hello {name}! Nice to meet you. {name}" +msgstr "Γειά {name}!Χάρηκα για τη γνωριμία. {name}" + +#: voice.py:68 +#, fuzzy, python-brace-format +msgid "Unit {name} is nearby! {name}" +msgstr "Η μονάδα{name}είναι κοντά! {name}" + +#: voice.py:72 +#, fuzzy, python-brace-format +msgid "Uhm ... goodbye {name}" +msgstr "Εμμ ...αντίο{name}" + +#: voice.py:73 +#, fuzzy, python-brace-format +msgid "{name} is gone ..." +msgstr "Το {name}έφυγε ..." + +#: voice.py:77 +#, fuzzy, python-brace-format +msgid "Whoops ... {name} is gone." +msgstr "Ουπς ... Εξαφανίστηκε το{name}." + +#: voice.py:78 +#, fuzzy, python-brace-format +msgid "{name} missed!" +msgstr "Έχασα το{name}!" + +#: voice.py:79 +msgid "Missed!" +msgstr "Το έχασα!" + +#: voice.py:83 +#, fuzzy +msgid "Nobody wants to play with me ..." +msgstr "Κανείς δε θέλει ναπαίξει μαζί μου ..." + +#: voice.py:84 +msgid "I feel so alone ..." +msgstr "Νιώθω μοναχός μου ..." + +#: voice.py:85 +msgid "Where's everybody?!" +msgstr "Μα, πού πήγαν όλοι;!" + +#: voice.py:89 +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "Ξεκουράζομαι για {secs}s ..." + +#: voice.py:90 +msgid "Zzzzz" +msgstr "" + +#: voice.py:91 +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "" + +#: voice.py:98 +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "Περιμένω για {secs}s ..." + +#: voice.py:100 +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "Ψάχνω τριγύρω ({secs})" + +#: voice.py:106 +#, fuzzy, python-brace-format +msgid "Hey {what} let's be friends!" +msgstr "Εε!{what},ας γίνουμε φίλοι!" + +#: voice.py:107 +#, fuzzy, python-brace-format +msgid "Associating to {what}" +msgstr "Συνδέομαι με το{what}" + +#: voice.py:108 +#, fuzzy, python-brace-format +msgid "Yo {what}!" +msgstr "Που'σαι ρε τρελέ{what}!" + +#: voice.py:112 +#, fuzzy, python-brace-format +msgid "Just decided that {mac} needs no WiFi!" +msgstr "Μόλις αποφάσισα ότι η{mac}δε χρείαζεται WiFi!" + +#: voice.py:113 +#, fuzzy, python-brace-format +msgid "Deauthenticating {mac}" +msgstr "Πετάω έξω την{mac}" + +#: voice.py:114 +#, fuzzy, python-brace-format +msgid "Kickbanning {mac}!" +msgstr "Μπανάρω την{mac}!" + +#: voice.py:118 +#, fuzzy, python-brace-format +msgid "Cool, we got {num} new handshake{plural}!" +msgstr "Τέλεια δικέ μου, πήραμε {num}νέες χειραψίες!" + +#: voice.py:121 +#, fuzzy +msgid "Ops, something went wrong ... Rebooting ..." +msgstr "Ουπς, κάτιπήγε λάθος ...Επανεκκινούμαι ..." + +#: voice.py:124 +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "Έριξα {num} σταθμούς\n" + +#: voice.py:125 +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "Έκανα {num} νέους φίλους\n" + +#: voice.py:126 +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "Πήρα {num} χειραψίες\n" + +#: voice.py:128 +msgid "Met 1 peer" +msgstr "Γνώρισα 1 φίλο" + +#: voice.py:130 +#, python-brace-format +msgid "Met {num} peers" +msgstr "Γνώρισα {num} φίλους" + +#: voice.py:135 +#, python-brace-format +msgid "" +"I've been pwning for {duration} and kicked {deauthed} clients! I've also met " +"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" +msgstr "" +"Pwnαρα για {duration} και έριξα {deauthed} πελάτες! Επίσης γνώρισα " +"{associated} νέους φίλους και καταβρόχθισα {handshakes} χειραψίες! " +"#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/fr/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/fr/LC_MESSAGES/voice.mo new file mode 100644 index 00000000..f6283273 Binary files /dev/null and b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/fr/LC_MESSAGES/voice.mo differ diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/fr/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/fr/LC_MESSAGES/voice.po new file mode 100644 index 00000000..17d03f3d --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/fr/LC_MESSAGES/voice.po @@ -0,0 +1,237 @@ +# pwnigotchi voice data +# Copyright (C) 2019 +# This file is distributed under the same license as the pwnagotchi package. +# FIRST AUTHOR <7271496+quantumsheep@users.noreply.github.com>, 2019. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 0.0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-10-03 12:22+0200\n" +"PO-Revision-Date: 2019-10-03 10:34+0200\n" +"Last-Translator: quantumsheep <7271496+quantumsheep@users.noreply.github." +"com>\n" +"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" +"Language: french\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: voice.py:18 +msgid "ZzzzZZzzzzZzzz" +msgstr "" + +#: voice.py:22 +msgid "Hi, I'm Pwnagotchi! Starting ..." +msgstr "" + +#: voice.py:23 +msgid "New day, new hunt, new pwns!" +msgstr "" + +#: voice.py:24 +msgid "Hack the Planet!" +msgstr "" + +#: voice.py:28 +msgid "AI ready." +msgstr "" + +#: voice.py:29 +msgid "The neural network is ready." +msgstr "" + +#: voice.py:37 +#, python-brace-format +msgid "Hey, channel {channel} is free! Your AP will say thanks." +msgstr "" + +#: voice.py:41 +msgid "I'm bored ..." +msgstr "" + +#: voice.py:42 +msgid "Let's go for a walk!" +msgstr "" + +#: voice.py:45 +msgid "This is the best day of my life!" +msgstr "" + +#: voice.py:48 +msgid "Shitty day :/" +msgstr "" + +#: voice.py:52 +msgid "I'm extremely bored ..." +msgstr "" + +#: voice.py:53 +msgid "I'm very sad ..." +msgstr "" + +#: voice.py:54 +msgid "I'm sad" +msgstr "" + +#: voice.py:59 +msgid "I'm living the life!" +msgstr "" + +#: voice.py:60 +msgid "I pwn therefore I am." +msgstr "" + +#: voice.py:61 +msgid "So many networks!!!" +msgstr "" + +#: voice.py:62 +msgid "I'm having so much fun!" +msgstr "" + +#: voice.py:63 +msgid "My crime is that of curiosity ..." +msgstr "" + +#: voice.py:67 +#, python-brace-format +msgid "Hello {name}! Nice to meet you. {name}" +msgstr "" + +#: voice.py:68 +#, python-brace-format +msgid "Unit {name} is nearby! {name}" +msgstr "" + +#: voice.py:72 +#, python-brace-format +msgid "Uhm ... goodbye {name}" +msgstr "" + +#: voice.py:73 +#, python-brace-format +msgid "{name} is gone ..." +msgstr "" + +#: voice.py:77 +#, python-brace-format +msgid "Whoops ... {name} is gone." +msgstr "" + +#: voice.py:78 +#, python-brace-format +msgid "{name} missed!" +msgstr "" + +#: voice.py:79 +msgid "Missed!" +msgstr "" + +#: voice.py:83 +msgid "Nobody wants to play with me ..." +msgstr "" + +#: voice.py:84 +msgid "I feel so alone ..." +msgstr "" + +#: voice.py:85 +msgid "Where's everybody?!" +msgstr "" + +#: voice.py:89 +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "" + +#: voice.py:90 +msgid "Zzzzz" +msgstr "" + +#: voice.py:91 +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "" + +#: voice.py:98 +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "" + +#: voice.py:100 +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "" + +#: voice.py:106 +#, python-brace-format +msgid "Hey {what} let's be friends!" +msgstr "" + +#: voice.py:107 +#, python-brace-format +msgid "Associating to {what}" +msgstr "" + +#: voice.py:108 +#, python-brace-format +msgid "Yo {what}!" +msgstr "" + +#: voice.py:112 +#, python-brace-format +msgid "Just decided that {mac} needs no WiFi!" +msgstr "" + +#: voice.py:113 +#, python-brace-format +msgid "Deauthenticating {mac}" +msgstr "" + +#: voice.py:114 +#, python-brace-format +msgid "Kickbanning {mac}!" +msgstr "" + +#: voice.py:118 +#, python-brace-format +msgid "Cool, we got {num} new handshake{plural}!" +msgstr "" + +#: voice.py:121 +msgid "Ops, something went wrong ... Rebooting ..." +msgstr "" + +#: voice.py:124 +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "" + +#: voice.py:125 +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "" + +#: voice.py:126 +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "" + +#: voice.py:128 +msgid "Met 1 peer" +msgstr "" + +#: voice.py:130 +#, python-brace-format +msgid "Met {num} peers" +msgstr "" + +#: voice.py:135 +#, python-brace-format +msgid "" +"I've been pwning for {duration} and kicked {deauthed} clients! I've also met " +"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" +msgstr "" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.mo deleted file mode 100644 index b2bf23d5..00000000 Binary files a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.mo and /dev/null differ diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.po deleted file mode 100644 index 26a2511d..00000000 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.po +++ /dev/null @@ -1,339 +0,0 @@ -# pwnigotchi voice data -# Copyright (C) 2019 -# This file is distributed under the same license as the pwnagotchi package. -# FIRST AUTHOR Perilis Fregkos , 2019. -# -msgid "" -msgstr "" -"Project-Id-Version: 0.0.1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-29 13:42+0200\n" -"PO-Revision-Date: 2019-10-01 16:22+0000\n" -"Last-Translator: Panos Vasilopoulos \n" -"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" -"Language: el\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: voice.py:16 -msgid "ZzzzZZzzzzZzzz" -msgstr "" - -#: voice.py:21 -msgid "" -"Hi, I'm Pwnagotchi!\n" -"Starting ..." -msgstr "" -"Γεία, είμαι το Pwnagotchi!\n" -"Εκκινούμαι ..." - -#: voice.py:22 -msgid "" -"New day, new hunt,\n" -"new pwns!" -msgstr "" -"Νέα μέρα, νέο κυνήγι,\n" -"νέα pwns!" - -#: voice.py:23 -msgid "Hack the Planet!" -msgstr "Hackαρε τον πλανήτη!" - -#: voice.py:28 -msgid "AI ready." -msgstr "ΤΝ έτοιμη." - -#: voice.py:29 -msgid "" -"The neural network\n" -"is ready." -msgstr "" -"Το νευρωνικό δίκτυο\n" -"είναι έτοιμο." - -#: voice.py:39 -#, python-brace-format -msgid "" -"Hey, channel {channel} is\n" -"free! Your AP will\n" -"say thanks." -msgstr "" -"Ε, το κανάλι {channel} είναι\n" -"ελεύθερο! Το AP σου θα\n" -"είναι ευγνώμων." - -#: voice.py:44 -msgid "I'm bored ..." -msgstr "Βαριέμαι ..." - -#: voice.py:45 -msgid "Let's go for a walk!" -msgstr "Ας πάμε μια βόλτα!" - -#: voice.py:49 -msgid "" -"This is the best\n" -"day of my life!" -msgstr "" -"Είναι η καλύτερη\n" -"μέρα της ζωής μου!" - -#: voice.py:53 -msgid "Shitty day :/" -msgstr "Σκατένια μέρα :/" - -#: voice.py:58 -msgid "I'm extremely bored ..." -msgstr "Βαριέμαι πάρα πολύ ..." - -#: voice.py:59 -msgid "I'm very sad ..." -msgstr "Είμαι πολύ λυπημένο ..." - -#: voice.py:60 -msgid "I'm sad" -msgstr "Είμαι λυπημένο" - -#: voice.py:66 -msgid "I'm living the life!" -msgstr "Ζω την ζωή μου!" - -#: voice.py:67 -msgid "I pwn therefore I am." -msgstr "Pwnάρω, άρα υπάρχω." - -#: voice.py:68 -msgid "So many networks!!!" -msgstr "Τόσα πολλά δίκτυα!!!" - -#: voice.py:69 -msgid "" -"I'm having so much\n" -"fun!" -msgstr "Περνάω τέλεια!" - -#: voice.py:70 -msgid "" -"My crime is that of\n" -"curiosity ..." -msgstr "" -"Η περιέργεια είναι\n" -"το μόνο έγκλημά μου ..." - -#: voice.py:75 -#, python-brace-format -msgid "" -"Hello\n" -"{name}!\n" -"Nice to meet you. {name}" -msgstr "" -"Γειά {name}!\n" -"Χάρηκα για τη γνωριμία. {name}" - -#: voice.py:76 -#, python-brace-format -msgid "" -"Unit\n" -"{name}\n" -"is nearby! {name}" -msgstr "" -"Η μονάδα\n" -"{name}\n" -"είναι κοντά! {name}" - -#: voice.py:81 -#, python-brace-format -msgid "" -"Uhm ...\n" -"goodbye\n" -"{name}" -msgstr "" -"Εμμ ...\n" -"αντίο\n" -"{name}" - -#: voice.py:82 -#, python-brace-format -msgid "" -"{name}\n" -"is gone ..." -msgstr "" -"Το {name}\n" -"έφυγε ..." - -#: voice.py:87 -#, python-brace-format -msgid "" -"Whoops ...\n" -"{name}\n" -"is gone." -msgstr "" -"Ουπς ... \n" -"Εξαφανίστηκε το\n" -"{name}." - -#: voice.py:88 -#, python-brace-format -msgid "" -"{name}\n" -"missed!" -msgstr "" -"Έχασα το\n" -"{name}!" - -#: voice.py:89 -msgid "Missed!" -msgstr "Το έχασα!" - -#: voice.py:94 -msgid "" -"Nobody wants to\n" -"play with me ..." -msgstr "" -"Κανείς δε θέλει να\n" -"παίξει μαζί μου ..." - -#: voice.py:95 -msgid "I feel so alone ..." -msgstr "Νιώθω μοναχός μου ..." - -#: voice.py:96 -msgid "Where's everybody?!" -msgstr "Μα, πού πήγαν όλοi;!" - -#: voice.py:101 -#, python-brace-format -msgid "Napping for {secs}s ..." -msgstr "Ξεκουράζομαι για {secs}s ..." - -#: voice.py:102 -msgid "Zzzzz" -msgstr "" - -#: voice.py:103 -#, python-brace-format -msgid "ZzzZzzz ({secs}s)" -msgstr "" - -#: voice.py:112 -#, python-brace-format -msgid "Waiting for {secs}s ..." -msgstr "Περιμένω για {secs}s ..." - -#: voice.py:114 -#, python-brace-format -msgid "Looking around ({secs}s)" -msgstr "Ψάχνω τριγύρω ({secs})" - -#: voice.py:121 -#, python-brace-format -msgid "" -"Hey\n" -"{what}\n" -"let's be friends!" -msgstr "" -"Εε!\n" -"{what},\n" -"ας γίνουμε φίλοι!" - -#: voice.py:122 -#, python-brace-format -msgid "" -"Associating to\n" -"{what}" -msgstr "" -"Συνδέομαι με το\n" -"{what}" - -#: voice.py:123 -#, python-brace-format -msgid "" -"Yo\n" -"{what}!" -msgstr "" -"Που'σ ρε τρελέ\n" -"{what}!" - -#: voice.py:128 -#, python-brace-format -msgid "" -"Just decided that\n" -"{mac}\n" -"needs no WiFi!" -msgstr "" -"Μόλις αποφάσισα ότι η\n" -"{mac}\n" -"δε χρείαζεται WiFi!" - -#: voice.py:129 -#, python-brace-format -msgid "" -"Deauthenticating\n" -"{mac}" -msgstr "" -"Πετάω έξω την\n" -"{mac}" - -#: voice.py:130 -#, python-brace-format -msgid "" -"Kickbanning\n" -"{mac}!" -msgstr "" -"Μπανάρω την\n" -"{mac}!" - -#: voice.py:135 -#, python-brace-format -msgid "" -"Cool, we got {num}\n" -"new handshake{plural}!" -msgstr "" -"Τέλεια δικέ μου, πήραμε {num}\n" -"νέες χειραψίες{plural}!" - -#: voice.py:139 -msgid "" -"Ops, something\n" -"went wrong ...\n" -"Rebooting ..." -msgstr "" -"Ουπς, κάτι\n" -"πήγε λάθος ...\n" -"Επανεκκινούμαι ..." - -#: voice.py:143 -#, python-brace-format -msgid "Kicked {num} stations\n" -msgstr "Έριξα {num} σταθμούς\n" - -#: voice.py:144 -#, python-brace-format -msgid "Made {num} new friends\n" -msgstr "Έκανα {num} νέους φίλους\n" - -#: voice.py:145 -#, python-brace-format -msgid "Got {num} handshakes\n" -msgstr "Πήρα {num} χειραψίες\n" - -#: voice.py:147 -msgid "Met 1 peer" -msgstr "Γνώρισα 1 φίλο" - -#: voice.py:149 -#, python-brace-format -msgid "Met {num} peers" -msgstr "Γνώρισα {num} φίλους" - -#: voice.py:154 -#, python-brace-format -msgid "" -"I've been pwning for {duration} and kicked {deauthed} clients! I've also met " -"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi #pwnlog " -"#pwnlife #hacktheplanet #skynet" -msgstr "" -"Pwnαρα για {duration} και έριξα {deauthed} πελάτες! Επίσης γνώρισα " -"{associated} νέους φίλους και καταβρόχθισα {handshakes} χειραψίες! #pwnagotchi " -"#pwnlog #pwnlife #hacktheplanet #skynet" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.mo index 038f5023..be9d4b19 100644 Binary files a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.mo and b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.mo differ diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po index da7383ae..7ef4d8d7 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po @@ -1,347 +1,239 @@ -# pwnigotchi voice data +# pwnaigotchi voice data # Copyright (C) 2019 # This file is distributed under the same license as the pwnagotchi package. -# 5h4d0wb0y <28193209+5h4d0wb0y@users.noreply.github.com>, 2019. +# FIRST AUTHOR 5h4d0wb0y <28193209+5h4d0wb0y@users.noreply.github.com>, 2019. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-01 14:15+0200\n" -"PO-Revision-Date: 2019-10-01 14:00+0200\n" -"Last-Translator: 5h4d0wb0y <28193209+5h4d0wb0y@users.noreply.github.com>\n" +"POT-Creation-Date: 2019-10-03 13:10+0200\n" +"PO-Revision-Date: 2019-10-02 17:20+0000\n" "Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" "Language: italian\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:18 +#: voice.py:18 msgid "ZzzzZZzzzzZzzz" -msgstr "ZzzzZZzzzzZzzz" - -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:23 -msgid "" -"Hi, I'm Pwnagotchi!\n" -"Starting ..." msgstr "" -"Ciao, sono Pwnagotchi!\n" -"Avviamento ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:24 -msgid "" -"New day, new hunt,\n" -"new pwns!" -msgstr "" -"Nuovo giorno, nuova caccia,\n" -"nuovi pwns!" +#: voice.py:22 +msgid "Hi, I'm Pwnagotchi! Starting ..." +msgstr "Ciao! Piacere Pwnagotchi! Caricamento ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:25 +#: voice.py:23 +#, fuzzy +msgid "New day, new hunt, new pwns!" +msgstr "Nuovo giorno...nuovi handshakes!!!" + +#: voice.py:24 msgid "Hack the Planet!" -msgstr "Hack il pianeta!" +msgstr "" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:30 +#: voice.py:28 msgid "AI ready." msgstr "IA pronta." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:31 -msgid "" -"The neural network\n" -"is ready." -msgstr "" -"La rete neurale\n" -"è pronta." +#: voice.py:29 +msgid "The neural network is ready." +msgstr "La rete neurale è pronta." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:41 +#: voice.py:37 #, python-brace-format -msgid "" -"Hey, channel {channel} is\n" -"free! Your AP will\n" -"say thanks." -msgstr "" -"Hey, il canale {channel} è\n" -"libero! Il tuo AP\n" -"dirà grazie." +msgid "Hey, channel {channel} is free! Your AP will say thanks." +msgstr "Hey, il canale {channel} è libero! Il tuo AP ringrazia." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:46 +#: voice.py:41 msgid "I'm bored ..." -msgstr "Sono annoiato ..." +msgstr "Che noia ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:47 +#: voice.py:42 msgid "Let's go for a walk!" -msgstr "Andiamo a fare una \npasseggiata!" - -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:51 -msgid "" -"This is the best\n" -"day of my life!" msgstr "" -"Questo è il migliore\n" -"giorno della mia vita!" +"Andiamo a fare una passeggiata!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:55 +#: voice.py:45 +msgid "This is the best day of my life!" +msgstr "Questo è il più bel giorno della mia vita!!!!" + +#: voice.py:48 msgid "Shitty day :/" msgstr "Giorno di merda :/" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:60 +#: voice.py:52 msgid "I'm extremely bored ..." -msgstr "" -"Sono estremamente\n" -"annoiato ..." +msgstr "Sono estremamente annoiato ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:61 +#: voice.py:53 msgid "I'm very sad ..." -msgstr "Sono molto triste ..." +msgstr "Sono molto triste..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:62 +#: voice.py:54 msgid "I'm sad" msgstr "Sono triste" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:68 +#: voice.py:59 msgid "I'm living the life!" -msgstr "Sto vivendo la vita!" +msgstr "Mi sento vivo!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:69 +#: voice.py:60 msgid "I pwn therefore I am." -msgstr "Possiedo quindi sono." +msgstr "Pwn ergo sum." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:70 +#: voice.py:61 msgid "So many networks!!!" -msgstr "Così tante reti!!!" +msgstr "Qui è pieno di reti!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:71 -msgid "" -"I'm having so much\n" -"fun!" +#: voice.py:62 +msgid "I'm having so much fun!" +msgstr "Mi sto divertendo tantissimo!" + +#: voice.py:63 +msgid "My crime is that of curiosity ..." msgstr "" -"Mi sto divertendo\n" -"tanto!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:72 -msgid "" -"My crime is that of\n" -"curiosity ..." -msgstr "" -"La mia colpa è di\n" -"essere curioso ..." - -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:77 +#: voice.py:67 #, python-brace-format -msgid "" -"Hello\n" -"{name}!\n" -"Nice to meet you. {name}" -msgstr "" -"Ciao\n" -"{name}!\n" -"Piacere di conoscerti. {name}" +msgid "Hello {name}! Nice to meet you. {name}" +msgstr "Ciao {name}! E' un piacere. {name}" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:78 +#: voice.py:68 #, python-brace-format -msgid "" -"Unit\n" -"{name}\n" -"is nearby! {name}" -msgstr "" -"L'Unità\n" -"{name}\n" -"è vicina! {name}" +msgid "Unit {name} is nearby! {name}" +msgstr "L'Unità {name} è vicina! {name}" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:83 +#: voice.py:72 #, python-brace-format -msgid "" -"Uhm ...\n" -"goodbye\n" -"{name}" -msgstr "" -"Uhm ...\n" -"addio\n" -"{name}" +msgid "Uhm ... goodbye {name}" +msgstr "Uhm ... addio {name}, mi mancherai..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:84 +#: voice.py:73 #, python-brace-format -msgid "" -"{name}\n" -"is gone ..." -msgstr "" -"{name}\n" -"è andato ..." +msgid "{name} is gone ..." +msgstr "{name} se n'è andato ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:89 +#: voice.py:77 #, python-brace-format -msgid "" -"Whoops ...\n" -"{name}\n" -"is gone." -msgstr "" -"Whoops ...\n" -"{name}\n" -"è andato." +msgid "Whoops ... {name} is gone." +msgstr "Whoops ...{name} se n'è andato." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:90 +#: voice.py:78 #, python-brace-format -msgid "" -"{name}\n" -"missed!" -msgstr "" -"{name}\n" -"perso!" +msgid "{name} missed!" +msgstr "{name} è scomparso..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:91 +#: voice.py:79 msgid "Missed!" -msgstr "Perso!" +msgstr "Ehi! Dove sei andato!?" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:96 -msgid "" -"Nobody wants to\n" -"play with me ..." -msgstr "" -"Nessuno vuole\n" -"giocare con me..." +#: voice.py:83 +msgid "Nobody wants to play with me ..." +msgstr "Nessuno vuole giocare con me..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:97 +#: voice.py:84 msgid "I feel so alone ..." -msgstr "Mi sento così solo ..." +msgstr "Mi sento così solo..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:98 +#: voice.py:85 msgid "Where's everybody?!" msgstr "Dove sono tutti?!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:103 +#: voice.py:89 #, python-brace-format msgid "Napping for {secs}s ..." -msgstr "Pisolino per {secs}i ..." +msgstr "Schiaccio un pisolino per {secs}s ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:104 +#: voice.py:90 msgid "Zzzzz" -msgstr "Zzzzz" +msgstr "" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:105 +#: voice.py:91 #, python-brace-format msgid "ZzzZzzz ({secs}s)" -msgstr "ZzzZzzz ({secs}i)" +msgstr "" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:114 +#: voice.py:98 #, python-brace-format msgid "Waiting for {secs}s ..." -msgstr "In attesa di {secs}i ..." +msgstr "Aspetto {secs}s ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:116 +#: voice.py:100 #, python-brace-format msgid "Looking around ({secs}s)" -msgstr "Guardando intorno ({secs}s)" +msgstr "Do uno sguardo qui intorno... ({secs}s)" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:123 +#: voice.py:106 #, python-brace-format -msgid "" -"Hey\n" -"{what}\n" -"let's be friends!" -msgstr "" -"Hey\n" -"{what}\n" -"diventiamo amici!" +msgid "Hey {what} let's be friends!" +msgstr "Hey {what}! Diventiamo amici!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:124 +#: voice.py:107 #, python-brace-format -msgid "" -"Associating to\n" -"{what}" -msgstr "" -"Associarci a\n" -"{what}" +msgid "Associating to {what}" +msgstr "Collegamento con {what} in corso..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:125 +#: voice.py:108 #, python-brace-format -msgid "" -"Yo\n" -"{what}!" -msgstr "" -"Yo\n" -"{what}!" +msgid "Yo {what}!" +msgstr "Yo {what}!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:130 +#: voice.py:112 #, python-brace-format -msgid "" -"Just decided that\n" -"{mac}\n" -"needs no WiFi!" -msgstr "" -"Ho appena deciso che\n" -"{mac}\n" -"non necessita di\n" -"WiFi!" +msgid "Just decided that {mac} needs no WiFi!" +msgstr "Ho appena deciso che {mac} non necessita di WiFi!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:131 +#: voice.py:113 #, python-brace-format -msgid "" -"Deauthenticating\n" -"{mac}" +msgid "Deauthenticating {mac}" msgstr "" -"Dissociarci da\n" -"{mac}" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:132 +#: voice.py:114 #, python-brace-format -msgid "" -"Kickbanning\n" -"{mac}!" -msgstr "" -"Sto prendendo\n" -"a calci\n" -"{mac}!" +msgid "Kickbanning {mac}!" +msgstr "Sto prendendo a calci {mac}!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:137 +#: voice.py:118 #, python-brace-format -msgid "" -"Cool, we got {num}\n" -"new handshake{plural}!" -msgstr "" -"Bene, abbiamo {num}\n" -"nuovi handshake{plural}!" +msgid "Cool, we got {num} new handshake{plural}!" +msgstr "Bene, abbiamo {num} handshake{plural} in più!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:141 -msgid "" -"Ops, something\n" -"went wrong ...\n" -"Rebooting ..." -msgstr "" -"Ops, qualcosa\n" -"è andato storto ...\n" -"Riavvio ..." +#: voice.py:121 +msgid "Ops, something went wrong ... Rebooting ..." +msgstr "Ops, qualcosa è andato storto ... Riavvio ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:145 +#: voice.py:124 #, python-brace-format msgid "Kicked {num} stations\n" -msgstr "Calciate {num} stazioni\n" +msgstr "{num} stazioni pestate\n" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:146 +#: voice.py:125 #, python-brace-format msgid "Made {num} new friends\n" -msgstr "Fatti {num} nuovi amici\n" +msgstr "{num} nuovi amici\n" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:147 +#: voice.py:126 #, python-brace-format msgid "Got {num} handshakes\n" -msgstr "Presi {num} handshakes\n" +msgstr "{num} handshakes presi\n" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:149 +#: voice.py:128 msgid "Met 1 peer" -msgstr "Incontrato 1 peer" +msgstr "1 peer incontrato" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:151 +#: voice.py:130 #, python-brace-format msgid "Met {num} peers" -msgstr "Incontrati {num} peers" +msgstr "{num} peers incontrati" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:156 +#: voice.py:135 #, python-brace-format msgid "" "I've been pwning for {duration} and kicked {deauthed} clients! I've also met " "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "#pwnlog #pwnlife #hacktheplanet #skynet" msgstr "" -"Ho lavorato per {duration} e preso a calci i clienti di {deauthed}! Ho anche " -"incontrato{associate} nuovi amici e ho mangiato {handshakes} handshakes! " -"#pwnagotchi#pwnlog #pwnlife #hacktheplanet #skynet" +"Ho lavorato per {duration} e preso a calci {deauthed} clients! Ho anche " +"incontrato {associate} nuovi amici e ho mangiato {handshakes} handshakes! " +"#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.mo new file mode 100644 index 00000000..8a736612 Binary files /dev/null and b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.mo differ diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.po new file mode 100644 index 00000000..f2fe8fc9 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.po @@ -0,0 +1,247 @@ +# pwnigotchi voice data +# Copyright (C) 2019 +# This file is distributed under the same license as the pwnagotchi package. +# FIRST AUTHOR <33197631+dadav@users.noreply.github.com>, 2019. +# kovach <2214005+kovachwt@users.noreply.github.com>, 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-10-03 12:44+0200\n" +"PO-Revision-Date: 2019-09-30 23:53+0200\n" +"Last-Translator: kovach <2214005+kovachwt@users.noreply.github.com>\n" +"Language-Team: \n" +"Language: mk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: voice.py:18 +msgid "ZzzzZZzzzzZzzz" +msgstr "ДреееММмммМммм" + +#: voice.py:22 +#, fuzzy +msgid "Hi, I'm Pwnagotchi! Starting ..." +msgstr "Здраво, јас сум Pwnagotchi!Почнувам ..." + +#: voice.py:23 +#, fuzzy +msgid "New day, new hunt, new pwns!" +msgstr "Нов ден, нов лов,ќе си газиме!" + +#: voice.py:24 +msgid "Hack the Planet!" +msgstr "Хак д Планет!" + +#: voice.py:28 +msgid "AI ready." +msgstr "AI спремно." + +#: voice.py:29 +#, fuzzy +msgid "The neural network is ready." +msgstr "Невронската мрежае спремна." + +#: voice.py:37 +#, fuzzy, python-brace-format +msgid "Hey, channel {channel} is free! Your AP will say thanks." +msgstr "Еј, каналот {channel} еслободен! APто ќе тикаже фала." + +#: voice.py:41 +msgid "I'm bored ..." +msgstr "Досаднооо ..." + +#: voice.py:42 +msgid "Let's go for a walk!" +msgstr "Ајде да шетнеме!" + +#: voice.py:45 +#, fuzzy +msgid "This is the best day of my life!" +msgstr "Ова ми е најдобриот ден во животот!" + +#: voice.py:48 +msgid "Shitty day :/" +msgstr "Срање ден :/" + +#: voice.py:52 +msgid "I'm extremely bored ..." +msgstr "Ултра досадно ..." + +#: voice.py:53 +msgid "I'm very sad ..." +msgstr "Многу тажно ..." + +#: voice.py:54 +msgid "I'm sad" +msgstr "Тажно" + +#: voice.py:59 +msgid "I'm living the life!" +msgstr "Ммхх животче!" + +#: voice.py:60 +msgid "I pwn therefore I am." +msgstr "Си газам значи постојам." + +#: voice.py:61 +msgid "So many networks!!!" +msgstr "Мммм колку мрежи!!!" + +#: voice.py:62 +#, fuzzy +msgid "I'm having so much fun!" +msgstr "Јухуу забавноо ее!" + +#: voice.py:63 +#, fuzzy +msgid "My crime is that of curiosity ..." +msgstr "Виновен сум само заљубопитност ..." + +#: voice.py:67 +#, fuzzy, python-brace-format +msgid "Hello {name}! Nice to meet you. {name}" +msgstr "Здраво{name}!Мило ми е. {name}" + +#: voice.py:68 +#, fuzzy, python-brace-format +msgid "Unit {name} is nearby! {name}" +msgstr "Опаа{name}е во близина! {name}" + +#: voice.py:72 +#, fuzzy, python-brace-format +msgid "Uhm ... goodbye {name}" +msgstr "Хмм ...чао{name}" + +#: voice.py:73 +#, fuzzy, python-brace-format +msgid "{name} is gone ..." +msgstr "{name}го снема ..." + +#: voice.py:77 +#, fuzzy, python-brace-format +msgid "Whoops ... {name} is gone." +msgstr "Уупс ...{name}го снема." + +#: voice.py:78 +#, fuzzy, python-brace-format +msgid "{name} missed!" +msgstr "{name}промаши!" + +#: voice.py:79 +msgid "Missed!" +msgstr "Промаши!" + +#: voice.py:83 +#, fuzzy +msgid "Nobody wants to play with me ..." +msgstr "Никој не сака даси игра со мене ..." + +#: voice.py:84 +msgid "I feel so alone ..." +msgstr "Толку сам ..." + +#: voice.py:85 +msgid "Where's everybody?!" +msgstr "Каде се сите?!" + +#: voice.py:89 +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "Ќе дремнам {secs}с ..." + +#: voice.py:90 +msgid "Zzzzz" +msgstr "Дреммм" + +#: voice.py:91 +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "Дремммм ({secs}с)" + +#: voice.py:98 +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "Чекам {secs}с ..." + +#: voice.py:100 +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "Шарам наоколу ({secs}с)" + +#: voice.py:106 +#, fuzzy, python-brace-format +msgid "Hey {what} let's be friends!" +msgstr "Еј{what}ајде да се дружиме!" + +#: voice.py:107 +#, fuzzy, python-brace-format +msgid "Associating to {what}" +msgstr "Се закачувам на{what}" + +#: voice.py:108 +#, fuzzy, python-brace-format +msgid "Yo {what}!" +msgstr "Јо{what}!" + +#: voice.py:112 +#, fuzzy, python-brace-format +msgid "Just decided that {mac} needs no WiFi!" +msgstr "Знаеш што, на{mac}не му треба WiFi!" + +#: voice.py:113 +#, fuzzy, python-brace-format +msgid "Deauthenticating {mac}" +msgstr "Го деавтентицирам{mac}" + +#: voice.py:114 +#, fuzzy, python-brace-format +msgid "Kickbanning {mac}!" +msgstr "Кикбан{mac}!" + +#: voice.py:118 +#, fuzzy, python-brace-format +msgid "Cool, we got {num} new handshake{plural}!" +msgstr "Кул, фативме {num}нови ракувања!" + +#: voice.py:121 +#, fuzzy +msgid "Ops, something went wrong ... Rebooting ..." +msgstr "Упс, нешто не еко што треба ...Рестартирам ..." + +#: voice.py:124 +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "Избацив {num} станици\n" + +#: voice.py:125 +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "{num} нови другарчиња\n" + +#: voice.py:126 +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "Фатив {num} ракувања\n" + +#: voice.py:128 +msgid "Met 1 peer" +msgstr "Запознав 1 пријател" + +#: voice.py:130 +#, python-brace-format +msgid "Met {num} peers" +msgstr "Запознав {num} пријатели" + +#: voice.py:135 +#, python-brace-format +msgid "" +"I've been pwning for {duration} and kicked {deauthed} clients! I've also met " +"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" +msgstr "" +"Си газам веќе {duration} и избацив {deauthed} клиенти! Запознав {associated} " +"нови другарчиња и лапнав {handshakes} ракувања! #pwnagotchi #pwnlog #pwnlife " +"#hacktheplanet #skynet" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo index 5c0ae61c..b4db7471 100644 Binary files a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo and b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo differ diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.po index 1f6e8325..ce55a631 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.po +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.po @@ -3,43 +3,32 @@ # This file is distributed under the same license as the pwnagotchi package. # FIRST AUTHOR justin-p@users.noreply.github.com, 2019. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-29 13:42+0200\n" +"POT-Creation-Date: 2019-10-03 12:44+0200\n" "PO-Revision-Date: 2019-09-29 14:00+0200\n" "Last-Translator: Justin-P \n" "Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" -"Language: english\n" +"Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: voice.py:16 +#: voice.py:18 msgid "ZzzzZZzzzzZzzz" msgstr "ZzzzZZzzzzZzzz" -#: voice.py:21 -msgid "" -"Hi, I'm Pwnagotchi!\n" -"Starting ..." -msgstr "" -"Hoi, Ik ben\n" -"Pwnagotchi!\n" -"Opstarten ..." - #: voice.py:22 -msgid "" -"New day, new hunt,\n" -"new pwns!" -msgstr "" -"Nieuwe dag,\n" -"nieuwe jacht,\n" -"nieuwe pwns!" +msgid "Hi, I'm Pwnagotchi! Starting ..." +msgstr "Hoi, Ik ben Pwnagotchi! Opstarten ..." #: voice.py:23 +msgid "New day, new hunt, new pwns!" +msgstr "Nieuwe dag, nieuwe jacht, nieuwe pwns!" + +#: voice.py:24 msgid "Hack the Planet!" msgstr "Hack de Wereld!" @@ -48,301 +37,203 @@ msgid "AI ready." msgstr "AI is klaar." #: voice.py:29 -msgid "" -"The neural network\n" -"is ready." -msgstr "" -"Neuronen netwerk\n" -"is klaar voor gebruik." +msgid "The neural network is ready." +msgstr "Neuronen netwerkis klaar voor gebruik." -#: voice.py:39 +#: voice.py:37 #, python-brace-format -msgid "" -"Hey, channel {channel} is\n" -"free! Your AP will\n" -"say thanks." -msgstr "" -"Hey, kanaal {channel} is\n" -"vrij! Je AP zal je\n" -"bedanken." +msgid "Hey, channel {channel} is free! Your AP will say thanks." +msgstr "Hey, kanaal {channel} is vrij! Je AP zal je bedanken." -#: voice.py:44 +#: voice.py:41 msgid "I'm bored ..." msgstr "Ik verveel me ..." -#: voice.py:45 +#: voice.py:42 msgid "Let's go for a walk!" msgstr "Laten we een rondje lopen!" -#: voice.py:49 -msgid "" -"This is the best\n" -"day of my life!" -msgstr "" -"Dit is de beste\n" -"dag van mijn leven!" +#: voice.py:45 +msgid "This is the best day of my life!" +msgstr "Dit is de beste dag van mijn leven!" -#: voice.py:53 +#: voice.py:48 msgid "Shitty day :/" msgstr "Ruk dag :/" -#: voice.py:58 +#: voice.py:52 msgid "I'm extremely bored ..." -msgstr "Ik verveel me \n" -"kapot ..." +msgstr "Ik verveel me kapot ..." -#: voice.py:59 +#: voice.py:53 msgid "I'm very sad ..." -msgstr "Ik ben erg\n" -"verdrietig ..." +msgstr "Ik ben ergverdrietig ..." -#: voice.py:60 +#: voice.py:54 msgid "I'm sad" msgstr "Ik ben verdrietig" -#: voice.py:66 +#: voice.py:59 msgid "I'm living the life!" -msgstr "Beter kan het leven\n" -"niet worden!" +msgstr "Beter kan het levenniet worden!" -#: voice.py:67 +#: voice.py:60 msgid "I pwn therefore I am." msgstr "Ik pwn daarom besta ik." -#: voice.py:68 +#: voice.py:61 msgid "So many networks!!!" msgstr "Zo veel netwerken!!!" -#: voice.py:69 -msgid "" -"I'm having so much\n" -"fun!" +#: voice.py:62 +msgid "I'm having so much fun!" msgstr "Dit is zo leuk!" -#: voice.py:70 -msgid "" -"My crime is that of\n" -"curiosity ..." -msgstr "" -"Mijn enige misdrijf\n" -"is mijn \n" -"nieuwsgierigheid ..." +#: voice.py:63 +#, fuzzy +msgid "My crime is that of curiosity ..." +msgstr "Mijn enige misdrijfis mijn nieuwsgierigheid ..." -#: voice.py:75 +#: voice.py:67 #, python-brace-format -msgid "" -"Hello\n" -"{name}!\n" -"Nice to meet you. {name}" -msgstr "" -"Hallo\n" -"{name}!\n" -"Leuk je te ontmoeten. {name}" +msgid "Hello {name}! Nice to meet you. {name}" +msgstr "Hallo {name}! Leuk je te ontmoeten. {name}" -#: voice.py:76 +#: voice.py:68 #, python-brace-format -msgid "" -"Unit\n" -"{name}\n" -"is nearby! {name}" -msgstr "" -"Unit\n" -"{name}\n" -"is dichtbij! {name}" +msgid "Unit {name} is nearby! {name}" +msgstr "Unit {name} is dichtbij! {name}" -#: voice.py:81 +#: voice.py:72 #, python-brace-format -msgid "" -"Uhm ...\n" -"goodbye\n" -"{name}" -msgstr "" -"Uhm ...\n" -"tot ziens\n" -"{name}" +msgid "Uhm ... goodbye {name}" +msgstr "Uhm ...tot ziens {name}" -#: voice.py:82 +#: voice.py:73 #, python-brace-format -msgid "" -"{name}\n" -"is gone ..." -msgstr "" -"{name}\n" -"is weg" +msgid "{name} is gone ..." +msgstr "{name} is weg" -#: voice.py:87 +#: voice.py:77 #, python-brace-format -msgid "" -"Whoops ...\n" -"{name}\n" -"is gone." -msgstr "" -"Whoopsie ...\n" -"{name}\n" -"is weg" +msgid "Whoops ... {name} is gone." +msgstr "Whoopsie ...{name} is weg" -#: voice.py:88 +#: voice.py:78 #, python-brace-format -msgid "" -"{name}\n" -"missed!" -msgstr "" -"{name}\n" -"gemist!" +msgid "{name} missed!" +msgstr "{name} gemist!" -#: voice.py:89 +#: voice.py:79 msgid "Missed!" msgstr "Gemist!" -#: voice.py:94 -msgid "" -"Nobody wants to\n" -"play with me ..." -msgstr "" -"Niemand wil met\n" -"mij spelen ..." +#: voice.py:83 +msgid "Nobody wants to play with me ..." +msgstr "Niemand wil metmij spelen ..." -#: voice.py:95 +#: voice.py:84 msgid "I feel so alone ..." msgstr "Zo alleen ..." -#: voice.py:96 +#: voice.py:85 msgid "Where's everybody?!" msgstr "Waar is iedereen?!" -#: voice.py:101 +#: voice.py:89 #, python-brace-format msgid "Napping for {secs}s ..." msgstr "Dutje doen voor {secs}s ..." -#: voice.py:102 +#: voice.py:90 msgid "Zzzzz" msgstr "Zzzzz" -#: voice.py:103 +#: voice.py:91 #, python-brace-format msgid "ZzzZzzz ({secs}s)" msgstr "" -#: voice.py:112 +#: voice.py:98 #, python-brace-format msgid "Waiting for {secs}s ..." msgstr "Even {secs}s wachten ..." -#: voice.py:114 +#: voice.py:100 #, python-brace-format msgid "Looking around ({secs}s)" msgstr "Rond kijken ({secs}s)" +#: voice.py:106 +#, python-brace-format +msgid "Hey {what} let's be friends!" +msgstr "Hey {what}, laten we vriendenworden!" + +#: voice.py:107 +#, python-brace-format +msgid "Associating to {what}" +msgstr "Verbinden met {what}" + +#: voice.py:108 +#, python-brace-format +msgid "Yo {what}!" +msgstr "" + +#: voice.py:112 +#, python-brace-format +msgid "Just decided that {mac} needs no WiFi!" +msgstr "Ik vind dat {mac} genoeg WiFiheeft gehad!" + +#: voice.py:113 +#, python-brace-format +msgid "Deauthenticating {mac}" +msgstr "De-autoriseren {mac}" + +#: voice.py:114 +#, python-brace-format +msgid "Kickbanning {mac}!" +msgstr "Ik ga {mac} even kicken!" + +#: voice.py:118 +#, python-brace-format +msgid "Cool, we got {num} new handshake{plural}!" +msgstr "Gaaf, we hebben {num} nieuwe handshake{plural}!" + #: voice.py:121 -#, python-brace-format -msgid "" -"Hey\n" -"{what}\n" -"let's be friends!" -msgstr "" -"Hey\n" -"{what}\n" -"Laten we vrienden\n" -"worden!" +msgid "Ops, something went wrong ... Rebooting ..." +msgstr "Oops, iets ging fout ...Rebooting ..." -#: voice.py:122 -#, python-brace-format -msgid "" -"Associating to\n" -"{what}" -msgstr "" -"Verbinden met\n" -"{what}" - -#: voice.py:123 -#, python-brace-format -msgid "" -"Yo\n" -"{what}!" -msgstr "" - - -#: voice.py:128 -#, python-brace-format -msgid "" -"Just decided that\n" -"{mac}\n" -"needs no WiFi!" -msgstr "Ik vind dat\n" -"{mac}\n" -"genoeg WiFi\n" -"heeft gehad!" - -#: voice.py:129 -#, python-brace-format -msgid "" -"Deauthenticating\n" -"{mac}" -msgstr "" -"De-autoriseren\n" -"{mac}" - -#: voice.py:130 -#, python-brace-format -msgid "" -"Kickbanning\n" -"{mac}!" -msgstr "" -"Ik ga\n" -"{mac}\n" -"even kicken!" - -#: voice.py:135 -#, python-brace-format -msgid "" -"Cool, we got {num}\n" -"new handshake{plural}!" -msgstr "" -"Gaaf, we hebben {num}\n" -"nieuwe handshake{plural}!" - -#: voice.py:139 -msgid "" -"Ops, something\n" -"went wrong ...\n" -"Rebooting ..." -msgstr "" -"Oops, iets" -"ging fout ...\n" -"Rebooting ..." - -#: voice.py:143 +#: voice.py:124 #, python-brace-format msgid "Kicked {num} stations\n" msgstr "{num} stations gekicked\n" -#: voice.py:144 +#: voice.py:125 #, python-brace-format msgid "Made {num} new friends\n" msgstr "{num} nieuwe vrienden\n" -#: voice.py:145 +#: voice.py:126 #, python-brace-format msgid "Got {num} handshakes\n" msgstr "{num} nieuwe handshakes\n" -#: voice.py:147 +#: voice.py:128 msgid "Met 1 peer" msgstr "1 peer ontmoet" -#: voice.py:149 +#: voice.py:130 #, python-brace-format msgid "Met {num} peers" msgstr "{num} peers ontmoet" -#: voice.py:154 +#: voice.py:135 #, python-brace-format msgid "" "I've been pwning for {duration} and kicked {deauthed} clients! I've also met " "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "#pwnlog #pwnlife #hacktheplanet #skynet" msgstr "" -"Ik heb gepwned voor {duration} and heb {deauthed} clients gekicked! Ik heb ook " -"{associated} nieuwe vrienden gevonden en heb {handshakes} handshakes gegeten! " -"#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" \ No newline at end of file +"Ik heb gepwned voor {duration} and heb {deauthed} clients gekicked! Ik heb " +"ook {associated} nieuwe vrienden gevonden en heb {handshakes} handshakes " +"gegeten! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot index 671e44dc..53f3557a 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot @@ -1,39 +1,35 @@ -# pwnigotchi voice data -# Copyright (C) 2019 -# This file is distributed under the same license as the pwnagotchi package. -# FIRST AUTHOR <33197631+dadav@users.noreply.github.com>, 2019. +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: 0.0.1\n" +"Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-29 13:42+0200\n" -"PO-Revision-Date: 2019-09-29 14:00+0200\n" -"Last-Translator: dadav <33197631+dadav@users.noreply.github.com>\n" -"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" -"Language: english\n" +"POT-Creation-Date: 2019-10-03 13:10+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" +"Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: voice.py:16 +#: voice.py:18 msgid "ZzzzZZzzzzZzzz" msgstr "" -#: voice.py:21 -msgid "" -"Hi, I'm Pwnagotchi!\n" -"Starting ..." -msgstr "" - #: voice.py:22 -msgid "" -"New day, new hunt,\n" -"new pwns!" +msgid "Hi, I'm Pwnagotchi! Starting ..." msgstr "" #: voice.py:23 +msgid "New day, new hunt, new pwns!" +msgstr "" + +#: voice.py:24 msgid "Hack the Planet!" msgstr "" @@ -42,244 +38,196 @@ msgid "AI ready." msgstr "" #: voice.py:29 -msgid "" -"The neural network\n" -"is ready." +msgid "The neural network is ready." msgstr "" -#: voice.py:39 +#: voice.py:37 #, python-brace-format -msgid "" -"Hey, channel {channel} is\n" -"free! Your AP will\n" -"say thanks." +msgid "Hey, channel {channel} is free! Your AP will say thanks." msgstr "" -#: voice.py:44 +#: voice.py:41 msgid "I'm bored ..." msgstr "" -#: voice.py:45 +#: voice.py:42 msgid "Let's go for a walk!" msgstr "" -#: voice.py:49 -msgid "" -"This is the best\n" -"day of my life!" +#: voice.py:45 +msgid "This is the best day of my life!" msgstr "" -#: voice.py:53 +#: voice.py:48 msgid "Shitty day :/" msgstr "" -#: voice.py:58 +#: voice.py:52 msgid "I'm extremely bored ..." msgstr "" -#: voice.py:59 +#: voice.py:53 msgid "I'm very sad ..." msgstr "" -#: voice.py:60 +#: voice.py:54 msgid "I'm sad" msgstr "" -#: voice.py:66 +#: voice.py:59 msgid "I'm living the life!" msgstr "" -#: voice.py:67 +#: voice.py:60 msgid "I pwn therefore I am." msgstr "" -#: voice.py:68 +#: voice.py:61 msgid "So many networks!!!" msgstr "" -#: voice.py:69 -msgid "" -"I'm having so much\n" -"fun!" +#: voice.py:62 +msgid "I'm having so much fun!" msgstr "" -#: voice.py:70 -msgid "" -"My crime is that of\n" -"curiosity ..." +#: voice.py:63 +msgid "My crime is that of curiosity ..." msgstr "" -#: voice.py:75 +#: voice.py:67 #, python-brace-format -msgid "" -"Hello\n" -"{name}!\n" -"Nice to meet you. {name}" +msgid "Hello {name}! Nice to meet you. {name}" msgstr "" -#: voice.py:76 +#: voice.py:68 #, python-brace-format -msgid "" -"Unit\n" -"{name}\n" -"is nearby! {name}" +msgid "Unit {name} is nearby! {name}" msgstr "" -#: voice.py:81 +#: voice.py:72 #, python-brace-format -msgid "" -"Uhm ...\n" -"goodbye\n" -"{name}" +msgid "Uhm ... goodbye {name}" msgstr "" -#: voice.py:82 +#: voice.py:73 #, python-brace-format -msgid "" -"{name}\n" -"is gone ..." +msgid "{name} is gone ..." msgstr "" -#: voice.py:87 +#: voice.py:77 #, python-brace-format -msgid "" -"Whoops ...\n" -"{name}\n" -"is gone." +msgid "Whoops ... {name} is gone." msgstr "" -#: voice.py:88 +#: voice.py:78 #, python-brace-format -msgid "" -"{name}\n" -"missed!" +msgid "{name} missed!" msgstr "" -#: voice.py:89 +#: voice.py:79 msgid "Missed!" msgstr "" -#: voice.py:94 -msgid "" -"Nobody wants to\n" -"play with me ..." +#: voice.py:83 +msgid "Nobody wants to play with me ..." msgstr "" -#: voice.py:95 +#: voice.py:84 msgid "I feel so alone ..." msgstr "" -#: voice.py:96 +#: voice.py:85 msgid "Where's everybody?!" msgstr "" -#: voice.py:101 +#: voice.py:89 #, python-brace-format msgid "Napping for {secs}s ..." msgstr "" -#: voice.py:102 +#: voice.py:90 msgid "Zzzzz" msgstr "" -#: voice.py:103 +#: voice.py:91 #, python-brace-format msgid "ZzzZzzz ({secs}s)" msgstr "" -#: voice.py:112 +#: voice.py:98 #, python-brace-format msgid "Waiting for {secs}s ..." msgstr "" -#: voice.py:114 +#: voice.py:100 #, python-brace-format msgid "Looking around ({secs}s)" msgstr "" +#: voice.py:106 +#, python-brace-format +msgid "Hey {what} let's be friends!" +msgstr "" + +#: voice.py:107 +#, python-brace-format +msgid "Associating to {what}" +msgstr "" + +#: voice.py:108 +#, python-brace-format +msgid "Yo {what}!" +msgstr "" + +#: voice.py:112 +#, python-brace-format +msgid "Just decided that {mac} needs no WiFi!" +msgstr "" + +#: voice.py:113 +#, python-brace-format +msgid "Deauthenticating {mac}" +msgstr "" + +#: voice.py:114 +#, python-brace-format +msgid "Kickbanning {mac}!" +msgstr "" + +#: voice.py:118 +#, python-brace-format +msgid "Cool, we got {num} new handshake{plural}!" +msgstr "" + #: voice.py:121 -#, python-brace-format -msgid "" -"Hey\n" -"{what}\n" -"let's be friends!" +msgid "Ops, something went wrong ... Rebooting ..." msgstr "" -#: voice.py:122 -#, python-brace-format -msgid "" -"Associating to\n" -"{what}" -msgstr "" - -#: voice.py:123 -#, python-brace-format -msgid "" -"Yo\n" -"{what}!" -msgstr "" - -#: voice.py:128 -#, python-brace-format -msgid "" -"Just decided that\n" -"{mac}\n" -"needs no WiFi!" -msgstr "" - -#: voice.py:129 -#, python-brace-format -msgid "" -"Deauthenticating\n" -"{mac}" -msgstr "" - -#: voice.py:130 -#, python-brace-format -msgid "" -"Kickbanning\n" -"{mac}!" -msgstr "" - -#: voice.py:135 -#, python-brace-format -msgid "" -"Cool, we got {num}\n" -"new handshake{plural}!" -msgstr "" - -#: voice.py:139 -msgid "" -"Ops, something\n" -"went wrong ...\n" -"Rebooting ..." -msgstr "" - -#: voice.py:143 +#: voice.py:124 #, python-brace-format msgid "Kicked {num} stations\n" msgstr "" -#: voice.py:144 +#: voice.py:125 #, python-brace-format msgid "Made {num} new friends\n" msgstr "" -#: voice.py:145 +#: voice.py:126 #, python-brace-format msgid "Got {num} handshakes\n" msgstr "" -#: voice.py:147 +#: voice.py:128 msgid "Met 1 peer" msgstr "" -#: voice.py:149 +#: voice.py:130 #, python-brace-format msgid "Met {num} peers" msgstr "" -#: voice.py:154 +#: voice.py:135 #, python-brace-format msgid "" "I've been pwning for {duration} and kicked {deauthed} clients! I've also met " diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py index d66008de..edf66ede 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py @@ -160,6 +160,9 @@ class SessionParser(object): break lines.reverse() + if len(lines) == 0: + lines.append("Initial Session"); + self.last_session = lines self.last_session_id = hashlib.md5(lines[0].encode()).hexdigest() self.last_saved_session_id = self._get_last_saved_session_id() diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py index c99cd578..8c84b942 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py @@ -1,7 +1,7 @@ import _thread import core -import pwnagotchi +import pwnagotchi, pwnagotchi.plugins as plugins from pwnagotchi.mesh import get_identity @@ -37,6 +37,8 @@ class AsyncAdvertiser(object): def _on_new_unit(self, peer): self._view.on_new_peer(peer) + plugins.on('peer_detected', self, peer) def _on_lost_unit(self, peer): self._view.on_lost_peer(peer) + plugins.on('peer_lost', self, peer) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py new file mode 100644 index 00000000..bcb89f8e --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py @@ -0,0 +1,43 @@ +import os +import glob +import importlib, importlib.util + +default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default") +loaded = {} + + +def dummy_callback(): + pass + + +def on(event_name, *args, **kwargs): + global loaded + cb_name = 'on_%s' % event_name + for _, plugin in loaded.items(): + if cb_name in plugin.__dict__: + # print("calling %s %s(%s)" %(cb_name, args, kwargs)) + plugin.__dict__[cb_name](*args, **kwargs) + + +def load_from_file(filename): + plugin_name = os.path.basename(filename.replace(".py", "")) + spec = importlib.util.spec_from_file_location(plugin_name, filename) + instance = importlib.util.module_from_spec(spec) + spec.loader.exec_module(instance) + return plugin_name, instance + + +def load_from_path(path): + global loaded + + for filename in glob.glob(os.path.join(path, "*.py")): + name, plugin = load_from_file(filename) + if name in loaded: + raise Exception("plugin %s already loaded from %s" % (name, plugin.__file__)) + elif not plugin.__enabled__: + # print("plugin %s is not enabled" % name) + pass + else: + loaded[name] = plugin + + return loaded diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py new file mode 100644 index 00000000..4a63275e --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py @@ -0,0 +1,162 @@ +__author__ = 'evilsocket@gmail.com' +__version__ = '1.0.0' +__name__ = 'hello_world' +__license__ = 'GPL3' +__description__ = 'An example plugin for pwnagotchi that implements all the available callbacks.' +__enabled__ = False # IMPORTANT: set this to True to enable your plugin. + +from pwnagotchi.ui.components import LabeledValue +from pwnagotchi.ui.view import BLACK +import pwnagotchi.ui.fonts as fonts +import core + + +# called when the plugin is loaded +def on_loaded(): + core.log("WARNING: plugin %s should be disabled!" % __name__) + + +# called to setup the ui elements +def on_ui_setup(ui): + # add custom UI elements + ui.add_element('ups', LabeledValue(color=BLACK, label='UPS', value='0%/0V', position=(ui.width() / 2 - 25, 0), + label_font=fonts.Bold, text_font=fonts.Medium)) + + +# called when the ui is updated +def on_ui_update(ui): + # update those elements + some_voltage = 0.1 + some_capacity = 100.0 + + ui.set('ups', "%4.2fV/%2i%%" % (some_voltage, some_capacity)) + + +# called when the hardware display setup is done, display is an hardware specific object +def on_display_setup(display): + pass + + +# called when everything is ready and the main loop is about to start +def on_ready(agent): + core.log("unit is ready") + # you can run custom bettercap commands if you want + # agent.run('ble.recon on') + # or set a custom state + # agent.set_bored() + + +# called when the AI finished loading +def on_ai_ready(agent): + pass + + +# called when the AI finds a new set of parameters +def on_ai_policy(agent, policy): + pass + + +# called when the AI starts training for a given number of epochs +def on_ai_training_start(agent, epochs): + pass + + +# called after the AI completed a training epoch +def on_ai_training_step(agent, _locals, _globals): + pass + + +# called when the AI has done training +def on_ai_training_end(agent): + pass + + +# called when the AI got the best reward so far +def on_ai_best_reward(agent, reward): + pass + + +# called when the AI got the best reward so far +def on_ai_worst_reward(agent, reward): + pass + + +# called when a non overlapping wifi channel is found to be free +def on_free_channel(agent, channel): + pass + + +# called when the status is set to bored +def on_bored(agent): + pass + + +# called when the status is set to sad +def on_sad(agent): + pass + + +# called when the status is set to excited +def on_excited(agent): + pass + + +# called when the status is set to lonely +def on_lonely(agent): + pass + + +# called when the agent is rebooting the board +def on_rebooting(agent): + pass + + +# called when the agent is waiting for t seconds +def on_wait(agent, t): + pass + + +# called when the agent is sleeping for t seconds +def on_sleep(agent, t): + pass + + +# called when the agent refreshed its access points list +def on_wifi_update(agent, access_points): + pass + + +# called when the agent is sending an association frame +def on_association(agent, access_point): + pass + + +# callend when the agent is deauthenticating a client station from an AP +def on_deauthentication(agent, access_point, client_station): + pass + + +# callend when the agent is tuning on a specific channel +def on_channel_hop(agent, channel): + pass + + +# called when a new handshake is captured, access_point and client_station are json objects +# if the agent could match the BSSIDs to the current list, otherwise they are just the strings of the BSSIDs +def on_handshake(agent, filename, access_point, client_station): + pass + + +# called when an epoch is over (where an epoch is a single loop of the main algorithm) +def on_epoch(agent, epoch, epoch_data): + pass + + +# called when a new peer is detected +def on_peer_detected(agent, peer): + pass + + +# called when a known peer is lost +def on_peer_lost(agent, peer): + pass diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py new file mode 100644 index 00000000..c3c53a98 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py @@ -0,0 +1,47 @@ +__author__ = 'evilsocket@gmail.com' +__version__ = '1.0.0' +__name__ = 'gps' +__license__ = 'GPL3' +__description__ = 'Save GPS coordinates whenever an handshake is captured.' +__enabled__ = True # set to false if you just don't use GPS + +import core +import json +import os + +device = '/dev/ttyUSB0' +speed = 19200 +running = False + + +def on_loaded(): + core.log("GPS plugin loaded for %s" % device) + + +def on_ready(agent): + global running + + if os.path.exists(device): + core.log("enabling GPS bettercap's module for %s" % device) + try: + agent.run('gps off') + except: + pass + + agent.run('set gps.device %s' % device) + agent.run('set gps.speed %d' % speed) + agent.run('gps on') + running = True + else: + core.log("no GPS detected") + + +def on_handshake(agent, filename, access_point, client_station): + if running: + info = agent.session() + gps = info['gps'] + gps_filename = filename.replace('.pcap', '.gps.json') + + core.log("saving GPS to %s (%s)" % (gps_filename, gps)) + with open(gps_filename, 'w+t') as fp: + json.dump(gps, fp) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/ups_lite.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/ups_lite.py new file mode 100644 index 00000000..7ddcecdd --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/ups_lite.py @@ -0,0 +1,65 @@ +# Based on UPS Lite v1.1 from https://github.com/xenDE +# +# funtions for get UPS status - needs enable "i2c" in raspi-config +# +# https://github.com/linshuqin329/UPS-Lite +# +# For Raspberry Pi Zero Ups Power Expansion Board with Integrated Serial Port S3U4 +# https://www.ebay.de/itm/For-Raspberry-Pi-Zero-Ups-Power-Expansion-Board-with-Integrated-Serial-Port-S3U4/323873804310 +# https://www.aliexpress.com/item/32888533624.html +__author__ = 'evilsocket@gmail.com' +__version__ = '1.0.0' +__name__ = 'ups_lite' +__license__ = 'GPL3' +__description__ = 'A plugin that will add a voltage indicator for the UPS Lite v1.1' +__enabled__ = False + +import struct + +from pwnagotchi.ui.components import LabeledValue +from pwnagotchi.ui.view import BLACK +import pwnagotchi.ui.fonts as fonts + + +# TODO: add enable switch in config.yml an cleanup all to the best place +class UPS: + def __init__(self): + # only import when the module is loaded and enabled + import smbus + # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1) + self._bus = smbus.SMBus(1) + + def voltage(self): + try: + address = 0x36 + read = self._bus.read_word_data(address, 2) + swapped = struct.unpack("H", read))[0] + return swapped * 1.25 / 1000 / 16 + except: + return 0.0 + + def capacity(self): + try: + address = 0x36 + read = self._bus.read_word_data(address, 4) + swapped = struct.unpack("H", read))[0] + return swapped / 256 + except: + return 0.0 + + +ups = None + + +def on_loaded(): + global ups + ups = UPS() + + +def on_ui_setup(ui): + ui.add_element('ups', LabeledValue(color=BLACK, label='UPS', value='0%/0V', position=(ui.width() / 2 - 25, 0), + label_font=fonts.Bold, text_font=fonts.Medium)) + + +def on_ui_update(ui): + ui.set('ups', "%4.2fV/%2i%%" % (ups.voltage(), ups.capacity())) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/components.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/components.py index 2d8b2f57..87b05765 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/components.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/components.py @@ -1,4 +1,5 @@ from PIL import Image +from textwrap import TextWrapper class Widget(object): @@ -39,14 +40,21 @@ class FilledRect(Widget): class Text(Widget): - def __init__(self, value="", position=(0, 0), font=None, color=0): + def __init__(self, value="", position=(0, 0), font=None, color=0, wrap=False, max_length=0): super().__init__(position, color) self.value = value self.font = font + self.wrap = wrap + self.max_length = max_length + self.wrapper = TextWrapper(width=self.max_length, replace_whitespace=False) if wrap else None def draw(self, canvas, drawer): if self.value is not None: - drawer.text(self.xy, self.value, font=self.font, fill=self.color) + if self.wrap: + text = '\n'.join(self.wrapper.wrap(self.value)) + else: + text = self.value + drawer.text(self.xy, text, font=self.font, fill=self.color) class LabeledValue(Widget): diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py index 66f2e36a..d6e00d14 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py @@ -5,7 +5,7 @@ from PIL import Image import shutil import core import os -import pwnagotchi +import pwnagotchi, pwnagotchi.plugins as plugins from pwnagotchi.ui.view import WHITE, View @@ -156,6 +156,8 @@ class Display(View): else: core.log("unknown display type %s" % self._display_type) + plugins.on('display_setup', self._display) + self.on_render(self._on_view_rendered) def image(self): diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/faces.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/faces.py index a13eb739..1e09be17 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/faces.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/faces.py @@ -15,3 +15,4 @@ LONELY = '(ب__ب)' SAD = '(╥☁╥ )' FRIEND = '(♥‿‿♥)' BROKEN = '(☓‿‿☓)' +DEBUG = '(#__#)' diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/state.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/state.py index 71b7d4ee..0a9e37a6 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/state.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/state.py @@ -6,6 +6,11 @@ class State(object): self._state = state self._lock = Lock() self._listeners = {} + self._changes = {} + + def add_element(self, key, elem): + self._state[key] = elem + self._changes[key] = True def add_listener(self, key, cb): with self._lock: @@ -19,10 +24,29 @@ class State(object): with self._lock: return self._state[key].value if key in self._state else None + def reset(self): + with self._lock: + self._changes = {} + + def changes(self, ignore=()): + with self._lock: + changes = [] + for change in self._changes.keys(): + if change not in ignore: + changes.append(change) + return changes + + def has_changes(self): + with self._lock: + return len(self._changes) > 0 + def set(self, key, value): with self._lock: if key in self._state: prev = self._state[key].value self._state[key].value = value - if key in self._listeners and self._listeners[key] is not None and prev != value: - self._listeners[key](prev, value) + + if prev != value: + self._changes[key] = True + if key in self._listeners and self._listeners[key] is not None: + self._listeners[key](prev, value) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py index 0d76b7e1..15a7d1b2 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py @@ -4,7 +4,7 @@ import time from PIL import Image, ImageDraw import core -import pwnagotchi +import pwnagotchi.plugins as plugins from pwnagotchi.voice import Voice import pwnagotchi.ui.fonts as fonts @@ -41,7 +41,7 @@ def setup_display_specifics(config): name_pos = (int(width / 2) - 15, int(height * .15)) status_pos = (int(width / 2) - 15, int(height * .30)) - elif config['ui']['display']['type'] in ('ws_1', 'ws1', 'waveshare_1', 'waveshare1', + elif config['ui']['display']['type'] in ('ws_1', 'ws1', 'waveshare_1', 'waveshare1', 'ws_2', 'ws2', 'waveshare_2', 'waveshare2'): if config['ui']['display']['color'] == 'black': fonts.setup(10, 9, 10, 35) @@ -87,22 +87,25 @@ class View(object): label_font=fonts.Bold, text_font=fonts.Medium), - # 'square': Rect([1, 11, 124, 111]), 'line1': Line([0, int(self._height * .12), self._width, int(self._height * .12)], color=BLACK), 'line2': Line( [0, self._height - int(self._height * .12), self._width, self._height - int(self._height * .12)], color=BLACK), - # 'histogram': Histogram([4, 94], color = BLACK), - 'face': Text(value=faces.SLEEP, position=face_pos, color=BLACK, font=fonts.Huge), 'friend_face': Text(value=None, position=(0, 90), font=fonts.Bold, color=BLACK), 'friend_name': Text(value=None, position=(40, 93), font=fonts.BoldSmall, color=BLACK), 'name': Text(value='%s>' % 'pwnagotchi', position=name_pos, color=BLACK, font=fonts.Bold), - # 'face2': Bitmap( '/root/pwnagotchi/data/images/face_happy.bmp', (0, 20)), - 'status': Text(value=self._voice.default(), position=status_pos, color=BLACK, font=fonts.Medium), + + 'status': Text(value=self._voice.default(), + position=status_pos, + color=BLACK, + font=fonts.Medium, + wrap=True, + # the current maximum number of characters per line, assuming each character is 6 pixels wide + max_length=(self._width - status_pos[0]) // 6), 'shakes': LabeledValue(label='PWND ', value='0 (00)', color=BLACK, position=(0, self._height - int(self._height * .12) + 1), label_font=fonts.Bold, @@ -114,7 +117,23 @@ class View(object): for key, value in state.items(): self._state.set(key, value) - _thread.start_new_thread(self._refresh_handler, ()) + plugins.on('ui_setup', self) + + if config['ui']['fps'] > 0.0: + _thread.start_new_thread(self._refresh_handler, ()) + self._ignore_changes = () + else: + core.log("ui.fps is 0, the display will only update for major changes") + self._ignore_changes = ('uptime', 'name') + + def add_element(self, key, elem): + self._state.add_element(key, elem) + + def width(self): + return self._width + + def height(self): + return self._height def on_state_change(self, key, cb): self._state.add_listener(key, cb) @@ -227,12 +246,12 @@ class View(object): if sleeping: if secs > 1: self.set('face', faces.SLEEP) - self.set('status', self._voice.on_napping(secs)) + self.set('status', self._voice.on_napping(int(secs))) else: self.set('face', faces.SLEEP2) self.set('status', self._voice.on_awakening()) else: - self.set('status', self._voice.on_waiting(secs)) + self.set('status', self._voice.on_waiting(int(secs))) if step % 2 == 0: self.set('face', faces.LOOK_R) else: @@ -298,13 +317,24 @@ class View(object): self.set('status', self._voice.on_rebooting()) self.update() + def on_custom(self, text): + self.set('face', faces.DEBUG) + self.set('status', self._voice.custom(text)) + self.update() + def update(self): with self._lock: - self._canvas = Image.new('1', (self._width, self._height), WHITE) - drawer = ImageDraw.Draw(self._canvas) + changes = self._state.changes(ignore=self._ignore_changes) + if len(changes): + self._canvas = Image.new('1', (self._width, self._height), WHITE) + drawer = ImageDraw.Draw(self._canvas) - for key, lv in self._state.items(): - lv.draw(self._canvas, drawer) + plugins.on('ui_update', self) - for cb in self._render_cbs: - cb(self._canvas) + for key, lv in self._state.items(): + lv.draw(self._canvas, drawer) + + for cb in self._render_cbs: + cb(self._canvas) + + self._state.reset() diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py index 5805086e..b6de9dad 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py @@ -1,218 +1,225 @@ -# //***************************************************************************** -# * | File : epd2in13.py -# * | Author : Waveshare team -# * | Function : Electronic paper driver -# * | Info : -# *---------------- -# * | This version: V3.1 -# * | Date : 2019-03-20 -# * | Info : python3 demo -# * fix: TurnOnDisplay() -# ******************************************************************************// -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documnetation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and//or sell -# copies of the Software, and to permit persons to whom the Software is -# furished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - - -from . import epdconfig -from PIL import Image -import RPi.GPIO as GPIO -# import numpy as np - -# Display resolution -EPD_WIDTH = 122 -EPD_HEIGHT = 250 - -class EPD: - def __init__(self): - self.reset_pin = epdconfig.RST_PIN - self.dc_pin = epdconfig.DC_PIN - self.busy_pin = epdconfig.BUSY_PIN - self.width = EPD_WIDTH - self.height = EPD_HEIGHT - lut_full_update = [ - 0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 - ] - - lut_partial_update = [ - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ] - - # Hardware reset - def reset(self): - epdconfig.digital_write(self.reset_pin, GPIO.HIGH) - epdconfig.delay_ms(200) - epdconfig.digital_write(self.reset_pin, GPIO.LOW) # module reset - epdconfig.delay_ms(200) - epdconfig.digital_write(self.reset_pin, GPIO.HIGH) - epdconfig.delay_ms(200) - - def send_command(self, command): - epdconfig.digital_write(self.dc_pin, GPIO.LOW) - epdconfig.spi_writebyte([command]) - - def send_data(self, data): - epdconfig.digital_write(self.dc_pin, GPIO.HIGH) - epdconfig.spi_writebyte([data]) - - def wait_until_idle(self): - # print("busy") - while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy - epdconfig.delay_ms(100) - # print("free busy") - - def TurnOnDisplay(self): - self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2 - self.send_data(0xC4) - self.send_command(0x20) # MASTER_ACTIVATION - self.send_command(0xFF) # TERMINATE_FRAME_READ_WRITE - self.wait_until_idle() - - def init(self, lut): - if (epdconfig.module_init() != 0): - return -1 - # EPD hardware init start - self.reset() - self.send_command(0x01) # DRIVER_OUTPUT_CONTROL - self.send_data((EPD_HEIGHT - 1) & 0xFF) - self.send_data(((EPD_HEIGHT - 1) >> 8) & 0xFF) - self.send_data(0x00) # GD = 0 SM = 0 TB = 0 - - self.send_command(0x0C) # BOOSTER_SOFT_START_CONTROL - self.send_data(0xD7) - self.send_data(0xD6) - self.send_data(0x9D) - - self.send_command(0x2C) # WRITE_VCOM_REGISTER - self.send_data(0xA8) # VCOM 7C - - self.send_command(0x3A) # SET_DUMMY_LINE_PERIOD - self.send_data(0x1A) # 4 dummy lines per gate - - self.send_command(0x3B) # SET_GATE_TIME - self.send_data(0x08) # 2us per line - - self.send_command(0X3C) # BORDER_WAVEFORM_CONTROL - self.send_data(0x03) - - self.send_command(0X11) # DATA_ENTRY_MODE_SETTING - self.send_data(0x03) # X increment; Y increment - - # WRITE_LUT_REGISTER - self.send_command(0x32) - for count in range(30): - self.send_data(lut[count]) - - return 0 - -## - # @brief: specify the memory area for data R//W - ## - def SetWindows(self, x_start, y_start, x_end, y_end): - self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION - self.send_data((x_start >> 3) & 0xFF) - self.send_data((x_end >> 3) & 0xFF) - self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION - self.send_data(y_start & 0xFF) - self.send_data((y_start >> 8) & 0xFF) - self.send_data(y_end & 0xFF) - self.send_data((y_end >> 8) & 0xFF) - -## - # @brief: specify the start point for data R//W - ## - def SetCursor(self, x, y): - self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER - # x point must be the multiple of 8 or the last 3 bits will be ignored - self.send_data((x >> 3) & 0xFF) - self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER - self.send_data(y & 0xFF) - self.send_data((y >> 8) & 0xFF) - self.wait_until_idle() - - def getbuffer(self, image): - if self.width%8 == 0: - linewidth = self.width//8 - else: - linewidth = self.width//8 + 1 - - buf = [0xFF] * (linewidth * self.height) - image_monocolor = image.convert('1') - imwidth, imheight = image_monocolor.size - pixels = image_monocolor.load() - - if(imwidth == self.width and imheight == self.height): - # print("Vertical") - for y in range(imheight): - for x in range(imwidth): - if pixels[x, y] == 0: - # x = imwidth - x - buf[x // 8 + y * linewidth] &= ~(0x80 >> (x % 8)) - elif(imwidth == self.height and imheight == self.width): - # print("Horizontal") - for y in range(imheight): - for x in range(imwidth): - newx = y - newy = self.height - x - 1 - if pixels[x, y] == 0: - # newy = imwidth - newy - 1 - buf[newx // 8 + newy*linewidth] &= ~(0x80 >> (y % 8)) - return buf - - - def display(self, image): - if self.width%8 == 0: - linewidth = self.width//8 - else: - linewidth = self.width//8 + 1 - - self.SetWindows(0, 0, EPD_WIDTH, EPD_HEIGHT); - for j in range(0, self.height): - self.SetCursor(0, j); - self.send_command(0x24); - for i in range(0, linewidth): - self.send_data(image[i + j * linewidth]) - self.TurnOnDisplay() - - def Clear(self, color): - if self.width%8 == 0: - linewidth = self.width//8 - else: - linewidth = self.width//8 + 1 - - self.SetWindows(0, 0, EPD_WIDTH, EPD_HEIGHT); - for j in range(0, self.height): - self.SetCursor(0, j); - self.send_command(0x24); - for i in range(0, linewidth): - self.send_data(color) - self.TurnOnDisplay() - - def sleep(self): - self.send_command(0x10) #enter deep sleep - # self.send_data(0x01) - epdconfig.delay_ms(100) - -### END OF FILE ### - +# ***************************************************************************** +# * | File : epd2in13.py +# * | Author : Waveshare team +# * | Function : Electronic paper driver +# * | Info : +# *---------------- +# * | This version: V4.0 +# * | Date : 2019-06-20 +# # | Info : python demo +# ----------------------------------------------------------------------------- +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documnetation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + + +import logging +from . import epdconfig +import numpy as np + +# Display resolution +EPD_WIDTH = 122 +EPD_HEIGHT = 250 + +class EPD: + def __init__(self): + self.reset_pin = epdconfig.RST_PIN + self.dc_pin = epdconfig.DC_PIN + self.busy_pin = epdconfig.BUSY_PIN + self.cs_pin = epdconfig.CS_PIN + self.width = EPD_WIDTH + self.height = EPD_HEIGHT + + lut_full_update = [ + 0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 + ] + + lut_partial_update = [ + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ] + + # Hardware reset + def reset(self): + epdconfig.digital_write(self.cs_pin, 0) + epdconfig.digital_write(self.reset_pin, 1) + epdconfig.delay_ms(200) + epdconfig.digital_write(self.reset_pin, 0) + epdconfig.delay_ms(10) + epdconfig.digital_write(self.reset_pin, 1) + epdconfig.delay_ms(200) + epdconfig.digital_write(self.cs_pin, 1) + + def send_command(self, command): + epdconfig.digital_write(self.cs_pin, 0) + epdconfig.digital_write(self.dc_pin, 0) + epdconfig.spi_writebyte([command]) + epdconfig.digital_write(self.cs_pin, 1) + + def send_data(self, data): + epdconfig.digital_write(self.cs_pin, 0) + epdconfig.digital_write(self.dc_pin, 1) + epdconfig.spi_writebyte([data]) + epdconfig.digital_write(self.cs_pin, 1) + + def ReadBusy(self): + while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy + epdconfig.delay_ms(100) + + def TurnOnDisplay(self): + self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2 + self.send_data(0xC4) + self.send_command(0x20) # MASTER_ACTIVATION + self.send_command(0xFF) # TERMINATE_FRAME_READ_WRITE + + logging.debug("e-Paper busy") + self.ReadBusy() + logging.debug("e-Paper busy release") + + def init(self, lut): + if (epdconfig.module_init() != 0): + return -1 + # EPD hardware init start + self.reset() + self.send_command(0x01) # DRIVER_OUTPUT_CONTROL + self.send_data((EPD_HEIGHT - 1) & 0xFF) + self.send_data(((EPD_HEIGHT - 1) >> 8) & 0xFF) + self.send_data(0x00) # GD = 0 SM = 0 TB = 0 + + self.send_command(0x0C) # BOOSTER_SOFT_START_CONTROL + self.send_data(0xD7) + self.send_data(0xD6) + self.send_data(0x9D) + + self.send_command(0x2C) # WRITE_VCOM_REGISTER + self.send_data(0xA8) # VCOM 7C + + self.send_command(0x3A) # SET_DUMMY_LINE_PERIOD + self.send_data(0x1A) # 4 dummy lines per gate + + self.send_command(0x3B) # SET_GATE_TIME + self.send_data(0x08) # 2us per line + + self.send_command(0X3C) # BORDER_WAVEFORM_CONTROL + self.send_data(0x03) + + self.send_command(0X11) # DATA_ENTRY_MODE_SETTING + self.send_data(0x03) # X increment; Y increment + + # WRITE_LUT_REGISTER + self.send_command(0x32) + for count in range(30): + self.send_data(lut[count]) + + return 0 + +## + # @brief: specify the memory area for data R/W + ## + def SetWindows(self, x_start, y_start, x_end, y_end): + self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION + self.send_data((x_start >> 3) & 0xFF) + self.send_data((x_end >> 3) & 0xFF) + self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION + self.send_data(y_start & 0xFF) + self.send_data((y_start >> 8) & 0xFF) + self.send_data(y_end & 0xFF) + self.send_data((y_end >> 8) & 0xFF) + +## + # @brief: specify the start point for data R/W + ## + def SetCursor(self, x, y): + self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER + # x point must be the multiple of 8 or the last 3 bits will be ignored + self.send_data((x >> 3) & 0xFF) + self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER + self.send_data(y & 0xFF) + self.send_data((y >> 8) & 0xFF) + self.ReadBusy() + + def getbuffer(self, image): + if self.width%8 == 0: + linewidth = int(self.width/8) + else: + linewidth = int(self.width/8) + 1 + + buf = [0xFF] * (linewidth * self.height) + image_monocolor = image.convert('1') + imwidth, imheight = image_monocolor.size + pixels = image_monocolor.load() + + if(imwidth == self.width and imheight == self.height): + for y in range(imheight): + for x in range(imwidth): + if pixels[x, y] == 0: + # x = imwidth - x + buf[int(x / 8) + y * linewidth] &= ~(0x80 >> (x % 8)) + elif(imwidth == self.height and imheight == self.width): + for y in range(imheight): + for x in range(imwidth): + newx = y + newy = self.height - x - 1 + if pixels[x, y] == 0: + # newy = imwidth - newy - 1 + buf[int(newx / 8) + newy*linewidth] &= ~(0x80 >> (y % 8)) + return buf + + + def display(self, image): + if self.width%8 == 0: + linewidth = int(self.width/8) + else: + linewidth = int(self.width/8) + 1 + + self.SetWindows(0, 0, self.width, self.height); + for j in range(0, self.height): + self.SetCursor(0, j); + self.send_command(0x24); + for i in range(0, linewidth): + self.send_data(image[i + j * linewidth]) + self.TurnOnDisplay() + + def Clear(self, color): + if self.width%8 == 0: + linewidth = int(self.width/8) + else: + linewidth = int(self.width/8) + 1 + + self.SetWindows(0, 0, self.width, self.height); + for j in range(0, self.height): + self.SetCursor(0, j); + self.send_command(0x24); + for i in range(0, linewidth): + self.send_data(color) + self.TurnOnDisplay() + + def sleep(self): + self.send_command(0x10) #enter deep sleep + self.send_data(0x01) + epdconfig.delay_ms(100) + + epdconfig.module_exit() + +### END OF FILE ### + diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/version.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/version.py new file mode 100644 index 00000000..c273c83b --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/version.py @@ -0,0 +1 @@ +version = '1.0.0travistest' diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py index 45f5092d..536bc179 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py @@ -17,129 +17,108 @@ class Voice: def default(self): return self._('ZzzzZZzzzzZzzz') - def on_starting(self): - return random.choice([ \ - self._('Hi, I\'m Pwnagotchi!\nStarting ...'), - self._('New day, new hunt,\nnew pwns!'), + return random.choice([ + self._('Hi, I\'m Pwnagotchi! Starting ...'), + self._('New day, new hunt, new pwns!'), self._('Hack the Planet!')]) - def on_ai_ready(self): return random.choice([ self._('AI ready.'), - self._('The neural network\nis ready.')]) - + self._('The neural network is ready.')]) def on_normal(self): - return random.choice([ \ + return random.choice([ '', '...']) - def on_free_channel(self, channel): - return self._('Hey, channel {channel} is\nfree! Your AP will\nsay thanks.').format(channel=channel) - + return self._('Hey, channel {channel} is free! Your AP will say thanks.').format(channel=channel) def on_bored(self): - return random.choice([ \ + return random.choice([ self._('I\'m bored ...'), self._('Let\'s go for a walk!')]) - def on_motivated(self, reward): - return self._('This is the best\nday of my life!') - + return self._('This is the best day of my life!') def on_demotivated(self, reward): return self._('Shitty day :/') - def on_sad(self): - return random.choice([ \ + return random.choice([ self._('I\'m extremely bored ...'), self._('I\'m very sad ...'), self._('I\'m sad'), '...']) - def on_excited(self): - return random.choice([ \ + return random.choice([ self._('I\'m living the life!'), self._('I pwn therefore I am.'), self._('So many networks!!!'), - self._('I\'m having so much\nfun!'), - self._('My crime is that of\ncuriosity ...')]) - + self._('I\'m having so much fun!'), + self._('My crime is that of curiosity ...')]) def on_new_peer(self, peer): - return random.choice([ \ - self._('Hello\n{name}!\nNice to meet you. {name}').format(name=peer.name()), - self._('Unit\n{name}\nis nearby! {name}').format(name=peer.name())]) - + return random.choice([ + self._('Hello {name}! Nice to meet you. {name}').format(name=peer.name()), + self._('Unit {name} is nearby! {name}').format(name=peer.name())]) def on_lost_peer(self, peer): - return random.choice([ \ - self._('Uhm ...\ngoodbye\n{name}').format(name=peer.name()), - self._('{name}\nis gone ...').format(name=peer.name())]) - + return random.choice([ + self._('Uhm ... goodbye {name}').format(name=peer.name()), + self._('{name} is gone ...').format(name=peer.name())]) def on_miss(self, who): - return random.choice([ \ - self._('Whoops ...\n{name}\nis gone.').format(name=who), - self._('{name}\nmissed!').format(name=who), + return random.choice([ + self._('Whoops ... {name} is gone.').format(name=who), + self._('{name} missed!').format(name=who), self._('Missed!')]) - def on_lonely(self): - return random.choice([ \ - self._('Nobody wants to\nplay with me ...'), + return random.choice([ + self._('Nobody wants to play with me ...'), self._('I feel so alone ...'), self._('Where\'s everybody?!')]) - def on_napping(self, secs): - return random.choice([ \ + return random.choice([ self._('Napping for {secs}s ...').format(secs=secs), self._('Zzzzz'), self._('ZzzZzzz ({secs}s)').format(secs=secs)]) - def on_awakening(self): return random.choice(['...', '!']) - def on_waiting(self, secs): - return random.choice([ \ + return random.choice([ self._('Waiting for {secs}s ...').format(secs=secs), '...', self._('Looking around ({secs}s)').format(secs=secs)]) - def on_assoc(self, ap): ssid, bssid = ap['hostname'], ap['mac'] what = ssid if ssid != '' and ssid != '' else bssid - return random.choice([ \ - self._('Hey\n{what}\nlet\'s be friends!').format(what=what), - self._('Associating to\n{what}').format(what=what), - self._('Yo\n{what}!').format(what=what)]) - - - def on_deauth(self,sta): - return random.choice([ \ - self._('Just decided that\n{mac}\nneeds no WiFi!').format(mac=sta['mac']), - self._('Deauthenticating\n{mac}').format(mac=sta['mac']), - self._('Kickbanning\n{mac}!').format(mac=sta['mac'])]) + return random.choice([ + self._('Hey {what} let\'s be friends!').format(what=what), + self._('Associating to {what}').format(what=what), + self._('Yo {what}!').format(what=what)]) + def on_deauth(self, sta): + return random.choice([ + self._('Just decided that {mac} needs no WiFi!').format(mac=sta['mac']), + self._('Deauthenticating {mac}').format(mac=sta['mac']), + self._('Kickbanning {mac}!').format(mac=sta['mac'])]) def on_handshakes(self, new_shakes): s = 's' if new_shakes > 1 else '' - return self._('Cool, we got {num}\nnew handshake{plural}!').format(num=new_shakes, plural=s) - + return self._('Cool, we got {num} new handshake{plural}!').format(num=new_shakes, plural=s) def on_rebooting(self): - return self._("Ops, something\nwent wrong ...\nRebooting ...") - + return self._("Ops, something went wrong ... Rebooting ...") def on_log(self, log): status = self._('Kicked {num} stations\n').format(num=log.deauthed) @@ -151,10 +130,13 @@ class Voice: status += self._('Met {num} peers').format(num=log.peers) return status - def on_log_tweet(self, log): - return self._('I\'ve been pwning for {duration} and kicked {deauthed} clients! I\'ve also met {associated} new friends and ate {handshakes} handshakes! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet').format( - duration=log.duration_human, - deauthed=log.deauthed, - associated=log.associated, - handshakes=log.handshakes) + return self._( + 'I\'ve been pwning for {duration} and kicked {deauthed} clients! I\'ve also met {associated} new friends and ate {handshakes} handshakes! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet').format( + duration=log.duration_human, + deauthed=log.deauthed, + associated=log.associated, + handshakes=log.handshakes) + + def custom(self, text): + return self._(text) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt b/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt index 0a82ef71..8fa5e8a7 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt +++ b/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt @@ -10,3 +10,4 @@ file_read_backwards numpy inky smbus +pillow diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/startup.sh b/sdcard/rootfs/root/pwnagotchi/scripts/startup.sh index f158830f..58b681c2 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/startup.sh +++ b/sdcard/rootfs/root/pwnagotchi/scripts/startup.sh @@ -9,5 +9,3 @@ if ifconfig | grep usb0 | grep RUNNING; then else sudo -H -u root /usr/bin/screen -dmS pwnagotchi -c /root/pwnagotchi/data/screenrc.auto fi - -