about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lunatic.cpp191
1 files changed, 109 insertions, 82 deletions
diff --git a/lunatic.cpp b/lunatic.cpp index 5dd198c..daebc73 100644 --- a/lunatic.cpp +++ b/lunatic.cpp
@@ -54,7 +54,7 @@ int main(int argc, char** argv)
54 auth.setAccessKey(config["access_key"].as<std::string>()); 54 auth.setAccessKey(config["access_key"].as<std::string>());
55 auth.setAccessSecret(config["access_secret"].as<std::string>()); 55 auth.setAccessSecret(config["access_secret"].as<std::string>());
56 56
57 //twitter::client client(auth); 57 twitter::client client(auth);
58 58
59 database db(config["database"].as<std::string>()); 59 database db(config["database"].as<std::string>());
60 60
@@ -97,132 +97,159 @@ int main(int argc, char** argv)
97 Magick::Image moonColor; 97 Magick::Image moonColor;
98 moonColor.read("res/" + ach.color + ".png"); 98 moonColor.read("res/" + ach.color + ".png");
99 99
100 // Start with the Odyssey text overlay
101 Magick::Image overlay;
100 try 102 try
101 { 103 {
102 // Start with the Odyssey text overlay
103 Magick::Image overlay;
104 overlay.read("res/overlay.png"); 104 overlay.read("res/overlay.png");
105 } catch (const Magick::WarningCoder& ex)
106 {
107 // Ok
108 }
109
110 // Add the moon image
111 overlay.composite(moonColor, 672, 85, Magick::OverCompositeOp);
105 112
106 // Add the moon image 113 // Add the name of the achievement
107 overlay.composite(moonColor, 672, 85, Magick::OverCompositeOp); 114 overlay.fontPointsize(54);
115 overlay.fillColor("white");
116 overlay.font("@" + config["title_font"].as<std::string>());
108 117
109 // Add the name of the achievement 118 std::list<std::string> words = split<std::list<std::string>>(
110 overlay.fontPointsize(54); 119 ach.title,
111 overlay.fillColor("white"); 120 " ");
112 overlay.font("@" + config["title_font"].as<std::string>()); 121 std::ostringstream wrappingStream;
122 std::string curline;
123 int lines = 1;
113 124
114 std::list<std::string> words = split<std::list<std::string>>( 125 Magick::TypeMetric metric;
115 ach.title, 126 while (!words.empty())
116 " "); 127 {
117 std::ostringstream wrappingStream; 128 std::string temp = curline;
118 std::string curline;
119 int lines = 1;
120 129
121 Magick::TypeMetric metric; 130 if (!curline.empty())
122 while (!words.empty())
123 { 131 {
124 std::string temp = curline; 132 temp += " ";
133 }
125 134
126 if (!curline.empty()) 135 temp += words.front();
127 {
128 temp += " ";
129 }
130 136
131 temp += words.front(); 137 overlay.fontTypeMetrics(temp, &metric);
132 138
133 overlay.fontTypeMetrics(temp, &metric); 139 if (metric.textWidth() > 1200)
140 {
141 wrappingStream << std::endl;
142 curline = words.front();
134 143
135 if (metric.textWidth() > 1200) 144 lines++;
145 } else {
146 if (!curline.empty())
136 { 147 {
137 wrappingStream << std::endl; 148 wrappingStream << " ";
138 curline = words.front();
139
140 lines++;
141 } else {
142 if (!curline.empty())
143 {
144 wrappingStream << " ";
145 }
146
147 curline = temp;
148 } 149 }
149 150
150 wrappingStream << words.front(); 151 curline = temp;
151 words.pop_front();
152 } 152 }
153 153
154 std::string wrapped = wrappingStream.str(); 154 wrappingStream << words.front();
155 words.pop_front();
156 }
155 157
156 overlay.annotate( 158 std::string wrapped = wrappingStream.str();
157 wrapped,
158 Magick::Geometry(1600, 228, 0, 710),
159 Magick::GravityType::NorthGravity);
160 159
161 // Add the achievement date 160 overlay.annotate(
162 did theDid = db.getRandomDidForAchievement(ach.achievementId); 161 wrapped,
162 Magick::Geometry(1600, 228, 0, 710),
163 Magick::GravityType::NorthGravity);
163 164
164 overlay.fontTypeMetrics(wrapped, &metric); 165 // Add the achievement date
166 did theDid = db.getRandomDidForAchievement(ach.achievementId);
165 167
166 overlay.fontPointsize(20); 168 overlay.fontTypeMetrics(wrapped, &metric);
167 overlay.font("@" + config["date_font"].as<std::string>());
168 overlay.annotate(
169 theDid.date,
170 Magick::Geometry(1600, 228, 0, 710 + metric.textHeight() * lines - 22),
171 Magick::GravityType::NorthGravity);
172 169
173 // Make a shadow copy 170 overlay.fontPointsize(20);
174 Magick::Image shadow(overlay); 171 overlay.font("@" + config["date_font"].as<std::string>());
175 shadow.negate(); 172 overlay.annotate(
176 shadow.blur(0, 12); 173 theDid.date,
174 Magick::Geometry(1600, 228, 0, 710 + metric.textHeight() * lines - 22),
175 Magick::GravityType::NorthGravity);
177 176
178 // Read the game image, using a default if the game has no images 177 // Make a shadow copy
179 Magick::Image image; 178 Magick::Image shadow(overlay);
179 shadow.negate();
180 shadow.blur(0, 12);
180 181
181 if (db.doesGameHaveImages(ach.gameId)) 182 // Read the game image, using a default if the game has no images
182 { 183 Magick::Image image;
183 std::string imageName = db.getRandomImageForGame(ach.gameId);
184 std::string imagePath = config["images"].as<std::string>()
185 + "/" + imageName;
186 184
185 if (db.doesGameHaveImages(ach.gameId))
186 {
187 std::string imageName = db.getRandomImageForGame(ach.gameId);
188 std::string imagePath = config["images"].as<std::string>()
189 + "/" + imageName;
190
191 try
192 {
187 image.read(imagePath); 193 image.read(imagePath);
194 } catch (const Magick::WarningCoder& ex)
195 {
196 // Ok
197 }
188 198
189 // Stretch and pixelate it 199 // Stretch and pixelate it
190 image.transform("1600x900!"); 200 image.transform("1600x900!");
191 image.scale("80x45"); 201 image.scale("80x45");
192 image.scale("1600x900"); 202 image.scale("1600x900");
193 } else { 203 } else {
204 try
205 {
194 image.read("res/default.png"); 206 image.read("res/default.png");
195 image.transform("1600x900!"); 207 } catch (const Magick::WarningCoder& ex)
208 {
209 // Ok
196 } 210 }
197 211
198 // Add the generated overlay to it 212 image.transform("1600x900!");
199 image.composite(shadow, 0, 0, Magick::OverCompositeOp); 213 }
200 image.composite(overlay, 0, 0, Magick::OverCompositeOp); 214
215 // Add the generated overlay to it
216 image.composite(shadow, 0, 0, Magick::OverCompositeOp);
217 image.composite(overlay, 0, 0, Magick::OverCompositeOp);
201 218
202 // Output for debug 219 // Output image
203 image.magick("png"); 220 Magick::Blob outputBlob;
204 image.write("output.png"); 221 image.magick("png");
222
223 try
224 {
225 image.write(&outputBlob);
205 } catch (const Magick::WarningCoder& ex) 226 } catch (const Magick::WarningCoder& ex)
206 { 227 {
207 // Ok 228 // Ok
208 } 229 }
209 230
210 std::string header = "YOU GOT A MOON!"; 231 std::string header = "YOU GOT A MOON!";
211
212 std::string action = header + "\n" + ach.title; 232 std::string action = header + "\n" + ach.title;
213 action.resize(140); 233 action.resize(140);
214 234
215 /*try 235 std::cout << action << std::endl;
236
237 try
216 { 238 {
217 client.updateStatus(action); 239 long media_id = client.uploadMedia(
240 "image/png",
241 static_cast<const char*>(outputBlob.data()),
242 outputBlob.length());
243
244 client.updateStatus(action, {media_id});
245
246 std::cout << "Tweeted!" << std::endl;
218 } catch (const twitter::twitter_error& e) 247 } catch (const twitter::twitter_error& e)
219 { 248 {
220 std::cout << "Twitter error: " << e.what() << std::endl; 249 std::cout << "Twitter error: " << e.what() << std::endl;
221 }*/ 250 }
222
223 std::cout << action << std::endl;
224 std::cout << "Waiting" << std::endl;
225 251
252 std::cout << "Waiting..." << std::endl;
226 std::this_thread::sleep_for(std::chrono::hours(1)); 253 std::this_thread::sleep_for(std::chrono::hours(1));
227 254
228 std::cout << std::endl; 255 std::cout << std::endl;