How to get the plaintext of an email message in dart/flutter - gmail-api

Using the google apis flutter package, I get back the email message object. For example, snippet is a property of this object. It returns a short plaintext of the email message. I would like to parse the email to return a plaintext. How do I parse the email message?
final list = await gmailApi.users.messages.list("me", maxResults: 10, q:"subject:receipt",);
for (var message in list.messages!) {
final m = await gmailApi.users.messages
.get(_currentUser!.id, message.id ?? "", format: "full");
final decoded = base64Url.decode(m.payload?.body?.data ?? "");
utf8.decode(decoded); // supposed to return plaintext (like m.snippet does) not html
}

Related

Discordpy Mod Logs Command

I'm trying to make a mod logs, I'm not really good at this, I scripted myself and kinda worked but it didn't worked. So basically my plan is when someone types .modlogs #channel, bot is gonna get the channel id and type it to json file with guild id, i made that it works very well I'm stuck on getting key info from json file, im printing the values and they are same.
#commands.command(aliases=['purge'])
#commands.guild_only()
#commands.has_permissions(manage_messages=True)
async def clear(self,ctx, arg: int = None):
if arg is None:
await ctx.send(':x: You need to state a value!')
else:
with open('./logs.json', 'r') as f:
logsf = json.load(f)
if ctx.guild.id in logsf:
embedv = discord.Embed(color = discord.Colour.random())
embedv.add_field(name='Event Type:', value="Clear")
embedv.add_field(name='Channel:', value= ctx.channel)
embedv.add_field(name='Moderator:', value=ctx.message.author)
embedv.footer(text='Epifiz Logging')
schannel = commands.get_channel(logsf[ctx.guild.id])
await ctx.channel.purge(limit=arg)
await discord.schannel.send(embed=embedv)
await ctx.send('Done')
elif ctx.guild.id not in logsf:
await ctx.channel.purge(limit=arg)
await ctx.send(':white_check_mark: Successfully cleared {} messages.'.format(arg))
also my json file:
{
"838355243817369620": 853297044922564608
}
Also guild id is on json file, its not wrong.
Output
You made multiple mistakes in your code. The reason why you are getting the error is because this line here if ctx.guild.id in logsf: returns False even if the guild's id is in your JSON file. Here is why:
logsf = json.load(f) returns a dictionary. You'll get {"838355243817369620": 853297044922564608} it's unclear whether 838355243817369620 or 853297044922564608 is your guild id but think of it this way:
s = {1:2}
2 in s return False
and the second mistake is inserting "838355243817369620" as a str rather than an int like this 838355243817369620.
The solution is to use list() as follow if ctx.guild.id in list(logsf): and to insert "838355243817369620" as an int in your JSON file so it looks like this:
{
838355243817369620: 853297044922564608
}
#rather than this
{
"838355243817369620": 853297044922564608
}
value in embeds accepts str not discord objects. Use f"{input}" rather than the object as an input.
embedv.add_field(name='Channel:', value= f"{ctx.channel}")
embedv.add_field(name='Moderator:', value=f"{ctx.message.author}")
await schannel.send(embed=embedv) rather than await discord.schannel.send(embed=embedv)
From this line schannel = commands.get_channel(logsf[ctx.guild.id]) I can assume that 838355243817369620 is your server's id. So, I think that you can use:
if ctx.guild.id in logsf.keys(): instead of if ctx.guild.id in list(logsf):
and make sure to convert its keys values into int rather than str to make it work.

Convert Image from Buffer to display in Frontend (Flutter)

I have a backend based on NodeJS and using mongodb as the database. Images with the field name photo is saved as object Type Buffer. I have successfully sent Images from the app using form data but I am not able to display the image in frontend.
This is the function used to get the data from API
Future<User> userWithId() async {
User result;
try {
final response = await http.get(
'api link',
headers: <String, String>{
'Authorization': 'Bearer $token',
},
);
if (response.statusCode == 200) {
result = User.fromJson(jsonDecode(response.body));
}
} catch (e) {
print(e.toString());
}
return result;
}
This is the fromJson function of the class User. The photo field here returns the image as buffer.
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['_id'] as String ?? "",
email: json['email'] as String ?? "",
// profilePhoto: json["photo"] ?? null,
// profilePhoto: base64.encode(jsonDecode(json["photo"])) ?? null,
);
}
This is the data from the photo field
This is the data from MongoDB database
For those who are facing this issue as well, this is a multi-part problem:
Converting List to List.
Using converted List to read/display image.
In OP's case, to get buffer List would be profilePhoto: json["photo"]["data"]["data"].
For step 1, To convert List to List:
List<dynamic> bufferDynamic = profilePhoto: json["photo"]["data"]["data"];
List<int> bufferInt = buffer.map((e) => e as int).toList();
For step 2 as some have already mention, use Image.memory class provided by Flutter.
Image.memory(Uint8List.fromList(bufferInt))
Hope this helps for those who need to read/display image from buffer. (:
you can use base64Decode method from dart:convert
store your image binary in string format:
factory User.fromJson(Map<String, dynamic> json) {
return User(
...
profilePhoto: json["photo"] ?? null,
...
);
}
and use the following code in UI:
Image.memory(base64Decode(user.profilePhoto))
also, don't forget to add an if statement to check if the photo is null or not
Hope, it helps
json['photo']['data']['data'];
By doing this you are getting this error List' is not a subtype of type 'String'. So may be your return type for profilePhoto is String. Change it to dynamic then try again.
Thanks to the great article bellow explaining about bytes in dart, you can convert your response data which is as List of integers, to Uint8List data type and pass it to Image.memory to render image.
Image.memory(Uint8List.fromList(// pass image data array here));
https://medium.com/flutter-community/working-with-bytes-in-dart-6ece83455721
Try like this
List<int> imageData = user.profilePhoto['data'] as List<int>
////
Image.memory(Uint8List.fromList(imageData));
Image type
You should modify your class User, currently you have something like:
class User {
final String id;
final String email;
final ? profilePhoto
}
I am not sure which type you are currently using but you need to change it accordingly to the data you get in your response. Your image is, in your computer, a list of bytes (uint8, meaning unsigned integer of 8 bits, so 1 byte), ranging from 0 to 255 in value (0 to 0xFF).
Images header
You can read about EXIF to understand better how the standard specifies the formats for images
Every JPEG file starts from binary value '0xFFD8', ends by binary value '0xFFD9'.
The first eight bytes of a PNG file always contain the following (decimal) values: 137 80 78 71 13 10 26 10
Fix
Change the type of your profilePhoto to Uint8List, full code:
class User {
final String id;
final String email;
String profilePhoto // I don't know which type you use
User({this.id, this.email, this.profilePhoto});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
id: json['_id'] as String ?? "",
email: json['email'] as String ?? "",
profilePhoto: json["photo"] ?? null,
);
}
}
And then load the image in your widget with Image.memory while being cautious as its value could be null:
return user.profilePhoto != null ? Image.memory(user.profilePhoto) : Container();
NB: Image.memory is a shorthand of an Image widget backed by MemoryImage.

EOL while scanning string literal, Unknown Emoji

Command raised an exception: HTTP Exception: 400 Bad Request (error code: 10014): Unknown Emoji and EOL while scanning string literal are the 2 errors I have having while trying to add a reaction to an embed msg with python (discord.py)
Here is the full code, the problem is around the exclamation mark
#client.command()
async def ask(ctx, *, question=None):
try:
page = urllib.request.urlopen(f'http://askdiscord.netlify.app/b/{ctx.message.author.id}.txt')
if page.read():
embed = discord.Embed(color=0xFF5555, title="Error", description="You are banned from using AskDiscord!")
await ctx.send(embed=embed, content=None)
return
except urllib.error.HTTPError:
pass
if question:
channel = client.get_channel(780111762418565121)
embed = discord.Embed(color=0x7289DA, title=question, description=f"""
Question asked by {ctx.message.author} ({ctx.message.author.id}). If you think this question violates our rules, click ❗️ below this message to report it
""")
embed.set_footer(text=f"{ctx.message.author.id}")
message = await channel.send(content=None, embed=embed)
for emoji in ('❗️'):
await message.add_reaction(emoji)
for emoji in ('🗑'):
await message.add_reaction(emoji)
embed = discord.Embed(color=0x55FF55, title="Question asked", description="Your question has been send! You can view in the answer channel in the [AskDiscord server](https://discord.gg/KwUmPHKmwq)")
await ctx.send(content=None, embed=embed)
else:
embed = discord.Embed(title="Error", description=f"Please make sure you ask a question...", color=0xFF5555)
await ctx.send(content=None, embed=embed)
Tuple need to have a , at the end if there is only one element in it else its considered as a string in your case change ('❗️') to ('❗️',)

Gmail API .NET: Get full message

How do I get the full message and not just the metadata using gmail api?
I have a service account and I am able to retrieve a message but only in the metadata, raw and minimal formats. How do I retrieve the full message in the full format? The following code works fine
var request = service.Users.Messages.Get(userId, messageId);
request.Format = UsersResource.MessagesResource.GetRequest.FormatEnum.Metadata;
Message message = request.Execute();
However, when I omit the format (hence I use the default format which is FULL) or I change the format to UsersResource.MessagesResource.GetRequest.FormatEnum.Full
I get the error: Metadata scope doesn't allow format FULL
I have included the following scopes:
https://www.googleapis.com/auth/gmail.readonly,
https://www.googleapis.com/auth/gmail.metadata,
https://www.googleapis.com/auth/gmail.modify,
https://mail.google.com/
How do I get the full message?
I had to remove the scope for the metadata to be able to get the full message format.
The user from the SO post have the same error.
Try this out first.
Go to https://security.google.com/settings/security/permissions
Choose the app you are working with.
Click Remove > OK
Next time, just request exactly which permissions you need.
Another thing, try to use gmailMessage.payload.parts[0].body.dataand to decode it into readable text, do the following from the SO post:
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
System.out.println(StringUtils.newStringUtf8(Base64.decodeBase64(gmailMessage.payload.parts[0].body.data)));
You can also check this for further reference.
try something like this
public String getMessage(string user_id, string message_id)
{
Message temp =service.Users.Messages.Get(user_id,message_id).Execute();
var parts = temp.Payload.Parts;
string s = "";
foreach (var part in parts) {
byte[] data = FromBase64ForUrlString(part.Body.Data);
s += Encoding.UTF8.GetString(data);
}
return s
}
public static byte[] FromBase64ForUrlString(string base64ForUrlInput)
{
int padChars = (base64ForUrlInput.Length % 4) == 0 ? 0 : (4 - (base64ForUrlInput.Length % 4));
StringBuilder result = new StringBuilder(base64ForUrlInput, base64ForUrlInput.Length + padChars);
result.Append(String.Empty.PadRight(padChars, '='));
result.Replace('-', '+');
result.Replace('_', '/');
return Convert.FromBase64String(result.ToString());
}

oauth problem( app engine)

i am trying to pull user's documents data from google docs using oauth,
but i cannot understand how to do it
- what's the purpose of oauth_verifier
- how to get the access token secret?
- if i try to use DocsService below, then i have a "server error"
- is there a clear tutorial for this? i cannot find any atm..
String oauth_verifier = req.getParameter("oauth_verifier");
String oauth_token = req.getParameter("oauth_token");
String oauthtokensecret = req.getParameter("oauth_token_secret");
GoogleOAuthParameters oauthparam = new GoogleOAuthParameters();
oauthparam.setOAuthConsumerKey("consumer key");
oauthparam.setOAuthConsumerSecret("secret");
oauthparam.setOAuthToken(oauth_token);
oauthparam.setOAuthTokenSecret(oauthtokensecret);
oauthparam.setOAuthVerifier(oauth_verifier);
OAuthHmacSha1Signer signer = new OAuthHmacSha1Signer();
GoogleOAuthHelper oauthhelper = new GoogleOAuthHelper(signer);
String accesstoken = "";
String accesstokensecret = "";
try {
oauthhelper.getUnauthorizedRequestToken(oauthparam);
accesstoken = oauthhelper.getAccessToken(oauthparam);
accesstokensecret = oauthparam.getOAuthTokenSecret();
// DocsService client = new DocsService("yourCompany-YourAppName-v1");
...
These may not be what you are looking for, since they are OAuth-specific and not google-related, but I found these "Getting started" articles very helpful:
http://oauth.net/documentation/getting-started
Turns out that I need to get the oauth_token_secret and reuse it later.
So (before redirecting user to google login page)
oauthhelper.getUnauthorizedRequestToken(oauthparam);
requesturl = oauthhelper.createUserAuthorizationUrl(oauthparam);
OAuthTokenSecret.tokenSecret = oauthparam.getOAuthTokenSecret();
resp.sendRedirect(requesturl);
Then after the user grants access and we have been redirected to oauth_callback url:
oauthparam.setOAuthToken(oauthtoken);
oauthparam.setOAuthVerifier(oauthverifier);
oauthparam.setOAuthTokenSecret(OAuthTokenSecret.tokenSecret);
oauthhelper.getAccessToken(oauthparam); // access token and access token secret are saved in oauthparam.
// access google service..
GoogleService googleService = new GoogleService( "cp", "test222");
googleService.setOAuthCredentials(oauthparam, signer);
BaseFeed resultFeed = googleService.getFeed(feedUrl, Feed.class);

Resources