Mercurial Hosting > nabble
comparison src/nabble/modules/ad/Ad.java @ 0:7ecd1a4ef557
add content
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 21 Mar 2019 19:15:52 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7ecd1a4ef557 |
---|---|
1 package nabble.modules.ad; | |
2 | |
3 import fschmidt.db.DbDatabase; | |
4 import fschmidt.db.DbExpression; | |
5 import fschmidt.db.DbNull; | |
6 import fschmidt.db.DbRecord; | |
7 import fschmidt.db.NoKey; | |
8 import nabble.model.Db; | |
9 import nabble.model.ExtensionFactory; | |
10 import nabble.model.ModelHome; | |
11 import nabble.model.Site; | |
12 import nabble.model.ViewCount; | |
13 import nabble.naml.compiler.Template; | |
14 import nabble.naml.compiler.TemplatePrintWriter; | |
15 import nabble.naml.namespaces.BasicNamespace; | |
16 import nabble.view.web.template.NabbleNamespace; | |
17 import org.slf4j.Logger; | |
18 import org.slf4j.LoggerFactory; | |
19 | |
20 import java.io.Serializable; | |
21 import java.sql.Connection; | |
22 import java.sql.PreparedStatement; | |
23 import java.sql.ResultSet; | |
24 import java.sql.SQLException; | |
25 import java.util.Collections; | |
26 import java.util.Date; | |
27 import java.util.Set; | |
28 import java.util.concurrent.ConcurrentHashMap; | |
29 | |
30 | |
31 public final class Ad { | |
32 private static final Logger logger = LoggerFactory.getLogger(Ad.class); | |
33 | |
34 private static final String AD_MODULE_TASK = "ad_free"; | |
35 | |
36 private static final ExtensionFactory<Site,Ad> FACTORY = new ExtensionFactory<Site,Ad>() { | |
37 | |
38 private final Set<Long> adFreeSites = Collections.newSetFromMap(new ConcurrentHashMap<Long,Boolean>()); | |
39 | |
40 public String getName() { | |
41 return AdModule.INSTANCE.getName(); | |
42 } | |
43 | |
44 public Class<Ad> extensionClass() { | |
45 return Ad.class; | |
46 } | |
47 | |
48 public Ad construct(Site site) { | |
49 return null; | |
50 } | |
51 | |
52 public Ad construct(Site site,ResultSet rs) | |
53 throws SQLException | |
54 { | |
55 boolean isSafe = rs.getBoolean("is_safe"); | |
56 int credits = rs.getInt("ad_free"); | |
57 if( credits > 0 && adFreeSites.add(site.getId()) ) | |
58 site.addTask(AD_MODULE_TASK); | |
59 boolean isCreditsForUsersOnly = rs.getBoolean("ad_credits_for_users"); | |
60 return new Ad(site,isSafe,credits,isCreditsForUsersOnly); | |
61 } | |
62 | |
63 public Serializable getExportData(Site site) { | |
64 throw new UnsupportedOperationException(); | |
65 } | |
66 | |
67 public void saveExportData(Site site,Serializable s) { | |
68 throw new UnsupportedOperationException(); | |
69 } | |
70 }; | |
71 | |
72 static { | |
73 ModelHome.addSiteExtensionFactory(FACTORY); | |
74 ViewCount.addCalculateActivityListener(new Runnable(){public void run(){ | |
75 try { | |
76 for( Site site : ModelHome.getSitesForTask(AD_MODULE_TASK) ) { | |
77 Ad ad = Ad.of(site); | |
78 int views; | |
79 { | |
80 Connection con = Db.dbGlobal().getConnection(); | |
81 String field = ad.isCreditsForUsersOnly ? "user_views" : "views"; | |
82 PreparedStatement stmt = con.prepareStatement( | |
83 "select " + field + " from site_global where site_id = ?" | |
84 ); | |
85 stmt.setLong(1,site.getId()); | |
86 ResultSet rs = stmt.executeQuery(); | |
87 rs.next(); | |
88 views = rs.getInt(field); | |
89 rs.close(); | |
90 stmt.close(); | |
91 con.close(); | |
92 if( views > 0 && !ad.wasCreatedRecently() ) { | |
93 ad.decCredits(views); | |
94 } else { | |
95 site.addTask(AD_MODULE_TASK); | |
96 } | |
97 } | |
98 if( ad.getCredits() > 0 ) { | |
99 Connection con = site.getDb().getConnection(); | |
100 PreparedStatement stmt = con.prepareStatement( | |
101 "update site set monthly_views = monthly_views*29/30 + ?" | |
102 ); | |
103 stmt.setInt(1,views); | |
104 stmt.executeUpdate(); | |
105 stmt.close(); | |
106 con.close(); | |
107 } | |
108 } | |
109 } catch(SQLException e) { | |
110 logger.error("",e); | |
111 throw new RuntimeException(e); | |
112 } | |
113 }}); | |
114 } | |
115 | |
116 static void init() {} | |
117 | |
118 public static Ad of(Site site) { | |
119 return site.getExtension(FACTORY); | |
120 } | |
121 | |
122 | |
123 private final Site site; | |
124 private boolean isSafe; | |
125 private int credits = 0; | |
126 private boolean isCreditsForUsersOnly; | |
127 | |
128 Ad(Site site,boolean isSafe,int credits,boolean isCreditsForUsersOnly) { | |
129 this.site = site; | |
130 this.isSafe = isSafe; | |
131 this.credits = credits; | |
132 this.isCreditsForUsersOnly = isCreditsForUsersOnly; | |
133 } | |
134 | |
135 public boolean isSafe() { | |
136 return isSafe; | |
137 } | |
138 | |
139 public void setSafe(boolean isSafe) { | |
140 DbRecord<NoKey,?> record = site.getDbRecord(); | |
141 this.isSafe = isSafe; | |
142 record.fields().put( "is_safe", isSafe ); | |
143 // if( !isSafe ) { | |
144 // record.fields().put( "when_created", DbExpression.NOW ); | |
145 // record.fields().put( "ad_credits_for_users", false ); | |
146 // } | |
147 if (!site.getDb().isInTransaction()) { | |
148 record.update(); | |
149 } | |
150 } | |
151 | |
152 public int getCredits() { | |
153 return credits; | |
154 } | |
155 | |
156 public void setCredits(int credits) { | |
157 if( credits < 0 ) | |
158 credits = 0; | |
159 DbRecord<NoKey,?> record = site.getDbRecord(); | |
160 this.credits = credits; | |
161 record.fields().put( "ad_free", DbNull.fix(credits) ); | |
162 DbDatabase db = site.getDb(); | |
163 if( !db.isInTransaction() ) | |
164 record.update(); | |
165 if( credits > 0 ) | |
166 site.addTask(AD_MODULE_TASK); | |
167 } | |
168 | |
169 public void incCredits(int n) { | |
170 setCredits(this.credits + n); | |
171 } | |
172 | |
173 private void decCredits(int n) { | |
174 setCredits(this.credits - n); | |
175 | |
176 // notify user? | |
177 // I'm supposing that everyday we will deduct n credits, so he has one more day to buy new ones | |
178 // I test if he has more than 0 credits to avoid send emails to everyone that doesn't have or buy credits | |
179 if( this.credits < n && this.credits > 0) { // condition here | |
180 Template template = site.getTemplate( "ad_notice", | |
181 BasicNamespace.class, NabbleNamespace.class | |
182 ); | |
183 template.run( TemplatePrintWriter.NULL, Collections.<String,Object>emptyMap(), | |
184 new BasicNamespace(template), | |
185 new NabbleNamespace(site) | |
186 ); | |
187 } | |
188 } | |
189 | |
190 public boolean isPaid() { | |
191 return false; | |
192 } | |
193 | |
194 public boolean isCreditsForUsersOnly() { | |
195 return isCreditsForUsersOnly; | |
196 } | |
197 | |
198 private static long ONE_DAY = 24 * 60 * 60 * 1000L; // 1 day | |
199 private static long LIMIT_DAYS = 6 * 30 * ONE_DAY; // 6 months | |
200 | |
201 boolean wasCreatedRecently() { | |
202 long whenCreated = site.getWhenCreated().getTime(); | |
203 long now = new Date().getTime(); | |
204 return now < whenCreated + LIMIT_DAYS; | |
205 } | |
206 | |
207 long lastDayWithoutAds() { | |
208 return site.getWhenCreated().getTime() + LIMIT_DAYS; | |
209 } | |
210 | |
211 } |