sugoi internally added
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
package sugoi.db;
|
||||
import sys.db.Types;
|
||||
import sugoi.mail.IMail;
|
||||
import sugoi.mail.IMailer;
|
||||
|
||||
/**
|
||||
* DB Buffer for emails
|
||||
*/
|
||||
@:index(remoteId,sdate,cdate)
|
||||
class BufferedMail extends sys.db.Object
|
||||
{
|
||||
public var id : SId;
|
||||
|
||||
//email content
|
||||
public var title : SString<256>;
|
||||
public var htmlBody : SNull<SText>;
|
||||
public var textBody : SNull<SText>;
|
||||
public var headers : SData<Map<String,String>>;
|
||||
public var sender : SData<{name:String,email:String,?userId:Int}>;
|
||||
public var recipients : SData<Array<{name:String,email:String,?userId:Int}>>;
|
||||
|
||||
//utility fields
|
||||
public var mailerType : SString<32>; //mailer used when sending for real
|
||||
public var tries : SInt; //number of times we tried to send the mail
|
||||
public var cdate : SDateTime; //creation date
|
||||
public var sdate : SNull<SDateTime>; //sent date
|
||||
public var rawStatus : SNull<SText>; //raw return from the smtp server or mandrill API
|
||||
public var status : SNull<SData<MailerResult>>; //map of emails with api/smtp results
|
||||
|
||||
//custom datas
|
||||
public var data : SNull<SData<Dynamic>>;//custom datas
|
||||
public var remoteId : SNull<Int>; //custom remote Id (userId, groupId ...)
|
||||
|
||||
|
||||
public function getMailerResultMessage(k:String):{failure:String, success:String}{
|
||||
var t = sugoi.i18n.Locale.texts;
|
||||
var out = {failure:null, success:null};
|
||||
switch(status.get(k)){
|
||||
case tink.core.Outcome.Failure(f):
|
||||
out.failure = switch(f){
|
||||
case GenericError(e): t._("Generic error: ") + e.toString();
|
||||
case HardBounce : t._("Mailbox does not exist");
|
||||
case SoftBounce : t._("Mailbox full or blocked");
|
||||
case Spam: t._("Message considered as spam");
|
||||
case Unsub: t._("This user unsubscribed");
|
||||
case Unsigned: t._("Sender incorrect (Unsigned)");
|
||||
|
||||
};
|
||||
case tink.core.Outcome.Success(s):
|
||||
out.success = switch(s){
|
||||
case Sent : t._("Sent");
|
||||
case Queued : t._("Queued");
|
||||
};
|
||||
}
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function new(){
|
||||
super();
|
||||
cdate = Date.now();
|
||||
tries = 0;
|
||||
}
|
||||
|
||||
public function isSent(){
|
||||
return sdate!=null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finally really send the message
|
||||
*/
|
||||
public function finallySend():Void{
|
||||
|
||||
if(isSent()) throw "already sent";
|
||||
|
||||
var conf = {
|
||||
smtp_host:sugoi.db.Variable.get("smtp_host"),
|
||||
smtp_port:sugoi.db.Variable.getInt("smtp_port"),
|
||||
smtp_user:sugoi.db.Variable.get("smtp_user"),
|
||||
smtp_pass:sugoi.db.Variable.get("smtp_pass")
|
||||
};
|
||||
|
||||
var mailer : sugoi.mail.IMailer = switch(this.mailerType){
|
||||
case "mandrill":
|
||||
new sugoi.mail.MandrillMailer().init(conf);
|
||||
case "smtp":
|
||||
new sugoi.mail.SmtpMailer().init(conf);
|
||||
case "debug":
|
||||
new sugoi.mail.DebugMailer();
|
||||
default :
|
||||
throw "Unknown mailer type : "+this.mailerType;
|
||||
};
|
||||
|
||||
|
||||
var m = new sugoi.mail.Mail();
|
||||
for( k in this.headers.keys() ) m.setHeader( k,headers[k] );
|
||||
m.setSubject(this.title);
|
||||
for( r in recipients) m.setRecipient(r.email,r.name,r.userId);
|
||||
m.setSender(sender.email,sender.name,sender.userId);
|
||||
m.setHtmlBody(this.htmlBody);
|
||||
m.setTextBody(this.textBody);
|
||||
|
||||
|
||||
this.lock();
|
||||
this.tries++;
|
||||
|
||||
try{
|
||||
mailer.send(m,null,afterSendCb);
|
||||
this.sdate = Date.now();
|
||||
this.rawStatus = null;
|
||||
}catch(e:Dynamic){
|
||||
this.sdate = null;
|
||||
this.rawStatus = Std.string(e);
|
||||
// App.current.logError( Std.string(e) );
|
||||
}
|
||||
|
||||
this.update();
|
||||
|
||||
}
|
||||
|
||||
|
||||
function afterSendCb(status:MailerResult){
|
||||
//App.current.logError(status);
|
||||
this.status = status;
|
||||
this.update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package sugoi.db;
|
||||
import sys.db.Types;
|
||||
|
||||
/**
|
||||
* Key-Value temporary storage in a Memcached style
|
||||
*/
|
||||
@:id(name)
|
||||
class Cache extends sys.db.Object
|
||||
{
|
||||
public var name : SString<128>;
|
||||
public var value : SText;
|
||||
public var expire : SDateTime;
|
||||
public var cdate : SNull<SDateTime>;
|
||||
|
||||
public function new(){
|
||||
super();
|
||||
cdate = Date.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value for key $id
|
||||
*/
|
||||
public static function get(id:String):Dynamic {
|
||||
if (Std.random(1000) == 0) Cache.manager.delete($expire < Date.now());
|
||||
|
||||
var c = manager.get(id, true);
|
||||
if (c == null) return null;
|
||||
if (c.expire.getTime() < Date.now().getTime()) {
|
||||
c.delete();
|
||||
return null;
|
||||
}
|
||||
return haxe.Unserializer.run(c.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value for key $id
|
||||
* and optionnaly a lifetime in seconds
|
||||
*/
|
||||
public static function set(id:String, value:Dynamic,expireInSeconds:Float) {
|
||||
var c = manager.get(id, true);
|
||||
var niou = false;
|
||||
if (c == null) {
|
||||
niou = true;
|
||||
c = new Cache();
|
||||
c.name = id;
|
||||
}
|
||||
c.value = haxe.Serializer.run(value);
|
||||
c.expire = DateTools.delta(Date.now(), expireInSeconds*1000.0);
|
||||
if (niou) {
|
||||
c.insert();
|
||||
}else {
|
||||
c.update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a value for key $id
|
||||
*/
|
||||
public static function destroy(id:String) {
|
||||
var c = manager.get(id, true);
|
||||
if (c != null) c.delete();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package sugoi.db;
|
||||
import sys.db.Types;
|
||||
|
||||
class Error extends sys.db.Object {
|
||||
|
||||
public var id : SId;
|
||||
public var date : SDateTime;
|
||||
public var error : SText;
|
||||
|
||||
@:relation(uid) public var user : SNull<db.User>;
|
||||
|
||||
public var ip : SNull<SString<15>>;
|
||||
public var userAgent : SNull<SString<256>>;
|
||||
public var url : SNull<STinyText>;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package sugoi.db;
|
||||
import sys.db.Manager;
|
||||
import sys.db.Types;
|
||||
|
||||
/**
|
||||
* Store files in DB
|
||||
*/
|
||||
|
||||
class File extends sys.db.Object {
|
||||
|
||||
public var id : SId;
|
||||
public var name : STinyText; //filename
|
||||
public var cdate : SNull<SDateTime>; //creation datetime
|
||||
public var data : SBinary;
|
||||
|
||||
@:skip
|
||||
static var CACHE = [];
|
||||
|
||||
override public function new(){
|
||||
super();
|
||||
cdate = Date.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file name related to this File record.
|
||||
* Usually files should be generated in /file/
|
||||
*/
|
||||
public static function makeSign( id : Int ) {
|
||||
if( id == null )
|
||||
return "";
|
||||
var s = CACHE[id];
|
||||
if( s != null ) return s;
|
||||
s = id+"_"+haxe.crypto.Md5.encode(id + App.config.get('key'));
|
||||
CACHE[id] = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
public override function toString() {
|
||||
return "#" + id + " " + name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a File record
|
||||
* from string data (typically sent from a form) and a file name
|
||||
*/
|
||||
public static function create(stringData:String, ?fileName=""):File {
|
||||
|
||||
var bytes = new haxe.io.StringInput(stringData).readAll();
|
||||
return createFromBytes(bytes, fileName);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static function createFromBytes(b:haxe.io.Bytes, ?fileName=""):File {
|
||||
|
||||
#if neko
|
||||
var f = new File();
|
||||
f.name = fileName;
|
||||
f.data = b;
|
||||
f.insert();
|
||||
return f;
|
||||
#else
|
||||
//there is a bug in PHP, we do it manually
|
||||
var hexa = b.toHex();
|
||||
Manager.cnx.request("INSERT INTO File (name,data) VALUES ('"+fileName+"', 0x"+hexa+")");
|
||||
return File.manager.select($name==fileName);
|
||||
#end
|
||||
|
||||
}
|
||||
|
||||
public function getExtension():String {
|
||||
if (name == null || name=="") return "jpg";
|
||||
|
||||
return name.split(".")[1];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package sugoi.db;
|
||||
import sys.db.Types;
|
||||
import db.User;
|
||||
#if neko
|
||||
import neko.Web;
|
||||
#else
|
||||
import php.Web;
|
||||
#end
|
||||
|
||||
@:id(sid)
|
||||
@:index(uid,unique)
|
||||
class Session extends sys.db.Object {
|
||||
|
||||
public var sid : SString<32>;
|
||||
public var ip : SString<15>;
|
||||
public var lang : SString<2>;
|
||||
public var messages : SData<Array<{ error : Bool, text : String }>>;
|
||||
public var lastTime : SDateTime;
|
||||
public var createTime : SDateTime;
|
||||
|
||||
#if neko
|
||||
public var sdata : SNekoSerialized;
|
||||
#else
|
||||
public var sdata : SText;
|
||||
#end
|
||||
|
||||
@:skip public var data : Dynamic;
|
||||
|
||||
//public var uid : SNull<SInt>;
|
||||
@:relation(uid) public var user : SNull<db.User>;
|
||||
|
||||
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
messages = [];
|
||||
data = {};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a message in session
|
||||
*/
|
||||
public function addMessage( text : String, ?error=false ) {
|
||||
messages.push({ error : error, text : text });
|
||||
}
|
||||
|
||||
|
||||
public function setUser( u : User ):Void {
|
||||
|
||||
//remove any previous session for this user
|
||||
manager.delete($uid==u.id);
|
||||
|
||||
lang = u.lang;
|
||||
user = u;
|
||||
update();
|
||||
|
||||
App.current.user = u;
|
||||
}
|
||||
|
||||
public override function update() {
|
||||
#if neko
|
||||
sdata = neko.Lib.serialize(data);
|
||||
#else
|
||||
sdata = haxe.Serializer.run(data);
|
||||
#end
|
||||
lastTime = Date.now();
|
||||
super.update();
|
||||
}
|
||||
|
||||
private static function get( sid:String ):Session {
|
||||
if ( sid == null ) return null;
|
||||
|
||||
var s = manager.get(sid,true);
|
||||
if ( s == null ) return null;
|
||||
try {
|
||||
#if neko
|
||||
s.data = neko.Lib.localUnserialize(s.sdata);
|
||||
#else
|
||||
s.data = haxe.Unserializer.run(s.sdata);
|
||||
#end
|
||||
}catch (e:Dynamic) {
|
||||
s.data = null;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
public static function init( sids : Array<String> ) {
|
||||
for( sid in sids ) {
|
||||
var s = get(sid);
|
||||
if( s != null ) return s;
|
||||
}
|
||||
var ip = Web.getClientIP();
|
||||
var s = new Session();
|
||||
s.ip = ip;
|
||||
s.createTime = Date.now();
|
||||
s.lastTime = Date.now();
|
||||
|
||||
s.sid = generateId();
|
||||
var count = 20;
|
||||
while( try { s.insert(); false; } catch( e : Dynamic ) true ) {
|
||||
s.sid = generateId();
|
||||
// prevent infinite loop in SQL error
|
||||
if( count-- == 0 ) {
|
||||
s.insert();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random 32 chars string
|
||||
*/
|
||||
public static var S = "abcdefjhijklmnopqrstuvwxyABCDEFJHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
public static function generateId():String {
|
||||
|
||||
var id = "";
|
||||
for ( x in 0...32 ) {
|
||||
id += S.substr(Std.random(S.length),1);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete sessions older than 1 month
|
||||
*/
|
||||
public static function clean() {
|
||||
manager.delete($lastTime < DateTools.delta(Date.now(),-1000.0*60*60*24*30));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package sugoi.db;
|
||||
import sys.db.Types;
|
||||
|
||||
@:id(name)
|
||||
class Variable extends sys.db.Object {
|
||||
|
||||
public var name : SString<50>;
|
||||
public var value : SString<50>;
|
||||
|
||||
public static function get( name ) {
|
||||
var v = manager.get(name,false);
|
||||
return v == null ? null : v.value;
|
||||
}
|
||||
|
||||
public static function set(name, val:Dynamic) {
|
||||
var v = Variable.manager.get(name,true);
|
||||
if (v==null) {
|
||||
v = new Variable();
|
||||
v.name = name;
|
||||
v.value = Std.string(val);
|
||||
v.insert();
|
||||
}
|
||||
else {
|
||||
v.value = Std.string(val);
|
||||
v.update();
|
||||
}
|
||||
}
|
||||
|
||||
public static function increment(name, ?inc=1) {
|
||||
var v = Variable.manager.get(name,true);
|
||||
if (v==null) {
|
||||
v = new Variable();
|
||||
v.name = name;
|
||||
v.value = Std.string(inc);
|
||||
v.insert();
|
||||
}
|
||||
else {
|
||||
v.value = Std.string(Std.parseInt(v.value)+1);
|
||||
v.update();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getInt( name ) {
|
||||
var v = manager.get(name,false);
|
||||
return v == null ? 0 : Std.parseInt(v.value);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user