10

Teams seems to lack any native way of mirroring files to a shared directory. I'm Trying use Python (or another language but python preferred!) to either:

a. Directly pull from microsoft teams into memory using Python to process with Pandas

b. Copy files from teams into a shared network folder (which Python could then read in)

I found this but can't get it to work with teams - the teams URLs don't look anything like these do. How to read SharePoint Online (Office365) Excel files in Python with Work or School Account?

It seems close to what I want to do though. I also found "pymsteams" on PyPi repository. https://pypi.org/project/pymsteams/ which just seems to let you send messages to Teams and nothing else? unless I misunderstand something.

https://pypi.org/project/Office365-REST-Python-Client/

https://pypi.org/project/pymsteams/

from office365.runtime.auth.authentication_context
import AuthenticationContext
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.file import File 

url = 'https://teams.microsoft.com/l/file'
username = 'myusername'
password = 'mypassword'
relative_url ='myurl'

ctx_auth = AuthenticationContext(url)
ctx_auth.acquire_token_for_user(username, password)

Trying to run the above code gives AttributeError: 'NoneType' object has no attribute 'text'

Full stack trace:

runfile('H:/repos/foo/untitled0.py', wdir='H:/repos/foo')
Traceback (most recent call last):

  File "<ipython-input-35-314ab7dc63c9>", line 1, in <module>
    runfile('H:/repos/foo/untitled0.py', wdir='H:/foo/image_ai')

  File "C:\ProgramData\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 786, in runfile
    execfile(filename, namespace)

  File "C:\ProgramData\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "H:/repos/image_ai/untitled0.py", line 10, in <module>
    ctx_auth.acquire_token_for_user(username, password)

  File "C:\ProgramData\Anaconda3\lib\site-packages\office365\runtime\auth\authentication_context.py", line 18, in acquire_token_for_user
    return self.provider.acquire_token()

  File "C:\ProgramData\Anaconda3\lib\site-packages\office365\runtime\auth\saml_token_provider.py", line 57, in acquire_token
    self.acquire_service_token(options)

  File "C:\ProgramData\Anaconda3\lib\site-packages\office365\runtime\auth\saml_token_provider.py", line 88, in acquire_service_token
    token = self.process_service_token_response(response)

  File "C:\ProgramData\Anaconda3\lib\site-packages\office365\runtime\auth\saml_token_provider.py", line 119, in process_service_token_response
    return token.text

AttributeError: 'NoneType' object has no attribute 'text'
  • can you show the entire stack trace? – ocket8888 Jul 18 '19 at 23:11
  • Thanks, I added the full stack trace. – Christopher Klapperich Jul 19 '19 at 00:18
  • looks like an authentication error to me – ocket8888 Jul 19 '19 at 00:35
  • 1
    All the Microsoft Teams files are stored on SharePoint so you should be using Microsoft Graph APIs for [OneDrive and SharePoint](https://learn.microsoft.com/en-us/onedrive/developer/rest-api/?view=odsp-graph-online). Here is the documentation on [Send and receive files through your bot](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/bots/bots-files#using-the-microsoft-graph-apis). – Wajeed Shaikh Jul 19 '19 at 06:31
  • The bots only work with personal chats, not files posted in channels. – Christopher Klapperich Jul 19 '19 at 13:21
  • [Using the Microsoft Graph APIs](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/bots/bots-files#using-the-microsoft-graph-apis) works in all Teams scopes. – Wajeed Shaikh Jul 23 '19 at 02:43
  • @ChristopherKlapperich Have you got this working? – davidbilla Apr 27 '20 at 15:50
  • @davidbilla Basically yes just not as well as I like. The python script MUST be running on windows, Teams and one drive MUST be installed. You can use sharepoint / onedrive to "mirror" a Teams folder / sharepoint folder to your hard drive (turns out, they're the same thing. Any file added to teams is basically added to sharepoint automagically. Just different frontends.) Now use python to read from the filepath like ANY other filepath. Easy as. – Christopher Klapperich Apr 28 '20 at 03:05
  • @davidbilla I'm certain there are other ways to access sharepoint files programatically too, if I were smarter. ;) in teams, you can right click a file and 'open in sharepoint' or 'view in sharepoint, and it'll bring up the webbrowser. Might get you started in that direction. – Christopher Klapperich Apr 28 '20 at 03:10
  • @ChristopherKlapperich see https://stackoverflow.com/a/59981556/6715335 It's not the solution, but it could help you to download a file – pareyesv Jul 03 '20 at 09:47
  • If you're looking for a tool.... you might try rclone, which supports numerous cloud providers, including OneDrive Personal or Business, as well as Sharepoint. https://rclone.org/onedrive/. Setup looks kinda painful initially (getting the OAuth stuff set up), but if you need to synchronise content, I've used it well for other types of remote providers, such as WebDAV. – Cameron Kerr Nov 26 '21 at 10:14

1 Answers1

7

I've managed to get it working using the Office-365-REST-Python-Client you linked.

If you're using SharePoint Online, you'll need to get an App-Only principle set up and connect using the acquire_token_for_app function instead of acquire_token_for_user, then passing a client_id and client_secret instead of username & password.

from office365.runtime.auth.authentication_context import AuthenticationContext
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.file import File

client_id = 'yourclientid'
client_secret = 'yourclientsecret'
url = 'https://yoursharepointsite.com/teams/yourteam'
relative_url = '/teams/yourteam/Shared%20Documents/yourteamschannel/yourdoc.extension'
  
ctx_auth = AuthenticationContext(url)
if ctx_auth.acquire_token_for_app(client_id, client_secret):
    ctx = ClientContext(url, ctx_auth)
    with open(filename, 'wb') as output_file:
        response = File.open_binary(ctx, relative_url)
        output_file.write(response.content) 
else:
    print(ctx_auth.get_last_error())

This should download your file to a local drive (specified via the filename variable) and you can then load into pandas etc to process

james_goodall
  • 71
  • 1
  • 2