BluePigeon
BluePigeon

Reputation: 1812

discord.py - Sending file without creating one on my computer?

So, I have a JSON file, let's call it my_file.json, that contains some information:

[
   {
      "user": 0,
      "infos": []
   },
   {
      "user": 1,
      "infos": []
   }
]

On my BOT, I want to create a function to access the "infos" of a user id:

import json

@bot.command()
async def getinfo(ctx, *, user_id):
    user_id = int(user_id)
    with open("my_file.json") as f:
        for _ in json.load(f):
            if _["user"] == user_id:
                # HERE I WANT TO SEND THE CONTENTS OF "infos" OF THE 
                # CORRESPONDING USER ID IN A FILE, EACH LIST ITEM SEPERATED BY 
                # A NEWLINE

So I want the BOT to send the file containing all the items of the "infos" list of the corresponding user id, each of them separated by a newline, but I don't want the file to be saved on my computer. Is this possible?

Upvotes: 1

Views: 1966

Answers (2)

Inspi
Inspi

Reputation: 599

It is possible!

The key is using StringIO instead of a regular file.

Solution

from os import linesep
import io
import json
from discord import File


@bot.command()
async def getinfo(ctx, *, user_id):
    user_id = int(user_id)
    with open("my_file.json") as fdata:
        for _ in json.load(fdata):
            if _["user"] == user_id:
                f = io.StringIO(linesep.join(_["info"]))
                await ctx.channel.send(content="info", file=File(fp=f, filename="user_info.txt"))

Sidenotes

Your data structure might not be the right one, if you can organize your data this way in the json file:

{
    "0": {"info": []},
    "1": {"info": []},
    ...
}

Then the solution to your problem is both easier to code and faster to run, because by putting your users in a dictionary indexed by their IDs you won't have to iterate over a list to find the user you want:

from os import linesep
import io
import json
from discord import File


@bot.command()
async def getinfo(ctx, *, user_id):
    with open("my_file.json") as fdata:
        users = json.load(fdata)
        if user_id in users:
            f = io.StringIO(linesep.join(users[user_id]["info"]))
            await ctx.channel.send(content="info", file=File(fp=f, filename="user_info.txt"))

EDIT1: to use string as keys instead of int in the sidenote solution

EDIT2: added \r\n to have functional newlines on Windows

EDIT3: now using os.linesep to get functional line breaks on every OS

Upvotes: 2

Alex R
Alex R

Reputation: 77

I believe StringIO is what you are looking for.

Examples: python PIL image how to save image to a buffer so can be used later?

Manual: https://docs.python.org/2/library/stringio.html

Upvotes: 2

Related Questions