# Download the latest version of Blender for linux if not already in folder
# 2020-06-29
baseUrl=https://download.blender.org/release/
latest=$( curl -s $baseUrl \
| egrep "^<a" \
| sed -re 's/^[^"]+"([^"]+)">[^>]+>\s+([^-]+)-([^-]+)-([0-9]+).+/\4-\3-\2 \1/' \
-e 's/-Jan-/-01-/' \
-e 's/-Feb-/-02-/' \
-e 's/-Mar-/-03-/' \
-e 's/-Apr-/-04-/' \
-e 's/-May-/-05-/' \
-e 's/-Jun-/-06-/' \
-e 's/-Jul-/-07-/' \
-e 's/-Aug-/-08-/' \
-e 's/-Sep-/-09-/' \
-e 's/-Oct-/-10-/' \
-e 's/-Nov-/-11-/' \
-e 's/-Dec-/-12-/' \
| sort -n | tail -n 1 \
| sed -re 's/\S+\s(.+)/\1/' )
latestUrl="$baseUrl$latest"
echo looking in $latestUrl
latest=$( curl -s $latestUrl \
| egrep "^<a" \
| egrep -i "linux" \
| sed -re 's/^[^"]+"([^"]+)">[^>]+>\s+([^-]+)-([^-]+)-([0-9]+).+/\4-\3-\2 \1/' \
-e 's/-Jan-/-01-/' \
-e 's/-Feb-/-02-/' \
-e 's/-Mar-/-03-/' \
-e 's/-Apr-/-04-/' \
-e 's/-May-/-05-/' \
-e 's/-Jun-/-06-/' \
-e 's/-Jul-/-07-/' \
-e 's/-Aug-/-08-/' \
-e 's/-Sep-/-09-/' \
-e 's/-Oct-/-10-/' \
-e 's/-Nov-/-11-/' \
-e 's/-Dec-/-12-/' \
| sort -n | tail -n 1 \
| sed -re 's/\S+\s(.+)/\1/' )
latestUrl="$latestUrl$latest"
echo looking at $latestUrl
if [ ! -f "$latest" ]; then
wget "$latestUrl"
echo "You probably want to do the following now"
echo "tar xvf $latest"
blender=$(echo $latest | sed -re 's/\.tar.+$//')
current=$(pwd)
echo "ln -sf ${current}/${blender}/blender /usr/bin/blender"
else
echo "Congratulations! you already have what I have deemed to be the latest version of Blender for Linux"
ls -l --color=always /usr/bin/blender
fi
kex_exchange_identification: read: Connection reset by peer
egrep -v "^#" /boot/config.txt | egrep -v "^$"
hdmi_force_hotplug=1
hdmi_group=2
hdmi_mode=4
dtparam=i2c_arm=off
dtparam=spi=off
dtparam=audio=on
[pi4]
dtoverlay=vc4-fkms-v3d
max_framebuffers=2
[all]
dtoverlay=vga666
enable_dpi_lcd=1
display_default_lcd=1
hdmi_force_hotplug=1
dpi_group=2
dpi_mode=4
dtparam=i2c_arm=off
dtparam=spi=off
dtparam=audio=on
[pi4]
dtoverlay=vc4-fkms-v3d
max_framebuffers=2
[all]
dtoverlay=vga666
enable_dpi_lcd=1
display_default_lcd=1
#hdmi_force_hotplug=1
dpi_group=2
dpi_mode=9
dpi_group=2
dpi_mode=4
dpi_group=2
dpi_mode=5
dd bs=4M if=rpd_x86_latest of=/dev/sdd status=progress conv=fsync
dd bs=1M if=rpd_x86_latest of=/dev/sdd status=progress conv=fsync
dd bs=4M if=raspios_armhf_latest of=/dev/sdd status=progress conv=fsync
unzip -p raspios_armhf_latest | dd bs=4M of=/dev/sdd status=progress conv=fsync
sudo vi /boot/config.txt
dtoverlay=vga666
enable_dpi_lcd=1
display_default_lcd=1
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install xscreensaver xscreensaver-data xscreensaver-data-extra xscreensaver-gl xscreensaver-gl-extra
#!/bin/bash
# Creates and emails Moodle user reports
# uses ~/.my.cnf for SQL access
DATE=$(date +"%Y-%m-%d")
# Never logged in
FN="/..../reports/moodle_user_never_logged_in-$DATE.txt"
SQL="/..../dbscripts/moodle_user_never_logged_in.sql"
EMAIL="example@example.com"
SUBJECT="Moodle User report - never logged in $DATE"
#echo $DATE
#echo $FN
#echo $SQL
if [ ! -e "$FN" ]; then
# echo "Creating report $SUBJECT"
mysql -t -u dbUSER --host dbHOST dbINST < $SQL > $FN
RES=$( cat $FN | wc -l )
echo "Total $(($RES-4))" >> $FN
mail -s "$SUBJECT" $EMAIL < $FN
else
echo "File already exists for $SUBJECT"
fi
sudo apt update && sudo apt upgrade -y
sudo apt install python3 python3-pip
pip3 install --upgrade pip
pip3 install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
wget https://github.com/gsuitedevs/python-samples/raw/master/gmail/quickstart/quickstart.py
user_id = "me";
query = "from:example@example.com";
response = service.users().messages().list(userId=user_id, q=query).execute()
message = service.users().messages().get(userId=user_id, id=msg_id, format='full').execute()
#msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII')) # when format was 'raw'
#print(msg_str)
print(base64.urlsafe_b64decode(message['payload']['body']['data'].encode('ASCII')) )
messageHeaders = message['payload']['headers']
subject= [i['value'] for i in messageHeaders if i["name"]=="Subject"]
print(subject)
from __future__ import print_function
import pickle
import os.path
import base64
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from apiclient import errors
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
def printMessage(service, msg_id):
user_id = "me";
try:
message = service.users().messages().get(userId=user_id, id=msg_id,
format='full').execute()
#msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII')) # when format was 'raw'
#print(msg_str)
print(base64.urlsafe_b64decode(message['payload']['body']['data'].encode('ASCII')) )
messageHeaders = message['payload']['headers']
subject= [i['value'] for i in messageHeaders if i["name"]=="Subject"]
print(subject)
except errors.HttpError as error:
print ('An error occurred: {0}'.format(error))
def getMessages(service):
user_id = "me"
query = "from:example@example.com" # specific to my requirements
try:
response = service.users().messages().list(userId=user_id,
q=query).execute()
messages = []
if 'messages' in response:
messages.extend(response['messages'])
while 'nextPageToken' in response:
page_token = response['nextPageToken']
response = service.users().messages().list(userId=user_id, q=query,
pageToken=page_token).execute()
messages.extend(response['messages'])
return messages
except errors.HttpError as error:
print ('An error occurred: {0}'.format(error))
def main():
"""Searches for specific email.
Lists the messages contents.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('gmail', 'v1', credentials=creds)
results = getMessages(service)
print("Number of Messages found {0}".format(len(results)))
#for message in results:
# print(message['id'])
printMessage(service, results[0]['id'])
if __name__ == '__main__':
main()
wget https://raw.githubusercontent.com/gsuitedevs/python-samples/master/docs/quickstart/quickstart.py
title = 'My Document'
body = {
'title': title
}
doc = service.documents().create(body=body).execute()
print('Created document with title: {0}'.format(doc.get('title')))
DOCUMENT_ID = doc.get('documentId')
# Retrieve the documents contents from the Docs service.
document = service.documents().get(documentId=DOCUMENT_ID).execute()
print('The title of the document is: {}'.format(document.get('title')))
text1 = "the"
text2 = " quick"
text3 = " red"
requests = [
{
'insertText': {
'location': {
'index': 1,
},
'text': text1
}
},
{
'insertText': {
'location': {
'index': 1,
},
'text': text2
}
},
{
'insertText': {
'location': {
'index': 1,
},
'text': text3
}
},
]
result = service.documents().batchUpdate(documentId=DOCUMENT_ID, body={'requests': requests}).execute()
text1 = "the"
text2 = " quick"
text3 = " red"
requests = [
{
'insertText': {
'location': {
'index': 1,
},
'text': text1
}
},
{
'insertText': {
'location': {
'index': 1+ len(text1),
},
'text': text2
}
},
{
'insertText': {
'location': {
'index': 1+ len(text1) + len(text2),
},
'text': text3
}
},
]
result = service.documents().batchUpdate(documentId=DOCUMENT_ID, body={'requests': requests}).execute()
msg_str = base64.urlsafe_b64decode(message['payload']['body']['data'].encode('UTF-8'))
requests = [
{
'insertText': {
'location': {
'index': 1,
},
'text': contents.decode()
}
}]
requests = [
...
{
'updateDocumentStyle': {
"documentStyle":{
'pageSize':{
"width": {
'magnitude': 842,
'unit': 'PT'
},
"height": {
'magnitude': 595,
'unit': 'PT'
}
}
},
"fields": 'pageSize'}
}]
requests = [
...
{
'updateDocumentStyle': {
"documentStyle":{
'pageSize':{
"width": {
'magnitude': 842,
'unit': 'PT'
},
"height": {
'magnitude': 595,
'unit': 'PT'
}
},
'marginTop': {
'magnitude': 0,
'unit': 'PT'
},
'marginBottom': {
'magnitude': 0,
'unit': 'PT'
},
'marginLeft': {
'magnitude': 0,
'unit': 'PT'
},
'marginRight': {
'magnitude': 0,
'unit': 'PT'
}
},
"fields": 'pageSize, marginTop, marginBottom, marginLeft, marginRight'
}
}]
requests = [
...
{
'updateTextStyle': {
'range': {
'startIndex': 1,
'endIndex': 5
},
'textStyle': {
'bold': True,
},
'fields': 'bold'
}
},
]
Invalid requests[0].updateTextStyle: Index 1399 must be less than the end index of the referenced segment, 1313."
+-----------+-------------------+--
| firstname | lastname | C
+-----------+-------------------+--
| Rey | Palpatine |
| Fin | Skywalker |
+-----------+-------------------+--
WINDOWS_LINE_ENDING = b'\r\n'
UNIX_LINE_ENDING = b'\n'
report_contents = message_contents.replace(WINDOWS_LINE_ENDING, UNIX_LINE_ENDING)
'endIndex': len( contents.decode() )
requests = [
...
{
'updateTextStyle': {
'range': {
'startIndex': 1,
'endIndex': len( contents.decode() )
},
'textStyle': {
'weightedFontFamily': { 'fontFamily' : 'Courier New'},
'fontSize': {
'magnitude': 8,
'unit': 'PT'
}
},
'fields': 'fontSize, weightedFontFamily'
}
}]
result = service.files().copy(fileId=fileId, supportsAllDrives=True, body={'name': title, "parents": [folder] }).execute()
result = service.files().delete(fileId=fileId).execute()
json returned "Insufficient Permission"
json returned "Insufficient Permission"
def archiveMessage(service, msg_id):
user_id = "me";
msg_labels = { 'removeLabelIds' : ['INBOX']}
service.users().messages().modify(userId=user_id, id=msg_id, body=msg_labels).execute()
email
root
flog archives
Disclaimer:
This page is by me for me, if you are not me then please be aware of the following
I am not responsible for anything that works or does not work including files and pages made available at www.jumpstation.co.uk
I am also not responsible for any information(or what you or others do with it) available at www.jumpstation.co.uk
In fact I'm not responsible for anything ever, so there!