Added Tweet65.

Tweet65 is sample application for triggering an IFTTT maker webhook. If ~450 chars are not enough for the URL then either the IP65 output_buffer needs to be increased or url_parse needs to be modified to use a different buffer. E.g. when called from url_download then the url_download_buffer could be temporarily used to hold the selector.
This commit is contained in:
Oliver Schmidt 2018-11-01 14:21:20 +01:00
parent 41de6a76bd
commit 334bdb88a0
4 changed files with 346 additions and 9 deletions

View File

@ -31,7 +31,8 @@ UDP =\
TCP =\
hfs65 \
telnet65
telnet65 \
tweet65
bin: wget65.bin
@ -39,10 +40,12 @@ wget65.bin: w5100.c linenoise.c
wget65.bin: IP65LIB = ../ip65/ip65.lib
wget65.bin: A2_DRIVERLIB = ../drivers/ip65_apple2_uther2.lib
date65.bin hfs65.bin: CL65FLAGS = --start-addr 0x0C00 apple2enh-iobuf-0800.o
date65.bin hfs65.bin tweet65.bin: CL65FLAGS = --start-addr 0x0C00 apple2enh-iobuf-0800.o
telnet65.com: ATARI_CFG = atrtelnet.cfg
tweet65.prg tweet65.bin tweet65.com: ifttt.c
all: $(UDP) $(TCP)
.PHONY: $(UDP) $(TCP)
@ -109,16 +112,19 @@ ip65.d64: prg
$(C1541) -attach $@ -write date65.prg date65,p
$(C1541) -attach $@ -write hfs65.prg hfs65,p
$(C1541) -attach $@ -write telnet65.prg telnet65,p
$(C1541) -attach $@ -write tweet65.prg tweet65,p
ip65.dsk: bin
cp ../build/prodos.dsk $@
java -jar $(AC) -as $@ date65 < date65.bin
java -jar $(AC) -p $@ date65.system sys < $(CC65)/apple2enh/util/loader.system
java -jar $(AC) -as $@ hfs65 < hfs65.bin
java -jar $(AC) -p $@ hfs65.system sys < $(CC65)/apple2enh/util/loader.system
java -jar $(AC) -as $@ wget65 < wget65.bin
java -jar $(AC) -p $@ wget65.system sys < $(CC65)/apple2enh/util/loader.system
java -jar $(AC) -as $@ telnet65 < telnet65.bin
java -jar $(AC) -as $@ date65 < date65.bin
java -jar $(AC) -p $@ date65.system sys < $(CC65)/apple2enh/util/loader.system
java -jar $(AC) -as $@ hfs65 < hfs65.bin
java -jar $(AC) -p $@ hfs65.system sys < $(CC65)/apple2enh/util/loader.system
java -jar $(AC) -as $@ tweet65 < tweet65.bin
java -jar $(AC) -p $@ tweet65.system sys < $(CC65)/apple2enh/util/loader.system
java -jar $(AC) -as $@ wget65 < wget65.bin
java -jar $(AC) -p $@ wget65.system sys < $(CC65)/apple2enh/util/loader.system
java -jar $(AC) -as $@ telnet65 < telnet65.bin
ip65.atr: com
mkdir atr
@ -126,6 +132,7 @@ ip65.atr: com
cp ../build/dup.sys atr/dup.sys
cp date65.com atr/date65.com
cp telnet65.com atr/telnet65.com
cp tweet65.com atr/tweet65.com
$(DIR2ATR) -b Dos25 1040 $@ atr
rm -r atr

102
apps/ifttt.c Normal file
View File

@ -0,0 +1,102 @@
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../inc/ip65.h"
#include "ifttt.h"
static char url[1024];
static char download[1024];
static bool isclean(char c)
{
switch (c)
{
case '*':
case '-':
case '.':
case '_':
return true;
}
return false;
}
static void querystrcat(char* url, const char* val)
{
if (!val)
{
return;
}
url += strlen(url);
while (true)
{
if (isalnum(*val) || isclean(*val))
{
*url++ = *val++;
continue;
}
if (*val == ' ')
{
*url++ = '+';
++val;
continue;
}
if (*val == '\0')
{
*url = '\0';
break;
}
url += sprintf(url, "%%%02X", toascii(*val++));
}
}
// Trigger IFTTT maker event via webhook
//
// Inputs: key: Webhook key to use
// event: Maker event to trigger
// val1: Webhook parameter 'value1'
// val2: Webhook parameter 'value2'
// val3: Webhook parameter 'value3'
// Output: Webhook HTTP status code, -1 on error
//
int ifttt_trigger(const char* key, const char* event,
const char* val1, const char* val2, const char* val3)
{
char* ptr = url;
uint16_t len;
strcpy(url, "http://maker.ifttt.com/trigger/");
strcat(url, event);
strcat(url, "/with/key/");
strcat(url, key);
strcat(url, "?value1=");
querystrcat(url, val1);
strcat(url, "&value2=");
querystrcat(url, val2);
strcat(url, "&value3=");
querystrcat(url, val3);
while (*ptr)
{
*ptr = toascii(*ptr);
++ptr;
}
if (strlen(url) > 450)
{
ip65_error = IP65_ERROR_MALFORMED_URL;
return -1;
}
len = url_download(url, download, sizeof(download));
if (len < 12)
{
return -1;
}
return atoi(download + 9);
}

18
apps/ifttt.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _IFTTT_H_
#define _IFTTT_H_
#include <stdbool.h>
// Trigger IFTTT maker event via webhook
//
// Inputs: key: Webhook key to use
// event: Maker event to trigger
// val1: Webhook parameter 'value1'
// val2: Webhook parameter 'value2'
// val3: Webhook parameter 'value3'
// Output: Webhook HTTP status code, -1 on error
//
int ifttt_trigger(const char* key, const char* event,
const char* val1, const char* val2, const char* val3);
#endif

210
apps/tweet65.c Normal file
View File

@ -0,0 +1,210 @@
#include <cc65.h>
#include <fcntl.h>
#include <ctype.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef __APPLE2__
#include <apple2_filetype.h>
#endif
#include "../inc/ip65.h"
#include "ifttt.h"
char key[22 + 1];
char text[280 + 1];
void error_exit(void)
{
switch (ip65_error)
{
case IP65_ERROR_DEVICE_FAILURE:
printf("- No device found\n");
break;
case IP65_ERROR_ABORTED_BY_USER:
printf("- User abort\n");
break;
case IP65_ERROR_TIMEOUT_ON_RECEIVE:
printf("- Timeout\n");
break;
case IP65_ERROR_DNS_LOOKUP_FAILED:
printf("- Lookup failed\n");
break;
default:
printf("- Error $%X\n", ip65_error);
}
exit(EXIT_FAILURE);
}
void confirm_exit(void)
{
printf("\nPress any key ");
cgetc();
}
unsigned char cols(void)
{
unsigned char cols, rows;
screensize(&cols, &rows);
return cols;
}
void input(char* str, unsigned int max, const char* tag)
{
char chr;
uint8_t row;
uint16_t len = max / cols() + 1;
for (row = len; --row; row)
{
putchar('\n');
}
row = wherey() - len;
len = 0;
while (true)
{
str[len] = '\0';
gotoxy(0, row);
cprintf("%s (%d/%d) \r\n%s", tag, len, max, str);
cursor(1);
chr = cgetc();
cursor(0);
if (chr == CH_ENTER)
{
break;
}
if (chr == CH_DEL)
{
if (len == 0)
{
continue;
}
if (wherex() > 0)
{
gotox(wherex() - 1);
}
else
{
gotoxy(cols() - 1, wherey() - 1);
}
cputc(' ');
--len;
continue;
}
if (len == max)
{
continue;
}
if (isprint(chr))
{
str[len++] = chr;
}
}
}
void main()
{
int retval;
uint8_t drv_init = DRV_INIT_DEFAULT;
if (doesclrscrafterexit())
{
atexit(confirm_exit);
}
{
int file;
printf("\nLoading key ");
file = open("ifttt.key", O_RDONLY);
if (file != -1)
{
read(file, key, sizeof(key));
close(file);
printf("- Ok\n");
}
else
{
printf("- Failed\n\n\n");
input(key, sizeof(key) - 1, "IFTTT webhook key");
if (*key == '\0')
{
printf("\n");
return;
}
printf("\n\nSaving key ");
#ifdef __APPLE2__
_filetype = PRODOS_T_TXT;
#endif
file = open("ifttt.key", O_WRONLY | O_CREAT | O_TRUNC);
if (file != -1)
{
write(file, key, sizeof(key));
close(file);
printf("- Ok\n");
}
else
{
printf("- ");
perror(NULL);
}
}
}
#ifdef __APPLE2__
{
int file;
printf("\nSetting slot ");
file = open("ethernet.slot", O_RDONLY);
if (file != -1)
{
read(file, &drv_init, 1);
close(file);
drv_init &= ~'0';
}
printf("- %d\n", drv_init);
}
#endif
printf("\nInitializing ");
if (ip65_init(drv_init))
{
error_exit();
}
printf("- Ok\n\nObtaining IP address ");
if (dhcp_init())
{
error_exit();
}
printf("- Ok\n\n\n");
input(text, sizeof(text) - 1, "Text");
if (*text == '\0')
{
printf("\n");
return;
}
printf("\n\nSending tweet ");
retval = ifttt_trigger(key, "tweet", text, NULL, NULL);
if (retval < 0)
{
error_exit();
}
if (retval != 200)
{
printf("- Error (HTTP status %d)\n", retval);
exit(EXIT_FAILURE);
}
printf("- Ok\n");
}