web3py EthereumTesterProvider - Basic transaction fails - ethereum

On the web3py EthereumTesterProvider blockchain, I send 2 ethers from the first test account to the second one. The python program ends normally but the transaction seems to fail :
the status of the transaction receipt ('status': 0), which I guess means failed.
the balance of the 2 accounts is not updated after the transaction.
pip config (windows 10) :
web3py (5.31.3)
eth-tester (0.8.0b3)
Code:
from web3 import Web3, EthereumTesterProvider
from pprint import pprint
w3 = Web3(EthereumTesterProvider())
print(f"{w3.isConnected() = }")
print(f"\n{w3.eth.get_balance(w3.eth.accounts[0]) = }")
print(f"{w3.eth.get_balance(w3.eth.accounts[1]) = }")
tx_hash = w3.eth.send_transaction(
{
'from': w3.eth.accounts[0],
'to': w3.eth.accounts[1],
'value': w3.toWei(2, 'ether'),
'gas': 21000
}
)
print(f"\n{tx_hash = }")
print("\ntx_receipt = ")
tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
pprint(dict(tx_receipt))
print(f"\n{w3.eth.get_balance(w3.eth.accounts[0]) = }")
print(f"{w3.eth.get_balance(w3.eth.accounts[1]) = }")
Traces:
w3.isConnected() = True
w3.eth.get_balance(w3.eth.accounts[0]) = 1000000000000000000000000
w3.eth.get_balance(w3.eth.accounts[1]) = 1000000000000000000000000
tx_hash = HexBytes('0x72345d1c23a10ac3849e1f8e53b517da8200e58ab211ebaf44df732f6f8a29af')
tx_receipt =
{'blockHash': HexBytes('0xadfcec5788a8757a5eed6aeee15c997a6b75a612fa4919a878b02a69d04f8a0c'),
'blockNumber': 1,
'contractAddress': '0xa0Beb7081fDaF3ed157370836A85eeC20CEc9e04',
'cumulativeGasUsed': 21000,
'effectiveGasPrice': 1000000000,
'from': '0xaBbACadABa000000000000000000000000000000',
'gasUsed': 21000,
'logs': [],
'state_root': b'\x00',
'status': 0, <======== failure ==========
'to': '0xaBbACaDaBA000000000000000000000000000001',
'transactionHash': HexBytes('0x72345d1c23a10ac3849e1f8e53b517da8200e58ab211ebaf44df732f6f8a29af'),
'transactionIndex': 0,
'type': '0x2'}
w3.eth.get_balance(w3.eth.accounts[0]) = 1000000000000000000000000
w3.eth.get_balance(w3.eth.accounts[1]) = 1000000000000000000000000
Please also note that this code works with ganache when I change the instance of web3 like that :
w3 = Web3(Web3.HTTPProvider('HTTP://127.0.0.1:8545'))

Related

How to create a valid signature message to POST an order to the Kucoin Future API?

I am trying to place an order but it gives me this error:
{"code":"400005","msg":"Invalid KC-API-SIGN"}
I'll be so thankful if someone check my code and let me know the problem
import requests
import time
import base64
import hashlib
import hmac
import json
import uuid
api_key = 'XXXXXXXXXXXXXXXXXXXXXXX'
api_secret = 'XXXXXXXXXXXXXXXXXXXXXX'
api_passphrase = 'XXXXXXXXXXXXXXX'
future_base_url = "https://api-futures.kucoin.com"
clientOid = uuid.uuid4().hex
params = {
"clientOid": str(clientOid),
"side": str(side),
"symbol": str(symbol),
"type": "limit",
"leverage": "5",
"stop": "down",
"stopPriceType": "TP",
"price": str(price),
"size": int(size),
"stopPrice": str(stopprice)
}
json_params = json.dumps(params)
print(json_params)
now = int(time.time() * 1000)
str_to_sign = str(now) + 'POST' + '/api/v1/orders' + json_params
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), str_to_sign.encode('utf-8'), hashlib.sha256).digest())
passphrase = base64.b64encode(hmac.new(api_secret.encode('utf-8'), api_passphrase.encode('utf-8'), hashlib.sha256).digest())
headers = {
"KC-API-SIGN": signature,
"KC-API-TIMESTAMP": str(now),
"KC-API-KEY": api_key,
"KC-API-PASSPHRASE": passphrase,
"KC-API-KEY-VERSION": "2",
"Content-Type": "application/json"
}
response = requests.request('POST', future_base_url + '/api/v1/orders', params=params, headers=headers)
print(response.text)
This worked for me:
tickerK = "AVAXUSDTM"
clientOid = tickerK + '_' + str(now)
side = "buy"
typee = "market"
leverage = "2"
stop = "up"
stopPriceType = "TP"
stopPrice = "12"
size = "3"
# Set the request body
data = {
"clientOid":clientOid,
"side":side,
"symbol":tickerK,
"type":typee,
"leverage":leverage,
"stop":stop,
"stopPriceType":stopPriceType,
"stopPrice":stopPrice,
"size":size
}
data_json = json.dumps(data, separators=(',', ':'))
data_json
url = 'https://api-futures.kucoin.com/api/v1/orders'
now = int(time() * 1000)
str_to_sign = str(now) + 'POST' + '/api/v1/orders' + data_json
signature = base64.b64encode(
hmac.new(api_secret.encode('utf-8'), str_to_sign.encode('utf-8'), hashlib.sha256).digest())
passphrase = base64.b64encode(hmac.new(api_secret.encode('utf-8'), api_passphrase.encode('utf-8'), hashlib.sha256).digest())
headers = {
"KC-API-SIGN": signature,
"KC-API-TIMESTAMP": str(now),
"KC-API-KEY": api_key,
"KC-API-PASSPHRASE": passphrase,
"KC-API-KEY-VERSION": "2",
"Content-Type": "application/json"
}
# Send the POST request
response = requests.request('post', url, headers=headers, data=data_json)
# Print the response
print(response.json())
Please take care of the lines marked in red:
Remove spaces from the json
Add the json to the string to sign
Add content type to the header
Do the request this way

DISCORD.PY Creating an end Giveaway Command

I am working on a giveaway bot and after doing the start and reroll command I have run into the end command , which i cannot fully grasp how to do it. I thought to register something when the giveaway is created (msgID of the giveaway im registering) in my aiosqlite database and for the end function , i could be able to fetch it and stop the giveaway. Now here is the thing, i cant think of a function or a task that will end the giveaway or somehow just end the duration.
For reference here is my start command :
class Start(commands.Cog):
def __init__(self, client):
self.client = client
def convert(self, timer):
pos = ["s", "m", "h", "d"]
time_dict = {"s" : 1, "m" : 60, "h" : 3600, "d" : 3600*24}
unit = timer[-1]
if unit not in pos:
return -1
try:
val = int(timer[:-1])
except:
return -2
return val * time_dict[unit]
#commands.command()
async def start(self, ctx, duration, winners: str, *, prize):
timer = (self.convert(duration))
winners = int(winners.replace("w",""))
await ctx.message.delete()
timestamp = time.time() + timer
epoch_time = int((time.time() + timer))
embed = discord.Embed(title = f"{prize}", description = f'React with 🎉 to enter\nEnds: <t:{epoch_time}:R> (<t:{epoch_time}>)\nHosted by {ctx.author.mention}\n', color =
ctx.author.color, timestamp=(datetime.datetime.utcfromtimestamp(timestamp)))
embed.set_footer(text=f'Winners : {winners} | Ends at \u200b')
gaw_msg = await ctx.send(content = "<:spadess:939938117736091678> **GIVEAWAY** <:spadess:939938117736091678>",embed=embed)
await gaw_msg.add_reaction("🎉")
db = await aiosqlite.connect("main.db")
cursor = await db.cursor()
await cursor.execute(f'SELECT * FROM storingStuff WHERE msgID = {gaw_msg.id}')
data = await cursor.fetchone()
if data is None:
await cursor.execute(f'INSERT INTO storingStuff (msgID, guildID) VALUES({gaw_msg.guild.id} , {gaw_msg.id})')
await db.commit()
await cursor.close()
await db.close()
await asyncio.sleep(timer)
new_msg = await ctx.channel.fetch_message(gaw_msg.id)
users_mention = []
for i in range(winners):
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(self.client.user))
winner = random.choice(users)
users_mention.append(winner.mention)
users.remove(winner)
displayed_winners = ",".join(users_mention)
endembed = discord.Embed(title=f"{prize}", description=f"Winner: {displayed_winners}\nHosted by: {ctx.author.mention}", color = ctx.author.color, timestamp=(datetime.datetime.utcfromtimestamp(timestamp)))
endembed.set_footer(text= 'Ended at \u200b')
await gaw_msg.edit(content = "<:done:939940228746072096> **GIVEAWAY ENDED** <:done:939940228746072096>",embed=endembed)
await ctx.send(f"Congragulations {displayed_winners}! You won the **{prize}**.\n{gaw_msg.jump_url}")
def setup(client):
client.add_cog(Start(client))
Any help with the case would be appreciated , or any code reference as I'm pretty new. Thank you for spending your time and reading this.

Attribute error when sending json with Requests from mediainfo AWS Lambda

I m trying to send video metadata to MongoDB Atlas from an s3 bucket with media info as an AWS Lambda in Python 3.7. It works when I hardcode the data, but I receive either an object key error or an attribute error. I tried importing json and using json.loads() and json.dumps() and receive errors. Here's the code,
import boto3
from botocore.client import Config
from botocore.exceptions import ClientError
import json
import xmltodict
import subprocess
import os
import uuid
import requests
import json
# Generate a presigned URL for S3 Object
def get_presigned_url(expiration, objBucket, objKey):
s3 = boto3.client('s3', 'us-east-1', config=Config(s3={'addressing_style': 'virtual'}))
Params={
'Bucket': objBucket,
'Key': objKey
}
print ('CORE:: Media Evaluator:: Bucket Name: ' + objBucket)
print ('CORE:: Media Evaluator:: Object Key: ' + objKey)
try:
response = s3.generate_presigned_url('get_object', Params, ExpiresIn=expiration)
print('this is the response !!!!!!!!!', response)
except ClientError as e:
print (e)
raise
return None
return response
# Get MD5 from S3 Object Tag
def get_md5_from_objectTag(objBucket, objKey):
s3 = boto3.client('s3', 'us-east-1', config=Config(s3={'addressing_style': 'virtual'}))
response = s3.get_object_tagging(
Bucket=objBucket,
Key=objKey
)
for tag in response['TagSet']:
if tag['Key'] == 'MD5':
md5 = tag['Value']
return md5
# Evaluate the media using MediaInfo
def get_mediainfo(presignedURL):
print("presignedURL !!!!!!!!!!!!!", presignedURL)
try:
output = subprocess.check_output(['./mediainfo', '--full', '--output=JSON', presignedURL], shell=False, stderr=subprocess.STDOUT)
# subprocess.check_output(["./mediainfo", "--full", "--output=JSON", presignedURL], stdin=None, stderr=subprocess.STDOUT, shell=True)
print("this si the output !!!!!!!!!!!!!!!!!", output)
json_output = json.loads(output)
print("this is the JOSN output!!!!!!", json_output)
# Prepare the short media analysis JSON
json_track = json_output['media']
for f in json_track['track']:
if f['#type'] == 'General':
wrapper = f['Format']
if f['#type'] == 'Video':
wrapperType = f['Format_Profile']
codec = f['Format']
bitRate = f['BitRate']
#frameRate = f['FrameRate']
#som = f['TimeCode_FirstFrame']
width = f['Width']
height = f['Height']
#framecount = f['FrameCount']
#if f['#type'] == 'Other' and f['Type'] == 'Time code':
#som = f['TimeCode_FirstFrame']
mediaResult = {
"Wrapper": wrapper + wrapperType,
"Codec": codec,
"BitRate": bitRate,
#"FrameRate": frameRate,
#"SOM": som,
"Resolution": width + 'X' + height,
#"FrameCount": framecount
}
except Exception as e:
print (e)
raise
return None
return mediaResult
def lambda_handler(event, context):
print("this is the event !!!!!!!!!!!!!!!", event)
bucketName = event['bucketName']
objectName = event['objectKey']
signed_url = get_presigned_url(3600, bucketName, objectName)
print ('CORE:: Media Evaluator:: Presigned URL: ' + signed_url)
mediaAnalysis = get_mediainfo(signed_url)
print('CORE:: Media Evaluator:: Parsed Media Analysis: ' + json.dumps(mediaAnalysis, indent=4))
#md5 = get_md5_from_objectTag(bucketName, objectName)
#print('CORE:: Media Evaluator:: MD5 Value from Object Tag: ' + md5)
ingestData = {
"MediaEvaluation": mediaAnalysis,
#"MD5": md5,
"AssetID": objectName.partition(".")[0],
"AssetUID": uuid.uuid4().hex,
"Bucket": bucketName,
"ObjectKey": objectName
}
print('this is ingestData !!!!!!!!!!!!!!!!!!!!!!!', ingestData)
print('this is mediaAnalysis !!!!!!!!!!!!!!!!!!!!!!!', mediaAnalysis)
#ingestDataJson = json.dumps(ingestData)
#mediaAnalysisJson = json.dumps(mediaAnalysis)
dataNotFake = { 's3url': ingestData.Bucket + '.s3.amazonaws.com/' + ingestData.objectKey,
'Codec': mediaAnalysis.Codec, 'resolution': mediaAnalysis.Resolution}
r = requests.post(url ='<mongobdAtlasUrlConnectStringHere>', data = dataNotFake)
return ingestData
what I am sending the Lambda is,
{
"bucketName": "<s3-bucket-name>",
"objectKey": "<video-file-name>"
}
edit:
the initial response
{
"errorMessage": "'str' object has no attribute 'Bucket'",
"errorType": "AttributeError",
"stackTrace": [
" File \"/var/task/mediaEvaluator.py\", line 107, in lambda_handler\n dataNotFake = { 's3url': ingestDataJson.Bucket + '.s3.amazonaws.com/' + ingestDataJson.objectKey, 'Codec': mediaAnalysisJson.Codec, 'resolution': mediaAnalysisJson.Resolution}\n"
]
}
and, then the logs
7c4Uwzk422qMqIJfcFOZr6kwDasq3AEIy%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FARAAGgw2MTYwODIzMjAyOTEiDHJGza1WClZUa%2BZKEyqwAWPyeYiNirreNeRtXlelQjCxUnEj3HMZiMF2UlPLpzwY3RRNo5LBpieIuIRUm7HtbWqXp19lDsUBHiGSoZqmNW5i5EN5nTPe6c6LNdKYFXYutvd4X1dsVEij8srY0DW%2FjBpiZxGt3DlhLWiDtoA8EjgXEe4JcpvU6Z9EpJeotjFhBzfe%2BM7xoPYE%2BoYS4ipx0nyntPQ4Qia1Cdh9LBwsHbcPL59JeI27lVmkggCFevZXMLqPzIEGOuABHPLi%2B3fu1bxwoDJYaA0HOwnAbF%2FncPMWpIR9NATDHyq%2B6BbaOxFAygyNXC%2FAjjqCEOezv1yfZ0VCMAP9i0Wi%2BBqgL8s4Qbuwk1PdgSfZdwqxrSOynSeX6s7Z5au9QYn%2BY%2F5upVr%2F5dt6Q8veRAWuqEQx4muzEix0jorBm4j1KAmuTYfv3A71Hv9YfhMmbR6h4XZv1U8nQpqNJNIJ%2FC%2BBBbRuXDWMhbfnK6IiXw9e3VWqQa7Esjj0WqHgOZ1wWGLZvqqy5Re%2Bm%2BF9eFdE%2F3mUv516aeU31eZ0gkHxnZGZ6HY%3D&Expires=1613960653', 'track': [{'#type': 'General', 'ID': '1', 'VideoCount': '1', 'MenuCount': '1', 'FileExtension': 'mpg?AWSAccessKeyId=ASIAY64K6FOR54JVBB5W&Signature=b16%2BkSWWYrrZvBlYA5tvs7DsqO4%3D&x-amz-security-token=IQoJb3JpZ2luX2VjEML%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCXVzLWVhc3QtMSJHMEUCIQCyP7t3a9Y6%2F4brzVhIOH5GEMpkargZlHCnX55tbiJKwQIgdBNqAwljhCiLZbf%2F7c4Uwzk422qMqIJfcFOZr6kwDasq3AEIy%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FARAAGgw2MTYwODIzMjAyOTEiDHJGza1WClZUa%2BZKEyqwAWPyeYiNirreNeRtXlelQjCxUnEj3HMZiMF2UlPLpzwY3RRNo5LBpieIuIRUm7HtbWqXp19lDsUBHiGSoZqmNW5i5EN5nTPe6c6LNdKYFXYutvd4X1dsVEij8srY0DW%2FjBpiZxGt3DlhLWiDtoA8EjgXEe4JcpvU6Z9EpJeotjFhBzfe%2BM7xoPYE%2BoYS4ipx0nyntPQ4Qia1Cdh9LBwsHbcPL59JeI27lVmkggCFevZXMLqPzIEGOuABHPLi%2B3fu1bxwoDJYaA0HOwnAbF%2FncPMWpIR9NATDHyq%2B6BbaOxFAygyNXC%2FAjjqCEOezv1yfZ0VCMAP9i0Wi%2BBqgL8s4Qbuwk1PdgSfZdwqxrSOynSeX6s7Z5au9QYn%2BY%2F5upVr%2F5dt6Q8veRAWuqEQx4muzEix0jorBm4j1KAmuTYfv3A71Hv9YfhMmbR6h4XZv1U8nQpqNJNIJ%2FC%2BBBbRuXDWMhbfnK6IiXw9e3VWqQa7Esjj0WqHgOZ1wWGLZvqqy5Re%2Bm%2BF9eFdE%2F3mUv516aeU31eZ0gkHxnZGZ6HY%3D&Expires=1613960653', 'Format': 'MPEG-TS', 'FileSize': '102004664', 'Duration': '200.236328125', 'OverallBitRate_Mode': 'CBR', 'OverallBitRate': '4075040', 'StreamSize': '7646822', 'extra': {'OverallBitRate_Precision_Min': '4075030', 'OverallBitRate_Precision_Max': '4075051', 'FileExtension_Invalid': 'ts m2t m2s m4t m4s tmf ts tp trp ty'}}, {'#type': 'Video', 'StreamOrder': '0-0', 'ID': '481', 'MenuID': '1', 'Format': 'AVC', 'Format_Profile': 'Main', 'Format_Level': '4.1', 'Format_Settings_CABAC': 'Yes', 'Format_Settings_RefFrames': '1', 'Format_Settings_GOP': 'M=1, N=15', 'CodecID': '27', 'Duration': '194.867', 'BitRate': '3873733', 'Width': '1280', 'Height': '720', 'Sampled_Width': '1280', 'Sampled_Height': '720', 'PixelAspectRatio': '1.000', 'DisplayAspectRatio': '1.778', 'ColorSpace': 'YUV', 'ChromaSubsampling': '4:2:0', 'BitDepth': '8', 'ScanType': 'Progressive', 'Delay': '10.000000', 'StreamSize': '94357842'}, {'#type': 'Menu', 'StreamOrder': '0', 'ID': '480', 'MenuID': '1', 'Format': 'AVC / KLV', 'Duration': '200.236328125', 'Delay': '0.001107222', 'List_StreamKind': '1 / ', 'List_StreamPos': '0 / ', 'extra': {'pointer_field': '0', 'section_length': '55'}}]}}
CORE:: Media Evaluator:: Parsed Media Analysis: {
"Wrapper": "MPEG-TSMain",
"Codec": "AVC",
"BitRate": "3873733",
"Resolution": "1280X720"
}
this is ingestData !!!!!!!!!!!!!!!!!!!!!!! {'MediaEvaluation': {'Wrapper': 'MPEG-TSMain', 'Codec': 'AVC', 'BitRate': '3873733', 'Resolution': '1280X720'}, 'AssetID': 'Day Flight', 'AssetUID': 'cb0651e1151f41a5a890425d41bda3cb', 'Bucket': 'video-uploads-94viwznlhm88', 'ObjectKey': 'Day Flight.mpg'}
this is mediaAnalysis !!!!!!!!!!!!!!!!!!!!!!! {'Wrapper': 'MPEG-TSMain', 'Codec': 'AVC', 'BitRate': '3873733', 'Resolution': '1280X720'}
[ERROR] AttributeError: 'str' object has no attribute 'Bucket'
Traceback (most recent call last):
  File "/var/task/mediaEvaluator.py", line 107, in lambda_handler
    dataNotFake = { 's3url': ingestDataJson.Bucket + '.s3.amazonaws.com/' + ingestDataJson.objectKey, 'Codec': mediaAnalysisJson.Codec, 'resolution': mediaAnalysisJson.Resolution}
END RequestId: bfcf3bb8-d709-44c5-9e42-8c7a6a31a879
REPORT RequestId: bfcf3bb8-d709-44c5-9e42-8c7a6a31a879 Duration: 6679.29 ms Billed Duration: 6680 ms Memory Size: 128 MB Max Memory Used: 104 MB Init Duration: 382.19 ms
I think here
dataNotFake = { 's3url': ingestData.Bucket + '.s3.amazonaws.com/' + ingestData.objectKey,
considering these
ingestData = {'MediaEvaluation': {'Wrapper': 'MPEG-TSMain',
'Codec': 'AVC',
'BitRate': '3873733',
'Resolution': '1280X720'},
'AssetID': 'Day Flight',
'AssetUID': 'cb0651e1151f41a5a890425d41bda3cb',
'Bucket': 'video-uploads-94viwznlhm88',
'ObjectKey': 'Day Flight.mpg'}
mediaAnalysis = {
'Wrapper': 'MPEG-TSMain', 'Codec': 'AVC', 'BitRate': '3873733', 'Resolution': '1280X720'}
You should use something like this
dataNotFake = {
's3url': f'{ingestData["Bucket"]}.s3.amazonaws.com/{ingestData["ObjectKey"]}',
'Codec': mediaAnalysis['Codec'],
'resolution': mediaAnalysis['Resolution']
}
I still cannot drill into ingestData, but I managed to avoid the issue by passing bucketName and objectName to create the s3 URL to link to the upload data in mongo and passing the whole mediaAnalysis to mongo.
dataNotFake = { "s3url": bucketName + '.s3.amazonaws.com/' + objectName, "mediaAnalysis": mediaAnalysis}

TypeError: can't concat str to bytes when converting Python 2 to 3 with Encryption Function

I am trying to transfer a code from python2 to 3. The problem happens. "pad * chr(pad)" looks like a string but when I print it out it shows . I dont know what it is really is.
<ipython-input-26-6c9679723473> in aesEncrypt(text, secKey)
43 def aesEncrypt(text, secKey):
44 pad = 16 - len(text) % 16
---> 45 text =text + pad * chr(pad)
46 encryptor = AES.new(secKey, 2, '0102030405060708')
47 ciphertext = encryptor.encrypt(text)
TypeError: can't concat str to bytes
I then tried encode() but it didnt work. I am wonder how can concat two string in python3.
<ipython-input-53-e9f33b00348a> in aesEncrypt(text, secKey)
43 def aesEncrypt(text, secKey):
44 pad = 16 - len(text) % 16
---> 45 text = text.encode("utf-8") + (pad * chr(pad)).encode("utf-8")
46 encryptor = AES.new(secKey, 2, '0102030405060708')
47 ciphertext = encryptor.encrypt(text)
AttributeError:'bytes' object has no attribute 'encode'
For the reference the original code is
作者:路人甲
链接:https://www.zhihu.com/question/31677442/answer/119959112
#encoding=utf8
import requests
from bs4 import BeautifulSoup
import re,time
import os,json
import base64
from Crypto.Cipher import AES
from pprint import pprint
Default_Header = {
'Referer':'http://music.163.com/',
'Host':'music.163.com',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.3.0',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Encoding':'gzip, deflate'
}
BASE_URL = 'http://music.163.com'
_session = requests.session()
_session.headers.update(Default_Header)
def getPage(pageIndex):
pageUrl = 'http://music.163.com/discover/playlist/?order=hot&cat=全部&limit=35&offset='+pageIndex
soup = BeautifulSoup(_session.get(pageUrl).content)
songList = soup.findAll('a',attrs = {'class':'tit f-thide s-fc0'})
for i in songList:
print i['href']
getPlayList(i['href'])
def getPlayList(playListId):
playListUrl = BASE_URL + playListId
soup = BeautifulSoup(_session.get(playListUrl).content)
songList = soup.find('ul',attrs = {'class':'f-hide'})
for i in songList.findAll('li'):
startIndex = (i.find('a'))['href']
songId = startIndex.split('=')[1]
readEver(songId)
def getSongInfo(songId):
pass
def aesEncrypt(text, secKey):
pad = 16 - len(text) % 16
text = text + pad * chr(pad)
encryptor = AES.new(secKey, 2, '0102030405060708')
ciphertext = encryptor.encrypt(text)
ciphertext = base64.b64encode(ciphertext)
return ciphertext
def rsaEncrypt(text, pubKey, modulus):
text = text[::-1]
rs = int(text.encode('hex'), 16)**int(pubKey, 16) % int(modulus, 16)
return format(rs, 'x').zfill(256)
def createSecretKey(size):
return (''.join(map(lambda xx: (hex(ord(xx))[2:]), os.urandom(size))))[0:16]
def readEver(songId):
url = 'http://music.163.com/weapi/v1/resource/comments/R_SO_4_'+str(songId)+'/?csrf_token='
headers = { 'Cookie': 'appver=1.5.0.75771;', 'Referer': 'http://music.163.com/' }
text = { 'username': '', 'password': '', 'rememberLogin': 'true' }
modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
nonce = '0CoJUm6Qyw8W8jud'
pubKey = '010001'
text = json.dumps(text)
secKey = createSecretKey(16)
encText = aesEncrypt(aesEncrypt(text, nonce), secKey)
encSecKey = rsaEncrypt(secKey, pubKey, modulus)
data = { 'params': encText, 'encSecKey': encSecKey }
req = requests.post(url, headers=headers, data=data)
total = req.json()['total']
if int(total) > 10000:
print songId,total
else:
pass
if __name__=='__main__':
for i in range(1,43):
getPage(str(i*35))
around line 85: encText = aesEncrypt(aesEncrypt(text, nonce), secKey)
aesEncrypt() is called first time with data as shown with subscript '_1' and 2nd time with data shown with subscript '_2'. Notice that the type of secKey changes from a string to a list of strings, and text from a string to a bytes object.
>>> secKey_1
'0CoJUm6Qyw8W8jud'
>>> secKey_2
['e4', '1a', '61', '7c', '1e', '62', '76', '5', '94', '62', '5a', '92', '9', 'fd', '2f', '4a']
>>>
>>> text_1
'{"username": "", "password": "", "rememberLogin": "true"}'
>>> text_2
b'qjTTWCVgh3v45StLOhGtNtY3zzoImIeGkRry1Vq0LzNSgr9hDHkkh19ujd+iqbvXnzjmHDhOIA5H0z/Wf3uU5Q=='
>>>
Thanks to #Todd. He has found the issue. aesEncrypt()has been called twice and it returns bytes while it receives str, which is acceptable in Python2 but not for Python3.
In the end, I change return ciphertext to return str(ciphertext).

Serialize Gtk TreeStore / ListStore using JSON

I made a new example which shows much better what I am trying to do. The new example gives the following ouput. Is there a way that the data can go into the respective store key (the {} brackets)?
{
"copy": [
[
[
5.0,
8.0,
9.0
]
],
[
[
4.0,
0.0,
1.0
]
]
],
"name": "dataset1",
"sets": [
{
"store": {},
"type": "vector"
},
{
"store": {},
"type": "vector"
}
]
}
New example
from gi.repository import Gtk
import json
import random
class Vector(object):
def __init__(self, data):
self.store = Gtk.ListStore(float, float, float)
self.store.append([data[0], data[1], data[2]])
self.type = "vector"
def return_data(self):
store_data = []
def iterate_over_data(model, path, itr):
row = model[path]
store_data.append([row[0], row[1], row[2]])
self.store.foreach(iterate_over_data)
return store_data
class DataSet(object):
def __init__(self, name):
self.name = name
self.sets = []
def add_vector(self):
data = [random.randint(0,9) for x in range(3)]
self.sets.append(Vector(data))
def to_json(self):
self.copy = []
for s in self.sets:
self.copy.append(s.return_data())
return json.dumps(self, default=lambda o: o.__dict__,
sort_keys=True, indent=4)
obj1 = DataSet("dataset1")
for x in range(2):
obj1.add_vector()
print(obj1.to_json())
Old example
I am currently figuring out how to serialize a Gtk ListStore that is nested in a Gtk TreeStore. I got a small example to work, but am not sure if this approach will scale for programs that have more data attached (For example the layer object could hold a color or a date of creation). Is there maybe another way to to this?
My current approach is to gather the data in list and dictionary form myself and then just create the JSON-dump. I have the feeling that this would be rather difficult to maintain if I need to attach 25 values to each layer-object.
from gi.repository import Gtk, Gdk
import json
import random
class LayerTreeView(Gtk.TreeView):
def __init__(self, store):
Gtk.TreeView.__init__(self, store)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Name", renderer, text=0)
self.append_column(column)
class DataTreeView(Gtk.TreeView):
def __init__(self, store):
Gtk.TreeView.__init__(self, store)
self.store = store
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Data", renderer, text=0)
self.append_column(column)
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="TreeView Serialize")
self.connect("delete-event", Gtk.main_quit)
self.set_border_width(10)
self.set_default_size(400, 300)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True)
self.add(vbox)
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
button = Gtk.Button("Cut")
button.connect("clicked", self.on_cut_clicked)
hbox.pack_start(button, True, True, 0)
button = Gtk.Button(stock=Gtk.STOCK_COPY)
button.connect("clicked", self.on_copy_clicked)
hbox.pack_start(button, True, True, 0)
button = Gtk.Button(stock=Gtk.STOCK_PASTE)
button.connect("clicked", self.on_paste_clicked)
hbox.pack_start(button, True, True, 0)
vbox.add(hbox)
self.layer_store = Gtk.TreeStore(str, object, object)
self.layer_view = LayerTreeView(self.layer_store)
self.layer_sw = Gtk.ScrolledWindow()
self.data_sw = Gtk.ScrolledWindow()
self.layer_sw.add(self.layer_view)
treebox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6, expand=True)
treebox.pack_start(self.layer_sw, True, True, 0)
treebox.pack_start(self.data_sw, True, True, 0)
vbox.add(treebox)
self.select = self.layer_view.get_selection()
self.select.connect("changed", self.on_selection_changed)
self.add_test_data()
def add_test_data(self):
for x in range(3):
data_store = Gtk.ListStore(str)
data_view = DataTreeView(data_store)
for y in range(5):
data_store.append([str(y+x)])
self.layer_store.append(None, ["Data {}".format(x), data_store, data_view])
def on_selection_changed(self, selection):
"""
When layer is switched load respective data
"""
model, treeiter = selection.get_selected()
if treeiter != None:
data_view = model[treeiter][2]
child = self.data_sw.get_child()
if child != None:
self.data_sw.remove(self.data_sw.get_child())
self.data_sw.add(data_view)
self.show_all()
def on_cut_clicked(self, button):
pass
def on_copy_clicked(self, button):
copy_list = ["safe-to-paste"]
data_dict = {}
for row in self.layer_store:
name = row[0]
data_obj = row[1]
value_list = []
for datarow in data_obj:
value = datarow[0]
value_list.append(value)
data_dict[name] = value_list
copy_list.append(data_dict)
data = json.dumps(copy_list)
self.clipboard.set_text(data, -1)
def on_paste_clicked(self, button):
paste_str = self.clipboard.wait_for_text()
try:
parse = json.loads(paste_str)
json_str = True
except:
json_str = False
if json_str is False:
return
keyword = parse[0]
if keyword != "safe-to-paste":
return
data_dict = parse[1]
for x in data_dict:
data_list = data_dict[x]
data_store = Gtk.ListStore(str)
data_view = DataTreeView(data_store)
for y in data_list:
data_store.append([str(y)])
self.layer_store.append(None, [x, data_store, data_view])
win = MainWindow()
win.show_all()
Gtk.main()
I have an improved version of your code with dict comprehension and #staticmethod that makes the signal callbacks more readable and shorter. Nevertheless, this does not really solve your problem as it still generates the json manually. If the ListStore gets more complex, it would probably be better to let the DataListStore class generate its own json with a corresponding method.
from gi.repository import Gtk, Gdk
import json
class LayerTreeView(Gtk.TreeView):
def __init__(self, store):
Gtk.TreeView.__init__(self, store)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Name", renderer, text=0)
self.append_column(column)
class DataTreeView(Gtk.TreeView):
def __init__(self):
Gtk.TreeView.__init__(self)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Data", renderer, text=0)
self.append_column(column)
class DataListStore(Gtk.ListStore):
#staticmethod
def from_json(*args, values=[]):
store = DataListStore(*args)
for value in values:
store.append((value,))
return store
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="TreeView Serialize")
self.connect("delete-event", Gtk.main_quit)
self.set_border_width(10)
self.set_default_size(400, 300)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True)
self.add(vbox)
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
button = Gtk.Button("Cut")
button.connect("clicked", self.on_cut_clicked)
hbox.pack_start(button, True, True, 0)
button = Gtk.Button(stock=Gtk.STOCK_COPY)
button.connect("clicked", self.on_copy_clicked)
hbox.pack_start(button, True, True, 0)
button = Gtk.Button(stock=Gtk.STOCK_PASTE)
button.connect("clicked", self.on_paste_clicked)
hbox.pack_start(button, True, True, 0)
vbox.add(hbox)
self.layer_store = Gtk.TreeStore(str, object)
self.layer_view = LayerTreeView(self.layer_store)
self.data_view = DataTreeView()
layer_sw = Gtk.ScrolledWindow()
layer_sw.add(self.layer_view)
data_sw = Gtk.ScrolledWindow()
data_sw.add(self.data_view)
treebox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6, expand=True)
treebox.pack_start(layer_sw, True, True, 0)
treebox.pack_start(data_sw, True, True, 0)
vbox.add(treebox)
select = self.layer_view.get_selection()
select.connect("changed", self.on_selection_changed)
self.add_test_data()
def add_test_data(self):
for x in range(3):
data_list = [str(y+x) for y in range(5)]
self.layer_store.append(None, ["Data {}".format(x), data_list])
def on_selection_changed(self, selection):
"""
When layer is switched load respective data
"""
model, treeiter = selection.get_selected()
if treeiter != None:
self.data_view.set_model(
DataListStore.from_json(str, values=model[treeiter][1])
)
def on_cut_clicked(self, button):
pass
def on_copy_clicked(self, button):
copy_list = [
'safe-to-paste',
{row[0]: row[1] for row in self.layer_store},
]
data = json.dumps(copy_list)
self.clipboard.set_text(data, -1)
def on_paste_clicked(self, button):
paste_str = self.clipboard.wait_for_text()
try:
parse = json.loads(paste_str)
except:
return
if parse[0] != "safe-to-paste":
return
data_dict = parse[1]
for x in data_dict:
self.layer_store.append(None, [x, data_dict[x]])
win = MainWindow()
win.show_all()
Gtk.main()