euler314 commited on
Commit
7cf4e47
·
verified ·
1 Parent(s): 2562720

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -59
app.py CHANGED
@@ -1,92 +1,113 @@
1
- from flask import Flask, render_template, request, jsonify, session
2
- from google_auth_oauthlib.flow import InstalledAppFlow
3
  from google.oauth2.credentials import Credentials
4
  from googleapiclient.discovery import build
5
  from googleapiclient.http import MediaIoBaseUpload
6
- from google.auth.transport.requests import Request
7
- import pickle
8
  import os
9
  import io
10
  import datetime
11
 
12
  app = Flask(__name__)
13
- app.secret_key = 'your-secret-key' # Change this to a random secure string
14
-
15
- # If modifying these scopes, delete the file token.pickle.
16
- SCOPES = ['https://www.googleapis.com/auth/spreadsheets',
17
- 'https://www.googleapis.com/auth/drive.file']
18
 
19
  SPREADSHEET_ID = '1rcIJflbC1VIc70F6dnASLFvGQ90TXHhCx0iyxsXR7Ww'
20
  FOLDER_ID = '1brmLNqOMCvRS0TDY6ECHvIBmlRx8pcPz'
21
 
22
- def get_google_auth():
23
- creds = None
24
- # The file token.pickle stores the user's access and refresh tokens
25
- if os.path.exists('token.pickle'):
26
- with open('token.pickle', 'rb') as token:
27
- creds = pickle.load(token)
28
-
29
- # If there are no (valid) credentials available, let the user log in.
30
- if not creds or not creds.valid:
31
- if creds and creds.expired and creds.refresh_token:
32
- creds.refresh(Request())
33
- else:
34
- flow = InstalledAppFlow.from_client_secrets_file(
35
- 'client_secret.json', SCOPES)
36
- creds = flow.run_local_server(port=0)
37
- # Save the credentials for the next run
38
- with open('token.pickle', 'wb') as token:
39
- pickle.dump(creds, token)
40
-
41
- return creds
42
 
43
- # HTML template (same as before)
44
  HTML_TEMPLATE = '''
45
  <!DOCTYPE html>
46
  <html>
47
  <head>
48
  <title>Purchase Record Form</title>
 
49
  <style>
50
- body { font-family: Arial, sans-serif; margin: 20px; max-width: 600px; margin: 0 auto; }
51
- .form-group { margin-bottom: 15px; }
52
- label { display: block; margin-bottom: 5px; }
53
- input { width: 100%; padding: 8px; margin-bottom: 10px; border: 1px solid #ddd; border-radius: 4px; }
54
- button { background-color: #4CAF50; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
55
- button:hover { background-color: #45a049; }
56
- #status { margin-top: 20px; padding: 10px; display: none; }
57
- .success { background-color: #dff0d8; color: #3c763d; }
58
- .error { background-color: #f2dede; color: #a94442; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  </style>
60
  </head>
61
  <body>
62
- <h2>Purchase Record Form</h2>
63
  <form id="purchaseForm">
64
  <div class="form-group">
65
- <label for="name">Name:</label>
66
  <input type="text" id="name" name="name" required>
67
  </div>
68
 
69
  <div class="form-group">
70
- <label for="studentId">Student ID (學號):</label>
71
  <input type="text" id="studentId" name="studentId" required>
72
  </div>
73
 
74
  <div class="form-group">
75
- <label for="product">Product:</label>
76
  <input type="text" id="product" name="product" required>
77
  </div>
78
 
79
  <div class="form-group">
80
- <label for="cost">Cost:</label>
81
  <input type="number" id="cost" name="cost" required>
82
  </div>
83
 
84
  <div class="form-group">
85
- <label for="receipt">Receipt (發票):</label>
86
- <input type="file" id="receipt" name="receipt" required>
87
  </div>
88
 
89
- <button type="submit">Submit</button>
90
  </form>
91
  <div id="status"></div>
92
 
@@ -96,7 +117,7 @@ HTML_TEMPLATE = '''
96
 
97
  const status = document.getElementById('status');
98
  status.style.display = 'block';
99
- status.textContent = 'Submitting...';
100
  status.className = '';
101
 
102
  const formData = new FormData(e.target);
@@ -111,15 +132,15 @@ HTML_TEMPLATE = '''
111
 
112
  if (result.success) {
113
  status.className = 'success';
114
- status.textContent = result.message;
115
  e.target.reset();
116
  } else {
117
  status.className = 'error';
118
- status.textContent = result.message;
119
  }
120
  } catch (error) {
121
  status.className = 'error';
122
- status.textContent = 'Error submitting form';
123
  }
124
  });
125
  </script>
@@ -129,26 +150,24 @@ HTML_TEMPLATE = '''
129
 
130
  @app.route('/')
131
  def index():
132
- return HTML_TEMPLATE
133
 
134
  @app.route('/submit', methods=['POST'])
135
  def submit():
136
  try:
137
- # Get form data
138
  name = request.form['name']
139
  student_id = request.form['studentId']
140
  product = request.form['product']
141
  cost = request.form['cost']
142
  file = request.files['receipt']
143
 
144
- # Get Google credentials
145
- creds = get_google_auth()
146
 
147
  # Upload file to Drive
148
- drive_service = build('drive', 'v3', credentials=creds)
149
 
150
  file_metadata = {
151
- 'name': file.filename,
152
  'parents': [FOLDER_ID]
153
  }
154
 
@@ -167,7 +186,7 @@ def submit():
167
  file_url = uploaded_file.get('webViewLink', '')
168
 
169
  # Update Google Sheet
170
- sheets_service = build('sheets', 'v4', credentials=creds)
171
 
172
  timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
173
  ip_address = request.remote_addr
@@ -188,5 +207,4 @@ def submit():
188
  return jsonify({'success': False, 'message': f'Error: {str(e)}'})
189
 
190
  if __name__ == '__main__':
191
- os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' # Only for development
192
  app.run(host='0.0.0.0', port=7860)
 
1
+ from flask import Flask, request, jsonify, render_template_string
 
2
  from google.oauth2.credentials import Credentials
3
  from googleapiclient.discovery import build
4
  from googleapiclient.http import MediaIoBaseUpload
 
 
5
  import os
6
  import io
7
  import datetime
8
 
9
  app = Flask(__name__)
 
 
 
 
 
10
 
11
  SPREADSHEET_ID = '1rcIJflbC1VIc70F6dnASLFvGQ90TXHhCx0iyxsXR7Ww'
12
  FOLDER_ID = '1brmLNqOMCvRS0TDY6ECHvIBmlRx8pcPz'
13
 
14
+ # OAuth 2.0 credentials
15
+ CREDENTIALS = {
16
+ 'token': None,
17
+ 'refresh_token': None,
18
+ 'token_uri': 'https://oauth2.googleapis.com/token',
19
+ 'client_id': os.environ.get('GOOGLE_CLIENT_ID'),
20
+ 'client_secret': os.environ.get('GOOGLE_CLIENT_SECRET'),
21
+ 'scopes': ['https://www.googleapis.com/auth/spreadsheets',
22
+ 'https://www.googleapis.com/auth/drive.file']
23
+ }
 
 
 
 
 
 
 
 
 
 
24
 
 
25
  HTML_TEMPLATE = '''
26
  <!DOCTYPE html>
27
  <html>
28
  <head>
29
  <title>Purchase Record Form</title>
30
+ <meta charset="UTF-8">
31
  <style>
32
+ body {
33
+ font-family: Arial, sans-serif;
34
+ max-width: 600px;
35
+ margin: 20px auto;
36
+ padding: 20px;
37
+ }
38
+ .form-group {
39
+ margin-bottom: 20px;
40
+ }
41
+ label {
42
+ display: block;
43
+ margin-bottom: 8px;
44
+ font-weight: bold;
45
+ }
46
+ input {
47
+ width: 100%;
48
+ padding: 10px;
49
+ border: 1px solid #ddd;
50
+ border-radius: 4px;
51
+ font-size: 16px;
52
+ }
53
+ button {
54
+ background-color: #4CAF50;
55
+ color: white;
56
+ padding: 12px 24px;
57
+ border: none;
58
+ border-radius: 4px;
59
+ cursor: pointer;
60
+ font-size: 16px;
61
+ width: 100%;
62
+ }
63
+ button:hover {
64
+ background-color: #45a049;
65
+ }
66
+ #status {
67
+ margin-top: 20px;
68
+ padding: 15px;
69
+ border-radius: 4px;
70
+ display: none;
71
+ }
72
+ .success {
73
+ background-color: #dff0d8;
74
+ color: #3c763d;
75
+ }
76
+ .error {
77
+ background-color: #f2dede;
78
+ color: #a94442;
79
+ }
80
  </style>
81
  </head>
82
  <body>
83
+ <h2>購買記錄表單 Purchase Record Form</h2>
84
  <form id="purchaseForm">
85
  <div class="form-group">
86
+ <label for="name">姓名 Name:</label>
87
  <input type="text" id="name" name="name" required>
88
  </div>
89
 
90
  <div class="form-group">
91
+ <label for="studentId">學號 Student ID:</label>
92
  <input type="text" id="studentId" name="studentId" required>
93
  </div>
94
 
95
  <div class="form-group">
96
+ <label for="product">購買商品 Product:</label>
97
  <input type="text" id="product" name="product" required>
98
  </div>
99
 
100
  <div class="form-group">
101
+ <label for="cost">金額 Cost:</label>
102
  <input type="number" id="cost" name="cost" required>
103
  </div>
104
 
105
  <div class="form-group">
106
+ <label for="receipt">發票 Receipt:</label>
107
+ <input type="file" id="receipt" name="receipt" accept="image/*,.pdf" required>
108
  </div>
109
 
110
+ <button type="submit">提交 Submit</button>
111
  </form>
112
  <div id="status"></div>
113
 
 
117
 
118
  const status = document.getElementById('status');
119
  status.style.display = 'block';
120
+ status.textContent = '提交中... Submitting...';
121
  status.className = '';
122
 
123
  const formData = new FormData(e.target);
 
132
 
133
  if (result.success) {
134
  status.className = 'success';
135
+ status.textContent = '提交成功! ' + result.message;
136
  e.target.reset();
137
  } else {
138
  status.className = 'error';
139
+ status.textContent = '錯誤:' + result.message;
140
  }
141
  } catch (error) {
142
  status.className = 'error';
143
+ status.textContent = '提交錯誤 Error submitting form';
144
  }
145
  });
146
  </script>
 
150
 
151
  @app.route('/')
152
  def index():
153
+ return render_template_string(HTML_TEMPLATE)
154
 
155
  @app.route('/submit', methods=['POST'])
156
  def submit():
157
  try:
 
158
  name = request.form['name']
159
  student_id = request.form['studentId']
160
  product = request.form['product']
161
  cost = request.form['cost']
162
  file = request.files['receipt']
163
 
164
+ credentials = Credentials.from_authorized_user_info(CREDENTIALS)
 
165
 
166
  # Upload file to Drive
167
+ drive_service = build('drive', 'v3', credentials=credentials)
168
 
169
  file_metadata = {
170
+ 'name': f"{student_id}_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}_{file.filename}",
171
  'parents': [FOLDER_ID]
172
  }
173
 
 
186
  file_url = uploaded_file.get('webViewLink', '')
187
 
188
  # Update Google Sheet
189
+ sheets_service = build('sheets', 'v4', credentials=credentials)
190
 
191
  timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
192
  ip_address = request.remote_addr
 
207
  return jsonify({'success': False, 'message': f'Error: {str(e)}'})
208
 
209
  if __name__ == '__main__':
 
210
  app.run(host='0.0.0.0', port=7860)